Completed
Push — develop ( 25e00b...d3334c )
by Gennady
16:24
created

View::offsetExists()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 17 and the first side effect is on line 6.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
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 future
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 110
	 *                    main field_id:
82 110
	 *
83 110
	 *                    array(
84 110
	 *                        $form_id => array(
85 110
	 *                            $field_id => $field,
86
	 *                            $field_id => $field,
87
	 *                        )
88
	 *                    )
89
	 *
90
	 * @api
91
	 * @since future
92
	 */
93
	public $unions = array();
94
95
	/**
96
	 * The constructor.
97
	 */
98
	public function __construct() {
99
		$this->settings = new View_Settings();
100
		$this->fields = new Field_Collection();
101
		$this->widgets = new Widget_Collection();
102
	}
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 );
0 ignored issues
show
introduced by
No space after closing casting parenthesis is prohibited
Loading history...
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 1
				 * @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 1
		register_post_type( 'gravityview', $args );
213 1
	}
214 1
215
	/**
216
	 * Add extra rewrite endpoints.
217
	 *
218
	 * @return void
219
	 */
220
	public static function add_rewrite_endpoint() {
221
		/**
222
		 * CSV.
223
		 */
224
		global $wp_rewrite;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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 10
		add_filter( 'query_vars', function( $query_vars ) { 
230 10
			$query_vars[] = 'csv';
231
			return $query_vars;
232
		} );
233 10
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
	public static function content( $content ) {
247
		$request = gravityview()->request;
248
249 10
		// Plugins may run through the content in the header. WP SEO does this for its OpenGraph functionality.
250 5
		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 5
			//	We don't want this filter to run infinite loop on any post content fields
257 5
			remove_filter( 'the_content', array( __CLASS__, __METHOD__ ) );
258 5
		}
259
260 1
		/**
261 1
		 * This is not a View. Bail.
262 1
		 *
263 1
		 * Shortcodes and oEmbeds and whatnot will be handled
264
		 *  elsewhere.
265
		 */
266
		if ( ! $view = $request->is_view() ) {
267
			return $content;
268
		}
269
270
		/**
271
		 * Check permissions.
272
		 */
273
		while ( $error = $view->can_render( null, $request ) ) {
274
			if ( ! is_wp_error( $error ) )
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
275 1
				break;
276 1
277 1
			switch ( str_replace( 'gravityview/', '', $error->get_error_code() ) ) {
278
				case 'post_password_required':
279 1
					return get_the_password_form( $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...
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 5
					 * ...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 ) ) {
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...
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' );
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...
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'sprintf'
Loading history...
290
					}
291 5
					break;
292
				case 'no_direct_access':
293
				case 'embed_only':
294
				case 'not_public':
295
				default:
296
					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() ) );
297
					return __( 'You are not allowed to view this content.', 'gravityview' );
298
			}
299
300
			return $content;
301
		}
302
303
		$is_admin_and_can_view = $view->settings->get( 'admin_show_all_statuses' ) && \GVCommon::has_cap('gravityview_moderate_entries', $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...
Coding Style introduced by
Expected 1 spaces after opening bracket; 0 found
Loading history...
304
305
		/**
306
		 * Editing a single entry.
307
		 */
308
		if ( $entry = $request->is_edit_entry( $view->form ? $view->form->ID : 0 ) ) {
309
			if ( $entry['status'] != 'active' ) {
0 ignored issues
show
introduced by
Found "!= '". Use Yoda Condition checks, you must
Loading history...
310
				gravityview()->log->notice( 'Entry ID #{entry_id} is not active', array( 'entry_id' => $entry->ID ) );
311
				return __( 'You are not allowed to view this content.', 'gravityview' );
312
			}
313
314
			if ( apply_filters( 'gravityview_custom_entry_slug', false ) && $entry->slug != get_query_var( \GV\Entry::get_endpoint_name() ) ) {
315 5
				gravityview()->log->error( 'Entry ID #{entry_id} was accessed by a bad slug', array( 'entry_id' => $entry->ID ) );
316
				return __( 'You are not allowed to view this content.', 'gravityview' );
317 1
			}
318
319 1
			if ( $view->settings->get( 'show_only_approved' ) && ! $is_admin_and_can_view ) {
320 1
				if ( ! \GravityView_Entry_Approval_Status::is_approved( gform_get_meta( $entry->ID, \GravityView_Entry_Approval::meta_key ) )  ) {
321
					gravityview()->log->error( 'Entry ID #{entry_id} is not approved for viewing', array( 'entry_id' => $entry->ID ) );
322 1
					return __( 'You are not allowed to view this content.', 'gravityview' );
323
				}
324 1
			}
325
326 1
			$renderer = new Edit_Entry_Renderer();
327 1
			return $renderer->render( $entry, $view, $request );
328 1
329
		/**
330
		 * Viewing a single entry.
331 1
		 */
332 1
		} else if ( $entry = $request->is_entry( $view->form ? $view->form->ID : 0 ) ) {
333 1
334
			$entryset = $entry->is_multi() ? $entry->entries : array( $entry );
0 ignored issues
show
Bug introduced by
The property entries does not seem to exist in GV\GF_Entry.

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...
335
336 1
			$custom_slug = apply_filters( 'gravityview_custom_entry_slug', false );
337 1
			$ids = explode( ',', get_query_var( \GV\Entry::get_endpoint_name() ) );
338 1
339 1
			$show_only_approved = $view->settings->get( 'show_only_approved' );
340
341
			foreach ( $entryset as $e ) {
342
343
				if ( 'active' !== $e['status'] ) {
344 1
					gravityview()->log->notice( 'Entry ID #{entry_id} is not active', array( 'entry_id' => $e->ID ) );
345
					return __( 'You are not allowed to view this content.', 'gravityview' );
346 1
				}
347
348
				if ( $custom_slug && ! in_array( $e->slug, $ids ) ) {
349
					gravityview()->log->error( 'Entry ID #{entry_id} was accessed by a bad slug', array( 'entry_id' => $e->ID ) );
350
					return __( 'You are not allowed to view this content.', 'gravityview' );
351 1
				}
352 1
353
				if ( $show_only_approved && ! $is_admin_and_can_view ) {
354
					if ( ! \GravityView_Entry_Approval_Status::is_approved( gform_get_meta( $e->ID, \GravityView_Entry_Approval::meta_key ) )  ) {
355
						gravityview()->log->error( 'Entry ID #{entry_id} is not approved for viewing', array( 'entry_id' => $e->ID ) );
356
						return __( 'You are not allowed to view this content.', 'gravityview' );
357
					}
358 4
				}
359 4
			}
360
361
			$error = \GVCommon::check_entry_display( $entry->as_entry(), $view );
362
363
			if ( is_wp_error( $error ) ) {
364
				gravityview()->log->error( 'Entry ID #{entry_id} is not approved for viewing: {message}', array( 'entry_id' => $entry->ID, 'message' => $error->get_error_message() ) );
365
				return __( 'You are not allowed to view this content.', 'gravityview' );
366
			}
367
368
			$renderer = new Entry_Renderer();
369
			return $renderer->render( $entry, $view, $request );
370
		}
371
372
		/**
373
		 * Plain old View.
374
		 */
375
		$renderer = new View_Renderer();
376
		return $renderer->render( $view, $request );
377 19
	}
