From 302afefea2c4a97fbcd9f8831de63737058a7d90 Mon Sep 17 00:00:00 2001 From: omarkasem Date: Thu, 19 Dec 2024 19:18:28 +0200 Subject: [PATCH 01/15] Adds heartbeat ajax functions from gf, Fixes enqueue issue and Fixes Modal issue in frontend --- .../edit-entry/class-edit-entry-locking.php | 188 +++++++++++++++++- .../edit-entry/class-edit-entry.php | 2 +- 2 files changed, 183 insertions(+), 7 deletions(-) diff --git a/includes/extensions/edit-entry/class-edit-entry-locking.php b/includes/extensions/edit-entry/class-edit-entry-locking.php index 8382df6797..75da47bde6 100644 --- a/includes/extensions/edit-entry/class-edit-entry-locking.php +++ b/includes/extensions/edit-entry/class-edit-entry-locking.php @@ -28,12 +28,35 @@ public function load() { add_action( 'wp_enqueue_scripts', array( $this, 'maybe_enqueue_scripts' ) ); } + add_filter( 'heartbeat_received', array( $this, 'heartbeat_refresh_nonces' ), 10, 3 ); + add_filter( 'heartbeat_received', array( $this, 'heartbeat_check_locked_objects' ), 10, 3 ); + add_filter( 'heartbeat_received', array( $this, 'heartbeat_refresh_lock' ), 10, 3 ); + add_filter( 'heartbeat_received', array( $this, 'heartbeat_request_lock' ), 10, 3 ); + add_action( 'wp_ajax_gf_lock_request_entry', array( $this, 'ajax_lock_request' ), 1 ); add_action( 'wp_ajax_gf_reject_lock_request_entry', array( $this, 'ajax_reject_lock_request' ), 1 ); add_action( 'wp_ajax_nopriv_gf_lock_request_entry', array( $this, 'ajax_lock_request' ) ); add_action( 'wp_ajax_nopriv_gf_reject_lock_request_entry', array( $this, 'ajax_reject_lock_request' ) ); } + + protected function get_lock_request_meta( $object_id ) { + return GFCache::get( 'lock_request_entry_' . $object_id ); + } + + protected function check_lock_request( $object_id ) { + + if ( ! $user_id = $this->get_lock_request_meta( $object_id ) ) { + return false; + } + + if ( $user_id != get_current_user_id() ) { + return $user_id; + } + + return false; + } + // TODO: Convert to extending Gravity Forms public function ajax_lock_request() { $object_id = rgget( 'object_id' ); @@ -130,12 +153,8 @@ public function maybe_enqueue_scripts() { continue; } - // Make sure that the entry belongs to one of the forms connected to one of the Views in this request - $joined_forms = $view::get_joined_forms( $view->ID ); - - $entry_form_id = $entry_array['form_id']; - - if ( ! isset( $joined_forms[ $entry_form_id ] ) ) { + // Make sure that the entry belongs to the view form + if( $view->form->ID != $entry_array['form_id'] ){ continue; } @@ -164,12 +183,33 @@ public function maybe_enqueue_scripts() { */ protected function enqueue_scripts( $entry ) { + $lock_user_id = $this->check_lock( $entry['id'] ); + + // Gravity forms locking checks if #wpwrap exist in the admin dashboard, + // So we have to add the lock UI to the body before the gforms locking script is loaded. + wp_add_inline_script( 'heartbeat', ' + jQuery(document).ready(function($) { + if ($("#wpwrap").length === 0) { + var lockUI = ' . json_encode( $this->get_lock_ui( $lock_user_id ) ) . '; + $("body").prepend(lockUI); + } + }); + ', 'after' ); + + $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || isset( $_GET['gform_debug'] ) ? '' : '.min'; $locking_path = GFCommon::get_base_url() . '/includes/locking/'; wp_enqueue_script( 'gforms_locking', $locking_path . "js/locking{$min}.js", array( 'jquery', 'heartbeat' ), GFCommon::$version ); wp_enqueue_style( 'gforms_locking_css', $locking_path . "css/locking{$min}.css", array( 'edit' ), GFCommon::$version ); + // add inline css to hide notification-dialog-wrap if it has the hidden class + wp_add_inline_style( 'gforms_locking_css', ' + .notification-dialog-wrap.hidden { + display: none; + } + ' ); + $translations = array_map( 'wp_strip_all_tags', $this->get_strings() ); $strings = array( @@ -417,4 +457,140 @@ public function set_lock( $entry_id ) { return $user_id; } + + + public function heartbeat_check_locked_objects( $response, $data, $screen_id ) { + $checked = array(); + $heartbeat_key = 'gform-check-locked-objects-entry'; + if ( array_key_exists( $heartbeat_key, $data ) && is_array( $data[ $heartbeat_key ] ) ) { + foreach ( $data[ $heartbeat_key ] as $object_id ) { + if ( ( $user_id = $this->check_lock( $object_id ) ) && ( $user = get_userdata( $user_id ) ) ) { + $send = array( 'text' => sprintf( __( $this->get_string( 'currently_editing' ) ), $user->display_name ) ); + + if ( ( $avatar = get_avatar( $user->ID, 18 ) ) && preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { + $send['avatar_src'] = $matches[1]; + } + + $checked[ $object_id ] = $send; + } + } + } + + if ( ! empty( $checked ) ) { + $response[ $heartbeat_key ] = $checked; + } + + return $response; + } + + public function heartbeat_refresh_lock( $response, $data, $screen_id ) { + $heartbeat_key = 'gform-refresh-lock-entry'; + if ( array_key_exists( $heartbeat_key, $data ) ) { + $received = $data[ $heartbeat_key ]; + $send = array(); + + if ( ! isset( $received['objectID'] ) ) { + return $response; + } + + $object_id = $received['objectID']; + + if ( ( $user_id = $this->check_lock( $object_id ) ) && ( $user = get_userdata( $user_id ) ) ) { + + $error = array( + 'text' => sprintf( __( $this->get_string( 'taken_over' ) ), $user->display_name ) + ); + + if ( $avatar = get_avatar( $user->ID, 64 ) ) { + if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { + $error['avatar_src'] = $matches[1]; + } + } + + $send['lock_error'] = $error; + } else { + + if ( $new_lock = $this->set_lock( $object_id ) ) { + $send['new_lock'] = $new_lock; + + if ( ( $lock_requester = $this->check_lock_request( $object_id ) ) && ( $user = get_userdata( $lock_requester ) ) ) { + $lock_request = array( + 'text' => sprintf( __( $this->get_string( 'lock_requested' ) ), $user->display_name ) + ); + + if ( $avatar = get_avatar( $user->ID, 64 ) ) { + if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { + $lock_request['avatar_src'] = $matches[1]; + } + } + $send['lock_request'] = $lock_request; + } + } + } + + $response[ $heartbeat_key ] = $send; + } + + return $response; + } + + public function heartbeat_request_lock( $response, $data, $screen_id ) { + $heartbeat_key = 'gform-request-lock-entry'; + if ( array_key_exists( $heartbeat_key, $data ) ) { + $received = $data[ $heartbeat_key ]; + $send = array(); + + if ( ! isset( $received['objectID'] ) ) { + return $response; + } + + $object_id = $received['objectID']; + + if ( ( $user_id = $this->check_lock( $object_id ) ) && ( $user = get_userdata( $user_id ) ) ) { + if ( $this->get_lock_request_meta( $object_id ) ) { + $send['status'] = 'pending'; + } else { + $send['status'] = 'deleted'; + } + } else { + if ( $new_lock = $this->set_lock( $object_id ) ) { + $send['status'] = 'granted'; + } + } + + $response[ $heartbeat_key ] = $send; + } + + return $response; + } + + + public function heartbeat_refresh_nonces( $response, $data, $screen_id ) { + if ( array_key_exists( 'gform-refresh-nonces', $data ) ) { + $received = $data['gform-refresh-nonces']; + $response['gform-refresh-nonces'] = array( 'check' => 1 ); + + if ( ! isset( $received['objectID'] ) ) { + return $response; + } + + $object_id = $received['objectID']; + + if ( ! GFCommon::current_user_can_any( $this->_capabilities ) || empty( $received['post_nonce'] ) ) { + return $response; + } + + if ( 2 === wp_verify_nonce( $received['object_nonce'], 'update-contact_' . $object_id ) ) { + $response['gform-refresh-nonces'] = array( + 'replace' => array( + '_wpnonce' => wp_create_nonce( 'update-object_' . $object_id ), + ), + 'heartbeatNonce' => wp_create_nonce( 'heartbeat-nonce' ), + ); + } + } + + return $response; + } + } diff --git a/includes/extensions/edit-entry/class-edit-entry.php b/includes/extensions/edit-entry/class-edit-entry.php index 7c531a4f76..abb5acce2f 100644 --- a/includes/extensions/edit-entry/class-edit-entry.php +++ b/includes/extensions/edit-entry/class-edit-entry.php @@ -403,7 +403,7 @@ public static function check_user_cap_edit_entry( $entry, $view = 0 ) { $current_user = wp_get_current_user(); // User edit is disabled - if ( empty( $user_edit ) ) { + if ( $view_id && empty( $user_edit ) ) { gravityview()->log->debug( 'User Edit is disabled. Returning false.' ); From efea6752d95a36ad6ea93db39aaf1839049a36e0 Mon Sep 17 00:00:00 2001 From: omarkasem Date: Sun, 29 Dec 2024 19:39:18 +0200 Subject: [PATCH 02/15] Fixes gravatar issue and Fixes redirect to edit page --- .../edit-entry/class-edit-entry-locking.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/includes/extensions/edit-entry/class-edit-entry-locking.php b/includes/extensions/edit-entry/class-edit-entry-locking.php index 75da47bde6..8e89636a5f 100644 --- a/includes/extensions/edit-entry/class-edit-entry-locking.php +++ b/includes/extensions/edit-entry/class-edit-entry-locking.php @@ -190,7 +190,7 @@ protected function enqueue_scripts( $entry ) { wp_add_inline_script( 'heartbeat', ' jQuery(document).ready(function($) { if ($("#wpwrap").length === 0) { - var lockUI = ' . json_encode( $this->get_lock_ui( $lock_user_id ) ) . '; + var lockUI = ' . json_encode( $this->get_lock_ui( $lock_user_id, $entry ) ) . '; $("body").prepend(lockUI); } }); @@ -225,7 +225,7 @@ protected function enqueue_scripts( $entry ) { $vars = array( 'hasLock' => ! $lock_user_id ? 1 : 0, - 'lockUI' => $this->get_lock_ui( $lock_user_id ), + 'lockUI' => $this->get_lock_ui( $lock_user_id, $entry ), 'objectID' => $entry['id'], 'objectType' => 'entry', 'strings' => $strings, @@ -245,10 +245,11 @@ protected function enqueue_scripts( $entry ) { * * @param int $user_id The User ID that has the current lock. Will be empty if entry is not locked * or is locked to the current user. + * @param array $entry The entry array. * * @return string The Lock UI dialog box, etc. */ - public function get_lock_ui( $user_id ) { + public function get_lock_ui( $user_id, $entry ) { $user = get_userdata( $user_id ); $locked = $user_id && $user; @@ -256,7 +257,7 @@ public function get_lock_ui( $user_id ) { $hidden = $locked ? '' : ' hidden'; if ( $locked ) { - if ( GVCommon::has_cap( 'gravityforms_edit_entries' ) ) { + if ( GVCommon::has_cap( 'gravityforms_edit_entries' ) || $entry['created_by'] == get_current_user_id() ) { $avatar = get_avatar( $user->ID, 64 ); $person_editing_text = $user->display_name; } else { @@ -361,7 +362,7 @@ public function get_string( $string ) { public function maybe_lock_object( $entry_id ) { global $wp; - $current_url = add_query_arg( $wp->query_string, '', home_url( $wp->request ) ); + $current_url = home_url( add_query_arg( null, null ) ); if ( isset( $_GET['get-edit-lock'] ) ) { $this->set_lock( $entry_id ); @@ -373,7 +374,7 @@ public function maybe_lock_object( $entry_id ) { echo ''; exit(); } elseif ( ! $user_id = $this->check_lock( $entry_id ) ) { - $this->set_lock( $entry_id ); + $this->set_lock( $entry_id ); } } @@ -576,7 +577,7 @@ public function heartbeat_refresh_nonces( $response, $data, $screen_id ) { $object_id = $received['objectID']; - if ( ! GFCommon::current_user_can_any( $this->_capabilities ) || empty( $received['post_nonce'] ) ) { + if ( ! GVCommon::has_cap( 'gravityforms_edit_entries' ) || empty( $received['post_nonce'] ) ) { return $response; } From ad1088dde57f137511d26e86b549c62a5f1c2bbf Mon Sep 17 00:00:00 2001 From: omarkasem Date: Fri, 10 Jan 2025 23:45:03 +0200 Subject: [PATCH 03/15] Adds docblock comments to functions --- .../edit-entry/class-edit-entry-locking.php | 52 ++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/includes/extensions/edit-entry/class-edit-entry-locking.php b/includes/extensions/edit-entry/class-edit-entry-locking.php index 8e89636a5f..644e57fe2a 100644 --- a/includes/extensions/edit-entry/class-edit-entry-locking.php +++ b/includes/extensions/edit-entry/class-edit-entry-locking.php @@ -40,10 +40,24 @@ public function load() { } + /** + * Get the lock request meta for an object. + * + * @param int $object_id The object ID. + * + * @return int|null The User ID or null. + */ protected function get_lock_request_meta( $object_id ) { return GFCache::get( 'lock_request_entry_' . $object_id ); } + /** + * Check if the current user has a lock request for an object. + * + * @param int $object_id The object ID. + * + * @return int|null The User ID or null. + */ protected function check_lock_request( $object_id ) { if ( ! $user_id = $this->get_lock_request_meta( $object_id ) ) { @@ -459,7 +473,15 @@ public function set_lock( $entry_id ) { return $user_id; } - + /** + * Check if the objects are locked. + * + * @param array $response The response array. + * @param array $data The data array. + * @param string $screen_id The screen ID. + * + * @return array The response array. + */ public function heartbeat_check_locked_objects( $response, $data, $screen_id ) { $checked = array(); $heartbeat_key = 'gform-check-locked-objects-entry'; @@ -484,6 +506,15 @@ public function heartbeat_check_locked_objects( $response, $data, $screen_id ) { return $response; } + /** + * Refresh the lock for an entry. + * + * @param array $response The response array. + * @param array $data The data array. + * @param string $screen_id The screen ID. + * + * @return array The response array. + */ public function heartbeat_refresh_lock( $response, $data, $screen_id ) { $heartbeat_key = 'gform-refresh-lock-entry'; if ( array_key_exists( $heartbeat_key, $data ) ) { @@ -535,6 +566,15 @@ public function heartbeat_refresh_lock( $response, $data, $screen_id ) { return $response; } + /** + * Request the lock for an entry. + * + * @param array $response The response array. + * @param array $data The data array. + * @param string $screen_id The screen ID. + * + * @return array The response array. + */ public function heartbeat_request_lock( $response, $data, $screen_id ) { $heartbeat_key = 'gform-request-lock-entry'; if ( array_key_exists( $heartbeat_key, $data ) ) { @@ -565,7 +605,15 @@ public function heartbeat_request_lock( $response, $data, $screen_id ) { return $response; } - + /** + * Refresh the nonces for an entry. + * + * @param array $response The response array. + * @param array $data The data array. + * @param string $screen_id The screen ID. + * + * @return array The response array. + */ public function heartbeat_refresh_nonces( $response, $data, $screen_id ) { if ( array_key_exists( 'gform-refresh-nonces', $data ) ) { $received = $data['gform-refresh-nonces']; From 987635f6e97124663033b544f146926c9a44d677 Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 23 Jan 2025 15:59:37 -0500 Subject: [PATCH 04/15] Format code --- .../edit-entry/class-edit-entry-locking.php | 104 +++++++++--------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/includes/extensions/edit-entry/class-edit-entry-locking.php b/includes/extensions/edit-entry/class-edit-entry-locking.php index 644e57fe2a..7dabc5bdae 100644 --- a/includes/extensions/edit-entry/class-edit-entry-locking.php +++ b/includes/extensions/edit-entry/class-edit-entry-locking.php @@ -17,26 +17,26 @@ class GravityView_Edit_Entry_Locking { * * DO NOT RENAME this method. Required by the class-edit-entry.php component loader. * - * @see GravityView_Edit_Entry::load_components() - * * @since 2.5.2 * + * @see GravityView_Edit_Entry::load_components() + * * @return void */ public function load() { - if ( ! has_action( 'wp_enqueue_scripts', array( $this, 'maybe_enqueue_scripts' ) ) ) { - add_action( 'wp_enqueue_scripts', array( $this, 'maybe_enqueue_scripts' ) ); + if ( ! has_action( 'wp_enqueue_scripts', [ $this, 'maybe_enqueue_scripts' ] ) ) { + add_action( 'wp_enqueue_scripts', [ $this, 'maybe_enqueue_scripts' ] ); } - add_filter( 'heartbeat_received', array( $this, 'heartbeat_refresh_nonces' ), 10, 3 ); - add_filter( 'heartbeat_received', array( $this, 'heartbeat_check_locked_objects' ), 10, 3 ); - add_filter( 'heartbeat_received', array( $this, 'heartbeat_refresh_lock' ), 10, 3 ); - add_filter( 'heartbeat_received', array( $this, 'heartbeat_request_lock' ), 10, 3 ); + add_filter( 'heartbeat_received', [ $this, 'heartbeat_refresh_nonces' ], 10, 3 ); + add_filter( 'heartbeat_received', [ $this, 'heartbeat_check_locked_objects' ], 10, 3 ); + add_filter( 'heartbeat_received', [ $this, 'heartbeat_refresh_lock' ], 10, 3 ); + add_filter( 'heartbeat_received', [ $this, 'heartbeat_request_lock' ], 10, 3 ); - add_action( 'wp_ajax_gf_lock_request_entry', array( $this, 'ajax_lock_request' ), 1 ); - add_action( 'wp_ajax_gf_reject_lock_request_entry', array( $this, 'ajax_reject_lock_request' ), 1 ); - add_action( 'wp_ajax_nopriv_gf_lock_request_entry', array( $this, 'ajax_lock_request' ) ); - add_action( 'wp_ajax_nopriv_gf_reject_lock_request_entry', array( $this, 'ajax_reject_lock_request' ) ); + add_action( 'wp_ajax_gf_lock_request_entry', [ $this, 'ajax_lock_request' ], 1 ); + add_action( 'wp_ajax_gf_reject_lock_request_entry', [ $this, 'ajax_reject_lock_request' ], 1 ); + add_action( 'wp_ajax_nopriv_gf_lock_request_entry', [ $this, 'ajax_lock_request' ] ); + add_action( 'wp_ajax_nopriv_gf_reject_lock_request_entry', [ $this, 'ajax_reject_lock_request' ] ); } @@ -102,7 +102,7 @@ protected function request_lock( $object_id ) { $lock_holder_user_id = $this->check_lock( $object_id ); - $result = array(); + $result = []; if ( ! $lock_holder_user_id ) { $this->set_lock( $object_id ); $result['html'] = __( 'You now have control', 'gk-gravityview' ); @@ -168,7 +168,7 @@ public function maybe_enqueue_scripts() { } // Make sure that the entry belongs to the view form - if( $view->form->ID != $entry_array['form_id'] ){ + if ( $view->form->ID != $entry_array['form_id'] ) { continue; } @@ -214,8 +214,8 @@ protected function enqueue_scripts( $entry ) { $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || isset( $_GET['gform_debug'] ) ? '' : '.min'; $locking_path = GFCommon::get_base_url() . '/includes/locking/'; - wp_enqueue_script( 'gforms_locking', $locking_path . "js/locking{$min}.js", array( 'jquery', 'heartbeat' ), GFCommon::$version ); - wp_enqueue_style( 'gforms_locking_css', $locking_path . "css/locking{$min}.css", array( 'edit' ), GFCommon::$version ); + wp_enqueue_script( 'gforms_locking', $locking_path . "js/locking{$min}.js", [ 'jquery', 'heartbeat' ], GFCommon::$version ); + wp_enqueue_style( 'gforms_locking_css', $locking_path . "css/locking{$min}.css", [ 'edit' ], GFCommon::$version ); // add inline css to hide notification-dialog-wrap if it has the hidden class wp_add_inline_style( 'gforms_locking_css', ' @@ -226,24 +226,24 @@ protected function enqueue_scripts( $entry ) { $translations = array_map( 'wp_strip_all_tags', $this->get_strings() ); - $strings = array( + $strings = [ 'noResponse' => $translations['no_response'], 'requestAgain' => $translations['request_again'], 'requestError' => $translations['request_error'], 'gainedControl' => $translations['gained_control'], 'rejected' => $translations['request_rejected'], 'pending' => $translations['request_pending'], - ); + ]; $lock_user_id = $this->check_lock( $entry['id'] ); - $vars = array( + $vars = [ 'hasLock' => ! $lock_user_id ? 1 : 0, 'lockUI' => $this->get_lock_ui( $lock_user_id, $entry ), 'objectID' => $entry['id'], 'objectType' => 'entry', 'strings' => $strings, - ); + ]; wp_localize_script( 'gforms_locking', 'gflockingVars', $vars ); } @@ -255,11 +255,11 @@ protected function enqueue_scripts( $entry ) { * * @since 2.5.2 * - * @see GravityView_Edit_Entry_Locking::check_lock + * @see GravityView_Edit_Entry_Locking::check_lock * - * @param int $user_id The User ID that has the current lock. Will be empty if entry is not locked - * or is locked to the current user. - * @param array $entry The entry array. + * @param int $user_id The User ID that has the current lock. Will be empty if entry is not locked + * or is locked to the current user. + * @param array $entry The entry array. * * @return string The Lock UI dialog box, etc. */ @@ -308,7 +308,7 @@ public function get_lock_ui( $user_id, $entry ) { '; } - $html = '
+ $html = '
'; $html .= $message; @@ -329,7 +329,7 @@ public function get_lock_ui( $user_id, $entry ) { * @return array An array of translations. */ public function get_strings() { - $translations = array( + $translations = [ 'currently_locked' => __( 'This entry is currently locked. Click on the "Request Control" button to let %s know you\'d like to take over.', 'gk-gravityview' ), 'currently_editing' => __( '%s is currently editing this entry', 'gk-gravityview' ), 'taken_over' => __( '%s has taken over and is currently editing this entry.', 'gk-gravityview' ), @@ -342,7 +342,7 @@ public function get_strings() { 'request_again' => __( 'Request again', 'gk-gravityview' ), 'request_error' => __( 'Error', 'gk-gravityview' ), 'request_rejected' => __( 'Your request was rejected', 'gk-gravityview' ), - ); + ]; $translations = array_map( 'wp_strip_all_tags', $translations ); @@ -421,6 +421,8 @@ public function check_lock( $entry_id ) { * @return int|null The User ID or null. */ public function get_lock_meta( $entry_id ) { + ray()->trace(); + return GFCache::get( 'lock_entry_' . $entry_id ); } @@ -428,7 +430,7 @@ public function get_lock_meta( $entry_id ) { * Set the lock for an entry. * * @param int $entry_id The entry ID. - * @param int $user_id The user ID to lock the entry to. + * @param int $user_id The user ID to lock the entry to. * * @return void */ @@ -476,19 +478,19 @@ public function set_lock( $entry_id ) { /** * Check if the objects are locked. * - * @param array $response The response array. - * @param array $data The data array. + * @param array $response The response array. + * @param array $data The data array. * @param string $screen_id The screen ID. * * @return array The response array. */ public function heartbeat_check_locked_objects( $response, $data, $screen_id ) { - $checked = array(); + $checked = []; $heartbeat_key = 'gform-check-locked-objects-entry'; if ( array_key_exists( $heartbeat_key, $data ) && is_array( $data[ $heartbeat_key ] ) ) { foreach ( $data[ $heartbeat_key ] as $object_id ) { if ( ( $user_id = $this->check_lock( $object_id ) ) && ( $user = get_userdata( $user_id ) ) ) { - $send = array( 'text' => sprintf( __( $this->get_string( 'currently_editing' ) ), $user->display_name ) ); + $send = [ 'text' => sprintf( __( $this->get_string( 'currently_editing' ) ), $user->display_name ) ]; if ( ( $avatar = get_avatar( $user->ID, 18 ) ) && preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { $send['avatar_src'] = $matches[1]; @@ -509,8 +511,8 @@ public function heartbeat_check_locked_objects( $response, $data, $screen_id ) { /** * Refresh the lock for an entry. * - * @param array $response The response array. - * @param array $data The data array. + * @param array $response The response array. + * @param array $data The data array. * @param string $screen_id The screen ID. * * @return array The response array. @@ -519,7 +521,7 @@ public function heartbeat_refresh_lock( $response, $data, $screen_id ) { $heartbeat_key = 'gform-refresh-lock-entry'; if ( array_key_exists( $heartbeat_key, $data ) ) { $received = $data[ $heartbeat_key ]; - $send = array(); + $send = []; if ( ! isset( $received['objectID'] ) ) { return $response; @@ -529,9 +531,9 @@ public function heartbeat_refresh_lock( $response, $data, $screen_id ) { if ( ( $user_id = $this->check_lock( $object_id ) ) && ( $user = get_userdata( $user_id ) ) ) { - $error = array( - 'text' => sprintf( __( $this->get_string( 'taken_over' ) ), $user->display_name ) - ); + $error = [ + 'text' => sprintf( __( $this->get_string( 'taken_over' ) ), $user->display_name ), + ]; if ( $avatar = get_avatar( $user->ID, 64 ) ) { if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { @@ -546,9 +548,9 @@ public function heartbeat_refresh_lock( $response, $data, $screen_id ) { $send['new_lock'] = $new_lock; if ( ( $lock_requester = $this->check_lock_request( $object_id ) ) && ( $user = get_userdata( $lock_requester ) ) ) { - $lock_request = array( - 'text' => sprintf( __( $this->get_string( 'lock_requested' ) ), $user->display_name ) - ); + $lock_request = [ + 'text' => sprintf( __( $this->get_string( 'lock_requested' ) ), $user->display_name ), + ]; if ( $avatar = get_avatar( $user->ID, 64 ) ) { if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { @@ -569,8 +571,8 @@ public function heartbeat_refresh_lock( $response, $data, $screen_id ) { /** * Request the lock for an entry. * - * @param array $response The response array. - * @param array $data The data array. + * @param array $response The response array. + * @param array $data The data array. * @param string $screen_id The screen ID. * * @return array The response array. @@ -579,7 +581,7 @@ public function heartbeat_request_lock( $response, $data, $screen_id ) { $heartbeat_key = 'gform-request-lock-entry'; if ( array_key_exists( $heartbeat_key, $data ) ) { $received = $data[ $heartbeat_key ]; - $send = array(); + $send = []; if ( ! isset( $received['objectID'] ) ) { return $response; @@ -608,8 +610,8 @@ public function heartbeat_request_lock( $response, $data, $screen_id ) { /** * Refresh the nonces for an entry. * - * @param array $response The response array. - * @param array $data The data array. + * @param array $response The response array. + * @param array $data The data array. * @param string $screen_id The screen ID. * * @return array The response array. @@ -617,7 +619,7 @@ public function heartbeat_request_lock( $response, $data, $screen_id ) { public function heartbeat_refresh_nonces( $response, $data, $screen_id ) { if ( array_key_exists( 'gform-refresh-nonces', $data ) ) { $received = $data['gform-refresh-nonces']; - $response['gform-refresh-nonces'] = array( 'check' => 1 ); + $response['gform-refresh-nonces'] = [ 'check' => 1 ]; if ( ! isset( $received['objectID'] ) ) { return $response; @@ -630,12 +632,12 @@ public function heartbeat_refresh_nonces( $response, $data, $screen_id ) { } if ( 2 === wp_verify_nonce( $received['object_nonce'], 'update-contact_' . $object_id ) ) { - $response['gform-refresh-nonces'] = array( - 'replace' => array( + $response['gform-refresh-nonces'] = [ + 'replace' => [ '_wpnonce' => wp_create_nonce( 'update-object_' . $object_id ), - ), + ], 'heartbeatNonce' => wp_create_nonce( 'heartbeat-nonce' ), - ); + ]; } } From 2f56acb0eff9ca84fcca9f47a4d5f7fc1f41a19f Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 23 Jan 2025 16:24:41 -0500 Subject: [PATCH 05/15] Update docblocks and simplify code in some places --- .../edit-entry/class-edit-entry-locking.php | 299 ++++++++++-------- 1 file changed, 162 insertions(+), 137 deletions(-) diff --git a/includes/extensions/edit-entry/class-edit-entry-locking.php b/includes/extensions/edit-entry/class-edit-entry-locking.php index 7dabc5bdae..b7bdf770a2 100644 --- a/includes/extensions/edit-entry/class-edit-entry-locking.php +++ b/includes/extensions/edit-entry/class-edit-entry-locking.php @@ -1,6 +1,10 @@ get_lock_request_meta( $object_id ) ) { - return false; - } - - if ( $user_id != get_current_user_id() ) { - return $user_id; - } - - return false; - } - // TODO: Convert to extending Gravity Forms public function ajax_lock_request() { $object_id = rgget( 'object_id' ); @@ -153,7 +139,7 @@ public function maybe_enqueue_scripts() { return; } - $views = \GV\View_Collection::from_post( $post ); + $views = View_Collection::from_post( $post ); $entry_array = $entry->as_entry(); @@ -161,7 +147,6 @@ public function maybe_enqueue_scripts() { // If any Views being loaded have entry locking, enqueue the scripts foreach ( $views->all() as $view ) { - // Make sure the View has edit locking enabled if ( ! $view->settings->get( 'edit_locking' ) ) { continue; @@ -185,7 +170,7 @@ public function maybe_enqueue_scripts() { } /** - * Enqueue the required scripts and styles from Gravity Forms. + * Enqueues the required scripts and styles from Gravity Forms. * * Called via load() and `wp_enqueue_scripts` * @@ -196,7 +181,6 @@ public function maybe_enqueue_scripts() { * @return void */ protected function enqueue_scripts( $entry ) { - $lock_user_id = $this->check_lock( $entry['id'] ); // Gravity forms locking checks if #wpwrap exist in the admin dashboard, @@ -208,8 +192,7 @@ protected function enqueue_scripts( $entry ) { $("body").prepend(lockUI); } }); - ', 'after' ); - + '); $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || isset( $_GET['gform_debug'] ) ? '' : '.min'; $locking_path = GFCommon::get_base_url() . '/includes/locking/'; @@ -222,7 +205,7 @@ protected function enqueue_scripts( $entry ) { .notification-dialog-wrap.hidden { display: none; } - ' ); + '); $translations = array_map( 'wp_strip_all_tags', $this->get_strings() ); @@ -251,7 +234,7 @@ protected function enqueue_scripts( $entry ) { /** * Returns a string with the Lock UI HTML markup. * - * Called script enqueuing, added to JavaScript gforms_locking global variable. + * Called script enqueuing, added to JavaScript `gforms_locking` global variable. * * @since 2.5.2 * @@ -269,8 +252,8 @@ public function get_lock_ui( $user_id, $entry ) { $locked = $user_id && $user; $hidden = $locked ? '' : ' hidden'; - if ( $locked ) { + if ( $locked ) { if ( GVCommon::has_cap( 'gravityforms_edit_entries' ) || $entry['created_by'] == get_current_user_id() ) { $avatar = get_avatar( $user->ID, 64 ); $person_editing_text = $user->display_name; @@ -284,7 +267,6 @@ public function get_lock_ui( $user_id, $entry ) {
' . $avatar . '

' . esc_html( sprintf( $this->get_string( 'currently_locked' ), $person_editing_text ) ) . '

- ' . esc_html( $this->get_string( 'cancel' ) ) . ' @@ -293,9 +275,7 @@ public function get_lock_ui( $user_id, $entry ) {

'; - } else { - $message = '

@@ -308,21 +288,17 @@ public function get_lock_ui( $user_id, $entry ) {

'; } + $html = '
-
'; - $html .= $message; - - $html .= '
-
'; +
' . $message . '
'; + $html .= '
'; return $html; } /** - * Localized string for the UI. - * - * Uses gravityforms textdomain unchanged. + * Returns localized text strings used in the UI. * * @since 2.5.2 * @@ -350,84 +326,107 @@ public function get_strings() { } /** - * Get a localized string. + * Returns a localized string. * * @param string $string The string to get. * * @return string A localized string. See self::get_strings() */ public function get_string( $string ) { - return \GV\Utils::get( $this->get_strings(), $string, '' ); + return Utils::get( $this->get_strings(), $string, '' ); } /** - * Lock the entry... maybe. + * Locks the entry... maybe. * * Has 3 modes of locking: - * * - acquire (get), which reloads the page after locking the entry * - release, which reloads the page after unlocking the entry * - default action to lock on load if not locked * + * @since 2.34 + * * @param int $entry_id The entry ID. * * @return void */ public function maybe_lock_object( $entry_id ) { - global $wp; - $current_url = home_url( add_query_arg( null, null ) ); if ( isset( $_GET['get-edit-lock'] ) ) { $this->set_lock( $entry_id ); + echo ''; + exit(); } elseif ( isset( $_GET['release-edit-lock'] ) ) { $this->delete_lock_meta( $entry_id ); + $current_url = remove_query_arg( 'edit', $current_url ); + echo ''; + exit(); - } elseif ( ! $user_id = $this->check_lock( $entry_id ) ) { + } elseif ( ! $this->check_lock( $entry_id ) ) { $this->set_lock( $entry_id ); } } /** - * Is this entry locked to some other user? + * Checks if this entry is locked to some other user. + * + * @since TBD * * @param int $entry_id The entry ID. * * @return boolean Yes or no. */ public function check_lock( $entry_id ) { - if ( ! $user_id = $this->get_lock_meta( $entry_id ) ) { + $user_id = $this->get_lock_meta( $entry_id ); + + if ( ! $user_id || $user_id == get_current_user_id() ) { return false; } - if ( $user_id != get_current_user_id() ) { - return $user_id; + return $user_id; + } + + /** + * Check if the current user has a lock request for an object. + * + * @since TBD + * + * @param int $object_id The object ID. + * + * @return int|false The User ID or false. + */ + protected function check_lock_request( $object_id ) { + $user_id = (int) $this->get_lock_request_meta( $object_id ); + + if ( ! $user_id || $user_id === get_current_user_id() ) { + return false; } - return false; + return $user_id; } /** - * The lock for an entry. + * Returns the lock status by leveraging GF's persistent caching mechanism. * - * Leverages Gravity Forms' persistent caching mechanisms. + * @since TBD * * @param int $entry_id The entry ID. * * @return int|null The User ID or null. */ public function get_lock_meta( $entry_id ) { - ray()->trace(); - - return GFCache::get( 'lock_entry_' . $entry_id ); + return GFCache::get( $this->get_lock_cache_key_for_entry( $entry_id ) ); } /** - * Set the lock for an entry. + * Sets the lock for an entry. + * + * @since TBD * * @param int $entry_id The entry ID. * @param int $user_id The user ID to lock the entry to. @@ -435,22 +434,37 @@ public function get_lock_meta( $entry_id ) { * @return void */ public function update_lock_meta( $entry_id, $user_id ) { - GFCache::set( 'lock_entry_' . $entry_id, $user_id, true, 1500 ); + GFCache::set( $this->get_lock_cache_key_for_entry( $entry_id ), $user_id, true, 1500 ); } /** - * Release the lock for an entry. + * Returns the cache key used to retrieve/save the lock status for an entry. + * + * @since TBD + * + * @param int $entry_id + * + * @return string + */ + public function get_lock_cache_key_for_entry( $entry_id ) { + return self::LOCK_CACHE_KEY_PREFIX . $entry_id; + } + + /** + * Releases the lock for an entry. + * + * @since TBD * * @param int $entry_id The entry ID. * * @return void */ public function delete_lock_meta( $entry_id ) { - GFCache::delete( 'lock_entry_' . $entry_id ); + GFCache::delete( $this->get_lock_cache_key_for_entry( $entry_id ) ); } /** - * Lock the entry to the current user. + * Locks the entry to the current user. * * @since 2.5.2 * @@ -459,7 +473,6 @@ public function delete_lock_meta( $entry_id ) { * @return int|false Locked or not. */ public function set_lock( $entry_id ) { - $entry = GFAPI::get_entry( $entry_id ); if ( ! GravityView_Edit_Entry::check_user_cap_edit_entry( $entry ) ) { @@ -476,17 +489,20 @@ public function set_lock( $entry_id ) { } /** - * Check if the objects are locked. + * Checks if the objects are locked. * - * @param array $response The response array. - * @param array $data The data array. - * @param string $screen_id The screen ID. + * @since TBD + * + * @param array $response The response array. + * @param array $data The data array. * * @return array The response array. */ - public function heartbeat_check_locked_objects( $response, $data, $screen_id ) { - $checked = []; + public function heartbeat_check_locked_objects( $response, $data ) { + $checked = []; + $heartbeat_key = 'gform-check-locked-objects-entry'; + if ( array_key_exists( $heartbeat_key, $data ) && is_array( $data[ $heartbeat_key ] ) ) { foreach ( $data[ $heartbeat_key ] as $object_id ) { if ( ( $user_id = $this->check_lock( $object_id ) ) && ( $user = get_userdata( $user_id ) ) ) { @@ -509,19 +525,22 @@ public function heartbeat_check_locked_objects( $response, $data, $screen_id ) { } /** - * Refresh the lock for an entry. + * Refreshes the lock for an entry. * - * @param array $response The response array. - * @param array $data The data array. - * @param string $screen_id The screen ID. + * @since TBD + * + * @param array $response The response array. + * @param array $data The data array. * * @return array The response array. */ - public function heartbeat_refresh_lock( $response, $data, $screen_id ) { + public function heartbeat_refresh_lock( $response, $data ) { $heartbeat_key = 'gform-refresh-lock-entry'; + if ( array_key_exists( $heartbeat_key, $data ) ) { $received = $data[ $heartbeat_key ]; - $send = []; + + $send = []; if ( ! isset( $received['objectID'] ) ) { return $response; @@ -530,35 +549,32 @@ public function heartbeat_refresh_lock( $response, $data, $screen_id ) { $object_id = $received['objectID']; if ( ( $user_id = $this->check_lock( $object_id ) ) && ( $user = get_userdata( $user_id ) ) ) { - $error = [ 'text' => sprintf( __( $this->get_string( 'taken_over' ) ), $user->display_name ), ]; - if ( $avatar = get_avatar( $user->ID, 64 ) ) { - if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { - $error['avatar_src'] = $matches[1]; - } + $avatar = get_avatar( $user->ID, 64 ); + + if ( $avatar && preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { + $error['avatar_src'] = $matches[1]; } $send['lock_error'] = $error; - } else { + } elseif ( $new_lock = $this->set_lock( $object_id ) ) { + $send['new_lock'] = $new_lock; - if ( $new_lock = $this->set_lock( $object_id ) ) { - $send['new_lock'] = $new_lock; + if ( ( $lock_requester = $this->check_lock_request( $object_id ) ) && ( $user = get_userdata( $lock_requester ) ) ) { + $lock_request = [ + 'text' => sprintf( __( $this->get_string( 'lock_requested' ) ), $user->display_name ), + ]; - if ( ( $lock_requester = $this->check_lock_request( $object_id ) ) && ( $user = get_userdata( $lock_requester ) ) ) { - $lock_request = [ - 'text' => sprintf( __( $this->get_string( 'lock_requested' ) ), $user->display_name ), - ]; + $avatar = get_avatar( $user->ID, 64 ); - if ( $avatar = get_avatar( $user->ID, 64 ) ) { - if ( preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { - $lock_request['avatar_src'] = $matches[1]; - } - } - $send['lock_request'] = $lock_request; + if ( $avatar && preg_match( "|src='([^']+)'|", $avatar, $matches ) ) { + $lock_request['avatar_src'] = $matches[1]; } + + $send['lock_request'] = $lock_request; } } @@ -569,7 +585,9 @@ public function heartbeat_refresh_lock( $response, $data, $screen_id ) { } /** - * Request the lock for an entry. + * Requests the lock for an entry. + * + * @since TBD * * @param array $response The response array. * @param array $data The data array. @@ -577,38 +595,44 @@ public function heartbeat_refresh_lock( $response, $data, $screen_id ) { * * @return array The response array. */ - public function heartbeat_request_lock( $response, $data, $screen_id ) { + public function heartbeat_request_lock( $response, $data ) { $heartbeat_key = 'gform-request-lock-entry'; - if ( array_key_exists( $heartbeat_key, $data ) ) { - $received = $data[ $heartbeat_key ]; - $send = []; - if ( ! isset( $received['objectID'] ) ) { - return $response; - } + if ( ! array_key_exists( $heartbeat_key, $data ) ) { + return $response; + } - $object_id = $received['objectID']; + $received = $data[ $heartbeat_key ]; - if ( ( $user_id = $this->check_lock( $object_id ) ) && ( $user = get_userdata( $user_id ) ) ) { - if ( $this->get_lock_request_meta( $object_id ) ) { - $send['status'] = 'pending'; - } else { - $send['status'] = 'deleted'; - } + $send = []; + + if ( ! isset( $received['objectID'] ) ) { + return $response; + } + + $object_id = $received['objectID']; + + if ( ( $user_id = $this->check_lock( $object_id ) ) && ( $user = get_userdata( $user_id ) ) ) { + if ( $this->get_lock_request_meta( $object_id ) ) { + $send['status'] = 'pending'; } else { - if ( $new_lock = $this->set_lock( $object_id ) ) { - $send['status'] = 'granted'; - } + $send['status'] = 'deleted'; + } + } else { + if ( $this->set_lock( $object_id ) ) { + $send['status'] = 'granted'; } - - $response[ $heartbeat_key ] = $send; } + $response[ $heartbeat_key ] = $send; + return $response; } /** - * Refresh the nonces for an entry. + * Refreshes nonces for an entry. + * + * @since TBD * * @param array $response The response array. * @param array $data The data array. @@ -617,31 +641,32 @@ public function heartbeat_request_lock( $response, $data, $screen_id ) { * @return array The response array. */ public function heartbeat_refresh_nonces( $response, $data, $screen_id ) { - if ( array_key_exists( 'gform-refresh-nonces', $data ) ) { - $received = $data['gform-refresh-nonces']; - $response['gform-refresh-nonces'] = [ 'check' => 1 ]; + if ( ! array_key_exists( 'gform-refresh-nonces', $data ) ) { + return $response; + } + $received = $data['gform-refresh-nonces']; - if ( ! isset( $received['objectID'] ) ) { - return $response; - } + $response['gform-refresh-nonces'] = [ 'check' => 1 ]; - $object_id = $received['objectID']; + if ( ! isset( $received['objectID'] ) ) { + return $response; + } - if ( ! GVCommon::has_cap( 'gravityforms_edit_entries' ) || empty( $received['post_nonce'] ) ) { - return $response; - } + $object_id = $received['objectID']; - if ( 2 === wp_verify_nonce( $received['object_nonce'], 'update-contact_' . $object_id ) ) { - $response['gform-refresh-nonces'] = [ - 'replace' => [ - '_wpnonce' => wp_create_nonce( 'update-object_' . $object_id ), - ], - 'heartbeatNonce' => wp_create_nonce( 'heartbeat-nonce' ), - ]; - } + if ( ! GVCommon::has_cap( 'gravityforms_edit_entries' ) || empty( $received['post_nonce'] ) ) { + return $response; + } + + if ( 2 === wp_verify_nonce( $received['object_nonce'], 'update-contact_' . $object_id ) ) { + $response['gform-refresh-nonces'] = [ + 'replace' => [ + '_wpnonce' => wp_create_nonce( 'update-object_' . $object_id ), + ], + 'heartbeatNonce' => wp_create_nonce( 'heartbeat-nonce' ), + ]; } return $response; } - } From ee8b9b53dc04a867deb99eda3a78b7118f65726f Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 23 Jan 2025 16:41:49 -0500 Subject: [PATCH 06/15] Do not enqueue scripts if user can't edit entries There is no reason to show the lock message on top of the "you do not have permission to edit this entry" message. --- includes/extensions/edit-entry/class-edit-entry-locking.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/includes/extensions/edit-entry/class-edit-entry-locking.php b/includes/extensions/edit-entry/class-edit-entry-locking.php index b7bdf770a2..84330908b1 100644 --- a/includes/extensions/edit-entry/class-edit-entry-locking.php +++ b/includes/extensions/edit-entry/class-edit-entry-locking.php @@ -157,6 +157,10 @@ public function maybe_enqueue_scripts() { continue; } + if ( ! GravityView_Edit_Entry::check_user_cap_edit_entry( $entry_array, $view ) ) { + continue; + } + $continue_enqueuing = true; break; From e20ddfe66a1b9494009967325abd6cf13cebdbd6 Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 23 Jan 2025 16:52:09 -0500 Subject: [PATCH 07/15] Simplify code --- .../edit-entry/class-edit-entry-locking.php | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/includes/extensions/edit-entry/class-edit-entry-locking.php b/includes/extensions/edit-entry/class-edit-entry-locking.php index 84330908b1..1af904257a 100644 --- a/includes/extensions/edit-entry/class-edit-entry-locking.php +++ b/includes/extensions/edit-entry/class-edit-entry-locking.php @@ -33,7 +33,7 @@ public function load() { add_action( 'wp_enqueue_scripts', [ $this, 'maybe_enqueue_scripts' ] ); } - add_filter( 'heartbeat_received', [ $this, 'heartbeat_refresh_nonces' ], 10, 3 ); + add_filter( 'heartbeat_received', [ $this, 'heartbeat_refresh_nonces' ], 10, 2 ); add_filter( 'heartbeat_received', [ $this, 'heartbeat_check_locked_objects' ], 10, 2 ); add_filter( 'heartbeat_received', [ $this, 'heartbeat_refresh_lock' ], 10, 2 ); add_filter( 'heartbeat_received', [ $this, 'heartbeat_request_lock' ], 10, 2 ); @@ -196,7 +196,7 @@ protected function enqueue_scripts( $entry ) { $("body").prepend(lockUI); } }); - '); + ' ); $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || isset( $_GET['gform_debug'] ) ? '' : '.min'; $locking_path = GFCommon::get_base_url() . '/includes/locking/'; @@ -209,7 +209,7 @@ protected function enqueue_scripts( $entry ) { .notification-dialog-wrap.hidden { display: none; } - '); + ' ); $translations = array_map( 'wp_strip_all_tags', $this->get_strings() ); @@ -616,16 +616,12 @@ public function heartbeat_request_lock( $response, $data ) { $object_id = $received['objectID']; - if ( ( $user_id = $this->check_lock( $object_id ) ) && ( $user = get_userdata( $user_id ) ) ) { - if ( $this->get_lock_request_meta( $object_id ) ) { - $send['status'] = 'pending'; - } else { - $send['status'] = 'deleted'; - } - } else { - if ( $this->set_lock( $object_id ) ) { - $send['status'] = 'granted'; - } + $user_id = $this->check_lock( $object_id ); + + if ( $user_id && get_userdata( $user_id ) ) { + $send['status'] = $this->get_lock_request_meta( $object_id ) ? 'pending' : 'deleted'; + } elseif ( $this->set_lock( $object_id ) ) { + $send['status'] = 'granted'; } $response[ $heartbeat_key ] = $send; @@ -640,14 +636,14 @@ public function heartbeat_request_lock( $response, $data ) { * * @param array $response The response array. * @param array $data The data array. - * @param string $screen_id The screen ID. * * @return array The response array. */ - public function heartbeat_refresh_nonces( $response, $data, $screen_id ) { + public function heartbeat_refresh_nonces( $response, $data ) { if ( ! array_key_exists( 'gform-refresh-nonces', $data ) ) { return $response; } + $received = $data['gform-refresh-nonces']; $response['gform-refresh-nonces'] = [ 'check' => 1 ]; From b3a102ad379850ded4e7a3679c63a56725ac71eb Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 26 Jan 2025 10:26:03 -0500 Subject: [PATCH 08/15] Do not enqueue scripts if edit entry link is invalid There is no reason to show the lock message on top of the "the link to edit this entry is not valid" message. --- includes/extensions/edit-entry/class-edit-entry-locking.php | 4 ++++ includes/extensions/edit-entry/class-edit-entry.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/includes/extensions/edit-entry/class-edit-entry-locking.php b/includes/extensions/edit-entry/class-edit-entry-locking.php index 1af904257a..66fec06d5d 100644 --- a/includes/extensions/edit-entry/class-edit-entry-locking.php +++ b/includes/extensions/edit-entry/class-edit-entry-locking.php @@ -161,6 +161,10 @@ public function maybe_enqueue_scripts() { continue; } + if ( ! ( new GravityView_Edit_Entry_Render( GravityView_Edit_Entry::getInstance() ) )->verify_nonce() ) { + continue; + } + $continue_enqueuing = true; break; diff --git a/includes/extensions/edit-entry/class-edit-entry.php b/includes/extensions/edit-entry/class-edit-entry.php index abb5acce2f..5a8dba7210 100644 --- a/includes/extensions/edit-entry/class-edit-entry.php +++ b/includes/extensions/edit-entry/class-edit-entry.php @@ -352,7 +352,7 @@ function get_field_blocklist( $entry = array() ) { /** * checks if user has permissions to edit a specific entry * - * Needs to be used combined with GravityView_Edit_Entry::user_can_edit_entry for maximum security!! + * Needs to be used combined with GravityView_Edit_Entry_Render::user_can_edit_entry for maximum security!! * * @param array|\WP_Error $entry Gravity Forms entry array or WP_Error if the entry wasn't found. * @param \GV\View|int $view ID of the view you want to check visibility against {@since 1.9.2}. Required since 2.0. From 1bf51b26174c1ed716fe2161e61f4b97db3cf7a0 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 27 Jan 2025 15:38:10 -0500 Subject: [PATCH 09/15] Add filter to override the loading of the lock UI assets --- .../edit-entry/class-edit-entry-locking.php | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/includes/extensions/edit-entry/class-edit-entry-locking.php b/includes/extensions/edit-entry/class-edit-entry-locking.php index 66fec06d5d..a197c6dd2c 100644 --- a/includes/extensions/edit-entry/class-edit-entry-locking.php +++ b/includes/extensions/edit-entry/class-edit-entry-locking.php @@ -120,6 +120,8 @@ protected function update_lock_request_meta( $object_id, $lock_request_value ) { * - Is it Edit Entry? * - Is the entry connected to a View that has `edit_locking` enabled? * - Is the entry connected to a form connected to a currently-loaded View? + * - Does the user have the capability to edit the entry? + * - Is the nonce valid? * * @internal * @since 2.7 @@ -135,46 +137,55 @@ public function maybe_enqueue_scripts() { return; } + $entry = $entry->as_entry(); + + /** + * Overrides whether to load the entry lock UI assets. + * This filter runs before checking whether if the edit entry link is valid, user has the capability to edit the entry, etc. + * + * Filter: `gk/gravityview/edit-entry/renderer/enqueue-entry-lock-assets` + * + * @since TBD + * + * @param bool $load Whether to load the entry lock UI assets. Default: false. + * @param array $entry The entry. + */ + if ( apply_filters( 'gk/gravityview/edit-entry/renderer/enqueue-entry-lock-assets', false, $entry ) ) { + $this->enqueue_scripts( $entry ); + } + if ( ! $post || ! is_a( $post, 'WP_Post' ) ) { return; } $views = View_Collection::from_post( $post ); - $entry_array = $entry->as_entry(); - - $continue_enqueuing = false; - - // If any Views being loaded have entry locking, enqueue the scripts + // If any Views being loaded have entry locking, enqueue the scripts. foreach ( $views->all() as $view ) { // Make sure the View has edit locking enabled if ( ! $view->settings->get( 'edit_locking' ) ) { continue; } - // Make sure that the entry belongs to the view form - if ( $view->form->ID != $entry_array['form_id'] ) { + // Make sure that the entry belongs to the View form. + if ( $view->form->ID !== (int) $entry['form_id'] ) { continue; } - if ( ! GravityView_Edit_Entry::check_user_cap_edit_entry( $entry_array, $view ) ) { + // Check user capabilities. + if ( ! GravityView_Edit_Entry::check_user_cap_edit_entry( $entry, $view ) ) { continue; } + // Check the nonce. if ( ! ( new GravityView_Edit_Entry_Render( GravityView_Edit_Entry::getInstance() ) )->verify_nonce() ) { continue; } - $continue_enqueuing = true; + $this->enqueue_scripts( $entry ); break; } - - if ( ! $continue_enqueuing ) { - return; - } - - $this->enqueue_scripts( $entry_array ); } /** From 6e99da9771c68667c5aeaf987eae0e0f3a85a80f Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 27 Jan 2025 17:26:55 -0500 Subject: [PATCH 10/15] Add filter to modify the lock UI markup --- .../edit-entry/class-edit-entry-locking.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/includes/extensions/edit-entry/class-edit-entry-locking.php b/includes/extensions/edit-entry/class-edit-entry-locking.php index a197c6dd2c..593f53257a 100644 --- a/includes/extensions/edit-entry/class-edit-entry-locking.php +++ b/includes/extensions/edit-entry/class-edit-entry-locking.php @@ -313,7 +313,16 @@ public function get_lock_ui( $user_id, $entry ) {
' . $message . '
'; $html .= ''; - return $html; + /** + * Modifies the edit entry lock UI markup. + * + * @filter `gk/gravityview/edit-entry/renderer/entry-lock-dialog-markup` + * + * @since TBD + * + * @param string $html The HTML markup. + */ + return apply_filters( 'gk/gravityview/edit-entry/renderer/entry-lock-dialog-markup', $html ); } /** From 988ef1181b0428766709570ecf1e96b53e9ed108 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 27 Jan 2025 17:29:49 -0500 Subject: [PATCH 11/15] Add support for entry locking in lightbox --- .../class-gravityview-lightbox-entry.php | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/includes/extensions/lightbox-entry/class-gravityview-lightbox-entry.php b/includes/extensions/lightbox-entry/class-gravityview-lightbox-entry.php index 2f752cda2e..14eb8492fd 100644 --- a/includes/extensions/lightbox-entry/class-gravityview-lightbox-entry.php +++ b/includes/extensions/lightbox-entry/class-gravityview-lightbox-entry.php @@ -323,6 +323,8 @@ private function process_edit_entry( $nonce, $view, $entry, $form ) { return; } + add_filter( 'gk/gravityview/edit-entry/renderer/enqueue-entry-lock-assets', '__return_true' ); + add_filter( 'gravityview/edit_entry/verify_nonce', '__return_true' ); add_filter( 'gravityview/edit_entry/cancel_onclick', function () use ( $view ) { @@ -333,6 +335,25 @@ private function process_edit_entry( $nonce, $view, $entry, $form ) { } } ); + // Updates the GF entry lock UI markup to properly handle requests for accepting the release or taking over the edit lock. + add_filter( 'gk/gravityview/edit-entry/renderer/entry-lock-dialog-markup', function ( $markup ) { + // To accept the release, we do an Ajax GET request by passing "release-edit-lock=1" and then close the lightbox. + $markup = str_replace( + 'id="gform-release-lock-button"', + 'id="gform-release-lock-button" onclick="event.preventDefault(); jQuery.ajax({ url: window.location.href, data: { \'release-edit-lock\': 1 }, method: \'GET\', dataType: \'html\' }).done(function() { window.parent.postMessage({ closeFancybox: true }); });"', + $markup + ); + + // To take over once the release has been accepted, we do an Ajax GET request by passing "get-edit-lock=1" and then close the GF lock dialog window. + $markup = str_replace( + 'id="gform-take-over-button"', + 'id="gform-take-over-button" onclick="event.preventDefault(); jQuery.ajax({ url: window.location.href, data: { \'get-edit-lock\': 1 }, method: \'GET\', dataType: \'html\' }).done(function() { jQuery( \'#gform-lock-dialog\' ).hide(); });"', + $markup + ); + + return $markup; + } ); + // Prevent redirection inside the lightbox by sending event to the parent window and hiding the success message. if ( ! in_array( $view->settings->get( 'edit_redirect' ), [ '1', '2' ] ) ) { return; From 0a0dffb5a5b37bed23774deaabf009db0a419e50 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 27 Jan 2025 17:38:48 -0500 Subject: [PATCH 12/15] Format code --- .../edit-entry/class-edit-entry-locking.php | 50 ++++-- .../class-gravityview-lightbox-entry.php | 153 +++++++++--------- 2 files changed, 110 insertions(+), 93 deletions(-) diff --git a/includes/extensions/edit-entry/class-edit-entry-locking.php b/includes/extensions/edit-entry/class-edit-entry-locking.php index 593f53257a..3aee253764 100644 --- a/includes/extensions/edit-entry/class-edit-entry-locking.php +++ b/includes/extensions/edit-entry/class-edit-entry-locking.php @@ -60,17 +60,19 @@ protected function get_lock_request_meta( $object_id ) { // TODO: Convert to extending Gravity Forms public function ajax_lock_request() { $object_id = rgget( 'object_id' ); - $response = $this->request_lock( $object_id ); - echo json_encode( $response ); - die(); + + $response = $this->request_lock( $object_id ); + + wp_send_json( $response ); } // TODO: Convert to extending Gravity Forms public function ajax_reject_lock_request() { $object_id = rgget( 'object_id' ); - $response = $this->delete_lock_request_meta( $object_id ); - echo json_encode( $response ); - die(); + + $response = $this->delete_lock_request_meta( $object_id ); + + wp_send_json( $response ); } // TODO: Convert to extending Gravity Forms @@ -89,27 +91,41 @@ protected function request_lock( $object_id ) { $lock_holder_user_id = $this->check_lock( $object_id ); $result = []; + if ( ! $lock_holder_user_id ) { $this->set_lock( $object_id ); + $result['html'] = __( 'You now have control', 'gk-gravityview' ); $result['status'] = 'lock_obtained'; - } else { - if ( GVCommon::has_cap( 'gravityforms_edit_entries' ) ) { - $user = get_userdata( $lock_holder_user_id ); - $result['html'] = sprintf( __( 'Your request has been sent to %s.', 'gk-gravityview' ), $user->display_name ); - } else { - $result['html'] = __( 'Your request has been sent.', 'gk-gravityview' ); - } + return $result; + } - $this->update_lock_request_meta( $object_id, $user_id ); + if ( GVCommon::has_cap( 'gravityforms_edit_entries' ) ) { + $user = get_userdata( $lock_holder_user_id ); - $result['status'] = 'lock_requested'; + $result['html'] = sprintf( __( 'Your request has been sent to %s.', 'gk-gravityview' ), $user->display_name ); + } else { + $result['html'] = __( 'Your request has been sent.', 'gk-gravityview' ); } + $this->update_lock_request_meta( $object_id, $user_id ); + + $result['status'] = 'lock_requested'; + return $result; } + /** + * Updates the lock request meta for an object. + * + * @since 2.34 + * + * @param string $object_id + * @param string $lock_request_value + * + * @return void + */ protected function update_lock_request_meta( $object_id, $lock_request_value ) { GFCache::set( 'lock_request_entry_' . $object_id, $lock_request_value, true, 120 ); } @@ -658,8 +674,8 @@ public function heartbeat_request_lock( $response, $data ) { * * @since TBD * - * @param array $response The response array. - * @param array $data The data array. + * @param array $response The response array. + * @param array $data The data array. * * @return array The response array. */ diff --git a/includes/extensions/lightbox-entry/class-gravityview-lightbox-entry.php b/includes/extensions/lightbox-entry/class-gravityview-lightbox-entry.php index 14eb8492fd..172c9f5ca2 100644 --- a/includes/extensions/lightbox-entry/class-gravityview-lightbox-entry.php +++ b/includes/extensions/lightbox-entry/class-gravityview-lightbox-entry.php @@ -51,7 +51,7 @@ public function __construct() { * * @used-by `gravityview/template/before` filter. * - * @since 2.29.0 + * @since 2.29.0 * * @param Template_Context $context * @@ -151,7 +151,7 @@ public function process_rest_request( $request ) { * * @used-by `gravityview/view/links/directory` filter. * - * @since 2.29.0 + * @since 2.29.0 * * @param string $link The directory link. * @@ -509,14 +509,15 @@ private function render_entry( $type, $view, $entry, $form ) { * * @action `gk/gravityview/lightbox/entry/before-output` * - * @since 2.31.0 + * @since 2.31.0 * - * @param array $args { - * @type View $view The View object being rendered. - * @type GF_Entry $entry The Gravity Forms entry data. - * @type array $form The Gravity Forms form array. - * @type Entry_Render $entry_renderer The renderer object responsible for rendering the entry. - * } + * @param array $args { + * + * @type View $view The View object being rendered. + * @type GF_Entry $entry The Gravity Forms entry data. + * @type array $form The Gravity Forms form array. + * @type Entry_Render $entry_renderer The renderer object responsible for rendering the entry. + * } */ do_action_ref_array( 'gk/gravityview/lightbox/entry/before-output', [ &$view, &$entry, &$form, &$entry_renderer ] ); @@ -540,19 +541,19 @@ private function render_entry( $type, $view, $entry, $form ) { tag. - * - * @action `gk/gravityview/lightbox/entry/output/head-before` - * - * @since 2.31.0 - * - * @param string $type The type of the entry view (single or edit). - * @param View $view The View object being rendered. - * @param GF_Entry $entry The Gravity Forms entry data. - * @param array $form The Gravity Forms form array. - */ - do_action( 'gk/gravityview/lightbox/entry/output/head-before', $type, $view, $entry, $form ); + /** + * Fires after tag. + * + * @action `gk/gravityview/lightbox/entry/output/head-before` + * + * @since 2.31.0 + * + * @param string $type The type of the entry view (single or edit). + * @param View $view The View object being rendered. + * @param GF_Entry $entry The Gravity Forms entry data. + * @param array $form The Gravity Forms form array. + */ + do_action( 'gk/gravityview/lightbox/entry/output/head-before', $type, $view, $entry, $form ); ?> <?php echo $title; ?> @@ -568,73 +569,73 @@ private function render_entry( $type, $view, $entry, $form ) { tag. - * - * @action `gk/gravityview/lightbox/entry/output/head-after` - * - * @since 2.31.0 - * - * @param string $type The type of the entry view (single or edit). - * @param View $view The View object being rendered. - * @param GF_Entry $entry The Gravity Forms entry data. - * @param array $form The Gravity Forms form array. - */ - do_action( 'gk/gravityview/lightbox/entry/output/head-after', $type, $view, $entry, $form ); + /** + * Fires before tag. + * + * @action `gk/gravityview/lightbox/entry/output/head-after` + * + * @since 2.31.0 + * + * @param string $type The type of the entry view (single or edit). + * @param View $view The View object being rendered. + * @param GF_Entry $entry The Gravity Forms entry data. + * @param array $form The Gravity Forms form array. + */ + do_action( 'gk/gravityview/lightbox/entry/output/head-after', $type, $view, $entry, $form ); ?> tag before the content is rendered. - * - * @action `gk/gravityview/lightbox/entry/output/content-before` - * - * @since 2.31.0 - * - * @param string $type The type of the entry view (single or edit). - * @param View $view The View object being rendered. - * @param GF_Entry $entry The Gravity Forms entry data. - * @param array $form The Gravity Forms form array. - */ - do_action( 'gk/gravityview/lightbox/entry/output/content-before', $type, $view, $entry, $form ); + /** + * Fires after tag before the content is rendered. + * + * @action `gk/gravityview/lightbox/entry/output/content-before` + * + * @since 2.31.0 + * + * @param string $type The type of the entry view (single or edit). + * @param View $view The View object being rendered. + * @param GF_Entry $entry The Gravity Forms entry data. + * @param array $form The Gravity Forms form array. + */ + do_action( 'gk/gravityview/lightbox/entry/output/content-before', $type, $view, $entry, $form ); ?> tag after the content is rendered and before the footer. - * - * @action `gk/gravityview/lightbox/entry/output/content-after` - * - * @since 2.31.0 - * - * @param string $type The type of the entry view (single or edit). - * @param View $view The View object being rendered. - * @param GF_Entry $entry The Gravity Forms entry data. - * @param array $form The Gravity Forms form array. - */ - do_action( 'gk/gravityview/lightbox/entry/output/content-after', $type, $view, $entry, $form ); + /** + * Fires inside the tag after the content is rendered and before the footer. + * + * @action `gk/gravityview/lightbox/entry/output/content-after` + * + * @since 2.31.0 + * + * @param string $type The type of the entry view (single or edit). + * @param View $view The View object being rendered. + * @param GF_Entry $entry The Gravity Forms entry data. + * @param array $form The Gravity Forms form array. + */ + do_action( 'gk/gravityview/lightbox/entry/output/content-after', $type, $view, $entry, $form ); ?> tag. - * - * @action `gk/gravityview/lightbox/entry/output/footer-after` - * - * @since 2.31.0 - * - * @param string $type The type of the entry view (single or edit). - * @param View $view The View object being rendered. - * @param GF_Entry $entry The Gravity Forms entry data. - * @param array $form The Gravity Forms form array. - */ - do_action( 'gk/gravityview/lightbox/entry/output/footer-after', $type, $view, $entry, $form ); + /** + * Fires after the footer and before the closing tag. + * + * @action `gk/gravityview/lightbox/entry/output/footer-after` + * + * @since 2.31.0 + * + * @param string $type The type of the entry view (single or edit). + * @param View $view The View object being rendered. + * @param GF_Entry $entry The Gravity Forms entry data. + * @param array $form The Gravity Forms form array. + */ + do_action( 'gk/gravityview/lightbox/entry/output/footer-after', $type, $view, $entry, $form ); ?> @@ -652,7 +653,7 @@ private function render_entry( $type, $view, $entry, $form ) { * * @used-by `gk/foundation/inline-scripts` filter. * - * @since 2.29.0 + * @since 2.29.0 * * @param array $scripts The registered scripts. * @@ -746,7 +747,7 @@ function handleChange( changedInput, otherInput ) { * @since 2.31.0 * * @param string $type The type of the entry view (single or edit). - * @param View $view The View object being rendered. + * @param View $view The View object being rendered. * * @return void */ From 7caf5d41651f2163a3a4a7feaaa4de83c454023c Mon Sep 17 00:00:00 2001 From: Doeke Norg Date: Wed, 22 Jan 2025 10:12:25 +0100 Subject: [PATCH 13/15] Show search bar when hiding data until search is performed --- readme.txt | 4 ++ .../views/gravityview-layout-builder.php | 39 ++++++++++--------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/readme.txt b/readme.txt index 0600f034ec..803c5ab6e3 100644 --- a/readme.txt +++ b/readme.txt @@ -21,6 +21,10 @@ Beautifully display your Gravity Forms entries. Learn more on [gravitykit.com](h == Changelog == += develop = + +* Fixed: The Search Bar would not always be visible on Views with the Layout Builder. + = 2.34 on January 9, 2025 = This release introduces the [Layout Builder](https://www.gravitykit.com/announcing-gravityview-2-34-all-new-layout-builder) that allows creating custom layouts with rows and columns directly in the View editor, adds support for exporting entries by Approval Status, and includes various fixes and improvements. diff --git a/templates/views/gravityview-layout-builder.php b/templates/views/gravityview-layout-builder.php index 5f75b7b3e5..73b393b6dc 100644 --- a/templates/views/gravityview-layout-builder.php +++ b/templates/views/gravityview-layout-builder.php @@ -16,15 +16,17 @@ gravityview_before( $gravityview ); gravityview_header( $gravityview ); - +?> +
entries->count() ) { ?> -
-
-

-
-
+
+
+

+
+
entries->all() as $entry ) { ?> -
+
-
+
$areas ) { $column = $col; ?> -
+
-
+
-
+
-
+
+
+view->get_anchor_id() ) . '" class="' . esc_attr( $class ) . '">{content}', + '
{content}
', $gravityview->view->get_anchor_id(), $gravityview->view ); From 3908bb07e4116009f647a100f5c89917f8819ce5 Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 24 Jan 2025 11:10:37 -0500 Subject: [PATCH 14/15] Allow main network site users to delete own entries on subsites (#2261) --- .../delete-entry/class-delete-entry.php | 40 ++++++------------- readme.txt | 4 +- 2 files changed, 15 insertions(+), 29 deletions(-) diff --git a/includes/extensions/delete-entry/class-delete-entry.php b/includes/extensions/delete-entry/class-delete-entry.php index 830aac11a0..cebc4bb183 100644 --- a/includes/extensions/delete-entry/class-delete-entry.php +++ b/includes/extensions/delete-entry/class-delete-entry.php @@ -653,7 +653,6 @@ public static function get_confirm_dialog() { * @return boolean|WP_Error True: can edit form. WP_Error: nope. */ function user_can_delete_entry( $entry = array(), $view_id = null ) { - $error = null; if ( ! $this->verify_nonce() ) { @@ -697,13 +696,9 @@ function user_can_delete_entry( $entry = array(), $view_id = null ) { public static function check_user_cap_delete_entry( $entry, $field = array(), $view = 0 ) { if ( ! $view ) { /** @deprecated path */ - $view_id = GravityView_View::getInstance()->getViewId(); - $view = \GV\View::by_id( $view_id ); - } else { - if ( ! $view instanceof \GV\View ) { - $view = \GV\View::by_id( $view ); - } - $view_id = $view->ID; + $view = \GV\View::by_id( GravityView_View::getInstance()->getViewId() ); + } elseif ( ! $view instanceof \GV\View ) { + $view = \GV\View::by_id( $view ); } $current_user = wp_get_current_user(); @@ -712,40 +707,28 @@ public static function check_user_cap_delete_entry( $entry, $field = array(), $v // Or if they can delete any entries (as defined in Gravity Forms), we're good. if ( GVCommon::has_cap( array( 'gravityforms_delete_entries', 'gravityview_delete_others_entries' ), $entry_id ) ) { - gravityview()->log->debug( 'Current user has `gravityforms_delete_entries` or `gravityview_delete_others_entries` capability.' ); return true; } - // If field options are passed, check if current user can view the link + // If field options are passed, check if current user can view the link. if ( ! empty( $field ) ) { - // If capability is not defined, something is not right! if ( empty( $field['allow_edit_cap'] ) ) { - gravityview()->log->error( 'Cannot read delete entry field caps', array( 'data' => $field ) ); return false; } - if ( GVCommon::has_cap( $field['allow_edit_cap'] ) ) { - - // Do not return true if cap is read, as we need to check if the current user created the entry - if ( 'read' !== $field['allow_edit_cap'] ) { - return true; - } - } else { - - gravityview()->log->debug( 'User {user_id} is not authorized to view delete entry link ', array( 'user_id' => $current_user->ID ) ); - - return false; + // Do not return true if cap is read, as we need to check if the current user created the entry. + if ( GVCommon::has_cap( $field['allow_edit_cap'] ) && 'read' !== $field['allow_edit_cap'] ) { + return true; } } if ( ! isset( $entry['created_by'] ) ) { - - gravityview()->log->error( 'Entry `created_by` doesn\'t exist.' ); + gravityview()->log->error( 'Entry property `created_by` doesn\'t exist.' ); return false; } @@ -755,21 +738,22 @@ public static function check_user_cap_delete_entry( $entry, $field = array(), $v // Only checks user_delete view option if view is already set if ( $view && empty( $user_delete ) ) { gravityview()->log->debug( 'User Delete is disabled. Returning false.' ); + return false; } // If the logged-in user is the same as the user who created the entry, we're good. - if ( is_user_logged_in() && intval( $current_user->ID ) === intval( $entry['created_by'] ) ) { - + if ( is_user_logged_in() && $current_user->ID === (int) $entry['created_by'] ) { gravityview()->log->debug( 'User {user_id} created the entry.', array( 'user_id' => $current_user->ID ) ); return true; } + gravityview()->log->debug( 'User {user_id} is not authorized to view delete entry link ', array( 'user_id' => $current_user->ID ) ); + return false; } - /** * After processing delete entry, the user will be redirected to the referring View or embedded post/page. Display a message on redirection. * diff --git a/readme.txt b/readme.txt index 803c5ab6e3..e92a4ca8e6 100644 --- a/readme.txt +++ b/readme.txt @@ -23,7 +23,9 @@ Beautifully display your Gravity Forms entries. Learn more on [gravitykit.com](h = develop = -* Fixed: The Search Bar would not always be visible on Views with the Layout Builder. +#### 🐛 Fixed +* The Search Bar would not always be visible in Views using the Layout Builder. +* Users belonging to the main network site in a multisite environment couldn’t delete their own entries on subsites. = 2.34 on January 9, 2025 = From a073676744e3cc8b6611713898f9330772d650e1 Mon Sep 17 00:00:00 2001 From: Vlad Date: Mon, 27 Jan 2025 17:43:15 -0500 Subject: [PATCH 15/15] Update changelog --- readme.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/readme.txt b/readme.txt index e92a4ca8e6..bc0c64c9c1 100644 --- a/readme.txt +++ b/readme.txt @@ -26,6 +26,11 @@ Beautifully display your Gravity Forms entries. Learn more on [gravitykit.com](h #### 🐛 Fixed * The Search Bar would not always be visible in Views using the Layout Builder. * Users belonging to the main network site in a multisite environment couldn’t delete their own entries on subsites. +* Entry locking not working. + +#### 💻 Developer Updates +* Added `gk/gravityview/edit-entry/renderer/enqueue-entry-lock-assets` filter to override whether to load the entry lock UI assets. +* Added `gk/gravityview/edit-entry/renderer/entry-lock-dialog-markup` filter to modify the entry locking UI dialog window markup. = 2.34 on January 9, 2025 =