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 AccessCollections 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 AccessCollections, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
14 | class AccessCollections { |
||
15 | /** |
||
16 | * @var int |
||
17 | */ |
||
18 | private $site_guid; |
||
19 | |||
20 | /** |
||
21 | * Constructor |
||
22 | * |
||
23 | * @param int $site_guid The GUID of the default Elgg site |
||
24 | */ |
||
25 | 1 | public function __construct($site_guid) { |
|
28 | |||
29 | /** |
||
30 | * Return a string of access_ids for $user_guid appropriate for inserting into an SQL IN clause. |
||
31 | * |
||
32 | * @uses get_access_array |
||
33 | * |
||
34 | * @see get_access_array() |
||
35 | * |
||
36 | * @param int $user_guid User ID; defaults to currently logged in user |
||
37 | * @param int $site_guid Site ID; defaults to current site |
||
38 | * @param bool $flush If set to true, will refresh the access list from the |
||
39 | * database rather than using this function's cache. |
||
40 | * |
||
41 | * @return string A list of access collections suitable for using in an SQL call |
||
42 | * @access private |
||
43 | */ |
||
44 | function getAccessList($user_guid = 0, $site_guid = 0, $flush = false) { |
||
77 | |||
78 | /** |
||
79 | * Returns an array of access IDs a user is permitted to see. |
||
80 | * |
||
81 | * Can be overridden with the 'access:collections:read', 'user' plugin hook. |
||
82 | * @warning A callback for that plugin hook needs to either not retrieve data |
||
83 | * from the database that would use the access system (triggering the plugin again) |
||
84 | * or ignore the second call. Otherwise, an infinite loop will be created. |
||
85 | * |
||
86 | * This returns a list of all the collection ids a user owns or belongs |
||
87 | * to plus public and logged in access levels. If the user is an admin, it includes |
||
88 | * the private access level. |
||
89 | * |
||
90 | * @internal this is only used in core for creating the SQL where clause when |
||
91 | * retrieving content from the database. The friends access level is handled by |
||
92 | * _elgg_get_access_where_sql(). |
||
93 | * |
||
94 | * @see get_write_access_array() for the access levels that a user can write to. |
||
95 | * |
||
96 | * @param int $user_guid User ID; defaults to currently logged in user |
||
97 | * @param int $site_guid Site ID; defaults to current site |
||
98 | * @param bool $flush If set to true, will refresh the access ids from the |
||
99 | * database rather than using this function's cache. |
||
100 | * |
||
101 | * @return array An array of access collections ids |
||
102 | */ |
||
103 | function getAccessArray($user_guid = 0, $site_guid = 0, $flush = false) { |
||
185 | |||
186 | /** |
||
187 | * Returns the SQL where clause for enforcing read access to data. |
||
188 | * |
||
189 | * Note that if this code is executed in privileged mode it will return (1=1). |
||
190 | * |
||
191 | * Otherwise it returns a where clause to retrieve the data that a user has |
||
192 | * permission to read. |
||
193 | * |
||
194 | * Plugin authors can hook into the 'get_sql', 'access' plugin hook to modify, |
||
195 | * remove, or add to the where clauses. The plugin hook will pass an array with the current |
||
196 | * ors and ands to the function in the form: |
||
197 | * array( |
||
198 | * 'ors' => array(), |
||
199 | * 'ands' => array() |
||
200 | * ) |
||
201 | * |
||
202 | * The results will be combined into an SQL where clause in the form: |
||
203 | * ((or1 OR or2 OR orN) AND (and1 AND and2 AND andN)) |
||
204 | * |
||
205 | * @param array $options Array in format: |
||
206 | * |
||
207 | * table_alias => STR Optional table alias. This is based on the select and join clauses. |
||
208 | * Default is 'e'. |
||
209 | * |
||
210 | * user_guid => INT Optional GUID for the user that we are retrieving data for. |
||
211 | * Defaults to the logged in user. |
||
212 | * |
||
213 | * use_enabled_clause => BOOL Optional. Should we append the enabled clause? The default |
||
214 | * is set by access_show_hidden_entities(). |
||
215 | * |
||
216 | * access_column => STR Optional access column name. Default is 'access_id'. |
||
217 | * |
||
218 | * owner_guid_column => STR Optional owner_guid column. Default is 'owner_guid'. |
||
219 | * |
||
220 | * guid_column => STR Optional guid_column. Default is 'guid'. |
||
221 | * |
||
222 | * @return string |
||
223 | * @access private |
||
224 | */ |
||
225 | function getWhereSql(array $options = array()) { |
||
299 | |||
300 | /** |
||
301 | * Can a user access an entity. |
||
302 | * |
||
303 | * @warning If a logged in user doesn't have access to an entity, the |
||
304 | * core engine will not load that entity. |
||
305 | * |
||
306 | * @tip This is mostly useful for checking if a user other than the logged in |
||
307 | * user has access to an entity that is currently loaded. |
||
308 | * |
||
309 | * @todo This function would be much more useful if we could pass the guid of the |
||
310 | * entity to test access for. We need to be able to tell whether the entity exists |
||
311 | * and whether the user has access to the entity. |
||
312 | * |
||
313 | * @param \ElggEntity $entity The entity to check access for. |
||
314 | * @param \ElggUser $user Optionally user to check access for. Defaults to |
||
315 | * logged in user (which is a useless default). |
||
316 | * |
||
317 | * @return bool |
||
318 | */ |
||
319 | function hasAccessToEntity($entity, $user = null) { |
||
347 | |||
348 | /** |
||
349 | * Returns an array of access permissions that the user is allowed to save content with. |
||
350 | * Permissions returned are of the form (id => 'name'). |
||
351 | * |
||
352 | * Example return value in English: |
||
353 | * array( |
||
354 | * 0 => 'Private', |
||
355 | * -2 => 'Friends', |
||
356 | * 1 => 'Logged in users', |
||
357 | * 2 => 'Public', |
||
358 | * 34 => 'My favorite friends', |
||
359 | * ); |
||
360 | * |
||
361 | * Plugin hook of 'access:collections:write', 'user' |
||
362 | * |
||
363 | * @warning this only returns access collections that the user owns plus the |
||
364 | * standard access levels. It does not return access collections that the user |
||
365 | * belongs to such as the access collection for a group. |
||
366 | * |
||
367 | * @param int $user_guid The user's GUID. |
||
368 | * @param int $site_guid The current site. |
||
369 | * @param bool $flush If this is set to true, this will ignore a cached access array |
||
370 | * @param array $input_params Some parameters passed into an input/access view |
||
371 | * |
||
372 | * @return array List of access permissions |
||
373 | */ |
||
374 | function getWriteAccessArray($user_guid = 0, $site_guid = 0, $flush = false, array $input_params = array()) { |
||
425 | |||
426 | /** |
||
427 | * Can the user change this access collection? |
||
428 | * |
||
429 | * Use the plugin hook of 'access:collections:write', 'user' to change this. |
||
430 | * @see get_write_access_array() for details on the hook. |
||
431 | * |
||
432 | * Respects access control disabling for admin users and {@link elgg_set_ignore_access()} |
||
433 | * |
||
434 | * @see get_write_access_array() |
||
435 | * |
||
436 | * @param int $collection_id The collection id |
||
437 | * @param mixed $user_guid The user GUID to check for. Defaults to logged in user. |
||
438 | * @return bool |
||
439 | */ |
||
440 | function canEdit($collection_id, $user_guid = null) { |
||
462 | |||
463 | /** |
||
464 | * Creates a new access collection. |
||
465 | * |
||
466 | * Access colletions allow plugins and users to create granular access |
||
467 | * for entities. |
||
468 | * |
||
469 | * Triggers plugin hook 'access:collections:addcollection', 'collection' |
||
470 | * |
||
471 | * @internal Access collections are stored in the access_collections table. |
||
472 | * Memberships to collections are in access_collections_membership. |
||
473 | * |
||
474 | * @param string $name The name of the collection. |
||
475 | * @param int $owner_guid The GUID of the owner (default: currently logged in user). |
||
476 | * @param int $site_guid The GUID of the site (default: current site). |
||
477 | * |
||
478 | * @return int|false The collection ID if successful and false on failure. |
||
479 | */ |
||
480 | function create($name, $owner_guid = 0, $site_guid = 0) { |
||
517 | |||
518 | /** |
||
519 | * Updates the membership in an access collection. |
||
520 | * |
||
521 | * @warning Expects a full list of all members that should |
||
522 | * be part of the access collection |
||
523 | * |
||
524 | * @note This will run all hooks associated with adding or removing |
||
525 | * members to access collections. |
||
526 | * |
||
527 | * @param int $collection_id The ID of the collection. |
||
528 | * @param array $members Array of member GUIDs |
||
529 | * |
||
530 | * @return bool |
||
531 | */ |
||
532 | function update($collection_id, $members) { |
||
558 | |||
559 | /** |
||
560 | * Deletes a specified access collection and its membership. |
||
561 | * |
||
562 | * @param int $collection_id The collection ID |
||
563 | * |
||
564 | * @return bool |
||
565 | */ |
||
566 | function delete($collection_id) { |
||
588 | |||
589 | /** |
||
590 | * Get a specified access collection |
||
591 | * |
||
592 | * @note This doesn't return the members of an access collection, |
||
593 | * just the database row of the actual collection. |
||
594 | * |
||
595 | * @see get_members_of_access_collection() |
||
596 | * |
||
597 | * @param int $collection_id The collection ID |
||
598 | * |
||
599 | * @return object|false |
||
600 | */ |
||
601 | function get($collection_id) { |
||
613 | |||
614 | /** |
||
615 | * Adds a user to an access collection. |
||
616 | * |
||
617 | * Triggers the 'access:collections:add_user', 'collection' plugin hook. |
||
618 | * |
||
619 | * @param int $user_guid The GUID of the user to add |
||
620 | * @param int $collection_id The ID of the collection to add them to |
||
621 | * |
||
622 | * @return bool |
||
623 | */ |
||
624 | function addUser($user_guid, $collection_id) { |
||
656 | |||
657 | /** |
||
658 | * Removes a user from an access collection. |
||
659 | * |
||
660 | * Triggers the 'access:collections:remove_user', 'collection' plugin hook. |
||
661 | * |
||
662 | * @param int $user_guid The user GUID |
||
663 | * @param int $collection_id The access collection ID |
||
664 | * |
||
665 | * @return bool |
||
666 | */ |
||
667 | function removeUser($user_guid, $collection_id) { |
||
696 | |||
697 | /** |
||
698 | * Returns an array of database row objects of the access collections owned by $owner_guid. |
||
699 | * |
||
700 | * @param int $owner_guid The entity guid |
||
701 | * @param int $site_guid The GUID of the site (default: current site). |
||
702 | * |
||
703 | * @return array|false |
||
704 | */ |
||
705 | View Code Duplication | function getEntityCollections($owner_guid, $site_guid = 0) { |
|
725 | |||
726 | /** |
||
727 | * Get all of members of an access collection |
||
728 | * |
||
729 | * @param int $collection_id The collection's ID |
||
730 | * @param bool $guids_only If set to true, will only return the members' GUIDs (default: false) |
||
731 | * |
||
732 | * @return ElggUser[]|int[]|false guids or entities if successful, false if not |
||
733 | */ |
||
734 | function getMembers($collection_id, $guids_only = false) { |
||
760 | |||
761 | /** |
||
762 | * Return an array of database row objects of the access collections $entity_guid is a member of. |
||
763 | * |
||
764 | * @param int $member_guid The entity guid |
||
765 | * @param int $site_guid The GUID of the site (default: current site). |
||
766 | * |
||
767 | * @return array|false |
||
768 | */ |
||
769 | View Code Duplication | function getCollectionsByMember($member_guid, $site_guid = 0) { |
|
790 | |||
791 | /** |
||
792 | * Return the name of an ACCESS_* constant or an access collection, |
||
793 | * but only if the logged in user owns the access collection or is an admin. |
||
794 | * Ownership requirement prevents us from exposing names of access collections |
||
795 | * that current user has been added to by other members and may contain |
||
796 | * sensitive classification of the current user (e.g. close friends vs acquaintances). |
||
797 | * |
||
798 | * Returns a string in the language of the user for global access levels, e.g.'Public, 'Friends', 'Logged in', 'Private'; |
||
799 | * or a name of the owned access collection, e.g. 'My work colleagues'; |
||
800 | * or a name of the group or other access collection, e.g. 'Group: Elgg technical support'; |
||
801 | * or 'Limited' if the user access is restricted to read-only, e.g. a friends collection the user was added to |
||
802 | * |
||
803 | * @param int $entity_access_id The entity's access id |
||
804 | * |
||
805 | * @return string |
||
806 | * @since 1.11 |
||
807 | */ |
||
808 | function getReadableAccessLevel($entity_access_id) { |
||
845 | } |
||
846 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.