plugin install

This commit is contained in:
Tony Volpe
2024-06-18 17:29:05 -04:00
parent e1aaedd1ae
commit 41f50eacc4
5880 changed files with 1057631 additions and 39681 deletions

View File

@@ -0,0 +1,593 @@
<?php
if ( ! class_exists( 'GFForms' ) ) {
die();
}
/**
* Handles all tasks related to locking.
*
* - Loads the WordPress Heartbeat API and scripts & styles for GF Locking
* - Provides standardized UX
*
* @package GFLocking
* @author Rocketgenius
*/
abstract class GFLocking {
private $_object_type;
private $_object_id;
private $_edit_url;
private $_redirect_url;
private $_capabilities;
const PREFIX_EDIT_LOCK = 'lock_';
const PREFIX_EDIT_LOCK_REQUEST = 'lock_request_';
public function __construct( $object_type, $redirect_url, $edit_url = '', $capabilities = array() ) {
$this->_object_type = $object_type;
$this->_redirect_url = $redirect_url;
$this->_capabilities = $capabilities;
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
$this->init_ajax();
} else {
$this->register_scripts();
$is_locking_page = false;
$is_edit_page = false;
if ( $this->is_edit_page() ) {
$this->init_edit_lock();
$is_locking_page = true;
$is_edit_page = true;
} else if ( $this->is_list_page() ) {
$this->init_list_page();
$is_locking_page = true;
} else if ( $this->is_view_page() ) {
$this->init_view_page();
$is_locking_page = true;
}
if ( $is_locking_page ) {
$this->_object_id = $this->get_object_id();
$this->_edit_url = $edit_url;
$this->maybe_lock_object( $is_edit_page );
}
}
}
/**
* Override this method to check the condition for the edit page.
*
* @return bool
*/
protected function is_edit_page() {
return false;
}
/**
* Override this method to check the condition for the list page.
*
* @return bool
*/
protected function is_list_page() {
return false;
}
/**
* Override this method to check the condition for the view page.
*
* @return bool
*/
protected function is_view_page() {
return false;
}
/**
* Override this method to provide the class with the correct object id.
*
* @return bool
*/
protected function get_object_id() {
$id = rgget( 'id' );
$id = absint( $id );
return $id; // example in the case of form id
}
public function init_edit_lock() {
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
}
public function init_ajax() {
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( 'wp_ajax_gf_lock_request_' . $this->_object_type, array( $this, 'ajax_lock_request' ) );
add_filter( 'wp_ajax_gf_reject_lock_request_' . $this->_object_type, array( $this, 'ajax_reject_lock_request' ) );
}
public function init_list_page() {
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_list_scripts' ) );
}
public function init_view_page() {
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_view_page_scripts' ) );
}
public function register_scripts() {
$min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || isset( $_GET['gform_debug'] ) ? '' : '.min';
$locking_path = GFCommon::get_base_url() . '/includes/locking/';
wp_register_script( 'gforms_locking', $locking_path . "js/locking{$min}.js", array( 'jquery', 'heartbeat' ), GFCommon::$version );
wp_register_script( 'gforms_locking_view', $locking_path . "js/locking-view{$min}.js", array( 'jquery', 'heartbeat' ), GFCommon::$version );
wp_register_script( 'gforms_locking_list', $locking_path . "js/locking-list{$min}.js", array( 'jquery', 'heartbeat' ), GFCommon::$version );
wp_register_style( 'gforms_locking_css', $locking_path . "css/locking{$min}.css", array(), GFCommon::$version );
wp_register_style( 'gforms_locking_list_css', $locking_path . "css/locking-list{$min}.css", array(), GFCommon::$version );
// No conflict scripts
add_filter( 'gform_noconflict_scripts', array( $this, 'register_noconflict_scripts' ) );
add_filter( 'gform_noconflict_styles', array( $this, 'register_noconflict_styles' ) );
}
public function register_noconflict_scripts( $scripts ) {
$locking_scripts = array( 'gforms_locking', 'gforms_locking_list', 'gforms_locking_view' );
return array_merge( $scripts, $locking_scripts );
}
public function register_noconflict_styles( $styles ) {
$locking_styles = array( 'gforms_locking_css', 'gforms_locking_list_css' );
return array_merge( $styles, $locking_styles );
}
public function enqueue_scripts() {
wp_enqueue_script( 'gforms_locking' );
wp_enqueue_style( 'gforms_locking_css' );
$lock_user_id = $this->check_lock( $this->get_object_id() );
$strings = array(
'noResponse' => $this->get_string( 'no_response' ),
'requestAgain' => $this->get_string( 'request_again' ),
'requestError' => $this->get_string( 'request_error' ),
'gainedControl' => $this->get_string( 'gained_control' ),
'rejected' => $this->get_string( 'request_rejected' ),
'pending' => $this->get_string( 'request_pending' )
);
$vars = array(
'hasLock' => ! $lock_user_id ? 1 : 0,
'lockUI' => $this->get_lock_ui( $lock_user_id ),
'objectID' => $this->_object_id,
'objectType' => $this->_object_type,
'strings' => $strings,
);
wp_localize_script( 'gforms_locking', 'gflockingVars', $vars );
}
public function enqueue_list_scripts() {
wp_enqueue_script( 'gforms_locking_list' );
wp_enqueue_style( 'gforms_locking_list_css' );
$vars = array(
'objectType' => $this->_object_type,
);
wp_localize_script( 'gforms_locking_list', 'gflockingVars', $vars );
}
public function enqueue_view_page_scripts() {
wp_enqueue_script( 'gforms_locking_view' );
wp_enqueue_style( 'gforms_locking_view_css' );
$lock_user_id = $this->check_lock( $this->get_object_id() );
$vars = array(
'hasLock' => ! $lock_user_id ? 1 : 0,
'objectID' => $this->_object_id,
'objectType' => $this->_object_type,
);
wp_localize_script( 'gforms_locking_view', 'gflockingVars', $vars );
}
protected function get_strings() {
$strings = array(
'currently_locked' => wp_strip_all_tags( __( 'This page is currently locked. Click on the "Request Control" button to let %s know you\'d like to take over.', 'gravityforms' ) ),
'accept' => wp_strip_all_tags( __( 'Accept', 'gravityforms' ) ),
'cancel' => wp_strip_all_tags( __( 'Cancel', 'gravityforms' ) ),
'currently_editing' => wp_strip_all_tags( __( '%s is currently editing', 'gravityforms' ) ),
'taken_over' => wp_strip_all_tags( __( '%s has taken over and is currently editing.', 'gravityforms' ) ),
'lock_requested' => wp_strip_all_tags( __( '%s has requested permission to take over control.', 'gravityforms' ) ),
'gained_control' => wp_strip_all_tags( __( 'You now have control', 'gravityforms' ) ),
'request_pending' => wp_strip_all_tags( __( 'Pending', 'gravityforms' ) ),
'no_response' => wp_strip_all_tags( __( 'No response', 'gravityforms' ) ),
'request_again' => wp_strip_all_tags( __( 'Request again', 'gravityforms' ) ),
'request_error' => wp_strip_all_tags( __( 'Error', 'gravityforms' ) ),
'request_rejected' => wp_strip_all_tags( __( 'Your request was rejected', 'gravityforms' ) ),
);
return $strings;
}
public function ajax_lock_request() {
$object_id = rgget( 'object_id' );
$response = $this->request_lock( $object_id );
echo json_encode( $response );
die();
}
public function ajax_reject_lock_request() {
$object_id = rgget( 'object_id' );
$response = $this->delete_lock_request_meta( $object_id );
echo json_encode( $response );
die();
}
protected function has_lock() {
return $this->check_lock( $this->get_object_id() ) ? true : false;
}
protected function check_lock( $object_id ) {
if ( ! $user_id = $this->get_lock_meta( $object_id ) ) {
return false;
}
if ( $user_id != get_current_user_id() ) {
return $user_id;
}
return false;
}
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;
}
protected function set_lock( $object_id ) {
if ( ! GFCommon::current_user_can_any( $this->_capabilities ) ) {
return false;
}
if ( 0 == ( $user_id = get_current_user_id() ) ) {
return false;
}
$this->update_lock_meta( $object_id, $user_id );
return $user_id;
}
protected function request_lock( $object_id ) {
if ( 0 == ( $user_id = get_current_user_id() ) ) {
return false;
}
$lock_holder_user_id = $this->check_lock( $object_id );
$result = array();
if ( ! $lock_holder_user_id ) {
$this->set_lock( $object_id );
$result['html'] = __( 'You now have control', 'gravityforms' );
$result['status'] = 'lock_obtained';
} else {
$user = get_userdata( $lock_holder_user_id );
$this->update_lock_request_meta( $object_id, $user_id );
$result['html'] = sprintf( __( 'Your request has been sent to %s.', 'gravityforms' ), $user->display_name );
$result['status'] = 'lock_requested';
}
return $result;
}
protected function get_lock_request_meta( $object_id ) {
return GFCache::get( self::PREFIX_EDIT_LOCK_REQUEST . $this->_object_type . '_' . $object_id );
}
protected function get_lock_meta( $object_id ) {
return GFCache::get( self::PREFIX_EDIT_LOCK . $this->_object_type . '_' . $object_id );
}
protected function update_lock_meta( $object_id, $lock_value ) {
GFCache::set( self::PREFIX_EDIT_LOCK . $this->_object_type . '_' . $object_id, $lock_value, true, 150 );
}
protected function update_lock_request_meta( $object_id, $lock_request_value ) {
GFCache::set( self::PREFIX_EDIT_LOCK_REQUEST . $this->_object_type . '_' . $object_id, $lock_request_value, true, 120 );
}
protected function delete_lock_request_meta( $object_id ) {
GFCache::delete( self::PREFIX_EDIT_LOCK_REQUEST . $this->_object_type . '_' . $object_id );
return true;
}
protected function delete_lock_meta( $object_id ) {
GFCache::delete( self::PREFIX_EDIT_LOCK . $this->_object_type . '_' . $object_id );
return true;
}
public function maybe_lock_object( $is_edit_page ) {
if ( isset( $_GET['get-edit-lock'] ) ) {
$this->set_lock( $this->_object_id );
wp_safe_redirect( $this->_edit_url );
exit();
} else if ( isset( $_GET['release-edit-lock'] ) ) {
$this->delete_lock_meta( $this->_object_id );
wp_safe_redirect( $this->_redirect_url );
exit();
} else {
if ( $is_edit_page && ! $user_id = $this->check_lock( $this->_object_id ) ) {
$this->set_lock( $this->_object_id );
}
}
}
public function heartbeat_check_locked_objects( $response, $data, $screen_id ) {
$checked = array();
$heartbeat_key = 'gform-check-locked-objects-' . $this->_object_type;
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-' . $this->_object_type;
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-' . $this->_object_type;
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;
}
public function get_lock_ui( $user_id ) {
$user = get_userdata( $user_id );
$locked = $user_id && $user;
$edit_url = $this->_edit_url === null ? '' : $this->_edit_url;
$hidden = $locked ? '' : ' hidden';
if ( $locked ) {
$message = '<div class="gform-locked-message">
<div class="gform-locked-avatar">' . get_avatar( $user->ID, 64 ) . '</div>
<p class="currently-editing" tabindex="0">' . sprintf( $this->get_string( 'currently_locked' ), $user->display_name ) . '</p>
<p>
<a id="gform-take-over-button" style="display:none" class="button button-primary wp-tab-first" href="' . esc_url( add_query_arg( 'get-edit-lock', '1', $edit_url ) ) . '">' . __( 'Take Over', 'gravityforms' ) . '</a>
<button id="gform-lock-request-button" class="button button-primary wp-tab-last">' . __( 'Request Control', 'gravityforms' ) . '</button>
<a class="button" href="' . esc_url( $this->_redirect_url ) . '">' . $this->get_string( 'cancel' ) . '</a>
</p>
<div id="gform-lock-request-status">
<!-- placeholder -->
</div>
</div>';
} else {
$message = '<div class="gform-taken-over">
<div class="gform-locked-avatar"></div>
<p class="wp-tab-first" tabindex="0">
<span class="currently-editing"></span><br>
</p>
<p>
<a id="gform-release-lock-button" class="button button-primary wp-tab-last" href="' . esc_url( add_query_arg( 'release-edit-lock', '1', $edit_url ) ) . '">' . $this->get_string( 'accept' ) . '</a>
<button id="gform-reject-lock-request-button" style="display:none" class="button button-primary wp-tab-last">' . __( 'Reject Request', 'gravityforms' ) . '</button>
</p>
</div>';
}
$html = '<div id="gform-lock-dialog" class="notification-dialog-wrap' . $hidden . '">
<div class="notification-dialog-background"></div>
<div class="notification-dialog">';
$html .= $message;
$html .= ' </div>
</div>';
return $html;
}
public function get_string( $string_key ) {
$strings = $this->get_strings();
return rgar( $strings, $string_key );
}
// helper functions for the list page
public function list_row_class( $object_id, $echo = true ) {
$locked_class = $this->is_locked( $object_id ) ? 'wp-locked' : '';
$classes = ' gf-locking ' . $locked_class;
if ( $echo ) {
echo $classes;
}
return $classes;
}
public function is_locked( $object_id ) {
if ( ! $user_id = GFCache::get( self::PREFIX_EDIT_LOCK . $this->_object_type . '_' . $object_id ) ) {
return false;
}
if ( $user_id != get_current_user_id() ) {
return true;
}
return false;
}
public function lock_indicator( $echo = true ) {
$lock_indicator = '<div class="locked-indicator"></div>';
if ( $echo ) {
echo $lock_indicator;
}
return $lock_indicator;
}
public function lock_info( $object_id, $echo = true ) {
$user_id = $this->check_lock( $object_id );
if ( ! $user_id ) {
return '';
}
if ( $user_id && $user = get_userdata( $user_id ) ) {
$locked_avatar = get_avatar( $user->ID, 18 );
$locked_text = esc_html( sprintf( $this->get_string( 'currently_editing' ), $user->display_name ) );
} else {
$locked_avatar = $locked_text = '';
}
$locked_info = '<div class="locked-info"><span class="locked-avatar">' . $locked_avatar . '</span> <span class="locked-text">' . $locked_text . "</span></div>\n";
if ( $echo ) {
echo $locked_info;
}
return $locked_info;
}
protected function is_page( $page_name ) {
return $page_name == GFForms::get_page();
}
}

