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 PMF_Installer 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 PMF_Installer, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
36 | class PMF_Installer |
||
37 | { |
||
38 | /** |
||
39 | * PMF_System object |
||
40 | * |
||
41 | * @var PMF_System |
||
42 | */ |
||
43 | protected $_system; |
||
44 | |||
45 | /** |
||
46 | * Array with user rights |
||
47 | * @var array |
||
48 | */ |
||
49 | protected $_mainRights = array( |
||
50 | //1 => "adduser", |
||
|
|||
51 | array( |
||
52 | 'name' => 'adduser', |
||
53 | 'description' => 'Right to add user accounts' |
||
54 | ), |
||
55 | //2 => "edituser", |
||
56 | array( |
||
57 | 'name' => 'edituser', |
||
58 | 'description' => 'Right to edit user accounts' |
||
59 | ), |
||
60 | //3 => "deluser", |
||
61 | array( |
||
62 | 'name' => 'deluser', |
||
63 | 'description' => 'Right to delete user accounts' |
||
64 | ), |
||
65 | //4 => "addbt", |
||
66 | array( |
||
67 | 'name' => 'addbt', |
||
68 | 'description' => 'Right to add faq entries' |
||
69 | ), |
||
70 | //5 => "editbt", |
||
71 | array( |
||
72 | 'name' => 'editbt', |
||
73 | 'description' => 'Right to edit faq entries' |
||
74 | ), |
||
75 | //6 => "delbt", |
||
76 | array( |
||
77 | 'name' => 'delbt', |
||
78 | 'description' => 'Right to delete faq entries' |
||
79 | ), |
||
80 | //7 => "viewlog", |
||
81 | array( |
||
82 | 'name' => 'viewlog', |
||
83 | 'description' => 'Right to view logfiles' |
||
84 | ), |
||
85 | //8 => "adminlog", |
||
86 | array( |
||
87 | 'name' => 'adminlog', |
||
88 | 'description' => 'Right to view admin log' |
||
89 | ), |
||
90 | //9 => "delcomment", |
||
91 | array( |
||
92 | 'name' => 'delcomment', |
||
93 | 'description' => 'Right to delete comments' |
||
94 | ), |
||
95 | //10 => "addnews", |
||
96 | array( |
||
97 | 'name' => 'addnews', |
||
98 | 'description' => 'Right to add news' |
||
99 | ), |
||
100 | //11 => "editnews", |
||
101 | array( |
||
102 | 'name' => 'editnews', |
||
103 | 'description' => 'Right to edit news' |
||
104 | ), |
||
105 | //12 => "delnews", |
||
106 | array( |
||
107 | 'name' => 'delnews', |
||
108 | 'description' => 'Right to delete news' |
||
109 | ), |
||
110 | //13 => "addcateg", |
||
111 | array( |
||
112 | 'name' => 'addcateg', |
||
113 | 'description' => 'Right to add categories' |
||
114 | ), |
||
115 | //14 => "editcateg", |
||
116 | array( |
||
117 | 'name' => 'editcateg', |
||
118 | 'description' => 'Right to edit categories' |
||
119 | ), |
||
120 | //15 => "delcateg", |
||
121 | array( |
||
122 | 'name' => 'delcateg', |
||
123 | 'description' => 'Right to delete categories' |
||
124 | ), |
||
125 | //16 => "passwd", |
||
126 | array( |
||
127 | 'name' => 'passwd', |
||
128 | 'description' => 'Right to change passwords' |
||
129 | ), |
||
130 | //17 => "editconfig", |
||
131 | array( |
||
132 | 'name' => 'editconfig', |
||
133 | 'description' => 'Right to edit configuration' |
||
134 | ), |
||
135 | //18 => "addatt", // Duplicate, removed with 2.7.3 |
||
136 | //array( |
||
137 | // 'name' => 'addatt', |
||
138 | // 'description' => 'Right to add attachments' |
||
139 | //), |
||
140 | //19 => "backup delatt", // Duplicate, removed with 2.7.3 |
||
141 | //array( |
||
142 | // 'name' => 'delatt', |
||
143 | // 'description' => 'Right to delete attachments' |
||
144 | //), |
||
145 | //20 => "backup", |
||
146 | array( |
||
147 | 'name' => 'backup', |
||
148 | 'description' => 'Right to save backups' |
||
149 | ), |
||
150 | //21 => "restore", |
||
151 | array( |
||
152 | 'name' => 'restore', |
||
153 | 'description' => 'Right to load backups' |
||
154 | ), |
||
155 | //22 => "delquestion", |
||
156 | array( |
||
157 | 'name' => 'delquestion', |
||
158 | 'description' => 'Right to delete questions' |
||
159 | ), |
||
160 | //23 => 'addglossary', |
||
161 | array( |
||
162 | 'name' => 'addglossary', |
||
163 | 'description' => 'Right to add glossary entries' |
||
164 | ), |
||
165 | //24 => 'editglossary', |
||
166 | array( |
||
167 | 'name' => 'editglossary', |
||
168 | 'description' => 'Right to edit glossary entries' |
||
169 | ), |
||
170 | //25 => 'delglossary' |
||
171 | array( |
||
172 | 'name' => 'delglossary', |
||
173 | 'description' => 'Right to delete glossary entries' |
||
174 | ), |
||
175 | //26 => 'changebtrevs' |
||
176 | array( |
||
177 | 'name' => 'changebtrevs', |
||
178 | 'description' => 'Right to edit revisions' |
||
179 | ), |
||
180 | //27 => "addgroup", |
||
181 | array( |
||
182 | 'name' => 'addgroup', |
||
183 | 'description' => 'Right to add group accounts' |
||
184 | ), |
||
185 | //28 => "editgroup", |
||
186 | array( |
||
187 | 'name' => 'editgroup', |
||
188 | 'description' => 'Right to edit group accounts' |
||
189 | ), |
||
190 | //29 => "delgroup", |
||
191 | array( |
||
192 | 'name' => 'delgroup', |
||
193 | 'description' => 'Right to delete group accounts' |
||
194 | ), |
||
195 | //30 => "addtranslation", |
||
196 | array( |
||
197 | 'name' => 'addtranslation', |
||
198 | 'description' => 'Right to add translation' |
||
199 | ), |
||
200 | //31 => "edittranslation", |
||
201 | array( |
||
202 | 'name' => 'edittranslation', |
||
203 | 'description' => 'Right to edit translations' |
||
204 | ), |
||
205 | //32 => "deltranslation", |
||
206 | array( |
||
207 | 'name' => 'deltranslation', |
||
208 | 'description' => 'Right to delete translations' |
||
209 | ), |
||
210 | // 33 => 'approverec' |
||
211 | array( |
||
212 | 'name' => 'approverec', |
||
213 | 'description' => 'Right to approve records' |
||
214 | ), |
||
215 | // 34 => 'addattachment' |
||
216 | array( |
||
217 | 'name' => 'addattachment', |
||
218 | 'description' => 'Right to add attachments' |
||
219 | ), |
||
220 | // 35 => 'editattachment' |
||
221 | array( |
||
222 | 'name' => 'editattachment', |
||
223 | 'description' => 'Right to edit attachments' |
||
224 | ), |
||
225 | // 36 => 'delattachment' |
||
226 | array( |
||
227 | 'name' => 'delattachment', |
||
228 | 'description' => 'Right to delete attachments' |
||
229 | ), |
||
230 | // 37 => 'dlattachment' |
||
231 | array( |
||
232 | 'name' => 'dlattachment', |
||
233 | 'description' => 'Right to download attachments' |
||
234 | ), |
||
235 | // 38 => 'dlattachment' |
||
236 | array( |
||
237 | 'name' => 'reports', |
||
238 | 'description' => 'Right to generate reports' |
||
239 | ), |
||
240 | // 39 => 'addfaq' |
||
241 | array( |
||
242 | 'name' => 'addfaq', |
||
243 | 'description' => 'Right to add FAQs in frontend' |
||
244 | ), |
||
245 | // 40 => 'addquestion' |
||
246 | array( |
||
247 | 'name' => 'addquestion', |
||
248 | 'description' => 'Right to add questions in frontend' |
||
249 | ), |
||
250 | // 41 => 'addcomment' |
||
251 | array( |
||
252 | 'name' => 'addcomment', |
||
253 | 'description' => 'Right to add comments in frontend' |
||
254 | ), |
||
255 | // 42 => 'editinstances' |
||
256 | array( |
||
257 | 'name' => 'editinstances', |
||
258 | 'description' => 'Right to edit multi-site instances' |
||
259 | ), |
||
260 | // 43 => 'addinstances' |
||
261 | array( |
||
262 | 'name' => 'addinstances', |
||
263 | 'description' => 'Right to add multi-site instances' |
||
264 | ), |
||
265 | // 44 => 'delinstances' |
||
266 | array( |
||
267 | 'name' => 'delinstances', |
||
268 | 'description' => 'Right to delete multi-site instances' |
||
269 | ), |
||
270 | // 45 => 'export' |
||
271 | array( |
||
272 | 'name' => 'export', |
||
273 | 'description' => 'Right to export the complete FAQ' |
||
274 | ), |
||
275 | ); |
||
276 | |||
277 | /** |
||
278 | * Configuration array |
||
279 | * |
||
280 | * @var array |
||
281 | */ |
||
282 | protected $_mainConfig = array( |
||
283 | 'main.currentVersion' => null, |
||
284 | 'main.currentApiVersion' => null, |
||
285 | 'main.language' => '__PHPMYFAQ_LANGUAGE__', |
||
286 | 'main.languageDetection' => 'true', |
||
287 | 'main.phpMyFAQToken' => null, |
||
288 | 'main.referenceURL' => '__PHPMYFAQ_REFERENCE_URL__', |
||
289 | 'main.administrationMail' => '[email protected]', |
||
290 | 'main.contactInformations' => '', |
||
291 | 'main.enableAdminLog' => 'true', |
||
292 | 'main.enableRewriteRules' => 'false', |
||
293 | 'main.enableUserTracking' => 'true', |
||
294 | 'main.metaDescription' => 'phpMyFAQ should be the answer for all questions in life', |
||
295 | 'main.metaKeywords' => '', |
||
296 | 'main.metaPublisher' => '__PHPMYFAQ_PUBLISHER__', |
||
297 | 'main.send2friendText' => '', |
||
298 | 'main.titleFAQ' => 'phpMyFAQ Codename Poseidon', |
||
299 | 'main.urlValidateInterval' => '86400', |
||
300 | 'main.enableWysiwygEditor' => 'true', |
||
301 | 'main.enableWysiwygEditorFrontend' => 'false', |
||
302 | 'main.templateSet' => 'default', |
||
303 | 'main.optionalMailAddress' => 'false', |
||
304 | 'main.dateFormat' => 'Y-m-d H:i', |
||
305 | 'main.maintenanceMode' => 'false', |
||
306 | 'main.enableGravatarSupport' => 'false', |
||
307 | 'main.enableRssFeeds' => 'true', |
||
308 | |||
309 | 'records.numberOfRecordsPerPage' => '10', |
||
310 | 'records.numberOfShownNewsEntries' => '3', |
||
311 | 'records.defaultActivation' => 'false', |
||
312 | 'records.defaultAllowComments' => 'false', |
||
313 | 'records.enableVisibilityQuestions' => 'false', |
||
314 | 'records.numberOfRelatedArticles' => '5', |
||
315 | 'records.orderby' => 'id', |
||
316 | 'records.sortby' => 'DESC', |
||
317 | 'records.orderingPopularFaqs' => 'visits', |
||
318 | 'records.disableAttachments' => 'true', |
||
319 | 'records.maxAttachmentSize' => '100000', |
||
320 | 'records.attachmentsPath' => 'attachments', |
||
321 | 'records.attachmentsStorageType' => '0', |
||
322 | 'records.enableAttachmentEncryption' => 'false', |
||
323 | 'records.defaultAttachmentEncKey' => '', |
||
324 | 'records.enableCloseQuestion' => 'false', |
||
325 | 'records.enableDeleteQuestion' => 'false', |
||
326 | 'records.autosaveActive' => 'false', |
||
327 | 'records.autosaveSecs' => '180', |
||
328 | 'records.randomSort' => 'false', |
||
329 | 'records.allowCommentsForGuests' => 'true', |
||
330 | 'records.allowQuestionsForGuests' => 'true', |
||
331 | 'records.allowNewFaqsForGuests' => 'true', |
||
332 | 'records.hideEmptyCategories' => 'false', |
||
333 | |||
334 | 'search.useAjaxSearchOnStartpage' => 'false', |
||
335 | 'search.numberSearchTerms' => '10', |
||
336 | 'search.relevance' => 'thema,content,keywords', |
||
337 | 'search.enableRelevance' => 'false', |
||
338 | 'search.enableHighlighting' => 'true', |
||
339 | 'search.searchForSolutionId' => 'true', |
||
340 | |||
341 | 'security.permLevel' => 'basic', |
||
342 | 'security.ipCheck' => 'false', |
||
343 | 'security.enableLoginOnly' => 'false', |
||
344 | 'security.ldapSupport' => 'false', |
||
345 | 'security.bannedIPs' => '', |
||
346 | 'security.ssoSupport' => 'false', |
||
347 | 'security.ssoLogoutRedirect' => '', |
||
348 | 'security.useSslForLogins' => 'false', |
||
349 | 'security.useSslOnly' => 'false', |
||
350 | 'security.forcePasswordUpdate' => 'false', |
||
351 | |||
352 | 'spam.checkBannedWords' => 'true', |
||
353 | 'spam.enableCaptchaCode' => null, |
||
354 | 'spam.enableSafeEmail' => 'true', |
||
355 | |||
356 | 'socialnetworks.enableTwitterSupport' => 'false', |
||
357 | 'socialnetworks.twitterConsumerKey' => '', |
||
358 | 'socialnetworks.twitterConsumerSecret' => '', |
||
359 | 'socialnetworks.twitterAccessTokenKey' => '', |
||
360 | 'socialnetworks.twitterAccessTokenSecret' => '', |
||
361 | 'socialnetworks.enableFacebookSupport' => 'false', |
||
362 | 'socialnetworks.disableAll' => 'false' |
||
363 | ); |
||
364 | |||
365 | /** |
||
366 | * Constructor |
||
367 | * |
||
368 | * @return PMF_Installer |
||
369 | */ |
||
370 | public function __construct() |
||
371 | { |
||
372 | $this->_system = new PMF_System(); |
||
373 | $dynMainConfig = array( |
||
374 | 'main.currentVersion' => PMF_System::getVersion(), |
||
375 | 'main.currentApiVersion' => PMF_System::getApiVersion(), |
||
376 | 'main.phpMyFAQToken' => md5(uniqid(rand())), |
||
377 | 'spam.enableCaptchaCode' => (extension_loaded('gd') ? 'true' : 'false'), |
||
378 | ); |
||
379 | $this->_mainConfig = array_merge($this->_mainConfig, $dynMainConfig); |
||
380 | } |
||
381 | |||
382 | /** |
||
383 | * Check absolutely necessary stuff and die |
||
384 | * |
||
385 | * @return array |
||
386 | */ |
||
387 | public function checkBasicStuff() |
||
438 | |||
439 | /** |
||
440 | * Checks for the minimum PHP requirement and if the database credentials file is readable |
||
441 | * |
||
442 | * @return void |
||
443 | */ |
||
444 | public function checkPreUpgrade() |
||
470 | |||
471 | /** |
||
472 | * Checks the minimum required PHP version, defined in PMF_System |
||
473 | * |
||
474 | * @return bool |
||
475 | */ |
||
476 | public function checkMinimumPhpVersion() |
||
477 | { |
||
478 | if (version_compare(PHP_VERSION, PMF_System::VERSION_MINIMUM_PHP, '<')) { |
||
479 | return false; |
||
480 | } |
||
481 | return true; |
||
482 | } |
||
483 | |||
484 | /** |
||
485 | * Checks if the file permissions are okay |
||
486 | * |
||
487 | * @return string |
||
488 | */ |
||
489 | public function checkFilesystemPermissions() |
||
516 | |||
517 | /** |
||
518 | * Checks some non critical settings and print some hints |
||
519 | * |
||
520 | * @return array |
||
521 | */ |
||
522 | public function checkNoncriticalSettings() |
||
549 | |||
550 | /** |
||
551 | * Checks if we can store data via sessions. If not, e.g. an user can't |
||
552 | * login into the admin section |
||
553 | * |
||
554 | * @return bool |
||
555 | */ |
||
556 | public function checkSessionSettings() |
||
557 | { |
||
558 | return true; |
||
559 | } |
||
560 | |||
561 | /** |
||
562 | * Starts the installation |
||
563 | * |
||
564 | * @param array $DB |
||
565 | */ |
||
566 | public function startInstall(Array $DB = null) |
||
838 | |||
839 | /** |
||
840 | * Cleanup all files after an installation |
||
841 | * |
||
842 | * @return void |
||
843 | */ |
||
844 | public function cleanUpFiles() |
||
859 | |||
860 | /** |
||
861 | * Renders the <option> list with supported languages |
||
862 | * |
||
863 | * @param array $languageCodes |
||
864 | * |
||
865 | * @return string |
||
866 | */ |
||
867 | public function renderLanguageOptions(Array $languageCodes) |
||
889 | } |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.