Completed
Push — develop ( e63648...3edd81 )
by Zack
19:54 queued 12:35
created

View::can_render()   D

Complexity

Conditions 18
Paths 144

Size

Total Lines 81

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 20.592

Importance

Changes 0
Metric Value
cc 18
nc 144
nop 2
dl 0
loc 81
ccs 24
cts 30
cp 0.8
crap 20.592
rs 4.5
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
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
	 * The constructor.
80
	 */
81 77
	public function __construct() {
82 77
		$this->settings = new View_Settings();
83 77
		$this->fields = new Field_Collection();
84 77
		$this->widgets = new Widget_Collection();
85 77
	}
86
87
	/**
88
	 * Register the gravityview WordPress Custom Post Type.
89
	 *
90
	 * @internal
91
	 * @return void
92
	 */
93
	public static function register_post_type() {
94
95
		/** Register only once */
96
		if ( post_type_exists( 'gravityview' ) ) {
97
			return;
98
		}
99
100
		/**
101
		 * @filter `gravityview_is_hierarchical` Make GravityView Views hierarchical by returning TRUE
102
		 * This will allow for Views to be nested with Parents and also allows for menu order to be set in the Page Attributes metabox
103
		 * @since 1.13
104
		 * @param boolean $is_hierarchical Default: false
105
		 */
106
		$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...
107
108
		$supports = array( 'title', 'revisions' );
109
110
		if ( $is_hierarchical ) {
111
			$supports[] = 'page-attributes';
112
		}
113
114
		/**
115
		 * @filter  `gravityview_post_type_supports` Modify post type support values for `gravityview` post type
116
		 * @see add_post_type_support()
117
		 * @since 1.15.2
118
		 * @param array $supports Array of features associated with a functional area of the edit screen. Default: 'title', 'revisions'. If $is_hierarchical, also 'page-attributes'
119
		 * @param[in] boolean $is_hierarchical Do Views support parent/child relationships? See `gravityview_is_hierarchical` filter.
120
		 */
121
		$supports = apply_filters( 'gravityview_post_type_support', $supports, $is_hierarchical );
122
123
		/** Register Custom Post Type - gravityview */
124
		$labels = array(
125
			'name'                => _x( 'Views', 'Post Type General Name', 'gravityview' ),
126
			'singular_name'       => _x( 'View', 'Post Type Singular Name', 'gravityview' ),
127
			'menu_name'           => _x( 'Views', 'Menu name', 'gravityview' ),
128
			'parent_item_colon'   => __( 'Parent View:', 'gravityview' ),
129
			'all_items'           => __( 'All Views', 'gravityview' ),
130
			'view_item'           => _x( 'View', 'View Item', 'gravityview' ),
131
			'add_new_item'        => __( 'Add New View', 'gravityview' ),
132
			'add_new'             => __( 'New View', 'gravityview' ),
133
			'edit_item'           => __( 'Edit View', 'gravityview' ),
134
			'update_item'         => __( 'Update View', 'gravityview' ),
135
			'search_items'        => __( 'Search Views', 'gravityview' ),
136
			'not_found'           => \GravityView_Admin::no_views_text(),
137
			'not_found_in_trash'  => __( 'No Views found in Trash', 'gravityview' ),
138
			'filter_items_list'     => __( 'Filter Views list', 'gravityview' ),
139
			'items_list_navigation' => __( 'Views list navigation', 'gravityview' ),
140
			'items_list'            => __( 'Views list', 'gravityview' ),
141
			'view_items'            => __( 'See Views', 'gravityview' ),
142
			'attributes'            => __( 'View Attributes', 'gravityview' ),
143
		);
144
		$args = array(
145
			'label'               => __( 'view', 'gravityview' ),
146
			'description'         => __( 'Create views based on a Gravity Forms form', 'gravityview' ),
147
			'labels'              => $labels,
148
			'supports'            => $supports,
149
			'hierarchical'        => $is_hierarchical,
150
			/**
151
			 * @filter `gravityview_direct_access` Should Views be directly accessible, or only visible using the shortcode?
152
			 * @see https://codex.wordpress.org/Function_Reference/register_post_type#public
153
			 * @since 1.15.2
154
			 * @param[in,out] boolean `true`: allow Views to be accessible directly. `false`: Only allow Views to be embedded via shortcode. Default: `true`
155
			 * @param int $view_id The ID of the View currently being requested. `0` for general setting
156
			 */
157
			'public'              => apply_filters( 'gravityview_direct_access', gravityview()->plugin->is_compatible(), 0 ),
158
			'show_ui'             => gravityview()->plugin->is_compatible(),
159
			'show_in_menu'        => gravityview()->plugin->is_compatible(),
160
			'show_in_nav_menus'   => true,
161
			'show_in_admin_bar'   => true,
162
			'menu_position'       => 17,
163
			'menu_icon'           => '',
164
			'can_export'          => true,
165
			/**
166
			 * @filter `gravityview_has_archive` Enable Custom Post Type archive?
167
			 * @since 1.7.3
168
			 * @param boolean False: don't have frontend archive; True: yes, have archive. Default: false
169
			 */
170
			'has_archive'         => apply_filters( 'gravityview_has_archive', false ),
171
			'exclude_from_search' => true,
172
			'rewrite'             => array(
173
				/**
174
				 * @filter `gravityview_slug` Modify the url part for a View.
175
				 * @see https://docs.gravityview.co/article/62-changing-the-view-slug
176
				 * @param string $slug The slug shown in the URL
177
				 */
178
				'slug' => apply_filters( 'gravityview_slug', 'view' ),
179
180
				/**
181
				 * @filter `gravityview/post_type/with_front` Should the permalink structure
182
				 *  be prepended with the front base.
183
				 *  (example: if your permalink structure is /blog/, then your links will be: false->/view/, true->/blog/view/).
184
				 *  Defaults to true.
185
				 * @see https://codex.wordpress.org/Function_Reference/register_post_type
186
				 * @since 2.0
187
				 * @param bool $with_front
188
				 */
189
				'with_front' => apply_filters( 'gravityview/post_type/with_front', true ),
190
			),
191
			'capability_type'     => 'gravityview',
192
			'map_meta_cap'        => true,
193
		);
194
195
		register_post_type( 'gravityview', $args );
196
	}