View File

@@ -0,0 +1,2 @@
<?php
//Nothing to see here

View File

@@ -0,0 +1,3 @@
tr.wp-locked .locked-indicator {
background: url('../images/lock.png') no-repeat;
}

View File

@@ -0,0 +1 @@
tr.wp-locked .locked-indicator{background:url('../images/lock.png') no-repeat}

View File

@@ -0,0 +1,20 @@
#gform-lock-dialog .gform-locked-message,
#gform-lock-dialog .gform-taken-over {
margin: 25px;
}
#gform-lock-dialog .gform-locked-message a.button {
margin-right: 10px;
}
#gform-lock-dialog .gform-locked-avatar {
float: left;
margin: 0 20px 20px 0;
}
#gform-lock-dialog .wp-tab-first {
outline: 0;
}

View File

@@ -0,0 +1 @@
#gform-lock-dialog .gform-locked-message,#gform-lock-dialog .gform-taken-over{margin:25px}#gform-lock-dialog .gform-locked-message a.button{margin-right:10px}#gform-lock-dialog .gform-locked-avatar{float:left;margin:0 20px 20px 0}#gform-lock-dialog .wp-tab-first{outline:0}

View File

@@ -0,0 +1,2 @@
<?php
//Nothing to see here

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

View File

@@ -0,0 +1,2 @@
<?php
//Nothing to see here

