Completed
Push — develop ( ace222...9d06cc )
by Zack
15:53
created

add_custom_column_content()   B

Complexity

Conditions 8
Paths 9

Size

Total Lines 52

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
cc 8
nc 9
nop 2
dl 0
loc 52
ccs 0
cts 19
cp 0
crap 72
rs 7.8028
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
19
class GravityView_Admin_Views {
20
21
22
23
	function __construct() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
24
		add_action( 'save_post', array( $this, 'save_postdata' ) );
25
26
		// set the blacklist field types across the entire plugin
27
		add_filter( 'gravityview_blacklist_field_types', array( $this, 'default_field_blacklist' ), 10, 2 );
28
29
		// Tooltips
30
		add_filter( 'gform_tooltips', array( $this, 'tooltips') );
31
32
		// adding styles and scripts
33
		add_action( 'admin_enqueue_scripts', array( 'GravityView_Admin_Views', 'add_scripts_and_styles'), 999 );
34
		add_filter( 'gform_noconflict_styles', array( $this, 'register_no_conflict') );
35
		add_filter( 'gform_noconflict_scripts', array( $this, 'register_no_conflict') );
36
		add_filter( 'gravityview_noconflict_styles', array( $this, 'register_no_conflict') );
37
		add_filter( 'gravityview_noconflict_scripts', array( $this, 'register_no_conflict') );
38
39
		add_action( 'gravityview_render_directory_active_areas', array( $this, 'render_directory_active_areas'), 10, 4 );
40
		add_action( 'gravityview_render_widgets_active_areas', array( $this, 'render_widgets_active_areas'), 10, 3 );
41
		add_action( 'gravityview_render_field_pickers', array( $this, 'render_field_pickers'), 10, 2 );
42
		add_action( 'gravityview_render_available_fields', array( $this, 'render_available_fields'), 10, 2 );
43
		add_action( 'gravityview_render_available_widgets', array( $this, 'render_available_widgets') );
44
		add_action( 'gravityview_render_active_areas', array( $this, 'render_active_areas'), 10, 5 );
45
46
		// @todo check if this hook is needed..
47
		//add_action( 'gravityview_render_field_options', array( $this, 'render_field_options'), 10, 9 );
48
49
		// Add Connected Form column
50
		add_filter('manage_gravityview_posts_columns' , array( $this, 'add_post_type_columns' ) );
51
52
		add_filter( 'gform_toolbar_menu', array( 'GravityView_Admin_Views', 'gform_toolbar_menu' ), 10, 2 );
53
		add_action( 'gform_form_actions', array( 'GravityView_Admin_Views', 'gform_toolbar_menu' ), 10, 2 );
54
55
		add_action( 'manage_gravityview_posts_custom_column', array( $this, 'add_custom_column_content'), 10, 2 );
56
57
		add_action( 'restrict_manage_posts', array( $this, 'add_view_dropdown' ) );
58
59
		add_action( 'pre_get_posts', array( $this, 'filter_pre_get_posts' ) );
60
61
		add_filter( 'gravityview/support_port/localization_data', array( $this, 'suggest_support_articles' ) );
62
	}
63
64
	/**
65
     * When on the Add/Edit View screen, suggest most popular articles related to that
66
     *
67
	 * @param array $localization_data Data to be passed to the Support Port JS
68
	 *
69
	 * @return array
70
	 */
71
	function suggest_support_articles( $localization_data = array() ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
72
73
	    if( ! gravityview()->request->is_view() ) {
74
	        return $localization_data;
75
        }
76
77
		$localization_data['suggest'] = array(
78
            '57ef23539033602e61d4a560',
79
            '54c67bb9e4b0512429885513',
80
            '54c67bb9e4b0512429885512',
81
            '54c67bbbe4b07997ea3f3f6b',
82
            '54d1a33ae4b086c0c0964ce9',
83
            '57ef253c9033602e61d4a563',
84
            '552355bfe4b0221aadf2572b',
85
            '54c67bcde4b051242988553e',
86
        );
87
88
		return $localization_data;
89
	}
90
91
	/**
92
	 * @since 1.15
93
	 * @param WP_Query $query
94
	 */
95
	public function filter_pre_get_posts( &$query ) {
96
		global $pagenow;
97
98
		if ( ! is_admin() ) {
99
			return;
100
		}
101
102
		if ( 'edit.php' !== $pagenow ) {
103
			return;
104
		}
105
106
		if ( ! isset( $query->query_vars['post_type'] ) ) {
107
			return;
108
		}
109
110
		if ( 'gravityview' !== $query->query_vars['post_type'] ) {
111
			return;
112
		}
113
114
		$form_id = (int) \GV\Utils::_GET( 'gravityview_form_id' );
115
116
		$meta_query = array();
117
118
		if ( $form_id ) {
119
			$meta_query[] = array(
120
					'key'   => '_gravityview_form_id',
121
					'value' => $form_id,
122
			);
123
		}
124
125
		$layout_id = \GV\Utils::_GET( 'gravityview_layout' );
126
127
		if ( $layout_id ) {
128
			$meta_query[] = array(
129
					'key'   => '_gravityview_directory_template',
130
					'value' => esc_attr( $layout_id ),
131
			);
132
		}
133
134
		$query->set( 'meta_query', $meta_query );
135
	}
136
137
	/**
138
	 * Adds dropdown selects to filter Views by connected form and layout
139
	 *
140
	 * @return void
141
	 */
142
	public function add_view_dropdown() {
143
		$current_screen = get_current_screen();
144
145
		if( 'gravityview' !== $current_screen->post_type ) {
146
			return;
147
		}
148
149
		$forms = gravityview_get_forms();
150
		$current_form = \GV\Utils::_GET( 'gravityview_form_id' );
151
152
		// If there are no forms to select, show no forms.
153
		if( ! empty( $forms ) ) { ?>
154
			<label for="gravityview_form_id" class="screen-reader-text"><?php esc_html_e( 'Filter Views by form', 'gravityview' ); ?></label>
155
			<select name="gravityview_form_id" id="gravityview_form_id">
156
				<option value="" <?php selected( '', $current_form, true ); ?>><?php esc_html_e( 'All forms', 'gravityview' ); ?></option>
157
				<?php foreach( $forms as $form ) { ?>
158
					<option value="<?php echo esc_attr( $form['id'] ); ?>" <?php selected( $form['id'], $current_form, true ); ?>><?php echo esc_html( $form['title'] ); ?></option>
159
				<?php } ?>
160
			</select>
161
		<?php }
162
163
		$layouts = gravityview_get_registered_templates();
164
		$current_layout = \GV\Utils::_GET( 'gravityview_layout' );
165
166
		// If there are no forms to select, show no forms.
167
		if( ! empty( $layouts ) ) { ?>
168
			<label for="gravityview_layout_name" class="screen-reader-text"><?php esc_html_e( 'Filter Views by layout', 'gravityview' ); ?></label>
169
			<select name="gravityview_layout" id="gravityview_layout_name">
170
				<option value="" <?php selected( '', $current_layout, true ); ?>><?php esc_html_e( 'All layouts', 'gravityview' ); ?></option>
171
				<optgroup label="<?php esc_html_e( 'Layouts', 'gravityview' ); ?>">
172
				<?php foreach( $layouts as $layout_id => $layout ) {
173
					if ( in_array( $layout['type'], array( 'preset', 'internal' ), true ) ) {
174
						continue;
175
					}
176
					?>
177
					<option value="<?php echo esc_attr( $layout_id ); ?>" <?php selected( $layout_id, $current_layout, true ); ?>><?php echo esc_html( $layout['label'] ); ?></option>
178
				<?php } ?>
179
				</optgroup>
180
				<optgroup label="<?php esc_html_e( 'Form Presets', 'gravityview' ); ?>">
181
				<?php foreach( $layouts as $layout_id => $layout ) {
182
					if ( ! in_array( $layout['type'], array( 'preset' ), true ) ) {
183
						continue;
184
					}
185
					?>
186
					<option value="<?php echo esc_attr( $layout_id ); ?>" <?php selected( $layout_id, $current_layout, true ); ?>><?php echo esc_html( $layout['label'] ); ?></option>
187
				<?php } ?>
188
				</optgroup>
189
			</select>
190
		<?php }
191
	}