378 19
379 1
	/**
380
	 * Checks whether this view can be accessed or not.
381
	 *
382 19
	 * @param string[]    $context The context we're asking for access from.
383 5
	 *                             Can any and as many of one of:
384
	 *                                 edit      An edit context.
385
	 *                                 single    A single context.
386
	 *                                 cpt       The custom post type single page acessed.
387
	 *                                 shortcode Embedded as a shortcode.
388
	 *                                 oembed    Embedded as an oEmbed.
389
	 *                                 rest      A REST call.
390
	 * @param \GV\Request $request The request
391
	 *
392
	 * @return bool|\WP_Error An error if this View shouldn't be rendered here.
393 19
	 */
394
	public function can_render( $context = null, $request = null ) {
395
		if ( ! $request ) {
396
			$request = gravityview()->request;
397 19
		}
398
399 6
		if ( ! is_array( $context ) ) {
400 1
			$context = array();
401 6
		}
402 1
403
		/**
404
		 * @filter `gravityview/view/can_render` Whether the view can be rendered or not.
405
		 * @param bool|\WP_Error $result  The result. Default: null.
406 19
		 * @param \GV\View       $view	The view.
407 1
		 * @param string[]       $context See \GV\View::can_render
408 1
		 * @param \GV\Request    $request The request.
409
		 */
410
		if ( ! is_null( $result = apply_filters( 'gravityview/view/can_render', null, $this, $context, $request ) ) ) {
411
			return $result;
412
		}
413
414
		if ( in_array( 'rest', $context ) ) {
415 19
			// REST
416 3
			if ( gravityview()->plugin->settings->get( 'rest_api' ) === '1' && $this->settings->get( 'rest_disable' ) === '1' ) {
0 ignored issues
show
introduced by
Found "=== '". Use Yoda Condition checks, you must
Loading history...
417 3
				return new \WP_Error( 'gravityview/rest_disabled' );
418
			} elseif ( gravityview()->plugin->settings->get( 'rest_api' ) !== '1' && $this->settings->get( 'rest_enable' ) !== '1' ) {
0 ignored issues
show
introduced by
Found "!== '". Use Yoda Condition checks, you must
Loading history...
419
				return new \WP_Error( 'gravityview/rest_disabled' );
420 19
			}
421
		}
422
423
		if ( in_array( 'csv', $context ) ) {
424
			if ( $this->settings->get( 'csv_enable' ) !== '1' ) {
0 ignored issues
show
introduced by
Found "!== '". Use Yoda Condition checks, you must
Loading history...
425 19
				return new \WP_Error( 'gravityview/csv_disabled', 'The CSV endpoint is not enabled for this View' );
426
			}
427
		}
428
429
		/**
430
		 * This View is password protected. Nothing to do here.
431
		 */
432
		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...
433
			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...
434
			return new \WP_Error( 'gravityview/post_password_required' );
435
		}
436
437
		if ( ! $this->form ) {
438 12
			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...
439
			return new \WP_Error( 'gravityview/no_form_attached' );
440
		}
441
442
		if ( ! in_array( 'shortcode', $context ) ) {
443
			/**
444
			 * Is this View directly accessible via a post URL?
445
			 *
446
			 * @see https://codex.wordpress.org/Function_Reference/register_post_type#public
447 12
			 */
448
449
			/**
450
			 * @filter `gravityview_direct_access` Should Views be directly accessible, or only visible using the shortcode?
451
			 * @deprecated
452
			 * @param[in,out] boolean `true`: allow Views to be accessible directly. `false`: Only allow Views to be embedded. Default: `true`
453
			 * @param int $view_id The ID of the View currently being requested. `0` for general setting
454
			 */
455 12
			$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...
456 1
457
			/**
458
			 * @filter `gravityview/request/output/direct` Should this View be directly accessbile?
459
			 * @since 2.0
460
			 * @param[in,out] boolean Accessible or not. Default: accessbile.
461 19
			 * @param \GV\View $view The View we're trying to directly render here.
462 19
			 * @param \GV\Request $request The current request.
463 3
			 */
464 3
			if ( ! apply_filters( 'gravityview/view/output/direct', $direct_access, $this, $request ) ) {
465
				return new \WP_Error( 'gravityview/no_direct_access' );
466
			}
467 19
468
			/**
469
			 * Is this View an embed-only View? If so, don't allow rendering here,
470
			 *  as this is a direct request.
471
			 */
472
			if ( $this->settings->get( 'embed_only' ) && ! \GVCommon::has_cap( 'read_private_gravityviews' ) ) {
473
				return new \WP_Error( 'gravityview/embed_only' );
474
			}
475
		}
