Completed
Push — develop ( 50e840...dec1cf )
by Gennady
31:40 queued 16:54
created

gravityview::parse_and_sanitize_atts()   C

Complexity

Conditions 11
Paths 15

Size

Total Lines 59

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 11.1659

Importance

Changes 0
Metric Value
cc 11
nc 15
nop 1
dl 0
loc 59
ccs 24
cts 27
cp 0.8889
crap 11.1659
rs 6.7478
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
2
namespace GV\Shortcodes;
3
4
/** If this file is called directly, abort. */
5
if ( ! defined( 'GRAVITYVIEW_DIR' ) ) {
6
	die();
7
}
8
9
/**
10
 * The [gravityview] shortcode.
11
 */
12
class gravityview extends \GV\Shortcode {
13
	/**
14
	 * {@inheritDoc}
15
	 */
16
	public $name = 'gravityview';
17
18
	/**
19
	 * A stack of calls to track nested shortcodes.
20
	 */
21
	public static $callstack = array();
22
23
	/**
24
	 * Process and output the [gravityview] shortcode.
25
	 *
26
	 * @param array $passed_atts The attributes passed.
27
	 * @param string $content The content inside the shortcode.
28
	 *
29
	 * @return string|null The output.
30
	 */
31 10
	public function callback( $passed_atts, $content = null ) {
32 10
		$request = gravityview()->request;
33
34 10
		if ( $request->is_admin() ) {
35
			return '';
36
		}
37
38 10
		$atts = wp_parse_args( $passed_atts, array(
39 10
			'id' => 0,
40
			'view_id' => 0,
41
			'detail' => null,
42
		) );
43
		
44 10
		if ( ! $view_id = $atts['id'] ? : $atts['view_id'] ) {
45
			if ( $atts['detail'] && $view = $request->is_view() ) {
46
				$view_id = $view->ID;
0 ignored issues
show
Bug introduced by
The property ID does not seem to exist in GV\View.

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...
47
			}
48
		}
49
50 10
		$view = \GV\View::by_id( $view_id );
51
52 10
		if ( ! $view ) {
53
			gravityview()->log->error( 'View does not exist #{view_id}', array( 'view_id' => $view_id ) );
54
			return '';
55
		}
56
57 10
		gravityview()->views->set( $view );
0 ignored issues
show
Documentation introduced by
The property views does not exist on object<GV\Core>. 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...
58
59
		/**
60
		 * When this shortcode is embedded inside a View we can only display it as a directory. There's no other way.
61
		 * Try to detect that we're not embedded to allow edit and single contexts.
62
		 */
63 10
		$is_reembedded = false; // Assume not embedded unless detected otherwise.
64 10
		if ( in_array( get_class( $request ), array( 'GV\Frontend_Request', 'GV\Mock_Request' ) ) ) {
65
66 10
			if ( ( $_view = $request->is_view() ) && $_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...
67
				$is_reembedded = true;
68
69 10
			} elseif ( $request->is_entry( $view->form ? $view->form->ID : 0 ) && self::$callstack ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression self::$callstack of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

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

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

Loading history...
70 1
				$is_reembedded = true;
71
			}
72
		}
73
74 10
		array_push( self::$callstack, true );
75
76
		/**
77
		 * Remove Widgets on a nested embedded View.
78
		 */
79 10
		if ( $is_reembedded ) {
80 1
			$view->widgets = new \GV\Widget_Collection();
81
		}
82
83 10
		$atts = $this->parse_and_sanitize_atts( $atts );
84
85 10
		$view->settings->update( $atts );
86
87
		/**
88
		 * Check permissions.
89
		 */
90 10
		while ( $error = $view->can_render( array( 'shortcode' ), $request ) ) {
91 10
			if ( ! is_wp_error( $error ) )
92 10
				break;
93
94 1
			switch ( str_replace( 'gravityview/', '', $error->get_error_code() ) ) {
95 1
				case 'post_password_required':
96 1
					return self::_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...
97 1
				case 'no_form_attached':
98
					/**
99
					 * This View has no data source. There's nothing to show really.
100
					 * ...apart from a nice message if the user can do anything about it.
101
					 */
102
					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...
103
						return self::_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...
104
					}
105
					break;
106 1
				case 'no_direct_access':
107 1
				case 'embed_only':
108 1
				case 'not_public':
109
				default:
110 1
					return self::_return( __( 'You are not allowed to view this content.', 'gravityview' ) );
111
			}
112
		}
113
114 10
		$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...
115
116
		/**
117
		 * View details.
118
		 */
119 10
		if ( $atts['detail'] ) {
120 2
			$entries = $view->get_entries( $request );
121 2
			return self::_return( $this->detail( $view, $entries, $atts ) );
122
123
		/**
124
		 * Editing a single entry.
125
		 */
126 9
		} else if ( ! $is_reembedded && ( $entry = $request->is_edit_entry( $view->form ? $view->form->ID : 0 ) ) ) {
127
128
			/**
129
			 * When editing an entry don't render multiple views.
130
			 */
131
			if ( ( $selected = \GV\Utils::_GET( 'gvid' ) ) && $view->ID != $selected ) {
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...
132
				gravityview()->log->notice( 'Entry ID #{entry_id} not rendered because another View ID was passed using `?gvid`: #{selected}', array( 'entry_id' => $entry->ID, 'selected' => $selected ) );
133
				return self::_return( '' );
134
			}
135
136
			if ( $entry['status'] != 'active' ) {
137
				gravityview()->log->notice( 'Entry ID #{entry_id} is not active', array( 'entry_id' => $entry->ID ) );
138
				return self::_return( __( 'You are not allowed to view this content.', 'gravityview' ) );
139
			}
140
141
			if ( apply_filters( 'gravityview_custom_entry_slug', false ) && $entry->slug != get_query_var( \GV\Entry::get_endpoint_name() ) ) {
0 ignored issues
show
Bug introduced by
The property slug does not seem to exist in GV\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...
142
				gravityview()->log->error( 'Entry ID #{entry_id} was accessed by a bad slug', array( 'entry_id' => $entry->ID ) );
143
				return self::_return( __( 'You are not allowed to view this content.', 'gravityview' ) );
144
			}
145
146
			if ( $view->settings->get( 'show_only_approved' ) && ! $is_admin_and_can_view ) {
147
				if ( ! \GravityView_Entry_Approval_Status::is_approved( gform_get_meta( $entry->ID, \GravityView_Entry_Approval::meta_key ) )  ) {
148
					gravityview()->log->error( 'Entry ID #{entry_id} is not approved for viewing', array( 'entry_id' => $entry->ID ) );
149
					return self::_return( __( 'You are not allowed to view this content.', 'gravityview' ) );
150
				}
151
			}
152
153
			$renderer = new \GV\Edit_Entry_Renderer();
154
			return self::_return( $renderer->render( $entry, $view, $request ) );
155
156
		/**
157
		 * Viewing a single entry.
158
		 */
159 9
		} else if ( ! $is_reembedded && ( $entry = $request->is_entry( $view->form ? $view->form->ID : 0 ) ) ) {
160
			/**
161
			 * When viewing an entry don't render multiple views.
162
			 */
163 4
			if ( ( $selected = \GV\Utils::_GET( 'gvid' ) ) && $view->ID != $selected ) {
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...
164
				return self::_return( '' );
165
			}
166
167 4
			$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...
168
169 4
			foreach ( $entryset as $e ) {
170 4
				if ( $e['status'] != 'active' ) {
171 1
					gravityview()->log->notice( 'Entry ID #{entry_id} is not active', array( 'entry_id' => $e->ID ) );
172 1
					return self::_return( __( 'You are not allowed to view this content.', 'gravityview' ) );
173
				}
174
175 4
				if ( apply_filters( 'gravityview_custom_entry_slug', false ) && $e->slug != get_query_var( \GV\Entry::get_endpoint_name() ) ) {
176 1
					gravityview()->log->error( 'Entry ID #{entry_id} was accessed by a bad slug', array( 'entry_id' => $e->ID ) );
177 1
					return self::_return( __( 'You are not allowed to view this content.', 'gravityview' ) );
178
				}
179
180 4
				if ( $view->settings->get( 'show_only_approved' ) && ! $is_admin_and_can_view ) {
181 1
					if ( ! \GravityView_Entry_Approval_Status::is_approved( gform_get_meta( $e->ID, \GravityView_Entry_Approval::meta_key ) )  ) {
182 1
						gravityview()->log->error( 'Entry ID #{entry_id} is not approved for viewing', array( 'entry_id' => $e->ID ) );
183 1
						return self::_return( __( 'You are not allowed to view this content.', 'gravityview' ) );
184
					}
185
				}
186
187 4
				$error = \GVCommon::check_entry_display( $e->as_entry(), $view );
188
189 4
				if ( is_wp_error( $error ) ) {
190 2
					gravityview()->log->error( 'Entry ID #{entry_id} is not approved for viewing: {message}', array( 'entry_id' => $e->ID, 'message' => $error->get_error_message() ) );
191 2
					return self::_return( __( 'You are not allowed to view this content.', 'gravityview' ) );
192
				}
193
			}
194
195 4
			$renderer = new \GV\Entry_Renderer();
196 4
			return self::_return( $renderer->render( $entry, $view, $request ) );
197
198
		/**
199
		 * Just this view.
200
		 */
201
		} else {
202 7
			if ( $is_reembedded ) {
203
				
204
				// Mock the request with the actual View, not the global one
205 1
				$mock_request = new \GV\Mock_Request();
206 1
				$mock_request->returns['is_view'] = $view;
207 1
				$mock_request->returns['is_entry'] = $request->is_entry( $view->form ? $view->form->ID : 0 );
208 1
				$mock_request->returns['is_edit_entry'] = $request->is_edit_entry( $view->form ? $view->form->ID : 0 );
209 1
				$mock_request->returns['is_search'] = $request->is_search();
210
211 1
				$request = $mock_request;
212
			}
213
214 7
			$renderer = new \GV\View_Renderer();
215 7
			return self::_return( $renderer->render( $view, $request ) );
216
		}
217
	}