197
198
	/**
199
	 * Add extra rewrite endpoints.
200
	 *
201
	 * @return void
202
	 */
203 1
	public static function add_rewrite_endpoint() {
204
		/**
205
		 * CSV.
206
		 */
207
		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...
208
209
		$slug = apply_filters( 'gravityview_slug', 'view' );
210
		$rule = array( sprintf( '%s/([^/]+)/csv/?', $slug ), 'index.php?gravityview=$matches[1]&csv=1', 'top' );
211
212 1
		add_filter( 'query_vars', function( $query_vars ) { 
213 1
			$query_vars[] = 'csv';
214 1
			return $query_vars;
215
		} );
216
217
		if ( ! isset( $wp_rewrite->extra_rules_top[ $rule[0] ] ) ) {
218
			call_user_func_array( 'add_rewrite_rule', $rule );
219
		}
220
	}
221
222
	/**
223
	 * A renderer filter for the View post type content.
224
	 *
225
	 * @param string $content Should be empty, as we don't store anything there.
226
	 *
227
	 * @return string $content The view content as output by the renderers.
228
	 */
229 10
	public static function content( $content ) {
230 10
		$request = gravityview()->request;
231
232
		// Plugins may run through the content in the header. WP SEO does this for its OpenGraph functionality.
233 10
		if ( ! defined( 'DOING_GRAVITYVIEW_TESTS' ) ) {
234
			if ( ! did_action( 'loop_start' ) ) {
235
				gravityview()->log->debug( 'Not processing yet: loop_start hasn\'t run yet. Current action: {action}', array( 'action' => current_filter() ) );
236
				return $content;
237
			}
238
239
			//	We don't want this filter to run infinite loop on any post content fields
240
			remove_filter( 'the_content', array( __CLASS__, __METHOD__ ) );
241
		}
242
243
		/**
244
		 * This is not a View. Bail.
245
		 *
246
		 * Shortcodes and oEmbeds and whatnot will be handled
247
		 *  elsewhere.
248
		 */
249 10
		if ( ! $view = $request->is_view() ) {
250 5
			return $content;
251
		}
252
253
		/**
254
		 * Check permissions.
255
		 */
256 5
		while ( $error = $view->can_render( null, $request ) ) {
257 5
			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...
258 5
				break;
259
260 1
			switch ( str_replace( 'gravityview/', '', $error->get_error_code() ) ) {
261 1
				case 'post_password_required':
262 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...
263 1
				case 'no_form_attached':
264
					/**
265
					 * This View has no data source. There's nothing to show really.
266
					 * ...apart from a nice message if the user can do anything about it.
267
					 */
268
					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...
269
						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...
270
					}
271
					break;
272 1
				case 'no_direct_access':
273 1
				case 'embed_only':
274 1
				case 'not_public':
275 1
					return __( 'You are not allowed to view this content.', 'gravityview' );
276
			}
277
278
			return $content;
279
		}
280
281 5
		$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...
282
283
		/**
284
		 * Editing a single entry.
285
		 */