476
477
		/** Private, pending, draft, etc. */
478
		$public_states = get_post_stati( array( 'public' => true ) );
479
		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...
480 110
			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...
481 110
			return new \WP_Error( 'gravityview/not_public' );
482
		}
483 110
484
		return true;
485
	}
486
487
	/**
488 110
	 * Get joins associated with a view
489
	 *
490
	 * @param \WP_Post $post GravityView CPT to get joins for
491
	 *
492
	 * @api
493 110
	 * @since 2.0.11
494
	 *
495 110
	 * @return \GV\Join[] Array of \GV\Join instances
496 110
	 */
497
	public static function get_joins( $post ) {
498
		$joins = array();
499
500
		if ( ! gravityview()->plugin->supports( Plugin::FEATURE_JOINS ) ) {
501
			gravityview()->log->error( 'Cannot get joined forms; joins feature not supported.' );
502
			return $joins;
503
		}
504
505
		if ( ! $post || 'gravityview' !== get_post_type( $post ) ) {
506
			gravityview()->log->error( 'Only "gravityview" post types can be \GV\View instances.' );
507
			return $joins;
508
		}
509
510
		$joins_meta = get_post_meta( $post->ID, '_gravityview_form_joins', true );
511
512
		if ( empty( $joins_meta ) ) {
513
			return $joins;
514
		}
515
516
		foreach ( $joins_meta as $meta ) {
517
			if ( ! is_array( $meta ) || count( $meta ) != 4 ) {
0 ignored issues
show
introduced by
Found "!= 4". Use Yoda Condition checks, you must
Loading history...
518
				continue;
519
			}
520
521
			list( $join, $join_column, $join_on, $join_on_column ) = $meta;
522
523
			$join    = GF_Form::by_id( $join );
524
			$join_on = GF_Form::by_id( $join_on );
525
526
			$join_column    = is_numeric( $join_column ) ? GF_Field::by_id( $join, $join_column ) : Internal_Field::by_id( $join_column );
527
			$join_on_column = is_numeric( $join_on_column ) ? GF_Field::by_id( $join_on, $join_on_column ) : Internal_Field::by_id( $join_on_column );
528
529
			$joins [] = new Join( $join, $join_column, $join_on, $join_on_column );
530
		}
531
532
		return $joins;
533
	}
534
535
	/**
536
	 * Get joined forms associated with a view
537
	 * In no particular order.
538
	 *
539
	 * @since 2.0.11
540
	 *
541
	 * @api
542
	 * @since 2.0
543
	 * @param int $post_id ID of the View
544
	 *
545
	 * @return \GV\GF_Form[] Array of \GV\GF_Form instances
546
	 */
547
	public static function get_joined_forms( $post_id ) {
548
		$forms = array();
549
550
		if ( ! gravityview()->plugin->supports( Plugin::FEATURE_JOINS ) ) {
551
			gravityview()->log->error( 'Cannot get joined forms; joins feature not supported.' );
552
			return $forms;
553
		}
554
555
		if ( ! $post_id || ! gravityview()->plugin->supports( Plugin::FEATURE_JOINS ) ) {
556
			return $forms;
557
		}
558
559
		if ( empty( $post_id ) ) {
560
			gravityview()->log->error( 'Cannot get joined forms; $post_id was empty' );
561
			return $forms;
562
		}
563
564
		$joins_meta = get_post_meta( $post_id, '_gravityview_form_joins', true );
565
566
		if ( empty( $joins_meta ) ) {
567
			return $forms;
568
		}
569
570
		foreach ( $joins_meta  as $meta ) {
571
			if ( ! is_array( $meta ) || count( $meta ) != 4 ) {
0 ignored issues
show
introduced by
Found "!= 4". Use Yoda Condition checks, you must
Loading history...
572
				continue;
573
			}
574
575
			list( $join, $join_column, $join_on, $join_on_column ) = $meta;
576
577
			if ( $form = GF_Form::by_id( $join_on ) ) {
578
				$forms[ $join_on ] = $form;
579
			}
580
581 111
			if ( $form = GF_Form::by_id( $join ) ) {
582
				$forms[ $join ] = $form;
583 111
			}
584 2
		}
585 2
586
		return $forms;
587
	}
588 111
589
	/**
590
	 * Get unions associated with a view
591
	 *
592
	 * @param \WP_Post $post GravityView CPT to get unions for
593
	 *
594 55
	 * @api
595
	 * @since future
596 55
	 *
597
	 * @return \GV\Field[][] Array of unions (see self::$unions)
598
	 */
599 111
	public static function get_unions( $post ) {
600 111
		$unions = array();
601
602
		if ( ! gravityview()->plugin->supports( Plugin::FEATURE_UNIONS ) ) {
603 111
			gravityview()->log->error( 'Cannot get unions; unions feature not supported.' );
604 111
			return $unions;
605
		}
606
607
		if ( ! $post || 'gravityview' !== get_post_type( $post ) ) {
608
			gravityview()->log->error( 'Only "gravityview" post types can be \GV\View instances.' );
609
			return $unions;
610
		}
611 111
612
		$fields = get_post_meta( $post->ID, '_gravityview_directory_fields', true );
613
614
		if ( empty( $fields ) ) {
615
			return $unions;
616
		}
617
618
		foreach ( $fields as $location => $_fields ) {
619
			if ( strpos( $location, 'directory_' ) !== 0 ) {
0 ignored issues
show
introduced by
Found "!== 0". Use Yoda Condition checks, you must
Loading history...
620
				continue;
621
			}
622 111
623
			foreach ( $_fields as $field ) {
624
				if ( ! empty( $field['unions'] ) ) {
625
					foreach ( $field['unions'] as $form_id => $field_id ) {
626
						if ( ! isset( $unions[ $form_id ] ) ) {
627
							$unions[ $form_id ] = array();
628
						}
629
630
						$unions[ $form_id ][ $field['id'] ] =
631 111
							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 );
632
					}
633
				}
634
			}
635
636
			break;
637
		}