View File

@@ -0,0 +1,2 @@
<?php
//Nothing to see here

View File

@@ -0,0 +1,55 @@
(function (gflocking, $) {
var objectType;
$(document).ready(function () {
objectType = gflockingVars.objectType;
gflocking.init();
});
gflocking.init = function () {
initHeartbeat();
};
function initHeartbeat() {
var checkLocksKey = 'gform-check-locked-objects-' + objectType;
wp.heartbeat.interval( 30 );
$(document).on('heartbeat-tick.' + checkLocksKey,function (e, data) {
var locked = data[checkLocksKey] || {};
$('.gf-locking').each(function (i, el) {
var id , $row = $(el), lock_data, avatar;
id = $row.data("id");
if (locked.hasOwnProperty(id)) {
if (!$row.hasClass('wp-locked')) {
lock_data = locked[id];
$row.find('.locked-text').text(lock_data.text);
$row.find('.check-column input[type=checkbox]').prop('checked', false);
if (lock_data.avatar_src) {
avatar = $('<img class="avatar avatar-18 photo" width="18" height="18" />').attr('src', lock_data.avatar_src.replace(/&amp;/g, '&'));
$row.find('.locked-avatar').empty().append(avatar);
}
$row.addClass('wp-locked');
}
} else if ($row.hasClass('wp-locked')) {
$row.removeClass('wp-locked').delay(1000).find('.locked-info span').empty();
}
});
}).on('heartbeat-send.' + checkLocksKey, function (e, data) {
var check = [];
$('.gf-locking').each(function (i, row) {
check.push($(row).data("id"));
});
if (check.length)
data[checkLocksKey] = check;
});
}
}(window.gflocking = window.gflocking || {}, jQuery));