218
219
	/**
220
	 * Validate attributes passed to the [gravityview] shortcode. Supports {get} Merge Tags values.
221
	 *
222
	 * Attributes passed to the shortcode are compared to registered attributes {@see \GV\View_Settings::defaults}
223
	 * Only attributes that are defined will be allowed through.
224
	 *
225
	 * Then, {get} merge tags are replaced with their $_GET values, if passed
226
	 *
227
	 * Then, attributes are sanitized based on the type of setting (number, checkbox, select, radio, text)
228
	 *
229
	 * @see \GV\View_Settings::defaults() Only attributes defined in default() are valid to be passed via the shortcode
230
	 *
231
	 * @param array $passed_atts Attribute pairs defined to render the View
232
	 *
233
	 * @return array Valid and sanitized attribute pairs
234
	 */
235 9
	private function parse_and_sanitize_atts( $passed_atts ) {
236
237 9
		$defaults = \GV\View_Settings::defaults( true );
238
239 9
		$supported_atts = array_fill_keys( array_keys( $defaults ), '' );
240
241
		// Whittle down the attributes to only valid pairs
242 9
		$filtered_atts = shortcode_atts( $supported_atts, $passed_atts, 'gravityview' );
243
244
		// Only keep the passed attributes after making sure that they're valid pairs
245 9
		$filtered_atts = array_intersect_key( (array) $passed_atts, $filtered_atts );
246
247 9
		$atts = array();
248
249 9
		foreach( $filtered_atts as $key => $passed_value ) {
250
251
			// Allow using GravityView merge tags in shortcode attributes, like {get} and {created_by}
252 9
			$passed_value = \GravityView_Merge_Tags::replace_variables( $passed_value );
253
254 9
			switch( $defaults[ $key ]['type'] ) {
255
256
				/**
257
				 * Make sure number fields are numeric.
258
				 * Also, convert mixed number strings to numbers
259
				 * @see http://php.net/manual/en/function.is-numeric.php#107326
260
				 */
261 9
				case 'number':
262 9
					if( is_numeric( $passed_value ) ) {
263 9
						$atts[ $key ] = ( $passed_value + 0 );
264
					}
265 9
					break;
266
267
				// Checkboxes should be 1 or 0
268 3
				case 'checkbox':
269
					$atts[ $key ] = gv_empty( $passed_value, true, false ) ? 0 : 1;
270
					break;
271
272
				/**
273
				 * Only allow values that are defined in the settings
274
				 */
275 3
				case 'select':
276 2
				case 'radio':
277 1
					$options = isset( $defaults[ $key ]['choices'] ) ? $defaults[ $key ]['choices'] : $defaults[ $key ]['options'];
278 1
					if( in_array( $passed_value, array_keys( $options ) ) ) {
279
						$atts[ $key ] = $passed_value;
280
					}
281 1
					break;
282
283 2
				case 'text':
284
				default:
285 2
					$atts[ $key ] = $passed_value;
286 2
					break;
287
			}
288
		}
289
290 9
		$atts['detail'] = \GV\Utils::get( $passed_atts, 'detail', null );
291
292 9
		return $atts;
293
	}