286 5
		if ( $entry = $request->is_edit_entry() ) {
287
			if ( $entry['status'] != 'active' ) {
0 ignored issues
show
introduced by
Found "!= '". Use Yoda Condition checks, you must
Loading history...
288
				gravityview()->log->notice( 'Entry ID #{entry_id} is not active', array( 'entry_id' => $entry->ID ) );
289
				return __( 'You are not allowed to view this content.', 'gravityview' );
290
			}
291
292
			if ( apply_filters( 'gravityview_custom_entry_slug', false ) && $entry->slug != get_query_var( \GV\Entry::get_endpoint_name() ) ) {
293
				gravityview()->log->error( 'Entry ID #{entry_id} was accessed by a bad slug', array( 'entry_id' => $entry->ID ) );
294
				return __( 'You are not allowed to view this content.', 'gravityview' );
295
			}
296
297
			if ( $view->settings->get( 'show_only_approved' ) && ! $is_admin_and_can_view ) {
298
				if ( ! \GravityView_Entry_Approval_Status::is_approved( gform_get_meta( $entry->ID, \GravityView_Entry_Approval::meta_key ) )  ) {
299
					gravityview()->log->error( 'Entry ID #{entry_id} is not approved for viewing', array( 'entry_id' => $entry->ID ) );
300
					return __( 'You are not allowed to view this content.', 'gravityview' );
301
				}
302
			}
303
304
			$renderer = new Edit_Entry_Renderer();
305
			return $renderer->render( $entry, $view, $request );
306
307
		/**
308
		 * Viewing a single entry.
309
		 */
310 5
		} else if ( $entry = $request->is_entry() ) {
311 1
			if ( $entry['status'] != 'active' ) {
0 ignored issues
show
introduced by
Found "!= '". Use Yoda Condition checks, you must
Loading history...
312 1
				gravityview()->log->notice( 'Entry ID #{entry_id} is not active', array( 'entry_id' => $entry->ID ) );
313 1
				return __( 'You are not allowed to view this content.', 'gravityview' );
314
			}
315
316 1
			if ( apply_filters( 'gravityview_custom_entry_slug', false ) && $entry->slug != get_query_var( \GV\Entry::get_endpoint_name() ) ) {
317 1
				gravityview()->log->error( 'Entry ID #{entry_id} was accessed by a bad slug', array( 'entry_id' => $entry->ID ) );
318 1
				return __( 'You are not allowed to view this content.', 'gravityview' );
319
			}
320
321 1
			if ( $view->settings->get( 'show_only_approved' ) && ! $is_admin_and_can_view ) {
322 1
				if ( ! \GravityView_Entry_Approval_Status::is_approved( gform_get_meta( $entry->ID, \GravityView_Entry_Approval::meta_key ) )  ) {
323 1
					gravityview()->log->error( 'Entry ID #{entry_id} is not approved for viewing', array( 'entry_id' => $entry->ID ) );
324 1
					return __( 'You are not allowed to view this content.', 'gravityview' );
325
				}
326
			}
327
328 1
			$error = \GVCommon::check_entry_display( $entry->as_entry() );
329
330 1
			if( is_wp_error( $error ) ) {
331
				gravityview()->log->error( 'Entry ID #{entry_id} is not approved for viewing: {message}', array( 'entry_id' => $entry->ID, 'message' => $error->get_error_message() ) );
332
				return __( 'You are not allowed to view this content.', 'gravityview' );
333
			}
334
335 1
			$renderer = new Entry_Renderer();
336 1
			return $renderer->render( $entry, $view, $request );
337
338
		/**
339
		 * Plain old View.
340
		 */
341
		} else {
342 4
			$renderer = new View_Renderer();
343 4
			return $renderer->render( $view, $request );
344
		}
345
346
		return $content;
0 ignored issues
show
Unused Code introduced by
return $content; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
347
	}
348
349
	/**
350
	 * Checks whether this view can be accessed or not.
351
	 *
352
	 * @param string[]    $context The context we're asking for access from.
353
	 *                             Can any and as many of one of:
354
	 *                                 edit      An edit context.
355
	 *                                 single    A single context.
356
	 *                                 cpt       The custom post type single page acessed.
357
	 *                                 shortcode Embedded as a shortcode.
358
	 *                                 oembed    Embedded as an oEmbed.
359
	 *                                 rest      A REST call.
360
	 * @param \GV\Request $request The request
361
	 *
362
	 * @return bool|\WP_Error An error if this View shouldn't be rendered here.
363
	 */
364 16
	public function can_render( $context = null, $request = null ) {
365 16
		if ( ! $request ) {
366
			$request = gravityview()->request;
367
		}
368
369 16
		if ( ! is_array( $context ) ) {
370 5
			$context = array();
371
		}
372
373 16
		if ( in_array( 'rest', $context ) ) {
374
			// REST
375 5
			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...
376 1
				return new \WP_Error( 'gravityview/rest_disabled' );
377 5
			} 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...
378 1
				return new \WP_Error( 'gravityview/rest_disabled' );
379
			}
