GravityView  2.10.1
The best, easiest way to display Gravity Forms entries on your website.
class-edit-entry.php
Go to the documentation of this file.
1 <?php
2 /**
3  * The GravityView Edit Entry Extension
4  *
5  * Easily edit entries in GravityView.
6  *
7  * @package GravityView
8  * @license GPL2+
9  * @author GravityView <[email protected]>
10  * @link http://gravityview.co
11  * @copyright Copyright 2014, Katz Web Services, Inc.
12  */
13 
14 if ( ! defined( 'WPINC' ) ) {
15  die;
16 }
17 
18 
20 
21  /**
22  * @var string
23  */
24  static $file;
25 
26  static $instance;
27 
28  /**
29  * Component instances.
30  * @var array
31  */
32  public $instances = array();
33 
34 
35  function __construct() {
36 
37  self::$file = plugin_dir_path( __FILE__ );
38 
39  if( is_admin() ) {
40  $this->load_components( 'admin' );
41  }
42 
43  $this->load_components( 'locking' );
44 
45  $this->load_components( 'render' );
46 
47  // If GF User Registration Add-on exists
48  $this->load_components( 'user-registration' );
49 
50  $this->add_hooks();
51 
52  // Process hooks for addons that may or may not be present
53  $this->addon_specific_hooks();
54  }
55 
56 
57  static function getInstance() {
58 
59  if( empty( self::$instance ) ) {
60  self::$instance = new GravityView_Edit_Entry;
61  }
62 
63  return self::$instance;
64  }
65 
66 
67  private function load_components( $component ) {
68 
69  $dir = trailingslashit( self::$file );
70 
71  $filename = $dir . 'class-edit-entry-' . $component . '.php';
72  $classname = 'GravityView_Edit_Entry_' . str_replace( ' ', '_', ucwords( str_replace( '-', ' ', $component ) ) );
73 
74  // Loads component and pass extension's instance so that component can
75  // talk each other.
76  require_once $filename;
77  $this->instances[ $component ] = new $classname( $this );
78  $this->instances[ $component ]->load();
79 
80  }
81 
82  private function add_hooks() {
83 
84  // Add front-end access to Gravity Forms delete file action
85  add_action( 'wp_ajax_nopriv_rg_delete_file', array( 'GFForms', 'delete_file') );
86 
87  // Make sure this hook is run for non-admins
88  add_action( 'wp_ajax_rg_delete_file', array( 'GFForms', 'delete_file') );
89 
90  add_filter( 'gravityview_blacklist_field_types', array( $this, 'modify_field_blacklist' ), 10, 2 );
91 
92  // add template path to check for field
93  add_filter( 'gravityview_template_paths', array( $this, 'add_template_path' ) );
94 
95  add_filter( 'gravityview/field/is_visible', array( $this, 'maybe_not_visible' ), 10, 3 );
96 
97  add_filter( 'gravityview/api/reserved_query_args', array( $this, 'add_reserved_arg' ) );
98  }
99 
100  /**
101  * Adds "edit" to the list of internal reserved query args
102  *
103  * @since 2.10
104  *
105  * @param array $args Existing reserved args
106  *
107  * @return array
108  */
109  public function add_reserved_arg( $args ) {
110 
111  $args[] = 'edit';
112 
113  return $args;
114  }
115 
116  /**
117  * Trigger hooks that are normally run in the admin for Addons, but need to be triggered manually because we're not in the admin
118  * @return void
119  */
120  private function addon_specific_hooks() {
121 
122  if( class_exists( 'GFSignature' ) && is_callable( array( 'GFSignature', 'get_instance' ) ) ) {
123  add_filter('gform_admin_pre_render', array( GFSignature::get_instance(), 'edit_lead_script'));
124  }
125 
126  }
127 
128  /**
129  * Hide the field or not.
130  *
131  * For non-logged in users.
132  * For users that have no edit rights on any of the current entries.
133  *
134  * @param bool $visible Visible or not.
135  * @param \GV\Field $field The field.
136  * @param \GV\View $view The View context.
137  *
138  * @return bool
139  */
140  public function maybe_not_visible( $visible, $field, $view ) {
141 
142  if ( 'edit_link' !== $field->ID ) {
143  return $visible;
144  }
145 
146  if ( ! $view instanceof \GV\View ) {
147  return $visible;
148  }
149 
150  static $visibility_cache_for_view = array();
151 
152  if ( ! is_null( $result = \GV\Utils::get( $visibility_cache_for_view, $view->ID, null ) ) ) {
153  return $result;
154  }
155 
156  foreach ( $view->get_entries()->all() as $entry ) {
157  if ( self::check_user_cap_edit_entry( $entry->as_entry(), $view ) ) {
158  // At least one entry is deletable for this user
159  $visibility_cache_for_view[ $view->ID ] = true;
160  return true;
161  }
162  }
163 
164  $visibility_cache_for_view[ $view->ID ] = false;
165 
166  return false;
167  }
168 
169  /**
170  * Include this extension templates path
171  * @param array $file_paths List of template paths ordered
172  */
173  public function add_template_path( $file_paths ) {
174 
175  // Index 100 is the default GravityView template path.
176  $file_paths[ 110 ] = self::$file;
177 
178  return $file_paths;
179  }
180 
181  /**
182  *
183  * Return a well formatted nonce key according to GravityView Edit Entry protocol
184  *
185  * @param $view_id int GravityView view id
186  * @param $form_id int Gravity Forms form id
187  * @param $entry_id int Gravity Forms entry id
188  * @return string
189  */
190  public static function get_nonce_key( $view_id, $form_id, $entry_id ) {
191  return sprintf( 'edit_%d_%d_%d', $view_id, $form_id, $entry_id );
192  }
193 
194 
195  /**
196  * The edit entry link creates a secure link with a nonce
197  *
198  * It also mimics the URL structure Gravity Forms expects to have so that
199  * it formats the display of the edit form like it does in the backend, like
200  * "You can edit this post from the post page" fields, for example.
201  *
202  * @param $entry array Gravity Forms entry object
203  * @param $view_id int GravityView view id
204  * @param $post_id int GravityView Post ID where View may be embedded {@since 1.9.2}
205  * @param string|array $field_values Parameters to pass in to the Edit Entry form to prefill data. Uses the same format as Gravity Forms "Allow field to be populated dynamically" {@since 1.9.2} {@see https://www.gravityhelp.com/documentation/article/allow-field-to-be-populated-dynamically/ }
206  * @return string
207  */
208  public static function get_edit_link( $entry, $view_id, $post_id = null, $field_values = '' ) {
209 
210  $nonce_key = self::get_nonce_key( $view_id, $entry['form_id'], $entry['id'] );
211 
212  $base = gv_entry_link( $entry, $post_id ? : $view_id );
213 
214  $url = add_query_arg( array(
215  'edit' => wp_create_nonce( $nonce_key )
216  ), $base );
217 
218  if( $post_id ) {
219  $url = add_query_arg( array( 'gvid' => $view_id ), $url );
220  }
221 
222  /**
223  * Allow passing params to dynamically populate entry with values
224  * @since 1.9.2
225  */
226  if( !empty( $field_values ) ) {
227 
228  if( is_array( $field_values ) ) {
229  // If already an array, no parse_str() needed
230  $params = $field_values;
231  } else {
232  parse_str( $field_values, $params );
233  }
234 
235  $url = add_query_arg( $params, $url );
236  }
237 
238  /**
239  * @filter `gravityview/edit/link` Filter the edit URL link.
240  * @param[in,out] string $url The url.
241  * @param array $entry The entry.
242  * @param \GV\View $view The View.
243  */
244  return apply_filters( 'gravityview/edit/link', $url, $entry, \GV\View::by_id( $view_id ) );
245  }
246 
247  /**
248  * Edit mode doesn't allow certain field types.
249  * @param array $fields Existing blacklist fields
250  * @param string|null $context Context
251  * @return array If not edit context, original field blacklist. Otherwise, blacklist including post fields.
252  */
253  public function modify_field_blacklist( $fields = array(), $context = NULL ) {
254 
255  if( empty( $context ) || $context !== 'edit' ) {
256  return $fields;
257  }
258 
259  $add_fields = $this->get_field_blacklist();
260 
261  return array_merge( $fields, $add_fields );
262  }
263 
264  /**
265  * Returns array of field types that should not be displayed in Edit Entry
266  *
267  * @since 1.20
268  *
269  * @param array $entry Gravity Forms entry array
270  *
271  * @return array Blacklist of field types
272  */
273  function get_field_blacklist( $entry = array() ) {
274 
275  $fields = array(
276  'page',
277  'payment_status',
278  'payment_date',
279  'payment_amount',
280  'is_fulfilled',
281  'transaction_id',
282  'transaction_type',
283  'captcha',
284  'honeypot',
285  'creditcard',
286  );
287 
288  /**
289  * @filter `gravityview/edit_entry/field_blacklist` Array of fields that should not be displayed in Edit Entry
290  * @since 1.20
291  * @param array $fields Blacklist field type array
292  * @param array $entry Gravity Forms entry array
293  */
294  $fields = apply_filters( 'gravityview/edit_entry/field_blacklist', $fields, $entry );
295 
296  return $fields;
297  }
298 
299 
300  /**
301  * checks if user has permissions to edit a specific entry
302  *
303  * Needs to be used combined with GravityView_Edit_Entry::user_can_edit_entry for maximum security!!
304  *
305  * @param array $entry Gravity Forms entry array
306  * @param \GV\View|int $view ID of the view you want to check visibility against {@since 1.9.2}. Required since 2.0
307  * @return bool
308  */
309  public static function check_user_cap_edit_entry( $entry, $view = 0 ) {
310 
311  // No permission by default
312  $user_can_edit = false;
313 
314  // get user_edit setting
315  if ( empty( $view ) ) {
316  // @deprecated path
317  $view_id = GravityView_View::getInstance()->getViewId();
318  $user_edit = GravityView_View::getInstance()->getAtts( 'user_edit' );
319  } else {
320  if ( $view instanceof \GV\View ) {
321  $view_id = $view->ID;
322  } else {
323  $view_id = $view;
324  }
325 
326  // in case is specified and not the current view
327  $user_edit = GVCommon::get_template_setting( $view_id, 'user_edit' );
328  }
329 
330  // If they can edit any entries (as defined in Gravity Forms)
331  // Or if they can edit other people's entries
332  // Then we're good.
333  if( GVCommon::has_cap( array( 'gravityforms_edit_entries', 'gravityview_edit_others_entries' ), $entry['id'] ) ) {
334 
335  gravityview()->log->debug( 'User has ability to edit all entries.' );
336 
337  $user_can_edit = true;
338 
339  } else if( !isset( $entry['created_by'] ) ) {
340 
341  gravityview()->log->error( 'Entry `created_by` doesn\'t exist.');
342 
343  $user_can_edit = false;
344 
345  } else {
346 
347  $current_user = wp_get_current_user();
348 
349  // User edit is disabled
350  if( empty( $user_edit ) ) {
351 
352  gravityview()->log->debug( 'User Edit is disabled. Returning false.' );
353 
354  $user_can_edit = false;
355  }
356 
357  // User edit is enabled and the logged-in user is the same as the user who created the entry. We're good.
358  else if( is_user_logged_in() && intval( $current_user->ID ) === intval( $entry['created_by'] ) ) {
359 
360  gravityview()->log->debug( 'User {user_id} created the entry.', array( 'user_id', $current_user->ID ) );
361 
362  $user_can_edit = true;
363 
364  } else if( ! is_user_logged_in() ) {
365 
366  gravityview()->log->debug( 'No user defined; edit entry requires logged in user' );
367 
368  $user_can_edit = false; // Here just for clarity
369  }
370 
371  }
372 
373  /**
374  * @filter `gravityview/edit_entry/user_can_edit_entry` Modify whether user can edit an entry.
375  * @since 1.15 Added `$entry` and `$view_id` parameters
376  * @param[in,out] boolean $user_can_edit Can the current user edit the current entry? (Default: false)
377  * @param[in] array $entry Gravity Forms entry array {@since 1.15}
378  * @param[in] int $view_id ID of the view you want to check visibility against {@since 1.15}
379  */
380  $user_can_edit = apply_filters( 'gravityview/edit_entry/user_can_edit_entry', $user_can_edit, $entry, $view_id );
381 
382  return (bool) $user_can_edit;
383  }
384 
385 
386 
387 } // end class
388 
389 //add_action( 'plugins_loaded', array('GravityView_Edit_Entry', 'getInstance'), 6 );
391 
$url
Definition: post_image.php:25
static get_edit_link( $entry, $view_id, $post_id=null, $field_values='')
The edit entry link creates a secure link with a nonce.
add_reserved_arg( $args)
Adds "edit" to the list of internal reserved query args.
__construct()
static getInstance( $passed_post=NULL)
static get_template_setting( $post_id, $key)
Get the setting for a View.
static $instance
static check_user_cap_edit_entry( $entry, $view=0)
checks if user has permissions to edit a specific entry
add_hooks()
gravityview()
Definition: _stubs.php:26
maybe_not_visible( $visible, $field, $view)
Hide the field or not.
get( $key, $default=null)
Retrieve a setting.
modify_field_blacklist( $fields=array(), $context=NULL)
Edit mode doesn&#39;t allow certain field types.
$instances
add_template_path( $file_paths)
Include this extension templates path.
static get_nonce_key( $view_id, $form_id, $entry_id)
Return a well formatted nonce key according to GravityView Edit Entry protocol.
load_components( $component)
static $file
get_field_blacklist( $entry=array())
Returns array of field types that should not be displayed in Edit Entry.
if(empty( $created_by)) $form_id
gv_entry_link( $entry, $post_id=NULL)
Definition: class-api.php:926
addon_specific_hooks()
Trigger hooks that are normally run in the admin for Addons, but need to be triggered manually becaus...
static has_cap( $caps='', $object_id=null, $user_id=null)
Alias of GravityView_Roles_Capabilities::has_cap()
$entry
Definition: notes.php:27
$field
Definition: gquiz_grade.php:11
static getInstance()