Total Complexity | 56 |
Total Lines | 280 |
Duplicated Lines | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Complex classes like ModelElementTypeImpl 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.
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 ModelElementTypeImpl, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
28 | class ModelElementTypeImpl implements ModelElementTypeInterface |
||
29 | { |
||
30 | private $model; |
||
31 | private $typeName; |
||
32 | private $instanceType; |
||
33 | private $typeNamespace; |
||
34 | private $baseType; |
||
35 | private $extendingTypes = []; |
||
36 | private $attributes = []; |
||
37 | private $childElementTypes = []; |
||
38 | private $childElementCollections = []; |
||
39 | private $instanceProvider; |
||
40 | private $isAbstract; |
||
41 | |||
42 | public function __construct(ModelImpl $model, string $name, string $instanceType) |
||
43 | { |
||
44 | $this->model = $model; |
||
45 | $this->typeName = $name; |
||
46 | $this->instanceType = $instanceType; |
||
47 | } |
||
48 | |||
49 | public function newInstance( |
||
50 | ModelInstanceInterface $modelInstance, |
||
51 | ?DomElementInterface $domElement = null |
||
52 | ): ModelElementInstanceInterface { |
||
53 | if ($domElement !== null) { |
||
54 | $modelTypeInstanceContext = new ModelTypeInstanceContext($domElement, $modelInstance, $this); |
||
55 | return $this->createModelElementInstance($modelTypeInstanceContext); |
||
56 | } else { |
||
57 | $document = $modelInstance->getDocument(); |
||
58 | $domElement = $document->createElement($this->typeNamespace, $this->typeName); |
||
59 | return $this->newInstance($modelInstance, $domElement); |
||
60 | } |
||
61 | } |
||
62 | |||
63 | public function registerAttribute(AttributeInterface $attribute): void |
||
64 | { |
||
65 | if (!in_array($attribute, $this->attributes)) { |
||
66 | $this->attributes[] = $attribute; |
||
67 | } |
||
68 | } |
||
69 | |||
70 | public function registerChildElementType(ModelElementTypeInterface $childElementType): void |
||
71 | { |
||
72 | if (!in_array($childElementType, $this->childElementTypes)) { |
||
73 | $this->childElementTypes[] = $childElementType; |
||
74 | } |
||
75 | } |
||
76 | |||
77 | public function registerChildElementCollection(ChildElementCollectionInterface $childElementCollection): void |
||
78 | { |
||
79 | if (!in_array($childElementCollection, $this->childElementCollections)) { |
||
80 | $this->childElementCollections[] = $childElementCollection; |
||
81 | } |
||
82 | } |
||
83 | |||
84 | public function registerExtendingType(ModelElementTypeInterface $modelType): void |
||
85 | { |
||
86 | if (!in_array($modelType, $this->extendingTypes)) { |
||
87 | $this->extendingTypes[] = $modelType; |
||
88 | } |
||
89 | } |
||
90 | |||
91 | protected function createModelElementInstance( |
||
92 | ModelTypeInstanceContext $instanceContext |
||
93 | ): ModelElementInstanceInterface { |
||
94 | if ($this->isAbstract) { |
||
95 | throw new ModelTypeException( |
||
96 | sprintf( |
||
97 | "Model element type %s is abstract and no instances can be created.", |
||
98 | $this->getTypeName() |
||
99 | ) |
||
100 | ); |
||
101 | } else { |
||
102 | return $this->instanceProvider->newInstance($instanceContext); |
||
103 | } |
||
104 | } |
||
105 | |||
106 | public function getAttributes(): array |
||
107 | { |
||
108 | return $this->attributes; |
||
109 | } |
||
110 | |||
111 | public function getTypeName(): string |
||
112 | { |
||
113 | return $this->typeName; |
||
114 | } |
||
115 | |||
116 | public function getInstanceType(): string |
||
117 | { |
||
118 | return $this->instanceType; |
||
119 | } |
||
120 | |||
121 | public function setTypeNamespace(?string $typeNamespace): void |
||
122 | { |
||
123 | $this->typeNamespace = $typeNamespace; |
||
124 | } |
||
125 | |||
126 | public function getTypeNamespace(): ?string |
||
127 | { |
||
128 | return $this->typeNamespace; |
||
129 | } |
||
130 | |||
131 | public function setBaseType(ModelElementTypeImpl $baseType): void |
||
132 | { |
||
133 | if ($this->baseType === null) { |
||
134 | $this->baseType = $baseType; |
||
135 | } elseif ($this->baseType != $baseType) { |
||
136 | throw new ModelException( |
||
137 | sprintf( |
||
138 | "Type can not have multiple base types. %s already extends type %s and can not also extend type %s", |
||
139 | get_class($this), |
||
140 | get_class($this->baseType), |
||
141 | get_class($this) |
||
142 | ) |
||
143 | ); |
||
144 | } |
||
145 | } |
||
146 | |||
147 | public function setInstanceProvider(ModelTypeInstanceProviderInterface $instanceProvider): void |
||
148 | { |
||
149 | $this->instanceProvider = $instanceProvider; |
||
150 | } |
||
151 | |||
152 | public function isAbstract(): bool |
||
155 | } |
||
156 | |||
157 | public function setAbstract(bool $isAbstract): void |
||
158 | { |
||
159 | $this->isAbstract = $isAbstract; |
||
160 | } |
||
161 | |||
162 | public function getExtendingTypes(): array |
||
163 | { |
||
164 | return $this->extendingTypes; |
||
165 | } |
||
166 | |||
167 | public function getAllExtendingTypes(): array |
||
168 | { |
||
169 | $extendingTypes = []; |
||
170 | $extendingTypes[] = $this; |
||
171 | $this->resolveExtendingTypes($extendingTypes); |
||
172 | return $extendingTypes; |
||
173 | } |
||
174 | |||
175 | public function resolveExtendingTypes(array &$allExtendingTypes): void |
||
176 | { |
||
177 | foreach ($this->extendingTypes as $modelElementTypeImpl) { |
||
178 | if (!in_array($modelElementTypeImpl, $allExtendingTypes)) { |
||
179 | $allExtendingTypes[] = $modelElementTypeImpl; |
||
180 | $modelElementTypeImpl->resolveExtendingTypes($allExtendingTypes); |
||
181 | } |
||
182 | } |
||
183 | } |
||
184 | |||
185 | public function resolveBaseTypes(array &$baseTypes): void |
||
186 | { |
||
187 | if ($this->baseType !== null) { |
||
188 | $baseTypes[] = $this->baseType; |
||
189 | $this->baseType->resolveBaseTypes($baseTypes); |
||
190 | } |
||
191 | } |
||
192 | |||
193 | public function getBaseType(): ?ModelElementTypeInterface |
||
194 | { |
||
195 | return $this->baseType; |
||
196 | } |
||
197 | |||
198 | public function getModel(): ModelInterface |
||
199 | { |
||
200 | return $this->model; |
||
201 | } |
||
202 | |||
203 | public function getChildElementTypes(): array |
||
204 | { |
||
205 | return $this->childElementTypes; |
||
206 | } |
||
207 | |||
208 | public function getAllChildElementTypes(): array |
||
209 | { |
||
210 | $allChildElementTypes = []; |
||
211 | if ($this->baseType !== null) { |
||
212 | $allChildElementTypes = array_merge($allChildElementTypes, $this->baseType->getAllChildElementTypes()); |
||
213 | } |
||
214 | $allChildElementTypes = array_merge($allChildElementTypes, $this->childElementTypes); |
||
215 | return $allChildElementTypes; |
||
216 | } |
||
217 | |||
218 | public function getChildElementCollections(): array |
||
219 | { |
||
220 | return $this->childElementCollections; |
||
221 | } |
||
222 | |||
223 | public function getAllChildElementCollections(): array |
||
224 | { |
||
225 | $allChildElementCollections = []; |
||
226 | if ($this->baseType !== null) { |
||
227 | $allChildElementCollections = array_merge( |
||
228 | $allChildElementCollections, |
||
229 | $this->baseType->getAllChildElementCollections() |
||
230 | ); |
||
231 | } |
||
232 | $allChildElementCollections = array_merge($allChildElementCollections, $this->childElementCollections); |
||
233 | return $allChildElementCollections; |
||
234 | } |
||
235 | |||
236 | public function getInstances(ModelInstanceInterface $modelInstanceImpl): array |
||
247 | } |
||
248 | |||
249 | protected function getElementsByNameNs(DomDocumentInterface $document, string $namespaceURI): array |
||
250 | { |
||
251 | $elements = $document->getElementsByNameNs($namespaceURI, $this->typeName); |
||
252 | |||
253 | if (empty($elements)) { |
||
254 | $alternativeNamespaces = $this->getModel()->getAlternativeNamespaces($namespaceURI); |
||
255 | |||
256 | if (!empty($alternativeNamespaces)) { |
||
257 | foreach ($alternativeNamespaces as $namespace) { |
||
258 | $elements = $this->getElementsByNameNs($document, $namespace); |
||
259 | if (!empty($elements)) { |
||
260 | break; |
||
261 | } |
||
262 | } |
||
263 | } |
||
264 | } |
||
265 | |||
266 | return $elements; |
||
267 | } |
||
268 | |||
269 | public function isBaseTypeOf(ModelElementTypeInterface $elementType): bool |
||
276 | } |
||
277 | } |
||
278 | |||
279 | public function getAllAttributes(): array |
||
280 | { |
||
281 | $allAttributes = array_merge([], $this->getAttributes()); |
||
282 | $baseTypes = ModelUtil::calculateAllBaseTypes($this); |
||
283 | foreach ($baseTypes as $baseType) { |
||
284 | $allAttributes = array_merge($allAttributes, $baseType->getAttributes()); |
||
285 | } |
||
286 | return $allAttributes; |
||
287 | } |
||
288 | |||
289 | public function getAttribute(string $attributeName): ?AttributeInterface |
||
297 | } |
||
298 | |||
299 | public function getChildElementCollection( |
||
300 | ModelElementTypeInterface $childElementType |
||
301 | ): ChildElementCollectionInterface { |
||
302 | foreach ($this->getChildElementCollections() as $childElementCollection) { |
||
303 | if ($childElementType == $childElementCollection->getChildElementType($this->model)) { |
||
304 | return $childElementCollection; |
||
305 | } |
||
308 | } |
||
309 | } |
||
310 |