380
		}
381
382 16
		if ( in_array( 'csv', $context ) ) {
383
			if ( $this->settings->get( 'csv_enable' ) !== '1' ) {
0 ignored issues
show
introduced by
Found "!== '". Use Yoda Condition checks, you must
Loading history...
384
				return new \WP_Error( 'gravityview/csv_disabled', 'The CSV endpoint is not enabled for this View' );
385
			}
386
		}
387
388
		/**
389
		 * This View is password protected. Nothing to do here.
390
		 */
391 16
		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...
392 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...
393 3
			return new \WP_Error( 'gravityview/post_password_required' );
394
		}
395
396 16
		if ( ! $this->form ) {
397
			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...
398
			return new \WP_Error( 'gravityview/no_form_attached' );
399
		}
400
401 16
		if ( ! in_array( 'shortcode', $context ) ) {
402
			/**
403
			 * Is this View directly accessible via a post URL?
404
			 *
405
			 * @see https://codex.wordpress.org/Function_Reference/register_post_type#public
406
			 */
407
408
			/**
409
			 * @filter `gravityview_direct_access` Should Views be directly accessible, or only visible using the shortcode?
410
			 * @deprecated
411
			 * @param[in,out] boolean `true`: allow Views to be accessible directly. `false`: Only allow Views to be embedded. Default: `true`
412
			 * @param int $view_id The ID of the View currently being requested. `0` for general setting
413
			 */
414 10
			$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...
415
416
			/**
417
			 * @filter `gravityview/request/output/direct` Should this View be directly accessbile?
418
			 * @since 2.0
419
			 * @param[in,out] boolean Accessible or not. Default: accessbile.
420
			 * @param \GV\View $view The View we're trying to directly render here.
421
			 * @param \GV\Request $request The current request.
422
			 */
423 10
			if ( ! apply_filters( 'gravityview/view/output/direct', $direct_access, $this, $request ) ) {
424
				return new \WP_Error( 'gravityview/no_direct_access' );
425
			}
426
427
			/**
428
			 * Is this View an embed-only View? If so, don't allow rendering here,
429
			 *  as this is a direct request.
430
			 */
431 10
			if ( $this->settings->get( 'embed_only' ) && ! \GVCommon::has_cap( 'read_private_gravityviews' ) ) {
432 1
				return new \WP_Error( 'gravityview/embed_only' );
433
			}
434
		}
435
436
		/** Private, pending, draft, etc. */
437 16
		$public_states = get_post_stati( array( 'public' => true ) );
438 16
		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...
439 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...
440 3
			return new \WP_Error( 'gravityview/not_public' );
441
		}
442
443 16
		return true;
444
	}
445
446
	/**
447
	 * Get joins associated with a view
448
	 *
449
	 * @param \WP_Post $post GravityView CPT to get joins for
450
	 *
451
	 * @since 2.0.11
452
	 *
453
	 * @return \GV\Join[] Array of \GV\Join instances
454
	 */
455 77
	public static function get_joins( $post ) {
456
457 77
		if ( ! gravityview()->plugin->supports( Plugin::FEATURE_JOINS ) ) {
458
			gravityview()->log->error( 'Cannot get joined forms; joins feature not supported.' );
459
			return array();
460
		}
461
462 77
		if ( ! $post || 'gravityview' !== get_post_type( $post ) ) {
463
			gravityview()->log->error( 'Only "gravityview" post types can be \GV\View instances.' );
464
			return array();
465
		}
466
467 77
		$joins_meta = get_post_meta( $post->ID, '_gravityview_form_joins', true );
468
469 77
		if ( empty( $joins_meta ) ) {
470 73
			return array();
471
		}
472
473 4
		$joins = array();
474
475 4
		foreach ( $joins_meta as $meta ) {
476 4
			if ( ! is_array( $meta ) || count( $meta ) != 4 ) {
0 ignored issues
show
introduced by
Found "!= 4". Use Yoda Condition checks, you must
Loading history...
477
				continue;
478
			}
479
480 4
			list( $join, $join_column, $join_on, $join_on_column ) = $meta;
481
482 4
			$join    = GF_Form::by_id( $join );
483 4
			$join_on = GF_Form::by_id( $join_on );
484
485 4
			$join_column    = is_numeric( $join_column ) ? GF_Field::by_id( $join, $join_column ) : Internal_Field( $join_column );
486 4
			$join_on_column = is_numeric( $join_on_column ) ? GF_Field::by_id( $join_on, $join_on_column ) : Internal_Field( $join_on_column );
487
488 4
			$joins [] = new Join( $join, $join_column, $join_on, $join_on_column );
489
		}
490
491 4
		return $joins;
492
	}
