Completed
Pull Request — develop (#1487)
by Gennady
07:46
created

View   F

Complexity

Total Complexity 237

Size/Duplication

Total Lines 1627
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 27

Test Coverage

Coverage 76.15%

Importance

Changes 0
Metric Value
dl 0
loc 1627
ccs 463
cts 608
cp 0.7615
rs 0.8
c 0
b 0
f 0
wmc 237
lcom 1
cbo 27

22 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B register_post_type() 0 104 3
D can_render() 0 92 19
B get_joins() 0 37 10
B get_joined_forms() 0 41 11
F content() 0 140 34
C get_unions() 0 45 13
B from_post() 0 103 6
A _flush_cache() 0 7 2
A by_id() 0 6 3
A exists() 0 3 1
A offsetExists() 0 4 1
B offsetGet() 0 26 10
A offsetSet() 0 3 1
A offsetUnset() 0 3 1
A as_data() 0 12 3
A add_rewrite_endpoint() 0 18 2
F get_entries() 0 540 83
F template_redirect() 0 104 18
A get_query_class() 0 9 1
B restrict() 0 35 11
A __get() 0 7 3

How to fix   Complexity   

Complex Class

Complex classes like View often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use View, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace GV;
3
4
/** If this file is called directly, abort. */
5
if ( ! defined( 'GRAVITYVIEW_DIR' ) ) {
6
	die();
7
}
8
9
/**
10
 * The default GravityView View class.
11
 *
12
 * Houses all base View functionality.
13
 *
14
 * Can be accessed as an array for old compatibility's sake
15
 *  in line with the elements inside the \GravityView_View_Data::$views array.
16
 */
17
class View implements \ArrayAccess {
18
19
	/**
20
	 * @var \WP_Post The backing post instance.
21
	 */
22
	private $post;
23
24
	/**
25
	 * @var \GV\View_Settings The settings.
26
	 *
27
	 * @api
28
	 * @since 2.0
29
	 */
30
	public $settings;
31
32
	/**
33
	 * @var \GV\Widget_Collection The widets attached here.
34
	 *
35
	 * @api
36
	 * @since 2.0
37
	 */
38
	public $widgets;
39
40
	/**
41
	 * @var \GV\GF_Form|\GV\Form The backing form for this view.
42
	 *
43
	 * Contains the form that is sourced for entries in this view.
44
	 *
45
	 * @api
46
	 * @since 2.0
47
	 */
48
	public $form;
49
50
	/**
51
	 * @var \GV\Field_Collection The fields for this view.
52
	 *
53
	 * Contains all the fields that are attached to this view.
54
	 *
55
	 * @api
56
	 * @since 2.0
57
	 */
58
	public $fields;
59
60
	/**
61
	 * @var array
62
	 *
63
	 * Internal static cache for gets, and whatnot.
64
	 * This is not persistent, resets across requests.
65
66
	 * @internal
67
	 */
68
	private static $cache = array();
69
70
	/**
71
	 * @var \GV\Join[] The joins for all sources in this view.
72
	 *
73
	 * @api
74
	 * @since 2.0.1
75
	 */
76
	public $joins = array();
77
78
	/**
79
	 * @var \GV\Field[][] The unions for all sources in this view.
80
	 *                    An array of fields grouped by form_id keyed by
81
	 *                    main field_id:
82
	 *
83
	 *                    array(
84
	 *                        $form_id => array(
85
	 *                            $field_id => $field,
86
	 *                            $field_id => $field,
87
	 *                        )
88
	 *                    )
89
	 *
90
	 * @api
91
	 * @since 2.2.2
92
	 */
93
	public $unions = array();
94
95
	/**
96
	 * The constructor.
97
	 */
98 178
	public function __construct() {
99 178
		$this->settings = new View_Settings();
100 178
		$this->fields = new Field_Collection();
101 178
		$this->widgets = new Widget_Collection();
102 178
	}
103
104
	/**
105
	 * Register the gravityview WordPress Custom Post Type.
106
	 *
107
	 * @internal
108
	 * @return void
109
	 */
110
	public static function register_post_type() {
111
112
		/** Register only once */
113
		if ( post_type_exists( 'gravityview' ) ) {
114
			return;
115
		}
116
117
		/**
118
		 * @filter `gravityview_is_hierarchical` Make GravityView Views hierarchical by returning TRUE
119
		 * This will allow for Views to be nested with Parents and also allows for menu order to be set in the Page Attributes metabox
120
		 * @since 1.13
121
		 * @param boolean $is_hierarchical Default: false
122
		 */
123
		$is_hierarchical = (bool)apply_filters( 'gravityview_is_hierarchical', false );
124
125
		$supports = array( 'title', 'revisions' );
126
127
		if ( $is_hierarchical ) {
128
			$supports[] = 'page-attributes';
129
		}
130
131
		/**
132
		 * @filter  `gravityview_post_type_supports` Modify post type support values for `gravityview` post type
133
		 * @see add_post_type_support()
134
		 * @since 1.15.2
135
		 * @param array $supports Array of features associated with a functional area of the edit screen. Default: 'title', 'revisions'. If $is_hierarchical, also 'page-attributes'
136
		 * @param[in] boolean $is_hierarchical Do Views support parent/child relationships? See `gravityview_is_hierarchical` filter.
137
		 */
138
		$supports = apply_filters( 'gravityview_post_type_support', $supports, $is_hierarchical );
139
140
		/** Register Custom Post Type - gravityview */
141
		$labels = array(
142
			'name'                => _x( 'Views', 'Post Type General Name', 'gravityview' ),
143
			'singular_name'       => _x( 'View', 'Post Type Singular Name', 'gravityview' ),
144
			'menu_name'           => _x( 'Views', 'Menu name', 'gravityview' ),
145
			'parent_item_colon'   => __( 'Parent View:', 'gravityview' ),
146
			'all_items'           => __( 'All Views', 'gravityview' ),
147
			'view_item'           => _x( 'View', 'View Item', 'gravityview' ),
148
			'add_new_item'        => __( 'Add New View', 'gravityview' ),
149
			'add_new'             => __( 'New View', 'gravityview' ),
150
			'edit_item'           => __( 'Edit View', 'gravityview' ),
151
			'update_item'         => __( 'Update View', 'gravityview' ),
152
			'search_items'        => __( 'Search Views', 'gravityview' ),
153
			'not_found'           => \GravityView_Admin::no_views_text(),
154
			'not_found_in_trash'  => __( 'No Views found in Trash', 'gravityview' ),
155
			'filter_items_list'     => __( 'Filter Views list', 'gravityview' ),
156
			'items_list_navigation' => __( 'Views list navigation', 'gravityview' ),
157
			'items_list'            => __( 'Views list', 'gravityview' ),
158
			'view_items'            => __( 'See Views', 'gravityview' ),
159
			'attributes'            => __( 'View Attributes', 'gravityview' ),
160
		);
161
		$args = array(
162
			'label'               => __( 'view', 'gravityview' ),
163
			'description'         => __( 'Create views based on a Gravity Forms form', 'gravityview' ),
164
			'labels'              => $labels,
165
			'supports'            => $supports,
166
			'hierarchical'        => $is_hierarchical,
167
			/**
168
			 * @filter `gravityview_direct_access` Should Views be directly accessible, or only visible using the shortcode?
169
			 * @see https://codex.wordpress.org/Function_Reference/register_post_type#public
170
			 * @since 1.15.2
171
			 * @param[in,out] boolean `true`: allow Views to be accessible directly. `false`: Only allow Views to be embedded via shortcode. Default: `true`
172
			 * @param int $view_id The ID of the View currently being requested. `0` for general setting
173
			 */
174
			'public'              => apply_filters( 'gravityview_direct_access', gravityview()->plugin->is_compatible(), 0 ),
175
			'show_ui'             => gravityview()->plugin->is_compatible(),
176
			'show_in_menu'        => gravityview()->plugin->is_compatible(),
177
			'show_in_nav_menus'   => true,
178
			'show_in_admin_bar'   => true,
179
			'menu_position'       => 17,
180
			'menu_icon'           => '',
181
			'can_export'          => true,
182
			/**
183
			 * @filter `gravityview_has_archive` Enable Custom Post Type archive?
184
			 * @since 1.7.3
185
			 * @param boolean False: don't have frontend archive; True: yes, have archive. Default: false
186
			 */
187
			'has_archive'         => apply_filters( 'gravityview_has_archive', false ),
188
			'exclude_from_search' => true,
189
			'rewrite'             => array(
190
				/**
191
				 * @filter `gravityview_slug` Modify the url part for a View.
192
				 * @see https://docs.gravityview.co/article/62-changing-the-view-slug
193
				 * @param string $slug The slug shown in the URL
194
				 */
195
				'slug' => apply_filters( 'gravityview_slug', 'view' ),
196
197
				/**
198
				 * @filter `gravityview/post_type/with_front` Should the permalink structure
199
				 *  be prepended with the front base.
200
				 *  (example: if your permalink structure is /blog/, then your links will be: false->/view/, true->/blog/view/).
201
				 *  Defaults to true.
202
				 * @see https://codex.wordpress.org/Function_Reference/register_post_type
203
				 * @since 2.0
204
				 * @param bool $with_front
205
				 */
206
				'with_front' => apply_filters( 'gravityview/post_type/with_front', true ),
207
			),
208
			'capability_type'     => 'gravityview',
209
			'map_meta_cap'        => true,
210
		);
211
212
		register_post_type( 'gravityview', $args );
213
	}
214
215
	/**
216
	 * Add extra rewrite endpoints.
217
	 *
218
	 * @return void
219
	 */
220 2
	public static function add_rewrite_endpoint() {
221
		/**
222
		 * CSV.
223
		 */
224
		global $wp_rewrite;
225
226
		$slug = apply_filters( 'gravityview_slug', 'view' );
227
		$rule = array( sprintf( '%s/([^/]+)/csv/?', $slug ), 'index.php?gravityview=$matches[1]&csv=1', 'top' );
228
229
		add_filter( 'query_vars', function( $query_vars ) {
230 2
			$query_vars[] = 'csv';
231 2
			return $query_vars;
232
		} );
233
234
		if ( ! isset( $wp_rewrite->extra_rules_top[ $rule[0] ] ) ) {
235
			call_user_func_array( 'add_rewrite_rule', $rule );
236
		}
237
	}
238
239
	/**
240
	 * A renderer filter for the View post type content.
241
	 *
242
	 * @param string $content Should be empty, as we don't store anything there.
243
	 *
244
	 * @return string $content The view content as output by the renderers.
245
	 */
246 12
	public static function content( $content ) {
247 12
		$request = gravityview()->request;
248
249
		// Plugins may run through the content in the header. WP SEO does this for its OpenGraph functionality.
250 12
		if ( ! defined( 'DOING_GRAVITYVIEW_TESTS' ) ) {
251
			if ( ! did_action( 'loop_start' ) ) {
252
				gravityview()->log->debug( 'Not processing yet: loop_start hasn\'t run yet. Current action: {action}', array( 'action' => current_filter() ) );
253
				return $content;
254
			}
255
256
			//	We don't want this filter to run infinite loop on any post content fields
257
			remove_filter( 'the_content', array( __CLASS__, __METHOD__ ) );
258
		}
259
260
		/**
261
		 * This is not a View. Bail.
262
		 *
263
		 * Shortcodes and oEmbeds and whatnot will be handled
264
		 *  elsewhere.
265
		 */
266 12
		if ( ! $view = $request->is_view() ) {
267 6
			return $content;
268
		}
269
270
		/**
271
		 * Check permissions.
272
		 */
273 6
		while ( $error = $view->can_render( null, $request ) ) {
274 6
			if ( ! is_wp_error( $error ) )
275 6
				break;
276
277 1
			switch ( str_replace( 'gravityview/', '', $error->get_error_code() ) ) {
278 1
				case 'post_password_required':
279 1
					return get_the_password_form( $view->ID );
280 1
				case 'no_form_attached':
281
282
					gravityview()->log->error( 'View #{view_id} cannot render: {error_code} {error_message}', array( 'error_code' => $error->get_error_code(), 'error_message' => $error->get_error_message() ) );
283
284
					/**
285
					 * This View has no data source. There's nothing to show really.
286
					 * ...apart from a nice message if the user can do anything about it.
287
					 */
288
					if ( \GVCommon::has_cap( array( 'edit_gravityviews', 'edit_gravityview' ), $view->ID ) ) {
289
						return __( sprintf( 'This View is not configured properly. Start by <a href="%s">selecting a form</a>.', esc_url( get_edit_post_link( $view->ID, false ) ) ), 'gravityview' );
290
					}
291
					break;
292 1
				case 'in_trash':
293
294
					if ( \GVCommon::has_cap( array( 'edit_gravityviews', 'edit_gravityview' ), $view->ID ) ) {
295
						return __( sprintf( 'This View is in the Trash. You can <a href="%s">restore the View here</a>.', esc_url( get_edit_post_link( $view->ID, false ) ) ), 'gravityview' );
296
					}
297
298
					return ''; // Do not show
299
					break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
300 1
				case 'no_direct_access':
301 1
				case 'embed_only':
302 1
				case 'not_public':
303
				default:
304 1
					gravityview()->log->notice( 'View #{view_id} cannot render: {error_code} {error_message}', array( 'error_code' => $error->get_error_code(), 'error_message' => $error->get_error_message() ) );
305 1
					return __( 'You are not allowed to view this content.', 'gravityview' );
306
			}
307
308
			return $content;
309
		}
310
311 6
		$is_admin_and_can_view = $view->settings->get( 'admin_show_all_statuses' ) && \GVCommon::has_cap('gravityview_moderate_entries', $view->ID );
312
313
		/**
314
		 * Editing a single entry.
315
		 */
316 6
		if ( $entry = $request->is_edit_entry( $view->form ? $view->form->ID : 0 ) ) {
317
			if ( $entry['status'] != 'active' ) {
318
				gravityview()->log->notice( 'Entry ID #{entry_id} is not active', array( 'entry_id' => $entry->ID ) );
319
				return __( 'You are not allowed to view this content.', 'gravityview' );
320
			}
321
322
			if ( apply_filters( 'gravityview_custom_entry_slug', false ) && $entry->slug != get_query_var( \GV\Entry::get_endpoint_name() ) ) {
323
				gravityview()->log->error( 'Entry ID #{entry_id} was accessed by a bad slug', array( 'entry_id' => $entry->ID ) );
324
				return __( 'You are not allowed to view this content.', 'gravityview' );
325
			}
326
327
			if ( $view->settings->get( 'show_only_approved' ) && ! $is_admin_and_can_view ) {
328
				if ( ! \GravityView_Entry_Approval_Status::is_approved( gform_get_meta( $entry->ID, \GravityView_Entry_Approval::meta_key ) )  ) {
329
					gravityview()->log->error( 'Entry ID #{entry_id} is not approved for viewing', array( 'entry_id' => $entry->ID ) );
330
					return __( 'You are not allowed to view this content.', 'gravityview' );
331
				}
332
			}
333
334
			$renderer = new Edit_Entry_Renderer();
335
			return $renderer->render( $entry, $view, $request );
336
337
		/**
338
		 * Viewing a single entry.
339
		 */
340 6
		} else if ( $entry = $request->is_entry( $view->form ? $view->form->ID : 0 ) ) {
341
342 2
			$entryset = $entry->is_multi() ? $entry->entries : array( $entry );
343
344 2
			$custom_slug = apply_filters( 'gravityview_custom_entry_slug', false );
345 2
			$ids = explode( ',', get_query_var( \GV\Entry::get_endpoint_name() ) );
346
347 2
			$show_only_approved = $view->settings->get( 'show_only_approved' );
348
349 2
			foreach ( $entryset as $e ) {
350
351 2
				if ( 'active' !== $e['status'] ) {
352 1
					gravityview()->log->notice( 'Entry ID #{entry_id} is not active', array( 'entry_id' => $e->ID ) );
353 1
					return __( 'You are not allowed to view this content.', 'gravityview' );
354
				}
355
356 2
				if ( $custom_slug && ! in_array( $e->slug, $ids ) ) {
357 1
					gravityview()->log->error( 'Entry ID #{entry_id} was accessed by a bad slug', array( 'entry_id' => $e->ID ) );
358 1
					return __( 'You are not allowed to view this content.', 'gravityview' );
359
				}
360
361 2
				if ( $show_only_approved && ! $is_admin_and_can_view ) {
362 1
					if ( ! \GravityView_Entry_Approval_Status::is_approved( gform_get_meta( $e->ID, \GravityView_Entry_Approval::meta_key ) )  ) {
363 1
						gravityview()->log->error( 'Entry ID #{entry_id} is not approved for viewing', array( 'entry_id' => $e->ID ) );
364 1
						return __( 'You are not allowed to view this content.', 'gravityview' );
365
					}
366
				}
367
368 2
				$error = \GVCommon::check_entry_display( $e->as_entry(), $view );
369
370 2
				if ( is_wp_error( $error ) ) {
371
					gravityview()->log->error( 'Entry ID #{entry_id} is not approved for viewing: {message}', array( 'entry_id' => $e->ID, 'message' => $error->get_error_message() ) );
372
					return __( 'You are not allowed to view this content.', 'gravityview' );
373
				}
374
			}
375
376 2
			$renderer = new Entry_Renderer();
377 2
			return $renderer->render( $entry, $view, $request );
378
		}
379
380
		/**
381
		 * Plain old View.
382
		 */
383 5
		$renderer = new View_Renderer();
384 5
		return $renderer->render( $view, $request );
385
	}
386
387
	/**
388
	 * Checks whether this view can be accessed or not.
389
	 *
390
	 * @param string[]    $context The context we're asking for access from.
391
	 *                             Can any and as many of one of:
392
	 *                                 edit      An edit context.
393
	 *                                 single    A single context.
394
	 *                                 cpt       The custom post type single page accessed.
395
	 *                                 shortcode Embedded as a shortcode.
396
	 *                                 oembed    Embedded as an oEmbed.
397
	 *                                 rest      A REST call.
398
	 * @param \GV\Request $request The request
399
	 *
400
	 * @return bool|\WP_Error An error if this View shouldn't be rendered here.
401
	 */
402 28
	public function can_render( $context = null, $request = null ) {
403 28
		if ( ! $request ) {
404 6
			$request = gravityview()->request;
405
		}
406
407 28
		if ( ! is_array( $context ) ) {
408 6
			$context = array();
409
		}
410
411
		/**
412
		 * @filter `gravityview/view/can_render` Whether the view can be rendered or not.
413
		 * @param bool|\WP_Error $result  The result. Default: null.
414
		 * @param \GV\View       $view	The view.
415
		 * @param string[]       $context See \GV\View::can_render
416
		 * @param \GV\Request    $request The request.
417
		 */
418 28
		if ( ! is_null( $result = apply_filters( 'gravityview/view/can_render', null, $this, $context, $request ) ) ) {
419
			return $result;
420
		}
421
422 28
		if ( in_array( 'rest', $context ) ) {
423
			// REST
424 8
			if ( gravityview()->plugin->settings->get( 'rest_api' ) === '1' && $this->settings->get( 'rest_disable' ) === '1' ) {
425 1
				return new \WP_Error( 'gravityview/rest_disabled' );
426 8
			} elseif ( gravityview()->plugin->settings->get( 'rest_api' ) !== '1' && $this->settings->get( 'rest_enable' ) !== '1' ) {
427 1
				return new \WP_Error( 'gravityview/rest_disabled' );
428
			}
429
		}
430
431 28
		if ( in_array( 'csv', $context ) ) {
432 6
			if ( $this->settings->get( 'csv_enable' ) !== '1' ) {
433 1
				return new \WP_Error( 'gravityview/csv_disabled', 'The CSV endpoint is not enabled for this View' );
434
			}
435
		}
436
437
		/**
438
		 * This View is password protected. Nothing to do here.
439
		 */
440 28
		if ( post_password_required( $this->ID ) ) {
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
441 3
			gravityview()->log->notice( 'Post password is required for View #{view_id}', array( 'view_id' => $this->ID ) );
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
442 3
			return new \WP_Error( 'gravityview/post_password_required' );
443
		}
444
445 28
		if ( ! $this->form ) {
446
			gravityview()->log->notice( 'View #{id} has no form attached to it.', array( 'id' => $this->ID ) );
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
447
			return new \WP_Error( 'gravityview/no_form_attached' );
448
		}
449
450 28
		if ( ! in_array( 'shortcode', $context ) ) {
451
			/**
452
			 * Is this View directly accessible via a post URL?
453
			 *
454
			 * @see https://codex.wordpress.org/Function_Reference/register_post_type#public
455
			 */
456
457
			/**
458
			 * @filter `gravityview_direct_access` Should Views be directly accessible, or only visible using the shortcode?
459
			 * @deprecated
460
			 * @param[in,out] boolean `true`: allow Views to be accessible directly. `false`: Only allow Views to be embedded. Default: `true`
461
			 * @param int $view_id The ID of the View currently being requested. `0` for general setting
462
			 */
463 20
			$direct_access = apply_filters( 'gravityview_direct_access', true, $this->ID );
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
464
465
			/**
466
			 * @filter `gravityview/request/output/direct` Should this View be directly accessbile?
467
			 * @since 2.0
468
			 * @param[in,out] boolean Accessible or not. Default: accessbile.
469
			 * @param \GV\View $view The View we're trying to directly render here.
470
			 * @param \GV\Request $request The current request.
471
			 */
472 20
			if ( ! apply_filters( 'gravityview/view/output/direct', $direct_access, $this, $request ) ) {
473
				return new \WP_Error( 'gravityview/no_direct_access' );
474
			}
475
476
			/**
477
			 * Is this View an embed-only View? If so, don't allow rendering here,
478
			 *  as this is a direct request.
479
			 */
480 20
			if ( $this->settings->get( 'embed_only' ) && ! \GVCommon::has_cap( 'read_private_gravityviews' ) ) {
481 1
				return new \WP_Error( 'gravityview/embed_only' );
482
			}
483
		}
484
485
		/** Private, pending, draft, etc. */
486 28
		$public_states = get_post_stati( array( 'public' => true ) );
487 28
		if ( ! in_array( $this->post_status, $public_states ) && ! \GVCommon::has_cap( 'read_gravityview', $this->ID ) ) {
0 ignored issues
show
Documentation introduced by
The property post_status does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property ID does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
488 3
			gravityview()->log->notice( 'The current user cannot access this View #{view_id}', array( 'view_id' => $this->ID ) );
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
489 3
			return new \WP_Error( 'gravityview/not_public' );
490
		}
491
492 28
		return true;
493
	}
494
495
	/**
496
	 * Get joins associated with a view
497
	 *
498
	 * @param \WP_Post $post GravityView CPT to get joins for
499
	 *
500
	 * @api
501
	 * @since 2.0.11
502
	 *
503
	 * @return \GV\Join[] Array of \GV\Join instances
504
	 */
505 178
	public static function get_joins( $post ) {
506 178
		$joins = array();
507
508 178
		if ( ! gravityview()->plugin->supports( Plugin::FEATURE_JOINS ) ) {
509
			gravityview()->log->error( 'Cannot get joined forms; joins feature not supported.' );
510
			return $joins;
511
		}
512
513 178
		if ( ! $post || 'gravityview' !== get_post_type( $post ) ) {
514
			gravityview()->log->error( 'Only "gravityview" post types can be \GV\View instances.' );
515
			return $joins;
516
		}
517
518 178
		$joins_meta = get_post_meta( $post->ID, '_gravityview_form_joins', true );
519
520 178
		if ( empty( $joins_meta ) ) {
521 166
			return $joins;
522
		}
523
524 12
		foreach ( $joins_meta as $meta ) {
525 12
			if ( ! is_array( $meta ) || count( $meta ) != 4 ) {
526
				continue;
527
			}
528
529 12
			list( $join, $join_column, $join_on, $join_on_column ) = $meta;
530
531 12
			$join    = GF_Form::by_id( $join );
532 12
			$join_on = GF_Form::by_id( $join_on );
533
534 12
			$join_column    = is_numeric( $join_column ) ? GF_Field::by_id( $join, $join_column ) : Internal_Field::by_id( $join_column );
535 12
			$join_on_column = is_numeric( $join_on_column ) ? GF_Field::by_id( $join_on, $join_on_column ) : Internal_Field::by_id( $join_on_column );
536
537 12
			$joins [] = new Join( $join, $join_column, $join_on, $join_on_column );
538
		}
539
540 12
		return $joins;
541
	}
542
543
	/**
544
	 * Get joined forms associated with a view
545
	 * In no particular order.
546
	 *
547
	 * @since 2.0.11
548
	 *
549
	 * @api
550
	 * @since 2.0
551
	 * @param int $post_id ID of the View
552
	 *
553
	 * @return \GV\GF_Form[] Array of \GV\GF_Form instances
554
	 */
555 2
	public static function get_joined_forms( $post_id ) {
556 2
		$forms = array();
557
558 2
		if ( ! gravityview()->plugin->supports( Plugin::FEATURE_JOINS ) ) {
559
			gravityview()->log->error( 'Cannot get joined forms; joins feature not supported.' );
560
			return $forms;
561
		}
562
563 2
		if ( ! $post_id || ! gravityview()->plugin->supports( Plugin::FEATURE_JOINS ) ) {
564
			return $forms;
565
		}
566
567 2
		if ( empty( $post_id ) ) {
568
			gravityview()->log->error( 'Cannot get joined forms; $post_id was empty' );
569
			return $forms;
570
		}
571
572 2
		$joins_meta = get_post_meta( $post_id, '_gravityview_form_joins', true );
573
574 2
		if ( empty( $joins_meta ) ) {
575
			return $forms;
576
		}
577
578 2
		foreach ( $joins_meta  as $meta ) {
579 2
			if ( ! is_array( $meta ) || count( $meta ) != 4 ) {
580
				continue;
581
			}
582
583 2
			list( $join, $join_column, $join_on, $join_on_column ) = $meta;
584
585 2
			if ( $form = GF_Form::by_id( $join_on ) ) {
586 2
				$forms[ $join_on ] = $form;
587
			}
588
589 2
			if ( $form = GF_Form::by_id( $join ) ) {
590 2
				$forms[ $join ] = $form;
591
			}
592
		}
593
594 2
		return $forms;
595
	}
596
597
	/**
598
	 * Get unions associated with a view
599
	 *
600
	 * @param \WP_Post $post GravityView CPT to get unions for
601
	 *
602
	 * @api
603
	 * @since 2.2.2
604
	 *
605
	 * @return \GV\Field[][] Array of unions (see self::$unions)
606
	 */
607 178
	public static function get_unions( $post ) {
608 178
		$unions = array();
609
610 178
		if ( ! $post || 'gravityview' !== get_post_type( $post ) ) {
611
			gravityview()->log->error( 'Only "gravityview" post types can be \GV\View instances.' );
612
			return $unions;
613
		}
614
615 178
		$fields = get_post_meta( $post->ID, '_gravityview_directory_fields', true );
616
617 178
		if ( empty( $fields ) ) {
618 1
			return $unions;
619
		}
620
621 177
		foreach ( $fields as $location => $_fields ) {
622 177
			if ( strpos( $location, 'directory_' ) !== 0 ) {
623 51
				continue;
624
			}
625
626 128
			foreach ( $_fields as $field ) {
627 128
				if ( ! empty( $field['unions'] ) ) {
628 1
					foreach ( $field['unions'] as $form_id => $field_id ) {
629 1
						if ( ! isset( $unions[ $form_id ] ) ) {
630 1
							$unions[ $form_id ] = array();
631
						}
632
633 1
						$unions[ $form_id ][ $field['id'] ] =
634 1
							is_numeric( $field_id ) ? \GV\GF_Field::by_id( \GV\GF_Form::by_id( $form_id ), $field_id ) : \GV\Internal_Field::by_id( $field_id );
635
					}
636
				}
637
			}
638
639 128
			break;
640
		}
641
642 177
		if ( $unions ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $unions 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...
643 1
			if ( ! gravityview()->plugin->supports( Plugin::FEATURE_UNIONS ) ) {
644
				gravityview()->log->error( 'Cannot get unions; unions feature not supported.' );
645
			}
646
		}
647
648
		// @todo We'll probably need to backfill null unions
649
650 177
		return $unions;
651
	}
652
653
	/**
654
	 * Construct a \GV\View instance from a \WP_Post.
655
	 *
656
	 * @param \WP_Post $post The \WP_Post instance to wrap.
657
	 *
658
	 * @api
659
	 * @since 2.0
660
	 * @return \GV\View|null An instance around this \WP_Post if valid, null otherwise.
661
	 */
662 179
	public static function from_post( $post ) {
663
664 179
		if ( ! $post || 'gravityview' !== get_post_type( $post ) ) {
665 2
			gravityview()->log->error( 'Only gravityview post types can be \GV\View instances.' );
666 2
			return null;
667
		}
668
669 179
		if ( $view = Utils::get( self::$cache, "View::from_post:{$post->ID}" ) ) {
670
			/**
671
			 * @filter `gravityview/view/get` Override View.
672
			 * @param \GV\View $view The View instance pointer.
673
			 * @since 2.1
674
			 */
675 105
			do_action_ref_array( 'gravityview/view/get', array( &$view ) );
676
677 105
			return $view;
678
		}
679
680 179
		$view = new self();
681 179
		$view->post = $post;
682
683
		/** Get connected form. */
684 179
		$view->form = GF_Form::by_id( $view->_gravityview_form_id );
0 ignored issues
show
Documentation introduced by
The property _gravityview_form_id does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
685 179
		if ( ! $view->form ) {
686
			gravityview()->log->error( 'View #{view_id} tried attaching non-existent Form #{form_id} to it.', array(
687
				'view_id' => $view->ID,
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
688
				'form_id' => $view->_gravityview_form_id ? : 0,
0 ignored issues
show
Documentation introduced by
The property _gravityview_form_id does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
689
			) );
690
		}
691
692 179
		$view->joins = $view::get_joins( $post );
693
694 179
		$view->unions = $view::get_unions( $post );
695
696
		/**
697
		 * @filter `gravityview/configuration/fields` Filter the View fields' configuration array.
698
		 * @since 1.6.5
699
		 *
700
		 * @deprecated Use `gravityview/view/configuration/fields` or `gravityview/view/fields` filters.
701
		 *
702
		 * @param $fields array Multi-array of fields with first level being the field zones.
703
		 * @param $view_id int The View the fields are being pulled for.
704
		 */
705 179
		$configuration = apply_filters( 'gravityview/configuration/fields', (array)$view->_gravityview_directory_fields, $view->ID );
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
706
707
		/**
708
		 * @filter `gravityview/view/configuration/fields` Filter the View fields' configuration array.
709
		 * @since 2.0
710
		 *
711
		 * @param array $fields Multi-array of fields with first level being the field zones.
712
		 * @param \GV\View $view The View the fields are being pulled for.
713
		 */
714 179
		$configuration = apply_filters( 'gravityview/view/configuration/fields', $configuration, $view );
715
716
		/**
717
		 * @filter `gravityview/view/fields` Filter the Field Collection for this View.
718
		 * @since 2.0
719
		 *
720
		 * @param \GV\Field_Collection $fields A collection of fields.
721
		 * @param \GV\View $view The View the fields are being pulled for.
722
		 */
723 179
		$view->fields = apply_filters( 'gravityview/view/fields', Field_Collection::from_configuration( $configuration ), $view );
724
725
		/**
726
		 * @filter `gravityview/view/configuration/widgets` Filter the View widgets' configuration array.
727
		 * @since 2.0
728
		 *
729
		 * @param array $fields Multi-array of widgets with first level being the field zones.
730
		 * @param \GV\View $view The View the widgets are being pulled for.
731
		 */
732 179
		$configuration = apply_filters( 'gravityview/view/configuration/widgets', (array)$view->_gravityview_directory_widgets, $view );
733
734
		/**
735
		 * @filter `gravityview/view/widgets` Filter the Widget Collection for this View.
736
		 * @since 2.0
737
		 *
738
		 * @param \GV\Widget_Collection $widgets A collection of widgets.
739
		 * @param \GV\View $view The View the widgets are being pulled for.
740
		 */
741 179
		$view->widgets = apply_filters( 'gravityview/view/widgets', Widget_Collection::from_configuration( $configuration ), $view );
742
743
		/** View configuration. */
744 179
		$view->settings->update( gravityview_get_template_settings( $view->ID ) );
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
745
746
		/** Add the template name into the settings. */
747 179
		$view->settings->update( array( 'template' => gravityview_get_template_id( $view->ID ) ) );
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
748
749
		/** View basics. */
750 179
		$view->settings->update( array(
751 179
			'id' => $view->ID,
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
752
		) );
753
754 179
		self::$cache[ "View::from_post:{$post->ID}" ] = &$view;
755
756
		/**
757
		 * @filter `gravityview/view/get` Override View.
758
		 * @param \GV\View $view The View instance pointer.
759
		 * @since 2.1
760
		 */
761 179
		do_action_ref_array( 'gravityview/view/get', array( &$view ) );
762
763 179
		return $view;
764
	}
765
766
	/**
767
	 * Flush the view cache.
768
	 *
769
	 * @param int $view_id The View to reset cache for. Optional. Default: resets everything.
770
	 *
771
	 * @internal
772
	 */
773 190
	public static function _flush_cache( $view_id = null ) {
774 190
		if ( $view_id ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $view_id of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

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

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
775 184
			unset( self::$cache[ "View::from_post:$view_id" ] );
776 184
			return;
777
		}
778 95
		self::$cache = array();
779 95
	}
780
781
	/**
782
	 * Construct a \GV\View instance from a post ID.
783
	 *
784
	 * @param int|string $post_id The post ID.
785
	 *
786
	 * @api
787
	 * @since 2.0
788
	 * @return \GV\View|null An instance around this \WP_Post or null if not found.
789
	 */
790 119
	public static function by_id( $post_id ) {
791 119
		if ( ! $post_id || ! $post = get_post( $post_id ) ) {
792 3
			return null;
793
		}
794 119
		return self::from_post( $post );
795
	}
796
797
	/**
798
	 * Determines if a view exists to begin with.
799
	 *
800
	 * @param int|\WP_Post|null $view The WordPress post ID, a \WP_Post object or null for global $post;
801
	 *
802
	 * @api
803
	 * @since 2.0
804
	 * @return bool Whether the post exists or not.
805
	 */
806 25
	public static function exists( $view ) {
807 25
		return get_post_type( $view ) == 'gravityview';
808
	}
809
810
	/**
811
	 * ArrayAccess compatibility layer with GravityView_View_Data::$views
812
	 *
813
	 * @internal
814
	 * @deprecated
815
	 * @since 2.0
816
	 * @return bool Whether the offset exists or not, limited to GravityView_View_Data::$views element keys.
817
	 */
818 14
	public function offsetExists( $offset ) {
819 14
		$data_keys = array( 'id', 'view_id', 'form_id', 'template_id', 'atts', 'fields', 'widgets', 'form' );
820 14
		return in_array( $offset, $data_keys );
821
	}
822
823
	/**
824
	 * ArrayAccess compatibility layer with GravityView_View_Data::$views
825
	 *
826
	 * Maps the old keys to the new data;
827
	 *
828
	 * @internal
829
	 * @deprecated
830
	 * @since 2.0
831
	 *
832
	 * @return mixed The value of the requested view data key limited to GravityView_View_Data::$views element keys. If offset not found, return null.
833
	 */
834 14
	public function offsetGet( $offset ) {
835
836 14
		gravityview()->log->notice( 'This is a \GV\View object should not be accessed as an array.' );
837
838 14
		if ( ! isset( $this[ $offset ] ) ) {
839
			return null;
840
		}
841
842 14
		switch ( $offset ) {
843 14
			case 'id':
844 14
			case 'view_id':
845 1
				return $this->ID;
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
846 14
			case 'form':
847 14
				return $this->form;
848 1
			case 'form_id':
849 1
				return $this->form ? $this->form->ID : null;
850 1
			case 'atts':
851
				return $this->settings->as_atts();
0 ignored issues
show
Deprecated Code introduced by
The method GV\View_Settings::as_atts() has been deprecated.

This method has been deprecated.

Loading history...
852 1
			case 'template_id':
853 1
				return $this->settings->get( 'template' );
854
			case 'widgets':
855
				return $this->widgets->as_configuration();
856
		}
857
858
		return null;
859
	}
860
861
	/**
862
	 * ArrayAccess compatibility layer with GravityView_View_Data::$views
863
	 *
864
	 * @internal
865
	 * @deprecated
866
	 * @since 2.0
867
	 *
868
	 * @return void
869
	 */
870 1
	public function offsetSet( $offset, $value ) {
871 1
		gravityview()->log->error( 'The old view data is no longer mutable. This is a \GV\View object should not be accessed as an array.' );
872 1
	}
873
874
	/**
875
	 * ArrayAccess compatibility layer with GravityView_View_Data::$views
876
	 *
877
	 * @internal
878
	 * @deprecated
879
	 * @since 2.0
880
	 * @return void
881
	 */
882 1
	public function offsetUnset( $offset ) {
883 1
		gravityview()->log->error( 'The old view data is no longer mutable. This is a \GV\View object should not be accessed as an array.' );
884 1
	}
885
886
	/**
887
	 * Be compatible with the old data object.
888
	 *
889
	 * Some external code expects an array (doing things like foreach on this, or array_keys)
890
	 *  so let's return an array in the old format for such cases. Do not use unless using
891
	 *  for back-compatibility.
892
	 *
893
	 * @internal
894
	 * @deprecated
895
	 * @since 2.0
896
	 * @return array
897
	 */
898 28
	public function as_data() {
899
		return array(
900 28
			'id' => $this->ID,
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
901 28
			'view_id' => $this->ID,
0 ignored issues
show
Documentation introduced by
The property ID does not exist on object<GV\View>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
902 28
			'form_id' => $this->form ? $this->form->ID : null,
903 28
			'form' => $this->form ? gravityview_get_form( $this->form->ID ) : null,
904 28
			'atts' => $this->settings->as_atts(),
0 ignored issues
show
Deprecated Code introduced by
The method GV\View_Settings::as_atts() has been deprecated.

This method has been deprecated.

Loading history...
905 28
			'fields' => $this->fields->by_visible( $this )->as_configuration(),
906 28
			'template_id' => $this->settings->get( 'template' ),
907 28
			'widgets' => $this->widgets->as_configuration(),
908
		);
909
	}
910
911
	/**
912
	 * Retrieve the entries for the current view and request.
913
	 *
914
	 * @param \GV\Request The request. Unused for now.
915
	 *
916
	 * @return \GV\Entry_Collection The entries.
917
	 */
918 70
	public function get_entries( $request = null ) {
919 70
		$entries = new \GV\Entry_Collection();
920
921 70
		if ( $this->form ) {
922 70
			$parameters = $this->settings->as_atts();
0 ignored issues
show
Deprecated Code introduced by
The method GV\View_Settings::as_atts() has been deprecated.

This method has been deprecated.

Loading history...
923
924
			/**
925
			 * Remove multiple sorting before calling legacy filters.
926
			 * This allows us to fake it till we make it.
927
			 */
928 70
			if ( ! empty( $parameters['sort_field'] ) && is_array( $parameters['sort_field'] ) ) {
929 2
				$has_multisort = true;
930 2
				$parameters['sort_field'] = reset( $parameters['sort_field'] );
931 2
				if ( ! empty( $parameters['sort_direction'] ) && is_array( $parameters['sort_direction'] ) ) {
932 2
					$parameters['sort_direction'] = reset( $parameters['sort_direction'] );
933
				}
934
			}
935
936
			/**
937
			 * @todo: Stop using _frontend and use something like $request->get_search_criteria() instead
938
			 */
939 70
			$parameters = \GravityView_frontend::get_view_entries_parameters( $parameters, $this->form->ID );
940
941 70
			$parameters['context_view_id'] = $this->ID;
0 ignored issues
show
Bug introduced by
The property ID does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
942 70
			$parameters = \GVCommon::calculate_get_entries_criteria( $parameters, $this->form->ID );
943
944 70
			if ( ! is_array( $parameters ) ) {
945
				$parameters = array();
946
			}
947
948 70
			if ( ! is_array( $parameters['search_criteria'] ) ) {
949
				$parameters['search_criteria'] = array();
950
			}
951
952 70
			if ( ( ! isset( $parameters['search_criteria']['field_filters'] ) ) || ( ! is_array( $parameters['search_criteria']['field_filters'] ) ) ) {
953
				$parameters['search_criteria']['field_filters'] = array();
954
			}
955
956 70
			if ( $request instanceof REST\Request ) {
957 6
				$atts = $this->settings->as_atts();
0 ignored issues
show
Deprecated Code introduced by
The method GV\View_Settings::as_atts() has been deprecated.

This method has been deprecated.

Loading history...
958 6
				$paging_parameters = wp_parse_args( $request->get_paging(), array(
959 6
						'paging' => array( 'page_size' => $atts['page_size'] ),
960
					) );
961 6
				$parameters['paging'] = $paging_parameters['paging'];
962
			}
963
964 70
			$page = Utils::get( $parameters['paging'], 'current_page' ) ?
965 70
				: ( ( ( $parameters['paging']['offset'] - $this->settings->get( 'offset' ) ) / \GV\Utils::get( $parameters, 'paging/page_size', 25 ) ) + 1 );
966
967
			/**
968
			 * Cleanup duplicate field_filter parameters to simplify the query.
969
			 */
970 70
			$unique_field_filters = array();
971 70
			foreach ( Utils::get( $parameters, 'search_criteria/field_filters', array() ) as $key => $filter ) {
972 22
				if ( 'mode' === $key ) {
973 21
					$unique_field_filters['mode'] = $filter;
974 22
				} else if ( ! in_array( $filter, $unique_field_filters ) ) {
975 22
					$unique_field_filters[] = $filter;
976
				}
977
			}
978 70
			$parameters['search_criteria']['field_filters'] = $unique_field_filters;
979
980 70
			if ( ! empty( $parameters['search_criteria']['field_filters'] ) ) {
981 22
				gravityview()->log->notice( 'search_criteria/field_filters is not empty, third-party code may be using legacy search_criteria filters.' );
982
			}
983
984 70
			if ( gravityview()->plugin->supports( Plugin::FEATURE_GFQUERY ) ) {
985
986 70
				$query_class = $this->get_query_class();
987
988
				/** @var \GF_Query $query */
989 70
				$query = new $query_class( $this->form->ID, $parameters['search_criteria'], Utils::get( $parameters, 'sorting' ) );
990
991
				/**
992
				 * Apply multisort.
993
				 */
994 70
				if ( ! empty( $has_multisort ) ) {
995 2
					$atts = $this->settings->as_atts();
0 ignored issues
show
Deprecated Code introduced by
The method GV\View_Settings::as_atts() has been deprecated.

This method has been deprecated.

Loading history...
996
997 2
					$view_setting_sort_field_ids = \GV\Utils::get( $atts, 'sort_field', array() );
998 2
					$view_setting_sort_directions = \GV\Utils::get( $atts, 'sort_direction', array() );
999
1000 2
					$has_sort_query_param = ! empty( $_GET['sort'] ) && is_array( $_GET['sort'] );
1001
1002 2
					if( $has_sort_query_param ) {
1003
						$has_sort_query_param = array_filter( array_values( $_GET['sort'] ) );
1004
					}
1005
1006 2
					if ( $this->settings->get( 'sort_columns' ) && $has_sort_query_param ) {
1007
						$sort_field_ids = array_keys( $_GET['sort'] );
1008
						$sort_directions = array_values( $_GET['sort'] );
1009
					} else {
1010 2
						$sort_field_ids = $view_setting_sort_field_ids;
1011 2
						$sort_directions = $view_setting_sort_directions;
1012
					}
1013
1014 2
					$skip_first = false;
1015
1016 2
					foreach ( (array) $sort_field_ids as $key => $sort_field_id ) {
1017
1018 2
						if ( ! $skip_first && ! $has_sort_query_param ) {
1019 2
							$skip_first = true; // Skip the first one, it's already in the query
1020 2
							continue;
1021
						}
1022
1023 1
						$sort_field_id = \GravityView_frontend::_override_sorting_id_by_field_type( $sort_field_id, $this->form->ID );
1024 1
						$sort_direction = strtoupper( \GV\Utils::get( $sort_directions, $key, 'ASC' ) );
1025
1026 1
						if ( ! empty( $sort_field_id ) ) {
1027 1
							$order = new \GF_Query_Column( $sort_field_id, $this->form->ID );
1028 1
							if ( \GVCommon::is_field_numeric( $this->form->ID, $sort_field_id ) ) {
1029
								$order = \GF_Query_Call::CAST( $order, defined( 'GF_Query::TYPE_DECIMAL' ) ? \GF_Query::TYPE_DECIMAL : \GF_Query::TYPE_SIGNED );
1030
							}
1031
1032 1
							$query->order( $order, $sort_direction );
1033
						}
1034
					}
1035
				}
1036
1037
				/**
1038
				 * Merge time subfield sorts.
1039
				 */
1040
				add_filter( 'gform_gf_query_sql', $gf_query_timesort_sql_callback = function( $sql ) use ( &$query ) {
1041 70
					$q = $query->_introspect();
1042 70
					$orders = array();
1043
1044 70
					$merged_time = false;
1045
1046 70
					foreach ( $q['order'] as $oid => $order ) {
1047 70
						if ( $order[0] instanceof \GF_Query_Column ) {
0 ignored issues
show
Bug introduced by
The class GF_Query_Column does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
1048 69
							$column = $order[0];
1049 1
						} else if ( $order[0] instanceof \GF_Query_Call ) {
0 ignored issues
show
Bug introduced by
The class GF_Query_Call does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
1050 1
							if ( count( $order[0]->columns ) != 1 || ! $order[0]->columns[0] instanceof \GF_Query_Column ) {
0 ignored issues
show
Bug introduced by
The class GF_Query_Column does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
1051
								$orders[ $oid ] = $order;
1052
								continue; // Need something that resembles a single sort
1053
							}
1054 1
							$column = $order[0]->columns[0];
1055
						}
1056
1057 70
						if ( ( ! $field = \GFAPI::get_field( $column->source, $column->field_id ) ) || $field->type !== 'time' ) {
0 ignored issues
show
Bug introduced by
The variable $column does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1058 69
							$orders[ $oid ] = $order;
1059 69
							continue; // Not a time field
1060
						}
1061
1062 1
						if ( ! class_exists( '\GV\Mocks\GF_Query_Call_TIMESORT' ) ) {
1063 1
							require_once gravityview()->plugin->dir( 'future/_mocks.timesort.php' );
1064
						}
1065
1066 1
						$orders[ $oid ] = array(
1067 1
							new \GV\Mocks\GF_Query_Call_TIMESORT( 'timesort', array( $column, $sql ) ),
1068 1
							$order[1] // Mock it!
1069
						);
1070
1071 1
						$merged_time = true;
1072
					}
1073
1074 70
					if ( $merged_time ) {
1075
						/**
1076
						 * ORDER again.
1077
						 */
1078 1
						if ( ! empty( $orders ) && $_orders = $query->_order_generate( $orders ) ) {
1079 1
							$sql['order'] = 'ORDER BY ' . implode( ', ', $_orders );
1080
						}
1081
					}
1082
1083 70
					return $sql;
1084 70
				} );
1085
1086 70
				$query->limit( $parameters['paging']['page_size'] )
1087 70
					->offset( ( ( $page - 1 ) * $parameters['paging']['page_size'] ) + $this->settings->get( 'offset' ) );
1088
1089
				/**
1090
				 * Any joins?
1091
				 */
1092 70
				if ( gravityview()->plugin->supports( Plugin::FEATURE_JOINS ) && count( $this->joins ) ) {
1093
1094 12
					$is_admin_and_can_view = $this->settings->get( 'admin_show_all_statuses' ) && \GVCommon::has_cap( 'gravityview_moderate_entries', $this->ID );
1095
1096 12
					foreach ( $this->joins as $join ) {
1097 12
						$query = $join->as_query_join( $query );
1098
1099 12
						if ( $this->settings->get( 'multiple_forms_disable_null_joins' ) ) {
1100
1101
							// Disable NULL outputs
1102
							$condition = new \GF_Query_Condition(
1103
								new \GF_Query_Column( $join->join_on_column->ID, $join->join_on->ID ),
0 ignored issues
show
Bug introduced by
The property ID does not seem to exist in GV\Source.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1104
								\GF_Query_Condition::NEQ,
1105
								new \GF_Query_Literal( '' )
1106
							);
1107
1108
							$query_parameters = $query->_introspect();
1109
1110
							$query->where( \GF_Query_Condition::_and( $query_parameters['where'], $condition ) );
1111
						}
1112
1113
						/**
1114
						 * This is a temporary stub filter, until GF_Query supports NULL conditions.
1115
						 * Do not use! This filter will be removed.
1116
						 */
1117 12
						if ( defined( 'GF_Query_Condition::NULL' ) ) {
1118 12
							$is_null_condition_native = true;
1119
						} else {
1120
							$is_null_condition_class = apply_filters( 'gravityview/query/is_null_condition', null );
1121
							$is_null_condition_native = false;
1122
						}
1123
1124
						// Filter to active entries only
1125 12
						$condition = new \GF_Query_Condition(
1126 12
							new \GF_Query_Column( 'status', $join->join_on->ID ),
1127 12
							\GF_Query_Condition::EQ,
1128 12
							new \GF_Query_Literal( 'active' )
1129
						);
1130
1131 12
						if ( $is_null_condition_native ) {
1132 12
							$condition = \GF_Query_Condition::_or( $condition, new \GF_Query_Condition(
1133 12
								new \GF_Query_Column( 'status', $join->join_on->ID ),
1134 12
								\GF_Query_Condition::IS,
1135 12
								\GF_Query_Condition::NULL
1136
							) );
1137
						} else if ( ! is_null( $is_null_condition_class ) ) {
1138
							$condition = \GF_Query_Condition::_or( $condition, new $is_null_condition_class(
0 ignored issues
show
Bug introduced by
The variable $is_null_condition_class does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1139
								new \GF_Query_Column( 'status', $join->join_on->ID )
1140
							) );
1141
						}
1142
1143 12
						$q = $query->_introspect();
1144 12
						$query->where( \GF_Query_Condition::_and( $q['where'], $condition ) );
1145
1146 12
						if ( $this->settings->get( 'show_only_approved' ) && ! $is_admin_and_can_view ) {
1147
1148
							// Show only approved joined entries
1149 1
							$condition = new \GF_Query_Condition(
1150 1
								new \GF_Query_Column( \GravityView_Entry_Approval::meta_key, $join->join_on->ID ),
1151 1
								\GF_Query_Condition::EQ,
1152 1
								new \GF_Query_Literal( \GravityView_Entry_Approval_Status::APPROVED )
1153
							);
1154
1155 1
							if ( $is_null_condition_native ) {
1156 1
								$condition = \GF_Query_Condition::_or( $condition, new \GF_Query_Condition(
1157 1
									new \GF_Query_Column( \GravityView_Entry_Approval::meta_key, $join->join_on->ID ),
1158 1
									\GF_Query_Condition::IS,
1159 1
									\GF_Query_Condition::NULL
1160
								) );
1161
							} else if ( ! is_null( $is_null_condition_class ) ) {
1162
								$condition = \GF_Query_Condition::_or( $condition, new $is_null_condition_class(
1163
									new \GF_Query_Column( \GravityView_Entry_Approval::meta_key, $join->join_on->ID )
1164
								) );
1165
							}
1166
1167 1
							$query_parameters = $query->_introspect();
1168
1169 1
							$query->where( \GF_Query_Condition::_and( $query_parameters['where'], $condition ) );
1170
						}
1171
					}
1172
1173
				/**
1174
				 * Unions?
1175
				 */
1176 58
				} else if ( gravityview()->plugin->supports( Plugin::FEATURE_UNIONS ) && count( $this->unions ) ) {
1177 1
					$query_parameters = $query->_introspect();
1178
1179 1
					$unions_sql = array();
1180
1181
					/**
1182
					 * @param \GF_Query_Condition $condition
1183
					 * @param array $fields
1184
					 * @param $recurse
1185
					 *
1186
					 * @return \GF_Query_Condition
1187
					 */
1188
					$where_union_substitute = function( $condition, $fields, $recurse ) {
1189 1
						if ( $condition->expressions ) {
1190 1
							$conditions = array();
1191
1192 1
							foreach ( $condition->expressions as $_condition ) {
1193 1
								$conditions[] = $recurse( $_condition, $fields, $recurse );
1194
							}
1195
1196 1
							return call_user_func_array(
1197 1
								array( '\GF_Query_Condition', $condition->operator == 'AND' ? '_and' : '_or' ),
1198 1
								$conditions
1199
							);
1200
						}
1201
1202 1
						if ( ! ( $condition->left && $condition->left instanceof \GF_Query_Column ) || ( ! $condition->left->is_entry_column() && ! $condition->left->is_meta_column() ) ) {
0 ignored issues
show
Bug introduced by
The class GF_Query_Column does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
1203 1
							return new \GF_Query_Condition(
1204 1
								new \GF_Query_Column( $fields[ $condition->left->field_id ]->ID ),
1205 1
								$condition->operator,
1206 1
								$condition->right
1207
							);
1208
						}
1209
1210 1
						return $condition;
1211 1
					};
1212
1213 1
					foreach ( $this->unions as $form_id => $fields ) {
1214
1215
						// Build a new query for every unioned form
1216 1
						$query_class = $this->get_query_class();
1217
1218
						/** @var \GF_Query|\GF_Patched_Query $q */
1219 1
						$q = new $query_class( $form_id );
1220
1221
						// Copy the WHERE clauses but substitute the field_ids to the respective ones
1222 1
						$q->where( $where_union_substitute( $query_parameters['where'], $fields, $where_union_substitute ) );
1223
1224
						// Copy the ORDER clause and substitute the field_ids to the respective ones
1225 1
						foreach ( $query_parameters['order'] as $order ) {
1226 1
							list( $column, $_order ) = $order;
1227
1228 1
							if ( $column && $column instanceof \GF_Query_Column ) {
0 ignored issues
show
Bug introduced by
The class GF_Query_Column does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
1229 1
								if ( ! $column->is_entry_column() && ! $column->is_meta_column() ) {
1230 1
									$column = new \GF_Query_Column( $fields[ $column->field_id ]->ID );
1231
								}
1232
1233 1
								$q->order( $column, $_order );
1234
							}
1235
						}
1236
1237
						add_filter( 'gform_gf_query_sql', $gf_query_sql_callback = function( $sql ) use ( &$unions_sql ) {
1238
							// Remove SQL_CALC_FOUND_ROWS as it's not needed in UNION clauses
1239 1
							$select = 'UNION ALL ' . str_replace( 'SQL_CALC_FOUND_ROWS ', '', $sql['select'] );
1240
1241
							// Record the SQL
1242 1
							$unions_sql[] = array(
1243
								// Remove columns, we'll rebuild them
1244 1
								'select'  => preg_replace( '#DISTINCT (.*)#', 'DISTINCT ', $select ),
1245 1
								'from'    => $sql['from'],
1246 1
								'join'    => $sql['join'],
1247 1
								'where'   => $sql['where'],
1248
								// Remove order and limit
1249
							);
1250
1251
							// Return empty query, no need to call the database
1252 1
							return array();
1253 1
						} );
1254
1255 1
						do_action_ref_array( 'gravityview/view/query', array( &$q, $this, $request ) );
1256
1257 1
						$q->get(); // Launch
1258
1259 1
						remove_filter( 'gform_gf_query_sql', $gf_query_sql_callback );
1260
					}
1261
1262
					add_filter( 'gform_gf_query_sql', $gf_query_sql_callback = function( $sql ) use ( $unions_sql ) {
1263
						// Remove SQL_CALC_FOUND_ROWS as it's not needed in UNION clauses
1264 1
						$sql['select'] = str_replace( 'SQL_CALC_FOUND_ROWS ', '', $sql['select'] );
1265
1266
						// Remove columns, we'll rebuild them
1267 1
						preg_match( '#DISTINCT (`[motc]\d+`.`.*?`)#', $sql['select'], $select_match );
1268 1
						$sql['select'] = preg_replace( '#DISTINCT (.*)#', 'DISTINCT ', $sql['select'] );
1269
1270 1
						$unions = array();
1271
1272
						// Transform selected columns to shared alias names
1273
						$column_to_alias = function( $column ) {
1274 1
							$column = str_replace( '`', '', $column );
1275 1
							return '`' . str_replace( '.', '_', $column ) . '`';
1276 1
						};
1277
1278
						// Add all the order columns into the selects, so we can order by the whole union group
1279 1
						preg_match_all( '#(`[motc]\d+`.`.*?`)#', $sql['order'], $order_matches );
1280
1281
						$columns = array(
1282 1
							sprintf( '%s AS %s', $select_match[1], $column_to_alias( $select_match[1] ) )
1283
						);
1284
1285 1
						foreach ( array_slice( $order_matches, 1 ) as $match ) {
1286 1
							$columns[] = sprintf( '%s AS %s', $match[0], $column_to_alias( $match[0] ) );
1287
1288
							// Rewrite the order columns to the shared aliases
1289 1
							$sql['order'] = str_replace( $match[0], $column_to_alias( $match[0] ), $sql['order'] );
1290
						}
1291
1292 1
						$columns = array_unique( $columns );
1293
1294
						// Add the columns to every UNION
1295 1
						foreach ( $unions_sql as $union_sql ) {
1296 1
							$union_sql['select'] .= implode( ', ', $columns );
1297 1
							$unions []= implode( ' ', $union_sql );
1298
						}
1299
1300
						// Add the columns to the main SELECT, but only grab the entry id column
1301 1
						$sql['select'] = 'SELECT SQL_CALC_FOUND_ROWS t1_id FROM (' . $sql['select'] . implode( ', ', $columns );
1302 1
						$sql['order'] = implode( ' ', $unions ) . ') AS u ' . $sql['order'];
1303
1304 1
						return $sql;
1305 1
					} );
1306
				}
1307
1308
				/**
1309
				 * @action `gravityview/view/add_filtersorts` The best place to create filtersorts.
1310
				 * @see `gravityview/view/remove_filtersorts` filter to remove filtersorts afterwards.
1311
				 *
1312
				 * @param \GV\View $view This view.
1313
				 * @param \GV\Request $request The request.
1314
				 *
1315
				 * @since develop
1316
				 */
1317 70
				do_action( 'gravityview/view/add_filtersorts', $this, $request );
1318
1319
				/**
1320
				 * If a PHP filtersort has been set remove all the pagination limits and offset.
1321
				 *
1322
				 * Since we're sorting and/or filtering in PHP we need to grab the whole dataset.
1323
				 * We will apply manual offest and pagination afterwards.
1324
				 */
1325 70
				if ( has_filter( 'gravityview/entries/filter' ) || has_filter( 'gravityview/entries/sort' ) ) {
1326 13
					$has_filtersort = true;
1327 13
					$query->limit( 0 )->offset( 0 );
1328
				}
1329
1330
				/**
1331
				 * @action `gravityview/view/query` Override the \GF_Query before the get() call.
1332
				 * @param \GF_Query $query The current query object reference
1333
				 * @param \GV\View $this The current view object
1334
				 * @param \GV\Request $request The request object
1335
				 */
1336 70
				do_action_ref_array( 'gravityview/view/query', array( &$query, $this, $request ) );
1337
1338 70
				gravityview()->log->debug( 'GF_Query parameters: ', array( 'data' => Utils::gf_query_debug( $query ) ) );
1339
1340
				/**
1341
				 * Map from Gravity Forms entries arrays to an Entry_Collection.
1342
				 */
1343 70
				if ( count( $this->joins ) ) {
1344 12
					foreach ( $query->get() as $entry ) {
1345 12
						$entries->add(
1346 12
							Multi_Entry::from_entries( array_map( '\GV\GF_Entry::from_entry', $entry ) )
1347
						);
1348
					}
1349
				} else {
1350 58
					array_map( array( $entries, 'add' ), array_map( '\GV\GF_Entry::from_entry', $query->get() ) );
1351
				}
1352
1353 70
				if ( isset( $gf_query_sql_callback ) ) {
1354 1
					remove_action( 'gform_gf_query_sql', $gf_query_sql_callback );
1355
				}
1356
1357 70
				if ( isset( $gf_query_timesort_sql_callback ) ) {
1358 70
					remove_action( 'gform_gf_query_sql', $gf_query_timesort_sql_callback );
1359
				}
1360
1361 70
				if ( isset( $has_filtersort ) ) {
1362 13
					$v = &$this;
1363
1364
					/**
1365
					 * A PHP filtersort has been set.
1366
					 * Execute the main filter and sort callback logic.
1367
					 * Then, set the actual total found.
1368
					 * Finally truncate to the correct pagination and offsets.
1369
					 */
1370
1371 13
					$filtered = $entries->all(); // Nyah all the things.
1372
1373 13
					foreach ( $filtered as &$entry ) {
1374
						/**
1375
						 * @filter `gravityview/entries/filter` Filter entries on the PHP side of things.
1376
						 * @param \GV\Entry $entry The entry object. Return null to filter out.
1377
						 * @param \GV\View $view The view.
1378
						 * @param \GV\Request $request The request.
1379
						 */
1380 12
						$entry = apply_filters( 'gravityview/entries/filter', $entry, $this, $request );
1381
					}
1382
1383 13
					$filtered = array_filter( $filtered );
1384
1385 13
					$entries = new \GV\Entry_Collection();
1386
1387 13
					if ( has_filter( 'gravityview/entries/sort' ) ) {
1388
						usort( $filtered, function( $entry1, $entry2 ) use ( $v, $request ) {
1389
							/**
1390
							 * @filter `gravityview/entries/sort` Sort filtered entries on the PHP side of things.
1391
							 * @param int $compare -1 if entry1 < entry2, 0 if they're equal, 1 if entry1 > entry2
1392
							 * @param \GV\Entry $entry1 One entry object.
1393
							 * @param \GV\Entry $entry2 Another entry object.
1394
							 * @param \GV\View $view The view.
1395
							 * @param \GV\Request $request The request.
1396
							 */
1397 2
							return apply_filters( 'gravityview/entries/sort', null, $entry1, $entry2, $v, $request );
1398 13
						} );
1399
					}
1400
1401 12
					array_map( array( $entries, 'add'), array_slice(
1402 12
						$filtered,
1403 12
						( ( $page - 1 ) * $parameters['paging']['page_size'] ) + $this->settings->get( 'offset' ), // Offset and page
1404 12
						$parameters['paging']['page_size'] // Per page
1405
					) );
1406
1407
					$entries->add_count_callback( function() use ( $filtered, $v ) {
1408 7
						return count( $filtered ) - $v->settings->get( 'offset' );
1409 12
					} );
1410
1411
					/**
1412
					 * @action `gravityview/view/remove_filtersorts` The best place to remove filtersorts once they're done.
1413
					 * @see `gravityview/view/add_filtersorts` filter to add filtersorts.
1414
					 *
1415
					 * @param \GV\View $view This view.
1416
					 * @param \GV\Request $request The request.
1417
					 *
1418
					 * @since develop
1419
					 */
1420 12
					do_action( 'gravityview/view/add_filtersorts', $this, $request );
1421
				} else {
1422
					/**
1423
					 * Add total count callback.
1424
					 */
1425
					$entries->add_count_callback( function() use ( $query ) {
1426 25
						return $query->total_found;
1427 69
					} );
1428
				}
1429
			} else {
1430
				$entries = $this->form->entries
0 ignored issues
show
Documentation introduced by
The property entries does not exist on object<GV\Form>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1431
					->filter( \GV\GF_Entry_Filter::from_search_criteria( $parameters['search_criteria'] ) )
1432
					->offset( $this->settings->get( 'offset' ) )
1433
					->limit( $parameters['paging']['page_size'] )
1434
					->page( $page );
1435
1436
				if ( ! empty( $parameters['sorting'] ) && is_array( $parameters['sorting'] && ! isset( $parameters['sorting']['key'] ) ) ) {
1437
					// Pluck off multisort arrays
1438
					$parameters['sorting'] = $parameters['sorting'][0];
1439
				}
1440
1441
				if ( ! empty( $parameters['sorting'] ) && ! empty( $parameters['sorting']['key'] ) ) {
1442
					$field = new \GV\Field();
1443
					$field->ID = $parameters['sorting']['key'];
1444
					$direction = strtolower( $parameters['sorting']['direction'] ) == 'asc' ? \GV\Entry_Sort::ASC : \GV\Entry_Sort::DESC;
1445
					$entries = $entries->sort( new \GV\Entry_Sort( $field, $direction ) );
1446
				}
1447
			}
1448
		}
1449
1450
		/**
1451
		 * @filter `gravityview/view/entries` Modify the entry fetching filters, sorts, offsets, limits.
1452
		 * @param \GV\Entry_Collection $entries The entries for this view.
1453
		 * @param \GV\View $view The view.
1454
		 * @param \GV\Request $request The request.
1455
		 */
1456 69
		return apply_filters( 'gravityview/view/entries', $entries, $this, $request );
1457
	}
1458
1459
	/**
1460
	 * Last chance to configure the output.
1461
	 *
1462
	 * Used for CSV output, for example.
1463
	 *
1464
	 * @return void
1465
	 */
1466 6
	public static function template_redirect() {
1467
		/**
1468
		 * CSV output.
1469
		 */
1470 6
		if ( ! get_query_var( 'csv' ) ) {
1471 1
			return;
1472
		}
1473
1474 6
		if ( ! $view = gravityview()->request->is_view() ) {
1475 1
			return;
1476
		}
1477
1478 6
		if ( is_wp_error( $error = $view->can_render( array( 'csv' ) ) ) ) {
1479 1
			gravityview()->log->error( 'Not rendering CSV: ' . $error->get_error_message() );
1480 1
			return;
1481
		}
1482
1483
		/**
1484
		 * Modify the name of the generated CSV file. Name will be sanitized using sanitize_file_name() before output.
1485
		 * @see sanitize_file_name()
1486
		 * @since 2.1
1487
		 * @param string   $filename File name used when downloading a CSV. Default is "{View title}.csv"
1488
		 * @param \GV\View $view Current View being rendered
1489
		 */
1490 6
		$filename = apply_filters( 'gravityview/output/csv/filename', get_the_title( $view->post ), $view );
1491
1492 6
		if ( ! defined( 'DOING_GRAVITYVIEW_TESTS' ) ) {
1493
			header( sprintf( 'Content-Disposition: attachment;filename="%s.csv"', sanitize_file_name( $filename ) ) );
1494
			header( 'Content-Transfer-Encoding: binary' );
1495
			header( 'Content-Type: text/csv' );
1496
		}
1497
1498 6
		ob_start();
1499 6
		$csv = fopen( 'php://output', 'w' );
1500
1501
		/**
1502
		 * Add da' BOM if GF uses it
1503
		 * @see GFExport::start_export()
1504
		 */
1505 6
		if ( apply_filters( 'gform_include_bom_export_entries', true, $view->form ? $view->form->form : null ) ) {
1506
			fputs( $csv, "\xef\xbb\xbf" );
1507
		}
1508
1509 6
		if ( $view->settings->get( 'csv_nolimit' ) ) {
1510
			$view->settings->update( array( 'page_size' => -1 ) );
1511
		}
1512
1513 6
		$entries = $view->get_entries();
1514
1515 6
		$headers_done = false;
1516 6
		$allowed = $headers = array();
1517
1518 6
		foreach ( $view->fields->by_position( "directory_*" )->by_visible( $view )->all() as $id => $field ) {
1519 6
			$allowed[] = $field;
1520
		}
1521
1522 6
		$renderer = new Field_Renderer();
1523
1524 6
		foreach ( $entries->all() as $entry ) {
1525
1526 6
			$return = array();
1527
1528
			/**
1529
			 * @filter `gravityview/csv/entry/fields` Whitelist more entry fields by ID that are output in CSV requests.
1530
			 * @param[in,out] array $allowed The allowed ones, default by_visible, by_position( "context_*" ), i.e. as set in the View.
1531
			 * @param \GV\View $view The view.
1532
			 * @param \GV\Entry $entry WordPress representation of the item.
1533
			 */
1534 6
			$allowed_field_ids = apply_filters( 'gravityview/csv/entry/fields', wp_list_pluck( $allowed, 'ID' ), $view, $entry );
1535
1536
			$allowed = array_filter( $allowed, function( $field ) use ( $allowed_field_ids ) {
1537 6
				return in_array( $field->ID, $allowed_field_ids, true );
1538 6
			} );
1539
1540 6
			foreach ( array_diff( $allowed_field_ids, wp_list_pluck( $allowed, 'ID' ) ) as $field_id ) {
1541
				$allowed[] = is_numeric( $field_id ) ? \GV\GF_Field::by_id( $view->form, $field_id ) : \GV\Internal_Field::by_id( $field_id );
1542
			}
1543
1544 6
			foreach ( $allowed as $field ) {
1545 6
				$source = is_numeric( $field->ID ) ? $view->form : new \GV\Internal_Source();
1546
1547 6
				$return[] = $renderer->render( $field, $view, $source, $entry, gravityview()->request, '\GV\Field_CSV_Template' );
1548
1549 6
				if ( ! $headers_done ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $headers_done of type false|integer is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

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

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1550 6
					$label = $field->get_label( $view, $source, $entry );
1551 6
					$headers[] = $label ? $label : $field->ID;
1552
				}
1553
			}
1554
1555 6
			if ( ! $headers_done ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $headers_done of type false|integer is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

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

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1556 6
				$headers_done = fputcsv( $csv, array_map( array( '\GV\Utils', 'strip_excel_formulas' ), array_values( $headers ) ) );
1557
			}
1558
1559 6
			fputcsv( $csv, array_map( array( '\GV\Utils', 'strip_excel_formulas' ), $return ) );
1560
		}
1561
1562 6
		fflush( $csv );
1563
1564 6
		echo rtrim( ob_get_clean() );
1565
1566 6
		if ( ! defined( 'DOING_GRAVITYVIEW_TESTS' ) ) {
1567
			exit;
1568
		}
1569 6
	}
1570
1571
	/**
1572
	 * Return the query class for this View.
1573
	 *
1574
	 * @return string The class name.
1575
	 */
1576 70
	public function get_query_class() {
1577
		/**
1578
		 * @filter `gravityview/query/class`
1579
		 * @param[in,out] string The query class. Default: GF_Query.
1580
		 * @param \GV\View $this The View.
1581
		 */
1582 70
		$query_class = apply_filters( 'gravityview/query/class', '\GF_Query', $this );
1583 70
		return $query_class;
1584
	}
1585
1586
	/**
1587
	 * Restrict View access to specific capabilities.
1588
	 *
1589
	 * Hooked into `map_meta_cap` WordPress filter.
1590
	 *
1591
	 * @since develop
1592
	 *
1593
	 * @param $caps    array  The output capabilities.
1594
	 * @param $cap     string The cap that is being checked.
1595
	 * @param $user_id int    The User ID.
1596
	 * @param $args    array  Additional arguments to the capability.
1597
	 *
1598
	 * @return array   The resulting capabilities.
1599
	 */
1600 61
	public static function restrict( $caps, $cap, $user_id, $args ) {
1601
		/**
1602
		 * @filter `gravityview/security/require_unfiltered_html` Bypass restrictions on Views that require `unfiltered_html`.
1603
		 * @param[in,out] boolean
1604
		 *
1605
		 * @since develop
1606
		 * @param string $cap The capability requested.
1607
		 * @param int $user_id The user ID.
1608
		 * @param array $args Any additional args to map_meta_cap
1609
		 */
1610 61
		if ( ! apply_filters( 'gravityview/security/require_unfiltered_html', true, $cap, $user_id ) ) {
1611 1
			return $caps;
1612
		}
1613
1614 61
		switch ( $cap ):
1615 61
			case 'edit_gravityview':
1616 61
			case 'edit_gravityviews':
1617 61
			case 'edit_others_gravityviews':
1618 61
			case 'edit_private_gravityviews':
1619 61
			case 'edit_published_gravityviews':
1620 8
				if ( ! user_can( $user_id, 'unfiltered_html' ) ) {
1621 5
					if ( ! user_can( $user_id, 'gravityview_full_access' ) ) {
1622 5
						return array( 'do_not_allow' );
1623
					}
1624
				}
1625
1626 8
				return $caps;
1627 61
			case 'edit_post':
1628 8
				if ( get_post_type( array_pop( $args ) ) == 'gravityview' ) {
1629 7
					return self::restrict( $caps, 'edit_gravityview', $user_id, $args );
1630
				}
1631
		endswitch;
1632
1633 61
		return $caps;
1634
	}
1635
1636 178
	public function __get( $key ) {
1637 178
		if ( $this->post ) {
1638 178
			$raw_post = $this->post->filter( 'raw' );
1639 178
			return $raw_post->{$key};
1640
		}
1641
		return isset( $this->{$key} ) ? $this->{$key} : null;
1642
	}
1643
}
1644