Complex classes like Give_Donators_Gravatars 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 Give_Donators_Gravatars, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 24 | class Give_Donors_Gravatars { |
||
| 25 | |||
| 26 | /** |
||
| 27 | * Class Constructor |
||
| 28 | * |
||
| 29 | * Set up the Give Donors Gravatars Class. |
||
| 30 | * |
||
| 31 | * @since 1.0 |
||
| 32 | * @access public |
||
| 33 | */ |
||
| 34 | public function __construct() { |
||
| 35 | $this->setup_actions(); |
||
| 36 | } |
||
| 37 | |||
| 38 | /** |
||
| 39 | * Setup the default hooks and actions |
||
| 40 | * |
||
| 41 | * @since 1.0 |
||
| 42 | * @access private |
||
| 43 | * |
||
| 44 | * @return void |
||
| 45 | */ |
||
| 46 | private function setup_actions() { |
||
| 47 | // add_action( 'widgets_init', array( $this, 'register_widget' ) ); |
||
| 48 | // add_shortcode( 'give_donors_gravatars', array( $this, 'shortcode' ) ); |
||
| 49 | // add_filter( 'give_settings_display', array( $this, 'settings' ) ); |
||
| 50 | // do_action( 'give_donors_gravatars_setup_actions' ); |
||
| 51 | } |
||
| 52 | |||
| 53 | /** |
||
| 54 | * Utility function to check if a gravatar exists for a given email or id |
||
| 55 | * |
||
| 56 | * @see: https://gist.github.com/justinph/5197810 |
||
| 57 | * |
||
| 58 | * @since 1.0 |
||
| 59 | * @access public |
||
| 60 | * |
||
| 61 | * @param int|string|object $id_or_email A user ID, email address, or comment object |
||
| 62 | * |
||
| 63 | * @return bool If the gravatar exists or not |
||
| 64 | */ |
||
| 65 | public function validate_gravatar( $id_or_email ) { |
||
| 66 | //id or email code borrowed from wp-includes/pluggable.php |
||
| 67 | $email = ''; |
||
| 68 | if ( is_numeric( $id_or_email ) ) { |
||
| 69 | $id = (int) $id_or_email; |
||
| 70 | $user = get_userdata( $id ); |
||
| 71 | if ( $user ) { |
||
| 72 | $email = $user->user_email; |
||
| 73 | } |
||
| 74 | } elseif ( is_object( $id_or_email ) ) { |
||
| 75 | // No avatar for pingbacks or trackbacks |
||
| 76 | $allowed_comment_types = apply_filters( 'get_avatar_comment_types', array( 'comment' ) ); |
||
| 77 | if ( ! empty( $id_or_email->comment_type ) && ! in_array( $id_or_email->comment_type, (array) $allowed_comment_types ) ) { |
||
| 78 | return false; |
||
| 79 | } |
||
| 80 | |||
| 81 | if ( ! empty( $id_or_email->user_id ) ) { |
||
| 82 | $id = (int) $id_or_email->user_id; |
||
| 83 | $user = get_userdata( $id ); |
||
| 84 | if ( $user ) { |
||
| 85 | $email = $user->user_email; |
||
| 86 | } |
||
| 87 | } elseif ( ! empty( $id_or_email->comment_author_email ) ) { |
||
| 88 | $email = $id_or_email->comment_author_email; |
||
| 89 | } |
||
| 90 | } else { |
||
| 91 | $email = $id_or_email; |
||
| 92 | } |
||
| 93 | |||
| 94 | $hashkey = md5( strtolower( trim( $email ) ) ); |
||
| 95 | $uri = 'http://www.gravatar.com/avatar/' . $hashkey . '?d=404'; |
||
| 96 | |||
| 97 | $data = wp_cache_get( $hashkey ); |
||
| 98 | if ( false === $data ) { |
||
| 99 | $response = wp_remote_head( $uri ); |
||
| 100 | if ( is_wp_error( $response ) ) { |
||
| 101 | $data = 'not200'; |
||
| 102 | } else { |
||
| 103 | $data = $response['response']['code']; |
||
| 104 | } |
||
| 105 | wp_cache_set( $hashkey, $data, $group = '', $expire = 60 * 5 ); |
||
| 106 | |||
| 107 | } |
||
| 108 | if ( $data == '200' ) { |
||
| 109 | return true; |
||
| 110 | } else { |
||
| 111 | return false; |
||
| 112 | } |
||
| 113 | } |
||
| 114 | |||
| 115 | /** |
||
| 116 | * Get an array of all the log IDs using the Give Logging Class |
||
| 117 | * |
||
| 118 | * @since 1.0 |
||
| 119 | * @access public |
||
| 120 | * |
||
| 121 | * @param int $form_id Donation form id |
||
| 122 | * |
||
| 123 | * @return array IDs if logs, false otherwise |
||
| 124 | */ |
||
| 125 | public function get_log_ids( $form_id = '' ) { |
||
| 126 | |||
| 127 | // get Give_Logging class |
||
| 128 | global $give_logs; |
||
| 129 | |||
| 130 | // get log for this form |
||
| 131 | $logs = $give_logs->get_logs( $form_id ); |
||
| 132 | |||
| 133 | if ( $logs ) { |
||
| 134 | $log_ids = array(); |
||
| 135 | |||
| 136 | // make an array with all the donor IDs |
||
| 137 | foreach ( $logs as $log ) { |
||
| 138 | $log_ids[] = $log->ID; |
||
| 139 | } |
||
| 140 | |||
| 141 | return $log_ids; |
||
| 142 | } |
||
| 143 | |||
| 144 | return null; |
||
| 145 | |||
| 146 | } |
||
| 147 | |||
| 148 | /** |
||
| 149 | * Get payment ID |
||
| 150 | * |
||
| 151 | * @since 1.0 |
||
| 152 | * @access public |
||
| 153 | * |
||
| 154 | * @param int $form_id Donation form id |
||
| 155 | * |
||
| 156 | * @return mixed |
||
| 157 | */ |
||
| 158 | public function get_payment_ids( $form_id = '' ) { |
||
| 159 | |||
| 160 | $give_options = give_get_settings(); |
||
| 161 | |||
| 162 | $log_ids = $this->get_log_ids( $form_id ); |
||
| 163 | |||
| 164 | if ( $log_ids ) { |
||
| 165 | |||
| 166 | $payment_ids = array(); |
||
| 167 | |||
| 168 | foreach ( $log_ids as $id ) { |
||
| 169 | // get the payment ID for each corresponding log ID |
||
| 170 | $payment_ids[] = get_post_meta( $id, '_give_log_payment_id', true ); |
||
| 171 | } |
||
| 172 | |||
| 173 | // remove donors who have donated more than once so we can have unique avatars |
||
| 174 | $unique_emails = array(); |
||
| 175 | |||
| 176 | foreach ( $payment_ids as $key => $id ) { |
||
| 177 | |||
| 178 | $email = get_post_meta( $id, '_give_payment_user_email', true ); |
||
| 179 | |||
| 180 | if ( isset ( $give_options['give_donors_gravatars_has_gravatar_account'] ) ) { |
||
| 181 | if ( ! $this->validate_gravatar( $email ) ) { |
||
| 182 | continue; |
||
| 183 | } |
||
| 184 | } |
||
| 185 | |||
| 186 | $unique_emails[ $id ] = get_post_meta( $id, '_give_payment_user_email', true ); |
||
| 187 | |||
| 188 | } |
||
| 189 | |||
| 190 | $unique_ids = array(); |
||
| 191 | |||
| 192 | // strip duplicate emails |
||
| 193 | $unique_emails = array_unique( $unique_emails ); |
||
| 194 | |||
| 195 | // convert the unique IDs back into simple array |
||
| 196 | foreach ( $unique_emails as $id => $email ) { |
||
| 197 | $unique_ids[] = $id; |
||
| 198 | } |
||
| 199 | |||
| 200 | // randomize the payment IDs if enabled |
||
| 201 | if ( isset( $give_options['give_donors_gravatars_random_gravatars'] ) ) { |
||
| 202 | shuffle( $unique_ids ); |
||
| 203 | } |
||
| 204 | |||
| 205 | // return our unique IDs |
||
| 206 | return $unique_ids; |
||
| 207 | |||
| 208 | } |
||
| 209 | |||
| 210 | } |
||
| 211 | |||
| 212 | /** |
||
| 213 | * Gravatars |
||
| 214 | * |
||
| 215 | * @since 1.0 |
||
| 216 | * @access public |
||
| 217 | * |
||
| 218 | * @param int $form_id Donation form id. |
||
| 219 | * @param string $title Donors gravatars title. |
||
| 220 | * |
||
| 221 | * @return string |
||
| 222 | */ |
||
| 223 | public function gravatars( $form_id = false, $title = '' ) { |
||
| 224 | |||
| 225 | // unique $payment_ids |
||
| 226 | $payment_ids = $this->get_payment_ids( $form_id ); |
||
| 227 | |||
| 228 | $give_options = give_get_settings(); |
||
| 229 | |||
| 230 | // return if no ID |
||
| 231 | if ( ! $form_id ) { |
||
| 232 | return; |
||
| 233 | } |
||
| 234 | |||
| 235 | // minimum amount of donations before showing gravatars |
||
| 236 | // if the number of items in array is not greater or equal to the number specified, then exit |
||
| 237 | if ( isset( $give_options['give_donors_gravatars_min_purchases_required'] ) && '' != $give_options['give_donors_gravatars_min_purchases_required'] ) { |
||
| 238 | if ( ! ( count( $payment_ids ) >= $give_options['give_donors_gravatars_min_purchases_required'] ) ) { |
||
| 239 | return; |
||
| 240 | } |
||
| 241 | } |
||
| 242 | |||
| 243 | ob_start(); |
||
| 244 | |||
| 245 | $output = ''; |
||
| 246 | echo '<div id="give-purchase-gravatars">'; |
||
| 247 | |||
| 248 | |||
| 249 | if ( isset ( $title ) ) { |
||
| 250 | |||
| 251 | if ( $title ) { |
||
| 252 | echo apply_filters( 'give_donors_gravatars_title', '<h3 class="give-gravatars-title">' . esc_attr( $title ) . '</h3>' ); |
||
| 253 | } elseif ( isset( $give_options['give_donors_gravatars_heading'] ) ) { |
||
| 254 | echo apply_filters( 'give_donors_gravatars_title', '<h3 class="give-gravatars-title">' . esc_attr( $give_options['give_donors_gravatars_heading'] ) . '</h2>' ); |
||
| 255 | } |
||
| 256 | |||
| 257 | } |
||
| 258 | echo '<ul class="give-purchase-gravatars-list">'; |
||
| 259 | $i = 0; |
||
| 260 | |||
| 261 | if ( $payment_ids ) { |
||
| 262 | foreach ( $payment_ids as $id ) { |
||
| 263 | |||
| 264 | // Give saves a blank option even when the control is turned off, hence the extra check |
||
| 265 | if ( isset( $give_options['give_donors_gravatars_maximum_number'] ) && '' != $give_options['give_donors_gravatars_maximum_number'] && $i == $give_options['give_donors_gravatars_maximum_number'] ) { |
||
| 266 | continue; |
||
| 267 | } |
||
| 268 | |||
| 269 | // get the payment meta |
||
| 270 | $payment_meta = get_post_meta( $id, '_give_payment_meta', true ); |
||
| 271 | |||
| 272 | // unserialize the payment meta |
||
| 273 | $user_info = maybe_unserialize( $payment_meta['user_info'] ); |
||
| 274 | |||
| 275 | // get donor's first name |
||
| 276 | $name = $user_info['first_name']; |
||
| 277 | |||
| 278 | // get donor's email |
||
| 279 | $email = get_post_meta( $id, '_give_payment_user_email', true ); |
||
| 280 | |||
| 281 | // set gravatar size and provide filter |
||
| 282 | $size = isset( $give_options['give_donors_gravatars_gravatar_size'] ) ? apply_filters( 'give_donors_gravatars_gravatar_size', $give_options['give_donors_gravatars_gravatar_size'] ) : ''; |
||
| 283 | |||
| 284 | // default image |
||
| 285 | $default_image = apply_filters( 'give_donors_gravatars_gravatar_default_image', false ); |
||
| 286 | |||
| 287 | // assemble output |
||
| 288 | $output .= '<li>'; |
||
| 289 | |||
| 290 | $output .= get_avatar( $email, $size, $default_image, $name ); |
||
| 291 | $output .= '</li>'; |
||
| 292 | |||
| 293 | $i ++; |
||
| 294 | |||
| 295 | } // end foreach |
||
| 296 | } |
||
| 297 | |||
| 298 | echo $output; |
||
| 299 | echo '</ul>'; |
||
| 300 | echo '</div>'; |
||
| 301 | |||
| 302 | return apply_filters( 'give_donors_gravatars', ob_get_clean() ); |
||
| 303 | } |
||
| 304 | |||
| 305 | /** |
||
| 306 | * Register widget |
||
| 307 | * |
||
| 308 | * @since 1.0 |
||
| 309 | * @access public |
||
| 310 | * |
||
| 311 | * @return void |
||
| 312 | */ |
||
| 313 | public function register_widget() { |
||
| 314 | register_widget( 'Give_Donors_Gravatars_Widget' ); |
||
| 315 | } |
||
| 316 | |||
| 317 | /** |
||
| 318 | * Shortcode |
||
| 319 | * |
||
| 320 | * @since 1.0 |
||
| 321 | * @access public |
||
| 322 | * |
||
| 323 | * @param array $atts Shortcode attribures. |
||
| 324 | * @param string $content Shortcode content. |
||
| 325 | * |
||
| 326 | * @return string |
||
| 327 | */ |
||
| 328 | public function shortcode( $atts, $content = null ) { |
||
| 345 | |||
| 346 | /** |
||
| 347 | * Settings |
||
| 348 | * |
||
| 349 | * @since 1.0 |
||
| 350 | * @access public |
||
| 351 | * |
||
| 352 | * @param array $settings Gravatar settings. |
||
| 353 | * |
||
| 354 | * @return array Gravatar settings. |
||
| 355 | */ |
||
| 356 | public function settings( $settings ) { |
||
| 407 | |||
| 408 | } |
||
| 409 | |||
| 410 | |||
| 547 |
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.