638
639
		// @todo We'll probably need to backfill null unions
640 111
641
		return $unions;
642
	}
643
644
	/**
645
	 * Construct a \GV\View instance from a \WP_Post.
646
	 *
647
	 * @param \WP_Post $post The \WP_Post instance to wrap.
648
	 *
649 111
	 * @api
650
	 * @since 2.0
651
	 * @return \GV\View|null An instance around this \WP_Post if valid, null otherwise.
652
	 */
653
	public static function from_post( $post ) {
654
655
		if ( ! $post || 'gravityview' !== get_post_type( $post ) ) {
656
			gravityview()->log->error( 'Only gravityview post types can be \GV\View instances.' );
657
			return null;
658 111
		}
659
660
		if ( $view = Utils::get( self::$cache, "View::from_post:{$post->ID}" ) ) {
661 111
			/**
662
			 * @filter `gravityview/view/get` Override View.
663
			 * @param \GV\View $view The View instance pointer.
664 111
			 * @since 2.1
665
			 */
666
			do_action_ref_array( 'gravityview/view/get', array( &$view ) );
667 111
668 111
			return $view;
669
		}
670
671 111
		$view = new self();
672
		$view->post = $post;
673
674
		/** Get connected form. */
675
		$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...
676
		if ( ! $view->form ) {
677
			gravityview()->log->error( 'View #{view_id} tried attaching non-existent Form #{form_id} to it.', array(
678 111
				'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...
679
				'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...
680 111
			) );
681
		}
682
683
		$view->joins = $view->get_joins( $post );
684
685
		$view->unions = $view->get_unions( $post );
686
687
		/**
688
		 * @filter `gravityview/configuration/fields` Filter the View fields' configuration array.
689
		 * @since 1.6.5
690 125
		 *
691 125
		 * @deprecated Use `gravityview/view/configuration/fields` or `gravityview/view/fields` filters.
692 118
		 *
693 118
		 * @param $fields array Multi-array of fields with first level being the field zones.
694
		 * @param $view_id int The View the fields are being pulled for.
695 71
		 */
696 71
		$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...
introduced by
No space after closing casting parenthesis is prohibited
Loading history...
697
698
		/**
699
		 * @filter `gravityview/view/configuration/fields` Filter the View fields' configuration array.
700
		 * @since 2.0
701
		 *
702
		 * @param array $fields Multi-array of fields with first level being the field zones.
703
		 * @param \GV\View $view The View the fields are being pulled for.
704
		 */
705
		$configuration = apply_filters( 'gravityview/view/configuration/fields', $configuration, $view );
706
707 68
		/**
708 68
		 * @filter `gravityview/view/fields` Filter the Field Collection for this View.
709 3
		 * @since 2.0
710
		 *
711 68
		 * @param \GV\Field_Collection $fields A collection of fields.
712
		 * @param \GV\View $view The View the fields are being pulled for.
713
		 */
714
		$view->fields = apply_filters( 'gravityview/view/fields', Field_Collection::from_configuration( $configuration ), $view );
715
716
		/**
717
		 * @filter `gravityview/view/configuration/widgets` Filter the View widgets' configuration array.
718
		 * @since 2.0
719
		 *
720
		 * @param array $fields Multi-array of widgets with first level being the field zones.
721
		 * @param \GV\View $view The View the widgets are being pulled for.
722
		 */
723 14
		$configuration = apply_filters( 'gravityview/view/configuration/widgets', (array)$view->_gravityview_directory_widgets, $view );
0 ignored issues
show
introduced by
No space after closing casting parenthesis is prohibited
Loading history...
724 14
725
		/**
726
		 * @filter `gravityview/view/widgets` Filter the Widget Collection for this View.
727
		 * @since 2.0
728
		 *
729
		 * @param \GV\Widget_Collection $widgets A collection of widgets.
730
		 * @param \GV\View $view The View the widgets are being pulled for.
731
		 */
732
		$view->widgets = apply_filters( 'gravityview/view/widgets', Widget_Collection::from_configuration( $configuration ), $view );
733
734
		/** View configuration. */
735 13
		$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...
736 13
737 13
		/** Add the template name into the settings. */
738
		$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...
739
740
		/** View basics. */
741
		$view->settings->update( array(
742
			'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...
743
		) );
744
745
		self::$cache[ "View::from_post:{$post->ID}" ] = &$view;
746
747
		/**
748
		 * @filter `gravityview/view/get` Override View.
749
		 * @param \GV\View $view The View instance pointer.
750
		 * @since 2.1
751 13
		 */
752
		do_action_ref_array( 'gravityview/view/get', array( &$view ) );
753 13
754
		return $view;
755 13
	}
756
757
	/**
758
	 * Flush the view cache.
759 13
	 *
760 13
	 * @param int $view_id The View to reset cache for. Optional. Default: resets everything.
761 13
	 *
762 1
	 * @internal
763 13
	 */
764 13
	public static function _flush_cache( $view_id = null ) {
765 1
		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...
766 1
			unset( self::$cache[ "View::from_post:$view_id" ] );
767 1
			return;
768
		}
769 1
		self::$cache = array();
770 1
	}
771
772
	/**
773
	 * Construct a \GV\View instance from a post ID.
774
	 *
775
	 * @param int|string $post_id The post ID.
776
	 *
777
	 * @api
778
	 * @since 2.0
779
	 * @return \GV\View|null An instance around this \WP_Post or null if not found.
780
	 */
781
	public static function by_id( $post_id ) {
782
		if ( ! $post_id || ! $post = get_post( $post_id ) ) {
783
			return null;
784
		}
785 1
		return self::from_post( $post );
786 1
	}
