15 if ( ! defined(
'WPINC' ) ) {
38 self::$file = plugin_dir_path( __FILE__ );
47 add_action(
'wp', array( $this,
'process_duplicate' ), 10000 );
49 add_filter(
'gravityview_entry_default_fields', array( $this,
'add_default_field' ), 10, 3 );
51 add_action(
'gravityview_before', array( $this,
'maybe_display_message' ) );
54 add_filter(
'gravityview_field_visibility_caps', array( $this,
'modify_visibility_caps' ), 10, 5 );
57 add_filter(
'gravityview_template_duplicate_link_options', array( $this,
'duplicate_link_field_options' ), 10, 5 );
60 add_filter(
'gravityview_template_paths', array( $this,
'add_template_path' ) );
63 add_action(
'gform_entries_first_column_actions', array( $this,
'make_duplicate_link_row' ), 10, 5 );
66 add_action(
'gform_pre_entry_list', array( $this,
'maybe_duplicate_list' ) );
68 add_filter(
'gravityview/sortable/field_blocklist', array( $this,
'_filter_sortable_fields' ), 1 );
70 add_filter(
'gravityview/field/is_visible', array( $this,
'maybe_not_visible' ), 10, 3 );
72 add_filter(
'gravityview/api/reserved_query_args', array( $this,
'add_reserved_arg' ) );
86 $args[] =
'duplicate';
99 if ( empty( self::$instance ) ) {
100 self::$instance =
new self;
103 return self::$instance;
120 if (
'duplicate_link' !==
$field->ID ) {
128 static $visibility_cache_for_view = array();
130 if ( ! is_null( $result = \
GV\Utils::get( $visibility_cache_for_view, $view->ID, null ) ) ) {
134 foreach ( $view->get_entries()->all() as
$entry ) {
135 if ( self::check_user_cap_duplicate_entry(
$entry->as_entry(),
$field->as_configuration() ) ) {
137 $visibility_cache_for_view[ $view->ID ] =
true;
142 $visibility_cache_for_view[ $view->ID ] =
false;
158 $fields = (array) $fields;
160 $fields[] =
'duplicate_link';
178 $file_paths[ 117 ] = self::$file;
199 unset( $field_options[
'show_as_link'], $field_options[
'search_filter'], $field_options[
'new_window'] );
202 unset( $field_options[
'only_loggedin'], $field_options[
'only_loggedin_cap'] );
204 $add_option[
'duplicate_link'] = array(
206 'label' => __(
'Duplicate Link Text',
'gk-gravityview' ),
208 'value' => __(
'Duplicate Entry',
'gk-gravityview' ),
209 'merge_tags' =>
true,
212 $field_options[
'allow_duplicate_cap'] = array(
214 'label' => __(
'Allow the following users to duplicate the entry:',
'gk-gravityview' ),
216 'tooltip' =>
'allow_duplicate_cap',
217 'class' =>
'widefat',
221 return array_merge( $add_option, $field_options );
238 if (
'edit' !== $zone ) {
239 $entry_default_fields[
'duplicate_link'] = array(
240 'label' => __(
'Duplicate Entry',
'gk-gravityview' ),
241 'type' =>
'duplicate_link',
242 'desc' => __(
'A link to duplicate the entry. Respects the Duplicate Entry permissions.',
'gk-gravityview' ),
243 'icon' =>
'dashicons-controls-repeat',
247 return $entry_default_fields;
261 $available_fields[
'duplicate_link'] = array(
262 'label_text' => __(
'Duplicate Entry',
'gk-gravityview' ),
263 'field_id' =>
'duplicate_link',
264 'label_type' =>
'field',
265 'input_type' =>
'duplicate_link',
266 'field_options' => NULL
269 return $available_fields;
288 $caps = $visibility_caps;
294 unset( $caps[
'publish_posts'], $caps[
'gravityforms_view_entries'], $caps[
'duplicate_others_posts'] );
296 $caps[
'read'] = _x(
'Entry Creator',
'User capability',
'gk-gravityview' );
312 return sprintf(
'duplicate_%s', $entry_id );
333 if ( empty( $base ) ) {
334 gravityview()->log->error(
'Post ID does not exist: {post_id}', array(
'post_id' => $post_id ) );
338 $actionurl = add_query_arg( array(
339 'action' =>
'duplicate',
340 'entry_id' =>
$entry[
'id'],
342 'view_id' => $view_id,
345 return add_query_arg(
'duplicate', wp_create_nonce( self::get_nonce_key(
$entry[
'id'] ) ), $actionurl );
366 if ( ( ! isset( $_GET[
'action'] ) ) ||
'duplicate' !== $_GET[
'action'] || ( ! isset( $_GET[
'entry_id'] ) ) ) {
371 $valid_nonce_key = wp_verify_nonce( \
GV\Utils::_GET(
'duplicate' ), self::get_nonce_key( $_GET[
'entry_id'] ) );
373 if ( ! $valid_nonce_key ) {
374 gravityview()->log->debug(
'Duplicate entry not processed: nonce validation failed.' );
388 if ( is_wp_error( $has_permission ) ) {
391 'message' => urlencode( $has_permission->get_error_message() ),
400 if ( is_wp_error( $duplicate_response ) ) {
403 'message' => urlencode( $duplicate_response->get_error_message() ),
407 gravityview()->log->error(
'Entry {entry_slug} cannot be duplicated: {error_code} {error_message}', array(
409 'error_code' => $duplicate_response->get_error_code(),
410 'error_message' => $duplicate_response->get_error_message(),
416 'status' => $duplicate_response,
425 gravityview()->log->error(
'Duplicate entry failed: there was no entry with the entry slug {entry_slug}', array(
'entry_slug' =>
$entry_slug ) );
428 'message' => urlencode( __(
'The entry does not exist.',
'gk-gravityview' ) ),
433 $redirect_to_base = esc_url_raw( remove_query_arg( array(
'action',
'gvid',
'entry_id' ) ) );
434 $redirect_to = add_query_arg( $messages, $redirect_to_base );
436 if ( defined(
'DOING_GRAVITYVIEW_TESTS' ) ) {
440 wp_safe_redirect( $redirect_to );
458 if ( ! $entry_id = \
GV\Utils::get(
$entry,
'id' ) ) {
459 return new WP_Error(
'gravityview-duplicate-entry-missing', __(
'The entry does not exist.',
'gk-gravityview' ) );
462 gravityview()->log->debug(
'Starting duplicate entry: {entry_id}', array(
'entry_id' => $entry_id ) );
466 $entry_table = GFFormsModel::get_entry_table_name();
467 $entry_meta_table = GFFormsModel::get_entry_meta_table_name();
469 if ( ! $row = $wpdb->get_row( $wpdb->prepare(
"SELECT * FROM $entry_table WHERE ID = %d", $entry_id ), ARRAY_A ) ) {
470 return new WP_Error(
'gravityview-duplicate-entry-missing', __(
'The entry does not exist.',
'gk-gravityview' ) );
476 $row[
'date_created'] = date(
'Y-m-d H:i:s', time() );
477 $row[
'date_updated'] = $row[
'date_created'];
478 $row[
'is_starred'] =
false;
479 $row[
'is_read'] =
false;
480 $row[
'ip'] = rgars(
$form,
'personalData/preventIP' ) ?
'' : GFFormsModel::get_ip();
481 $row[
'source_url'] = esc_url_raw( remove_query_arg( array(
'action',
'gvid',
'result',
'duplicate',
'entry_id' ) ) );
483 $row[
'created_by'] = wp_get_current_user()->ID;
491 $row = apply_filters(
'gravityview/entry/duplicate/details', $row,
$entry );
493 if ( ! $wpdb->insert( $entry_table, $row ) ) {
494 return new WP_Error(
'gravityview-duplicate-entry-db-details', __(
'There was an error duplicating the entry.',
'gk-gravityview' ) );
497 $duplicated_id = $wpdb->insert_id;
499 $meta = $wpdb->get_results( $wpdb->prepare(
"SELECT * FROM $entry_meta_table WHERE entry_id = %d", $entry_id ), ARRAY_A );
501 $duplicate_meta =
new WP_List_Util( $meta );
504 $reset_meta = array(
'is_approved',
'gravityview_unique_id',
'workflow_current_status_timestamp' );
505 foreach ( $reset_meta as $meta_key ) {
506 $duplicate_meta->filter( array(
'meta_key' => $meta_key ),
'NOT' );
509 $save_this_meta = array();
510 foreach ( $duplicate_meta->get_output() as $m ) {
511 $save_this_meta[] = array(
512 'meta_key' => $m[
'meta_key'],
513 'meta_value' => $m[
'meta_value'],
514 'item_index' => $m[
'item_index'],
519 $row[
'id'] = $duplicated_id;
527 $save_this_meta = apply_filters(
'gravityview/entry/duplicate/meta', $save_this_meta, $row,
$entry );
529 foreach ( $save_this_meta as $data ) {
530 $data[
'form_id'] =
$entry[
'form_id'];
531 $data[
'entry_id'] = $duplicated_id;
533 if ( ! $wpdb->insert( $entry_meta_table, $data ) ) {
534 return new WP_Error(
'gravityview-duplicate-entry-db-meta', __(
'There was an error duplicating the entry.',
'gk-gravityview' ) );
538 $duplicated_entry = \GFAPI::get_entry( $duplicated_id );
540 $duplicate_response =
'duplicated';
548 do_action(
'gravityview/duplicate-entry/duplicated', $duplicated_entry,
$entry );
550 gravityview()->log->debug(
'Duplicate response: {duplicate_response}', array(
'duplicate_response' => $duplicate_response ) );
552 return $duplicate_response;
565 if ( empty( $_GET[
'entry_id'] ) || empty( $_GET[
'duplicate'] ) ) {
569 $nonce_key = self::get_nonce_key( $_GET[
'entry_id'] );
571 $valid = wp_verify_nonce( $_GET[
'duplicate'], $nonce_key );
580 $valid = apply_filters(
'gravityview/duplicate-entry/verify_nonce', $valid, $nonce_key );
594 $confirm = __(
'Are you sure you want to duplicate this entry?',
'gk-gravityview' );
601 $confirm = apply_filters(
'gravityview/duplicate-entry/confirm-text', $confirm );
603 if ( empty( $confirm ) ) {
607 return 'return window.confirm(\''. esc_js( $confirm ) .
'\');
'; 624 private function user_can_duplicate_entry( $entry = array(), $view_id = null ) {
628 if ( ! $this->verify_nonce() ) {
629 $error = __( 'The link to duplicate
this entry is not valid; it may have expired.
', 'gk-
gravityview' ); 632 if ( ! self::check_user_cap_duplicate_entry( $entry, array(), $view_id ) ) { 633 $error = __( 'You
do not have permission to duplicate
this entry.
', 'gk-
gravityview' ); 636 // No errors; everything's fine here!
637 if ( empty( $error ) ) {
641 gravityview()->log->error(
'{error}', array(
'erorr' => $error ) );
643 return new WP_Error(
'gravityview-duplicate-entry-permissions', $error );
659 $current_user = wp_get_current_user();
661 $entry_id = isset(
$entry[
'id'] ) ?
$entry[
'id'] : null;
664 if (
GVCommon::has_cap( array(
'gravityforms_edit_entries',
'gform_full_access',
'gravityview_full_access' ), $entry_id ) ) {
666 gravityview()->log->debug(
'Current user has `gravityforms_edit_entries` capability.' );
673 if ( ! empty(
$field ) ) {
676 if ( empty(
$field[
'allow_duplicate_cap'] ) ) {
678 gravityview()->log->error(
'Cannot read duplicate entry field caps', array(
'data' =>
$field ) );
686 if (
'read' !==
$field[
'allow_duplicate_cap'] ) {
692 gravityview()->log->debug(
'User {user_id} is not authorized to view duplicate entry link ', array(
'user_id' => $current_user->ID ) );
699 if ( ! isset(
$entry[
'created_by'] ) ) {
701 gravityview()->log->error(
'Cannot duplicate entry; entry `created_by` doesn\'t exist.' );
709 if ( ! $view = \
GV\View::by_id( $view_id ) ) {
713 $user_duplicate = $view->settings->get(
'user_duplicate',
false );
715 if ( empty( $user_duplicate ) ) {
717 gravityview()->log->debug(
'User Duplicate is disabled. Returning false.' );
724 if ( is_user_logged_in() && intval( $current_user->ID ) === intval(
$entry[
'created_by'] ) ) {
726 gravityview()->log->debug(
'User {user_id} created the entry.', array(
'user_id' => $current_user->ID ) );
748 if ( empty( $_GET[
'status'] ) || ! self::verify_nonce() ) {
753 if ( isset( $_GET[
'view_id'] ) && ( intval( $_GET[
'view_id'] ) !== intval( $current_view_id ) ) ) {
761 if ( empty( $_GET[
'status'] ) || empty( $_GET[
'duplicate'] ) ) {
765 $status = esc_attr( $_GET[
'status'] );
767 $message_from_url = rawurldecode( stripslashes_deep( $message_from_url ) );
772 $class =
' gv-error error';
773 $error_message = __(
'There was an error duplicating the entry: %s',
'gk-gravityview' );
774 $message = sprintf( $error_message, $message_from_url );
777 $message = __(
'The entry was successfully duplicated.',
'gk-gravityview' );
788 $message = apply_filters(
'gravityview/duplicate-entry/message', esc_attr( $message ), $status, $message_from_url );
791 echo
'<div class="gv-notice' . esc_attr(
$class ) .
'">'. $message .
'</div>';
814 if ( ! apply_filters(
'gravityview/duplicate/backend/enable',
true,
$form_id ) ) {
819 <span
class=
"gv-duplicate">
821 <a href=
"<?php echo wp_nonce_url( add_query_arg( 'entry_id', $entry['id'] ), self::get_nonce_key( $entry['id'] ), 'duplicate' ); ?>"><?php esc_html_e(
'Duplicate',
'gk-gravityview' ); ?></a>
837 if ( ! is_admin() ) {
841 if (
'success' === \
GV\Utils::_GET(
'result' ) ) {
842 add_filter(
'gform_admin_messages',
function( $messages ) {
843 $messages = (array) $messages;
845 $messages[] = esc_html__(
'Entry duplicated.',
'gk-gravityview' );
850 if (
'error' === \
GV\Utils::_GET(
'result' ) ) {
851 $check_logs_message = sprintf(
' <a href="%s">%s</a>',
852 esc_url( admin_url(
'admin.php?page=gf_settings&subview=gravityformslogging' ) ),
853 esc_html_x(
'Check the GravityView logs for more information.',
'Error message links to logging page',
'gk-gravityview' )
856 add_filter(
'gform_admin_error_messages',
function( $messages ) use ( $check_logs_message ) {
857 $messages = (array) $messages;
859 $messages[] = esc_html__(
'There was an error duplicating the entry.',
'gk-gravityview' ) . $check_logs_message;
865 if ( ! wp_verify_nonce( \
GV\Utils::_GET(
'duplicate' ), self::get_nonce_key( $entry_id = \
GV\Utils::_GET(
'entry_id' ) ) ) ) {
869 if ( !
GVCommon::has_cap( array(
'gravityforms_edit_entries',
'gform_full_access',
'gravityview_full_access' ), $entry_id ) ) {
873 $entry = GFAPI::get_entry( $entry_id );
875 if ( is_wp_error(
$entry ) ) {
881 if ( is_wp_error( $is_duplicated ) ) {
882 gravityview()->log->error(
'Error duplicating {id}: {error}', array(
'id' => $entry_id,
'error' => $is_duplicated->get_error_message() ) );
885 $return_url = remove_query_arg(
'duplicate' );
886 $return_url = add_query_arg(
'result', is_wp_error( $is_duplicated ) ?
'error' :
'success', $return_url );
888 echo
'<script>window.location.href = ' . json_encode( $return_url ) .
';</script>';
static _GET( $name, $default=null)
Grab a value from the _GET superglobal or default.
static _SERVER( $name, $default=null)
Grab a value from the _SERVER superglobal or default.
add_reserved_arg( $args)
Adds "duplicate" to the list of internal reserved query args.
maybe_duplicate_list( $form_id)
Perhaps duplicate this entry if the action has been corrected.
add_template_path( $file_paths)
Include this extension templates path.
duplicate_entry( $entry)
Duplicate the entry.
gravityview_get_entry( $entry_slug, $force_allow_ids=false, $check_entry_display=true, $view=null)
Return a single entry object.
add_available_field( $available_fields=array())
Add Duplicate Entry Link to the Add Field dialog.
duplicate_link_field_options( $field_options, $template_id, $field_id, $context, $input_type)
Add "Duplicate Link Text" setting to the edit_link field settings.
add_default_field( $entry_default_fields, $form=array(), $zone='')
Add Edit Link as a default field, outside those set in the Gravity Form form.
verify_nonce()
Is the current nonce valid for editing the entry?
if(gravityview() ->plugin->is_GF_25()) $form
static directory_link( $post_id=NULL, $add_query_args=true, $context=null)
Generate a URL to the Directory context.
static getInstance()
Return the instantiated class object.
static check_user_cap_duplicate_entry( $entry, $field=array(), $view_id=0)
checks if user has permissions to view the link or duplicate a specific entry
static get_duplicate_link( $entry, $view_id, $post_id=null)
Generate a nonce link with the base URL of the current View embed.
maybe_display_message( $current_view_id=0)
After processing duplicate entry, the user will be redirected to the referring View or embedded post/...
static get_nonce_key( $entry_id)
Generate a consistent nonce key based on the Entry ID.
modify_visibility_caps( $visibility_caps=array(), $template_id='', $field_id='', $context='', $input_type='')
Change wording for the Edit context to read Entry Creator.
static get_confirm_dialog()
Get the onclick attribute for the confirm dialogs that warns users before they duplicate an entry...
user_can_duplicate_entry( $entry=array(), $view_id=null)
Check if the user can edit the entry.
make_duplicate_link_row( $form_id, $field_id, $value, $entry, $query_string)
Add a Duplicate link to the row of actions on the entry list in the backend.
if(empty( $created_by)) $form_id
_filter_sortable_fields( $fields)
Prevent users from being able to sort by the Duplicate field.
gravityview()
The main GravityView wrapper function.
static get_cap_choices( $template_id='', $field_id='', $context='', $input_type='')
Get capabilities options for GravityView.
maybe_not_visible( $visible, $field, $view)
Hide the field or not.
static has_cap( $caps='', $object_id=null, $user_id=null)
Alias of GravityView_Roles_Capabilities::has_cap()
if(false !==strpos( $value, '00:00')) $field_id
string $field_id ID of the field being displayed
process_duplicate()
Handle the duplication request, if $_GET['action'] is set to "duplicate".