Completed
Pull Request — master (#121)
by
unknown
11:29
created

PhpConverter::createConstantNameFromValue()   B

Complexity

Conditions 4
Paths 8

Size

Total Lines 86
Code Lines 76

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4.3035

Importance

Changes 0
Metric Value
dl 0
loc 86
ccs 11
cts 15
cp 0.7332
rs 8.4338
c 0
b 0
f 0
nc 8
cc 4
eloc 76
nop 1
crap 4.3035

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace Goetas\Xsd\XsdToPhp\Php;
3
4
use Cocur\Slugify\Slugify;
5
use Doctrine\Common\Inflector\Inflector;
6
use Exception;
7
use Goetas\Xsd\XsdToPhp\AbstractConverter;
8
use Goetas\Xsd\XsdToPhp\Naming\NamingStrategy;
9
use Goetas\Xsd\XsdToPhp\Php\Structure\PHPArg;
10
use Goetas\Xsd\XsdToPhp\Php\Structure\PHPClass;
11
use Goetas\Xsd\XsdToPhp\Php\Structure\PHPClassOf;
12
use Goetas\Xsd\XsdToPhp\Php\Structure\PHPProperty;
13
use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeItem;
14
use GoetasWebservices\XML\XSDReader\Schema\Attribute\Group as AttributeGroup;
15
use GoetasWebservices\XML\XSDReader\Schema\Element\Element;
16
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementDef;
17
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementRef;
18
use GoetasWebservices\XML\XSDReader\Schema\Element\ElementSingle;
19
use GoetasWebservices\XML\XSDReader\Schema\Element\Group;
20
use GoetasWebservices\XML\XSDReader\Schema\Item;
21
use GoetasWebservices\XML\XSDReader\Schema\Schema;
22
use GoetasWebservices\XML\XSDReader\Schema\Type\BaseComplexType;
23
use GoetasWebservices\XML\XSDReader\Schema\Type\ComplexType;
24
use GoetasWebservices\XML\XSDReader\Schema\Type\SimpleType;
25
use GoetasWebservices\XML\XSDReader\Schema\Type\Type;
26
27
class PhpConverter extends AbstractConverter
28
{
29
30 31
    public function __construct(NamingStrategy $namingStrategy)
31
    {
32 31
        parent::__construct($namingStrategy);
33
34
        $this->addAliasMap("http://www.w3.org/2001/XMLSchema", "dateTime", function (Type $type) {
0 ignored issues
show
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
35 3
            return "DateTime";
36 31
        });
37
        $this->addAliasMap("http://www.w3.org/2001/XMLSchema", "time", function (Type $type) {
0 ignored issues
show
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
38
            return "DateTime";
39 31
        });
40
        $this->addAliasMap("http://www.w3.org/2001/XMLSchema", "date", function (Type $type) {
0 ignored issues
show
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
41
            return "DateTime";
42 31
        });
43
        $this->addAliasMap("http://www.w3.org/2001/XMLSchema", "anySimpleType", function (Type $type) {
0 ignored issues
show
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
44
            return "mixed";
45 31
        });
46
        $this->addAliasMap("http://www.w3.org/2001/XMLSchema", "anyType", function (Type $type) {
0 ignored issues
show
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
47 2
            return "mixed";
48 31
        });
49 31
    }
50
51
    private $classes = [];
52
53 31 View Code Duplication
    public function convert(array $schemas)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
54
    {
55 31
        $visited = array();
56 31
        $this->classes = array();
57 31
        foreach ($schemas as $schema) {
58 31
            $this->navigate($schema, $visited);
59 31
        }
60 31
        return $this->getTypes();
61
    }
62
63
    /**
64
     *
65
     * @return PHPClass[]
66
     */
67
    private function getTypes()
68
    {
69 31
        uasort($this->classes, function ($a, $b) {
70 20
            return strcmp($a["class"]->getFullName(), $b["class"]->getFullName());
71 31
        });
72 31
        $ret = array();
73 31
        foreach ($this->classes as $classData) {
74 30
            if (!isset($classData["skip"]) || !$classData["skip"]) {
75 30
                $ret[$classData["class"]->getFullName()] = $classData["class"];
76 30
            }
77 31
        }
78
79 31
        return $ret;
80
    }
81
82 31 View Code Duplication
    private function navigate(Schema $schema, array &$visited)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
83
    {
84 31
        if (isset($visited[spl_object_hash($schema)])) {
85
            return;
86
        }
87 31
        $visited[spl_object_hash($schema)] = true;
88
89 31
        foreach ($schema->getTypes() as $type) {
90 17
            $this->visitType($type);
91 31
        }
92 31
        foreach ($schema->getElements() as $element) {
93 15
            $this->visitElementDef($element);
94 31
        }
95
96 31
        foreach ($schema->getSchemas() as $schildSchema) {
97 31
            if (!in_array($schildSchema->getTargetNamespace(), $this->baseSchemas, true)) {
98 1
                $this->navigate($schildSchema, $visited);
99 1
            }
100 31
        }
101 31
    }
102
103 25
    private function visitTypeBase(PHPClass $class, Type $type)
104
    {
105 25
        $class->setAbstract($type->isAbstract());
106
107 25
        if ($type instanceof SimpleType) {
108 9
            $this->visitSimpleType($class, $type);
109 9
        }
110 25
        if ($type instanceof BaseComplexType) {
111 20
            $this->visitBaseComplexType($class, $type);
112 20
        }
113 25
        if ($type instanceof ComplexType) {
114 18
            $this->visitComplexType($class, $type);
115 18
        }
116 25
    }
117
118 3 View Code Duplication
    private function visitGroup(PHPClass $class, Schema $schema, Group $group)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
119
    {
120 3
        foreach ($group->getElements() as $childGroup) {
121 3
            if ($childGroup instanceof Group) {
122 1
                $this->visitGroup($class, $schema, $childGroup);
123 1
            } else {
124 3
                $property = $this->visitElement($class, $schema, $childGroup);
125 3
                $class->addProperty($property);
126
            }
127 3
        }
128 3
    }
129
130 1
    private function visitAttributeGroup(PHPClass $class, Schema $schema, AttributeGroup $att)
131
    {
132 1 View Code Duplication
        foreach ($att->getAttributes() as $childAttr) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
133 1
            if ($childAttr instanceof AttributeGroup) {
134 1
                $this->visitAttributeGroup($class, $schema, $childAttr);
135 1
            } else {
136 1
                $property = $this->visitAttribute($class, $schema, $childAttr);
137 1
                $class->addProperty($property);
138
            }
139 1
        }
140 1
    }
141
142 15
    private function visitElementDef(ElementDef $element)
143
    {
144 15
        if (!isset($this->classes[spl_object_hash($element)])) {
145 15
            $schema = $element->getSchema();
146
147 15
            $class = new PHPClass();
148 15
            $class->setDoc($element->getDoc());
149 15
            $class->setName($this->getNamingStrategy()->getItemName($element));
150 15
            $class->setDoc($element->getDoc());
151
152 15 View Code Duplication
            if (!isset($this->namespaces[$schema->getTargetNamespace()])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
153
                throw new Exception(sprintf("Can't find a PHP namespace to '%s' namespace", $schema->getTargetNamespace()));
154
            }
155 15
            $class->setNamespace($this->namespaces[$schema->getTargetNamespace()]);
156
157 15
            $this->classes[spl_object_hash($element)]["class"] = $class;
158
159 15
            if (!$element->getType()->getName()) {
160 8
                $this->visitTypeBase($class, $element->getType());
161 8
            } else {
162 8
                $this->handleClassExtension($class, $element->getType());
163
            }
164 15
        }
165 15
        return $this->classes[spl_object_hash($element)]["class"];
166
    }
167
168 17
    private function findPHPName(Type $type)
169
    {
170 17
        $schema = $type->getSchema();
171
172 17
        if ($className = $this->getTypeAlias($type)) {
173
174
            if (($pos = strrpos($className, '\\')) !== false) {
175
                return [
176
                    substr($className, $pos + 1),
177
                    substr($className, 0, $pos)
178
                ];
179
            } else {
180
                return [
181
                    $className,
182
                    null
183
                ];
184
            }
185
        }
186
187 17
        $name = $this->getNamingStrategy()->getTypeName($type);
188
189 17 View Code Duplication
        if (!isset($this->namespaces[$schema->getTargetNamespace()])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
190
            throw new Exception(sprintf("Can't find a PHP namespace to '%s' namespace", $schema->getTargetNamespace()));
191
        }
192 17
        $ns = $this->namespaces[$schema->getTargetNamespace()];
193
        return [
194 17
            $name,
195
            $ns
196 17
        ];
197
    }
198
199
    /**
200
     *
201
     * @param Type $type
202
     * @param boolean $force
203
     * @return \Goetas\Xsd\XsdToPhp\Php\Structure\PHPClass
204
     */
205 19
    private function visitType(Type $type, $force = false)
206
    {
207 19
        if (!isset($this->classes[spl_object_hash($type)])) {
208
209 19
            $this->classes[spl_object_hash($type)]["class"] = $class = new PHPClass();
210
211 19
            if ($alias = $this->getTypeAlias($type)) {
212 18
                $class->setName($alias);
213 18
                $this->classes[spl_object_hash($type)]["skip"] = true;
214 18
                return $class;
215
            }
216
217 17
            list ($name, $ns) = $this->findPHPName($type);
218 17
            $class->setName($name);
219 17
            $class->setNamespace($ns);
220
221 17
            $class->setDoc($type->getDoc() . PHP_EOL . "XSD Type: " . ($type->getName() ?: 'anonymous'));
222
223 17
            $this->visitTypeBase($class, $type);
224
225 17
            if ( ( $restriction = $type->getRestriction() ) && $restriction->getChecksByType( 'enumeration' ) ) {
226
                return $class;
227
            }
228
229 17 View Code Duplication
            if ($type instanceof SimpleType) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
230 3
                $this->classes[spl_object_hash($type)]["skip"] = true;
231 3
                return $class;
232
            }
233 17 View Code Duplication
            if (($this->isArrayType($type) || $this->isArrayNestedElement($type)) && !$force) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
234 4
                $this->classes[spl_object_hash($type)]["skip"] = true;
235 4
                return $class;
236
            }
237
238 17
            $this->classes[spl_object_hash($type)]["skip"] = !!$this->getTypeAlias($type);
239 17 View Code Duplication
        } elseif ($force) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