294
295
	/**
296
	 * Output view details.
297
	 *
298
	 * @param \GV\View $view The View.
299
	 * @param \GV\Entry_Collection $entries The calculated entries.
300
	 * @param array $atts The shortcode attributes (with defaults).
301
	 *
302
	 * @return string The output.
303
	 */
304 1
	private function detail( $view, $entries, $atts ) {
305 1
		$output = '';
306
307 1
		switch ( $key = $atts['detail'] ):
308 1
			case 'total_entries':
309 1
				$output = number_format_i18n( $entries->total() );
310 1
				break;
311
			case 'first_entry':
312
				$output = number_format_i18n( min( $entries->total(), $view->settings->get( 'offset' ) + 1 ) );
313
				break;
314
			case 'last_entry':
315
				$output = number_format_i18n( $view->settings->get( 'page_size' ) + $view->settings->get( 'offset' ) );
316
				break;
317
			case 'page_size':
318
				$output = number_format_i18n( $view->settings->get( $key ) );
319
				break;
320
		endswitch;
321
322
		/**
323
		 * @filter `gravityview/shortcode/detail/{$detail}` Filter the detail output returned from `[gravityview detail="$detail"]`
324
		 * @since 1.13
325
		 * @param string[in,out] $output Existing output
0 ignored issues
show
Documentation introduced by
The doc-type string[in,out] could not be parsed: Expected "]" at position 2, but found "in". (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
326
		 *
327
		 * @since 2.0.3
328
		 * @param \GV\View $view The view.
329
		 * @param \GV\Entry_Collection $entries The entries.
330
		 * @param array $atts The shortcode atts with defaults.
331
		 */
332 1
		$output = apply_filters( "gravityview/shortcode/detail/$key", $output, $view );
333
334 1
		return $output;
335
	}
336
337
	/**
338
	 * Pop the callstack and return the value.
339
	 */
340 9
	private static function _return( $value ) {
341 9
		array_pop( self::$callstack );
342 9
		return $value;
343
	}
344
}
345