Complex classes like Give_Batch_Donors_Export 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_Batch_Donors_Export, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 24 | class Give_Batch_Donors_Export extends Give_Batch_Export { |
||
| 25 | |||
| 26 | /** |
||
| 27 | * Our export type. Used for export-type specific filters/actions. |
||
| 28 | * |
||
| 29 | * @var string |
||
| 30 | * @since 1.5 |
||
| 31 | */ |
||
| 32 | public $export_type = 'donors'; |
||
| 33 | |||
| 34 | /** |
||
| 35 | * Form submission data |
||
| 36 | * |
||
| 37 | * @var array |
||
| 38 | * @since 1.5 |
||
| 39 | */ |
||
| 40 | private $data = array(); |
||
| 41 | |||
| 42 | /** |
||
| 43 | * Array of donor ids which is already included in csv file. |
||
| 44 | * |
||
| 45 | * @since 1.8 |
||
| 46 | * @var array |
||
| 47 | */ |
||
| 48 | private $donor_ids = array(); |
||
| 49 | |||
| 50 | /** |
||
| 51 | * Array of payment stats which is already included in csv file. |
||
| 52 | * |
||
| 53 | * @since 1.8.9 |
||
| 54 | * @var array |
||
| 55 | */ |
||
| 56 | private $payment_stats = array(); |
||
| 57 | |||
| 58 | /** |
||
| 59 | * Export query id. |
||
| 60 | * |
||
| 61 | * @since 1.8 |
||
| 62 | * @var string |
||
| 63 | */ |
||
| 64 | private $query_id = ''; |
||
| 65 | |||
| 66 | /** |
||
| 67 | * Set the properties specific to the donors export. |
||
| 68 | * |
||
| 69 | * @since 1.5 |
||
| 70 | * |
||
| 71 | * @param array $request The Form Data passed into the batch processing |
||
| 72 | */ |
||
| 73 | public function set_properties( $request ) { |
||
| 92 | |||
| 93 | |||
| 94 | /** |
||
| 95 | * Cache donor ids. |
||
| 96 | * |
||
| 97 | * @since 1.8.9 |
||
| 98 | * @access private |
||
| 99 | */ |
||
| 100 | private function cache_donor_ids() { |
||
| 111 | |||
| 112 | /** |
||
| 113 | * Set the CSV columns. |
||
| 114 | * |
||
| 115 | * @access public |
||
| 116 | * @since 1.5 |
||
| 117 | * @return array|bool $cols All the columns. |
||
| 118 | */ |
||
| 119 | public function csv_cols() { |
||
| 132 | |||
| 133 | /** |
||
| 134 | * CSV file columns. |
||
| 135 | * |
||
| 136 | * @param array $columns |
||
| 137 | * |
||
| 138 | * @return array |
||
| 139 | */ |
||
| 140 | private function get_cols( $columns ) { |
||
| 182 | |||
| 183 | /** |
||
| 184 | * Get the Export Data |
||
| 185 | * |
||
| 186 | * @access public |
||
| 187 | * @since 1.0 |
||
| 188 | * @global object $give_logs Give Logs Object. |
||
| 189 | * @return array $data The data for the CSV file. |
||
| 190 | */ |
||
| 191 | public function get_data() { |
||
| 192 | $i = 0; |
||
| 193 | |||
| 194 | $data = array(); |
||
| 195 | $cached_donor_ids = Give_Cache::get( $this->query_id, true ); |
||
| 196 | |||
| 197 | if ( ! empty( $this->form ) ) { |
||
| 198 | |||
| 199 | // Export donors for a specific donation form and also within specified timeframe |
||
| 200 | $args = array( |
||
| 201 | 'output' => 'payments', // Use 'posts' to get standard post objects |
||
| 202 | 'post_type' => array( 'give_payment' ), |
||
| 203 | 'number' => 30, |
||
| 204 | 'paged' => $this->step, |
||
| 205 | 'status' => 'publish', |
||
| 206 | 'meta_key' => '_give_payment_form_id', |
||
| 207 | 'meta_value' => absint( $this->form ), |
||
| 208 | ); |
||
| 209 | |||
| 210 | // Check for date option filter |
||
| 211 | if ( ! empty( $this->data['donor_export_start_date'] ) || ! empty( $this->data['donor_export_end_date'] ) ) { |
||
| 212 | $args['start_date'] = ! empty( $this->data['donor_export_start_date'] ) ? date( 'Y-n-d 00:00:00', strtotime( $this->data['donor_export_start_date'] ) ) : date( 'Y-n-d 23:59:59', '1970-1-01 00:00:00' ); |
||
| 213 | $args['end_date'] = ! empty( $this->data['donor_export_end_date'] ) ? date( 'Y-n-d 23:59:59', strtotime( $this->data['donor_export_end_date'] ) ) : date( 'Y-n-d 23:59:59', current_time( 'timestamp' ) ); |
||
| 214 | } |
||
| 215 | |||
| 216 | // Check for price option. |
||
| 217 | if ( null !== $this->price_id ) { |
||
| 218 | $args['meta_query'] = array( |
||
| 219 | array( |
||
| 220 | 'key' => '_give_payment_price_id', |
||
| 221 | 'value' => (int) $this->price_id, |
||
| 222 | ), |
||
| 223 | ); |
||
| 224 | } |
||
| 225 | |||
| 226 | $payments_query = new Give_Payments_Query( $args ); |
||
| 227 | $payments = $payments_query->get_payments(); |
||
| 228 | |||
| 229 | if ( $payments ) { |
||
| 230 | /* @var Give_Payment $payment */ |
||
| 231 | foreach ( $payments as $payment ) { |
||
| 232 | // Set donation sum. |
||
| 233 | $this->payment_stats[ $payment->customer_id ]['donation_sum'] = isset( $this->payment_stats[ $payment->customer_id ]['donation_sum'] ) ? |
||
| 234 | $this->payment_stats[ $payment->customer_id ]['donation_sum'] : |
||
| 235 | 0; |
||
| 236 | $this->payment_stats[ $payment->customer_id ]['donation_sum'] += $payment->total; |
||
| 237 | |||
| 238 | // Set donation count. |
||
| 239 | $this->payment_stats[ $payment->customer_id ]['donations'] = isset( $this->payment_stats[ $payment->customer_id ]['donations'] ) ? |
||
| 240 | ++ $this->payment_stats[ $payment->customer_id ]['donations'] : |
||
| 241 | 1; |
||
| 242 | |||
| 243 | // Set donation form name. |
||
| 244 | $this->payment_stats[ $payment->customer_id ]['form_title'] = $payment->form_title; |
||
| 245 | |||
| 246 | // Continue if donor already included. |
||
| 247 | if ( empty( $payment->customer_id ) || |
||
| 248 | in_array( $payment->customer_id, $cached_donor_ids ) |
||
| 249 | ) { |
||
| 250 | continue; |
||
| 251 | } |
||
| 252 | |||
| 253 | $this->donor_ids[] = $cached_donor_ids[] = $payment->customer_id; |
||
| 254 | |||
| 255 | $i ++; |
||
| 256 | } |
||
| 257 | |||
| 258 | if ( ! empty( $this->donor_ids ) ) { |
||
| 259 | foreach ( $this->donor_ids as $donor_id ) { |
||
| 260 | $donor = Give()->donors->get_donor_by( 'id', $donor_id ); |
||
| 261 | $donor->donation_form_title = $this->payment_stats[ $donor_id ]['form_title']; |
||
| 262 | $donor->purchase_count = $this->payment_stats[ $donor_id ]['donations']; |
||
| 263 | $donor->purchase_value = $this->payment_stats[ $donor_id ]['donation_sum']; |
||
| 264 | $data[] = $this->set_donor_data( $i, $data, $donor ); |
||
| 265 | } |
||
| 266 | |||
| 267 | // Cache donor ids only if admin export donor for specific form. |
||
| 268 | $this->cache_donor_ids(); |
||
| 269 | } |
||
| 270 | } |
||
| 271 | } else { |
||
| 272 | |||
| 273 | // Export all donors. |
||
| 274 | $offset = 30 * ( $this->step - 1 ); |
||
| 275 | |||
| 276 | $args = array( |
||
| 277 | 'number' => 30, |
||
| 278 | 'offset' => $offset, |
||
| 279 | ); |
||
| 280 | |||
| 281 | // Check for date option filter |
||
| 282 | if ( ! empty( $this->data['donor_export_start_date'] ) || ! empty( $this->data['donor_export_end_date'] ) ) { |
||
| 283 | $args['date'] = array( |
||
| 284 | 'start' => ! empty( $this->data['donor_export_start_date'] ) ? date( 'Y-n-d 00:00:00', strtotime( $this->data['donor_export_start_date'] ) ) : date( 'Y-n-d 23:59:59', '1970-1-01 00:00:00' ), |
||
| 285 | 'end' => ! empty( $this->data['donor_export_end_date'] ) ? date( 'Y-n-d 23:59:59', strtotime( $this->data['donor_export_end_date'] ) ) : date( 'Y-n-d 23:59:59', current_time( 'timestamp' ) ), |
||
| 286 | ); |
||
| 287 | } |
||
| 288 | |||
| 289 | $donors = Give()->donors->get_donors( $args ); |
||
| 290 | |||
| 291 | foreach ( $donors as $donor ) { |
||
| 292 | |||
| 293 | // Continue if donor already included. |
||
| 294 | if ( empty( $donor->id ) || empty( $donor->payment_ids ) ) { |
||
| 295 | continue; |
||
| 296 | } |
||
| 297 | |||
| 298 | $payment = new Give_Payment( $donor->payment_ids ); |
||
| 299 | $donor->donation_form_title = $payment->form_title; |
||
| 300 | $data[] = $this->set_donor_data( $i, $data, $donor ); |
||
| 301 | $i ++; |
||
| 302 | } |
||
| 303 | }// End if(). |
||
| 304 | |||
| 305 | $data = apply_filters( 'give_export_get_data', $data ); |
||
| 306 | $data = apply_filters( "give_export_get_data_{$this->export_type}", $data ); |
||
| 307 | |||
| 308 | return $data; |
||
| 309 | } |
||
| 310 | |||
| 311 | /** |
||
| 312 | * Return the calculated completion percentage. |
||
| 313 | * |
||
| 314 | * @since 1.5 |
||
| 315 | * @return int |
||
| 316 | */ |
||
| 317 | public function get_percentage_complete() { |
||
| 318 | |||
| 319 | $percentage = 0; |
||
| 320 | |||
| 321 | // We can't count the number when getting them for a specific form. |
||
| 322 | if ( empty( $this->form ) ) { |
||
| 323 | |||
| 324 | $total = Give()->donors->count(); |
||
| 325 | |||
| 326 | if ( $total > 0 ) { |
||
| 327 | |||
| 328 | $percentage = ( ( 30 * $this->step ) / $total ) * 100; |
||
| 329 | |||
| 330 | } |
||
| 331 | } |
||
| 332 | |||
| 333 | if ( $percentage > 100 ) { |
||
| 334 | $percentage = 100; |
||
| 335 | } |
||
| 336 | |||
| 337 | return $percentage; |
||
| 338 | } |
||
| 339 | |||
| 340 | /** |
||
| 341 | * Set Donor Data |
||
| 342 | * |
||
| 343 | * @param int $i |
||
| 344 | * @param array $data |
||
| 345 | * @param Give_Donor $donor |
||
| 346 | * |
||
| 347 | * @return mixed |
||
| 348 | */ |
||
| 349 | private function set_donor_data( $i, $data, $donor ) { |
||
| 394 | |||
| 395 | /** |
||
| 396 | * Unset the properties specific to the donors export. |
||
| 397 | * |
||
| 398 | * @param array $request |
||
| 399 | * @param Give_Batch_Export $export |
||
| 400 | */ |
||
| 401 | public function unset_properties( $request, $export ) { |
||
| 406 | } |
||
| 407 |
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.