View File

@@ -0,0 +1 @@
!function(a,o){var e;o(document).ready(function(){e=gflockingVars.objectType,a.init()}),a.init=function(){var n;n="gform-check-locked-objects-"+e,wp.heartbeat.interval(30),o(document).on("heartbeat-tick."+n,function(a,e){var c=e[n]||{};o(".gf-locking").each(function(a,e){var e=o(e),t=e.data("id");c.hasOwnProperty(t)?e.hasClass("wp-locked")||(t=c[t],e.find(".locked-text").text(t.text),e.find(".check-column input[type=checkbox]").prop("checked",!1),t.avatar_src&&(t=o('<img class="avatar avatar-18 photo" width="18" height="18" />').attr("src",t.avatar_src.replace(/&amp;/g,"&")),e.find(".locked-avatar").empty().append(t)),e.addClass("wp-locked")):e.hasClass("wp-locked")&&e.removeClass("wp-locked").delay(1e3).find(".locked-info span").empty()})}).on("heartbeat-send."+n,function(a,e){var t=[];o(".gf-locking").each(function(a,e){t.push(o(e).data("id"))}),t.length&&(e[n]=t)})}}(window.gflocking=window.gflocking||{},jQuery);

View File

@@ -0,0 +1,42 @@
(function (gflocking, $) {
var objectID, objectType;
$(document).ready( function() {
objectID = gflockingVars.objectID;
objectType = gflockingVars.objectType;
gflocking.init();
});
gflocking.init = function () {
initHeartbeat();
};
function initHeartbeat() {
wp.heartbeat.interval( 30 );
var checkLocksKey = 'gform-check-locked-objects-' + objectType;
$( document ).on( 'heartbeat-tick.' + checkLocksKey, function( e, data ) {
var locked = data[checkLocksKey] || {};
if ( locked.hasOwnProperty( objectID ) ) {
var lock_data = locked[objectID];
$('.locked-text').text( lock_data.text );
if ( lock_data.avatar_src ) {
var avatar = $('<img class="avatar avatar-18 photo" width="18" height="18" />').attr( 'src', lock_data.avatar_src.replace(/&amp;/g, '&') );
$('.locked-avatar').empty().append( avatar );
}
} else {
$(".locked-info span").empty();
}
}).on( 'heartbeat-send.' + checkLocksKey, function( e, data ) {
var check = [];
check.push( objectID);
data[checkLocksKey] = check;
});
}
}(window.gflocking = window.gflocking || {}, jQuery));