787 1
788
	/**
789
	 * Determines if a view exists to begin with.
790
	 *
791
	 * @param int|\WP_Post|null $view The WordPress post ID, a \WP_Post object or null for global $post;
792
	 *
793
	 * @api
794
	 * @since 2.0
795
	 * @return bool Whether the post exists or not.
796
	 */
797 1
	public static function exists( $view ) {
798 1
		return get_post_type( $view ) == 'gravityview';
799 1
	}
800
801
	/**
802
	 * ArrayAccess compatibility layer with GravityView_View_Data::$views
803
	 *
804
	 * @internal
805
	 * @deprecated
806
	 * @since 2.0
807
	 * @return bool Whether the offset exists or not, limited to GravityView_View_Data::$views element keys.
808
	 */
809
	public function offsetExists( $offset ) {
0 ignored issues
show
Coding Style introduced by
The function name offsetExists is in camel caps, but expected offset_exists instead as per the coding standard.
Loading history...
810
		$data_keys = array( 'id', 'view_id', 'form_id', 'template_id', 'atts', 'fields', 'widgets', 'form' );
811
		return in_array( $offset, $data_keys );
812
	}
813 17
814
	/**
815 17
	 * ArrayAccess compatibility layer with GravityView_View_Data::$views
816 17
	 *
817 17
	 * Maps the old keys to the new data;
818 17
	 *
819 17
	 * @internal
820 17
	 * @deprecated
821 17
	 * @since 2.0
822 17
	 *
823
	 * @return mixed The value of the requested view data key limited to GravityView_View_Data::$views element keys.
824
	 */
825
	public function offsetGet( $offset ) {
0 ignored issues
show
Coding Style introduced by
The function name offsetGet is in camel caps, but expected offset_get instead as per the coding standard.
Loading history...
826
827
		gravityview()->log->notice( 'This is a \GV\View object should not be accessed as an array.' );
828
829
		if ( ! isset( $this[ $offset ] ) ) {
830
			return null;
831
		}
832
833 32
		switch ( $offset ) {
834 32
			case 'id':
835 32
			case 'view_id':
836
				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...
837
			case 'form':
838
				return $this->form;
839 32
			case 'form_id':
840 32
				return $this->form ? $this->form->ID : null;
841 32
			case 'atts':
842
				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...
843 32
			case 'template_id':
844 4
				return $this->settings->get( 'template' );
845 4
			case 'widgets':
846 4
				return $this->widgets->as_configuration();
847
		}
848 4
	}
849
850
	/**
851 32
	 * ArrayAccess compatibility layer with GravityView_View_Data::$views
852 32
	 *
853
	 * @internal
854
	 * @deprecated
855
	 * @since 2.0
856
	 *
857 32
	 * @return void
858 32
	 */
859 7
	public function offsetSet( $offset, $value ) {
0 ignored issues
show
Coding Style introduced by
The function name offsetSet is in camel caps, but expected offset_set instead as per the coding standard.
Loading history...
860 7
		gravityview()->log->error( 'The old view data is no longer mutable. This is a \GV\View object should not be accessed as an array.' );
861 7
	}
862 7
863
	/**
864
	 * ArrayAccess compatibility layer with GravityView_View_Data::$views
865 32
	 *
866
	 * @internal
867 32
	 * @deprecated
868 7
	 * @since 2.0
869
	 * @return void
870
	 */
871 32
	public function offsetUnset( $offset ) {
0 ignored issues
show
Coding Style introduced by
The function name offsetUnset is in camel caps, but expected offset_unset instead as per the coding standard.
Loading history...
872 32
		gravityview()->log->error( 'The old view data is no longer mutable. This is a \GV\View object should not be accessed as an array.' );
873 32
	}
874
875 32
	/**
876 32
	 * Be compatible with the old data object.
877
	 *
878
	 * Some external code expects an array (doing things like foreach on this, or array_keys)
879
	 *  so let's return an array in the old format for such cases. Do not use unless using
880
	 *  for back-compatibility.
881 32
	 *
882
	 * @internal
883
	 * @deprecated
884
	 * @since 2.0
885
	 * @return array
886
	 */
887
	public function as_data() {
888
		return array(
889
			'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...
890
			'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...
891
			'form_id' => $this->form ? $this->form->ID : null,
892
			'form' => $this->form ? gravityview_get_form( $this->form->ID ) : null,
893
			'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...
894
			'fields' => $this->fields->by_visible()->as_configuration(),
895
			'template_id' => $this->settings->get( 'template' ),
896
			'widgets' => $this->widgets->as_configuration(),
897
		);
898
	}
899
900
	/**
901
	 * Retrieve the entries for the current view and request.
902
	 *
903
	 * @param \GV\Request The request. Unused for now.
904
	 *
905
	 * @return \GV\Entry_Collection The entries.
906
	 */