493
494
	/**
495
	 * Get joined forms associated with a view
496
	 *
497
	 * @since 2.0.11
498
	 *
499
	 * @param int $post_id ID of the View
500
	 *
501
	 * @return \GV\GF_Form[] Array of \GV\GF_Form instances
502
	 */
503
	public static function get_joined_forms( $post_id = 0 ) {
504
505
		if ( ! gravityview()->plugin->supports( Plugin::FEATURE_JOINS ) ) {
506
			gravityview()->log->error( 'Cannot get joined forms; joins feature not supported.' );
507
			return array();
508
		}
509
510
		if ( empty( $post_id ) ) {
511
			gravityview()->log->error( 'Cannot get joined forms; $post_id was empty' );
512
			return array();
513
		}
514
515
		$joins_meta = get_post_meta( $post_id, '_gravityview_form_joins', true );
516
517
		if ( empty( $joins_meta ) ) {
518
			return array();
519
		}
520
521
		$forms_ids = array();
522
523
		foreach ( $joins_meta  as $meta ) {
524
			if ( ! is_array( $meta ) || count( $meta ) != 4 ) {
0 ignored issues
show
introduced by
Found "!= 4". Use Yoda Condition checks, you must
Loading history...
525
				continue;
526
			}
527
528
			list( $join, $join_column, $join_on, $join_on_column ) = $meta;
529
530
			$forms_ids [] = GF_Form::by_id( $join_on );
531
		}
532
533
		return ( !empty( $forms_ids) ) ? $forms_ids : null;
0 ignored issues
show
introduced by
Expected 1 space after "!"; 0 found
Loading history...
Coding Style introduced by
Expected 1 spaces before closing bracket; 0 found
Loading history...
534
	}
535
536
	/**
537
	 * Construct a \GV\View instance from a \WP_Post.
538
	 *
539
	 * @param \WP_Post $post The \WP_Post instance to wrap.
540
	 *
541
	 * @api
542
	 * @since 2.0
543
	 * @return \GV\View|null An instance around this \WP_Post if valid, null otherwise.
544
	 */
545 78
	public static function from_post( $post ) {
546
547 78
		if ( ! $post || 'gravityview' !== get_post_type( $post ) ) {
548 2
			gravityview()->log->error( 'Only gravityview post types can be \GV\View instances.' );
549 2
			return null;
550
		}
551
552 78
		if ( $view = Utils::get( self::$cache, "View::from_post:{$post->ID}" ) ) {
553 38
			return $view;
554
		}
555
556 78
		$view = new self();
557 78
		$view->post = $post;
558
559
		/** Get connected form. */
560 78
		$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...
561 78
		if ( ! $view->form ) {
562
			gravityview()->log->error( 'View #{view_id} tried attaching non-existent Form #{form_id} to it.', array(
563
				'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...
564
				'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...
565
			) );
566
		}
567
568 78
		$view->joins = $view->get_joins( $post );
569
570
		/**
571
		 * @filter `gravityview/configuration/fields` Filter the View fields' configuration array.
572
		 * @since 1.6.5
573
		 *
574
		 * @deprecated Use `gravityview/view/configuration/fields` or `gravityview/view/fields` filters.
575
		 *
576
		 * @param $fields array Multi-array of fields with first level being the field zones.
577
		 * @param $view_id int The View the fields are being pulled for.
578
		 */
579 78
		$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...
580
581
		/**
582
		 * @filter `gravityview/view/configuration/fields` Filter the View fields' configuration array.
583
		 * @since 2.0
584
		 *
585
		 * @param array $fields Multi-array of fields with first level being the field zones.
586
		 * @param \GV\View $view The View the fields are being pulled for.
587
		 */
588 78
		$configuration = apply_filters( 'gravityview/view/configuration/fields', $configuration, $view );
589
590
		/**
591
		 * @filter `gravityview/view/fields` Filter the Field Collection for this View.
592
		 * @since 2.0
593
		 *
594
		 * @param \GV\Field_Collection $fields A collection of fields.
595
		 * @param \GV\View $view The View the fields are being pulled for.
596
		 */
597 78
		$view->fields = apply_filters( 'gravityview/view/fields', Field_Collection::from_configuration( $configuration ), $view );
598
599
		/**
600
		 * @filter `gravityview/view/configuration/widgets` Filter the View widgets' configuration array.
601
		 * @since 2.0
602
		 *
603
		 * @param array $fields Multi-array of widgets with first level being the field zones.
604
		 * @param \GV\View $view The View the widgets are being pulled for.
605
		 */
606 78
		$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...
607
608
		/**
609
		 * @filter `gravityview/view/widgets` Filter the Widget Collection for this View.
610
		 * @since 2.0
611
		 *
612
		 * @param \GV\Widget_Collection $widgets A collection of widgets.
613
		 * @param \GV\View $view The View the widgets are being pulled for.
614
		 */
615 78
		$view->widgets = apply_filters( 'gravityview/view/widgets', Widget_Collection::from_configuration( $configuration ), $view );
616
617
		/** View configuration. */
618 78
		$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...
619
620
		/** Add the template name into the settings. */
621 78
		$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...
622
623
		/** View basics. */
624 78
		$view->settings->update( array(
625 78
			'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...
626
		) );
627
628 78
		self::$cache[ "View::from_post:{$post->ID}" ] = &$view;
629
630 78
		return $view;
631
	}
