Completed
Push — develop ( e58221...7a35e1 )
by Jaap
08:17 queued 01:05
created

phpDocumentor/Descriptor/ConstantDescriptor.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * phpDocumentor
4
 *
5
 * PHP Version 5.3
6
 *
7
 * @copyright 2010-2014 Mike van Riel / Naenius (http://www.naenius.com)
8
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
9
 * @link      http://phpdoc.org
10
 */
11
12
namespace phpDocumentor\Descriptor;
13
14
use phpDocumentor\Descriptor\Tag\VarDescriptor;
15
use phpDocumentor\Reflection\Type;
16
17
/**
18
 * Descriptor representing a constant
19
 */
20
class ConstantDescriptor extends DescriptorAbstract implements Interfaces\ConstantInterface
21
{
22
    /** @var ClassDescriptor|InterfaceDescriptor|null $parent */
23
    protected $parent;
24
25
    /** @var string[]|null $type */
26
    protected $types;
27
28
    /** @var string $value */
29
    protected $value;
30
31
    /**
32
     * Registers a parent class or interface with this constant.
33
     *
34
     * @param ClassDescriptor|InterfaceDescriptor|null $parent
35
     *
36
     * @throws \InvalidArgumentException if anything other than a class, interface or null was passed.
37
     *
38
     * @return void
39
     */
40 3
    public function setParent($parent)
41
    {
42 3
        if (!$parent instanceof ClassDescriptor && !$parent instanceof InterfaceDescriptor && $parent !== null) {
43 1
            throw new \InvalidArgumentException('Constants can only have an interface or class as parent');
44
        }
45
46 2
        $fqsen = $parent !== null
47 2
            ? $parent->getFullyQualifiedStructuralElementName() . '::' . $this->getName()
48 2
            : $this->getName();
49
50 2
        $this->setFullyQualifiedStructuralElementName($fqsen);
51
52 2
        $this->parent = $parent;
53 2
    }
54
55
    /**
56
     * @return null|ClassDescriptor|InterfaceDescriptor
57
     */
58 2
    public function getParent()
59
    {
60 2
        return $this->parent;
61
    }
62
63
    /**
64
     * {@inheritDoc}
65
     */
66 1
    public function setTypes(Type $types)
67
    {
68 1
        $this->types = $types;
69 1
    }
70
71
    /**
72
     * {@inheritDoc}
73
     */
74 3
    public function getTypes()
75
    {
76 3
        if ($this->types === null) {
77 3
            /** @var VarDescriptor $var */
78
            $var = $this->getVar()->get(0);
79
            if ($var) {
80 3
                return $var->getTypes();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $var->getTypes(); (phpDocumentor\Reflection\Type) is incompatible with the return type declared by the interface phpDocumentor\Descriptor...tantInterface::getTypes of type array[].

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
81 3
            }
82 2
        }
83
84
        return $this->types;
85
    }
86 3
87
    /**
88
     * {@inheritDoc}
89
     */
90
    public function setValue($value)
91
    {
92 1
        $this->value = $value;
93
    }
94 1
95 1
    /**
96
     * {@inheritDoc}
97
     */
98
    public function getValue()
99
    {
100 1
        return $this->value;
101
    }
102 1
103
    /**
104
     * @return Collection
105
     */
106
    public function getVar()
107
    {
108 3
        /** @var Collection $var */
109
        $var = $this->getTags()->get('var', new Collection());
110
        if ($var->count() != 0) {
111 3
            return $var;
112 3
        }
113 2
114
        $inheritedElement = $this->getInheritedElement();
115
        if ($inheritedElement) {
116 2
            return $inheritedElement->getVar();
117 2
        }
118 2
119
        return new Collection();
120
    }
121
122
    /**
123
     * Returns the file associated with the parent class, interface or trait when inside a container.
124
     *
125
     * @return FileDescriptor
126
     */
127
    public function getFile()
128
    {
129 2
        return parent::getFile() ?: $this->getParent()->getFile();
130
    }
131 2
132
    /**
133
     * Returns the Constant from which this one should inherit, if any.
134
     *
135
     * @return ConstantDescriptor|null
136
     */
137
    public function getInheritedElement()
138
    {
139
        /** @var ClassDescriptor|InterfaceDescriptor|null $associatedClass */
140
        $associatedClass = $this->getParent();
141
142
        if (($associatedClass instanceof ClassDescriptor || $associatedClass instanceof InterfaceDescriptor)
143
            && ($associatedClass->getParent() instanceof ClassDescriptor
144
                || $associatedClass->getParent() instanceof InterfaceDescriptor
145
            )
146
        ) {
147
            /** @var ClassDescriptor|InterfaceDescriptor $parentClass */
148
            $parentClass = $associatedClass->getParent();
149
150
            return $parentClass->getConstants()->get($this->getName());
151
        }
152
153
        return null;
154
    }
155
}
156