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:
| 1 | <?php | ||
| 18 | class Sensei_Legacy_Shortcodes { | ||
| 19 | |||
| 20 | /** | ||
| 21 | * Add the legacy shortcodes to WordPress | ||
| 22 | * | ||
| 23 | * @since 1.9.0 | ||
| 24 | */ | ||
| 25 |     public static function init(){ | ||
| 26 | |||
| 27 | add_shortcode( 'allcourses', array( __CLASS__, 'all_courses' ) ); | ||
| 28 | add_shortcode( 'newcourses', array( __CLASS__,'new_courses' ) ); | ||
| 29 | add_shortcode( 'featuredcourses', array( __CLASS__,'featured_courses') ); | ||
| 30 | add_shortcode( 'freecourses', array( __CLASS__,'free_courses') ); | ||
| 31 | add_shortcode( 'paidcourses', array( __CLASS__,'paid_courses') ); | ||
| 32 | add_shortcode( 'usercourses', array( __CLASS__,'user_courses' ) ); | ||
| 33 | |||
| 34 | } | ||
| 35 | /** | ||
| 36 | * all_courses shortcode output function. | ||
| 37 | * | ||
| 38 | * The function should only be called indirectly through do_shortcode() | ||
| 39 | * | ||
| 40 | * @access public | ||
| 41 | * @param mixed $atts | ||
| 42 | * @param mixed $content (default: null) | ||
| 43 | * @return string | ||
| 44 | */ | ||
| 45 |     public static function all_courses( $atts, $content = null ) { | ||
| 46 | |||
| 47 | return self::generate_shortcode_courses( '', 'allcourses' ); // all courses but no title | ||
| 48 | |||
| 49 | } // all_courses() | ||
| 50 | |||
| 51 | /** | ||
| 52 | * paid_courses function. | ||
| 53 | * | ||
| 54 | * @access public | ||
| 55 | * @param mixed $atts | ||
| 56 | * @param mixed $content (default: null) | ||
| 57 | * @return string | ||
| 58 | */ | ||
| 59 |     public static function paid_courses( $atts, $content = null ) { | ||
| 60 | |||
| 61 | return self::generate_shortcode_courses( __( 'Paid Courses', 'woothemes-sensei' ), 'paidcourses' ); | ||
| 62 | |||
| 63 | } // End paid_courses() | ||
| 64 | |||
| 65 | |||
| 66 | /** | ||
| 67 | * featured_courses function. | ||
| 68 | * | ||
| 69 | * @access public | ||
| 70 | * @param mixed $atts | ||
| 71 | * @param mixed $content (default: null) | ||
| 72 | * @return string | ||
| 73 | */ | ||
| 74 |     public static function featured_courses( $atts, $content = null ) { | ||
| 75 | |||
| 76 | return self::generate_shortcode_courses( __( 'Featured Courses', 'woothemes-sensei' ), 'featuredcourses' ); | ||
| 77 | |||
| 78 | } // End featured_courses() | ||
| 79 | |||
| 80 | /** | ||
| 81 | * shortcode_free_courses function. | ||
| 82 | * | ||
| 83 | * @access public | ||
| 84 | * @param mixed $atts | ||
| 85 | * @param mixed $content (default: null) | ||
| 86 | * @return string | ||
| 87 | */ | ||
| 88 |     public static function free_courses( $atts, $content = null ) { | ||
| 89 | |||
| 90 | return self::generate_shortcode_courses( __( 'Free Courses', 'woothemes-sensei' ) 'freecourses' ); | ||
|  | |||
| 91 | |||
| 92 | } // End free_courses() | ||
| 93 | |||
| 94 | /** | ||
| 95 | * shortcode_new_courses function. | ||
| 96 | * | ||
| 97 | * @access public | ||
| 98 | * @param mixed $atts | ||
| 99 | * @param mixed $content (default: null) | ||
| 100 | * @return string | ||
| 101 | */ | ||
| 102 |     public static function new_courses( $atts, $content = null ) { | ||
| 103 | |||
| 104 | return self::generate_shortcode_courses( __( 'New Courses', 'woothemes-sensei' ), 'newcourses' ); | ||
| 105 | |||
| 106 | } // End new_courses() | ||
| 107 | |||
| 108 | /** | ||
| 109 | * Generate courses adding a title. | ||
| 110 | * | ||
| 111 | * @since 1.9.0 | ||
| 112 | * | ||
| 113 | * @param $title | ||
| 114 | * @param $shortcode_specific_override | ||
| 115 | * @return string | ||
| 116 | */ | ||
| 117 |     public static function generate_shortcode_courses( $title , $shortcode_specific_override  ){ | ||
| 118 | |||
| 119 | global $shortcode_override, $posts_array; | ||
| 120 | |||
| 121 | $shortcode_override = $shortcode_specific_override; | ||
| 122 | |||
| 123 | // do not show this short code if there is a shortcode int he url and | ||
| 124 | // this specific shortcode is not the one requested in the ur. | ||
| 125 | $specific_shortcode_requested = isset( $_GET['action'] ) ? sanitize_text_field( $_GET['action'] ) : ''; | ||
| 126 | if( ! empty( $specific_shortcode_requested) && | ||
| 127 |             $specific_shortcode_requested != $shortcode_override ){ | ||
| 128 | |||
| 129 | return ''; | ||
| 130 | |||
| 131 | } | ||
| 132 | |||
| 133 | // loop and get all courses html | ||
| 134 | ob_start(); | ||
| 135 | self::initialise_legacy_course_loop(); | ||
| 136 | $courses = ob_get_clean(); | ||
| 137 | |||
| 138 | $content = ''; | ||
| 139 |         if( count( $posts_array ) > 0 ){ | ||
| 140 | |||
| 141 | $before = empty($title)? '' : '<header class="archive-header"><h2>'. $title .'</h2></header>'; | ||
| 142 | $before .= '<section id="main-course" class="course-container">'; | ||
| 143 | |||
| 144 | $after = '</section>'; | ||
| 145 | |||
| 146 | //assemble | ||
| 147 | $content = $before . $courses . $after; | ||
| 148 | |||
| 149 | } | ||
| 150 | |||
| 151 | return $content; | ||
| 152 | |||
| 153 | }// end generate_shortcode_courses | ||
| 154 | |||
| 155 | |||
| 156 | /** | ||
| 157 | * user_courses function. | ||
| 158 | * | ||
| 159 | * @access public | ||
| 160 | * @param mixed $atts | ||
| 161 | * @param mixed $content (default: null) | ||
| 162 | * @return string | ||
| 163 | */ | ||
| 164 |     public static function user_courses( $atts, $content = null ) { | ||
| 165 | global $shortcode_override; | ||
| 166 | extract( shortcode_atts( array( 'amount' => 0 ), $atts ) ); | ||
| 167 | |||
| 168 | $shortcode_override = 'usercourses'; | ||
| 169 | |||
| 170 | ob_start(); | ||
| 171 | |||
| 172 |         if( is_user_logged_in() ){ | ||
| 173 | |||
| 174 | Sensei_Templates::get_template( 'user/my-courses.php' ); | ||
| 175 | |||
| 176 |         }else{ | ||
| 177 | |||
| 178 | Sensei()->frontend->sensei_login_form(); | ||
| 179 | |||
| 180 | } | ||
| 181 | |||
| 182 | $content = ob_get_clean(); | ||
| 183 | return $content; | ||
| 184 | |||
| 185 | } // End user_courses() | ||
| 186 | |||
| 187 | /** | ||
| 188 | * This function is simply to honor the legacy | ||
| 189 | * loop-course.php for the old shortcodes. | ||
| 190 | * @since 1.9.0 | ||
| 191 | */ | ||
| 192 |     public static function initialise_legacy_course_loop(){ | ||
| 193 | |||
| 194 | global $post, $wp_query, $shortcode_override, $course_excludes; | ||
| 195 | |||
| 196 | // Handle Query Type | ||
| 197 | $query_type = ''; | ||
| 198 | |||
| 199 |         if ( isset( $_GET[ 'action' ] ) && ( '' != esc_html( $_GET[ 'action' ] ) ) ) { | ||
| 200 | $query_type = esc_html( $_GET[ 'action' ] ); | ||
| 201 | } // End If Statement | ||
| 202 | |||
| 203 |         if ( '' != $shortcode_override ) { | ||
| 204 | $query_type = $shortcode_override; | ||
| 205 | } // End If Statement | ||
| 206 | |||
| 207 |         if ( !is_array( $course_excludes ) ) { $course_excludes = array(); } | ||
| 208 | |||
| 209 | // Check that query returns results | ||
| 210 | // Handle Pagination | ||
| 211 | $paged = $wp_query->get( 'paged' ); | ||
| 212 | $paged = empty( $paged ) ? 1 : $paged; | ||
| 213 | |||
| 214 | |||
| 215 | // Check for pagination settings | ||
| 216 |         if ( isset( Sensei()->settings->settings[ 'course_archive_amount' ] ) && ( 0 < absint( Sensei()->settings->settings[ 'course_archive_amount' ] ) ) ) { | ||
| 217 | |||
| 218 | $amount = absint( Sensei()->settings->settings[ 'course_archive_amount' ] ); | ||
| 219 | |||
| 220 |         } else { | ||
| 221 | |||
| 222 | $amount = $wp_query->get( 'posts_per_page' ); | ||
| 223 | |||
| 224 | } // End If Statement | ||
| 225 | |||
| 226 | // This is not a paginated page (or it's simply the first page of a paginated page/post) | ||
| 227 | |||
| 228 | global $posts_array; | ||
| 229 | $course_includes = array(); | ||
| 230 | |||
| 231 | $query_args = Sensei()->course->get_archive_query_args( $shortcode_override, $amount, $course_includes, $course_excludes ); | ||
| 232 | $course_query = new WP_Query( $query_args ); | ||
| 233 | $posts_array = $course_query->get_posts(); | ||
| 234 | |||
| 235 | // output the courses | ||
| 236 |         if( ! empty( $posts_array ) ) { | ||
| 237 | |||
| 238 | //output all courses for current query | ||
| 239 | self::loop_courses( $course_query, $amount ); | ||
| 240 | |||
| 241 | } | ||
| 242 | |||
| 243 | } | ||
| 244 | |||
| 245 | /** | ||
| 246 | * Loop through courses in the query and output the infomration needed | ||
| 247 | * | ||
| 248 | * @since 1.9.0 | ||
| 249 | * | ||
| 250 | * @param WP_Query $course_query | ||
| 251 | */ | ||
| 252 |     public static function loop_courses( $course_query, $amount ){ | ||
| 253 | |||
| 254 | global $shortcode_override, $posts_array, $post, $wp_query, $shortcode_override, $course_excludes, $course_includes; | ||
| 255 | |||
| 256 |         if ( count( $course_query->get_posts() ) > 0 ) { | ||
| 257 | |||
| 258 | do_action( 'sensei_course_archive_header', $shortcode_override ); | ||
| 259 | |||
| 260 |             foreach ( $course_query->get_posts() as $course){ | ||
| 261 | |||
| 262 | // Make sure the other loops dont include the same post twice! | ||
| 263 | array_push( $course_excludes, $course->ID ); | ||
| 264 | |||
| 265 | // output the course markup | ||
| 266 | self::the_course( $course->ID ); | ||
| 267 | |||
| 268 | } // End For Loop | ||
| 269 | |||
| 270 | // More and Prev links | ||
| 271 | $posts_array_query = new WP_Query(Sensei()->course->course_query( $shortcode_override, $amount, $course_includes, $course_excludes ) ); | ||
| 272 | $posts_array = $posts_array_query->get_posts(); | ||
| 273 | $max_pages = $course_query->found_posts / $amount; | ||
| 274 |             if ( '' != $shortcode_override && ( $max_pages > $course_query->get( 'paged' ) ) ) { | ||
| 275 | |||
| 276 |                 switch( $shortcode_override ){ | ||
| 277 | case 'paidcourses': | ||
| 278 | $filter = 'paid'; | ||
| 279 | break; | ||
| 280 | case 'featuredcourses': | ||
| 281 | $filter = 'featured'; | ||
| 282 | break; | ||
| 283 | case 'freecourses': | ||
| 284 | $filter = 'free'; | ||
| 285 | break; | ||
| 286 | default: | ||
| 287 | $filter = ''; | ||
| 288 | break; | ||
| 289 | } | ||
| 290 | |||
| 291 | $quer_args = array(); | ||
| 292 | $quer_args[ 'paged' ] = '2'; | ||
| 293 |                 if( !empty( $filter ) ){ | ||
| 294 | $quer_args[ 'course_filter' ] = $filter; | ||
| 295 | } | ||
| 296 | |||
| 297 | $course_pagination_link = get_post_type_archive_link( 'course' ); | ||
| 298 | $more_link_text = esc_html( Sensei()->settings->settings[ 'course_archive_more_link_text' ] ); | ||
| 299 | $more_link_url = esc_url( add_query_arg( $quer_args, $course_pagination_link ) ); | ||
| 300 | |||
| 301 | // next/more | ||
| 302 | $html = '<div class="navigation"><div class="nav-next">'; | ||
| 303 | $html .= '<a href="' . $more_link_url . '">'; | ||
| 304 | $html .= $more_link_text; | ||
| 305 | $html .= '<span class="meta-nav"></span></a></div>'; | ||
| 306 | |||
| 307 | echo apply_filters( 'course_archive_next_link', $html ); | ||
| 308 | |||
| 309 | } // End If Statement | ||
| 310 | |||
| 311 | } // End If Statement | ||
| 312 | } | ||
| 313 | |||
| 314 | /** | ||
| 315 | * Print a single course markup | ||
| 316 | * | ||
| 317 | * @param $course_id | ||
| 318 | */ | ||
| 319 |     public static function the_course( $course_id ){ | ||
| 320 | |||
| 321 | // Get meta data | ||
| 322 | $course = get_post( $course_id ); | ||
| 323 | $user_info = get_userdata( absint( $course->post_author ) ); | ||
| 324 | $author_link = get_author_posts_url( absint( $course->post_author ) ); | ||
| 325 | $author_display_name = $user_info->display_name; | ||
| 326 | $author_id = $course->post_author; | ||
| 327 | $category_output = get_the_term_list( $course_id, 'course-category', '', ', ', '' ); | ||
| 328 | $preview_lesson_count = intval( Sensei()->course->course_lesson_preview_count( $course_id ) ); | ||
| 329 | $is_user_taking_course = Sensei_Utils::user_started_course( $course_id, get_current_user_id() ); | ||
| 330 | ?> | ||
| 331 | |||
| 332 | <article class="<?php echo esc_attr( join( ' ', get_post_class( array( 'course', 'post' ), $course_id ) ) ); ?>"> | ||
| 333 | <?php | ||
| 334 | // so that legacy shortcodes work with the party plugins that wants to hook in | ||
| 335 |             do_action('sensei_course_content_before',$course->ID ); | ||
| 336 | ?> | ||
| 337 | <div class="course-content"> | ||
| 338 | |||
| 339 | <?php Sensei()->course->course_image($course_id); ?> | ||
| 340 | |||
| 341 | <header> | ||
| 342 | |||
| 343 | <h2><a href="<?php echo get_permalink($course_id) ?>" title="<?php echo $course->post_title; ?>"><?php echo $course->post_title; ?></a></h2> | ||
| 344 | |||
| 345 | </header> | ||
| 346 | |||
| 347 | <section class="entry"> | ||
| 348 | |||
| 349 | <p class="sensei-course-meta"> | ||
| 350 | |||
| 351 |                         <?php if ( isset( Sensei()->settings->settings[ 'course_author' ] ) && ( Sensei()->settings->settings[ 'course_author' ] ) ) { ?> | ||
| 352 | <span class="course-author"><?php _e( 'by ', 'woothemes-sensei' ); ?><a href="<?php echo $author_link; ?>" title="<?php echo esc_attr( $author_display_name ); ?>"><?php echo esc_html( $author_display_name ); ?></a></span> | ||
| 353 | <?php } // End If Statement ?> | ||
| 354 | |||
| 355 | <span class="course-lesson-count"> | ||
| 356 | <?php echo Sensei()->course->course_lesson_count( $course_id ) . ' ' . __( 'Lessons', 'woothemes-sensei' ); ?> | ||
| 357 | </span> | ||
| 358 | |||
| 359 |                         <?php if ( '' != $category_output ) { ?> | ||
| 360 | <span class="course-category"><?php echo sprintf( __( 'in %s', 'woothemes-sensei' ), $category_output ); ?></span> | ||
| 361 | <?php } // End If Statement ?> | ||
| 362 | |||
| 363 | <?php sensei_simple_course_price( $course_id ); ?> | ||
| 364 | |||
| 365 | </p> | ||
| 366 | |||
| 367 | <p class="course-excerpt"><?php echo $course->post_excerpt; ?> | ||
| 368 | |||
| 369 | </p> | ||
| 370 | |||
| 371 |                     <?php if ( 0 < $preview_lesson_count && !$is_user_taking_course ) { | ||
| 372 | $preview_lessons = sprintf( __( '(%d preview lessons)', 'woothemes-sensei' ), $preview_lesson_count ); ?> | ||
| 373 | <p class="sensei-free-lessons"> | ||
| 374 | <a href="<?php echo get_permalink( $course_id ); ?>"><?php _e( 'Preview this course', 'woothemes-sensei' ) ?> | ||
| 375 | </a> - <?php echo $preview_lessons; ?> | ||
| 376 | </p> | ||
| 377 | <?php } ?> | ||
| 378 | |||
| 379 | </section> | ||
| 380 | |||
| 381 | </div> | ||
| 382 | <?php | ||
| 383 | // so that legacy shortcodes work with thir party plugins that wants to hook in | ||
| 384 |             do_action('sensei_course_content_after', $course->ID); | ||
| 385 | ?> | ||
| 386 | |||
| 387 | </article> | ||
| 388 | |||
| 389 | <?php | ||
| 390 | |||
| 391 | |||
| 392 | } // end the_course | ||
| 393 | |||
| 394 | }// end class legacy shortcodes |