240 8
            if (!($type instanceof SimpleType) && !$this->getTypeAlias($type)) {
241 3
                $this->classes[spl_object_hash($type)]["skip"] = false;
242 3
            }
243 8
        }
244 17
        return $this->classes[spl_object_hash($type)]["class"];
245
    }
246
247
    /**
248
     * @param Type $type
249
     * @param string $name
250
     * @param PHPClass $parentClass
251
     * @return \Goetas\Xsd\XsdToPhp\Php\Structure\PHPClass
252
     */
253 3
    private function visitTypeAnonymous(Type $type, $name, PHPClass $parentClass)
254
    {
255 3
        if (!isset($this->classes[spl_object_hash($type)])) {
256 3
            $this->classes[spl_object_hash($type)]["class"] = $class = new PHPClass();
257 3
            $class->setName($this->getNamingStrategy()->getAnonymousTypeName($type, $name));
258
259 3
            $class->setNamespace($parentClass->getNamespace() . "\\" . $parentClass->getName());
260 3
            $class->setDoc($type->getDoc());
261
262 3
            $this->visitTypeBase($class, $type);
263
264 3
            if ($type instanceof SimpleType) {
265 2
                $this->classes[spl_object_hash($type)]["skip"] = true;
266 2
            }
267 3
        }
268 3
        return $this->classes[spl_object_hash($type)]["class"];
269
    }