632
633
	/**
634
	 * Flush the view cache.
635
	 *
636
	 * @param int $view_id The View to reset cache for. Optional. Default: resets everything.
637
	 *
638
	 * @internal
639
	 */
640 89
	public static function _flush_cache( $view_id = null ) {
641 89
		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...
642 82
			unset( self::$cache[ "View::from_post:$view_id" ] );
643 82
			return;
644
		}
645 70
		self::$cache = array();
646 70
	}
647
648
	/**
649
	 * Construct a \GV\View instance from a post ID.
650
	 *
651
	 * @param int|string $post_id The post ID.
652
	 *
653
	 * @api
654
	 * @since 2.0
655
	 * @return \GV\View|null An instance around this \WP_Post or null if not found.
656
	 */
657 39
	public static function by_id( $post_id ) {
658 39
		if ( ! $post_id || ! $post = get_post( $post_id ) ) {
659 3
			return null;
660
		}
661 39
		return self::from_post( $post );
662
	}
663
664
	/**
665
	 * Determines if a view exists to begin with.
666
	 *
667
	 * @param int|\WP_Post|null $view The WordPress post ID, a \WP_Post object or null for global $post;
668
	 *
669
	 * @api
670
	 * @since 2.0
671
	 * @return bool Whether the post exists or not.
672
	 */
673 5
	public static function exists( $view ) {
674 5
		return get_post_type( $view ) == 'gravityview';
675
	}
676
677
	/**
678
	 * ArrayAccess compatibility layer with GravityView_View_Data::$views
679
	 *
680
	 * @internal
681
	 * @deprecated
682
	 * @since 2.0
683
	 * @return bool Whether the offset exists or not, limited to GravityView_View_Data::$views element keys.
684
	 */
685 12
	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...
686 12
		$data_keys = array( 'id', 'view_id', 'form_id', 'template_id', 'atts', 'fields', 'widgets', 'form' );
687 12
		return in_array( $offset, $data_keys );
688
	}
689
690
	/**
691
	 * ArrayAccess compatibility layer with GravityView_View_Data::$views
692
	 *
693
	 * Maps the old keys to the new data;
694
	 *
695
	 * @internal
696
	 * @deprecated
697
	 * @since 2.0
698
	 *
699
	 * @return mixed The value of the requested view data key limited to GravityView_View_Data::$views element keys.
700
	 */
701 12
	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...
702
703 12
		gravityview()->log->notice( 'This is a \GV\View object should not be accessed as an array.' );
704
705 12
		if ( ! isset( $this[ $offset ] ) ) {
706
			return null;
707
		}
708
709 12
		switch ( $offset ) {
710 12
			case 'id':
711 12
			case 'view_id':
712 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...
713 12
			case 'form':
714 12
				return $this->form;
715 1
			case 'form_id':
716 1
				return $this->form ? $this->form->ID : null;
717 1
			case 'atts':
718
				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...
719 1
			case 'template_id':
720 1
				return $this->settings->get( 'template' );
721
			case 'widgets':
722
				return $this->widgets->as_configuration();
723
		}
724
	}
725
726
	/**
727
	 * ArrayAccess compatibility layer with GravityView_View_Data::$views
728
	 *
729
	 * @internal
730
	 * @deprecated
731
	 * @since 2.0
732
	 *
733
	 * @return void
734
	 */
735 1
	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...
736 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.' );
737 1
	}
738
739
	/**
740
	 * ArrayAccess compatibility layer with GravityView_View_Data::$views
741
	 *
742
	 * @internal
743
	 * @deprecated
744
	 * @since 2.0
745
	 * @return void
746
	 */
747 1
	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...
748 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.' );
749 1
	}
750
751
	/**
752
	 * Be compatible with the old data object.
753
	 *
754
	 * Some external code expects an array (doing things like foreach on this, or array_keys)
755
	 *  so let's return an array in the old format for such cases. Do not use unless using
756
	 *  for back-compatibility.
757
	 *
758
	 * @internal
759
	 * @deprecated
760
	 * @since 2.0
761
	 * @return array
762
	 */
