GravityView  2.17
The best, easiest way to display Gravity Forms entries on your website.
class-gravityview-entry-link-shortcode.php
Go to the documentation of this file.
1 <?php
2 
3 /**
4  * Handle the [gv_entry_link] shortcode
5  *
6  * Replaces [gv_edit_entry_link] and [gv_delete_entry_link] shortcodes
7  *
8  * @since 1.15
9  */
11 
12  /**
13  * @type array Entry fetched using the $atts['entry_id'] shortcode setting.
14  * @since 1.15
15  */
16  private $entry = array();
17 
18  /**
19  * @type int If set, generate a link to the entry for this View ID. Required when used outside a View. Otherwise, current View ID is used.
20  * @since 1.15
21  */
22  private $view_id = 0;
23 
24  /**
25  * @type array The accepted shortcode attribute pairs, with defaults set
26  * @since 1.15
27  */
28  static private $defaults = array(
29  'action' => 'read',
30  'view_id' => 0,
31  'entry_id' => 0,
32  'post_id' => 0,
33  'link_atts' => '',
34  'return' => 'html',
35  'field_values' => '',
36  );
37 
38  /**
39  * @type array The final settings for the shortcode, after merging passed $atts with self::$defaults
40  * @since 1.15
41  */
42  private $settings = array();
43 
44  function __construct() {
45  $this->add_hooks();
46  }
47 
48  /**
49  * Add shortcodes
50  *
51  * @since 1.15
52  */
53  private function add_hooks() {
54  add_shortcode( 'gv_entry_link', array( $this, 'read_shortcode' ) );
55  add_shortcode( 'gv_edit_entry_link', array( $this, 'edit_shortcode' ) );
56  add_shortcode( 'gv_delete_entry_link', array( $this, 'delete_shortcode' ) );
57  }
58 
59  /**
60  * @since 1.15
61  * @copydoc GravityView_Entry_Link_Shortcode::shortcode
62  */
63  public function read_shortcode( $atts, $content = null, $context = 'gv_entry_link' ) {
64  return $this->shortcode( $atts, $content, $context );
65  }
66 
67  /**
68  * Backward compatibility for existing `gv_edit_entry_link` shortcode
69  * Forces $atts['action'] to "edit"
70  *
71  * @since 1.15
72  * @copydoc GravityView_Entry_Link_Shortcode::shortcode
73  */
74  public function edit_shortcode( $atts = array(), $content = null, $context = 'gv_edit_entry_link' ) {
75 
76  $atts = shortcode_atts( self::$defaults, $atts );
77 
78  $atts['action'] = 'edit';
79 
80  return $this->shortcode( $atts, $content, $context );
81  }
82 
83  /**
84  * Backward compatibility for existing `gv_delete_entry_link` shortcodes
85  * Forces $atts['action'] to "delete"
86  *
87  * @since 1.15
88  * @copydoc GravityView_Entry_Link_Shortcode::shortcode
89  */
90  public function delete_shortcode( $atts = array(), $content = null, $context = 'gv_delete_entry_link' ) {
91 
92  $atts = shortcode_atts( self::$defaults, $atts );
93 
94  $atts['action'] = 'delete';
95 
96  return $this->shortcode( $atts, $content, $context );
97  }
98 
99  /**
100  * Generate a link to an entry. The link can be an edit, delete, or standard link.
101  *
102  * @since 1.15
103  *
104  * @param array $atts {
105  * @type string $action What type of link to generate. Options: `read`, `edit`, and `delete`. Default: `read`
106  * @type string $view_id Define the ID for the View. If not set, use current View ID, if exists.
107  * @type string $entry_id ID of the entry to edit. If undefined, uses the current entry ID, if exists.
108  * @type string $post_id ID of the base post or page to use for an embedded View
109  * @type string $link_atts Pass anchor tag attributes (`target=_blank` to open Edit Entry link in a new window, for example)
110  * @type string $return What should the shortcode return: link HTML (`html`) or the URL (`url`). Default: `html`
111  * @type string $field_values Only used for `action="edit"`. Parameters to pass in to the prefill data in Edit Entry form. Uses the same format as Gravity Forms "Allow field to be populated dynamically" {@see https://www.gravityhelp.com/documentation/article/allow-field-to-be-populated-dynamically/ }
112  * }
113  *
114  * @param string|null $content Used as link anchor text, if specified.
115  * @param string $context Current shortcode being called. Not used.
116  *
117  * @return null|string If admin or an error occurred, returns null. Otherwise, returns entry link output. If `$atts['return']` is 'url', the entry link URL. Otherwise, entry link `<a>` HTML tag.
118  */
119  private function shortcode( $atts, $content = null, $context = 'gv_entry_link' ) {
120  // Don't process when saving post. Keep processing if it's admin-ajax.php
121  if ( gravityview()->request->is_admin() ) {
122  return null;
123  }
124 
125  // Make sure GV is loaded
126  if ( ! class_exists( 'GravityView_frontend' ) || ! class_exists( 'GravityView_View' ) ) {
127  gravityview()->log->error( 'GravityView_frontend or GravityView_View do not exist.' );
128 
129  return null;
130  }
131 
132  $this->settings = shortcode_atts( self::$defaults, $atts, $context );
133 
134  $this->view_id = empty( $this->settings['view_id'] ) ? GravityView_View::getInstance()->getViewId() : absint( $this->settings['view_id'] );
135 
136  if ( empty( $this->view_id ) ) {
137  gravityview()->log->error( 'A View ID was not defined and we are not inside a View' );
138 
139  return null;
140  }
141 
142  $this->entry = $this->get_entry( $this->settings['entry_id'] );
143 
144  if ( empty( $this->entry ) ) {
145  gravityview()->log->error( 'An Entry ID was not defined or found. Entry ID: {entry_id}', array( 'entry_id' => $this->settings['entry_id'] ) );
146 
147  return null;
148  }
149 
150  gravityview()->log->debug( '{context} atts:', array( 'context' => $context, 'data' => $atts ) );
151 
152  if ( ! $this->has_cap() ) {
153  gravityview()->log->error( 'User does not have the capability to {action} this entry: {entry_id}', array( 'action' => esc_attr( $this->settings['action'] ), 'entry_id' => $this->entry['id'] ) );
154 
155  return null;
156  }
157 
158  $url = $this->get_url();
159 
160  if ( ! $url ) {
161  gravityview()->log->error( 'Link returned false; View or Post may not exist.' );
162 
163  return false;
164  }
165 
166  // Get just the URL, not the tag
167  if ( 'url' === $this->settings['return'] ) {
168  return $url;
169  }
170 
171  $link_atts = $this->get_link_atts();
172 
173  $link_text = $this->get_anchor_text( $content );
174 
176 
177  /**
178  * @filter `gravityview/shortcodes/gv_entry_link/output` Modify the output of the [gv_entry_link] shortcode
179  * @since 2.0.15
180  * @param string $return The HTML link output
181  * @param array {
182  * @type string $url The URL used to generate the anchor tag. {@see GravityView_Entry_Link_Shortcode::get_url}
183  * @type string $link_text {@see GravityView_Entry_Link_Shortcode::get_anchor_text}
184  * @type array $link_atts {@see GravityView_Entry_Link_Shortcode::get_link_atts}
185  * @type array|string $atts Shortcode atts passed to shortcode
186  * @type string $content Content passed to shortcode
187  * @type string $context The tag of the shortcode being called
188  * }
189  */
190  $return = apply_filters( 'gravityview/shortcodes/gv_entry_link/output', $return, compact( 'url', 'link_text', 'link_atts', 'atts', 'content', 'context' ) );
191 
192  return $return;
193  }
194 
195  /**
196  * Parse shortcode atts to fetch `link_atts`, which will be added to the output of the HTML anchor tag generated by shortcode
197  * Only used when `return` value of shortcode is not "url"
198  *
199  * @since 1.15
200  * @see gravityview_get_link() See acceptable attributes here
201  * @return array Array of attributes to be added
202  */
203  private function get_link_atts() {
204 
205  wp_parse_str( $this->settings['link_atts'], $link_atts );
206 
207  if ( 'delete' === $this->settings['action'] ) {
208  $link_atts['onclick'] = isset( $link_atts['onclick'] ) ? $link_atts['onclick'] : GravityView_Delete_Entry::get_confirm_dialog();
209  }
210 
211  return (array) $link_atts;
212  }
213 
214  /**
215  * Get the anchor text for the link. If content inside shortcode is defined, use that as the text. Otherwise, use default values.
216  *
217  * Only used when `return` value of shortcode is not "url"
218  *
219  * @since 1.15
220  *
221  * @param string|null $content Content inside shortcode, if defined
222  *
223  * @return string Text to use for HTML anchor
224  */
225  private function get_anchor_text( $content = null ) {
226 
227  if ( $content ) {
228  return do_shortcode( $content );
229  }
230 
231  switch ( $this->settings['action'] ) {
232  case 'edit':
233  $anchor_text = __( 'Edit Entry', 'gk-gravityview' );
234  break;
235  case 'delete':
236  $anchor_text = __( 'Delete Entry', 'gk-gravityview' );
237  break;
238  default:
239  $anchor_text = __( 'View Details', 'gk-gravityview' );
240  }
241 
242  return $anchor_text;
243  }
244 
245  /**
246  * Get the URL for the entry.
247  *
248  * Uses the `post_id`, `view_id` params as defined in the shortcode attributes.
249  *
250  * @since 1.15
251  *
252  * @param string|null $content Content inside shortcode, if defined
253  *
254  * @return string|boolean If URL is fetched, the URL to the entry link. If not found, returns false.
255  */
256  private function get_url() {
257 
258  // if post_id is not defined, default to view_id
259  $post_id = empty( $this->settings['post_id'] ) ? $this->view_id : $this->settings['post_id'];
260 
261  switch ( $this->settings['action'] ) {
262  case 'edit':
263  $url = GravityView_Edit_Entry::get_edit_link( $this->entry, $this->view_id, $post_id );
264  break;
265  case 'delete':
266  $url = GravityView_Delete_Entry::get_delete_link( $this->entry, $this->view_id, $post_id );
267  break;
268  case 'read':
269  default:
270  $url = GravityView_API::entry_link( $this->entry, $post_id );
271  }
272 
274 
275  return $url;
276  }
277 
278  /**
279  * Check whether the user has the capability to see the shortcode output, depending on the action ('read', 'edit', 'delete')
280  *
281  * @since 1.15
282  * @return bool True: has cap.
283  */
284  private function has_cap() {
285 
286  switch ( $this->settings['action'] ) {
287  case 'edit':
288  $has_cap = GravityView_Edit_Entry::check_user_cap_edit_entry( $this->entry, $this->view_id );
289  break;
290  case 'delete':
291  $has_cap = GravityView_Delete_Entry::check_user_cap_delete_entry( $this->entry, array(), $this->view_id );
292  break;
293  case 'read':
294  default:
295  $has_cap = true; // TODO: add cap check for read_gravityview
296  }
297 
298  return $has_cap;
299  }
300 
301  /**
302  * Get entry array from `entry_id` parameter. If no $entry_id
303  *
304  * @since 1.15
305  * @uses GVCommon::get_entry
306  * @uses GravityView_frontend::getSingleEntry
307  *
308  * @param int|string $entry_id Gravity Forms Entry ID. If not passed, current View's current entry ID will be used, if found.
309  *
310  * @return array|bool Gravity Forms array, if found. Otherwise, false.
311  */
312  private function get_entry( $entry_id = 0 ) {
313  static $entries = array();
314 
315  if ( empty( $entry_id ) ) {
316  $backup_entry = GravityView_frontend::getInstance()->getSingleEntry() ? GravityView_frontend::getInstance()->getEntry() : GravityView_View::getInstance()->getCurrentEntry();
317 
318  if ( ! $backup_entry ) {
319  gravityview()->log->error( 'No entry defined (or entry id not valid number)', array( 'data' => $this->settings ) );
320 
321  return false;
322  }
323 
324  $entry = $backup_entry;
325  } else if ( in_array( $entry_id, [ 'first', 'last' ] ) ) {
326  $view = GV\View::by_id( $this->view_id );
327 
328  if ( ! $view ) {
329  gravityview()->log->error( "A View with ID {$this->view_id} was not found." );
330 
331  return false;
332  }
333 
334  if ( ! isset( $entry[ $entry_id ] ) ) {
335  $entry = 'last' === $entry_id ? $view->get_entries( null )->first() : $view->get_entries( null )->last();
336  }
337 
338  if ( $entry ) {
339  $entry = $entry->as_entry();
340  }
341  } else {
342  $entry = isset( $entries[ $entry_id ] ) ? $entries[ $entry_id ] : GVCommon::get_entry( $entry_id, true, false );
343  }
344 
345  if ( $entry ) {
346  $entries[ $entry_id ] = $entry;
347  } else {
348  // No search results
349  gravityview()->log->error( 'No entries match the entry ID defined: {entry_id}', array( 'entry_id' => $entry_id ) );
350 
351  return false;
352  }
353 
354  return $entry;
355  }
356 
357  /**
358  * Allow passing URL params to dynamically populate the Edit Entry form
359  * If `field_values` key is set, run it through `parse_str()` and add the values to $url
360  *
361  * @since 1.15
362  *
363  * @param string $href URL
364  */
366 
367  if ( $url && ! empty( $this->settings['field_values'] ) ) {
368 
369  wp_parse_str( $this->settings['field_values'], $field_values );
370 
371  $url = add_query_arg( $field_values, $url );
372  }
373 
374  return $url;
375  }
376 }
377 
$url
Definition: post_image.php:25
static get_delete_link( $entry, $view_id=0, $post_id=null)
Generate a nonce link with the base URL of the current View embed.
static get_edit_link( $entry, $view_id, $post_id=null, $field_values='')
The edit entry link creates a secure link with a nonce.
Handle the [gv_entry_link] shortcode.
static getInstance( $passed_post=NULL)
$settings
array The final settings for the shortcode, after merging passed $atts with self::$defaults ...
static check_user_cap_edit_entry( $entry, $view=0)
checks if user has permissions to edit a specific entry
$entry
array Entry fetched using the $atts[&#39;entry_id&#39;] shortcode setting.
$entries
gravityview_get_link( $href='', $anchor_text='', $atts=array())
Generate an HTML anchor tag with a list of supported attributes.
$view_id
int If set, generate a link to the entry for this View ID.
has_cap()
Check whether the user has the capability to see the shortcode output, depending on the action (&#39;read...
add_hooks()
Add shortcodes.
get_anchor_text( $content=null)
Get the anchor text for the link.
if(empty( $field_settings['content'])) $content
Definition: custom.php:37
static get_confirm_dialog()
Get the onclick attribute for the confirm dialogs that warns users before they delete an entry...
static check_user_cap_delete_entry( $entry, $field=array(), $view=0)
checks if user has permissions to view the link or delete a specific entry
static by_id( $post_id)
Construct a instance from a post ID.
edit_shortcode( $atts=array(), $content=null, $context='gv_edit_entry_link')
Backward compatibility for existing gv_edit_entry_link shortcode Forces $atts[&#39;action&#39;] to "edit"...
get_entry( $entry_id=0)
Get entry array from entry_id parameter.
maybe_add_field_values_query_args( $url)
Allow passing URL params to dynamically populate the Edit Entry form If field_values key is set...
get_link_atts()
Parse shortcode atts to fetch link_atts, which will be added to the output of the HTML anchor tag gen...
delete_shortcode( $atts=array(), $content=null, $context='gv_delete_entry_link')
Backward compatibility for existing gv_delete_entry_link shortcodes Forces $atts[&#39;action&#39;] to "delete...
shortcode( $atts, $content=null, $context='gv_entry_link')
Generate a link to an entry.
read_shortcode( $atts, $content=null, $context='gv_entry_link')
Generate a link to an entry.
gravityview()
The main GravityView wrapper function.
get_url()
Get the URL for the entry.
static $defaults
array The accepted shortcode attribute pairs, with defaults set
static get_entry( $entry_slug, $force_allow_ids=false, $check_entry_display=true, $view=null)
Return a single entry object.
static entry_link( $entry, $post_id=NULL, $add_directory_args=true, $view_id=0)
return href for single entry
Definition: class-api.php:656
__construct()
new GravityView_Entry_Link_Shortcode
static getInstance()
Get the one true instantiated self.