Complex classes like GravityView_Delete_Entry 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 GravityView_Delete_Entry, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 22 | final class GravityView_Delete_Entry { |
||
| 23 | |||
| 24 | static $file; |
||
| 25 | static $instance; |
||
| 26 | var $entry; |
||
| 27 | var $form; |
||
| 28 | var $view_id; |
||
| 29 | var $is_valid = NULL; |
||
| 30 | |||
| 31 | function __construct() { |
||
| 37 | |||
| 38 | /** |
||
| 39 | * @since 1.9.2 |
||
| 40 | */ |
||
| 41 | private function add_hooks() { |
||
| 42 | |||
| 43 | add_action( 'wp', array( $this, 'process_delete' ), 10000 ); |
||
| 44 | |||
| 45 | add_filter( 'gravityview_entry_default_fields', array( $this, 'add_default_field'), 10, 3 ); |
||
| 46 | |||
| 47 | add_action( 'gravityview_before', array( $this, 'display_message' ) ); |
||
| 48 | |||
| 49 | // For the Delete Entry Link, you don't want visible to all users. |
||
| 50 | add_filter( 'gravityview_field_visibility_caps', array( $this, 'modify_visibility_caps'), 10, 5 ); |
||
| 51 | |||
| 52 | // Modify the field options based on the name of the field type |
||
| 53 | add_filter( 'gravityview_template_delete_link_options', array( $this, 'delete_link_field_options' ), 10, 5 ); |
||
| 54 | |||
| 55 | // add template path to check for field |
||
| 56 | add_filter( 'gravityview_template_paths', array( $this, 'add_template_path' ) ); |
||
| 57 | |||
| 58 | add_action( 'gravityview/edit-entry/publishing-action/after', array( $this, 'add_delete_button'), 10, 3 ); |
||
| 59 | |||
| 60 | add_action ( 'gravityview/delete-entry/deleted', array( $this, 'process_connected_posts' ), 10, 2 ); |
||
| 61 | add_action ( 'gravityview/delete-entry/trashed', array( $this, 'process_connected_posts' ), 10, 2 ); |
||
| 62 | } |
||
| 63 | |||
| 64 | /** |
||
| 65 | * Return the instantiated class object |
||
| 66 | * |
||
| 67 | * @since 1.5.1 |
||
| 68 | * @return GravityView_Delete_Entry |
||
| 69 | */ |
||
| 70 | static function getInstance() { |
||
| 78 | |||
| 79 | /** |
||
| 80 | * Include this extension templates path |
||
| 81 | * |
||
| 82 | * @since 1.5.1 |
||
| 83 | * @param array $file_paths List of template paths ordered |
||
| 84 | */ |
||
| 85 | function add_template_path( $file_paths ) { |
||
| 93 | |||
| 94 | /** |
||
| 95 | * Add "Delete Link Text" setting to the edit_link field settings |
||
| 96 | * |
||
| 97 | * @since 1.5.1 |
||
| 98 | * @param [type] $field_options [description] |
||
| 99 | * @param [type] $template_id [description] |
||
| 100 | * @param [type] $field_id [description] |
||
| 101 | * @param [type] $context [description] |
||
| 102 | * @param [type] $input_type [description] |
||
| 103 | * @return [type] [description] |
||
| 104 | */ |
||
| 105 | function delete_link_field_options( $field_options, $template_id, $field_id, $context, $input_type ) { |
||
| 133 | |||
| 134 | |||
| 135 | /** |
||
| 136 | * Add Edit Link as a default field, outside those set in the Gravity Form form |
||
| 137 | * |
||
| 138 | * @since 1.5.1 |
||
| 139 | * @param array $entry_default_fields Existing fields |
||
| 140 | * @param string|array $form form_ID or form object |
||
| 141 | * @param string $zone Either 'single', 'directory', 'header', 'footer' |
||
| 142 | */ |
||
| 143 | function add_default_field( $entry_default_fields, $form = array(), $zone = '' ) { |
||
| 153 | |||
| 154 | /** |
||
| 155 | * Add Delete Entry Link to the Add Field dialog |
||
| 156 | * @since 1.5.1 |
||
| 157 | * @param array $available_fields |
||
| 158 | */ |
||
| 159 | function add_available_field( $available_fields = array() ) { |
||
| 171 | |||
| 172 | /** |
||
| 173 | * Change wording for the Edit context to read Entry Creator |
||
| 174 | * |
||
| 175 | * @since 1.5.1 |
||
| 176 | * @param array $visibility_caps Array of capabilities to display in field dropdown. |
||
| 177 | * @param string $field_type Type of field options to render (`field` or `widget`) |
||
| 178 | * @param string $template_id Table slug |
||
| 179 | * @param float $field_id GF Field ID - Example: `3`, `5.2`, `entry_link`, `created_by` |
||
| 180 | * @param string $context What context are we in? Example: `single` or `directory` |
||
| 181 | * @param string $input_type (textarea, list, select, etc.) |
||
| 182 | * @return array Array of field options with `label`, `value`, `type`, `default` keys |
||
| 183 | */ |
||
| 184 | public function modify_visibility_caps( $visibility_caps = array(), $template_id = '', $field_id = '', $context = '', $input_type = '' ) { |
||
| 199 | |||
| 200 | /** |
||
| 201 | * Make sure there's an entry |
||
| 202 | * |
||
| 203 | * @since 1.5.1 |
||
| 204 | * @param [type] $entry [description] |
||
| 205 | */ |
||
| 206 | function set_entry( $entry = null ) { |
||
| 209 | |||
| 210 | /** |
||
| 211 | * Generate a consistent nonce key based on the Entry ID |
||
| 212 | * |
||
| 213 | * @since 1.5.1 |
||
| 214 | * @param int $entry_id Entry ID |
||
| 215 | * @return string Key used to validate request |
||
| 216 | */ |
||
| 217 | public static function get_nonce_key( $entry_id ) { |
||
| 220 | |||
| 221 | |||
| 222 | /** |
||
| 223 | * Generate a nonce link with the base URL of the current View embed |
||
| 224 | * |
||
| 225 | * We don't want to link to the single entry, because when deleted, there would be nothing to return to. |
||
| 226 | * |
||
| 227 | * @since 1.5.1 |
||
| 228 | * @param array $entry Gravity Forms entry array |
||
| 229 | * @return string|null If directory link is valid, the URL to process the delete request. Otherwise, `NULL`. |
||
| 230 | */ |
||
| 231 | public static function get_delete_link( $entry, $view_id = 0, $post_id = null ) { |
||
| 258 | |||
| 259 | |||
| 260 | /** |
||
| 261 | * Add a Delete button to the #publishing-action section of the Delete Entry form |
||
| 262 | * |
||
| 263 | * @since 1.5.1 |
||
| 264 | * @param array $form Gravity Forms form array |
||
| 265 | * @param array $entry Gravity Forms entry array |
||
| 266 | * @param int $view_id GravityView View ID |
||
| 267 | */ |
||
| 268 | function add_delete_button( $form = array(), $entry = array(), $view_id = NULL ) { |
||
| 295 | |||
| 296 | /** |
||
| 297 | * Handle the deletion request, if $_GET['action'] is set to "delete" |
||
| 298 | * |
||
| 299 | * 1. Check referrer validity |
||
| 300 | * 2. Make sure there's an entry with the slug of $_GET['entry_id'] |
||
| 301 | * 3. If so, attempt to delete the entry. If not, set the error status |
||
| 302 | * 4. Remove `action=delete` from the URL |
||
| 303 | * 5. Redirect to the page using `wp_safe_redirect()` |
||
| 304 | * |
||
| 305 | * @since 1.5.1 |
||
| 306 | * @uses wp_safe_redirect() |
||
| 307 | * @return void |
||
| 308 | */ |
||
| 309 | function process_delete() { |
||
| 310 | |||
| 311 | // If the form is submitted |
||
| 312 | if( isset( $_GET['action'] ) && 'delete' === $_GET['action'] && isset( $_GET['entry_id'] ) ) { |
||
| 313 | |||
| 314 | // Make sure it's a GravityView request |
||
| 315 | $valid_nonce_key = wp_verify_nonce( $_GET['delete'], self::get_nonce_key( $_GET['entry_id'] ) ); |
||
| 316 | |||
| 317 | if( ! $valid_nonce_key ) { |
||
| 318 | do_action('gravityview_log_debug', __METHOD__ . ' Delete entry not processed: nonce validation failed.' ); |
||
| 319 | return; |
||
| 320 | } |
||
| 321 | |||
| 322 | // Get the entry slug |
||
| 323 | $entry_slug = esc_attr( $_GET['entry_id'] ); |
||
| 324 | |||
| 325 | // See if there's an entry there |
||
| 326 | $entry = gravityview_get_entry( $entry_slug ); |
||
| 327 | |||
| 328 | if( $entry ) { |
||
| 329 | |||
| 330 | $has_permission = $this->user_can_delete_entry( $entry ); |
||
| 331 | |||
| 332 | if( is_wp_error( $has_permission ) ) { |
||
| 333 | |||
| 334 | $messages = array( |
||
| 335 | 'message' => urlencode( $has_permission->get_error_message() ), |
||
| 336 | 'status' => 'error', |
||
| 337 | ); |
||
| 338 | |||
| 339 | } else { |
||
| 340 | |||
| 341 | // Delete the entry |
||
| 342 | $delete_response = $this->delete_or_trash_entry( $entry ); |
||
| 343 | |||
| 344 | if( is_wp_error( $delete_response ) ) { |
||
| 345 | |||
| 346 | $messages = array( |
||
| 347 | 'message' => urlencode( $delete_response->get_error_message() ), |
||
| 348 | 'status' => 'error', |
||
| 349 | ); |
||
| 350 | |||
| 351 | } else { |
||
| 352 | |||
| 353 | $messages = array( |
||
| 354 | 'status' => $delete_response, |
||
| 355 | ); |
||
| 356 | |||
| 357 | } |
||
|
1 ignored issue
–
show
|
|||
| 358 | |||
| 359 | } |
||
|
1 ignored issue
–
show
|
|||
| 360 | |||
| 361 | } else { |
||
| 362 | |||
| 363 | do_action('gravityview_log_debug', __METHOD__ . ' Delete entry failed: there was no entry with the entry slug '. $entry_slug ); |
||
| 364 | |||
| 365 | $messages = array( |
||
| 366 | 'message' => urlencode( __('The entry does not exist.', 'gravityview') ), |
||
| 367 | 'status' => 'error', |
||
| 368 | ); |
||
| 369 | } |
||
| 370 | |||
| 371 | $redirect_to_base = esc_url_raw( remove_query_arg( array( 'action' ) ) ); |
||
| 372 | $redirect_to = add_query_arg( $messages, $redirect_to_base ); |
||
| 373 | |||
| 374 | wp_safe_redirect( $redirect_to ); |
||
| 375 | |||
| 376 | exit(); |
||
| 377 | |||
| 378 | } // endif action is delete. |
||
| 379 | |||
| 380 | } |
||
| 381 | |||
| 382 | /** |
||
| 383 | * Delete mode: permanently delete, or move to trash? |
||
| 384 | * |
||
| 385 | * @return string `delete` or `trash` |
||
| 386 | */ |
||
| 387 | private function get_delete_mode() { |
||
| 398 | |||
| 399 | /** |
||
| 400 | * @since 1.13.1 |
||
| 401 | * @see GFAPI::delete_entry() |
||
| 402 | * @return WP_Error|boolean GFAPI::delete_entry() returns a WP_Error on error |
||
| 403 | */ |
||
| 404 | private function delete_or_trash_entry( $entry ) { |
||
| 405 | |||
| 406 | $entry_id = $entry['id']; |
||
| 407 | |||
| 408 | $mode = $this->get_delete_mode(); |
||
| 409 | |||
| 410 | if( 'delete' === $mode ) { |
||
| 411 | |||
| 412 | do_action( 'gravityview_log_debug', __METHOD__ . ' Starting delete entry: ', $entry_id ); |
||
| 413 | |||
| 414 | // Delete the entry |
||
| 415 | $delete_response = GFAPI::delete_entry( $entry_id ); |
||
| 416 | |||
| 417 | if( ! is_wp_error( $delete_response ) ) { |
||
| 418 | $delete_response = 'deleted'; |
||
| 419 | |||
| 420 | /** |
||
| 421 | * @action `gravityview/delete-entry/deleted` Triggered when an entry is deleted |
||
| 422 | * @since 1.16.4 |
||
| 423 | * @param int $entry_id ID of the Gravity Forms entry |
||
| 424 | * @param array $entry Deleted entry array |
||
| 425 | */ |
||
| 426 | do_action( 'gravityview/delete-entry/deleted', $entry_id, $entry ); |
||
| 427 | } |
||
| 428 | |||
| 429 | do_action( 'gravityview_log_debug', __METHOD__ . ' Delete response: ', $delete_response ); |
||
| 430 | |||
| 431 | } else { |
||
| 432 | |||
| 433 | do_action( 'gravityview_log_debug', __METHOD__ . ' Starting trash entry: ', $entry_id ); |
||
| 434 | |||
| 435 | $trashed = GFAPI::update_entry_property( $entry_id, 'status', 'trash' ); |
||
| 436 | new GravityView_Cache; |
||
| 437 | |||
| 438 | if( ! $trashed ) { |
||
| 439 | $delete_response = new WP_Error( 'trash_entry_failed', __('Moving the entry to the trash failed.', 'gravityview' ) ); |
||
| 440 | } else { |
||
| 441 | |||
| 442 | /** |
||
| 443 | * @action `gravityview/delete-entry/trashed` Triggered when an entry is trashed |
||
| 444 | * @since 1.16.4 |
||
| 445 | * @param int $entry_id ID of the Gravity Forms entry |
||
| 446 | * @param array $entry Deleted entry array |
||
| 447 | */ |
||
| 448 | do_action( 'gravityview/delete-entry/trashed', $entry_id, $entry ); |
||
| 449 | |||
| 450 | $delete_response = 'trashed'; |
||
| 451 | } |
||
| 452 | |||
| 453 | do_action( 'gravityview_log_debug', __METHOD__ . ' Trashed? ', $delete_response ); |
||
| 454 | } |
||
| 455 | |||
| 456 | return $delete_response; |
||
| 457 | } |
||
| 458 | |||
| 459 | /** |
||
| 460 | * Delete or trash a post connected to an entry |
||
| 461 | * |
||
| 462 | * @since 1.17 |
||
| 463 | * |
||
| 464 | * @param int $entry_id ID of entry being deleted/trashed |
||
| 465 | * @param array $entry Array of the entry being deleted/trashed |
||
| 466 | */ |
||
| 467 | public function process_connected_posts( $entry_id = 0, $entry = array() ) { |
||
| 468 | |||
| 469 | // The entry had no connected post |
||
| 470 | if( empty( $entry['post_id'] ) ) { |
||
| 471 | return; |
||
| 472 | } |
||
| 473 | |||
| 474 | /** |
||
| 475 | * @filter `gravityview/delete-entry/delete-connected-post` Should posts connected to an entry be deleted when the entry is deleted? |
||
| 476 | * @since 1.17 |
||
| 477 | * @param boolean $delete_post If trashing an entry, trash the post. If deleting an entry, delete the post. Default: true |
||
| 478 | */ |
||
| 479 | $delete_post = apply_filters( 'gravityview/delete-entry/delete-connected-post', true ); |
||
| 480 | |||
| 481 | if( false === $delete_post ) { |
||
| 482 | return; |
||
| 483 | } |
||
| 484 | |||
| 485 | $action = current_action(); |
||
| 486 | |||
| 487 | if( 'gravityview/delete-entry/deleted' === $action ) { |
||
| 488 | $result = wp_delete_post( $entry['post_id'], true ); |
||
| 489 | } else { |
||
| 490 | $result = wp_trash_post( $entry['post_id'] ); |
||
| 491 | } |
||
| 492 | |||
| 493 | if( false === $result ) { |
||
| 494 | do_action( 'gravityview_log_error', __METHOD__ . ' (called by '.$action.'): Error processing the Post connected to the entry.', $entry ); |
||
| 495 | } else { |
||
| 496 | do_action( 'gravityview_log_debug', __METHOD__ . ' (called by '.$action.'): Successfully processed Post connected to the entry.', $entry ); |
||
| 497 | } |
||
| 498 | } |
||
| 499 | |||
| 500 | /** |
||
| 501 | * Is the current nonce valid for editing the entry? |
||
| 502 | * |
||
| 503 | * @since 1.5.1 |
||
| 504 | * @return boolean |
||
| 505 | */ |
||
| 506 | public function verify_nonce() { |
||
| 507 | |||
| 508 | // No delete entry request was made |
||
| 509 | if( empty( $_GET['entry_id'] ) || empty( $_GET['delete'] ) ) { |
||
| 510 | return false; |
||
| 511 | } |
||
| 512 | |||
| 513 | $nonce_key = self::get_nonce_key( $_GET['entry_id'] ); |
||
| 514 | |||
| 515 | $valid = wp_verify_nonce( $_GET['delete'], $nonce_key ); |
||
| 516 | |||
| 517 | /** |
||
| 518 | * @filter `gravityview/delete-entry/verify_nonce` Override Delete Entry nonce validation. Return true to declare nonce valid. |
||
| 519 | * @since 1.15.2 |
||
| 520 | * @see wp_verify_nonce() |
||
| 521 | * @param int|boolean $valid False if invalid; 1 or 2 when nonce was generated |
||
| 522 | * @param string $nonce_key Name of nonce action used in wp_verify_nonce. $_GET['delete'] holds the nonce value itself. Default: `delete_{entry_id}` |
||
| 523 | */ |
||
| 524 | $valid = apply_filters( 'gravityview/delete-entry/verify_nonce', $valid, $nonce_key ); |
||
| 525 | |||
| 526 | return $valid; |
||
| 527 | } |
||
| 528 | |||
| 529 | /** |
||
| 530 | * Get the onclick attribute for the confirm dialogs that warns users before they delete an entry |
||
| 531 | * |
||
| 532 | * @since 1.5.1 |
||
| 533 | * @return string HTML `onclick` attribute |
||
| 534 | */ |
||
| 535 | public static function get_confirm_dialog() { |
||
| 536 | |||
| 537 | $confirm = __('Are you sure you want to delete this entry? This cannot be undone.', 'gravityview'); |
||
| 538 | |||
| 539 | /** |
||
| 540 | * @filter `gravityview/delete-entry/confirm-text` Modify the Delete Entry Javascript confirmation text |
||
| 541 | * @param string $confirm Default: "Are you sure you want to delete this entry? This cannot be undone." |
||
| 542 | */ |
||
| 543 | $confirm = apply_filters( 'gravityview/delete-entry/confirm-text', $confirm ); |
||
| 544 | |||
| 545 | return 'return window.confirm(\''. esc_js( $confirm ) .'\');'; |
||
| 546 | } |
||
| 547 | |||
| 548 | /** |
||
| 549 | * Check if the user can edit the entry |
||
| 550 | * |
||
| 551 | * - Is the nonce valid? |
||
| 552 | * - Does the user have the right caps for the entry |
||
| 553 | * - Is the entry in the trash? |
||
| 554 | * |
||
| 555 | * @since 1.5.1 |
||
| 556 | * @param array $entry Gravity Forms entry array |
||
| 557 | * @return boolean|WP_Error True: can edit form. WP_Error: nope. |
||
| 558 | */ |
||
| 559 | function user_can_delete_entry( $entry = array() ) { |
||
| 588 | |||
| 589 | |||
| 590 | /** |
||
| 591 | * checks if user has permissions to view the link or delete a specific entry |
||
| 592 | * |
||
| 593 | * @since 1.5.1 |
||
| 594 | * @since 1.15 Added `$view_id` param |
||
| 595 | * |
||
| 596 | * @param array $entry Gravity Forms entry array |
||
| 597 | * @param array $field Field settings (optional) |
||
| 598 | * @param int $view_id Pass a View ID to check caps against. If not set, check against current View (optional) |
||
| 599 | * @return bool |
||
| 600 | */ |
||
| 601 | public static function check_user_cap_delete_entry( $entry, $field = array(), $view_id = 0 ) { |
||
| 678 | |||
| 679 | |||
| 680 | /** |
||
| 681 | * After processing delete entry, the user will be redirected to the referring View or embedded post/page. Display a message on redirection. |
||
| 682 | * |
||
| 683 | * If success, there will be `status` URL parameters `status=>success` |
||
| 684 | * If an error, there will be `status` and `message` URL parameters `status=>error&message=example` |
||
| 685 | * |
||
| 686 | * @since 1.15.2 Only show message when the URL parameter's View ID matches the current View ID |
||
| 687 | * @since 1.5.1 |
||
| 688 | * |
||
| 689 | * @param int $current_view_id The ID of the View being rendered |
||
| 690 | * @return void |
||
| 691 | */ |
||
| 692 | public function display_message( $current_view_id = 0 ) { |
||
| 734 | |||
| 735 | |||
| 736 | } // end class |
||
| 737 | |||
| 738 | GravityView_Delete_Entry::getInstance(); |
||
| 739 | |||
| 740 |
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.