1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* \AppserverIo\Doppelgaenger\Entities\Definitions\TraitDefinition |
5
|
|
|
* |
6
|
|
|
* NOTICE OF LICENSE |
7
|
|
|
* |
8
|
|
|
* This source file is subject to the Open Software License (OSL 3.0) |
9
|
|
|
* that is available through the world-wide-web at this URL: |
10
|
|
|
* http://opensource.org/licenses/osl-3.0.php |
11
|
|
|
* |
12
|
|
|
* PHP version 5 |
13
|
|
|
* |
14
|
|
|
* @author Bernhard Wick <[email protected]> |
15
|
|
|
* @copyright 2015 TechDivision GmbH - <[email protected]> |
16
|
|
|
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) |
17
|
|
|
* @link https://github.com/appserver-io/doppelgaenger |
18
|
|
|
* @link http://www.appserver.io/ |
19
|
|
|
*/ |
20
|
|
|
|
21
|
|
|
namespace AppserverIo\Doppelgaenger\Entities\Definitions; |
22
|
|
|
|
23
|
|
|
use AppserverIo\Doppelgaenger\Entities\Lists\AssertionList; |
24
|
|
|
use AppserverIo\Doppelgaenger\Entities\Lists\AttributeDefinitionList; |
25
|
|
|
use AppserverIo\Doppelgaenger\Interfaces\PropertiedStructureInterface; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* This class acts as a DTO-like (we are not immutable due to protected visibility) |
29
|
|
|
* entity for describing class definitions |
30
|
|
|
* |
31
|
|
|
* @author Bernhard Wick <[email protected]> |
32
|
|
|
* @copyright 2015 TechDivision GmbH - <[email protected]> |
33
|
|
|
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) |
34
|
|
|
* @link https://github.com/appserver-io/doppelgaenger |
35
|
|
|
* @link http://www.appserver.io/ |
36
|
|
|
*/ |
37
|
|
|
class TraitDefinition extends AbstractStructureDefinition implements PropertiedStructureInterface |
38
|
|
|
{ |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @const string TYPE The structure type |
42
|
|
|
*/ |
43
|
|
|
const TYPE = 'trait'; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* List of defined attributes |
47
|
|
|
* |
48
|
|
|
* @var \AppserverIo\Doppelgaenger\Entities\Lists\AttributeDefinitionList $attributeDefinitions |
49
|
|
|
*/ |
50
|
|
|
protected $attributeDefinitions; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Trait constants |
54
|
|
|
* |
55
|
|
|
* @var array $constants |
56
|
|
|
*/ |
57
|
|
|
protected $constants; |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* List of directly defined invariant conditions |
61
|
|
|
* |
62
|
|
|
* @var \AppserverIo\Doppelgaenger\Entities\Lists\AssertionList $invariantConditions |
63
|
|
|
*/ |
64
|
|
|
protected $invariantConditions; |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Default constructor |
68
|
|
|
* |
69
|
|
|
* @param string $path File path to the class definition |
70
|
|
|
* @param string $namespace The namespace the class belongs to |
71
|
|
|
* @param string $docBlock The initial class docblock header |
72
|
|
|
* @param string $name Name of the class |
73
|
|
|
* @param null $attributeDefinitions List of defined attributes |
74
|
|
|
* @param null $invariantConditions List of directly defined invariant conditions |
75
|
|
|
*/ |
76
|
|
|
public function __construct( |
77
|
|
|
$path = '', |
78
|
|
|
$namespace = '', |
79
|
|
|
$docBlock = '', |
80
|
|
|
$name = '', |
81
|
|
|
$attributeDefinitions = null, |
82
|
|
|
$invariantConditions = null |
83
|
|
|
) { |
84
|
|
|
$this->path = $path; |
85
|
|
|
$this->namespace = $namespace; |
86
|
|
|
$this->docBlock = $docBlock; |
87
|
|
|
$this->name = $name; |
88
|
|
|
$this->attributeDefinitions = is_null( |
89
|
|
|
$attributeDefinitions |
90
|
|
|
) ? new AttributeDefinitionList() : $attributeDefinitions; |
91
|
|
|
$this->invariantConditions = is_null($invariantConditions) ? new AssertionList() : $invariantConditions; |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* Getter method for attribute $attributeDefinitions |
96
|
|
|
* |
97
|
|
|
* @return null|AttributeDefinitionList |
98
|
|
|
*/ |
99
|
|
|
public function getAttributeDefinitions() |
100
|
|
|
{ |
101
|
|
|
return $this->attributeDefinitions; |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* Getter method for attribute $constants |
106
|
|
|
* |
107
|
|
|
* @return array |
108
|
|
|
*/ |
109
|
|
|
public function getConstants() |
110
|
|
|
{ |
111
|
|
|
return $this->constants; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* Will return a list of all dependencies eg. parent class, interfaces and traits. |
116
|
|
|
* |
117
|
|
|
* @return array |
118
|
|
|
*/ |
119
|
|
|
public function getDependencies() |
120
|
|
|
{ |
121
|
|
|
return array(); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* Will return all invariants. |
126
|
|
|
* |
127
|
|
|
* @param boolean $nonPrivateOnly Make this true if you only want conditions which do not have a private context |
128
|
|
|
* |
129
|
|
|
* @return \AppserverIo\Doppelgaenger\Entities\Lists\AssertionList |
130
|
|
|
*/ |
131
|
|
View Code Duplication |
public function getInvariants($nonPrivateOnly = false) |
132
|
|
|
{ |
133
|
|
|
// We have to clone it here, otherwise we might have weird side effects, of having the "add()" operation |
134
|
|
|
// persistent on $this->ancestralInvariants |
135
|
|
|
$invariants = clone $this->invariantConditions; |
136
|
|
|
|
137
|
|
|
// If we need to we will filter all the non private conditions from the lists |
138
|
|
|
if ($nonPrivateOnly === true) { |
139
|
|
|
$invariantListIterator = $invariants->getIterator(); |
140
|
|
|
foreach ($invariantListIterator as $invariantList) { |
141
|
|
|
$invariantIterator = $invariantList->getIterator(); |
142
|
|
|
foreach ($invariantIterator as $key => $invariant) { |
143
|
|
|
if ($invariant->isPrivateContext()) { |
144
|
|
|
$invariantList->delete($key); |
145
|
|
|
} |
146
|
|
|
} |
147
|
|
|
} |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
// Return what is left |
151
|
|
|
return $invariants; |
|
|
|
|
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* Getter method for attribute $invariantConditions |
156
|
|
|
* |
157
|
|
|
* @return null|AssertionList |
158
|
|
|
*/ |
159
|
|
|
public function getInvariantConditions() |
160
|
|
|
{ |
161
|
|
|
return $this->invariantConditions; |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
/** |
165
|
|
|
* Does this structure have parent structures? |
166
|
|
|
* Traits do not by default |
167
|
|
|
* |
168
|
|
|
* @return boolean |
169
|
|
|
*/ |
170
|
|
|
public function hasParents() |
171
|
|
|
{ |
172
|
|
|
return false; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Setter method for attribute $attributeDefinitions |
177
|
|
|
* |
178
|
|
|
* @param \AppserverIo\Doppelgaenger\Entities\Lists\AttributeDefinitionList $attributeDefinitions List of attribute definitions |
179
|
|
|
* |
180
|
|
|
* @return null |
181
|
|
|
*/ |
182
|
|
|
public function setAttributeDefinitions(AttributeDefinitionList $attributeDefinitions) |
183
|
|
|
{ |
184
|
|
|
$this->attributeDefinitions = $attributeDefinitions; |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
/** |
188
|
|
|
* Setter method for the $constants property |
189
|
|
|
* |
190
|
|
|
* @param array $constants Constants the class defines |
191
|
|
|
* |
192
|
|
|
* @return null |
193
|
|
|
*/ |
194
|
|
|
public function setConstants($constants) |
195
|
|
|
{ |
196
|
|
|
$this->constants = $constants; |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
/** |
200
|
|
|
* Setter method for attribute $invariantConditions |
201
|
|
|
* |
202
|
|
|
* @param \AppserverIo\Doppelgaenger\Entities\Lists\AssertionList $invariantConditions List of invariant assertions |
203
|
|
|
* |
204
|
|
|
* @return null |
205
|
|
|
*/ |
206
|
|
|
public function setInvariantConditions(AssertionList $invariantConditions) |
207
|
|
|
{ |
208
|
|
|
$this->invariantConditions = $invariantConditions; |
209
|
|
|
} |
210
|
|
|
} |
211
|
|
|
|
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:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.