907
	public function get_entries( $request = null ) {
908
		$entries = new \GV\Entry_Collection();
909
		if ( $this->form ) {
910
			/**
911
			 * @todo: Stop using _frontend and use something like $request->get_search_criteria() instead
912
			 */
913
			$parameters = \GravityView_frontend::get_view_entries_parameters( $this->settings->as_atts(), $this->form->ID );
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...
914
			$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...
915
			$parameters = \GVCommon::calculate_get_entries_criteria( $parameters, $this->form->ID );
916
917
			if ( $request instanceof REST\Request ) {
918
				$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...
919
				$paging_parameters = wp_parse_args( $request->get_paging(), array(
920
						'paging' => array( 'page_size' => $atts['page_size'] ),
921
					) );
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 16 spaces, but found 20.
Loading history...
922
				$parameters['paging'] = $paging_parameters['paging'];
923
			}
924
925 32
			$page = Utils::get( $parameters['paging'], 'current_page' ) ?
926
				: ( ( ( $parameters['paging']['offset'] - $this->settings->get( 'offset' ) ) / $parameters['paging']['page_size'] ) + 1 );
927 32
928
			/**
929
			 * Cleanup duplicate field_filter parameters to simplify the query.
930
			 */
931
			$unique_field_filters = array();
932 32
			foreach ( $parameters['search_criteria']['field_filters'] as $key => $filter ) {
933
				if ( 'mode' === $key ) {
934
					$unique_field_filters['mode'] = $filter;
935
				} else if ( ! in_array( $filter, $unique_field_filters ) ) {
936
					$unique_field_filters[] = $filter;
937
				}
938
			}
939 32
			$parameters['search_criteria']['field_filters'] = $unique_field_filters;
940
941
			if ( ! empty( $parameters['search_criteria']['field_filters'] ) ) {
942
				gravityview()->log->notice( 'search_criteria/field_filters is not empty, third-party code may be using legacy search_criteria filters.' );
943
			}
944
945 32
			if ( gravityview()->plugin->supports( Plugin::FEATURE_GFQUERY ) ) {
946 19
				$query_class = $this->get_query_class();
947 32
				$query = new $query_class( $this->form->ID, $parameters['search_criteria'], $parameters['sorting'] );
948
949
				$query->limit( $parameters['paging']['page_size'] )
950
					->offset( ( ( $page - 1 ) * $parameters['paging']['page_size'] ) + $this->settings->get( 'offset' ) );
951
952
				/**
953
				 * Any joins?
954
				 */
955
				if ( gravityview()->plugin->supports( Plugin::FEATURE_JOINS ) && count( $this->joins ) ) {
956
957
					$is_admin_and_can_view = $this->settings->get( 'admin_show_all_statuses' ) && \GVCommon::has_cap( 'gravityview_moderate_entries', $this->ID );
958
959
					foreach ( $this->joins as $join ) {
960
						$query = $join->as_query_join( $query );
961
962
						if ( $this->settings->get( 'multiple_forms_disable_null_joins' ) ) {
963
964
							// Disable NULL outputs
965
							$condition = new \GF_Query_Condition(
966
								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...
967
								\GF_Query_Condition::NEQ,
968
								new \GF_Query_Literal( '' )
969
							);
970 32
971
							$query_parameters = $query->_introspect();
972
973
							$query->where( \GF_Query_Condition::_and( $query_parameters['where'], $condition ) );
974
						}
975
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
976
977
						if ( $this->settings->get( 'show_only_approved' ) && ! $is_admin_and_can_view ) {
978
979
							// Show only approved joined entries
980 1
							$condition = new \GF_Query_Condition(
981
								new \GF_Query_Column( \GravityView_Entry_Approval::meta_key, $join->join_on->ID ),
982
								\GF_Query_Condition::EQ,
983
								new \GF_Query_Literal( \GravityView_Entry_Approval_Status::APPROVED )
984 1
							);
985 1
986
							$query_parameters = $query->_introspect();
987
988 1
							$query->where( \GF_Query_Condition::_and( $query_parameters['where'], $condition ) );
989 1
						}
990
					}
991
				
992 1
				/**
993 1
				 * Unions?
994 1
				 */
995
				} else if ( gravityview()->plugin->supports( Plugin::FEATURE_UNIONS ) && count( $this->unions ) ) {
996
					$query_parameters = $query->_introspect();
997
998
					$unions_sql = array();
999
1000
					$where_union_substitute = function( $condition, $fields, $recurse ) {
1001
						if ( $condition->expressions ) {
1002
							$conditions = array();
1003
1004 1
							foreach ( $condition->expressions as $_condition ) {
1005
								$conditions[] = $recurse( $_condition, $fields, $recurse );
1006 1
							}
1007
1008
							return call_user_func_array(
1009
								array( '\GF_Query_Condition', $condition->operator == 'AND' ? '_and' : '_or' ),
1010
								$conditions
1011
							);
1012 1
						}
1013 1
1014
						if ( ! $condition->left->is_entry_column() && ! $condition->left->is_meta_column() ) {
1015
							return new \GF_Query_Condition(
1016
								new \GF_Query_Column( $fields[ $condition->left->field_id ]->ID ),
1017
								$condition->operator,
1018
								$condition->right
1019 1
							);
1020
						}
1021
1022
						return $condition;
1023 1
					};
1024
1025 1
					foreach ( $this->unions as $form_id => $fields ) {
1026 1
						// Build a new query for every unioned form
1027
						$query_class = $this->get_query_class();
1028 1
						$q = new $query_class( $form_id );
1029 1
1030
						// Copy the WHERE clauses but substitute the field_ids to the respective ones
1031
						$q->where( $where_union_substitute( $query_parameters['where'], $fields, $where_union_substitute ) );
1032 1
1033
						// Copy the ORDER clause and substitute the field_ids to the respective ones
1034 1
						$orders = array();
1035
						foreach ( $query_parameters['order'] as $order ) {
1036 1
							list( $column, $order ) = $order;
1037
1038
							if ( ! $column->is_entry_column() && ! $column->is_meta_column() ) {
1039
								$column = new \GF_Query_Column( $fields[ $column->field_id ]->ID );
1040
							}
1041
1042
							$q->order( $column, $order );
1043
						}
1044 1
1045
						add_filter( 'gf_query_sql', $gf_query_sql_callback = function( $sql ) use ( &$unions_sql ) {
1046 1
							// Remove SQL_CALC_FOUND_ROWS as it's not needed in UNION clauses
1047 1
							$select = 'UNION ALL ' . str_replace( 'SQL_CALC_FOUND_ROWS ', '', $sql['select'] );
1048
1049 1
							// Record the SQL
1050 1
							$unions_sql[] = array(
1051
								// Remove columns, we'll rebuild them
1052
								'select'  => preg_replace( '#DISTINCT (.*)#', 'DISTINCT ', $select ),
1053
								'from'    => $sql['from'],
1054
								'join'    => $sql['join'],
1055 1
								'where'   => $sql['where'],
1056
								// Remove order and limit
1057 1
							);
1058 1
1059 1
							// Return empty query, no need to call the database
1060
							return array();
1061
						} );
1062
1063 1
						do_action_ref_array( 'gravityview/view/query', array( &$q, $this, $request ) );
1064 1
1065
						$q->get(); // Launch
1066
1067 1
						remove_filter( 'gf_query_sql', $gf_query_sql_callback );
1068
					}
1069
1070 1
					add_filter( 'gf_query_sql', $gf_query_sql_callback = function( $sql ) use ( $unions_sql ) {
1071
						// Remove SQL_CALC_FOUND_ROWS as it's not needed in UNION clauses
1072 1
						$sql['select'] = str_replace( 'SQL_CALC_FOUND_ROWS ', '', $sql['select'] );
1073
1074 1
						// Remove columns, we'll rebuild them
1075
						preg_match( '#DISTINCT (`[motc]\d+`.`.*?`)#', $sql['select'], $select_match );
1076
						$sql['select'] = preg_replace( '#DISTINCT (.*)#', 'DISTINCT ', $sql['select'] );
1077 1
1078
						$unions = array();
1079
1080
						// Transform selected columns to shared alias names
1081
						$column_to_alias = function( $column ) {
1082
							$column = str_replace( '`', '', $column );
1083
							return '`' . str_replace( '.', '_', $column ) . '`';
1084 32
						};
1085
1086
						// Add all the order columns into the selects, so we can order by the whole union group
1087
						preg_match_all( '#(`[motc]\d+`.`.*?`)#', $sql['order'], $order_matches );
1088
						
1089
						$columns = array(
1090 32
							sprintf( '%s AS %s', $select_match[1], $column_to_alias( $select_match[1] ) )
1091 32
						);
1092
1093
						foreach ( array_slice( $order_matches, 1 ) as $match ) {
1094 110
							$columns[] = sprintf( '%s AS %s', $match[0], $column_to_alias( $match[0] ) );
1095 110
1096 110
							// Rewrite the order columns to the shared aliases
1097 110
							$sql['order'] = str_replace( $match[0], $column_to_alias( $match[0] ), $sql['order'] );
1098
						}
1099
1100
						$columns = array_unique( $columns );
1101
1102
						// Add the columns to every UNION
1103
						foreach ( $unions_sql as $union_sql ) {
1104
							$union_sql['select'] .= implode( ', ', $columns );
1105
							$unions []= implode( ' ', $union_sql );
0 ignored issues
show
introduced by
Expected 1 space before "="; 0 found
Loading history...
1106
						}
1107
1108
						// Add the columns to the main SELECT, but only grab the entry id column
1109
						$sql['select'] = 'SELECT SQL_CALC_FOUND_ROWS t1_id FROM (' . $sql['select'] . implode( ', ', $columns );
1110
						$sql['order'] = implode( ' ', $unions ) . ') AS u ' . $sql['order'];
1111
1112
						return $sql;
1113
					} );
1114
				}
1115
1116
				/**
1117
				 * @action `gravityview/view/query` Override the \GF_Query before the get() call.
1118
				 * @param \GF_Query $query The current query object reference
1119
				 * @param \GV\View $this The current view object
1120
				 * @param \GV\Request $request The request object
1121
				 */
1122
				do_action_ref_array( 'gravityview/view/query', array( &$query, $this, $request ) );
1123
1124
				gravityview()->log->debug( 'GF_Query parameters: ', array( 'data' => Utils::gf_query_debug( $query ) ) );
1125
1126
				/**
1127
				 * Map from Gravity Forms entries arrays to an Entry_Collection.
1128
				 */
1129
				if ( count( $this->joins ) ) {
1130
					foreach ( $query->get() as $entry ) {
1131
						$entries->add(
1132
							Multi_Entry::from_entries( array_map( '\GV\GF_Entry::from_entry', $entry ) )
1133
						);
1134
					}
1135
				} else {
1136
					array_map( array( $entries, 'add' ), array_map( '\GV\GF_Entry::from_entry', $query->get() ) );
1137
				}
1138
1139
				if ( isset( $gf_query_sql_callback ) ) {
1140
					remove_action( 'gf_query_sql', $gf_query_sql_callback );
1141
				}
1142
1143
				/**
1144
				 * Add total count callback.
1145
				 */
1146
				$entries->add_count_callback( function() use ( $query ) {
1147
					return $query->total_found;
1148
				} );
1149
			} else {
1150
				$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...
1151
					->filter( \GV\GF_Entry_Filter::from_search_criteria( $parameters['search_criteria'] ) )
1152
					->offset( $this->settings->get( 'offset' ) )
1153
					->limit( $parameters['paging']['page_size'] )
1154
					->page( $page );
1155
1156
				if ( ! empty( $parameters['sorting'] ) && ! empty( $parameters['sorting']['key'] ) ) {
1157
					$field = new \GV\Field();
1158
					$field->ID = $parameters['sorting']['key'];
1159
					$direction = strtolower( $parameters['sorting']['direction'] ) == 'asc' ? \GV\Entry_Sort::ASC : \GV\Entry_Sort::DESC;
1160
					$entries = $entries->sort( new \GV\Entry_Sort( $field, $direction ) );
1161
				}
1162
			}
1163
		}
1164
1165
		/**
1166
		 * @filter `gravityview/view/entries` Modify the entry fetching filters, sorts, offsets, limits.
1167
		 * @param \GV\Entry_Collection $entries The entries for this view.
1168
		 * @param \GV\View $view The view.
1169
		 * @param \GV\Request $request The request.
1170
		 */
1171
		return apply_filters( 'gravityview/view/entries', $entries, $this, $request );
1172
	}