763 9
	public function as_data() {
764
		return array(
765 9
			'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...
766 9
			'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...
767 9
			'form_id' => $this->form ? $this->form->ID : null,
768 9
			'form' => $this->form ? gravityview_get_form( $this->form->ID ) : null,
769 9
			'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...
770 9
			'fields' => $this->fields->by_visible()->as_configuration(),
771 9
			'template_id' => $this->settings->get( 'template' ),
772 9
			'widgets' => $this->widgets->as_configuration(),
773
		);
774
	}
775
776
	/**
777
	 * Retrieve the entries for the current view and request.
778
	 *
779
	 * @param \GV\Request The request. Usued for now.
780
	 *
781
	 * @return \GV\Entry_Collection The entries.
782
	 */
783 26
	public function get_entries( $request = null ) {
784 26
		$entries = new \GV\Entry_Collection();
785 26
		if ( $this->form ) {
786
			/**
787
			 * @todo: Stop using _frontend and use something like $request->get_search_criteria() instead
788
			 */
789 26
			$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...
790 26
			$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...
791 26
			$parameters = \GVCommon::calculate_get_entries_criteria( $parameters, $this->form->ID );
792
793 26
			if ( $request instanceof REST\Request ) {
794 3
				$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...
795 3
				$paging_parameters = wp_parse_args( $request->get_paging(), array(
796 3
						'paging' => array( 'page_size' => $atts['page_size'] ),
797
					) );
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...
798 3
				$parameters['paging'] = $paging_parameters['paging'];
799
			}
800
801 26
			$page = Utils::get( $parameters['paging'], 'current_page' ) ?
802 26
				: ( ( ( $parameters['paging']['offset'] - $this->settings->get( 'offset' ) ) / $parameters['paging']['page_size'] ) + 1 );
803
804 26
			if ( gravityview()->plugin->supports( Plugin::FEATURE_GFQUERY ) ) {
805
				/**
806
				 * New \GF_Query stuff :)
807
				 */
808 26
				$query = new \GF_Query( $this->form->ID, $parameters['search_criteria'], $parameters['sorting'] );
809
810 26
				$query->limit( $parameters['paging']['page_size'] )
811 26
					->offset( ( ( $page - 1 ) * $parameters['paging']['page_size'] ) + $this->settings->get( 'offset' ) );
812
813
				/**
814
				 * Any joins?
815
				 */
816 26
				if ( Plugin::FEATURE_JOINS && count( $this->joins ) ) {
817 4
					foreach ( $this->joins as $join ) {
818 4
						$query = $join->as_query_join( $query );
819
					}
820
				}
821
822
				/**
823
				 * @action `gravityview/view/query` Override the \GF_Query before the get() call.
824
				 * @param \GF_Query $query The current query object
825
				 * @param \GV\View $this The current view object
826
				 * @param \GV\Request $request The request object
827
				 */
828 26
				do_action( 'gravityview/view/query', $query, $this, $request );
829
830
				/**
831
				 * Map from Gravity Forms entries arrays to an Entry_Collection.
832
				 */
833 26
				if ( count( $this->joins ) ) {
834 4
					foreach ( $query->get() as $entry ) {
835 4
						$entries->add(
836 4
							Multi_Entry::from_entries( array_map( '\GV\GF_Entry::from_entry', $entry ) )
837
						);
838
					}
839
				} else {
840 22
					array_map( array( $entries, 'add' ), array_map( '\GV\GF_Entry::from_entry', $query->get() ) );
841
				}
842
843
				/**
844
				 * Add total count callback.
845
				 */
846 26
				$entries->add_count_callback( function() use ( $query ) {
847 20
					return $query->total_found;
848 26
				} );
849
			} else {
850
				$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...
851
					->filter( \GV\GF_Entry_Filter::from_search_criteria( $parameters['search_criteria'] ) )
852
					->offset( $this->settings->get( 'offset' ) )
853
					->limit( $parameters['paging']['page_size'] )
854
					->page( $page );
855
856
				if ( ! empty( $parameters['sorting'] ) && ! empty( $parameters['sorting']['key'] ) ) {
857
					$field = new \GV\Field();
858
					$field->ID = $parameters['sorting']['key'];
859
					$direction = strtolower( $parameters['sorting']['direction'] ) == 'asc' ? \GV\Entry_Sort::ASC : \GV\Entry_Sort::DESC;
860
					$entries = $entries->sort( new \GV\Entry_Sort( $field, $direction ) );
861
				}
862
			}
863
		}
864
865
		/**
866
		 * @filter `gravityview/view/entries` Modify the entry fetching filters, sorts, offsets, limits.
867
		 * @param \GV\Entry_Collection $entries The entries for this view.
868
		 * @param \GV\View $view The view.
869
		 * @param \GV\Request $request The request.
870
		 */
871 26
		return apply_filters( 'gravityview/view/entries', $entries, $this, $request );
872
	}
