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 Properties 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 Properties, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
31 | Class Properties { |
||
32 | |||
33 | const THUMBNAIL_PREFIX = 'contact-thumbnail-'; |
||
34 | const THUMBNAIL_SIZE = 32; |
||
35 | |||
36 | private static $deleteindexstmt; |
||
37 | private static $updateindexstmt; |
||
38 | protected static $cardsTableName = '*PREFIX*contacts_cards'; |
||
39 | protected static $indexTableName = '*PREFIX*contacts_cards_properties'; |
||
40 | |||
41 | /** |
||
42 | * @brief language object for calendar app |
||
43 | * |
||
44 | * @var \OCP\IL10N |
||
45 | */ |
||
46 | public static $l10n; |
||
47 | |||
48 | /** |
||
49 | * Properties there can be more than one of. |
||
50 | * |
||
51 | * @var array |
||
52 | */ |
||
53 | public static $multiProperties = array('EMAIL', 'TEL', 'IMPP', 'ADR', 'URL', 'CLOUD'); |
||
54 | |||
55 | /** |
||
56 | * Properties to index. |
||
57 | * |
||
58 | * @var array |
||
59 | */ |
||
60 | public static $indexProperties = array( |
||
61 | 'BDAY', 'UID', 'N', 'FN', 'TITLE', 'ROLE', 'NOTE', 'NICKNAME', |
||
62 | 'ORG', 'CATEGORIES', 'EMAIL', 'TEL', 'IMPP', 'ADR', 'URL', 'GEO', 'CLOUD'); |
||
63 | |||
64 | /** |
||
65 | * Get options for IMPP properties |
||
66 | * @param string $im |
||
67 | * @return array of vcard prop => label |
||
68 | */ |
||
69 | 1 | public static function getIMOptions($im = null) { |
|
70 | 1 | $l10n = self::$l10n; |
|
71 | $ims = array( |
||
72 | 'jabber' => array( |
||
73 | 1 | 'displayname' => (string)$l10n->t('Jabber'), |
|
74 | 1 | 'xname' => 'X-JABBER', |
|
75 | 1 | 'protocol' => 'xmpp', |
|
76 | 1 | ), |
|
77 | 'sip' => array( |
||
78 | 1 | 'displayname' => (string)$l10n->t('Internet call'), |
|
79 | 1 | 'xname' => 'X-SIP', |
|
80 | 1 | 'protocol' => 'sip', |
|
81 | 1 | ), |
|
82 | 'aim' => array( |
||
83 | 1 | 'displayname' => (string)$l10n->t('AIM'), |
|
84 | 1 | 'xname' => 'X-AIM', |
|
85 | 1 | 'protocol' => 'aim', |
|
86 | 1 | ), |
|
87 | 'msn' => array( |
||
88 | 1 | 'displayname' => (string)$l10n->t('MSN'), |
|
89 | 1 | 'xname' => 'X-MSN', |
|
90 | 1 | 'protocol' => 'msn', |
|
91 | 1 | ), |
|
92 | 'twitter' => array( |
||
93 | 1 | 'displayname' => (string)$l10n->t('Twitter'), |
|
94 | 1 | 'xname' => 'X-TWITTER', |
|
95 | 1 | 'protocol' => 'twitter', |
|
96 | 1 | ), |
|
97 | 'googletalk' => array( |
||
98 | 1 | 'displayname' => (string)$l10n->t('GoogleTalk'), |
|
99 | 1 | 'xname' => null, |
|
100 | 1 | 'protocol' => 'xmpp', |
|
101 | 1 | ), |
|
102 | 'facebook' => array( |
||
103 | 1 | 'displayname' => (string)$l10n->t('Facebook'), |
|
104 | 1 | 'xname' => null, |
|
105 | 1 | 'protocol' => 'xmpp', |
|
106 | 1 | ), |
|
107 | 'xmpp' => array( |
||
108 | 1 | 'displayname' => (string)$l10n->t('XMPP'), |
|
109 | 1 | 'xname' => null, |
|
110 | 1 | 'protocol' => 'xmpp', |
|
111 | 1 | ), |
|
112 | 'icq' => array( |
||
113 | 1 | 'displayname' => (string)$l10n->t('ICQ'), |
|
114 | 1 | 'xname' => 'X-ICQ', |
|
115 | 1 | 'protocol' => 'icq', |
|
116 | 1 | ), |
|
117 | 'yahoo' => array( |
||
118 | 1 | 'displayname' => (string)$l10n->t('Yahoo'), |
|
119 | 1 | 'xname' => 'X-YAHOO', |
|
120 | 1 | 'protocol' => 'ymsgr', |
|
121 | 1 | ), |
|
122 | 'skype' => array( |
||
123 | 1 | 'displayname' => (string)$l10n->t('Skype'), |
|
124 | 1 | 'xname' => 'X-SKYPE', |
|
125 | 1 | 'protocol' => 'skype', |
|
126 | 1 | ), |
|
127 | 'qq' => array( |
||
128 | 1 | 'displayname' => (string)$l10n->t('QQ'), |
|
129 | 1 | 'xname' => 'X-SKYPE', |
|
130 | 1 | 'protocol' => 'x-apple', |
|
131 | 1 | ), |
|
132 | 'gadugadu' => array( |
||
133 | 1 | 'displayname' => (string)$l10n->t('GaduGadu'), |
|
134 | 1 | 'xname' => 'X-SKYPE', |
|
135 | 1 | 'protocol' => 'x-apple', |
|
136 | 1 | ), |
|
137 | 'owncloud-handle' => array( |
||
138 | 1 | 'displayname' => (string)$l10n->t('ownCloud'), |
|
139 | 1 | 'xname' => null, |
|
140 | 'protocol' => 'x-owncloud-handle' |
||
141 | 1 | ), |
|
142 | 1 | ); |
|
143 | 1 | if(is_null($im)) { |
|
144 | 1 | return $ims; |
|
145 | } else { |
||
146 | $ims['ymsgr'] = $ims['yahoo']; |
||
147 | $ims['gtalk'] = $ims['googletalk']; |
||
148 | return isset($ims[$im]) ? $ims[$im] : null; |
||
149 | } |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * Get standard set of TYPE values for different properties. |
||
154 | * |
||
155 | * @param string $prop |
||
156 | * @return array Type values for property $prop |
||
157 | */ |
||
158 | 1 | public static function getTypesForProperty($prop) { |
|
159 | 1 | $l = self::$l10n; |
|
160 | switch($prop) { |
||
161 | 1 | case 'LABEL': |
|
162 | 1 | case 'ADR': |
|
163 | 1 | View Code Duplication | case 'IMPP': |
164 | return array( |
||
165 | 1 | 'HOME' => (string)$l->t('Home'), |
|
166 | 1 | 'WORK' => (string)$l->t('Work'), |
|
167 | 1 | 'OTHER' => (string)$l->t('Other'), |
|
168 | 1 | ); |
|
169 | 1 | case 'TEL': |
|
170 | return array( |
||
171 | 1 | 'HOME' => (string)$l->t('Home'), |
|
172 | 1 | 'CELL' => (string)$l->t('Mobile'), |
|
173 | 1 | 'WORK' => (string)$l->t('Work'), |
|
174 | 1 | 'TEXT' => (string)$l->t('Text'), |
|
175 | 1 | 'VOICE' => (string)$l->t('Voice'), |
|
176 | 1 | 'MSG' => (string)$l->t('Message'), |
|
177 | 1 | 'FAX' => (string)$l->t('Fax'), |
|
178 | 1 | 'VIDEO' => (string)$l->t('Video'), |
|
179 | 1 | 'PAGER' => (string)$l->t('Pager'), |
|
180 | 1 | 'OTHER' => (string)$l->t('Other'), |
|
181 | 1 | ); |
|
182 | 1 | View Code Duplication | case 'EMAIL': |
183 | return array( |
||
184 | 1 | 'HOME' => (string)$l->t('Home'), |
|
185 | 1 | 'WORK' => (string)$l->t('Work'), |
|
186 | 1 | 'INTERNET' => (string)$l->t('Internet'), |
|
187 | 1 | 'OTHER' => (string)$l->t('Other'), |
|
188 | 1 | ); |
|
189 | 1 | View Code Duplication | case 'CLOUD': |
190 | return array( |
||
191 | 1 | 'HOME' => (string)$l->t('Home'), |
|
192 | 1 | 'WORK' => (string)$l->t('Work'), |
|
193 | 1 | 'OTHER' => (string)$l->t('Other'), |
|
194 | 1 | ); |
|
195 | } |
||
196 | } |
||
197 | |||
198 | /** |
||
199 | * @brief returns the default categories of ownCloud |
||
200 | * @return string[] $categories |
||
201 | */ |
||
202 | public static function getDefaultCategories() { |
||
203 | $l10n = self::$l10n; |
||
204 | return array( |
||
205 | (string)$l10n->t('Friends'), |
||
206 | (string)$l10n->t('Family'), |
||
207 | (string)$l10n->t('Work'), |
||
208 | (string)$l10n->t('Other'), |
||
209 | ); |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * @return string |
||
214 | */ |
||
215 | 1 | public static function generateUID() { |
|
218 | |||
219 | /** |
||
220 | * Purge indexed properties. |
||
221 | * |
||
222 | * @param string[] $ids |
||
223 | */ |
||
224 | 2 | public static function purgeIndexes($ids) { |
|
245 | |||
246 | /** |
||
247 | * Update the contact property index. |
||
248 | * |
||
249 | * If vcard is null the properties for that contact will be purged. |
||
250 | * If it is a valid object the old properties will first be purged |
||
251 | * and the current properties indexed. |
||
252 | * |
||
253 | * @param string $contactId |
||
254 | * @param VCard|null $vCard |
||
255 | * @param string|null $owner |
||
256 | */ |
||
257 | 2 | public static function updateIndex($contactId, $vCard = null, $owner = null) { |
|
304 | |||
305 | public static function cacheThumbnail($backendName, $addressBookId, $contactId, |
||
374 | |||
375 | } |
||
376 |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.