1173
1174
	/**
1175
	 * Last chance to configure the output.
1176
	 *
1177
	 * Used for CSV output, for example.
1178
	 *
1179
	 * @return void
1180
	 */
1181
	public static function template_redirect() {
1182
		/**
1183
		 * CSV output.
1184
		 */
1185
		if ( ! get_query_var( 'csv' ) ) {
1186
			return;
1187
		}
1188
1189
		if ( ! $view = gravityview()->request->is_view() ) {
1190
			return;
1191
		}
1192
1193
		if ( is_wp_error( $error = $view->can_render( array( 'csv' ) ) ) ) {
1194
			gravityview()->log->error( 'Not rendering CSV: ' . $error->get_error_message() );
1195
			return;
1196
		}
1197
1198
		/**
1199
		 * Modify the name of the generated CSV file. Name will be sanitized using sanitize_file_name() before output.
1200
		 * @see sanitize_file_name()
1201
		 * @since 2.1
1202
		 * @param string   $filename File name used when downloading a CSV. Default is "{View title}.csv"
1203
		 * @param \GV\View $view Current View being rendered
1204
		 */
1205
		$filename = apply_filters( 'gravityview/output/csv/filename', get_the_title( $view->post ), $view );
1206
1207
		if ( ! defined( 'DOING_GRAVITYVIEW_TESTS' ) ) {
1208
			header( sprintf( 'Content-Disposition: attachment;filename="%s.csv"', sanitize_file_name( $filename ) ) );
1209
			header( 'Content-Transfer-Encoding: binary' );
1210
			header( 'Content-Type: text/csv' );
1211
		}
1212
1213
		ob_start();
1214
		$csv = fopen( 'php://output', 'w' );
1215
1216
		/**
1217
		 * Add da' BOM if GF uses it
1218
		 * @see GFExport::start_export()
1219
		 */
1220
		if ( apply_filters( 'gform_include_bom_export_entries', true, $view->form ? $view->form->form : null ) ) {
0 ignored issues
show
Documentation introduced by
The property $form is declared private in GV\Form. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write 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.");
        }
    }

}