873
874
	/**
875
	 * Last chance to configure the output.
876
	 *
877
	 * Used for CSV output, for example.
878
	 *
879
	 * @return void
880
	 */
881
	public static function template_redirect() {
882
		/**
883
		 * CSV output.
884
		 */
885
		if ( ! get_query_var( 'csv' ) ) {
886
			return;
887
		}
888
889
		if ( ! $view = gravityview()->request->is_view() ) {
890
			return;
891
		}
892
893
		if ( is_wp_error( $error = $view->can_render( array( 'csv' ) ) ) ) {
894
			gravityview()->log->error( 'Not rendering CSV: ' . $error->get_error_message() );
895
			return;
896
		}
897
898
		/**
899
		 * Modify the name of the generated CSV file. Name will be sanitized using sanitize_file_name() before output.
900
		 * @see sanitize_file_name()
901
		 * @since 2.1
902
		 * @param string   $filename File name used when downloading a CSV. Default is "{View title}.csv"
903
		 * @param \GV\View $view Current View being rendered
904
		 */
905
		$filename = apply_filters( 'gravityview/output/csv/filename', get_the_title( $view->post ), $view );
906
907
		header( sprintf( 'Content-Disposition: attachment;filename="%s.csv"', sanitize_file_name( $filename ) ) );
908
		header( 'Content-Transfer-Encoding: binary' );
909
		header( 'Content-Type: text/csv' );
910
911
		$csv = fopen( 'php://output', 'w' );
912
913
		/**
914
		 * Add da' BOM if GF uses it
915
		 * @see GFExport::start_export()
916
		 */
917
		if ( apply_filters( 'gform_include_bom_export_entries', true, $form ) ) {
0 ignored issues
show
Bug introduced by
The variable $form does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
918
			fputs( $csv, "\xef\xbb\xbf" );
0 ignored issues
show
introduced by
Filesystem writes are forbidden, you should not be using fputs()
Loading history...
919
		}
920
921
		$entries = $view->get_entries();
922
923
		$headers_done = false;
924
		$allowed = $headers = array();
925
926
		/**
927
		 * @todo Maybe create a CSV_Renderer?
928
		 */
929
		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...
930
			$allowed[] = $field->ID;
931
		}
932
933
		foreach ( $entries->all() as $entry ) {
934
			$return = $entry->as_entry();
935
936
			/**
937
			 * @filter `gravityview/csv/entry/fields` Whitelist more entry fields that are output in CSV requests.
938
			 * @param[in,out] array $allowed The allowed ones, default by_visible, by_position( "context_*" ), i.e. as set in the view.
939
			 * @param \GV\View $view The view.
940
			 * @param \GV\Entry $entry WordPress representation of the item.
941
			 */
942
			$allowed = apply_filters( 'gravityview/rest/entry/fields', $allowed, $view, $entry );
943
944
			foreach ( $return as $key => $value ) {
945
				if ( ! in_array( $key, $allowed ) ) {
946
					unset( $return[ $key ] );
947
				}
948
			}
949
950
			foreach ( $allowed as $field ) {
951
				$source = is_numeric( $field ) ? $view->form : new \GV\Internal_Source();
952
				$field  = is_numeric( $field ) ? \GV\GF_Field::by_id( $view->form, $field ) : \GV\Internal_Field::by_id( $field );
953
954
				$return[ $field->ID ] = $field->get_value( $view, $source, $entry );
955
956
				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...
957
					$label = $field->get_label( $view, $source, $entry );
958
					$headers[ $field->ID ] = $label ? $label : $field->ID;
959
				}
960
			}
961
962
			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...
963
				$headers_done = fputcsv( $csv, array_values( array_map( 'gravityview_strip_excel_formulas', $headers ) ) );
0 ignored issues
show
introduced by
Filesystem writes are forbidden, you should not be using fputcsv()
Loading history...
964
			}
965
966
			fputcsv( $csv, array_map( 'gravityview_strip_excel_formulas', $return ) );
0 ignored issues
show
introduced by
Filesystem writes are forbidden, you should not be using fputcsv()
Loading history...
967
		}
968
969
		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...
970
	}
971
972 77
	public function __get( $key ) {
973 77
		if ( $this->post ) {
974 77
			$raw_post = $this->post->filter( 'raw' );
975 77
			return $raw_post->{$key};
976
		}
977
		return isset( $this->{$key} ) ? $this->{$key} : null;
978
	}
979
}
980