GravityView  2.17
The best, easiest way to display Gravity Forms entries on your website.
class-admin-views.php
Go to the documentation of this file.
1 <?php
2 /**
3  * Renders all the metaboxes on Add New / Edit View post type.
4  *
5  * @package GravityView
6  * @license GPL2+
7  * @author GravityView <[email protected]>
8  * @link http://gravityview.co
9  * @copyright Copyright 2014, Katz Web Services, Inc.
10  *
11  * @since 1.0.0
12  */
13 
14 /** If this file is called directly, abort. */
15 if ( ! defined( 'ABSPATH' ) ) {
16  die;
17 }
18 
20 
21 
22 
23  function __construct() {
24  add_action( 'save_post', array( $this, 'save_postdata' ) );
25 
26  // set the blocklist field types across the entire plugin
27  add_filter( 'gravityview_blocklist_field_types', array( $this, 'default_field_blocklist' ), 10, 2 );
28 
29  // Tooltips
30  add_filter( 'gform_tooltips', array( $this, 'tooltips') );
31 
32  add_filter( 'admin_body_class', array( $this, 'add_gf_version_css_class' ) );
33 
34  // adding styles and scripts
35  add_action( 'admin_enqueue_scripts', array( 'GravityView_Admin_Views', 'add_scripts_and_styles'), 999 );
36  add_filter( 'gform_noconflict_styles', array( $this, 'register_no_conflict') );
37  add_filter( 'gform_noconflict_scripts', array( $this, 'register_no_conflict') );
38  add_filter( 'gravityview_noconflict_styles', array( $this, 'register_no_conflict') );
39  add_filter( 'gravityview_noconflict_scripts', array( $this, 'register_no_conflict') );
40 
41  add_action( 'gravityview_render_directory_active_areas', array( $this, 'render_directory_active_areas'), 10, 5 );
42  add_action( 'gravityview_render_widgets_active_areas', array( $this, 'render_widgets_active_areas'), 10, 3 );
43  add_action( 'gravityview_render_field_pickers', array( $this, 'render_field_pickers'), 10, 2 );
44  add_action( 'gravityview_render_available_fields', array( $this, 'render_available_fields'), 10, 2 );
45  add_action( 'gravityview_render_available_widgets', array( $this, 'render_available_widgets') );
46  add_action( 'gravityview_render_active_areas', array( $this, 'render_active_areas'), 10, 5 );
47  add_filter( 'gravityview/view/configuration/fields', array( $this, 'set_default_view_fields'), 10, 3 );
48 
49  // @todo check if this hook is needed..
50  //add_action( 'gravityview_render_field_options', array( $this, 'render_field_options'), 10, 9 );
51 
52  // Add Connected Form column
53  add_filter('manage_gravityview_posts_columns' , array( $this, 'add_post_type_columns' ) );
54 
55  add_filter( 'gform_toolbar_menu', array( 'GravityView_Admin_Views', 'gform_toolbar_menu' ), 10, 2 );
56  add_action( 'gform_form_actions', array( 'GravityView_Admin_Views', 'gform_toolbar_menu' ), 10, 2 );
57 
58  add_action( 'manage_gravityview_posts_custom_column', array( $this, 'add_custom_column_content'), 10, 2 );
59 
60  add_action( 'restrict_manage_posts', array( $this, 'add_view_dropdown' ) );
61 
62  add_action( 'pre_get_posts', array( $this, 'filter_pre_get_posts' ) );
63 
64  add_filter( 'gravityview/support_port/localization_data', array( $this, 'suggest_support_articles' ) );
65  }
66 
67  /**
68  * Allow targeting different versions of Gravity Forms using CSS selectors.
69  *
70  * Adds specific version class: `.gf-version-2.6.1.3` as well as point updates: `.gf-minor-version-2.6`.
71  *
72  * @internal Do not rely on this remaining public.
73  * @since 2.14.4
74  *
75  * @param string $class Existing body class for the WordPress admin.
76  *
77  * @return string Original with two classes added. If GFForms isn't available, returns original string.
78  */
79  public function add_gf_version_css_class( $class ) {
80 
81  if ( ! class_exists( 'GFForms' ) || empty( GFForms::$version ) ) {
82  return $class;
83  }
84 
85  $class .= ' gf-version-' . str_replace( '.', '-', GFForms::$version );
86 
87  $major_version = explode( '.', GFForms::$version );
88 
89  if ( 2 <= sizeof( $major_version ) ) {
90  $class .= ' gf-minor-version-' . esc_attr( $major_version[0] . '-' . $major_version[1] );
91  }
92 
93  return $class;
94  }
95 
96  /**
97  * When on the Add/Edit View screen, suggest most popular articles related to that
98  *
99  * @param array $localization_data Data to be passed to the Support Port JS
100  *
101  * @return array
102  */
103  function suggest_support_articles( $localization_data = array() ) {
104 
105  if( ! gravityview()->request->is_view( false ) ) {
106  return $localization_data;
107  }
108 
109  $localization_data['suggest'] = array(
110  '57ef23539033602e61d4a560',
111  '54c67bb9e4b0512429885513',
112  '54c67bb9e4b0512429885512',
113  '54c67bbbe4b07997ea3f3f6b',
114  '54d1a33ae4b086c0c0964ce9',
115  '57ef253c9033602e61d4a563',
116  '552355bfe4b0221aadf2572b',
117  '54c67bcde4b051242988553e',
118  );
119 
120  return $localization_data;
121  }
122 
123  /**
124  * @since 1.15
125  * @param WP_Query $query
126  */
127  public function filter_pre_get_posts( &$query ) {
128  global $pagenow;
129 
130  if ( ! is_admin() ) {
131  return;
132  }
133 
134  if ( 'edit.php' !== $pagenow ) {
135  return;
136  }
137 
138  if ( ! isset( $query->query_vars['post_type'] ) ) {
139  return;
140  }
141 
142  if ( 'gravityview' !== $query->query_vars['post_type'] ) {
143  return;
144  }
145 
146  $form_id = (int) \GV\Utils::_GET( 'gravityview_form_id' );
147 
148  $meta_query = array();
149 
150  if ( $form_id ) {
151  $meta_query[] = array(
152  'key' => '_gravityview_form_id',
153  'value' => $form_id,
154  );
155  }
156 
157  $layout_id = \GV\Utils::_GET( 'gravityview_layout' );
158 
159  if ( $layout_id ) {
160  $meta_query[] = array(
161  'key' => '_gravityview_directory_template',
162  'value' => esc_attr( $layout_id ),
163  );
164  }
165 
166  $query->set( 'meta_query', $meta_query );
167  }
168 
169  /**
170  * Adds dropdown selects to filter Views by connected form and layout
171  *
172  * @return void
173  */
174  public function add_view_dropdown() {
175  $current_screen = get_current_screen();
176 
177  if( 'gravityview' !== $current_screen->post_type ) {
178  return;
179  }
180 
182  $current_form = \GV\Utils::_GET( 'gravityview_form_id' );
183 
184  // If there are no forms to select, show no forms.
185  if( ! empty( $forms ) ) { ?>
186  <label for="gravityview_form_id" class="screen-reader-text"><?php esc_html_e( 'Filter Views by form', 'gk-gravityview' ); ?></label>
187  <select name="gravityview_form_id" id="gravityview_form_id">
188  <option value="" <?php selected( '', $current_form, true ); ?>><?php esc_html_e( 'All forms', 'gk-gravityview' ); ?></option>
189  <?php foreach( $forms as $form ) { ?>
190  <option value="<?php echo esc_attr( $form['id'] ); ?>" <?php selected( $form['id'], $current_form, true ); ?>><?php echo esc_html( $form['title'] ); ?></option>
191  <?php } ?>
192  </select>
193  <?php }
194 
196  $current_layout = \GV\Utils::_GET( 'gravityview_layout' );
197 
198  // If there are no forms to select, show no forms.
199  if( ! empty( $layouts ) ) { ?>
200  <label for="gravityview_layout_name" class="screen-reader-text"><?php esc_html_e( 'Filter Views by layout', 'gk-gravityview' ); ?></label>
201  <select name="gravityview_layout" id="gravityview_layout_name">
202  <option value="" <?php selected( '', $current_layout, true ); ?>><?php esc_html_e( 'All layouts', 'gk-gravityview' ); ?></option>
203  <optgroup label="<?php esc_html_e( 'Layouts', 'gk-gravityview' ); ?>">
204  <?php foreach( $layouts as $layout_id => $layout ) {
205  if ( in_array( $layout['type'], array( 'preset', 'internal' ), true ) ) {
206  continue;
207  }
208  ?>
209  <option value="<?php echo esc_attr( $layout_id ); ?>" <?php selected( $layout_id, $current_layout, true ); ?>><?php echo esc_html( $layout['label'] ); ?></option>
210  <?php } ?>
211  </optgroup>
212  <optgroup label="<?php esc_html_e( 'Form Presets', 'gk-gravityview' ); ?>">
213  <?php foreach( $layouts as $layout_id => $layout ) {
214  if ( ! in_array( $layout['type'], array( 'preset' ), true ) ) {
215  continue;
216  }
217  ?>
218  <option value="<?php echo esc_attr( $layout_id ); ?>" <?php selected( $layout_id, $current_layout, true ); ?>><?php echo esc_html( $layout['label'] ); ?></option>
219  <?php } ?>
220  </optgroup>
221  </select>
222  <?php }
223  }
224 
225 
226  /**
227  * @deprecated since 1.2
228  * Start using GravityView_Render_Settings::render_setting_row
229  */
230  public static function render_setting_row( $key = '', $current_settings = array(), $override_input = null, $name = 'template_settings[%s]', $id = 'gravityview_se_%s' ) {
231  _deprecated_function( 'GravityView_Admin_Views::render_setting_row', '1.1.7', 'GravityView_Render_Settings::render_setting_row' );
233  }
234 
235  /**
236  * @deprecated since 1.2
237  * Start using GravityView_Render_Settings::render_field_option
238  */
239  public static function render_field_option( $name = '', $option = array(), $curr_value = null ) {
240  _deprecated_function( 'GravityView_Admin_Views::render_field_option', '1.1.7', 'GravityView_Render_Settings::render_field_option' );
241  return GravityView_Render_Settings::render_field_option( $name, $option, $curr_value );
242  }
243 
244 
245  /**
246  * Add a GravityView menu to the Form Toolbar with connected views
247  * @param array $menu_items Menu items, as set in GFForms::top_toolbar()
248  * @param int $id ID of the current Gravity form
249  * @return array Modified array
250  */
251  public static function gform_toolbar_menu( $menu_items = array(), $id = NULL ) {
252 
253  // Don't show on Trashed forms
254  if ( 'trash' === rgget( 'filter' ) ) {
255  return $menu_items;
256  }
257 
258  $connected_views = gravityview_get_connected_views( $id, array( 'post_status' => 'any' ) );
259 
260  $priority = 0;
261 
262  if( 'form_list' === GFForms::get_page() ) {
263  $priority = 790;
264  }
265 
266  if( empty( $connected_views ) ) {
267 
268  $menu_items['gravityview'] = array(
269  'label' => esc_attr__( 'Create a View', 'gk-gravityview' ),
270  'icon' => '<i class="fa fa-lg gv-icon-astronaut-head gv-icon"></i>', // Only appears in GF pre-2.5
271  'title' => esc_attr__( 'Create a View using this form as a data source', 'gk-gravityview' ),
272  'url' => admin_url( 'post-new.php?post_type=gravityview&form_id=' . $id ),
273  'menu_class' => 'gv_connected_forms gf_form_toolbar_settings',
274  'priority' => $priority,
275  'capabilities' => array( 'edit_gravityviews' ),
276  );
277 
278  return $menu_items;
279  }
280 
281  $sub_menu_items = array();
282  foreach ( (array)$connected_views as $view ) {
283 
284  if( ! GVCommon::has_cap( 'edit_gravityview', $view->ID ) ) {
285  continue;
286  }
287 
288  $label = empty( $view->post_title ) ? sprintf( __('No Title (View #%d)', 'gk-gravityview' ), $view->ID ) : $view->post_title;
289 
290  $sub_menu_items[] = array(
291  'label' => esc_attr( $label ),
292  'url' => admin_url( 'post.php?action=edit&post='.$view->ID ),
293  'icon' => '<i class="fa fa-lg gv-icon-astronaut-head gv-icon"></i>',
294  );
295  }
296 
297  // If there were no items added, then let's create the parent menu
298  if( $sub_menu_items ) {
299 
300  $sub_menu_items[] = array(
301  'label' => esc_attr__( 'Create a View', 'gk-gravityview' ),
302  'icon' => '<span class="dashicons dashicons-plus"></span>',
303  'title' => esc_attr__( 'Create a View using this form as a data source', 'gk-gravityview' ),
304  'url' => admin_url( 'post-new.php?post_type=gravityview&form_id=' . $id ),
305  'capabilities' => array( 'edit_gravityviews' ),
306  );
307 
308  // Make sure Gravity Forms uses the submenu; if there's only one item, it uses a link instead of a dropdown
309  $sub_menu_items[] = array(
310  'url' => '#',
311  'label' => '',
312  'menu_class' => 'hidden',
313  'capabilities' => '',
314  );
315 
316  $menu_items['gravityview'] = array(
317  'label' => __( 'Connected Views', 'gk-gravityview' ),
318  'icon' => '<i class="fa fa-lg gv-icon-astronaut-head gv-icon"></i>',
319  'title' => __( 'GravityView Views using this form as a data source', 'gk-gravityview' ),
320  'url' => '#',
321  'onclick' => 'return false;',
322  'menu_class' => 'gv_connected_forms gf_form_toolbar_settings',
323  'sub_menu_items' => $sub_menu_items,
324  'priority' => $priority,
325  'capabilities' => array( 'edit_gravityviews' ),
326  );
327  }
328 
329  return $menu_items;
330  }
331 
332  /**
333  * List the field types without presentation properties (on a View context)
334  *
335  * @since 2.14
336  *
337  * @param array $array Existing field types to add to a blocklist
338  * @param string|null $context Context for the blocklist. Default: NULL.
339  *
340  * @return array Default blocklist fields merged with existing blocklist fields
341  */
342  public function default_field_blocklist( $array = array(), $context = NULL ) {
343 
344  $add = array( 'captcha', 'page' );
345 
346  // Don't allowing editing the following values:
347  if( $context === 'edit' ) {
348  $add[] = 'post_id';
349  }
350 
351  $return = array_merge( $array, $add );
352 
353  return $return;
354  }
355 
356  /**
357  * @deprecated 2.14
358  */
359  public function default_field_blacklist( $array, $context ) {
360  _deprecated_function( __METHOD__, '2.14', 'GravityView_Admin_Views::default_field_blocklist' );
361  $this->default_field_blocklist( $array, $context );
362  }
363 
364  /**
365  * Add tooltip text for use throughout the UI
366  * @param array $tooltips Array of Gravity Forms tooltips
367  * @return array Modified tooltips array
368  */
369  public function tooltips( $tooltips = array() ) {
370 
371  $gv_tooltips = array();
372 
373  // Generate tooltips for View settings
374  $default_args = \GV\View_Settings::defaults( true );
375 
376  foreach ( $default_args as $key => $arg ) {
377 
378  // If an arg has `tooltip` defined, but it's false, don't display a tooltip
379  if( isset( $arg['tooltip'] ) && empty( $arg['tooltip'] ) ) { continue; }
380 
381  // By default, use `tooltip` if defined.
382  $tooltip = empty( $arg['tooltip'] ) ? NULL : $arg['tooltip'];
383 
384  // If there's no tooltip set, continue
385  if( empty( $tooltip ) ) {
386  continue;
387  }
388 
389  // Add the tooltip
390  $gv_tooltips[ 'gv_'.$key ] = array(
391  'title' => $arg['label'],
392  'value' => $tooltip,
393  );
394 
395  }
396 
397  $gv_tooltips['gv_css_merge_tags'] = array(
398  'title' => __('CSS Merge Tags', 'gk-gravityview'),
399  'value' => sprintf( __( 'Developers: The CSS classes will be sanitized using the %ssanitize_title_with_dashes()%s function.', 'gk-gravityview'), '<code>', '</code>' )
400  );
401 
402  /**
403  * @filter `gravityview_tooltips` The tooltips GravityView adds to the Gravity Forms tooltip array
404  * @param array $gv_tooltips Associative array with unique keys containing array of `title` and `value` keys, as expected by `gform_tooltips` filter
405  * @deprecated Renamed to `gravityview/metaboxes/tooltips`
406  */
407  $gv_tooltips = apply_filters( 'gravityview_tooltips', $gv_tooltips );
408 
409  /**
410  * @filter `gravityview/metaboxes/tooltips` The tooltips GravityView adds to the Gravity Forms tooltip array
411  * @param array $gv_tooltips Associative array with unique keys containing array of `title` and `value` keys, as expected by `gform_tooltips` filter
412  */
413  $gv_tooltips = apply_filters( 'gravityview/metaboxes/tooltips', $gv_tooltips );
414 
415  foreach ( $gv_tooltips as $key => $tooltip ) {
416 
417  $title = empty( $tooltip['title'] ) ? '' : '<h6>'.esc_html( $tooltip['title'] ) .'</h6>';
418 
419  $tooltips[ $key ] = $title . wpautop( esc_html( $tooltip['value'] ) );
420  }
421 
422  return $tooltips;
423  }
424 
425  /**
426  * Add the Data Source information
427  *
428  * @param null $column_name Name of the column in the Views table.
429  * @param int $post_id Post ID.
430  *
431  * @return void
432  */
433  public function add_custom_column_content( $column_name = null, $post_id = 0 ) {
434 
435  $output = '';
436 
437  switch ( $column_name ) {
438  case 'gv_template':
439 
440  $template_id = gravityview_get_template_id( $post_id );
441 
442  // All Views should have a connected form. If it doesn't, that's not right.
443  if ( empty( $template_id ) ) {
444  gravityview()->log->error( 'View ID {view_id} does not have a connected template.', array( 'view_id' => $post_id ) );
445  break;
446  }
447 
449 
450  $template = isset( $templates[ $template_id ] ) ? $templates[ $template_id ] : false;
451 
452  // Generate backup if label doesn't exist: `example_name` => `Example Name`
453  $template_id_pretty = ucwords( implode( ' ', explode( '_', $template_id ) ) );
454 
455  $output = $template ? $template['label'] : $template_id_pretty;
456 
457  break;
458 
459  case 'gv_connected_form':
460 
461  $form_id = gravityview_get_form_id( $post_id );
462 
463  // All Views should have a connected form. If it doesn't, that's not right.
464  if ( empty( $form_id ) ) {
465  gravityview()->log->error( 'View ID {view_id} does not have a connected GF form.', array( 'view_id' => $post_id ) );
466  $output = __( 'Not connected.', 'gk-gravityview' );
467  break;
468  }
469 
471 
472  if ( ! $form ) {
473  gravityview()->log->error( 'Connected form not found: Form #{form_id}', array( 'form_id' => $form_id ) );
474 
475  $output = __( 'The connected form can not be found; it may no longer exist.', 'gk-gravityview' );
476  } else {
477  $output = self::get_connected_form_links( $form );
478  }
479 
480  break;
481  }
482 
483  echo $output;
484  }
485 
486 
487  /**
488  * Get HTML links relating to a connected form, like Edit, Entries, Settings, Preview
489  * @param array|int $form Gravity Forms forms array, or the form ID
490  * @param boolean $include_form_link Whether to include the bold name of the form in the output
491  * @return string HTML links
492  */
493  static public function get_connected_form_links( $form, $include_form_link = true ) {
494 
495  // Either the form is empty or the form ID is 0, not yet set.
496  if( empty( $form ) ) {
497  return '';
498  }
499 
500  // The $form is passed as the form ID
501  if( !is_array( $form ) ) {
503  }
504 
505  if ( empty( $form ) ) {
506  return '';
507  }
508 
509  $form_id = $form['id'];
510  $links = array();
511 
512  if( GVCommon::has_cap( 'gravityforms_edit_forms' ) ) {
513  $form_url = admin_url( sprintf( 'admin.php?page=gf_edit_forms&amp;id=%d', $form_id ) );
514  $form_link = '<strong class="gv-form-title">'.gravityview_get_link( $form_url, $form['title'], 'class=row-title' ).'</strong>';
515  $links[] = '<span>'.gravityview_get_link( $form_url, __('Edit Form', 'gk-gravityview') ).'</span>';
516  } else {
517  $form_link = '<strong class="gv-form-title">'. esc_html( $form['title'] ). '</strong>';
518  }
519 
520  if( GVCommon::has_cap( 'gravityforms_view_entries' ) ) {
521  $entries_url = admin_url( sprintf( 'admin.php?page=gf_entries&amp;id=%d', $form_id ) );
522  $links[] = '<span>'.gravityview_get_link( $entries_url, __('Entries', 'gk-gravityview') ).'</span>';
523  }
524 
525  if( GVCommon::has_cap( array( 'gravityforms_edit_settings', 'gravityview_view_settings' ) ) ) {
526  $settings_url = admin_url( sprintf( 'admin.php?page=gf_edit_forms&amp;view=settings&amp;id=%d', $form_id ) );
527  $links[] = '<span>'.gravityview_get_link( $settings_url, __('Settings', 'gk-gravityview'), 'title='.__('Edit settings for this form', 'gk-gravityview') ).'</span>';
528  }
529 
530  if( GVCommon::has_cap( array("gravityforms_edit_forms", "gravityforms_create_form", "gravityforms_preview_forms") ) ) {
531  $preview_url = site_url( sprintf( '?gf_page=preview&amp;id=%d', $form_id ) );
532  $links[] = '<span>'.gravityview_get_link( $preview_url, __('Preview Form', 'gk-gravityview'), 'title='.__('Preview this form', 'gk-gravityview') ).'</span>';
533  }
534 
535  $output = '';
536 
537  if( !empty( $include_form_link ) ) {
538  $output .= $form_link;
539  }
540 
541  /**
542  * @filter `gravityview_connected_form_links` Modify the links shown in the Connected Form links
543  * @since 1.6
544  * @param array $links Links to show
545  * @param array $form Gravity Forms form array
546  */
547  $links = apply_filters( 'gravityview_connected_form_links', $links, $form );
548 
549  $css_class = 'row-actions';
550 
551  // Is Screen Options > View mode set to "Extended view"? If so, keep actions visible.
552  if( 'excerpt' === get_user_setting( 'posts_list_mode', 'list' ) ) {
553  $css_class = 'row-actions visible';
554  }
555 
556  $output .= '<div class="' . $css_class . '">'. implode( ' | ', $links ) .'</div>';
557 
558  return $output;
559  }
560 
561  /**
562  * Add the Data Source column to the Views page
563  * @param array $columns Columns array
564  */
565  public function add_post_type_columns( $columns ) {
566 
567  // Get the date column and save it for later to add back in.
568  // This adds it after the Data Source column.
569  // This way, we don't need to do array_slice, array_merge, etc.
570  $date = $columns['date'];
571  unset( $columns['date'] );
572 
573  $data_source_required_caps = array(
574  'gravityforms_edit_forms',
575  'gravityforms_view_entries',
576  'gravityforms_edit_settings',
577  'gravityview_view_settings',
578  'gravityforms_create_form',
579  'gravityforms_preview_forms',
580  );
581 
582  if( GVCommon::has_cap( $data_source_required_caps ) ) {
583  $columns['gv_connected_form'] = __( 'Data Source', 'gk-gravityview' );
584  }
585 
586  $columns['gv_template'] = _x( 'Template', 'Column title that shows what template is being used for Views', 'gk-gravityview' );
587 
588  // Add the date back in.
589  $columns['date'] = $date;
590 
591  return $columns;
592  }
593 
594  /**
595  * Save View configuration
596  *
597  * @param int $post_id Currently saved Post ID
598  * @return void
599  */
600  function save_postdata( $post_id ) {
601 
602  if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ){
603  return;
604  }
605 
606  // validate post_type
607  if ( ! isset( $_POST['post_type'] ) || 'gravityview' != $_POST['post_type'] ) {
608  return;
609  }
610 
611  // validate user can edit and save View
612  if ( ! GVCommon::has_cap( 'edit_gravityview', $post_id ) ) {
613  gravityview()->log->error( 'Current user does not have the capability to edit View {view_id}', array( 'view_id' => $post_id, 'data' => wp_get_current_user() ) );
614  return;
615  }
616 
617  gravityview()->log->debug( '[save_postdata] Saving View post type.', array( 'data' => $_POST ) );
618 
619  $statii = array();
620 
621  // check if this is a start fresh View
622  if ( isset( $_POST['gravityview_select_form_nonce'] ) && wp_verify_nonce( $_POST['gravityview_select_form_nonce'], 'gravityview_select_form' ) ) {
623 
624  $form_id = !empty( $_POST['gravityview_form_id'] ) ? $_POST['gravityview_form_id'] : '';
625  // save form id
626  $statii['form_id'] = update_post_meta( $post_id, '_gravityview_form_id', $form_id );
627 
628  }
629 
630  if( false === GVCommon::has_cap( 'gravityforms_create_form' ) && empty( $statii['form_id'] ) ) {
631  gravityview()->log->error( 'Current user does not have the capability to create a new Form.', array( 'data' => wp_get_current_user() ) );
632  return;
633  }
634 
635  // Was this a start fresh?
636  if ( ! empty( $_POST['gravityview_form_id_start_fresh'] ) ) {
637  $statii['start_fresh'] = add_post_meta( $post_id, '_gravityview_start_fresh', 1 );
638  } else {
639  $statii['start_fresh'] = delete_post_meta( $post_id, '_gravityview_start_fresh' );
640  }
641 
642  // Check if we have a template id
643  if ( isset( $_POST['gravityview_select_template_nonce'] ) && wp_verify_nonce( $_POST['gravityview_select_template_nonce'], 'gravityview_select_template' ) ) {
644 
645  $template_id = !empty( $_POST['gravityview_directory_template'] ) ? $_POST['gravityview_directory_template'] : '';
646 
647  // now save template id
648  $statii['directory_template'] = update_post_meta( $post_id, '_gravityview_directory_template', $template_id );
649  }
650 
651 
652  // save View Configuration metabox
653  if ( isset( $_POST['gravityview_view_configuration_nonce'] ) && wp_verify_nonce( $_POST['gravityview_view_configuration_nonce'], 'gravityview_view_configuration' ) ) {
654 
655  // template settings
656  if( empty( $_POST['template_settings'] ) ) {
657  $_POST['template_settings'] = array();
658  }
659  $statii['template_settings'] = update_post_meta( $post_id, '_gravityview_template_settings', $_POST['template_settings'] );
660 
661  // guard against unloaded View configuration page
662  if ( isset( $_POST['gv_fields'] ) && isset( $_POST['gv_fields_done'] ) ) {
663  $fields = array();
664 
665  if ( ! empty( $_POST['gv_fields'] ) ) {
667  }
668 
669  $fields = wp_slash( $fields );
670 
671  $statii['directory_fields'] = update_post_meta( $post_id, '_gravityview_directory_fields', $fields );
672  }
673 
674  // Directory Visible Widgets
675  if( empty( $_POST['widgets'] ) ) {
676  $_POST['widgets'] = array();
677  }
678  $statii['directory_widgets'] = gravityview_set_directory_widgets( $post_id, $_POST['widgets'] );
679 
680  } // end save view configuration
681 
682  /**
683  * @action `gravityview_view_saved` After a View has been saved in the admin
684  * @param int $post_id ID of the View that has been saved
685  * @param array $statii Array of statuses of the post meta saving processes. If saving worked, each key should be mapped to a value of the post ID (`directory_widgets` => `124`). If failed (or didn't change), the value will be false.
686  * @since 1.17.2
687  */
688  do_action('gravityview_view_saved', $post_id, $statii );
689 
690  gravityview()->log->debug( '[save_postdata] Update Post Meta Statuses (also returns false if nothing changed)', array( 'data' => array_map( 'intval', $statii ) ) );
691  }
692 
693  /**
694  * @deprecated 1.1.6
695  */
696  function render_label() {
697  _deprecated_function( 'GravityView_Admin_Views::render_label()', '1.1.6', 'Use the GravityView_Admin_View_Field class instead.' );
698  }
699 
700  /**
701  * Render html for displaying available fields based on a Form ID
702  *
703  * @see GravityView_Ajax::get_available_fields_html() Triggers `gravityview_render_available_fields` action
704  *
705  * @param int|string $form_id Gravity Forms form ID. Default: 0.
706  * @param string $context (default: 'single')
707  *
708  * @return void
709  */
710  function render_available_fields( $form_id = 0, $context = 'single' ) {
712 
713  /**
714  * @deprecated 2.9
715  */
716  $blocklist_field_types = apply_filters_deprecated( 'gravityview_blacklist_field_types', array( array(), $context ), '2.14', 'gravityview_blocklist_field_types' );
717 
718  /**
719  * @filter `gravityview_blocklist_field_types` Modify the types of fields that shouldn't be shown in a View.
720  * @param array $blocklist_field_types Array of field types which are not proper to be shown for the $context.
721  * @param string $context View context ('single', 'directory', or 'edit').
722  * @since 2.9
723  */
724  $blocklist_field_types = apply_filters( 'gravityview_blocklist_field_types', $blocklist_field_types, $context );
725 
726  if ( ! is_array( $blocklist_field_types ) ) {
727 
728  gravityview()->log->error( '$blocklist_field_types is not an array', array( 'data' => print_r( $blocklist_field_types, true ) ) );
729 
730  $blocklist_field_types = array();
731  }
732 
733  $fields = $this->get_available_fields( $form, $context );
734 
735  $output = '';
736 
737  if( !empty( $fields ) ) {
738 
739  foreach( $fields as $id => $details ) {
740 
741  if( in_array( $details['type'], (array) $blocklist_field_types ) ) {
742  continue;
743  }
744 
745  // Edit mode only allows editing the parent fields, not single inputs.
746  if( $context === 'edit' && ! empty( $details['parent'] ) ) {
747  continue;
748  }
749 
750  $output .= new GravityView_Admin_View_Field( $details['label'], $id, $details, array(), $form_id, $form );
751 
752  } // End foreach
753  }
754 
755  echo $output;
756 
757  // For the EDIT view we only want to allow the form fields.
758  if( $context === 'edit' ) {
759  return;
760  }
761 
762  $this->render_additional_fields( $form_id, $context );
763  }
764 
765  /**
766  * Render html for displaying additional fields based on a Form ID
767  *
768  * @param int|string $form_id Gravity Forms form ID. Default: 0.
769  * @param string $context (default: 'single')
770  *
771  * @return void
772  */
773  public function render_additional_fields( $form_id = 0, $context = 'single' ) {
775 
776  $additional_fields = array(
777  array(
778  'label_text' => __( 'Add All Form Fields', 'gk-gravityview' ),
779  'desc' => __('Insert all the form fields at once.', 'gk-gravityview'),
780  'field_id' => 'all-fields',
781  'label_type' => 'field',
782  'input_type' => null,
783  'field_options' => null,
784  'settings_html' => null,
785  'icon' => 'dashicons-plus-alt',
786  )
787  );
788 
789  /**
790  * @filter `gravityview_additional_fields` non-standard Fields to show at the bottom of the field picker
791  * @param array $additional_fields Associative array of field arrays, with `label_text`, `desc`, `field_id`, `label_type`, `input_type`, `field_options`, and `settings_html` keys
792  */
793  $additional_fields = apply_filters( 'gravityview_additional_fields', $additional_fields );
794 
795  foreach ( (array) $additional_fields as $item ) {
796 
797  // Prevent items from not having index set
798  $item = wp_parse_args( $item, array(
799  'label_text' => null,
800  'field_id' => null,
801  'label_type' => null,
802  'input_type' => null,
803  'field_options' => null,
804  'settings_html' => null,
805  'icon' => null,
806  ));
807 
808  // Backward compat.
809  if( !empty( $item['field_options'] ) ) {
810  // Use settings_html from now on.
811  $item['settings_html'] = $item['field_options'];
812  }
813 
814  // Render a label for each of them
815  echo new GravityView_Admin_View_Field( $item['label_text'], $item['field_id'], $item, $settings = array(), $form_id, $form );
816 
817  }
818 
819  }
820 
821  /**
822  * Retrieve the default fields id, label and type
823  * @param string|array $form form_ID or form object
824  * @param string $zone Either 'single', 'directory', 'header', 'footer'
825  * @return array
826  */
827  function get_entry_default_fields($form, $zone) {
828 
829  $entry_default_fields = array();
830 
831  // if in zone directory or single
832  if( in_array( $zone, array( 'directory', 'single' ), true ) ) {
833 
834  $meta_fields = GravityView_Fields::get_all( array( 'meta', 'gravityview', 'add-ons' ) );
835 
836  $entry_default_fields = array();
837 
838  foreach ( $meta_fields as $meta_field ) {
839  $entry_default_fields += $meta_field->as_array();
840  }
841  }
842 
843  /**
844  * @filter `gravityview_entry_default_fields` Modify the default fields for each zone and context
845  * @param array $entry_default_fields Array of fields shown by default
846  * @param string|array $form form_ID or form object
847  * @param string $zone Either 'single', 'directory', 'header', 'footer'
848  */
849  return apply_filters( 'gravityview_entry_default_fields', $entry_default_fields, $form, $zone);
850  }
851 
852  /**
853  * Calculate the available fields
854  * @param string|array $form form_ID or form object
855  * @param string $zone Either 'single', 'directory', 'header', 'footer'
856  * @return array fields
857  */
858  function get_available_fields( $form = '', $zone = NULL ) {
859 
860  if( empty( $form ) ) {
861  gravityview()->log->error( '$form is empty' );
862  return array();
863  }
864 
865  // get form fields
866  $fields = gravityview_get_form_fields( $form, true );
867 
868  // get meta fields ( only if form was already created )
869  if( !is_array( $form ) ) {
870  $meta_fields = gravityview_get_entry_meta( $form );
871  } else {
872  $meta_fields = array();
873  }
874 
875  // get default fields
876  $default_fields = $this->get_entry_default_fields( $form, $zone );
877 
878  //merge without loosing the keys
879  $fields = $fields + $meta_fields + $default_fields;
880 
881  // Move Custom Content to top
882  if ( isset( $fields['custom'] ) ) {
883  $fields = array( 'custom' => $fields['custom'] ) + $fields;
884  }
885 
886  $gv_fields = GravityView_Fields::get_all();
887 
888  foreach ( $fields as &$field ) {
889  foreach ( $gv_fields as $gv_field ) {
890  if ( \GV\Utils::get( $field, 'type' ) === $gv_field->name ) {
891  $field['icon'] = $gv_field->get_icon();
892  }
893  }
894  }
895 
896  /**
897  * @filter `gravityview/admin/available_fields` Modify the available fields that can be used in a View.
898  * @param array $fields The fields.
899  * @param string|array $form form_ID or form object
900  * @param string $zone Either 'single', 'directory', 'header', 'footer'
901  */
902  return apply_filters( 'gravityview/admin/available_fields', $fields, $form, $zone );
903  }
904 
905 
906  /**
907  * Render html for displaying available widgets
908  * @return string html
909  */
911 
912  $widgets = \GV\Widget::registered();
913 
914  if ( empty( $widgets ) ) {
915  return;
916  }
917 
918  foreach ( $widgets as $id => $details ) {
919  echo new GravityView_Admin_View_Widget( $details['label'], $id, $details );
920  }
921 
922  }
923 
924  /**
925  * Get the list of registered widgets. Each item is used to instantiate a GravityView_Admin_View_Widget object
926  * @deprecated Use \GV\Widget::registered()
927  * @since 1.13.1
928  * @return array
929  */
931 
932  _deprecated_function( __METHOD__, '2.0', '\GV\Widget::registered()' );
933 
934  return \GV\Widget::registered();
935  }
936 
937  /**
938  * Generic function to render rows and columns of active areas for widgets & fields
939  * @param string $template_id The current slug of the selected View template
940  * @param string $type Either 'widget' or 'field'
941  * @param string $zone Either 'single', 'directory', 'edit', 'header', 'footer'
942  * @param array $rows The layout structure: rows, columns and areas
943  * @param array $values Saved objects
944  * @return void
945  */
946  function render_active_areas( $template_id, $type, $zone, $rows, $values ) {
947  global $post;
948 
949  if( $type === 'widget' ) {
950  $button_label = __( 'Add Widget', 'gk-gravityview' );
951  } else {
952  $button_label = __( 'Add Field', 'gk-gravityview' );
953  }
954 
955  /**
956  * @internal Don't rely on this filter! This is for internal use and may change.
957  *
958  * @since 2.8.1
959  *
960  * @param string $button_label Text for button: "Add Widget" or "Add Field"
961  * @param array $atts {
962  * @type string $type 'widget' or 'field'
963  * @type string $template_id The current slug of the selected View template
964  * @type string $zone Where is this button being shown? Either 'single', 'directory', 'edit', 'header', 'footer'
965  * }
966  */
967  $button_label = apply_filters( 'gravityview/admin/add_button_label', $button_label, array( 'type' => $type, 'template_id' => $template_id, 'zone' => $zone ) );
968 
969  $available_items = array();
970 
971  $view = \GV\View::from_post( $post );
972  $form_id = null;
973  $form = false;
974 
975  // if saved values, get available fields to label everyone
976  if( !empty( $values ) && ( !empty( $post->ID ) || ! empty( $_POST['template_id'] ) || ! empty( $_POST['form_id'] ) ) ) {
977 
978  if ( ! empty( $_POST['form_id'] ) ) {
979  $form_id = (int) \GV\Utils::_POST( 'form_id', 0 );
981  } elseif( ! empty( $_POST['template_id'] ) ) {
982  $form_id = esc_attr( $_POST['template_id'] );
983  $form = GravityView_Ajax::pre_get_form_fields( $_POST['template_id'] );
984  } else {
985  $form_id = gravityview_get_form_id( $post->ID );
987  }
988 
989  if ( 'field' === $type ) {
990  $available_items[ $form_id ] = $this->get_available_fields( $form, $zone );
991 
992  if ( ! empty( $post->ID ) ) {
993  $joined_forms = gravityview_get_joined_forms( $post->ID );
994 
995  foreach ( $joined_forms as $joined_form ) {
996  $available_items[ $joined_form->ID ] = $this->get_available_fields( $joined_form->ID, $zone );
997  }
998  }
999  } else {
1000  $available_items[ $form_id ] = \GV\Widget::registered();
1001  }
1002  }
1003 
1004  foreach( $rows as $row ) :
1005  foreach( $row as $col => $areas ) :
1006  $column = ($col == '2-2') ? '1-2' : $col; ?>
1007 
1008  <div class="gv-grid-col-<?php echo esc_attr( $column ); ?>">
1009 
1010  <?php foreach( $areas as $area ) : ?>
1011 
1012  <div class="gv-droppable-area" data-areaid="<?php echo esc_attr( $zone .'_'. $area['areaid'] ); ?>" data-context="<?php echo esc_attr( $zone ); ?>">
1013  <p class="gv-droppable-area-title" <?php if ( 'widget' === $type && empty( $area['subtitle'] ) ) { echo ' style="margin: 0; padding: 0;"'; } ?>>
1014  <strong <?php if ( 'widget' === $type ) { echo 'class="screen-reader-text"'; } ?>><?php echo esc_html( $area['title'] ); ?></strong>
1015 
1016  <?php if ( 'widget' !== $type ) { ?>
1017  <a class="clear-all-fields alignright" role="button" href="#" data-areaid="<?php echo esc_attr( $zone .'_'. $area['areaid'] ); ?>"><?php esc_html_e( 'Clear all fields', 'gk-gravityview' ); ?></a>
1018  <?php } ?>
1019 
1020  <?php if ( ! empty( $area['subtitle'] ) ) { ?>
1021  <span class="gv-droppable-area-subtitle"><span class="gf_tooltip gv_tooltip tooltip" title="<?php echo esc_attr( $area['subtitle'] ); ?>"></span></span>
1022  <?php } ?>
1023  </p>
1024  <div class="active-drop-container active-drop-container-<?php echo esc_attr( $type ); ?>">
1025  <div class="active-drop active-drop-<?php echo esc_attr( $type ); ?>" data-areaid="<?php echo esc_attr( $zone .'_'. $area['areaid'] ); ?>"><?php // render saved fields
1026  if( ! empty( $values[ $zone .'_'. $area['areaid'] ] ) ) {
1027 
1028  foreach( $values[ $zone .'_'. $area['areaid'] ] as $uniqid => $field ) {
1029 
1030  // Maybe has a form ID
1031  $form_id = empty( $field['form_id'] ) ? $form_id : $field['form_id'];
1032 
1033  $input_type = null;
1034 
1035  if ( $form_id ) {
1036  $original_item = isset( $available_items[ $form_id ] [ $field['id'] ] ) ? $available_items[ $form_id ] [ $field['id'] ] : false ;
1037  } else {
1038  $original_item = isset( $available_items[ $field['id'] ] ) ? $available_items[ $field['id'] ] : false ;
1039  }
1040 
1041  if ( ! $original_item ) {
1042 
1043  global $pagenow;
1044  if ( 'post-new.php' !== $pagenow ) {
1045  gravityview()->log->error( 'An item was not available when rendering the output; maybe it was added by a plugin that is now de-activated.', array(
1046  ' data' => array(
1047  'available_items' => $available_items,
1048  'field' => $field
1049  )
1050  ) );
1051  }
1052 
1053  $original_item = $field;
1054  }
1055 
1056  $input_type = isset( $original_item['type'] ) ? $original_item['type'] : null;
1057 
1058  // Field options dialog box
1059  $field_options = GravityView_Render_Settings::render_field_options( $form_id, $type, $template_id, $field['id'], $original_item['label'], $zone .'_'. $area['areaid'], $input_type, $uniqid, $field, $zone, $original_item );
1060 
1061  $item = array(
1062  'input_type' => $input_type,
1063  'settings_html' => $field_options,
1064  'label_type' => $type,
1065  );
1066 
1067  // Merge the values with the current item to pass things like widget descriptions and original field names
1068  if ( $original_item ) {
1069  $item = wp_parse_args( $item, $original_item );
1070  }
1071 
1072  switch( $type ) {
1073  case 'widget':
1074  echo new GravityView_Admin_View_Widget( $item['label'], $field['id'], $item, $field );
1075  break;
1076  default:
1077  echo new GravityView_Admin_View_Field( $field['label'], $field['id'], $item, $field, $form_id, $form );
1078  }
1079  }
1080 
1081  } // End if zone is not empty ?></div>
1082  <div class="gv-droppable-area-action">
1083  <a href="#" class="gv-add-field button button-link button-hero" title=""
1084  data-objecttype="<?php echo esc_attr( $type ); ?>"
1085  data-areaid="<?php echo esc_attr( $zone . '_' . $area['areaid'] ); ?>"
1086  data-context="<?php echo esc_attr( $zone ); ?>"
1087  data-formid="<?php echo $view ? esc_attr( $view->form ? $view->form->ID : '' ) : ''; ?>"><?php echo '<span class="dashicons dashicons-plus-alt"></span>' . esc_html( $button_label ); ?></a>
1088  </div>
1089  </div>
1090  </div>
1091 
1092  <?php endforeach; ?>
1093 
1094  </div>
1095  <?php endforeach;
1096  endforeach;
1097  }
1098 
1099  /**
1100  * Render the widget active areas
1101  *
1102  * @param string $template_id The current slug of the selected View template
1103  * @param string $zone Either 'header' or 'footer'
1104  * @param string $post_id Current Post ID (view)
1105  *
1106  * @return string html
1107  */
1108  function render_widgets_active_areas( $template_id = '', $zone = '', $post_id = '' ) {
1109 
1110  $default_widget_areas = \GV\Widget::get_default_widget_areas();
1111 
1112  $widgets = array();
1113  if ( ! empty( $post_id ) ) {
1114  if ( 'auto-draft' === get_post_status( $post_id ) ) {
1115  // This is a new View, prefill the widgets
1116  $widgets = array(
1117  'header_top' => array(
1118  substr( md5( microtime( true ) ), 0, 13 ) => array (
1119  'id' => 'search_bar',
1120  'label' => __( 'Search Bar', 'gk-gravityview' ),
1121  'search_layout' => 'horizontal',
1122  'search_clear' => '0',
1123  'search_fields' => '[{"field":"search_all","input":"input_text"}]',
1124  'search_mode' => 'any',
1125  ),
1126  ),
1127  'header_left' => array(
1128  substr( md5( microtime( true ) ), 0, 13 ) => array(
1129  'id' => 'page_info',
1130  'label' => __( 'Show Pagination Info', 'gk-gravityview' ),
1131  ),
1132  ),
1133  'header_right' => array(
1134  substr( md5( microtime( true ) ), 0, 13 ) => array(
1135  'id' => 'page_links',
1136  'label' => __( 'Page Links', 'gk-gravityview' ),
1137  'show_all' => '0',
1138  ),
1139  ),
1140  'footer_right' => array(
1141  substr( md5( microtime( true ) ), 0, 13 ) => array(
1142  'id' => 'page_links',
1143  'label' => __( 'Page Links', 'gk-gravityview' ),
1144  'show_all' => '0',
1145  ),
1146  ),
1147  );
1148 
1149  /**
1150  * @filter `gravityview/view/widgets/default` Modify the default widgets for new Views
1151  * @param array $widgets A Widget configuration array
1152  * @param string $zone The widget zone that's being requested
1153  * @param int $post_id The auto-draft post ID
1154  */
1155  $widgets = apply_filters( 'gravityview/view/widgets/default', $widgets, $template_id, $zone, $post_id );
1156  } else {
1157  $widgets = gravityview_get_directory_widgets( $post_id );
1158  }
1159  }
1160 
1161  ob_start();
1162  ?>
1163 
1164  <div class="gv-grid gv-grid-pad gv-grid-border" id="directory-<?php echo $zone; ?>-widgets">
1165  <?php $this->render_active_areas( $template_id, 'widget', $zone, $default_widget_areas, $widgets ); ?>
1166  </div>
1167 
1168  <?php
1169  $output = ob_get_clean();
1170 
1171  echo $output;
1172 
1173  return $output;
1174  }
1175 
1176  /**
1177  * Renders "Add Field" tooltips
1178  *
1179  * @since 2.0.11
1180  *
1181  * @param string $context "directory", "single", or "edit"
1182  * @param array $form_ids (default: array) Array of form IDs
1183  *
1184  * @return void
1185  */
1186  function render_field_pickers( $context = 'directory', $form_ids = array() ) {
1187 
1188  global $post;
1189 
1190  if ( $post ) {
1191  $source_form_id = gravityview_get_form_id( $post->ID );
1192  if ( $source_form_id ) {
1193  $form_ids[] = $source_form_id;
1194  }
1195 
1196  $joined_forms = \GV\View::get_joined_forms( $post->ID );
1197  foreach ( $joined_forms as $joined_form ) {
1198  $form_ids[] = $joined_form->ID;
1199  }
1200  }
1201  foreach ( array_unique( $form_ids ) as $form_id ) {
1202  $filter_field_id = sprintf( 'gv-field-filter-%s-%s', $context, $form_id );
1203 
1204  ?>
1205  <div id="<?php echo esc_html( $context ); ?>-available-fields-<?php echo esc_attr( $form_id ); ?>" class="hide-if-js gv-tooltip">
1206  <button class="close" role="button" aria-label="<?php esc_html_e( 'Close', 'gk-gravityview' ); ?>"><i class="dashicons dashicons-dismiss"></i></button>
1207 
1208  <div class="gv-field-filter-form">
1209  <label class="screen-reader-text" for="<?php echo esc_html( $filter_field_id ); ?>"><?php esc_html_e( 'Filter Fields:', 'gk-gravityview' ); ?></label>
1210  <input type="search" class="widefat gv-field-filter" aria-controls="<?php echo $filter_field_id; ?>" id="<?php echo esc_html( $filter_field_id ); ?>" placeholder="<?php esc_html_e( 'Filter fields by name or label', 'gk-gravityview' ); ?>" />
1211  <div class="button-group">
1212  <span role="button" class="button button-large gv-items-picker gv-items-picker--grid" data-value="grid"><i class="dashicons dashicons-grid-view "></i></span>
1213  <span role="button" class="button button-large gv-items-picker gv-items-picker--list active" data-value="list"><i class="dashicons dashicons-list-view"></i></span>
1214  </div>
1215  </div>
1216 
1217  <div id="available-fields-<?php echo $filter_field_id; ?>" aria-live="polite" role="listbox" class="gv-items-picker-container">
1218  <?php do_action( 'gravityview_render_available_fields', $form_id, $context ); ?>
1219  </div>
1220 
1221  <div class="gv-no-results hidden description"><?php esc_html_e( 'No fields were found matching the search.', 'gk-gravityview' ); ?></div>
1222  </div>
1223  <?php
1224  }
1225  }
1226 
1227  /**
1228  * Render the Template Active Areas and configured active fields for a given template id and post id
1229  *
1230  * @param string $template_id (default: '') Template ID, like `default_list`, `default_table`, `preset_business_data`, etc. {@see GravityView_Template::__construct()}
1231  * @param string $context (default: 'single') Context of the template. `single` or `directory` (`edit` not implemented but valid).
1232  * @param string $post_id (default: '')
1233  * @param bool $echo (default: false) Whether to echo the output or return it. Default: `false`.
1234  * @param int $form_id (default: 0) Main form ID for the View. Used to set default fields for a new View.
1235  *
1236  * @return string HTML of the active areas
1237  */
1238  function render_directory_active_areas( $template_id = '', $context = 'single', $post_id = 0, $echo = false, $form_id = 0 ) {
1239  if( empty( $template_id ) ) {
1240  gravityview()->log->debug( '[render_directory_active_areas] {template_id} is empty', array( 'template_id' => $template_id ) );
1241  return '';
1242  }
1243 
1244  /**
1245  * @filter `gravityview_template_active_areas`
1246  * @see GravityView_Template::assign_active_areas()
1247  * @param array $template_areas Empty array, to be filled in by the template class
1248  * @param string $template_id Template ID, like `default_list`, `default_table`, `preset_business_data`, etc. {@see GravityView_Template::__construct()}
1249  * @param string $context Current View context: `directory`, `single`, or `edit` (default: 'single')
1250  */
1251  $template_areas = apply_filters( 'gravityview_template_active_areas', array(), $template_id, $context );
1252 
1253  if( empty( $template_areas ) ) {
1254 
1255  gravityview()->log->error( '[render_directory_active_areas] No areas defined. Maybe template {template_id} is disabled.', array( 'data' => $template_id ) );
1256 
1257  $output = '<div>';
1258  $output .= '<h2 class="description" style="font-size: 16px; margin:0">'. sprintf( esc_html__( 'This View is configured using the %s View type, which is disabled.', 'gk-gravityview' ), '<em>'.$template_id.'</em>' ) .'</h2>';
1259  $output .= '<p class="description" style="font-size: 14px; margin:0 0 1em 0;padding:0">'.esc_html__('The data is not lost; re-activate the associated plugin and the configuration will re-appear.', 'gk-gravityview').'</p>';
1260  $output .= '</div>';
1261  } else {
1262 
1263  $fields = gravityview_get_directory_fields( $post_id, true, $form_id );
1264 
1265  ob_start();
1266  $this->render_active_areas( $template_id, 'field', $context, $template_areas, $fields );
1267  $output = ob_get_clean();
1268 
1269  }
1270 
1271  if( $echo ) {
1272  echo $output;
1273  }
1274 
1275  return $output;
1276  }
1277 
1278  /**
1279  * Set the default fields for new Views.
1280  *
1281  * @since 2.17
1282  * @internal Do not use this method directly. Use the `gravityview/view/configuration/fields` filter instead.
1283  *
1284  * @param array $fields A Widget configuration array.
1285  * @param \GV\View $view The View the fields are being pulled for. Unused in this method.
1286  * @param int $form_id The form ID.
1287  *
1288  * @return array
1289  */
1290  public function set_default_view_fields( $fields = array(), $view = null, $form_id = 0 ) {
1291 
1292  if ( empty( $form_id ) ) {
1293  return $fields;
1294  }
1295 
1296  $columns = GFFormsModel::get_grid_columns( $form_id );
1297 
1298  $directory_fields = array();
1299 
1300  foreach ( $columns as $column_id => $column ) {
1301 
1302  $gv_field = GravityView_Fields::get_instance( $column['type'] );
1303 
1304  if ( ! $gv_field ) {
1305  continue;
1306  }
1307 
1308  $directory_fields[ uniqid( '', true ) ] = array(
1309  'label' => \GV\Utils::get( $column, 'label' ),
1310  'type' => $gv_field->name,
1311  'id' => $column_id,
1312  'form_id' => $form_id,
1313  'show_as_link' => empty( $directory_fields ),
1314  );
1315 
1316  }
1317 
1319  $entry_fields = array();
1320 
1321  foreach( $form->form['fields'] as $gv_field ) {
1322 
1323  $entry_fields[ uniqid( '', true ) ] = array(
1324  'label' => $gv_field->label,
1325  'type' => $gv_field->type,
1326  'id' => $gv_field->id,
1327  'form_id' => $form_id,
1328  );
1329 
1330  }
1331 
1332  // Add Edit Entry to the bottom of the Single Entry configuration.
1333  $entry_fields[ uniqid( '', true ) ] = array(
1334  'label' => esc_html__( 'Edit Entry', 'gk-gravityview' ),
1335  'admin_label' => esc_html__( 'Link to Edit Entry', 'gk-gravityview' ),
1336  'type' => 'edit_link',
1337  'id' => 'edit_link',
1338  'form_id' => $form_id,
1339  );
1340 
1341  // This is a new View, prefill the fields
1342  return array(
1343  'directory_table-columns' => $directory_fields,
1344  'single_table-columns' => $entry_fields,
1345  );
1346  }
1347 
1348  /**
1349  * Enqueue scripts and styles at Views editor
1350  *
1351  * @param mixed $hook
1352  * @return void
1353  */
1354  static function add_scripts_and_styles( $hook ) {
1355  global $plugin_page, $pagenow;
1356 
1357  $script_debug = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
1358  $is_widgets_page = ( $pagenow === 'widgets.php' );
1359 
1360  // Add legacy (2.4 and older) Gravity Forms tooltip script/style
1361  if ( gravityview()->plugin->is_GF_25() && gravityview()->request->is_admin( '', 'single' ) ) {
1362  wp_dequeue_script( 'gform_tooltip_init' );
1363  wp_dequeue_style( 'gform_tooltip' );
1364  wp_enqueue_style( 'gravityview_gf_tooltip', plugins_url( 'assets/css/gf_tooltip.css', GRAVITYVIEW_FILE ), array(), \GV\Plugin::$version );
1365  wp_enqueue_script( 'gravityview_gf_tooltip', plugins_url( 'assets/js/gf_tooltip' . $script_debug . '.js', GRAVITYVIEW_FILE ), array(), \GV\Plugin::$version );
1366  }
1367 
1368  // Add the GV font (with the Astronaut)
1369  wp_enqueue_style( 'gravityview_global', plugins_url('assets/css/admin-global.css', GRAVITYVIEW_FILE), array(), \GV\Plugin::$version );
1370  wp_register_style( 'gravityview_views_styles', plugins_url( 'assets/css/admin-views.css', GRAVITYVIEW_FILE ), array( 'dashicons', 'wp-jquery-ui-dialog' ), \GV\Plugin::$version );
1371 
1372  wp_register_script( 'gravityview-jquery-cookie', plugins_url('assets/lib/jquery.cookie/jquery.cookie.min.js', GRAVITYVIEW_FILE), array( 'jquery' ), \GV\Plugin::$version, true );
1373 
1374  if( GFForms::get_page() === 'form_list' ) {
1375  wp_enqueue_style( 'gravityview_views_styles' );
1376  return;
1377  }
1378 
1379  // Don't process any scripts below here if it's not a GravityView page.
1380  if( ! gravityview()->request->is_admin( $hook, 'single' ) && ! $is_widgets_page ) {
1381  return;
1382  }
1383 
1384  wp_enqueue_code_editor( array( 'type' => 'text/html' ) );
1385 
1386  wp_enqueue_script( 'jquery-ui-datepicker' );
1387 
1388  wp_enqueue_style( 'gravityview_views_datepicker', plugins_url('assets/css/admin-datepicker.css', GRAVITYVIEW_FILE), \GV\Plugin::$version );
1389 
1390  // Enqueue scripts
1391  wp_enqueue_script( 'gravityview_views_scripts', plugins_url( 'assets/js/admin-views' . $script_debug . '.js', GRAVITYVIEW_FILE ), array( 'jquery-ui-tabs', 'jquery-ui-draggable', 'jquery-ui-droppable', 'jquery-ui-sortable', 'jquery-ui-tooltip', 'jquery-ui-dialog', 'gravityview-jquery-cookie', 'jquery-ui-datepicker', 'underscore' ), \GV\Plugin::$version );
1392 
1393  wp_localize_script( 'gravityview_views_scripts', 'gvGlobals', array(
1394  'cookiepath' => COOKIEPATH,
1395  'admin_cookiepath' => ADMIN_COOKIE_PATH,
1396  'passed_form_id' => (bool) \GV\Utils::_GET( 'form_id' ),
1397  'has_merge_tag_listener' => (bool) version_compare( GFForms::$version, '2.6.4', '>=' ),
1398  'nonce' => wp_create_nonce( 'gravityview_ajaxviews' ),
1399  'label_viewname' => __( 'Enter View name here', 'gk-gravityview' ),
1400  'label_reorder_search_fields' => __( 'Reorder Search Fields', 'gk-gravityview' ),
1401  'label_add_search_field' => __( 'Add Search Field', 'gk-gravityview' ),
1402  'label_remove_search_field' => __( 'Remove Search Field', 'gk-gravityview' ),
1403  'label_close' => __( 'Close', 'gk-gravityview' ),
1404  'label_cancel' => __( 'Cancel', 'gk-gravityview' ),
1405  'label_continue' => __( 'Continue', 'gk-gravityview' ),
1406  'label_ok' => __( 'Ok', 'gk-gravityview' ),
1407  'label_publisherror' => __( 'Error while creating the View for you. Check the settings or contact GravityView support.', 'gk-gravityview' ),
1408  'loading_text' => esc_html__( 'Loading&hellip;', 'gk-gravityview' ),
1409  'loading_error' => esc_html__( 'There was an error loading dynamic content.', 'gk-gravityview' ),
1410  'field_loaderror' => __( 'Error while adding the field. Please try again or contact GravityView support.', 'gk-gravityview' ),
1411  'remove_all_fields' => __( 'Would you like to remove all fields in this zone?', 'gk-gravityview' ),
1412  'foundation_licenses_router' => array_merge(
1413  GravityKitFoundation::get_ajax_params( 'licenses' ),
1414  array( 'ajaxRoute' => 'activate_product' )
1415  )
1416  ) );
1417 
1418  // Enqueue scripts needed for merge tags
1419  self::enqueue_gravity_forms_scripts();
1420 
1421  wp_enqueue_style( 'gravityview_views_styles' );
1422 
1423  // 2.5 changed how Merge Tags are enqueued
1424  if ( is_callable( array( 'GFCommon', 'output_hooks_javascript') ) ) {
1425  GFCommon::output_hooks_javascript();
1426  }
1427  }
1428 
1429  /**
1430  * Enqueue Gravity Forms scripts, needed for Merge Tags
1431  *
1432  * @since 1.0.5-beta
1433  *
1434  * @return void
1435  */
1436  static function enqueue_gravity_forms_scripts() {
1437  GFForms::register_scripts();
1438 
1439  $scripts = array(
1440  'sack',
1441  'gform_gravityforms',
1442  'gform_forms',
1443  'gform_form_admin',
1444  'jquery-ui-autocomplete'
1445  );
1446 
1447  if ( wp_is_mobile() ) {
1448  $scripts[] = 'jquery-touch-punch';
1449  }
1450 
1451  wp_enqueue_script( $scripts );
1452 
1453  $styles = array(
1454  'gform_admin_icons',
1455  );
1456 
1457  wp_enqueue_style( $styles );
1458  }
1459 
1460  /**
1461  * Add GravityView scripts and styles to Gravity Forms and GravityView No-Conflict modes
1462  *
1463  * @param array $registered Existing scripts or styles that have been registered (array of the handles)
1464  *
1465  * @return array
1466  */
1467  function register_no_conflict( $registered ) {
1468 
1469  $allowed_dependencies = array();
1470 
1471  $filter = current_filter();
1472 
1473  if ( preg_match( '/script/ism', $filter ) ) {
1474 
1475  $allowed_dependencies = array(
1476  'sack',
1477  );
1478 
1479  } elseif ( preg_match( '/style/ism', $filter ) ) {
1480 
1481  $allowed_dependencies = array(
1482  'dashicons',
1483  'wp-jquery-ui-dialog',
1484  );
1485  }
1486 
1487  return array_merge( $registered, $allowed_dependencies );
1488  }
1489 
1490 
1491 }
1492 
static _GET( $name, $default=null)
Grab a value from the _GET superglobal or default.
$forms
Definition: data-source.php:19
gravityview_set_directory_widgets( $post_id, $widgets=array())
Set the widgets, as configured for a View.
static render_field_options( $form_id, $field_type, $template_id, $field_id, $field_label, $area, $input_type=NULL, $uniqid='', $current='', $context='single', $item=array())
Render Field Options html (shown through a dialog box)
get_entry_default_fields($form, $zone)
Retrieve the default fields id, label and type.
static registered()
Return all registered widgets.
if(! isset( $gravityview)||empty( $gravityview->template)) $template
The entry loop for the list output.
suggest_support_articles( $localization_data=array())
When on the Add/Edit View screen, suggest most popular articles related to that.
render_additional_fields( $form_id=0, $context='single')
Render html for displaying additional fields based on a Form ID.
static render_setting_row( $key='', $current_settings=array(), $override_input=null, $name='template_settings[%s]', $id='gravityview_se_%s')
Output a table row for view settings.
gravityview_get_entry_meta( $form_id, $only_default_column=true)
get extra fields from entry meta
static gform_toolbar_menu( $menu_items=array(), $id=NULL)
Add a GravityView menu to the Form Toolbar with connected views.
static get_connected_form_links( $form, $include_form_link=true)
Get HTML links relating to a connected form, like Edit, Entries, Settings, Preview.
gravityview_get_form( $form_id)
Returns the form object for a given Form ID.
gravityview_get_directory_widgets( $post_id)
Get the widgets, as configured for a View.
$class
render_available_fields( $form_id=0, $context='single')
Render html for displaying available fields based on a Form ID.
gravityview_get_directory_fields( $post_id, $apply_filter=true, $form_id=0)
Get the field configuration for the View.
add_custom_column_content( $column_name=null, $post_id=0)
Add the Data Source information.
static get_default_widget_areas()
Default widget areas.
tooltips( $tooltips=array())
Add tooltip text for use throughout the UI.
add_view_dropdown()
Adds dropdown selects to filter Views by connected form and layout.
$templates
global $post
Definition: delete-entry.php:7
If this file is called directly, abort.
if(gravityview() ->plugin->is_GF_25()) $form
set_default_view_fields( $fields=array(), $view=null, $form_id=0)
Set the default fields for new Views.
render_widgets_active_areas( $template_id='', $zone='', $post_id='')
Render the widget active areas.
gravityview_get_forms( $active=true, $trash=false, $order_by='date_created', $order='ASC')
Alias of GFAPI::get_forms()
new GravityView_Admin_Views
$current_settings
static render_field_option( $name='', $option=array(), $curr_value=null)
render_active_areas( $template_id, $type, $zone, $rows, $values)
Generic function to render rows and columns of active areas for widgets & fields. ...
gravityview_get_form_fields( $form='', $add_default_properties=false, $include_parent_field=true)
Return array of fields&#39; id and label, for a given Form ID.
static render_setting_row( $key='', $current_settings=array(), $override_input=null, $name='template_settings[%s]', $id='gravityview_se_%s')
$gv_field
Definition: time.php:11
static pre_get_form_fields( $template_id='')
Get the form fields for a preset (no form created yet)
Definition: class-ajax.php:319
register_no_conflict( $registered)
Add GravityView scripts and styles to Gravity Forms and GravityView No-Conflict modes.
static get_form_or_form_template( $form_id=0)
Returns form object for existing form or a form template.
gravityview_get_connected_views( $form_id, $args=array())
Get the views for a particular form.
add_gf_version_css_class( $class)
Allow targeting different versions of Gravity Forms using CSS selectors.
default_field_blacklist( $array, $context)
gravityview_get_form_id( $view_id)
Get the connected form ID from a View ID.
static render_field_option( $name='', $option=array(), $curr_value=null)
Handle rendering a field option form element.
add_post_type_columns( $columns)
Add the Data Source column to the Views page.
get_registered_widgets()
Get the list of registered widgets.
const GRAVITYVIEW_FILE
Full path to the GravityView file "GRAVITYVIEW_FILE" "./gravityview.php".
Definition: gravityview.php:40
gravityview_get_registered_templates()
Get all available preset templates.
static by_id( $form_id)
Construct a instance by ID.
render_field_pickers( $context='directory', $form_ids=array())
Renders "Add Field" tooltips.
if(empty( $created_by)) $form_id
_gravityview_process_posted_fields()
Maybe convert jQuery-serialized fields into array, otherwise return $_POST[&#39;fields&#39;] array...
gravityview()
The main GravityView wrapper function.
render_available_widgets()
Render html for displaying available widgets.
static get_all( $groups='')
Get all fields.
gravityview_get_template_id( $post_id)
Get the template ID (list, table, datatables, map) for a View.
static get_joined_forms( $post_id)
Get joined forms associated with a view In no particular order.
default_field_blocklist( $array=array(), $context=NULL)
List the field types without presentation properties (on a View context)
static defaults( $detailed=false, $group=null)
Retrieve the default View settings.
render_directory_active_areas( $template_id='', $context='single', $post_id=0, $echo=false, $form_id=0)
Render the Template Active Areas and configured active fields for a given template id and post id...
gravityview_get_joined_forms( $view_id)
Get joined forms associated with a view.
static has_cap( $caps='', $object_id=null, $user_id=null)
Alias of GravityView_Roles_Capabilities::has_cap()
static add_scripts_and_styles( $hook)
Enqueue scripts and styles at Views editor.
get_available_fields( $form='', $zone=NULL)
Calculate the available fields.
$current_form
Definition: data-source.php:13
static enqueue_gravity_forms_scripts()
Enqueue Gravity Forms scripts, needed for Merge Tags.
static from_post( $post)
Construct a instance from a .
static get_instance( $field_name)
save_postdata( $post_id)
Save View configuration.
$title