192
193
194
	/**
195
	 * @deprecated since 1.2
196
	 * Start using GravityView_Render_Settings::render_setting_row
197
	 */
198
	public static function render_setting_row( $key = '', $current_settings = array(), $override_input = null, $name = 'template_settings[%s]', $id = 'gravityview_se_%s' ) {
199
		_deprecated_function( 'GravityView_Admin_Views::render_setting_row', '1.1.7', 'GravityView_Render_Settings::render_setting_row' );
200
		GravityView_Render_Settings::render_setting_row( $key, $current_settings, $override_input, $name , $id );
201
	}
202
203
	/**
204
	 * @deprecated since 1.2
205
	 * Start using GravityView_Render_Settings::render_field_option
206
	 */
207
	public static function render_field_option( $name = '', $option, $curr_value = NULL ) {
208
		_deprecated_function( 'GravityView_Admin_Views::render_field_option', '1.1.7', 'GravityView_Render_Settings::render_field_option' );
209
		return GravityView_Render_Settings::render_field_option( $name, $option, $curr_value );
210
	}
211
212
213
	/**
214
	 * Add a GravityView menu to the Form Toolbar with connected views
215
	 * @param  array  $menu_items Menu items, as set in GFForms::top_toolbar()
216
	 * @param  int $id         ID of the current Gravity form
217
	 * @return array            Modified array
218
	 */
219
	public static function gform_toolbar_menu( $menu_items = array(), $id = NULL ) {
220
221
		// Don't show on Trashed forms
222
		if( 'trash' === rgget( 'filter') ) {
223
			return $menu_items;
224
		}
225
226
		$connected_views = gravityview_get_connected_views( $id, array( 'post_status' => 'any' ) );
227
228
		$priority = 0;
229
230
		if( 'form_list' === GFForms::get_page() ) {
231
			$priority = 790;
232
        }
233
234
		if( empty( $connected_views ) ) {
235
236
		    $menu_items['gravityview'] = array(
237
				'label'          => esc_attr__( 'Create a View', 'gravityview' ),
238
				'icon'           => '<i class="fa fa-lg gv-icon-astronaut-head gv-icon"></i>',
239
				'title'          => esc_attr__( 'Create a View using this form as a data source', 'gravityview' ),
240
				'url'            => admin_url( 'post-new.php?post_type=gravityview&form_id=' . $id ),
241
				'menu_class'     => 'gv_connected_forms gf_form_toolbar_settings',
242
				'priority'       => $priority,
243
				'capabilities'   => array( 'edit_gravityviews' ),
244
			);
245
246
			return $menu_items;
247
		}
248
249
		$sub_menu_items = array();
250
		foreach ( (array)$connected_views as $view ) {
251
252
			if( ! GVCommon::has_cap( 'edit_gravityview', $view->ID ) ) {
253
				continue;
254
			}
255
256
			$label = empty( $view->post_title ) ? sprintf( __('No Title (View #%d)', 'gravityview' ), $view->ID ) : $view->post_title;
257
258
			$sub_menu_items[] = array(
259
				'label' => esc_attr( $label ),
260
				'url' => admin_url( 'post.php?action=edit&post='.$view->ID ),
261
			);
262
		}
263
264
		// If there were no items added, then let's create the parent menu
265
		if( $sub_menu_items ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $sub_menu_items of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
266
267
		    $sub_menu_items[] = array(
268
			    'label' => esc_attr__( 'Create a View', 'gravityview' ),
269
                'link_class' => 'gv-create-view',
270
			    'icon' => '<i>&nbsp;+&nbsp;</i>',
271
			    'title' => esc_attr__( 'Create a View using this form as a data source', 'gravityview' ),
272
			    'url'   => admin_url( 'post-new.php?post_type=gravityview&form_id=' . $id ),
273
			    'capabilities'   => array( 'edit_gravityviews' ),
274
            );
275
276
277
			/**
278
			 * In Gravity Forms 2.5, they got rid of the sub-menu items, so we are now forced to add them to the main dropdown
279
			 */
280
			if ( ! ( 'gf_edit_forms' === rgget( 'page' ) && '' === rgget( 'view' ) ) || version_compare( '2.5-beta', GFForms::$version, '>' ) ) {
281
282
				// Make sure Gravity Forms uses the submenu; if there's only one item, it uses a link instead of a dropdown
283
				$sub_menu_items[] = array(
284
					'url' => '#',
285
					'label' => '',
286
					'menu_class' => 'hidden',
287
					'capabilities' => '',
288
				);
289
290
				$menu_items['gravityview'] = array(
291
					'label'          => __( 'Connected Views', 'gravityview' ),
292
					'icon'           => '<i class="fa fa-lg gv-icon-astronaut-head gv-icon"></i>',
293
					'title'          => __( 'GravityView Views using this form as a data source', 'gravityview' ),
294
					'url'            => '#',
295
					'onclick'        => 'return false;',
296
					'menu_class'     => 'gv_connected_forms gf_form_toolbar_settings',
297
					'sub_menu_items' => $sub_menu_items,
298
					'priority'       => $priority,
299
					'capabilities'   => array( 'edit_gravityviews' ),
300
				);
301
302
			} else {
303
304
				$menu_items[ 'gravityview'] = array(
305
					'label' => __( 'Connected Views', 'gravityview' ),
306
					'url'   => '#gravityview-group-heading',
307
					'icon'  => '<i class="fa fa-lg gv-icon-astronaut-head gv-icon"></i>',
308
				);
309
				foreach ( $sub_menu_items as $key => $sub_menu_item ) {
310
311
					$menu_items[ 'gravityview-' . $key ] = array(
312
						'label'        => rgar( $sub_menu_item, 'label', '' ),
313
						'icon'         => rgar( $sub_menu_item, 'icon', '<i>&nbsp;&bull;&nbsp;</i>' ),
314
						'title'        => rgar( $sub_menu_item, 'title', '' ),
315
						'url'          => rgar( $sub_menu_item, 'url', '' ),
316
						'menu_class'   => 'gv_calendar gf_form_toolbar_settings',
317
						'priority'     => $priority,
318
						'capabilities' => array( 'edit_gravityviews' ),
319
					);
320
321
				}
322
			}
323
		}
324
325
		return $menu_items;
326
	}
327
328
	/**
329
	 * List the field types without presentation properties (on a View context)
330
	 *
331
	 * @param array $array Existing field types to add to a blacklist
332
	 * @param string|null $context Context for the blacklist. Default: NULL.
333
	 * @return array Default blacklist fields merged with existing blacklist fields
334
	 */
335
	function default_field_blacklist( $array = array(), $context = NULL ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
336
337
		$add = array( 'captcha', 'page' );
338
339
		// Don't allowing editing the following values:
340
		if( $context === 'edit' ) {
341
			$add[] = 'post_id';
342
		}
343
344
		$return = array_merge( $array, $add );
345
346
		return $return;
347
	}
