Complex classes like Node 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 Node, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
25 | abstract class Node implements INode, DAV\INode |
||
26 | { |
||
27 | /** |
||
28 | * name max lenght |
||
29 | */ |
||
30 | const MAX_NAME_LENGTH = 255; |
||
31 | |||
32 | |||
33 | /** |
||
34 | * Unique id |
||
35 | * |
||
36 | * @var ObjectId |
||
37 | */ |
||
38 | protected $_id; |
||
39 | |||
40 | |||
41 | /** |
||
42 | * Node name |
||
43 | * |
||
44 | * @var string |
||
45 | */ |
||
46 | protected $name = ''; |
||
47 | |||
48 | |||
49 | /** |
||
50 | * Owner |
||
51 | * |
||
52 | * @var ObjectId |
||
53 | */ |
||
54 | protected $owner; |
||
55 | |||
56 | |||
57 | /** |
||
58 | * User |
||
59 | * |
||
60 | * @var \Balloon\User |
||
61 | */ |
||
62 | protected $user; |
||
63 | |||
64 | |||
65 | /** |
||
66 | * Meta attributes |
||
67 | * |
||
68 | * @var array |
||
69 | */ |
||
70 | protected $meta = []; |
||
71 | |||
72 | |||
73 | /** |
||
74 | * Parent collection |
||
75 | * |
||
76 | * @var ObjectId |
||
77 | */ |
||
78 | protected $parent; |
||
79 | |||
80 | |||
81 | /** |
||
82 | * Is file deleted |
||
83 | * |
||
84 | * @var bool|UTCDateTime |
||
85 | */ |
||
86 | protected $deleted = false; |
||
87 | |||
88 | |||
89 | /** |
||
90 | * Is collection |
||
91 | * |
||
92 | * @var bool |
||
93 | */ |
||
94 | protected $directory = false; |
||
95 | |||
96 | |||
97 | /** |
||
98 | * Is shared? |
||
99 | * |
||
100 | * @var bool |
||
101 | */ |
||
102 | protected $shared = false; |
||
103 | |||
104 | |||
105 | /** |
||
106 | * Destory at a certain time |
||
107 | * |
||
108 | * @var UTCDateTime |
||
109 | */ |
||
110 | protected $destroy; |
||
111 | |||
112 | |||
113 | /** |
||
114 | * Changed timestamp |
||
115 | * |
||
116 | * @var UTCDateTime |
||
117 | */ |
||
118 | protected $changed; |
||
119 | |||
120 | |||
121 | /** |
||
122 | * Created timestamp |
||
123 | * |
||
124 | * @var UTCDateTime |
||
125 | */ |
||
126 | protected $created; |
||
127 | |||
128 | |||
129 | /** |
||
130 | * Point to antother node (Means this node is reference to $reference) |
||
131 | * |
||
132 | * @var ObjectId |
||
133 | */ |
||
134 | protected $reference; |
||
135 | |||
136 | |||
137 | /** |
||
138 | * Share link options |
||
139 | * |
||
140 | * @var bool|array |
||
141 | */ |
||
142 | protected $sharelink = false; |
||
143 | |||
144 | |||
145 | /** |
||
146 | * Raw attributes before any processing or modifications |
||
147 | * |
||
148 | * @var array |
||
149 | */ |
||
150 | protected $raw_attributes; |
||
151 | |||
152 | |||
153 | /** |
||
154 | * Readonly flag |
||
155 | * |
||
156 | * @var bool |
||
157 | */ |
||
158 | protected $readonly = false; |
||
159 | |||
160 | |||
161 | /** |
||
162 | * Filesystem |
||
163 | * |
||
164 | * @var Filesystem |
||
165 | */ |
||
166 | protected $_fs; |
||
167 | |||
168 | |||
169 | /** |
||
170 | * Database |
||
171 | * |
||
172 | * @var \MongoDB\Database |
||
173 | */ |
||
174 | protected $_db; |
||
175 | |||
176 | |||
177 | /** |
||
178 | * User |
||
179 | * |
||
180 | * @var User |
||
181 | */ |
||
182 | protected $_user; |
||
183 | |||
184 | |||
185 | /** |
||
186 | * Logger |
||
187 | * |
||
188 | * @var Logger |
||
189 | */ |
||
190 | protected $_logger; |
||
191 | |||
192 | |||
193 | /** |
||
194 | * Plugin |
||
195 | * |
||
196 | * @var Plugin |
||
197 | */ |
||
198 | protected $_pluginmgr; |
||
199 | |||
200 | |||
201 | /** |
||
202 | * Queue |
||
203 | * |
||
204 | * @var Queue |
||
205 | */ |
||
206 | protected $_queuemgr; |
||
207 | |||
208 | |||
209 | /** |
||
210 | * Config |
||
211 | * |
||
212 | * @var Config |
||
213 | */ |
||
214 | protected $_config; |
||
215 | |||
216 | |||
217 | /** |
||
218 | * Initialize |
||
219 | * |
||
220 | * @param BSONDocument $node |
||
221 | * @param Filesystem $fs |
||
222 | * @return void |
||
|
|||
223 | */ |
||
224 | public function __construct(?BSONDocument $node, Filesystem $fs) |
||
243 | |||
244 | |||
245 | /** |
||
246 | * Convert to filename |
||
247 | * |
||
248 | * @return string |
||
249 | */ |
||
250 | public function __toString() |
||
254 | |||
255 | |||
256 | /** |
||
257 | * Get filesystem |
||
258 | * |
||
259 | * @return Filesystem |
||
260 | */ |
||
261 | public function getFilesystem(): Filesystem |
||
265 | |||
266 | |||
267 | /** |
||
268 | * Get property |
||
269 | * |
||
270 | * @return mixed |
||
271 | */ |
||
272 | public function __call(string $attribute, array $params=[]) |
||
282 | |||
283 | |||
284 | /** |
||
285 | * Check if $node is a sub node of any parent nodes of this node |
||
286 | * |
||
287 | * @param INode $node |
||
288 | * @return bool |
||
289 | */ |
||
290 | public function isSubNode(INode $node): bool |
||
308 | |||
309 | |||
310 | /** |
||
311 | * Move node |
||
312 | * |
||
313 | * @param Collection $parent |
||
314 | * @param int $conflict |
||
315 | * @return INode |
||
316 | */ |
||
317 | public function setParent(Collection $parent, int $conflict=INode::CONFLICT_NOACTION): INode |
||
381 | |||
382 | |||
383 | /** |
||
384 | * Copy node |
||
385 | * |
||
386 | * @param Collection $parent |
||
387 | * @param int $conflict |
||
388 | * @param string $recursion |
||
389 | * @param bool $recursion_first |
||
390 | * @return INode |
||
391 | */ |
||
392 | abstract public function copyTo(Collection $parent, int $conflict=INode::CONFLICT_NOACTION, ?string $recursion=null, bool $recursion_first=true): INode; |
||
393 | |||
394 | |||
395 | /** |
||
396 | * Get share id |
||
397 | * |
||
398 | * @param bool $reference |
||
399 | * @return ObjectId |
||
400 | */ |
||
401 | public function getShareId(bool $reference=false): ?ObjectId |
||
417 | |||
418 | |||
419 | /** |
||
420 | * Check node |
||
421 | * |
||
422 | * @return void |
||
423 | */ |
||
424 | protected function _verifyAccess() |
||
441 | |||
442 | |||
443 | /** |
||
444 | * Get share node |
||
445 | * |
||
446 | * @param bool $reference |
||
447 | * @return Collection |
||
448 | */ |
||
449 | public function getShareNode(): ?Collection |
||
457 | |||
458 | |||
459 | /** |
||
460 | * Is node marked as readonly? |
||
461 | * |
||
462 | * @return bool |
||
463 | */ |
||
464 | public function isReadonly(): bool |
||
468 | |||
469 | |||
470 | /** |
||
471 | * Request is from node owner? |
||
472 | * |
||
473 | * @return bool |
||
474 | */ |
||
475 | public function isOwnerRequest(): bool |
||
476 | { |
||
477 | return ($this->_user !== null && $this->owner == $this->_user->getId()); |
||
478 | } |
||
479 | |||
480 | |||
481 | /** |
||
482 | * Check if node is kind of special |
||
483 | * |
||
484 | * @return bool |
||
485 | */ |
||
486 | public function isSpecial(): bool |
||
498 | |||
499 | |||
500 | /** |
||
501 | * Check if node is a sub node of a share |
||
502 | * |
||
503 | * @return bool |
||
504 | */ |
||
505 | public function isShareMember(): bool |
||
509 | |||
510 | |||
511 | /** |
||
512 | * Is share |
||
513 | * |
||
514 | * @return bool |
||
515 | */ |
||
516 | public function isShare(): bool |
||
520 | |||
521 | |||
522 | /** |
||
523 | * Is share (Reference or master share) |
||
524 | * |
||
525 | * @return bool |
||
526 | */ |
||
527 | public function isShared(): bool |
||
535 | |||
536 | |||
537 | /** |
||
538 | * Set the name |
||
539 | * |
||
540 | * @param string $name |
||
541 | * @return bool |
||
542 | */ |
||
543 | public function setName($name): bool |
||
556 | |||
557 | |||
558 | /** |
||
559 | * Check name |
||
560 | * |
||
561 | * @param string $name |
||
562 | * @return string |
||
563 | */ |
||
564 | public function checkName(string $name): string |
||
578 | |||
579 | |||
580 | /** |
||
581 | * Get the name |
||
582 | * |
||
583 | * @return string |
||
584 | */ |
||
585 | public function getName(): string |
||
589 | |||
590 | |||
591 | /** |
||
592 | * Check acl |
||
593 | * |
||
594 | * @param string $privilege |
||
595 | * @return bool |
||
596 | */ |
||
597 | public function isAllowed(string $privilege='r'): bool |
||
651 | |||
652 | |||
653 | /** |
||
654 | * Get privilege |
||
655 | * |
||
656 | * rw - READ/WRITE |
||
657 | * r - READ(only) |
||
658 | * w - WRITE(only) |
||
659 | * d - DENY |
||
660 | * |
||
661 | * @return string |
||
662 | */ |
||
663 | public function getAclPrivilege() |
||
763 | |||
764 | |||
765 | /** |
||
766 | * Get Attribute helper |
||
767 | * |
||
768 | * @param array|string $attribute |
||
769 | * @return array|string |
||
770 | */ |
||
771 | protected function _getAttribute($attribute) |
||
913 | |||
914 | |||
915 | /** |
||
916 | * Duplicate name with a uniqid within name |
||
917 | * |
||
918 | * @param string $name |
||
919 | * @return string |
||
920 | */ |
||
921 | protected function _getDuplicateName(?string $name=null): string |
||
940 | |||
941 | |||
942 | /** |
||
943 | * Undelete |
||
944 | * |
||
945 | * @param int $conflict |
||
946 | * @param string $recursion |
||
947 | * @param bool $recursion_first |
||
948 | * @return bool |
||
949 | */ |
||
950 | public function undelete(int $conflict=INode::CONFLICT_NOACTION, ?string $recursion=null, bool $recursion_first=true): bool |
||
1029 | |||
1030 | |||
1031 | /** |
||
1032 | * Is node deleted? |
||
1033 | * |
||
1034 | * @return bool |
||
1035 | */ |
||
1036 | public function isDeleted(): bool |
||
1040 | |||
1041 | |||
1042 | /** |
||
1043 | * Share link |
||
1044 | * |
||
1045 | * @param array $options |
||
1046 | * @return bool |
||
1047 | */ |
||
1048 | public function shareLink(array $options): bool |
||
1107 | |||
1108 | |||
1109 | /** |
||
1110 | * Get share options |
||
1111 | * |
||
1112 | * @return bool|array |
||
1113 | */ |
||
1114 | public function getShareLink() |
||
1122 | |||
1123 | |||
1124 | /** |
||
1125 | * Get last modified timestamp |
||
1126 | * |
||
1127 | * @return int |
||
1128 | */ |
||
1129 | public function getLastModified(): int |
||
1137 | |||
1138 | |||
1139 | /** |
||
1140 | * Get unique id |
||
1141 | * |
||
1142 | * @return ObjectId|string |
||
1143 | */ |
||
1144 | public function getId(bool $string=false) |
||
1152 | |||
1153 | |||
1154 | /** |
||
1155 | * Get parent |
||
1156 | * |
||
1157 | * @return Collection |
||
1158 | */ |
||
1159 | public function getParent(): ?Collection |
||
1160 | { |
||
1161 | try { |
||
1162 | if ($this->isRoot()) { |
||
1163 | return null; |
||
1164 | } elseif ($this->isInRoot()) { |
||
1165 | return $this->_fs->getRoot(); |
||
1166 | } else { |
||
1167 | $parent = $this->_fs->findNodeWithId($this->parent); |
||
1168 | if ($parent->isShare() && !$parent->isOwnerRequest() && $this->_user !== null) { |
||
1169 | $node = $this->_db->storage->findOne([ |
||
1170 | 'owner' => $this->_user->getId(), |
||
1171 | 'shared' => true, |
||
1172 | 'reference' => $this->parent, |
||
1173 | ]); |
||
1174 | |||
1175 | return new Collection($node, $this->_fs); |
||
1176 | } else { |
||
1177 | return $parent; |
||
1178 | } |
||
1179 | } |
||
1180 | } catch (Exception\NotFound $e) { |
||
1181 | throw new Exception\NotFound('parent node '.$this->parent.' could not be found', |
||
1182 | Exception\NotFound::PARENT_NOT_FOUND |
||
1183 | ); |
||
1184 | } |
||
1185 | } |
||
1186 | |||
1187 | |||
1188 | /** |
||
1189 | * Get parents |
||
1190 | * |
||
1191 | * @param array $parents |
||
1192 | * @return array |
||
1193 | */ |
||
1194 | public function getParents(?INode $node=null, array $parents=[]): array |
||
1210 | |||
1211 | |||
1212 | /** |
||
1213 | * Check if the node is a shared link |
||
1214 | * |
||
1215 | * @return bool |
||
1216 | */ |
||
1217 | public function isShareLink(): bool |
||
1221 | |||
1222 | |||
1223 | /** |
||
1224 | * Download |
||
1225 | * |
||
1226 | * @return void |
||
1227 | */ |
||
1228 | abstract public function get(); |
||
1229 | |||
1230 | |||
1231 | /** |
||
1232 | * Get as zip |
||
1233 | * |
||
1234 | * @return void |
||
1235 | */ |
||
1236 | public function getZip(): void |
||
1249 | |||
1250 | |||
1251 | /** |
||
1252 | * Create zip |
||
1253 | * |
||
1254 | * @param ZipStream $archive |
||
1255 | * @param bool $self true means that the zip represents the collection itself instead a child of the zip |
||
1256 | * @param INode $parent |
||
1257 | * @param string $path |
||
1258 | * @param int $depth |
||
1259 | * @return bool |
||
1260 | */ |
||
1261 | public function zip(ZipStream $archive, bool $self=true, ?INode $parent=null, string $path='', int $depth=0): bool |
||
1303 | |||
1304 | |||
1305 | /** |
||
1306 | * Is reference |
||
1307 | * |
||
1308 | * @return bool |
||
1309 | */ |
||
1310 | public function isReference(): bool |
||
1314 | |||
1315 | |||
1316 | /** |
||
1317 | * Set meta attribute |
||
1318 | * |
||
1319 | * @param array|string |
||
1320 | * @param mixed $value |
||
1321 | * @return INode |
||
1322 | */ |
||
1323 | public function setMetaAttribute($attributes, $value=null): INode |
||
1329 | |||
1330 | |||
1331 | /** |
||
1332 | * validate meta attribut |
||
1333 | * |
||
1334 | * @param array|string $attributes |
||
1335 | * @param mixed $value |
||
1336 | * @param array $set |
||
1337 | * @return array |
||
1338 | */ |
||
1339 | public static function validateMetaAttribute($attributes, $value=null, array $set=[]): array |
||
1362 | |||
1363 | |||
1364 | /** |
||
1365 | * Get meta attributes as array |
||
1366 | * |
||
1367 | * @param string|array $attribute Specify attributes to return |
||
1368 | * @return string|array |
||
1369 | */ |
||
1370 | public function getMetaAttribute($attribute=[]) |
||
1382 | |||
1383 | |||
1384 | /** |
||
1385 | * Mark node as readonly |
||
1386 | * |
||
1387 | * @param bool $readonly |
||
1388 | * @return bool |
||
1389 | */ |
||
1390 | public function setReadonly(bool $readonly=true): bool |
||
1395 | |||
1396 | |||
1397 | /** |
||
1398 | * Mark node as self-destroyable |
||
1399 | * |
||
1400 | * @param UTCDateTime $ts |
||
1401 | * @return bool |
||
1402 | */ |
||
1403 | public function setDestroyable(?UTCDateTime $ts): bool |
||
1413 | |||
1414 | |||
1415 | /** |
||
1416 | * Delete node |
||
1417 | * |
||
1418 | * Actually the node will not be deleted (Just set a delete flag), set $force=true to |
||
1419 | * delete finally |
||
1420 | * |
||
1421 | * @param bool $force |
||
1422 | * @param bool $recursion_first |
||
1423 | * @param string $recursion |
||
1424 | * @return bool |
||
1425 | */ |
||
1426 | abstract public function delete(bool $force=false, ?string $recursion=null, bool $recursion_first=true): bool; |
||
1427 | |||
1428 | |||
1429 | /** |
||
1430 | * Get original raw attributes before any processing |
||
1431 | * |
||
1432 | * @return array|\MongoDB\BSON\Document |
||
1433 | */ |
||
1434 | public function getRawAttributes() |
||
1438 | |||
1439 | |||
1440 | /** |
||
1441 | * Completly remove node |
||
1442 | * |
||
1443 | * @return bool |
||
1444 | */ |
||
1445 | abstract protected function _forceDelete(): bool; |
||
1446 | |||
1447 | |||
1448 | /** |
||
1449 | * Check if node is in root |
||
1450 | * |
||
1451 | * @return bool |
||
1452 | */ |
||
1453 | public function isInRoot(): bool |
||
1457 | |||
1458 | |||
1459 | /** |
||
1460 | * Check if node is an instance of the actual root collection |
||
1461 | * |
||
1462 | * @return bool |
||
1463 | */ |
||
1464 | public function isRoot(): bool |
||
1468 | |||
1469 | |||
1470 | /** |
||
1471 | * Resolve node path |
||
1472 | * |
||
1473 | * @return string |
||
1474 | */ |
||
1475 | public function getPath(): string |
||
1485 | |||
1486 | |||
1487 | /** |
||
1488 | * Save node attributes |
||
1489 | * |
||
1490 | * @param string|array $attributes |
||
1491 | * @param string|array $remove |
||
1492 | * @param string $recursion |
||
1493 | * @param bool $recursion_first |
||
1494 | * @return bool |
||
1495 | */ |
||
1496 | public function save($attributes=[], $remove=[], ?string $recursion=null, bool $recursion_first=true): bool |
||
1552 | |||
1553 | |||
1554 | /** |
||
1555 | * Get children |
||
1556 | * |
||
1557 | * @param array $filter |
||
1558 | * @param array $attributes |
||
1559 | * @param int $limit |
||
1560 | * @param string $cursor |
||
1561 | * @param bool $has_more |
||
1562 | * @return array |
||
1563 | */ |
||
1564 | public static function loadNodeAttributesWithCustomFilter( |
||
1611 | } |
||
1612 |
Adding a
@return
annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.Please refer to the PHP core documentation on constructors.