270
271 18 View Code Duplication
    private function visitComplexType(PHPClass $class, ComplexType $type)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
272
    {
273 18
        $schema = $type->getSchema();
274 18
        foreach ($type->getElements() as $element) {
275 18
            if ($element instanceof Group) {
276 3
                $this->visitGroup($class, $schema, $element);
277 3
            } else {
278 17
                $property = $this->visitElement($class, $schema, $element);
279 17
                $class->addProperty($property);
280
            }
281 18
        }
282 18
    }
283
284 9
    private function visitSimpleType(PHPClass $class, SimpleType $type)
285
    {
286 9
        if ($restriction = $type->getRestriction()) {
287 8
            $parent = $restriction->getBase();
288
289 8
            if ($parent instanceof Type) {
290 8
                $this->handleClassExtension($class, $parent);
291 8
            }
292
293 8
            foreach ($restriction->getChecks() as $typeCheck => $checks) {
294 1
                foreach ($checks as $check) {
295 1
                    if ( $typeCheck === 'enumeration' ) {
296 1
                        $class->addConstant(
297 1
                            $this->createConstantNameFromValue( $check[ 'value' ] ),
298 1
                            $check[ 'value' ]
299 1
                        );
300 1
                    } else {
301
                        $class->addCheck( '__value', $typeCheck, $check );
302
                    }
303 1
                }
304 8
            }
305 9
        } elseif ($unions = $type->getUnions()) {
306 1
            $types = array();
307 1
            foreach ($unions as $i => $unon) {
308 1
                if (!$unon->getName()) {
309 1
                    $types[] = $this->visitTypeAnonymous($unon, $type->getName() . $i, $class);
310 1
                } else {
311 1
                    $types[] = $this->visitType($unon);
312
                }
313 1
            }
314
315 1
            if ($candidato = reset($types)) {
316 1
                $class->setExtends($candidato);
317 1
            }
318 1
        }
319 9
    }