348
349
	/**
350
	 * Add tooltip text for use throughout the UI
351
	 * @param  array       $tooltips Array of Gravity Forms tooltips
352
	 * @return array                Modified tooltips array
353
	 */
354
	public function tooltips( $tooltips = array() ) {
355
356
		$gv_tooltips = array();
357
358
		// Generate tooltips for View settings
359
		$default_args = \GV\View_Settings::defaults( true );
360
361
		foreach ( $default_args as $key => $arg ) {
362
363
			// If an arg has `tooltip` defined, but it's false, don't display a tooltip
364
			if( isset( $arg['tooltip'] ) && empty( $arg['tooltip'] ) ) { continue; }
365
366
			// By default, use `tooltip` if defined.
367
			$tooltip = empty( $arg['tooltip'] ) ? NULL : $arg['tooltip'];
368
369
			// If there's no tooltip set, continue
370
			if( empty( $tooltip ) ) {
371
				continue;
372
			}
373
374
			// Add the tooltip
375
			$gv_tooltips[ 'gv_'.$key ] = array(
376
				'title'	=> $arg['label'],
377
				'value'	=> $tooltip,
378
			);
379
380
		}
381
382
		$gv_tooltips['gv_css_merge_tags'] = array(
383
			'title' => __('CSS Merge Tags', 'gravityview'),
384
			'value' => sprintf( __( 'Developers: The CSS classes will be sanitized using the %ssanitize_title_with_dashes()%s function.', 'gravityview'), '<code>', '</code>' )
385
		);
386
387
		/**
388
		 * @filter `gravityview_tooltips` The tooltips GravityView adds to the Gravity Forms tooltip array
389
		 * @param array $gv_tooltips Associative array with unique keys containing array of `title` and `value` keys, as expected by `gform_tooltips` filter
390
		 * @deprecated Renamed to `gravityview/metaboxes/tooltips`
391
		 */
392
		$gv_tooltips = apply_filters( 'gravityview_tooltips', $gv_tooltips );
393
394
		/**
395
		 * @filter `gravityview/metaboxes/tooltips` The tooltips GravityView adds to the Gravity Forms tooltip array
396
		 * @param array $gv_tooltips Associative array with unique keys containing array of `title` and `value` keys, as expected by `gform_tooltips` filter
397
		 */
398
		$gv_tooltips = apply_filters( 'gravityview/metaboxes/tooltips', $gv_tooltips );
399
400
		foreach ( $gv_tooltips as $key => $tooltip ) {
401
402
			$title = empty( $tooltip['title'] ) ? '' : '<h6>'.esc_html( $tooltip['title'] ) .'</h6>';
403
404
			$tooltips[ $key ] = $title . wpautop( esc_html( $tooltip['value'] ) );
405
		}
406
407
		return $tooltips;
408
	}
409
410
	/**
411
	 * Add the Data Source information
412
	 *
413
	 * @param null $column_name
414
	 * @param $post_id
415
	 *
416
	 * @return void
417
	 */
418
	public function add_custom_column_content( $column_name = NULL, $post_id )	{
419
420
		$output = '';
421
422
		switch ( $column_name ) {
423
			case 'gv_template':
424
425
				$template_id = gravityview_get_template_id( $post_id );
426
427
				// All Views should have a connected form. If it doesn't, that's not right.
428
				if ( empty( $template_id ) ) {
429
					gravityview()->log->error( 'View ID {view_id} does not have a connected template.', array( 'view_id' => $post_id ) );
430
					break;
431
				}
432
433
				$templates = gravityview_get_registered_templates();
434
435
				$template = isset( $templates[ $template_id ] ) ? $templates[ $template_id ] : false;
436
437
				// Generate backup if label doesn't exist: `example_name` => `Example Name`
438
				$template_id_pretty = ucwords( implode( ' ', explode( '_', $template_id ) ) );
439
440
				$output = $template ? $template['label'] : $template_id_pretty;
441
442
				break;
443
444
			case 'gv_connected_form':
445
446
				$form_id = gravityview_get_form_id( $post_id );
447
448
				// All Views should have a connected form. If it doesn't, that's not right.
449
				if ( empty( $form_id ) ) {
450
					gravityview()->log->error( 'View ID {view_id} does not have a connected GF form.', array( 'view_id' => $post_id ) );
451
					$output = __( 'Not connected.', 'gravityview' );
452
					break;
453
				}
454
455
				$form = gravityview_get_form( $form_id );
456
457
				if ( ! $form ) {
458
					gravityview()->log->error( 'Connected form not found: Form #{form_id}', array( 'form_id' => $form_id ) );
459
460
					$output = __( 'The connected form can not be found; it may no longer exist.', 'gravityview' );
461
				} else {
462
					$output = self::get_connected_form_links( $form );
463
				}
464
465
				break;
466
		}
467
468
		echo $output;
469
	}
470
471
472
	/**
473
	 * Get HTML links relating to a connected form, like Edit, Entries, Settings, Preview
474
	 * @param  array|int $form Gravity Forms forms array, or the form ID
475
	 * @param  boolean $include_form_link Whether to include the bold name of the form in the output
476
	 * @return string          HTML links
477
	 */
478
	static public function get_connected_form_links( $form, $include_form_link = true ) {
479
480
		// Either the form is empty or the form ID is 0, not yet set.
481
		if( empty( $form ) ) {
482
			return '';
483
		}
484
485
		// The $form is passed as the form ID
486
		if( !is_array( $form ) ) {
487
			$form = gravityview_get_form( $form );
488
		}
489
490
		$form_id = $form['id'];
491
		$links = array();
492
493
		if( GVCommon::has_cap( 'gravityforms_edit_forms' ) ) {
494
			$form_url = admin_url( sprintf( 'admin.php?page=gf_edit_forms&amp;id=%d', $form_id ) );
495
			$form_link = '<strong class="gv-form-title">'.gravityview_get_link( $form_url, $form['title'], 'class=row-title' ).'</strong>';
496
			$links[] = '<span>'.gravityview_get_link( $form_url, __('Edit Form', 'gravityview') ).'</span>';
497
		} else {
498
			$form_link = '<strong class="gv-form-title">'. esc_html( $form['title'] ). '</strong>';
499
		}
500
501
		if( GVCommon::has_cap( 'gravityforms_view_entries' ) ) {
502
			$entries_url = admin_url( sprintf( 'admin.php?page=gf_entries&amp;id=%d', $form_id ) );
503
			$links[] = '<span>'.gravityview_get_link( $entries_url, __('Entries', 'gravityview') ).'</span>';
504
		}
505
506
		if( GVCommon::has_cap( array( 'gravityforms_edit_settings', 'gravityview_view_settings' ) ) ) {
507
			$settings_url = admin_url( sprintf( 'admin.php?page=gf_edit_forms&amp;view=settings&amp;id=%d', $form_id ) );
508
			$links[] = '<span>'.gravityview_get_link( $settings_url, __('Settings', 'gravityview'), 'title='.__('Edit settings for this form', 'gravityview') ).'</span>';
509
		}
510
511
		if( GVCommon::has_cap( array("gravityforms_edit_forms", "gravityforms_create_form", "gravityforms_preview_forms") ) ) {
512
			$preview_url = site_url( sprintf( '?gf_page=preview&amp;id=%d', $form_id ) );
513
			$links[] = '<span>'.gravityview_get_link( $preview_url, __('Preview Form', 'gravityview'), 'title='.__('Preview this form', 'gravityview') ).'</span>';
514
		}
515
516
		$output = '';
517
518
		if( !empty( $include_form_link ) ) {
519
			$output .= $form_link;
520
		}
521
522
		/**
523
		 * @filter `gravityview_connected_form_links` Modify the links shown in the Connected Form links
524
		 * @since 1.6
525
		 * @param array $links Links to show
526
		 * @param array $form Gravity Forms form array
527
		 */
528
		$links = apply_filters( 'gravityview_connected_form_links', $links, $form );
529
530
		$output .= '<div class="row-actions">'. implode( ' | ', $links ) .'</div>';
531
532
		return $output;
533
	}
