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 CommentsExtension 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 CommentsExtension, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
8 | class CommentsExtension extends DataExtension |
||
9 | { |
||
10 | /** |
||
11 | * Default configuration values |
||
12 | * |
||
13 | * enabled: Allows commenting to be disabled even if the extension is present |
||
14 | * enabled_cms: Allows commenting to be enabled or disabled via the CMS |
||
15 | * require_login: Boolean, whether a user needs to login (required for required_permission) |
||
16 | * require_login_cms: Allows require_login to be set via the CMS |
||
17 | * required_permission: Permission (or array of permissions) required to comment |
||
18 | * include_js: Enhance operation by ajax behaviour on moderation links (required for use_preview) |
||
19 | * use_gravatar: Set to true to show gravatar icons |
||
20 | * gravatar_default: Theme for 'not found' gravatar {@see http://gravatar.com/site/implement/images} |
||
21 | * gravatar_rating: Gravatar rating (same as the standard default) |
||
22 | * show_comments_when_disabled: Show older comments when commenting has been disabled. |
||
23 | * order_comments_by: Default sort order. |
||
24 | * order_replies_by: Sort order for replies. |
||
25 | * comments_holder_id: ID for the comments holder |
||
26 | * comment_permalink_prefix: ID prefix for each comment |
||
27 | * require_moderation: Require moderation for all comments |
||
28 | * require_moderation_cms: Ignore other comment moderation config settings and set via CMS |
||
29 | * frontend_moderation: Display unmoderated comments in the frontend, if the user can moderate them. |
||
30 | * frontend_spam: Display spam comments in the frontend, if the user can moderate them. |
||
31 | * html_allowed: Allow for sanitized HTML in comments |
||
32 | * use_preview: Preview formatted comment (when allowing HTML) |
||
33 | * nested_comments: Enable nested comments |
||
34 | * nested_depth: Max depth of nested comments in levels (where root is 1 depth) 0 means no limit. |
||
35 | * |
||
36 | * @var array |
||
37 | * |
||
38 | * @config |
||
39 | */ |
||
40 | private static $comments = array( |
||
41 | 'enabled' => true, |
||
42 | 'enabled_cms' => false, |
||
43 | 'require_login' => false, |
||
44 | 'require_login_cms' => false, |
||
45 | 'required_permission' => false, |
||
46 | 'include_js' => true, |
||
47 | 'use_gravatar' => false, |
||
48 | 'gravatar_size' => 80, |
||
49 | 'gravatar_default' => 'identicon', |
||
50 | 'gravatar_rating' => 'g', |
||
51 | 'show_comments_when_disabled' => false, |
||
52 | 'order_comments_by' => '"Created" DESC', |
||
53 | 'order_replies_by' => false, |
||
54 | 'comments_per_page' => 10, |
||
55 | 'comments_holder_id' => 'comments-holder', |
||
56 | 'comment_permalink_prefix' => 'comment-', |
||
57 | 'require_moderation' => false, |
||
58 | 'require_moderation_nonmembers' => false, |
||
59 | 'require_moderation_cms' => false, |
||
60 | 'frontend_moderation' => false, |
||
61 | 'frontend_spam' => false, |
||
62 | 'html_allowed' => false, |
||
63 | 'html_allowed_elements' => array('a', 'img', 'i', 'b'), |
||
64 | 'use_preview' => false, |
||
65 | 'nested_comments' => false, |
||
66 | 'nested_depth' => 2, |
||
67 | ); |
||
68 | |||
69 | /** |
||
70 | * @var array |
||
71 | */ |
||
72 | private static $db = array( |
||
73 | 'ProvideComments' => 'Boolean', |
||
74 | 'ModerationRequired' => 'Enum(\'None,Required,NonMembersOnly\',\'None\')', |
||
75 | 'CommentsRequireLogin' => 'Boolean', |
||
76 | ); |
||
77 | |||
78 | /** |
||
79 | * CMS configurable options should default to the config values, but respect |
||
80 | * default values specified by the object |
||
81 | */ |
||
82 | public function populateDefaults() |
||
111 | |||
112 | |||
113 | /** |
||
114 | * If this extension is applied to a {@link SiteTree} record then |
||
115 | * append a Provide Comments checkbox to allow authors to trigger |
||
116 | * whether or not to display comments |
||
117 | * |
||
118 | * @todo Allow customization of other {@link Commenting} configuration |
||
119 | * |
||
120 | * @param FieldList $fields |
||
121 | */ |
||
122 | public function updateSettingsFields(FieldList $fields) |
||
166 | |||
167 | /** |
||
168 | * Get comment moderation rules for this parent |
||
169 | * |
||
170 | * None: No moderation required |
||
171 | * Required: All comments |
||
172 | * NonMembersOnly: Only anonymous users |
||
173 | * |
||
174 | * @return string |
||
175 | */ |
||
176 | public function getModerationRequired() |
||
188 | |||
189 | /** |
||
190 | * Determine if users must be logged in to post comments |
||
191 | * |
||
192 | * @return boolean |
||
193 | */ |
||
194 | public function getCommentsRequireLogin() |
||
202 | |||
203 | /** |
||
204 | * Returns the RelationList of all comments against this object. Can be used as a data source |
||
205 | * for a gridfield with write access. |
||
206 | * |
||
207 | * @return CommentList |
||
208 | */ |
||
209 | public function AllComments() |
||
218 | |||
219 | /** |
||
220 | * Returns all comments against this object, with with spam and unmoderated items excluded, for use in the frontend |
||
221 | * |
||
222 | * @return CommentList |
||
223 | */ |
||
224 | public function AllVisibleComments() |
||
244 | |||
245 | /** |
||
246 | * Returns the root level comments, with spam and unmoderated items excluded, for use in the frontend |
||
247 | * |
||
248 | * @return CommentList |
||
249 | */ |
||
250 | public function Comments() |
||
262 | |||
263 | /** |
||
264 | * Returns a paged list of the root level comments, with spam and unmoderated items excluded, |
||
265 | * for use in the frontend |
||
266 | * |
||
267 | * @return PaginatedList |
||
268 | */ |
||
269 | View Code Duplication | public function PagedComments() |
|
281 | |||
282 | /** |
||
283 | * Check if comments are configured for this page even if they are currently disabled. |
||
284 | * Do not include the comments on pages which don't have id's such as security pages |
||
285 | * |
||
286 | * @deprecated since version 2.0 |
||
287 | * |
||
288 | * @return boolean |
||
289 | */ |
||
290 | public function getCommentsConfigured() |
||
295 | |||
296 | /** |
||
297 | * Determine if comments are enabled for this instance |
||
298 | * |
||
299 | * @return boolean |
||
300 | */ |
||
301 | public function getCommentsEnabled() |
||
315 | |||
316 | /** |
||
317 | * Get the HTML ID for the comment holder in the template |
||
318 | * |
||
319 | * @return string |
||
320 | */ |
||
321 | public function getCommentHolderID() |
||
325 | |||
326 | /** |
||
327 | * @deprecated since version 2.0 |
||
328 | */ |
||
329 | public function getPostingRequiresPermission() |
||
334 | |||
335 | /** |
||
336 | * Permission codes required in order to post (or empty if none required) |
||
337 | * |
||
338 | * @return string|array Permission or list of permissions, if required |
||
339 | */ |
||
340 | public function getPostingRequiredPermission() |
||
344 | |||
345 | public function canPost() |
||
350 | |||
351 | /** |
||
352 | * Determine if a user can post comments on this item |
||
353 | * |
||
354 | * @param Member $member Member to check |
||
355 | * |
||
356 | * @return boolean |
||
357 | */ |
||
358 | public function canPostComment($member = null) |
||
385 | |||
386 | /** |
||
387 | * Determine if this member can moderate comments in the CMS |
||
388 | * |
||
389 | * @param Member $member |
||
390 | * |
||
391 | * @return boolean |
||
392 | */ |
||
393 | public function canModerateComments($member = null) |
||
403 | |||
404 | public function getRssLink() |
||
409 | |||
410 | /** |
||
411 | * Gets the RSS link to all comments |
||
412 | * |
||
413 | * @return string |
||
414 | */ |
||
415 | public function getCommentRSSLink() |
||
419 | |||
420 | public function getRssLinkPage() |
||
425 | |||
426 | /** |
||
427 | * Get the RSS link to all comments on this page |
||
428 | * |
||
429 | * @return string |
||
430 | */ |
||
431 | public function getCommentRSSLinkPage() |
||
437 | |||
438 | /** |
||
439 | * Comments interface for the front end. Includes the CommentAddForm and the composition |
||
440 | * of the comments display. |
||
441 | * |
||
442 | * To customize the html see templates/CommentInterface.ss or extend this function with |
||
443 | * your own extension. |
||
444 | * |
||
445 | * @todo Cleanup the passing of all this configuration based functionality |
||
446 | * |
||
447 | * @see docs/en/Extending |
||
448 | */ |
||
449 | public function CommentsForm() |
||
481 | |||
482 | /** |
||
483 | * Returns whether this extension instance is attached to a {@link SiteTree} object |
||
484 | * |
||
485 | * @return bool |
||
486 | */ |
||
487 | public function attachedToSiteTree() |
||
493 | |||
494 | /** |
||
495 | * @deprecated 1.0 Please use {@link CommentsExtension->CommentsForm()} |
||
496 | */ |
||
497 | public function PageComments() |
||
503 | |||
504 | /** |
||
505 | * Get the commenting option for this object |
||
506 | * |
||
507 | * This can be overridden in any instance or extension to customise the option available |
||
508 | * |
||
509 | * @param string $key |
||
510 | * |
||
511 | * @return mixed Result if the setting is available, or null otherwise |
||
512 | */ |
||
513 | public function getCommentsOption($key) |
||
529 | |||
530 | /** |
||
531 | * Add moderation functions to the current fieldlist |
||
532 | * |
||
533 | * @param FieldList $fields |
||
534 | */ |
||
535 | protected function updateModerationFields(FieldList $fields) |
||
590 | |||
591 | public function updateCMSFields(FieldList $fields) |
||
603 | } |
||
604 |
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.