View File

@@ -0,0 +1 @@
!function(t,e){var o,a;e(document).ready(function(){o=gflockingVars.objectID,a=gflockingVars.objectType,t.init()}),t.init=function(){var n;wp.heartbeat.interval(30),n="gform-check-locked-objects-"+a,e(document).on("heartbeat-tick."+n,function(t,a){var a=a[n]||{};a.hasOwnProperty(o)?(a=a[o],e(".locked-text").text(a.text),a.avatar_src&&(a=e('<img class="avatar avatar-18 photo" width="18" height="18" />').attr("src",a.avatar_src.replace(/&amp;/g,"&")),e(".locked-avatar").empty().append(a))):e(".locked-info span").empty()}).on("heartbeat-send."+n,function(t,a){var e=[];e.push(o),a[n]=e})}}(window.gflocking=window.gflocking||{},jQuery);

View File

@@ -0,0 +1,192 @@
(function (gflocking, $) {
$(document).ready(function () {
gflocking.init();
});
var objectID, objectType, strings, hasLock, lockUI, rejectionCountdown, rejectionRequestTimeout, lockRequestInProgress = false;
gflocking.init = function () {
hasLock = gflockingVars.hasLock;
objectID = gflockingVars.objectID;
objectType = gflockingVars.objectType;
lockUI = gflockingVars.lockUI;
strings = gflockingVars.strings;
initHeartbeat();
initUI();
};
function lock_request_timedout() {
$("#gform-lock-request-status").html( gform.utils.escapeHtml( strings.noResponse ) );
$("#gform-lock-request-button").attr("disabled", false).text( strings.requestAgain );
lockRequestInProgress = false;
rejectionRequestTimeout = true;
rejectionCountdown = false;
wp.heartbeat.interval( 30 );
}
function initUI() {
$("#gform-lock-request-button").click(function () {
var $this = $(this), key;
$this.text("Request sent");
$this.attr("disabled", true);
$("#gform-lock-request-status").html("");
rejectionRequestTimeout = false;
lockRequestInProgress = true;
wp.heartbeat.interval( 5 );
rejectionCountdown = setTimeout(lock_request_timedout, 120000);
$.getJSON(ajaxurl, { action: "gf_lock_request_" + objectType, object_id: objectID })
.done(function (json) {
$("#gform-lock-request-status").html( gform.utils.escapeScripts( json.html ) );
})
.fail(function (jqxhr, textStatus, error) {
var err = textStatus + ', ' + error;
$("#gform-lock-request-status").html( gform.utils.escapeScripts( strings.requestError + ": " + err ) );
});
});
$("#gform-reject-lock-request-button").click(function () {
$.getJSON(ajaxurl, { action: "gf_reject_lock_request_" + objectType, object_id: objectID, object_type: objectType })
.done(function (json) {
$('#gform-lock-dialog').hide();
})
.fail(function (jqxhr, textStatus, error) {
var err = textStatus + ', ' + error;
$("#gform-lock-request-status").html( gform.utils.escapeScripts( strings.requestError + ": " + err ) );
$('#gform-lock-dialog').hide();
});
});
}
function initHeartbeat() {
wp.heartbeat.interval( 30 );
$( "#wpwrap" ).append( lockUI );
// todo: refresh nonces
var refreshLockKey = 'gform-refresh-lock-' + objectType;
var requestLockKey = 'gform-request-lock-' + objectType;
$(document).on('heartbeat-send.' + refreshLockKey, function (e, data) {
var send = {};
if (!objectID || !$('#gform-lock-dialog').length)
return;
if (hasLock == 0)
return;
send['objectID'] = objectID;
data[refreshLockKey] = send;
});
$(document).on('heartbeat-send.' + requestLockKey, function (e, data) {
var send = {};
if (!lockRequestInProgress)
return data;
send['objectID'] = objectID;
data[requestLockKey] = send;
});
// update the lock or show the dialog if somebody has taken over editing
$(document).on('heartbeat-tick.' + refreshLockKey, function (e, data) {
var received, wrap, avatar, details;
if (data[refreshLockKey]) {
received = data[refreshLockKey];
if (received.lock_error || received.lock_request) {
details = received.lock_error ? received.lock_error : received.lock_request;
wrap = $('#gform-lock-dialog');
if (!wrap.length)
return;
if (!wrap.is(':visible')) {
if (details.avatar_src) {
avatar = $('<img class="avatar avatar-64 photo" width="64" height="64" />').attr('src', details.avatar_src.replace(/&amp;/g, '&'));
wrap.find('div.gform-locked-avatar').empty().append(avatar);
}
wrap.show().find('.currently-editing').text(details.text);
if (received.lock_request) {
$("#gform-reject-lock-request-button").show();
} else {
$("#gform-reject-lock-request-button").hide();
}
wrap.find('.wp-tab-first').focus();
} else {
// dialog is already visible so the context is different
if (received.lock_error) {
if ($("#gform-reject-lock-request-button").is(":visible")) {
if (received.lock_error.avatar_src) {
avatar = $('<img class="avatar avatar-64 photo" width="64" height="64" />').attr('src', received.lock_error.avatar_src.replace(/&amp;/g, '&'));
wrap.find('div.gform-locked-avatar').empty().append(avatar);
}
$("#gform-reject-lock-request-button").hide();
wrap.show().find('.currently-editing').text(received.lock_error.text);
}
} else if (received.lock_request) {
$("#gform-lock-request-status").html( gform.utils.escapeScripts( received.lock_request.text ) );
}
}
}
}
});
$(document).on('heartbeat-tick.' + requestLockKey, function (e, data) {
var received, wrap, status;
if (data[requestLockKey]) {
received = data[requestLockKey];
if (received.status) {
status = received.status;
wrap = $('#gform-lock-dialog');
if (!wrap.length)
return;
if (status != 'pending') {
clearTimeout(rejectionCountdown);
rejectionCountdown = false;
lockRequestInProgress = false
}
switch (status) {
case "granted" :
$("#gform-lock-request-status").html(strings.gainedControl);
$("#gform-take-over-button").show();
$("#gform-lock-request-button").hide();
hasLock = true;
break;
case "deleted" :
$("#gform-lock-request-button").text(strings.requestAgain).attr("disabled", false);
$("#gform-lock-request-status").html(strings.rejected);
break;
case "pending" :
$("#gform-lock-request-status").html(strings.pending);
}
}
}
});
}
}(window.gflocking = window.gflocking || {}, jQuery));