534
535
	/**
536
	 * Add the Data Source column to the Views page
537
	 * @param  array      $columns Columns array
538
	 */
539
	public function add_post_type_columns( $columns ) {
540
541
		// Get the date column and save it for later to add back in.
542
		// This adds it after the Data Source column.
543
		// This way, we don't need to do array_slice, array_merge, etc.
544
		$date = $columns['date'];
545
		unset( $columns['date'] );
546
547
		$data_source_required_caps = array(
548
			'gravityforms_edit_forms',
549
			'gravityforms_view_entries',
550
			'gravityforms_edit_settings',
551
			'gravityview_view_settings',
552
			'gravityforms_create_form',
553
			'gravityforms_preview_forms',
554
		);
555
556
		if( GVCommon::has_cap( $data_source_required_caps ) ) {
557
			$columns['gv_connected_form'] = __( 'Data Source', 'gravityview' );
558
		}
559
560
		$columns['gv_template'] = _x( 'Template', 'Column title that shows what template is being used for Views', 'gravityview' );
561
562
		// Add the date back in.
563
		$columns['date'] = $date;
564
565
		return $columns;
566
	}
567
568
	/**
569
	 * Save View configuration
570
	 *
571
	 * @param int $post_id Currently saved Post ID
572
	 * @return void
573
	 */
574
	function save_postdata( $post_id ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
575
576
		if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ){
577
			return;
578
		}
579
580
		// validate post_type
581
		if ( ! isset( $_POST['post_type'] ) || 'gravityview' != $_POST['post_type'] ) {
582
			return;
583
		}
584
585
		// validate user can edit and save View
586
		if ( ! GVCommon::has_cap( 'edit_gravityview', $post_id ) ) {
587
			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() ) );
588
			return;
589
		}
590
591
		gravityview()->log->debug( '[save_postdata] Saving View post type.', array( 'data' => $_POST ) );
592
593
		$statii = array();
594
595
		// check if this is a start fresh View
596
		if ( isset( $_POST['gravityview_select_form_nonce'] ) && wp_verify_nonce( $_POST['gravityview_select_form_nonce'], 'gravityview_select_form' ) ) {
597
598
			$form_id = !empty( $_POST['gravityview_form_id'] ) ? $_POST['gravityview_form_id'] : '';
599
			// save form id
600
			$statii['form_id'] = update_post_meta( $post_id, '_gravityview_form_id', $form_id );
601
602
		}
603
604
		if( false === GVCommon::has_cap( 'gravityforms_create_form' ) && empty( $statii['form_id'] ) ) {
605
			gravityview()->log->error( 'Current user does not have the capability to create a new Form.', array( 'data' => wp_get_current_user() ) );
606
			return;
607
		}
608
609
		// Was this a start fresh?
610
		if ( ! empty( $_POST['gravityview_form_id_start_fresh'] ) ) {
611
			$statii['start_fresh'] = add_post_meta( $post_id, '_gravityview_start_fresh', 1 );
612
		} else {
613
			$statii['start_fresh'] = delete_post_meta( $post_id, '_gravityview_start_fresh' );
614
		}
615
616
		// Check if we have a template id
617
		if ( isset( $_POST['gravityview_select_template_nonce'] ) && wp_verify_nonce( $_POST['gravityview_select_template_nonce'], 'gravityview_select_template' ) ) {
618
619
			$template_id = !empty( $_POST['gravityview_directory_template'] ) ? $_POST['gravityview_directory_template'] : '';
620
621
			// now save template id
622
			$statii['directory_template'] = update_post_meta( $post_id, '_gravityview_directory_template', $template_id );
623
		}
624
625
626
		// save View Configuration metabox
627
		if ( isset( $_POST['gravityview_view_configuration_nonce'] ) && wp_verify_nonce( $_POST['gravityview_view_configuration_nonce'], 'gravityview_view_configuration' ) ) {
628
629
			// template settings
630
			if( empty( $_POST['template_settings'] ) ) {
631
				$_POST['template_settings'] = array();
632
			}
633
			$statii['template_settings'] = update_post_meta( $post_id, '_gravityview_template_settings', $_POST['template_settings'] );
634
635
			// guard against unloaded View configuration page
636
			if ( isset( $_POST['gv_fields'] ) && isset( $_POST['gv_fields_done'] ) ) {
637
				$fields = array();
638
639
				if ( ! empty( $_POST['gv_fields'] ) ) {
640
					$fields = _gravityview_process_posted_fields();
641
				}
642
643
				$fields = wp_slash( $fields );
644
645
				$statii['directory_fields'] = update_post_meta( $post_id, '_gravityview_directory_fields', $fields );
646
			}
647
648
			// Directory Visible Widgets
649
			if( empty( $_POST['widgets'] ) ) {
650
				$_POST['widgets'] = array();
651
			}
652
			$statii['directory_widgets'] = gravityview_set_directory_widgets( $post_id, $_POST['widgets'] );
653
654
		} // end save view configuration
655
656
		/**
657
		 * @action `gravityview_view_saved` After a View has been saved in the admin
658
		 * @param int $post_id ID of the View that has been saved
659
		 * @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.
660
		 * @since 1.17.2
661
		 */
662
		do_action('gravityview_view_saved', $post_id, $statii );
663
664
		gravityview()->log->debug( '[save_postdata] Update Post Meta Statuses (also returns false if nothing changed)', array( 'data' => array_map( 'intval', $statii ) ) );
665
	}
666
667
	/**
668
	 * @deprecated 1.1.6
669
	 */
670
	function render_label() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
671
		_deprecated_function( 'GravityView_Admin_Views::render_label()', '1.1.6', 'Use the GravityView_Admin_View_Field class instead.' );
672
	}
673
674
	/**
675
	 * Render html for displaying available fields based on a Form ID
676
	 *
677
     * @see GravityView_Ajax::get_available_fields_html() Triggers `gravityview_render_available_fields` action
678
	 *
679
	 * @param int $form Gravity Forms Form ID (default: '')
680
	 * @param string $context (default: 'single')
681
     *
682
	 * @return void
683
	 */
684
	function render_available_fields( $form = 0, $context = 'single' ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
685
686
	    // Determine if form is a preset and convert it to an array with fields
687
		$form = ( is_string( $form ) && preg_match( '/^preset_/', $form ) ) ? GravityView_Ajax::pre_get_form_fields( $form ) : $form;
688
689
		/**
690
		 * @filter  `gravityview_blacklist_field_types` Modify the types of fields that shouldn't be shown in a View.
691
		 * @param[in,out] array $blacklist_field_types Array of field types to block for this context.
692
		 * @param[in] string $context View context ('single', 'directory', or 'edit')
693
		 */
694
		$blacklist_field_types = apply_filters( 'gravityview_blacklist_field_types', array(), $context );
695
696
		if ( ! is_array( $blacklist_field_types ) ) {
697
698
		    gravityview()->log->error( '$blacklist_field_types is not an array', array( 'data' => print_r( $blacklist_field_types, true ) ) );
699
700
			$blacklist_field_types = array();
701
		}
702
703
		$fields = $this->get_available_fields( $form, $context );
704
705
		$output = '';
706
707
		if( !empty( $fields ) ) {
708
709
			foreach( $fields as $id => $details ) {
710
711
				if( in_array( $details['type'], (array) $blacklist_field_types ) ) {
712
					continue;
713
				}
714
715
				// Edit mode only allows editing the parent fields, not single inputs.
716
				if( $context === 'edit' && ! empty( $details['parent'] ) ) {
717
					continue;
718
				}
719
720
				$output .= new GravityView_Admin_View_Field( $details['label'], $id, $details, array(), $form );
721
722
			} // End foreach
723
		}
724
725
		echo $output;
726
727
		// For the EDIT view we only want to allow the form fields.
728
		if( $context === 'edit' ) {
729
			return;
730
		}
731
732
		$this->render_additional_fields( $form, $context );
733
	}
