Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like ElggUser 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 ElggUser, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
20 | class ElggUser extends \ElggEntity |
||
21 | implements Friendable { |
||
22 | |||
23 | /** |
||
24 | * Initialize the attributes array. |
||
25 | * This is vital to distinguish between metadata and base attributes. |
||
26 | * |
||
27 | * @return void |
||
28 | */ |
||
29 | 2 | View Code Duplication | protected function initializeAttributes() { |
36 | |||
37 | /** |
||
38 | * Get default values for attributes stored in a separate table |
||
39 | * |
||
40 | * @return array |
||
41 | * @access private |
||
42 | * |
||
43 | * @see \Elgg\Database\EntityTable::getEntities |
||
44 | */ |
||
45 | 2 | final public static function getExternalAttributes() { |
|
61 | |||
62 | /** |
||
63 | * Construct a new user entity |
||
64 | * |
||
65 | * Plugin developers should only use the constructor to create a new entity. |
||
66 | * To retrieve entities, use get_entity() and the elgg_get_entities* functions. |
||
67 | * |
||
68 | * @param \stdClass $row Database row result. Default is null to create a new user. |
||
69 | * |
||
70 | * @throws IOException|InvalidParameterException if there was a problem creating the user. |
||
71 | */ |
||
72 | 2 | View Code Duplication | public function __construct($row = null) { |
112 | |||
113 | /** |
||
114 | * Load the \ElggUser data from the database |
||
115 | * |
||
116 | * @param mixed $guid \ElggUser GUID or \stdClass database row from entity table |
||
117 | * |
||
118 | * @return bool |
||
119 | */ |
||
120 | View Code Duplication | protected function load($guid) { |
|
136 | |||
137 | |||
138 | /** |
||
139 | * {@inheritdoc} |
||
140 | */ |
||
141 | protected function create() { |
||
165 | |||
166 | /** |
||
167 | * {@inheritdoc} |
||
168 | */ |
||
169 | protected function update() { |
||
192 | |||
193 | /** |
||
194 | * User specific override of the entity delete method. |
||
195 | * |
||
196 | * @return bool |
||
197 | */ |
||
198 | public function delete() { |
||
209 | |||
210 | /** |
||
211 | * {@inheritdoc} |
||
212 | */ |
||
213 | public function getDisplayName() { |
||
216 | |||
217 | /** |
||
218 | * {@inheritdoc} |
||
219 | */ |
||
220 | public function setDisplayName($displayName) { |
||
223 | |||
224 | /** |
||
225 | * {@inheritdoc} |
||
226 | */ |
||
227 | 1 | public function __set($name, $value) { |
|
265 | |||
266 | /** |
||
267 | * {@inheritdoc} |
||
268 | */ |
||
269 | public function set($name, $value) { |
||
275 | |||
276 | /** |
||
277 | * Ban this user. |
||
278 | * |
||
279 | * @param string $reason Optional reason |
||
280 | * |
||
281 | * @return bool |
||
282 | */ |
||
283 | public function ban($reason = "") { |
||
286 | |||
287 | /** |
||
288 | * Unban this user. |
||
289 | * |
||
290 | * @return bool |
||
291 | */ |
||
292 | public function unban() { |
||
295 | |||
296 | /** |
||
297 | * Is this user banned or not? |
||
298 | * |
||
299 | * @return bool |
||
300 | */ |
||
301 | public function isBanned() { |
||
304 | |||
305 | /** |
||
306 | * Is this user admin? |
||
307 | * |
||
308 | * @return bool |
||
309 | */ |
||
310 | public function isAdmin() { |
||
318 | |||
319 | /** |
||
320 | * Make the user an admin |
||
321 | * |
||
322 | * @return bool |
||
323 | */ |
||
324 | public function makeAdmin() { |
||
335 | |||
336 | /** |
||
337 | * Remove the admin flag for user |
||
338 | * |
||
339 | * @return bool |
||
340 | */ |
||
341 | public function removeAdmin() { |
||
352 | |||
353 | /** |
||
354 | * Get sites that this user is a member of |
||
355 | * |
||
356 | * @param array $options Options array. Used to be $subtype |
||
357 | * @param int $limit The number of results to return (deprecated) |
||
358 | * @param int $offset Any indexing offset (deprecated) |
||
359 | * |
||
360 | * @return array |
||
361 | */ |
||
362 | View Code Duplication | public function getSites($options = "", $limit = 10, $offset = 0) { |
|
370 | |||
371 | /** |
||
372 | * Add this user to a particular site |
||
373 | * |
||
374 | * @param \ElggSite $site The site to add this user to. This used to be the |
||
375 | * the site guid (still supported by deprecated) |
||
376 | * @return bool |
||
377 | */ |
||
378 | View Code Duplication | public function addToSite($site) { |
|
386 | |||
387 | /** |
||
388 | * Remove this user from a particular site |
||
389 | * |
||
390 | * @param \ElggSite $site The site to remove the user from. Used to be site GUID |
||
391 | * |
||
392 | * @return bool |
||
393 | */ |
||
394 | public function removeFromSite($site) { |
||
402 | |||
403 | /** |
||
404 | * Adds a user as a friend |
||
405 | * |
||
406 | * @param int $friend_guid The GUID of the user to add |
||
407 | * @param bool $create_river_item Create the river item announcing this friendship |
||
408 | * |
||
409 | * @return bool |
||
410 | */ |
||
411 | public function addFriend($friend_guid, $create_river_item = false) { |
||
431 | |||
432 | /** |
||
433 | * Removes a user as a friend |
||
434 | * |
||
435 | * @param int $friend_guid The GUID of the user to remove |
||
436 | * |
||
437 | * @return bool |
||
438 | */ |
||
439 | public function removeFriend($friend_guid) { |
||
455 | |||
456 | /** |
||
457 | * Determines whether or not this user is a friend of the currently logged in user |
||
458 | * |
||
459 | * @return bool |
||
460 | */ |
||
461 | public function isFriend() { |
||
464 | |||
465 | /** |
||
466 | * Determines whether this user is friends with another user |
||
467 | * |
||
468 | * @param int $user_guid The GUID of the user to check against |
||
469 | * |
||
470 | * @return bool |
||
471 | */ |
||
472 | public function isFriendsWith($user_guid) { |
||
475 | |||
476 | /** |
||
477 | * Determines whether or not this user is another user's friend |
||
478 | * |
||
479 | * @param int $user_guid The GUID of the user to check against |
||
480 | * |
||
481 | * @return bool |
||
482 | */ |
||
483 | public function isFriendOf($user_guid) { |
||
486 | |||
487 | /** |
||
488 | * Gets this user's friends |
||
489 | * |
||
490 | * @param array $options Options array. See elgg_get_entities_from_relationship() |
||
491 | * for a list of options. 'relationship_guid' is set to |
||
492 | * this entity, relationship name to 'friend' and type to 'user'. |
||
493 | * @param int $limit The number of users to retrieve (deprecated) |
||
494 | * @param int $offset Indexing offset, if any (deprecated) |
||
495 | * |
||
496 | * @return array|false Array of \ElggUser, or false, depending on success |
||
497 | */ |
||
498 | View Code Duplication | public function getFriends($options = array(), $limit = 10, $offset = 0) { |
|
516 | |||
517 | /** |
||
518 | * Gets users who have made this user a friend |
||
519 | * |
||
520 | * @param array $options Options array. See elgg_get_entities_from_relationship() |
||
521 | * for a list of options. 'relationship_guid' is set to |
||
522 | * this entity, relationship name to 'friend', type to 'user' |
||
523 | * and inverse_relationship to true. |
||
524 | * @param int $limit The number of users to retrieve (deprecated) |
||
525 | * @param int $offset Indexing offset, if any (deprecated) |
||
526 | * |
||
527 | * @return array|false Array of \ElggUser, or false, depending on success |
||
528 | */ |
||
529 | View Code Duplication | public function getFriendsOf($options = array(), $limit = 10, $offset = 0) { |
|
548 | |||
549 | /** |
||
550 | * Lists the user's friends |
||
551 | * |
||
552 | * @param string $subtype Optionally, the user subtype (leave blank for all) |
||
553 | * @param int $limit The number of users to retrieve |
||
554 | * @param array $vars Display variables for the user view |
||
555 | * |
||
556 | * @return string Rendered list of friends |
||
557 | * @since 1.8.0 |
||
558 | * @deprecated 1.9 Use elgg_list_entities_from_relationship() |
||
559 | */ |
||
560 | public function listFriends($subtype = "", $limit = 10, array $vars = array()) { |
||
578 | |||
579 | /** |
||
580 | * Gets the user's groups |
||
581 | * |
||
582 | * @param array $options Options array. Used to be the subtype string. |
||
583 | * @param int $limit The number of groups to retrieve (deprecated) |
||
584 | * @param int $offset Indexing offset, if any (deprecated) |
||
585 | * |
||
586 | * @return array|false Array of \ElggGroup, or false, depending on success |
||
587 | */ |
||
588 | public function getGroups($options = "", $limit = 10, $offset = 0) { |
||
611 | |||
612 | /** |
||
613 | * Lists the user's groups |
||
614 | * |
||
615 | * @param string $subtype Optionally, the user subtype (leave blank for all) |
||
616 | * @param int $limit The number of users to retrieve |
||
617 | * @param int $offset Indexing offset, if any |
||
618 | * |
||
619 | * @return string |
||
620 | * @deprecated 1.9 Use elgg_list_entities_from_relationship() |
||
621 | */ |
||
622 | public function listGroups($subtype = "", $limit = 10, $offset = 0) { |
||
639 | |||
640 | /** |
||
641 | * Get an array of \ElggObject owned by this user. |
||
642 | * |
||
643 | * @param array $options Options array. See elgg_get_entities() for a list of options. |
||
644 | * 'type' is set to object and owner_guid to this entity. |
||
645 | * @param int $limit Number of results to return (deprecated) |
||
646 | * @param int $offset Any indexing offset (deprecated) |
||
647 | * |
||
648 | * @return array|false |
||
649 | */ |
||
650 | public function getObjects($options = array(), $limit = 10, $offset = 0) { |
||
666 | |||
667 | /** |
||
668 | * Get an array of \ElggObjects owned by this user's friends. |
||
669 | * |
||
670 | * @param array $options Options array. See elgg_get_entities_from_relationship() |
||
671 | * for a list of options. 'relationship_guid' is set to |
||
672 | * this entity, type to 'object', relationship name to 'friend' |
||
673 | * and relationship_join_on to 'container_guid'. |
||
674 | * @param int $limit Number of results to return (deprecated) |
||
675 | * @param int $offset Any indexing offset (deprecated) |
||
676 | * |
||
677 | * @return array|false |
||
678 | */ |
||
679 | public function getFriendsObjects($options = array(), $limit = 10, $offset = 0) { |
||
699 | |||
700 | /** |
||
701 | * Counts the number of \ElggObjects owned by this user |
||
702 | * |
||
703 | * @param string $subtype The subtypes of the objects, if any |
||
704 | * |
||
705 | * @return int The number of \ElggObjects |
||
706 | * @deprecated 1.9 Use elgg_get_entities() |
||
707 | */ |
||
708 | public function countObjects($subtype = "") { |
||
712 | |||
713 | /** |
||
714 | * Get the collections associated with a user. |
||
715 | * |
||
716 | * @param string $subtype Optionally, the subtype of result we want to limit to |
||
717 | * @param int $limit The number of results to return |
||
718 | * @param int $offset Any indexing offset |
||
719 | * |
||
720 | * @return array|false |
||
721 | */ |
||
722 | public function getCollections($subtype = "", $limit = 10, $offset = 0) { |
||
726 | |||
727 | /** |
||
728 | * Get a user's owner GUID |
||
729 | * |
||
730 | * Returns it's own GUID if the user is not owned. |
||
731 | * |
||
732 | * @return int |
||
733 | */ |
||
734 | public function getOwnerGUID() { |
||
741 | |||
742 | /** |
||
743 | * If a user's owner is blank, return its own GUID as the owner |
||
744 | * |
||
745 | * @return int User GUID |
||
746 | * @deprecated 1.8 Use getOwnerGUID() |
||
747 | */ |
||
748 | public function getOwner() { |
||
752 | |||
753 | /** |
||
754 | * {@inheritdoc} |
||
755 | */ |
||
756 | protected function prepareObject($object) { |
||
764 | |||
765 | // EXPORTABLE INTERFACE //////////////////////////////////////////////////////////// |
||
766 | |||
767 | /** |
||
768 | * Return an array of fields which can be exported. |
||
769 | * |
||
770 | * @return array |
||
771 | * @deprecated 1.9 Use toObject() |
||
772 | */ |
||
773 | public function getExportableValues() { |
||
780 | |||
781 | /** |
||
782 | * Can a user comment on this user? |
||
783 | * |
||
784 | * @see \ElggEntity::canComment() |
||
785 | * |
||
786 | * @param int $user_guid User guid (default is logged in user) |
||
787 | * @return bool |
||
788 | * @since 1.8.0 |
||
789 | */ |
||
790 | public function canComment($user_guid = 0) { |
||
797 | |||
798 | /** |
||
799 | * Set the necessary attributes to store a hash of the user's password. Also removes |
||
800 | * the legacy hash/salt values. |
||
801 | * |
||
802 | * @tip You must save() to persist the attributes |
||
803 | * |
||
804 | * @param string $password The password to be hashed |
||
805 | * @return void |
||
806 | * @since 1.10.0 |
||
807 | */ |
||
808 | public function setPassword($password) { |
||
813 | } |
||
814 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.