View File

@@ -0,0 +1 @@
!function(t,s){s(document).ready(function(){t.init()});var a,e,i,n,r,l,u=!1;function g(){s("#gform-lock-request-status").html(gform.utils.escapeHtml(i.noResponse)),s("#gform-lock-request-button").attr("disabled",!1).text(i.requestAgain),l=!!(u=!1),wp.heartbeat.interval(30)}t.init=function(){var c,o;n=gflockingVars.hasLock,a=gflockingVars.objectID,e=gflockingVars.objectType,r=gflockingVars.lockUI,i=gflockingVars.strings,wp.heartbeat.interval(30),s("#wpwrap").append(r),c="gform-refresh-lock-"+e,o="gform-request-lock-"+e,s(document).on("heartbeat-send."+c,function(t,e){var r={};a&&s("#gform-lock-dialog").length&&0!=n&&(r.objectID=a,e[c]=r)}),s(document).on("heartbeat-send."+o,function(t,e){var r={};if(!u)return e;r.objectID=a,e[o]=r}),s(document).on("heartbeat-tick."+c,function(t,e){var r,o,a;e[c]&&((e=e[c]).lock_error||e.lock_request)&&(a=e.lock_error||e.lock_request,(r=s("#gform-lock-dialog")).length)&&(r.is(":visible")?e.lock_error?s("#gform-reject-lock-request-button").is(":visible")&&(e.lock_error.avatar_src&&(o=s('<img class="avatar avatar-64 photo" width="64" height="64" />').attr("src",e.lock_error.avatar_src.replace(/&amp;/g,"&")),r.find("div.gform-locked-avatar").empty().append(o)),s("#gform-reject-lock-request-button").hide(),r.show().find(".currently-editing").text(e.lock_error.text)):e.lock_request&&s("#gform-lock-request-status").html(gform.utils.escapeScripts(e.lock_request.text)):(a.avatar_src&&(o=s('<img class="avatar avatar-64 photo" width="64" height="64" />').attr("src",a.avatar_src.replace(/&amp;/g,"&")),r.find("div.gform-locked-avatar").empty().append(o)),r.show().find(".currently-editing").text(a.text),e.lock_request?s("#gform-reject-lock-request-button").show():s("#gform-reject-lock-request-button").hide(),r.find(".wp-tab-first").focus()))}),s(document).on("heartbeat-tick."+o,function(t,e){if(e[o]&&(e=e[o]).status&&(e=e.status,s("#gform-lock-dialog").length))switch("pending"!=e&&(clearTimeout(l),u=l=!1),e){case"granted":s("#gform-lock-request-status").html(i.gainedControl),s("#gform-take-over-button").show(),s("#gform-lock-request-button").hide(),n=!0;break;case"deleted":s("#gform-lock-request-button").text(i.requestAgain).attr("disabled",!1),s("#gform-lock-request-status").html(i.rejected);break;case"pending":s("#gform-lock-request-status").html(i.pending)}}),s("#gform-lock-request-button").click(function(){var t=s(this);t.text("Request sent"),t.attr("disabled",!0),s("#gform-lock-request-status").html(""),u=!!1,wp.heartbeat.interval(5),l=setTimeout(g,12e4),s.getJSON(ajaxurl,{action:"gf_lock_request_"+e,object_id:a}).done(function(t){s("#gform-lock-request-status").html(gform.utils.escapeScripts(t.html))}).fail(function(t,e,r){e=e+", "+r;s("#gform-lock-request-status").html(gform.utils.escapeScripts(i.requestError+": "+e))})}),s("#gform-reject-lock-request-button").click(function(){s.getJSON(ajaxurl,{action:"gf_reject_lock_request_"+e,object_id:a,object_type:e}).done(function(t){s("#gform-lock-dialog").hide()}).fail(function(t,e,r){e=e+", "+r;s("#gform-lock-request-status").html(gform.utils.escapeScripts(i.requestError+": "+e)),s("#gform-lock-dialog").hide()})})}}(window.gflocking=window.gflocking||{},jQuery);