734
735
	/**
736
	 * Render html for displaying additional fields based on a Form ID
737
	 *
738
	 * @param int $form Gravity Forms Form ID (default: '')
739
	 * @param string $context (default: 'single')
740
	 * @return void
741
	 */
742
	public function render_additional_fields( $form = 0, $context = 'single' ) {
0 ignored issues
show
Unused Code introduced by
The parameter $context is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
743
744
		$additional_fields = array(
745
			array(
746
				'label_text' => '+ ' . __( 'Add All Form Fields', 'gravityview' ),
747
				'desc' => __('Insert all the form fields at once.', 'gravityview'),
748
				'field_id' => 'all-fields',
749
				'label_type' => 'field',
750
				'input_type' => null,
751
				'field_options' => null,
752
				'settings_html'	=> null,
753
				'icon' => null,
754
			)
755
		);
756
757
		/**
758
		 * @filter `gravityview_additional_fields` non-standard Fields to show at the bottom of the field picker
759
		 * @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
760
		 */
761
		$additional_fields = apply_filters( 'gravityview_additional_fields', $additional_fields );
762
763
		foreach ( (array) $additional_fields as $item ) {
764
765
			// Prevent items from not having index set
766
			$item = wp_parse_args( $item, array(
767
				'label_text' => null,
768
				'field_id' => null,
769
				'label_type' => null,
770
				'input_type' => null,
771
				'field_options' => null,
772
				'settings_html'	=> null,
773
				'icon' => null,
774
			));
775
776
			// Backward compat.
777
			if( !empty( $item['field_options'] ) ) {
778
				// Use settings_html from now on.
779
				$item['settings_html'] = $item['field_options'];
780
			}
781
782
			// Render a label for each of them
783
			echo new GravityView_Admin_View_Field( $item['label_text'], $item['field_id'], $item, $settings = array(), $form );
784
785
		}
786
787
	}
788
789
	/**
790
	 * Retrieve the default fields id, label and type
791
	 * @param  string|array $form form_ID or form object
792
	 * @param  string $zone   Either 'single', 'directory', 'header', 'footer'
793
	 * @return array
794
	 */
795
	function get_entry_default_fields($form, $zone) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
796
797
		$entry_default_fields = array();
798
799
		if( in_array( $zone, array( 'directory', 'single' ) ) ) {
800
801
			$entry_default_fields = array(
802
				'id' => array(
803
					'label' => __('Entry ID', 'gravityview'),
804
					'type' => 'id',
805
					'desc'	=> __('The unique ID of the entry.', 'gravityview'),
806
				),
807
				'date_created' => array(
808
					'label' => __('Entry Date', 'gravityview'),
809
					'desc'	=> __('The date the entry was created.', 'gravityview'),
810
					'type' => 'date_created',
811
				),
812
				'date_updated' => array(
813
						'label' => __( 'Date Updated', 'gravityview'),
814
						'desc'	=> __('The date the entry was last updated.', 'gravityview'),
815
						'type' => 'date_updated',
816
				),
817
				'source_url' => array(
818
					'label' => __('Source URL', 'gravityview'),
819
					'type' => 'source_url',
820
					'desc'	=> __('The URL of the page where the form was submitted.', 'gravityview'),
821
				),
822
				'ip' => array(
823
					'label' => __('User IP', 'gravityview'),
824
					'type' => 'ip',
825
					'desc'	=> __('The IP Address of the user who created the entry.', 'gravityview'),
826
				),
827
				'created_by' => array(
828
					'label' => __('User', 'gravityview'),
829
					'type' => 'created_by',
830
					'desc'	=> __('Details of the logged-in user who created the entry (if any).', 'gravityview'),
831
				),
832
833
				/**
834
				 * @since 1.7.2
835
				 */
836
			    'other_entries' => array(
837
				    'label'	=> __('Other Entries', 'gravityview'),
838
				    'type'	=> 'other_entries',
839
				    'desc'	=> __('Display other entries created by the entry creator.', 'gravityview'),
840
			    ),
841
	        );
842
843
			if( 'single' !== $zone) {
844
845
				$entry_default_fields['entry_link'] = array(
846
					'label' => __('Link to Entry', 'gravityview'),
847
					'desc'	=> __('A dedicated link to the single entry with customizable text.', 'gravityview'),
848
					'type' => 'entry_link',
849
				);
850
			}
851
852
		} // if not zone directory or single
853
854
		/**
855
		 * @since  1.2
856
		 */
857
		$entry_default_fields['custom']	= array(
858
			'label'	=> __('Custom Content', 'gravityview'),
859
			'type'	=> 'custom',
860
			'desc'	=> __('Insert custom text or HTML.', 'gravityview'),
861
		);
862
863
		/**
864
		 * @since develop
865
		 */
866
		$entry_default_fields['sequence'] = array(
867
			'label'	=> __('Result Number', 'gravityview'),
868
			'type'	=> 'sequence',
869
			'desc'	=> __('Display a sequential result number for each entry.', 'gravityview'),
870
		);
871
872
		/**
873
		 * @filter `gravityview_entry_default_fields` Modify the default fields for each zone and context
874
		 * @param array $entry_default_fields Array of fields shown by default
875
		 * @param  string|array $form form_ID or form object
876
		 * @param  string $zone   Either 'single', 'directory', 'header', 'footer'
877
		 */
878
		return apply_filters( 'gravityview_entry_default_fields', $entry_default_fields, $form, $zone);
879
	}
880
881
	/**
882
	 * Calculate the available fields
883
	 * @param  string|array $form form_ID or form object
884
	 * @param  string $zone   Either 'single', 'directory', 'header', 'footer'
885
	 * @return array         fields
886
	 */
887
	function get_available_fields( $form = '', $zone = NULL ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
888
889
		if( empty( $form ) ) {
890
			gravityview()->log->error( '$form is empty' );
891
			return array();
892
		}
893
894
		// get form fields
895
		$fields = gravityview_get_form_fields( $form, true );
896
897
		// get meta fields ( only if form was already created )
898
		if( !is_array( $form ) ) {
899
			$meta_fields = gravityview_get_entry_meta( $form );
900
		} else {
901
			$meta_fields = array();
902
		}
903
904
		// get default fields
905
		$default_fields = $this->get_entry_default_fields( $form, $zone );
906
907
		//merge without loosing the keys
908
		$fields = $fields + $meta_fields + $default_fields;
909
910
		// Move Custom Content to top
911
		$fields = array( 'custom' => $fields['custom'] ) + $fields;
912
913
		$gv_fields = GravityView_Fields::get_all();
914
915
		foreach ( $fields as &$field ) {
916
			foreach ( $gv_fields as $gv_field ) {
917
				if ( $field['type'] === $gv_field->name ) {
918
					$field['icon'] = $gv_field->icon;
919
				}
920
			}
921
		}
922
923
		/**
924
		 * @filter `gravityview/admin/available_fields` Modify the available fields that can be used in a View.
925
		 * @param[in,out] array $fields The fields.
926
		 * @param  string|array $form form_ID or form object
927
		 * @param  string $zone Either 'single', 'directory', 'header', 'footer'
928
		 */
929
		return apply_filters( 'gravityview/admin/available_fields', $fields, $form, $zone );
930
	}
