Complex classes like Struct often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Struct, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
15 | class Struct extends AbstractModel |
||
16 | { |
||
17 | /** |
||
18 | * @var string |
||
19 | */ |
||
20 | const DOC_SUB_PACKAGE_STRUCTS = 'Structs'; |
||
21 | /** |
||
22 | * @var string |
||
23 | */ |
||
24 | const DOC_SUB_PACKAGE_ENUMERATIONS = 'Enumerations'; |
||
25 | /** |
||
26 | * @var string |
||
27 | */ |
||
28 | const DOC_SUB_PACKAGE_ARRAYS = 'Arrays'; |
||
29 | /** |
||
30 | * Attributes of the struct |
||
31 | * @var StructAttributeContainer |
||
32 | */ |
||
33 | private $attributes; |
||
34 | /** |
||
35 | * Is the struct a restriction with defined values ? |
||
36 | * @var bool |
||
37 | */ |
||
38 | private $isRestriction = false; |
||
39 | /** |
||
40 | * If the struct is a restriction with values, then store values |
||
41 | * @var StructValueContainer |
||
42 | */ |
||
43 | private $values; |
||
44 | /** |
||
45 | * Define if the urrent struct is a concrete struct or just a virtual struct to store meta informations |
||
46 | * @var bool |
||
47 | */ |
||
48 | private $isStruct = false; |
||
49 | /** |
||
50 | * Main constructor |
||
51 | * @see AbstractModel::__construct() |
||
52 | * @uses Struct::setIsStruct() |
||
53 | * @param Generator $generator |
||
54 | * @param string $name the original name |
||
55 | * @param bool $isStruct defines if it's a real sruct or not |
||
56 | * @param bool $isRestriction defines if it's an enumeration or not |
||
57 | */ |
||
58 | 536 | public function __construct(Generator $generator, $name, $isStruct = true, $isRestriction = false) |
|
59 | { |
||
60 | 536 | parent::__construct($generator, $name); |
|
61 | 536 | $this |
|
62 | 536 | ->setIsStruct($isStruct) |
|
63 | 536 | ->setIsRestriction($isRestriction) |
|
64 | 536 | ->setAttributes(new StructAttributeContainer($generator)) |
|
65 | 536 | ->setValues(new StructValueContainer($generator)); |
|
66 | 536 | } |
|
67 | /** |
||
68 | * Returns the contextual part of the class name for the package |
||
69 | * @see AbstractModel::getContextualPart() |
||
70 | * @uses Struct::getIsRestriction() |
||
71 | * @return string |
||
72 | */ |
||
73 | 256 | public function getContextualPart() |
|
74 | { |
||
75 | 256 | $part = $this->getGenerator()->getOptionStructsFolder(); |
|
76 | 256 | if ($this->getIsRestriction()) { |
|
77 | 88 | $part = $this->getGenerator()->getOptionEnumsFolder(); |
|
78 | 256 | } elseif ($this->isArray()) { |
|
79 | 48 | $part = $this->getGenerator()->getOptionArraysFolder(); |
|
80 | 48 | } |
|
81 | 256 | return $part; |
|
82 | } |
||
83 | /** |
||
84 | * Returns the sub package name which the model belongs to |
||
85 | * Must be overridden by sub classes |
||
86 | * @see AbstractModel::getDocSubPackages() |
||
87 | * @uses Struct::getIsRestriction() |
||
88 | * @return array |
||
89 | */ |
||
90 | 140 | public function getDocSubPackages() |
|
91 | { |
||
92 | 140 | $package = self::DOC_SUB_PACKAGE_STRUCTS; |
|
93 | 140 | if ($this->getIsRestriction()) { |
|
94 | 52 | $package = self::DOC_SUB_PACKAGE_ENUMERATIONS; |
|
95 | 140 | } elseif ($this->isArray()) { |
|
96 | 28 | $package = self::DOC_SUB_PACKAGE_ARRAYS; |
|
97 | 28 | } |
|
98 | return array( |
||
99 | 140 | $package, |
|
100 | 140 | ); |
|
101 | } |
||
102 | /** |
||
103 | * Returns true if the current struct is a collection of values (like an array) |
||
104 | * @uses AbstractModel::getName() |
||
105 | * @uses Struct::countOwnAttributes() |
||
106 | * @return bool |
||
107 | */ |
||
108 | 284 | public function isArray() |
|
109 | { |
||
110 | 284 | return ((($this->getIsStruct() && $this->countOwnAttributes() === 1) || (!$this->getIsStruct() && $this->countOwnAttributes() <= 1)) && stripos($this->getName(), 'array') !== false); |
|
111 | } |
||
112 | /** |
||
113 | * Returns the attributes of the struct and potentially from the parent class |
||
114 | * @uses AbstractModel::getInheritance() |
||
115 | * @uses Struct::getIsStruct() |
||
116 | * @uses Struct::getAttributes() |
||
117 | * @param bool $includeInheritanceAttributes include the attributes of parent class, default parent attributes are not included. If true, then the array is an associative array containing and index "attribute" for the StructAttribute object and an index "model" for the Struct object. |
||
118 | * @param bool $requiredFirst places the required attributes first, then the not required in order to have the _contrust method with the required attribute at first |
||
119 | * @return StructAttributeContainer |
||
120 | */ |
||
121 | 296 | public function getAttributes($includeInheritanceAttributes = false, $requiredFirst = false) |
|
122 | { |
||
123 | 296 | if ($includeInheritanceAttributes === false && $requiredFirst === false) { |
|
124 | 296 | $attributes = $this->attributes; |
|
125 | 296 | } else { |
|
126 | 104 | $attributes = $this->getAllAttributes($includeInheritanceAttributes, $requiredFirst); |
|
127 | } |
||
128 | 296 | return $attributes; |
|
129 | } |
||
130 | /** |
||
131 | * @param bool $includeInheritanceAttributes |
||
132 | * @param bool $requiredFirst |
||
133 | * @return StructAttributeContainer |
||
134 | */ |
||
135 | 104 | protected function getAllAttributes($includeInheritanceAttributes, $requiredFirst) |
|
136 | { |
||
137 | 104 | $allAttributes = new StructAttributeContainer($this->getGenerator()); |
|
138 | 104 | if ($includeInheritanceAttributes === true) { |
|
139 | 4 | $this->addInheritanceAttributes($allAttributes); |
|
140 | 4 | } |
|
141 | 104 | foreach ($this->attributes as $attribute) { |
|
142 | 104 | $allAttributes->add($attribute); |
|
143 | 104 | } |
|
144 | 104 | if ($requiredFirst === true) { |
|
145 | 104 | $attributes = $this->putRequiredFirst($allAttributes); |
|
146 | 104 | } else { |
|
147 | $attributes = $allAttributes; |
||
148 | } |
||
149 | 104 | return $attributes; |
|
150 | } |
||
151 | /** |
||
152 | * @param StructAttributeContainer $attributes |
||
153 | */ |
||
154 | 4 | protected function addInheritanceAttributes(StructAttributeContainer $attributes) |
|
155 | { |
||
156 | 4 | if ($this->getInheritance() != '' && ($model = $this->getInheritanceStruct()) instanceof Struct) { |
|
157 | while ($model->getIsStruct()) { |
||
158 | foreach ($model->getAttributes() as $attribute) { |
||
159 | $attributes->add($attribute); |
||
160 | } |
||
161 | $model = $this->getGenerator()->getStruct($model->getInheritance()); |
||
162 | } |
||
163 | } |
||
164 | 4 | } |
|
165 | /** |
||
166 | * @param StructAttributeContainer $allAttributes |
||
167 | * @return StructAttributeContainer |
||
168 | */ |
||
169 | 104 | protected function putRequiredFirst(StructAttributeContainer $allAttributes) |
|
170 | { |
||
171 | 104 | $attributes = new StructAttributeContainer($this->getGenerator()); |
|
172 | 104 | $requiredAttributes = new StructAttributeContainer($this->getGenerator()); |
|
173 | 104 | $notRequiredAttributes = new StructAttributeContainer($this->getGenerator()); |
|
174 | 104 | foreach ($allAttributes as $attribute) { |
|
175 | 104 | if ($attribute->isRequired()) { |
|
176 | 28 | $requiredAttributes->add($attribute); |
|
177 | 28 | } else { |
|
178 | 96 | $notRequiredAttributes->add($attribute); |
|
179 | } |
||
180 | 104 | } |
|
181 | 104 | foreach ($requiredAttributes as $attribute) { |
|
182 | 28 | $attributes->add($attribute); |
|
183 | 104 | } |
|
184 | 104 | foreach ($notRequiredAttributes as $attribute) { |
|
185 | 96 | $attributes->add($attribute); |
|
186 | 104 | } |
|
187 | 104 | unset($requiredAttributes, $notRequiredAttributes); |
|
188 | 104 | return $attributes; |
|
189 | } |
||
190 | /** |
||
191 | * Returns the number of own attributes |
||
192 | * @uses Struct::getAttributes() |
||
193 | * @return int |
||
194 | */ |
||
195 | 284 | public function countOwnAttributes() |
|
196 | { |
||
197 | 284 | return $this->getAttributes(false, false)->count(); |
|
198 | } |
||
199 | /** |
||
200 | * Sets the attributes of the struct |
||
201 | * @param StructAttributeContainer $structAttributeContainer |
||
202 | * @return Struct |
||
203 | */ |
||
204 | 536 | public function setAttributes(StructAttributeContainer $structAttributeContainer) |
|
205 | { |
||
206 | 536 | $this->attributes = $structAttributeContainer; |
|
207 | 536 | return $this; |
|
208 | } |
||
209 | /** |
||
210 | * Adds attribute based on its original name |
||
211 | * @throws \InvalidArgumentException |
||
212 | * @param string $attributeName the attribute name |
||
213 | * @param string $attributeType the attribute type |
||
214 | * @return Struct |
||
215 | */ |
||
216 | 480 | public function addAttribute($attributeName, $attributeType) |
|
217 | { |
||
218 | 480 | if (empty($attributeName) || empty($attributeType)) { |
|
219 | 8 | throw new \InvalidArgumentException(sprintf('Attribute name "%s" and/or attribute type "%s" is invalid for Struct "%s"', $attributeName, $attributeType, $this->getName()), __LINE__); |
|
220 | } |
||
221 | 472 | if ($this->attributes->getStructAttributeByName($attributeName) === null) { |
|
222 | 468 | $structAttribute = new StructAttribute($this->getGenerator(), $attributeName, $attributeType, $this); |
|
223 | 468 | $this->attributes->add($structAttribute); |
|
224 | 468 | } |
|
225 | 472 | return $this; |
|
226 | } |
||
227 | /** |
||
228 | * Returns the attribute by its name, otherwise null |
||
229 | * @uses Struct::getAttributes() |
||
230 | * @param string $attributeName the original attribute name |
||
231 | * @return StructAttribute|null |
||
232 | */ |
||
233 | 336 | public function getAttribute($attributeName) |
|
234 | { |
||
235 | 336 | return $this->attributes->getStructAttributeByName($attributeName); |
|
236 | } |
||
237 | /** |
||
238 | * Returns the isRestriction value |
||
239 | * @return bool |
||
240 | */ |
||
241 | 288 | public function getIsRestriction() |
|
242 | { |
||
243 | 288 | return $this->isRestriction; |
|
244 | } |
||
245 | /** |
||
246 | * Sets the isRestriction value |
||
247 | * @param bool $isRestriction |
||
248 | * @return Struct |
||
249 | */ |
||
250 | 536 | public function setIsRestriction($isRestriction = true) |
|
251 | { |
||
252 | 536 | $this->isRestriction = $isRestriction; |
|
253 | 536 | return $this; |
|
254 | } |
||
255 | /** |
||
256 | * Returns the isStruct value |
||
257 | * @return bool |
||
258 | */ |
||
259 | 312 | public function getIsStruct() |
|
260 | { |
||
261 | 312 | return $this->isStruct; |
|
262 | } |
||
263 | /** |
||
264 | * Sets the isStruct value |
||
265 | * @param bool $isStruct |
||
266 | * @return Struct |
||
267 | */ |
||
268 | 536 | public function setIsStruct($isStruct = true) |
|
269 | { |
||
270 | 536 | $this->isStruct = $isStruct; |
|
271 | 536 | return $this; |
|
272 | } |
||
273 | /** |
||
274 | * Returns the values for an enumeration |
||
275 | * @return StructValueContainer |
||
276 | */ |
||
277 | 300 | public function getValues() |
|
278 | { |
||
279 | 300 | return $this->values; |
|
280 | } |
||
281 | /** |
||
282 | * Sets the values for an enumeration |
||
283 | * @param StructValueContainer $structValueContainer |
||
284 | * @return Struct |
||
285 | */ |
||
286 | 536 | private function setValues(StructValueContainer $structValueContainer) |
|
287 | { |
||
288 | 536 | $this->values = $structValueContainer; |
|
289 | 536 | return $this; |
|
290 | } |
||
291 | /** |
||
292 | * Adds value to values array |
||
293 | * @uses Struct::getValue() |
||
294 | * @uses Struct::getValues() |
||
295 | * @param mixed $value the original value |
||
296 | * @return Struct |
||
297 | */ |
||
298 | 304 | public function addValue($value) |
|
299 | { |
||
300 | 304 | if ($this->getValue($value) === null) { |
|
301 | 300 | $this->values->add(new StructValue($this->getGenerator(), $value, $this->getValues()->count(), $this)); |
|
302 | 300 | $this->setIsRestriction(true); |
|
303 | 300 | $this->setIsStruct(true); |
|
304 | 300 | } |
|
305 | 304 | return $this; |
|
306 | } |
||
307 | /** |
||
308 | * Gets the value object for the given value |
||
309 | * @uses Struct::getValues() |
||
310 | * @uses AbstractModel::getName() |
||
311 | * @param string $value Value name |
||
312 | * @return StructValue|null |
||
313 | */ |
||
314 | 304 | public function getValue($value) |
|
315 | { |
||
316 | 304 | return $this->values->getStructValueByName($value); |
|
317 | } |
||
318 | /** |
||
319 | * Allows to define from which class the curent model extends |
||
320 | * @param bool $short |
||
321 | * @return string |
||
322 | */ |
||
323 | 132 | public function getExtends($short = false) |
|
324 | { |
||
325 | 132 | $extends = ''; |
|
326 | 132 | if ($this->isArray()) { |
|
327 | 28 | $extends = $this->getGenerator()->getOptionStructArrayClass(); |
|
328 | 132 | } elseif (!$this->getIsRestriction()) { |
|
329 | 84 | $extends = $this->getGenerator()->getOptionStructClass(); |
|
330 | 84 | } |
|
331 | 132 | return $short ? Utils::removeNamespace($extends) : $extends; |
|
332 | } |
||
333 | /** |
||
334 | * @return Struct|null |
||
335 | */ |
||
336 | 168 | public function getInheritanceStruct() |
|
340 | /** |
||
341 | * @return Struct|null |
||
342 | */ |
||
343 | 96 | public function getTopInheritance() |
|
358 | /** |
||
359 | * @see \WsdlToPhp\PackageGenerator\Model\AbstractModel::getMeta() |
||
360 | * @return string[] |
||
361 | */ |
||
362 | 160 | public function getMeta() |
|
367 | /** |
||
368 | * @param $filename |
||
369 | * @return StructReservedMethod|StructArrayReservedMethod |
||
370 | */ |
||
371 | 116 | public function getReservedMethodsInstance($filename = null) |
|
379 | } |
||
380 |