diff --git a/includes/extensions/edit-entry/class-edit-entry-locking.php b/includes/extensions/edit-entry/class-edit-entry-locking.php
index 8382df6797..3aee253764 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 @@
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
@@ -65,28 +90,42 @@ 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' );
$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 );
}
@@ -97,6 +136,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
@@ -112,47 +153,59 @@ 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 = \GV\View_Collection::from_post( $post );
-
- $entry_array = $entry->as_entry();
+ $views = View_Collection::from_post( $post );
- $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 one of the forms connected to one of the Views in this request
- $joined_forms = $view::get_joined_forms( $view->ID );
+ // Make sure that the entry belongs to the View form.
+ if ( $view->form->ID !== (int) $entry['form_id'] ) {
+ continue;
+ }
- $entry_form_id = $entry_array['form_id'];
+ // Check user capabilities.
+ if ( ! GravityView_Edit_Entry::check_user_cap_edit_entry( $entry, $view ) ) {
+ continue;
+ }
- if ( ! isset( $joined_forms[ $entry_form_id ] ) ) {
+ // 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 );
}
/**
- * 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`
*
@@ -163,33 +216,52 @@ 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,
+ // 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, $entry ) ) . ';
+ $("body").prepend(lockUI);
+ }
+ });
+ ' );
$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', '
+ .notification-dialog-wrap.hidden {
+ display: none;
+ }
+ ' );
$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 ),
+ 'lockUI' => $this->get_lock_ui( $lock_user_id, $entry ),
'objectID' => $entry['id'],
'objectType' => 'entry',
'strings' => $strings,
- );
+ ];
wp_localize_script( 'gforms_locking', 'gflockingVars', $vars );
}
@@ -197,26 +269,27 @@ 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
*
- * @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 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;
$hidden = $locked ? '' : ' hidden';
- if ( $locked ) {
- if ( GVCommon::has_cap( 'gravityforms_edit_entries' ) ) {
+ 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;
} else {
@@ -229,7 +302,6 @@ public function get_lock_ui( $user_id ) {
' . $avatar . '
' . esc_html( sprintf( $this->get_string( 'currently_locked' ), $person_editing_text ) ) . '
-
' . esc_html__( 'Take Over', 'gk-gravityview' ) . '
' . esc_html( $this->get_string( 'cancel' ) ) . '
@@ -238,9 +310,7 @@ public function get_lock_ui( $user_id ) {
';
-
} else {
-
$message = '
';
}
- $html = '';
- return $html;
+ $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 );
}
/**
- * Localized string for the UI.
- *
- * Uses gravityforms textdomain unchanged.
+ * Returns localized text strings used in the UI.
*
* @since 2.5.2
*
* @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' ),
@@ -287,7 +362,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 );
@@ -295,105 +370,145 @@ 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 = 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 );
+
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 ) ) {
- $this->set_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 ) {
- 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.
+ * @param int $user_id The user ID to lock the entry to.
*
* @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
*
@@ -402,7 +517,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 ) ) {
@@ -417,4 +531,182 @@ public function set_lock( $entry_id ) {
return $user_id;
}
+
+ /**
+ * Checks if the objects are locked.
+ *
+ * @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 ) {
+ $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 = [ '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;
+ }
+
+ /**
+ * Refreshes the lock for an entry.
+ *
+ * @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 ) {
+ $heartbeat_key = 'gform-refresh-lock-entry';
+
+ if ( array_key_exists( $heartbeat_key, $data ) ) {
+ $received = $data[ $heartbeat_key ];
+
+ $send = [];
+
+ if ( ! isset( $received['objectID'] ) ) {
+ return $response;
+ }
+
+ $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 ),
+ ];
+
+ $avatar = get_avatar( $user->ID, 64 );
+
+ if ( $avatar && preg_match( "|src='([^']+)'|", $avatar, $matches ) ) {
+ $error['avatar_src'] = $matches[1];
+ }
+
+ $send['lock_error'] = $error;
+ } elseif ( $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 ),
+ ];
+
+ $avatar = get_avatar( $user->ID, 64 );
+
+ if ( $avatar && preg_match( "|src='([^']+)'|", $avatar, $matches ) ) {
+ $lock_request['avatar_src'] = $matches[1];
+ }
+
+ $send['lock_request'] = $lock_request;
+ }
+ }
+
+ $response[ $heartbeat_key ] = $send;
+ }
+
+ return $response;
+ }
+
+ /**
+ * Requests the lock for an entry.
+ *
+ * @since TBD
+ *
+ * @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 ) {
+ $heartbeat_key = 'gform-request-lock-entry';
+
+ if ( ! array_key_exists( $heartbeat_key, $data ) ) {
+ return $response;
+ }
+
+ $received = $data[ $heartbeat_key ];
+
+ $send = [];
+
+ if ( ! isset( $received['objectID'] ) ) {
+ return $response;
+ }
+
+ $object_id = $received['objectID'];
+
+ $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;
+
+ return $response;
+ }
+
+ /**
+ * Refreshes nonces for an entry.
+ *
+ * @since TBD
+ *
+ * @param array $response The response array.
+ * @param array $data The data array.
+ *
+ * @return array The response array.
+ */
+ 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 ];
+
+ if ( ! isset( $received['objectID'] ) ) {
+ return $response;
+ }
+
+ $object_id = $received['objectID'];
+
+ 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;
+ }
}
diff --git a/includes/extensions/edit-entry/class-edit-entry.php b/includes/extensions/edit-entry/class-edit-entry.php
index 7c531a4f76..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.
@@ -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.' );
diff --git a/includes/extensions/lightbox-entry/class-gravityview-lightbox-entry.php b/includes/extensions/lightbox-entry/class-gravityview-lightbox-entry.php
index 2f752cda2e..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.
*
@@ -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;
@@ -488,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 ] );
@@ -519,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 );
?>
@@ -547,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 );
?>
@@ -631,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.
*
@@ -725,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
*/
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 =