931
932
933
	/**
934
	 * Render html for displaying available widgets
935
	 * @return string html
936
	 */
937
	function render_available_widgets() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
938
939
		$widgets = $this->get_registered_widgets();
0 ignored issues
show
Deprecated Code introduced by
The method GravityView_Admin_Views::get_registered_widgets() has been deprecated with message: Use \GV\Widget::registered()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
940
941
		if( !empty( $widgets ) ) {
942
943
			foreach( $widgets as $id => $details ) {
944
945
				echo new GravityView_Admin_View_Widget( $details['label'], $id, $details );
946
947
			}
948
		}
949
950
	}
951
952
	/**
953
	 * Get the list of registered widgets. Each item is used to instantiate a GravityView_Admin_View_Widget object
954
	 * @deprecated Use \GV\Widget::registered()
955
	 * @since 1.13.1
956
	 * @return array
957
	 */
958
	function get_registered_widgets() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
959
		return \GV\Widget::registered();
960
	}
961
962
	/**
963
	 * Generic function to render rows and columns of active areas for widgets & fields
964
	 * @param  string $template_id The current slug of the selected View template
965
	 * @param  string $type   Either 'widget' or 'field'
966
	 * @param  string $zone   Either 'single', 'directory', 'edit', 'header', 'footer'
967
	 * @param  array $rows    The layout structure: rows, columns and areas
968
	 * @param  array $values  Saved objects
969
	 * @return void
970
	 */
971
	function render_active_areas( $template_id, $type, $zone, $rows, $values ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
972
		global $post;
973
974
		if( $type === 'widget' ) {
975
			$button_label = __( 'Add Widget', 'gravityview' );
976
		} else {
977
			$button_label = __( 'Add Field', 'gravityview' );
978
		}
979
980
		/**
981
		 * @internal Don't rely on this filter! This is for internal use and may change.
982
		 *
983
		 * @since 2.8.1
984
		 *
985
		 * @param string $button_label Text for button: "Add Widget" or "Add Field"
986
		 * @param array $atts {
987
		 *   @type string $type 'widget' or 'field'
988
		 *   @type string $template_id The current slug of the selected View template
989
		 *   @type string $zone Where is this button being shown? Either 'single', 'directory', 'edit', 'header', 'footer'
990
		 * }
991
		 */
992
		$button_label = apply_filters( 'gravityview/admin/add_button_label', $button_label, array( 'type' => $type, 'template_id' => $template_id, 'zone' => $zone ) );
993
994
		$available_items = array();
995
996
		$view = \GV\View::from_post( $post );
997
		$form_id = null;
998
999
		// if saved values, get available fields to label everyone
1000
		if( !empty( $values ) && ( !empty( $post->ID ) || !empty( $_POST['template_id'] ) ) ) {
1001
1002
			if( !empty( $_POST['template_id'] ) ) {
1003
				$form = GravityView_Ajax::pre_get_form_fields( $_POST['template_id'] );
1004
			} else {
1005
				$form_id = $form = gravityview_get_form_id( $post->ID );
1006
			}
1007
1008
			if ( 'field' === $type ) {
1009
				$available_items[ $form ] = $this->get_available_fields( $form, $zone );
1010
1011
				$joined_forms = gravityview_get_joined_forms( $post->ID );
1012
1013
                foreach ( $joined_forms as $form ) {
1014
                    $available_items[ $form->ID ] = $this->get_available_fields( $form->ID, $zone );
1015
                }
1016
			} else {
1017
				$available_items[ $form ] = \GV\Widget::registered();
1018
			}
1019
		}
1020
1021
		foreach( $rows as $row ) :
1022
			foreach( $row as $col => $areas ) :
1023
				$column = ($col == '2-2') ? '1-2' : $col; ?>
1024
1025
				<div class="gv-grid-col-<?php echo esc_attr( $column ); ?>">
1026
1027
					<?php foreach( $areas as $area ) : 	?>
1028
1029
						<div class="gv-droppable-area" data-areaid="<?php echo esc_attr( $zone .'_'. $area['areaid'] ); ?>" data-context="<?php echo esc_attr( $zone ); ?>">
1030
							<div class="active-drop active-drop-<?php echo esc_attr( $type ); ?>" data-areaid="<?php echo esc_attr( $zone .'_'. $area['areaid'] ); ?>">
1031
								<?php // render saved fields
1032
								if( ! empty( $values[ $zone .'_'. $area['areaid'] ] ) ) {
1033
1034
									foreach( $values[ $zone .'_'. $area['areaid'] ] as $uniqid => $field ) {
1035
1036
										// Maybe has a form ID
1037
										$form_id = empty( $field['form_id'] ) ? $form_id : $field['form_id'];
1038
1039
										$input_type = NULL;
1040
1041
										if ( $form_id ) {
1042
											$original_item = isset( $available_items[ $form_id ] [ $field['id'] ] ) ? $available_items[ $form_id ] [ $field['id'] ] : false ;
1043
                                        } else {
1044
											$original_item = isset( $available_items[ $field['id'] ] ) ? $available_items[ $field['id'] ] : false ;
1045
                                        }
1046
1047
										if ( !$original_item ) {
1048
											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(' data' => array('available_items' => $available_items, 'field' => $field ) ) );
1049
1050
											$original_item = $field;
1051
										} else {
1052
											$input_type = isset( $original_item['type'] ) ? $original_item['type'] : NULL;
1053
										}
1054
1055
										// Field options dialog box
1056
										$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 );
1057
1058
										$item = array(
1059
											'input_type' => $input_type,
1060
											'settings_html' => $field_options,
1061
											'label_type' => $type,
1062
										);
1063
1064
										// Merge the values with the current item to pass things like widget descriptions and original field names
1065
										if ( $original_item ) {
1066
											$item = wp_parse_args( $item, $original_item );
1067
										}
1068
1069
										switch( $type ) {
1070
											case 'widget':
1071
												echo new GravityView_Admin_View_Widget( $item['label'], $field['id'], $item, $field );
1072
												break;
1073
											default:
1074
												echo new GravityView_Admin_View_Field( $field['label'], $field['id'], $item, $field, $form_id );
1075
										}
1076
									}
1077
1078
								} // End if zone is not empty ?>
1079
1080
								<span class="drop-message"><?php echo sprintf( esc_html__('"+ %s" or drag existing %ss here.', 'gravityview'), esc_html( $button_label ), esc_html( $type ) ); ?></span>
1081
							</div>
1082
							<div class="gv-droppable-area-action">
1083
								<button class="gv-add-field button-secondary" title="" data-objecttype="<?php echo esc_attr( $type ); ?>" data-areaid="<?php echo esc_attr( $zone .'_'. $area['areaid'] ); ?>" data-context="<?php echo esc_attr( $zone ); ?>" data-formid="<?php echo $view ? esc_attr( $view->form ? $view->form->ID : '' ) : ''; ?>"><?php echo '+ '.esc_html( $button_label ); ?></button>
1084
								<p class="gv-droppable-area-title"><strong><?php echo esc_html( $area['title'] ); ?></strong><?php if( !empty( $area['subtitle'] ) ) { ?><span class="gv-droppable-area-subtitle"> &ndash; <?php echo esc_html( $area['subtitle'] ); ?></span><?php } ?></p>