Since the property has write access only, you can use the @property-write 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...
1221
			fputs( $csv, "\xef\xbb\xbf" );
0 ignored issues
show
introduced by
Filesystem writes are forbidden, you should not be using fputs()
Loading history...
1222
		}
1223
1224
		$entries = $view->get_entries();
1225
1226
		$headers_done = false;
1227
		$allowed = $headers = array();
1228
1229
		foreach ( $view->fields->by_position( "directory_*" )->by_visible()->all() as $field ) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal directory_* does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
1230
			$allowed[ $field->ID ] = $field;
1231
		}
1232
1233
		$renderer = new Field_Renderer();
1234
1235
		foreach ( $entries->all() as $entry ) {
1236
1237
			$return = array();
1238
1239
			/**
1240
			 * @filter `gravityview/csv/entry/fields` Whitelist more entry fields that are output in CSV requests.
1241
			 * @param[in,out] array $allowed The allowed ones, default by_visible, by_position( "context_*" ), i.e. as set in the View.
1242
			 * @param \GV\View $view The view.
1243
			 * @param \GV\Entry $entry WordPress representation of the item.
1244
			 */
1245
			$allowed_field_ids = apply_filters( 'gravityview/csv/entry/fields', array_keys( $allowed ), $view, $entry );
1246
1247
			foreach ( $allowed_field_ids as $field_id ) {
1248
				$source = is_numeric( $field_id ) ? $view->form : new \GV\Internal_Source();
1249
1250
				if ( isset( $allowed[ $field_id ] ) ) {
1251
					$field = $allowed[ $field_id ];
1252
				} else {
1253
					$field = is_numeric( $field_id ) ? \GV\GF_Field::by_id( $view->form, $field_id ) : \GV\Internal_Field::by_id( $field_id );
1254
				}
1255
1256
				$return[ $field->ID ] = $renderer->render( $field, $view, $source, $entry, gravityview()->request, '\GV\Field_CSV_Template' );
1257
1258
				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...
1259
					$label = $field->get_label( $view, $source, $entry );
1260
					$headers[ $field->ID ] = $label ? $label : $field->ID;
1261
				}
1262
			}
1263
1264
			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...
1265
				$headers_done = fputcsv( $csv, array_map( array( '\GV\Utils', 'strip_excel_formulas' ), array_values( $headers ) ) );
0 ignored issues
show
introduced by
Filesystem writes are forbidden, you should not be using fputcsv()
Loading history...
1266
			}
1267
1268
			fputcsv( $csv, array_map( array( '\GV\Utils', 'strip_excel_formulas' ), $return ) );
0 ignored issues
show
introduced by
Filesystem writes are forbidden, you should not be using fputcsv()
Loading history...
1269
		}
1270
1271
		fflush( $csv );
1272
1273
		echo rtrim( ob_get_clean() );
0 ignored issues
show
introduced by
Expected a sanitizing function (see Codex for 'Data Validation'), but instead saw 'rtrim'
Loading history...
1274
1275
		if ( ! defined( 'DOING_GRAVITYVIEW_TESTS' ) ) {
1276
			exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method template_redirect() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
1277
		}
1278
	}
1279
1280
	/**
1281
	 * Return the query class for this View.
1282
	 *
1283
	 * @return string The class name.
1284
	 */
1285
	public function get_query_class() {
1286
		/**
1287
		 * @filter `gravityview/query/class`
1288
		 * @param[in,out] string The query class. Default: GF_Query.
1289
		 * @param \GV\View $this The View.
1290
		 */
1291
		$query_class = apply_filters( 'gravityview/query/class', '\GF_Query', $this );
1292
		return $query_class;
1293
	}
1294
1295
	public function __get( $key ) {
1296
		if ( $this->post ) {
1297
			$raw_post = $this->post->filter( 'raw' );
1298
			return $raw_post->{$key};
1299
		}
1300
		return isset( $this->{$key} ) ? $this->{$key} : null;
1301
	}
1302
}
1303