View File

@@ -0,0 +1,173 @@
<?php
if ( ! class_exists( 'GFForms' ) ) {
die();
}
require_once( 'class-gf-locking.php' );
class GFFormLocking extends GFLocking {
public function __construct() {
$capabilities = array( 'gravityforms_edit_forms' );
$redirect_url = admin_url( 'admin.php?page=gf_edit_forms' );
$form_id = $this->get_object_id();
$edit_url = admin_url( sprintf( 'admin.php?page=gf_edit_forms&id=%d', $form_id ) );
parent::__construct( 'form', $redirect_url, $edit_url, $capabilities );
}
public function get_strings() {
$strings = array(
'currently_locked' => __( 'This form is currently locked. Click on the "Request Control" button to let %s know you\'d like to take over.', 'gravityforms' ),
'accept' => __( 'Accept', 'gravityforms' ),
'currently_editing' => __( '%s is currently editing this form', 'gravityforms' ),
'taken_over' => __( '%s has taken over and is currently editing this form.', 'gravityforms' ),
'lock_requested' => __( '%s has requested permission to take over control of this form.', 'gravityforms' )
);
return array_merge( parent::get_strings(), $strings );
}
protected function is_edit_page() {
return $this->is_page( 'form_editor' );
}
protected function is_list_page() {
return $this->is_page( 'form_list' );
}
protected function get_object_id() {
$id = rgget( 'id' );
$id = absint( $id );
return $id;
}
}
new GFFormLocking();
class GFEntryLocking extends GFLocking {
public function __construct() {
$capabilities = array( 'gravityforms_edit_entries' );
$redirect_url = admin_url( 'admin.php?page=gf_entries' );
$entry_id = $this->get_object_id();
$form_id = rgget( 'id' );
$edit_url = admin_url( sprintf( 'admin.php?page=gf_entries&view=entry&id=%d&lid=%d', $form_id, $entry_id ) );
parent::__construct( 'entry', $redirect_url, $edit_url, $capabilities );
}
public function get_strings() {
$strings = array(
'currently_locked' => __( 'This entry is currently locked. Click on the "Request Control" button to let %s know you\'d like to take over.', 'gravityforms' ),
'currently_editing' => __( '%s is currently editing this entry', 'gravityforms' ),
'taken_over' => __( '%s has taken over and is currently editing this entry.', 'gravityforms' ),
'lock_requested' => __( '%s has requested permission to take over control of this entry.', 'gravityforms' )
);
return array_merge( parent::get_strings(), $strings );
}
protected function is_edit_page() {
return $this->is_page( 'entry_detail_edit' );
}
protected function is_list_page() {
return $this->is_page( 'entry_list' );
}
protected function is_view_page() {
return $this->is_page( 'entry_detail' );
}
protected function get_object_id() {
$id = rgget( 'lid' );
$id = absint( $id );
return $id;
}
}
new GFEntryLocking();
class GFFormSettingsLocking extends GFLocking {
public function __construct() {
$capabilities = array( 'gravityforms_edit_forms' );
$redirect_url = admin_url( 'admin.php?page=gf_edit_forms' );
$form_id = rgget( 'id' );
$subview = rgget( 'subview' );
if ( empty( $subview ) ) {
$subview = 'settings';
}
$edit_url = admin_url( sprintf( 'admin.php?page=gf_edit_forms&view=settings&subview=%s&id=%d', esc_attr( $subview ), $form_id ) );
parent::__construct( 'form_settings', $redirect_url, $edit_url, $capabilities );
}
public function get_strings() {
$strings = array(
'currently_locked' => __( 'These form settings are currently locked. Click on the "Request Control" button to let %s know you\'d like to take over.', 'gravityforms' ),
'currently_editing' => '%s is currently editing these settings',
'taken_over' => '%s has taken over and is currently editing these settings.',
'lock_requested' => __( '%s has requested permission to take over control of these settings.', 'gravityforms' )
);
return array_merge( parent::get_strings(), $strings );
}
protected function is_edit_page() {
$is_edit_page = rgget( 'page' ) == 'gf_edit_forms' && rgget( 'view' ) == 'settings';
return $is_edit_page;
}
protected function get_object_id() {
$subview = rgget( 'subview' );
if ( empty( $subview ) || ! ctype_alnum( $subview ) ) {
$subview = 'settings';
}
$form_id = rgget( 'id' );
$form_id = absint( $form_id );
return $subview . '-' . $form_id;
}
}
new GFFormSettingsLocking();
class GFPluginSettingsLocking extends GFLocking {
public function __construct() {
$capabilities = array( 'gravityforms_edit_settings' );
$redirect_url = admin_url( 'admin.php?page=gf_edit_forms' );
$edit_url = admin_url( 'admin.php?page=gf_settings' );
parent::__construct( 'plugin_settings', $redirect_url, $edit_url, $capabilities );
}
public function get_strings() {
$strings = array(
'currently_locked' => __( 'These settings are currently locked. Click on the "Request Control" button to let %s know you\'d like to take over.', 'gravityforms' ),
'currently_editing' => '%s is currently editing these settings',
'taken_over' => '%s has taken over and is currently editing these settings.',
'lock_requested' => __( '%s has requested permission to take over control of these settings.', 'gravityforms' )
);
return array_merge( parent::get_strings(), $strings );
}
protected function is_edit_page() {
return $this->is_page( 'settings' );
}
protected function get_object_id() {
$view = rgget( 'subview' );
if ( empty( $view ) || ! ctype_alnum( $view ) ) {
$view = 'settings';
}
return $view;
}
}
new GFPluginSettingsLocking();