1085
							</div>
1086
						</div>
1087
1088
					<?php endforeach; ?>
1089
1090
				</div>
1091
			<?php endforeach;
1092
		endforeach;
1093
	}
1094
1095
	/**
1096
	 * Render the widget active areas
1097
     * @param  string $template_id The current slug of the selected View template
1098
	 * @param  string $zone    Either 'header' or 'footer'
1099
	 * @param  string $post_id Current Post ID (view)
1100
	 * @return string          html
1101
	 */
1102
	function render_widgets_active_areas( $template_id = '', $zone = '', $post_id = '' ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1103
1104
		$default_widget_areas = \GV\Widget::get_default_widget_areas();
1105
1106
		$widgets = array();
1107
		if ( ! empty( $post_id ) ) {
1108
			if ( 'auto-draft' === get_post_status( $post_id ) ) {
1109
				// This is a new View, prefill the widgets
1110
				$widgets = array(
1111
					'header_top' => array(
1112
						substr( md5( microtime( true ) ), 0, 13 ) => array (
1113
							'id' => 'search_bar',
1114
							'label' => __( 'Search Bar', 'gravityview' ),
1115
							'search_layout' => 'horizontal',
1116
							'search_clear' => '0',
1117
							'search_fields' => '[{"field":"search_all","input":"input_text"}]',
1118
							'search_mode' => 'any',
1119
						),
1120
					),
1121
					'header_left' => array(
1122
						substr( md5( microtime( true ) ), 0, 13 ) => array(
1123
							'id' => 'page_info',
1124
							'label' => __( 'Show Pagination Info', 'gravityview' ),
1125
						),
1126
					),
1127
					'header_right' => array(
1128
						substr( md5( microtime( true ) ), 0, 13 ) => array(
1129
							'id' => 'page_links',
1130
							'label' => __( 'Page Links', 'gravityview' ),
1131
							'show_all' => '0',
1132
						),
1133
					),
1134
					'footer_right' => array(
1135
						substr( md5( microtime( true ) ), 0, 13 ) => array(
1136
							'id' => 'page_links',
1137
							'label' => __( 'Page Links', 'gravityview' ),
1138
							'show_all' => '0',
1139
						),
1140
					),
1141
				);
1142
1143
				/**
1144
				 * @filter `gravityview/view/widgets/default` Modify the default widgets for new Views
1145
				 * @param[in,out] array $widgets A Widget configuration array
1146
				 * @param string $zone The widget zone that's being requested
1147
				 * @param int $post_id The auto-draft post ID
1148
				 */
1149
				$widgets = apply_filters( 'gravityview/view/widgets/default', $widgets, $template_id, $zone, $post_id );
1150
			} else {
1151
				$widgets = gravityview_get_directory_widgets( $post_id );
1152
			}
1153
		}
1154
1155
		ob_start();
1156
		?>
1157
1158
		<div class="gv-grid" id="directory-<?php echo $zone; ?>-widgets">
1159
			<?php $this->render_active_areas( $template_id, 'widget', $zone, $default_widget_areas, $widgets ); ?>
1160
		</div>
1161
1162
		<?php
1163
		$output = ob_get_clean();
1164
1165
		echo $output;
1166
1167
		return $output;
1168
	}
1169
1170
	/**
1171
	 * Renders "Add Field" tooltips
1172
	 *
1173
	 * @since 2.0.11
1174
	 *
1175
	 * @param string $context  "directory", "single", or "edit"
1176
	 * @param array  $form_ids (default: array) Array of form IDs
1177
	 *
1178
	 * @return void
1179
	 */
1180
	function render_field_pickers( $context = 'directory', $form_ids = array() ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1181
1182
		global $post;
1183
1184
		if ( $post ) {
1185
			$source_form_id = gravityview_get_form_id( $post->ID );
1186
			if ( $source_form_id ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $source_form_id of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1187
				$form_ids[] = $source_form_id;
1188
			}
1189
1190
			$joined_forms = \GV\View::get_joined_forms( $post->ID );
1191
			foreach ( $joined_forms as $joined_form ) {
1192
				$form_ids[] = $joined_form->ID;
1193
			}
1194
		}
1195
		foreach ( array_unique( $form_ids ) as $form_id ) {
1196
			$filter_field_id = sprintf( 'gv-field-filter-%s-%s', $context, $form_id );
1197
1198
			?>
1199
            <div id="<?php echo esc_html( $context ); ?>-available-fields-<?php echo esc_attr( $form_id ); ?>" class="hide-if-js gv-tooltip">
1200
                <span class="close" role="button" aria-label="<?php esc_html_e( 'Close', 'gravityview' ); ?>"><i class="dashicons dashicons-dismiss"></i></span>
1201
1202
                <div class="gv-field-filter-form">
1203
                    <label class="screen-reader-text" for="<?php echo esc_html( $filter_field_id ); ?>"><?php esc_html_e( 'Filter Fields:', 'gravityview' ); ?></label>
1204
                    <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', 'gravityview' ); ?>" />
1205
                </div>
1206
1207
                <div id="available-fields-<?php echo $filter_field_id; ?>" aria-live="polite" role="listbox">
1208
					<?php do_action( 'gravityview_render_available_fields', $form_id, $context ); ?>
1209
                </div>
1210
1211
                <div class="gv-no-results hidden description"><?php esc_html_e( 'No fields were found matching the search.', 'gravityview' ); ?></div>
1212
            </div>
1213
			<?php
1214
		}
1215
	}
1216
1217
	/**
1218
	 * Render the Template Active Areas and configured active fields for a given template id and post id
1219
	 *
1220
	 * @param string $template_id (default: '') Template ID, like `default_list`, `default_table`, `preset_business_data`, etc. {@see GravityView_Template::__construct()}
1221
	 * @param string $post_id (default: '')
1222
	 * @param string $context (default: 'single')
1223
	 * @return string HTML of the active areas
1224
	 */
1225
	function render_directory_active_areas( $template_id = '', $context = 'single', $post_id = '', $echo = false ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1226
		if( empty( $template_id ) ) {
1227
			gravityview()->log->debug( '[render_directory_active_areas] {template_id} is empty', array( 'template_id' => $template_id ) );
1228
			return '';
1229
		}
1230
1231
		/**
1232
		 * @filter `gravityview_template_active_areas`
1233
		 * @see GravityView_Template::assign_active_areas()
1234
		 * @param array $template_areas Empty array, to be filled in by the template class
1235
		 * @param string $template_id Template ID, like `default_list`, `default_table`, `preset_business_data`, etc. {@see GravityView_Template::__construct()}
1236
		 * @param string $context Current View context: `directory`, `single`, or `edit` (default: 'single')
1237
		 */
1238
		$template_areas = apply_filters( 'gravityview_template_active_areas', array(), $template_id, $context );
1239
1240
		if( empty( $template_areas ) ) {
1241
1242
			gravityview()->log->debug( '[render_directory_active_areas] No areas defined. Maybe template {template_id} is disabled.', array( 'data' => $template_id ) );
1243
			$output = '<div>';
1244
			$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.', 'gravityview' ), '<em>'.$template_id.'</em>' ) .'</h2>';
1245
			$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.', 'gravityview').'</p>';
1246
			$output .= '</div>';
1247
		} else {
1248
1249
			$fields = '';
1250
			if ( ! empty( $post_id ) ) {
1251
				$fields = gravityview_get_directory_fields( $post_id );
1252
			}
1253
1254
			ob_start();
1255
			$this->render_active_areas( $template_id, 'field', $context, $template_areas, $fields );
1256
			$output = ob_get_clean();
1257
1258
		}
1259
1260
		if( $echo ) {
1261
			echo $output;
1262
		}
1263
1264
		return $output;
1265
	}