320
321 17
    private function handleClassExtension(PHPClass $class, Type $type)
322
    {
323
324 17
        if ($alias = $this->getTypeAlias($type)) {
325 16
            $c = PHPClass::createFromFQCN($alias);
326 16
            $val = new PHPProperty('__value');
327 16
            $val->setType($c);
328 16
            $c->addProperty($val);
329 16
            $class->setExtends($c);
330 16
        } else {
331 2
            $extension = $this->visitType($type, true);
332 2
            $class->setExtends($extension);
333
        }
334 17
    }
335
336 20
    private function visitBaseComplexType(PHPClass $class, BaseComplexType $type)
337
    {
338 20
        $parent = $type->getParent();
339 20
        if ($parent) {
340 4
            $parentType = $parent->getBase();
341 4
            if ($parentType instanceof Type) {
342 4
                $this->handleClassExtension($class, $parentType);
343 4
            }
344 4
        }
345 20
        $schema = $type->getSchema();
346
347 20 View Code Duplication
        foreach ($type->getAttributes() as $attr) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
348 7
            if ($attr instanceof AttributeGroup) {
349 1
                $this->visitAttributeGroup($class, $schema, $attr);
350 1
            } else {
351 7
                $property = $this->visitAttribute($class, $schema, $attr);
352 7
                $class->addProperty($property);
353
            }
354 20
        }
355 20
    }
356
357 7
    private function visitAttribute(PHPClass $class, Schema $schema, AttributeItem $attribute, $arrayize = true)
0 ignored issues
show
Unused Code introduced by
The parameter $schema is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
358
    {
359 7
        $property = new PHPProperty();
360 7
        $property->setName($this->getNamingStrategy()->getPropertyName($attribute));
361
362 7
        if ($arrayize && $itemOfArray = $this->isArrayType($attribute->getType())) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface GoetasWebservices\XML\XS...Attribute\AttributeItem as the method getType() does only exist in the following implementations of said interface: GoetasWebservices\XML\XS...ema\Attribute\Attribute, GoetasWebservices\XML\XS...\Attribute\AttributeDef, GoetasWebservices\XML\XS...\Attribute\AttributeRef.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
363
            if ($attribute->getType()->getName()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface GoetasWebservices\XML\XS...Attribute\AttributeItem as the method getType() does only exist in the following implementations of said interface: GoetasWebservices\XML\XS...ema\Attribute\Attribute, GoetasWebservices\XML\XS...\Attribute\AttributeDef, GoetasWebservices\XML\XS...\Attribute\AttributeRef.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
364
                $arg = new PHPArg($this->getNamingStrategy()->getPropertyName($attribute));
365
                $arg->setType($this->visitType($itemOfArray));
366
                $property->setType(new PHPClassOf($arg));
367
            } else {
368
                $property->setType($this->visitTypeAnonymous($attribute->getType(), $attribute->getName(), $class));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface GoetasWebservices\XML\XS...Attribute\AttributeItem as the method getType() does only exist in the following implementations of said interface: GoetasWebservices\XML\XS...ema\Attribute\Attribute, GoetasWebservices\XML\XS...\Attribute\AttributeDef, GoetasWebservices\XML\XS...\Attribute\AttributeRef.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
369
            }
370
        } else {
371 7
            $property->setType($this->findPHPClass($class, $attribute, true));
0 ignored issues
show
Documentation introduced by
$attribute is of type object<GoetasWebservices...ttribute\AttributeItem>, but the function expects a object<GoetasWebservices...\XSDReader\Schema\Item>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
372
        }
373
374 7
        $property->setDoc($attribute->getDoc());
375 7
        return $property;
376
    }
377
378
    /**
379
     *
380
     * @param PHPClass $class
381
     * @param Schema $schema
382
     * @param Element $element
383
     * @param boolean $arrayize
384
     * @return \Goetas\Xsd\XsdToPhp\Structure\PHPProperty
385
     */
386 18
    private function visitElement(PHPClass $class, Schema $schema, ElementSingle $element, $arrayize = true)
