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 Sensei_Templates 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 Sensei_Templates, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
13 | class Sensei_Templates { |
||
14 | |||
15 | /** |
||
16 | * Load the template files from within sensei/templates/ or the the theme if overrided within the theme. |
||
17 | * |
||
18 | * @since 1.9.0 |
||
19 | * @param string $slug |
||
20 | * @param string $name default: '' |
||
21 | * |
||
22 | * @return void |
||
23 | */ |
||
24 | public static function get_part( $slug, $name = '' ){ |
||
25 | |||
26 | $template = ''; |
||
27 | $plugin_template_url = Sensei()->template_url; |
||
28 | $plugin_template_path = Sensei()->plugin_path() . "/templates/"; |
||
29 | |||
30 | // Look in yourtheme/slug-name.php and yourtheme/sensei/slug-name.php |
||
31 | if ( $name ){ |
||
32 | |||
33 | $template = locate_template( array ( "{$slug}-{$name}.php", "{$plugin_template_url}{$slug}-{$name}.php" ) ); |
||
34 | |||
35 | } |
||
36 | |||
37 | // Get default slug-name.php |
||
38 | if ( ! $template && $name && file_exists( $plugin_template_path . "{$slug}-{$name}.php" ) ){ |
||
39 | |||
40 | $template = $plugin_template_path . "{$slug}-{$name}.php"; |
||
41 | |||
42 | } |
||
43 | |||
44 | |||
45 | // If template file doesn't exist, look in yourtheme/slug.php and yourtheme/sensei/slug.php |
||
46 | if ( !$template ){ |
||
47 | |||
48 | $template = locate_template( array ( "{$slug}.php", "{$plugin_template_url}{$slug}.php" ) ); |
||
49 | |||
50 | } |
||
51 | |||
52 | |||
53 | if ( $template ){ |
||
54 | |||
55 | load_template( $template, false ); |
||
56 | |||
57 | } |
||
58 | |||
59 | } // end get part |
||
60 | |||
61 | /** |
||
62 | * Get the template. |
||
63 | * |
||
64 | * @since 1.9.0 |
||
65 | * |
||
66 | * @param $template_name |
||
67 | * @param array $args |
||
68 | * @param string $template_path |
||
69 | * @param string $default_path |
||
70 | */ |
||
71 | public static function get_template( $template_name, $args = array(), $template_path = '', $default_path = '' ) { |
||
89 | |||
90 | /** |
||
91 | * Check if the template file exists. A wrapper for WP locate_template. |
||
92 | * |
||
93 | * @since 1.9.0 |
||
94 | * |
||
95 | * @param $template_name |
||
96 | * @param string $template_path |
||
97 | * @param string $default_path |
||
98 | * |
||
99 | * @return mixed|void |
||
100 | */ |
||
101 | public static function locate_template( $template_name, $template_path = '', $default_path = '' ) { |
||
129 | |||
130 | /** |
||
131 | * Determine which Sensei template to load based on the |
||
132 | * current page context. |
||
133 | * |
||
134 | * @since 1.0 |
||
135 | * |
||
136 | * @param string $template |
||
137 | * @return string $template |
||
138 | */ |
||
139 | public static function template_loader ( $template = '' ) { |
||
261 | |||
262 | /** |
||
263 | * This function loads the no-permissions template for users with no access |
||
264 | * if a Sensei template was loaded. |
||
265 | * |
||
266 | * This function doesn't determine the permissions. Permissions must be determined |
||
267 | * before loading this function as it only gets the template. |
||
268 | * |
||
269 | * This function also checks the user theme for overrides to ensure the right template |
||
270 | * file is returned. |
||
271 | * |
||
272 | * @since 1.9.0 |
||
273 | */ |
||
274 | public static function get_no_permission_template( ){ |
||
293 | |||
294 | /** |
||
295 | * This function is specifically created for loading template files from the theme. |
||
296 | * |
||
297 | * This function checks if the user has overwritten the templates like in their theme. If they have it in their theme it will load the header and the footer |
||
298 | * around the singular content file from their theme and exit. |
||
299 | * |
||
300 | * If none is found this function will do nothing. If a template is found this funciton |
||
301 | * will exit execution of the script an not continue. |
||
302 | * |
||
303 | * @since 1.9.0 |
||
304 | * @param string $template |
||
305 | * @param bool $load_header_footer should the file be wrapped in between header and footer? Default: true |
||
306 | */ |
||
307 | public static function locate_and_load_template_overrides( $template = '', $load_header_footer = false ){ |
||
329 | |||
330 | |||
331 | /** |
||
332 | * Hooks the deprecated archive content hook into the hook again just in |
||
333 | * case other developers have used it. |
||
334 | * |
||
335 | * @deprecated since 1.9.0 |
||
336 | */ |
||
337 | public static function deprecated_archive_course_content_hook(){ |
||
342 | |||
343 | /** |
||
344 | * A generic function for echoing the post title |
||
345 | * |
||
346 | * @since 1.9.0 |
||
347 | * @param WP_Post $post |
||
348 | */ |
||
349 | public static function the_title( $post ){ |
||
382 | |||
383 | /** |
||
384 | * This function adds the hooks inside and above the single course content for |
||
385 | * backwards compatibility sake. |
||
386 | * |
||
387 | * @since 1.9.0 |
||
388 | * @deprecated 1.9.0 |
||
389 | */ |
||
390 | public static function deprecated_single_course_inside_before_hooks(){ |
||
397 | |||
398 | /** |
||
399 | * This function adds the hooks to sensei_course_single_lessons for |
||
400 | * backwards compatibility sake. and provides developers with an alternative. |
||
401 | * |
||
402 | * @since 1.9.0 |
||
403 | * @deprecated 1.9.0 |
||
404 | */ |
||
405 | public static function deprecate_sensei_course_single_lessons_hook(){ |
||
410 | |||
411 | /** |
||
412 | * Deprecated all deprecated_single_main_content_hook hooked actions. |
||
413 | * |
||
414 | * The content must be dealt with inside the respective templates. |
||
415 | * |
||
416 | * @since 1.9.0 |
||
417 | * @deprecated 1.9.0 |
||
418 | */ |
||
419 | public static function deprecated_single_main_content_hook(){ |
||
431 | |||
432 | /** |
||
433 | * Deprecate the old sensei modules |
||
434 | * @since 1.9.0 |
||
435 | * @deprecated since 1.9.0 |
||
436 | */ |
||
437 | public static function deprecate_module_before_hook(){ |
||
442 | |||
443 | /** |
||
444 | * Deprecate the old sensei modules after hooks |
||
445 | * @since 1.9.0 |
||
446 | * @deprecated since 1.9.0 |
||
447 | */ |
||
448 | public static function deprecate_module_after_hook(){ |
||
453 | |||
454 | /** |
||
455 | * Deprecate the single message hooks for post types. |
||
456 | * |
||
457 | * @since 1.9.0 |
||
458 | * @deprecated since 1.9.0 |
||
459 | */ |
||
460 | public static function deprecate_all_post_type_single_title_hooks(){ |
||
469 | |||
470 | /** |
||
471 | * course_single_meta function. |
||
472 | * |
||
473 | * @access public |
||
474 | * @return void |
||
475 | * @deprecated since 1.9.0 |
||
476 | */ |
||
477 | public static function deprecate_course_single_meta_hooks() { |
||
486 | |||
487 | /** |
||
488 | * Run the deprecated hooks on the single lesson page |
||
489 | * @deprecated since 1.9.0 |
||
490 | */ |
||
491 | public static function deprecate_single_lesson_breadcrumbs_and_comments_hooks() { |
||
501 | |||
502 | /** |
||
503 | * Deprecate the hook sensei_lesson_course_signup. |
||
504 | * |
||
505 | * The hook content will be linked directly on the recommended |
||
506 | * sensei_single_lesson_content_inside_after |
||
507 | * |
||
508 | * @deprecated since 1.9.0 |
||
509 | */ |
||
510 | public static function deprecate_sensei_lesson_course_signup_hook(){ |
||
521 | |||
522 | /** |
||
523 | * Running the deprecated hook: sensei_lesson_single_meta |
||
524 | * |
||
525 | * @since 1.9.0 |
||
526 | * @deprecated since 1.9.0 |
||
527 | */ |
||
528 | public static function deprecate_sensei_lesson_single_meta_hook(){ |
||
538 | |||
539 | /** |
||
540 | * Deprecate the sensei lesson single title hook |
||
541 | * @deprecated since 1.9.0 |
||
542 | */ |
||
543 | public static function deprecate_sensei_lesson_single_title(){ |
||
548 | |||
549 | /** |
||
550 | * hook in the deperecated single main content to the lesson |
||
551 | * @deprecated since 1.9.0 |
||
552 | */ |
||
553 | public static function deprecate_lesson_single_main_content_hook(){ |
||
558 | |||
559 | /** |
||
560 | * hook in the deperecated single main content to the lesson |
||
561 | * @deprecated since 1.9.0 |
||
562 | */ |
||
563 | public static function deprecate_lesson_image_hook(){ |
||
568 | |||
569 | /** |
||
570 | * hook in the deprecated sensei_login_form hook for backwards |
||
571 | * compatibility |
||
572 | * |
||
573 | * @since 1.9.0 |
||
574 | * @deprecated since 1.9.0 |
||
575 | */ |
||
576 | public static function deprecate_sensei_login_form_hook(){ |
||
581 | |||
582 | /** |
||
583 | * Fire the sensei_complete_course action. |
||
584 | * |
||
585 | * This is just a backwards compatible function to add the action |
||
586 | * to a template. This should not be used as the function from this |
||
587 | * hook will be added directly to my-courses page via one of the hooks there. |
||
588 | * |
||
589 | * @since 1.9.0 |
||
590 | */ |
||
591 | public static function fire_sensei_complete_course_hook(){ |
||
596 | |||
597 | /** |
||
598 | * Fire the frontend message hook |
||
599 | * |
||
600 | * @since 1.9.0 |
||
601 | */ |
||
602 | public static function fire_frontend_messages_hook(){ |
||
607 | |||
608 | /** |
||
609 | * deprecate the sensei_before_user_course_content hook in favor |
||
610 | * of sensei_my_courses_content_inside_before. |
||
611 | * |
||
612 | * @deprected since 1.9.0 |
||
613 | */ |
||
614 | public static function deprecate_sensei_before_user_course_content_hook(){ |
||
619 | |||
620 | /** |
||
621 | * deprecate the sensei_before_user_course_content hook in favor |
||
622 | * of sensei_my_courses_content_inside_after hook. |
||
623 | * |
||
624 | * @deprected since 1.9.0 |
||
625 | */ |
||
626 | public static function deprecate_sensei_after_user_course_content_hook(){ |
||
631 | |||
632 | /** |
||
633 | * Deprecate the 2 main hooks on the archive message template |
||
634 | * |
||
635 | * @deprecated since 1.9.0 |
||
636 | * @since 1.9.0 |
||
637 | */ |
||
638 | public static function deprecated_archive_message_hooks (){ |
||
644 | |||
645 | /** |
||
646 | * Run the sensei_complete_quiz for those still hooking |
||
647 | * into but deprecated it. |
||
648 | * |
||
649 | * @deprecated since 1.9.0 |
||
650 | */ |
||
651 | public static function deprecate_sensei_complete_quiz_action(){ |
||
656 | |||
657 | /** |
||
658 | * Run the sensei_quiz_question_type action for those still hooing into it, but depreate |
||
659 | * it to provide user with a better alternative. |
||
660 | * |
||
661 | * @deprecated since 1.9.0 |
||
662 | */ |
||
663 | public static function deprecate_sensei_quiz_question_type_action(){ |
||
671 | |||
672 | |||
673 | public static function the_register_button( $post_id = "" ){ |
||
703 | }//end class |
||
704 |
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.