1266
1267
	/**
1268
	 * Enqueue scripts and styles at Views editor
1269
	 *
1270
	 * @param mixed $hook
1271
	 * @return void
1272
	 */
1273
	static function add_scripts_and_styles( $hook ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1274
		global $plugin_page, $pagenow;
1275
1276
		$script_debug    = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
1277
		$is_widgets_page = ( $pagenow === 'widgets.php' );
1278
1279
		// Add legacy (2.4 and older) Gravity Forms tooltip script/style
1280
		if ( gravityview()->plugin->is_GF_25() && gravityview()->request->is_admin( '', 'single' ) ) {
0 ignored issues
show
Unused Code introduced by
The call to Frontend_Request::is_admin() has too many arguments starting with ''.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
Unused Code introduced by
The call to Request::is_admin() has too many arguments starting with ''.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1281
			wp_dequeue_script( 'gform_tooltip_init' );
1282
			wp_dequeue_style( 'gform_tooltip' );
1283
			wp_enqueue_style( 'gravityview_gf_tooltip', plugins_url( 'assets/css/gf_tooltip.css', GRAVITYVIEW_FILE ), array(), \GV\Plugin::$version );
1284
			wp_enqueue_script( 'gravityview_gf_tooltip', plugins_url( 'assets/js/gf_tooltip' . $script_debug . '.js', GRAVITYVIEW_FILE ), array(), \GV\Plugin::$version );
1285
		}
1286
1287
		// Add the GV font (with the Astronaut)
1288
        wp_enqueue_style( 'gravityview_global', plugins_url('assets/css/admin-global.css', GRAVITYVIEW_FILE), array(), \GV\Plugin::$version );
1289
		wp_register_style( 'gravityview_views_styles', plugins_url( 'assets/css/admin-views.css', GRAVITYVIEW_FILE ), array( 'dashicons', 'wp-jquery-ui-dialog' ), \GV\Plugin::$version );
1290
1291
		wp_register_script( 'gravityview-jquery-cookie', plugins_url('assets/lib/jquery.cookie/jquery.cookie.min.js', GRAVITYVIEW_FILE), array( 'jquery' ), \GV\Plugin::$version, true );
1292
1293
		if( GFForms::get_page() === 'form_list' ) {
1294
			wp_enqueue_style( 'gravityview_views_styles' );
1295
			return;
1296
        }
1297
1298
		// Don't process any scripts below here if it's not a GravityView page.
1299
		if( ! gravityview()->request->is_admin( $hook, 'single' ) && ! $is_widgets_page ) {
0 ignored issues
show
Unused Code introduced by
The call to Frontend_Request::is_admin() has too many arguments starting with $hook.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
Unused Code introduced by
The call to Request::is_admin() has too many arguments starting with $hook.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1300
		    return;
1301
		}
1302
1303
        wp_enqueue_script( 'jquery-ui-datepicker' );
1304
        wp_enqueue_style( 'gravityview_views_datepicker', plugins_url('assets/css/admin-datepicker.css', GRAVITYVIEW_FILE), \GV\Plugin::$version );
1305
1306
        // Enqueue scripts
1307
        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 );
1308
1309
        wp_localize_script('gravityview_views_scripts', 'gvGlobals', array(
1310
            'cookiepath' => COOKIEPATH,
1311
            'passed_form_id' => (bool) \GV\Utils::_GET( 'form_id' ),
1312
            'nonce' => wp_create_nonce( 'gravityview_ajaxviews' ),
1313
            'label_viewname' => __( 'Enter View name here', 'gravityview' ),
1314
            'label_reorder_search_fields' => __( 'Reorder Search Fields', 'gravityview' ),
1315
            'label_add_search_field' => __( 'Add Search Field', 'gravityview' ),
1316
            'label_remove_search_field' => __( 'Remove Search Field', 'gravityview' ),
1317
            'label_close' => __( 'Close', 'gravityview' ),
1318
            'label_cancel' => __( 'Cancel', 'gravityview' ),
1319
            'label_continue' => __( 'Continue', 'gravityview' ),
1320
            'label_ok' => __( 'Ok', 'gravityview' ),
1321
            'label_publisherror' => __( 'Error while creating the View for you. Check the settings or contact GravityView support.', 'gravityview' ),
1322
            'loading_text' => esc_html__( 'Loading&hellip;', 'gravityview' ),
1323
            'loading_error' => esc_html__( 'There was an error loading dynamic content.', 'gravityview' ),
1324
            'field_loaderror' => __( 'Error while adding the field. Please try again or contact GravityView support.', 'gravityview' ),
1325
            'remove_all_fields' => __( 'Would you like to remove all fields in this zone? (You are seeing this message because you were holding down the ALT key)', 'gravityview' ),
1326
        ));
1327
1328
		wp_enqueue_style( 'gravityview_views_styles' );
1329
1330
        // Enqueue scripts needed for merge tags
1331
        self::enqueue_gravity_forms_scripts();
1332
	}
1333
1334
	/**
1335
	 * Enqueue Gravity Forms scripts, needed for Merge Tags
1336
     *
1337
     * @since 1.0.5-beta
1338
     *
1339
     * @return void
1340
	 */
1341
	static function enqueue_gravity_forms_scripts() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1342
		GFForms::register_scripts();
1343
1344
		$scripts = array(
1345
		    'sack',
1346
		    'gform_gravityforms',
1347
		    'gform_forms',
1348
		    'gform_form_admin',
1349
		    'jquery-ui-autocomplete'
1350
		);
1351
1352
		if ( wp_is_mobile() ) {
1353
		    $scripts[] = 'jquery-touch-punch';
1354
		}
1355
1356
		wp_enqueue_script( $scripts );
1357
	}
1358
1359
	/**
1360
	 * Add GravityView scripts and styles to Gravity Forms and GravityView No-Conflict modes
1361
	 *
1362
	 * @param array $registered Existing scripts or styles that have been registered (array of the handles)
1363
	 *
1364
	 * @return array
1365
	 */
1366
	function register_no_conflict( $registered ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1367
1368
		$allowed_dependencies = array();
1369
1370
		$filter = current_filter();
1371
1372
		if ( preg_match( '/script/ism', $filter ) ) {
1373
1374
			$allowed_dependencies = array(
1375
				'jquery-ui-core',
1376
				'jquery-ui-dialog',
1377
				'jquery-ui-tabs',
1378
				'jquery-ui-draggable',
1379
				'jquery-ui-droppable',
1380
				'jquery-ui-sortable',
1381
				'jquery-ui-tooltip',
1382
				'gravityview_views_scripts',
1383
				'gravityview-support',
1384
				'gravityview-jquery-cookie',
1385
				'gravityview_views_datepicker',
1386
				'gravityview_gf_tooltip',
1387
				'sack',
1388
				'gform_gravityforms',
1389
				'gform_forms',
1390
				'gform_form_admin',
1391
				'jquery-ui-autocomplete',
1392
			);
1393
1394
		} elseif ( preg_match( '/style/ism', $filter ) ) {
1395
1396
			$allowed_dependencies = array(
1397
				'dashicons',
1398
				'wp-jquery-ui-dialog',
1399
				'gravityview_views_styles',
1400
				'gravityview_global',
1401
				'gravityview_views_datepicker',
1402
				'gravityview_gf_tooltip',
1403
			);
1404
		}
1405
1406
		return array_merge( $registered, $allowed_dependencies );
1407
	}
1408
1409
1410
}
1411
1412
new GravityView_Admin_Views;
1413