387
    {
388 18
        $property = new PHPProperty();
389 18
        $property->setName($this->getNamingStrategy()->getPropertyName($element));
390 18
        $property->setDoc($element->getDoc());
391
392 18
        $t = $element->getType();
393
394 18
        if ($arrayize) {
395 18
            if ($itemOfArray = $this->isArrayType($t)) {
396 1 View Code Duplication
                if (!$itemOfArray->getName()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
397
                    $classType = $this->visitTypeAnonymous($itemOfArray, $element->getName(), $class);
398
                } else {
399 1
                    $classType = $this->visitType($itemOfArray);
400
                }
401
402 1
                $arg = new PHPArg($this->getNamingStrategy()->getPropertyName($element));
403 1
                $arg->setType($classType);
404 1
                $property->setType(new PHPClassOf($arg));
405 1
                return $property;
406 17
            } elseif ($itemOfArray = $this->isArrayNestedElement($t)) {
407 4 View Code Duplication
                if (!$t->getName()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
408
                    $classType = $this->visitTypeAnonymous($t, $element->getName(), $class);
409
                } else {
410 4
                    $classType = $this->visitType($t);
411
                }
412 4
                $elementProp = $this->visitElement($classType, $schema, $itemOfArray, false);
413 4
                $property->setType(new PHPClassOf($elementProp));
414 4
                return $property;
415 17
            } elseif ($this->isArrayElement($element)) {
416 8
                $arg = new PHPArg($this->getNamingStrategy()->getPropertyName($element));
417 8
                $arg->setType($this->findPHPClass($class, $element));
0 ignored issues
show
Documentation introduced by
$element is of type object<GoetasWebservices...\Element\ElementSingle>, but the function expects a object<GoetasWebservices...\XSDReader\Schema\Item>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
418 8
                $arg->setDefault('array()');
419 8
                $property->setType(new PHPClassOf($arg));
420 8
                return $property;
421
            }
422 12
        }
423
424 16
        $property->setType($this->findPHPClass($class, $element, true));
0 ignored issues
show
Documentation introduced by
$element is of type object<GoetasWebservices...\Element\ElementSingle>, but the function expects a object<GoetasWebservices...\XSDReader\Schema\Item>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
425 16
        return $property;
426
    }
427
428 18
    private function findPHPClass(PHPClass $class, Item $node, $force = false)
429
    {
430
431 18
        if ($node instanceof ElementRef) {
432 5
            return $this->visitElementDef($node->getReferencedElement());
433
        }
434
435 17 View Code Duplication
        if (!$node->getType()->getName()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
436 3
            return $this->visitTypeAnonymous($node->getType(), $node->getName(), $class);
437
        } else {
438 17
            return $this->visitType($node->getType(), $force);
439
        }
440
    }
441
	/**
442
	 * @param $constantValue
443
	 *
444
	 * @return string
445
	 */
446 1
	public function createConstantNameFromValue( $constantValue ) {
447
		static $keywords = [
448
			'abstract',
449
			'and',
450
			'array',
451
			'as',
452
			'break',
453
			'callable',
454
			'case',
455
			'catch',
456
			'class',
457
			'clone',
458
			'const',
459
			'continue',
460
			'declare',
461
			'default',
462
			'die',
463
			'do',
464
			'echo',
465
			'else',
466
			'elseif',
467
			'empty',
468
			'enddeclare',
469
			'endfor',
470
			'endforeach',
471
			'endif',
472
			'endswitch',
473
			'endwhile',
474
			'eval',
475
			'exit',
476
			'extends',
477
			'final',
478
			'for',
479
			'foreach',
480
			'function',
481
			'global',
482
			'goto',
483
			'if',
484
			'implements',
485
			'include',
486
			'include_once',
487
			'instanceof',
488
			'insteadof',
489
			'interface',
490
			'isset',
491
			'list',
492
			'namespace',
493
			'new',
494
			'or',
495
			'print',
496
			'private',
497
			'protected',
498
			'public',
499
			'require',
500
			'require_once',
501
			'return',
502
			'static',
503
			'switch',
504
			'throw',
505
			'trait',
506
			'try',
507
			'unset',
508
			'use',
509
			'var',
510
			'while',
511
			'xor',
512 1
		];
513
514 1
		$slugify      = new Slugify();
515 1
		$constantName = $slugify->slugify( $constantValue, '_' );
516 1
		if ( in_array( $constantName, $keywords ) ) {
517
			$constantName = $constantName . '_';
518
		}
519
520 1
        if (is_numeric($constantName)) {
521
            $constantName = 'NUM_' . $constantName;
522
        }
523
524 1
        if ($constantName === '') {
525 1
            $constantName = 'EMPTY_STRING';
526 1
        }
527
528 1
		$constantName = strtoupper( $constantName );
529
530 1
		return $constantName;
531
	}
532
    
533
}
534