Completed
Push — develop ( 6ab3bd...540b54 )
by
unknown
17:26
created

GravityView_Admin_View_Item::additional_info()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 1
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @file class-gravityview-admin-view-item.php
4
 * @since 1.17.3
5
 */
6
7
/**
8
 * A field or widget in GravityView view configuration
9
 */
10
abstract class GravityView_Admin_View_Item {
11
12
	/**
13
	 * @var string Name of the item in the field or widget picker
14
	 */
15
	protected $title;
16
17
	/**
18
	 * @var string The field ID or the widget slug ( `2.3` or `custom_content`)
19
	 */
20
	protected $id;
21
22
	/**
23
	 * @var string Description of the item
24
	 */
25
	protected $subtitle;
26
27
	/**
28
	 * @var string The type of item ("field" or "widget")
29
	 */
30
	protected $label_type;
31
32
	/**
33
	 * @var array Associative array of item details
34
	 */
35
	protected $item;
36
37
	/**
38
	 * @var array Existing settings for the item
39
	 */
40
	protected $settings;
41
42
	/**
43
	 * @var string For ID, if available
44
	 */
45
	protected $form_id;
46
47
	function __construct( $title = '', $item_id = '', $item = array(), $settings = array(), $form_id = null) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

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

Loading history...
48
49
		// Backward compat
50
		if ( ! empty( $item['type'] ) ) {
51
			$item['input_type'] = $item['type'];
52
			unset( $item['type'] );
53
		}
54
55
		if ( $admin_label = \GV\Utils::get( $settings, 'admin_label' ) ) {
56
			$title = $admin_label;
57
		}
58
59
		// Prevent items from not having index set
60
		$item = wp_parse_args( $item, array(
61
			'label_text'    => $title,
62
			'field_id'      => null,
63
			'parent_label'  => null,
64
			'label_type'    => null,
65
			'input_type'    => null,
66
			'settings_html' => null,
67
			'adminLabel'    => null,
68
			'adminOnly'     => null,
69
			'subtitle'      => null,
70
			'placeholder'   => null,
71
			'icon'          => null,
72
		) );
73
74
		$this->title      = $title;
75
		$this->item       = $item;
76
		$this->id         = $item_id;
77
		$this->form_id    = $form_id;
78
		$this->settings   = $settings;
79
		$this->label_type = $item['label_type'];
80
	}
81
82
	/**
83
	 * When echoing this class, print the HTML output
84
	 * @return string HTML output of the class
85
	 */
86
	public function __toString() {
87
88
		return $this->getOutput();
89
	}
90
91
	/**
92
	 * Overridden by child classes
93
	 * @return array Array of content with arrays for each item. Those arrays have `value`, `label` and (optional) `class` keys
94
	 */
95
	protected function additional_info() {
96
		return array();
97
	}
98
99
	/**
100
	 * Generate the output for a field based on the additional_info() output
101
	 *
102
	 * @see GravityView_Admin_View_Item::additional_info()
103
	 * @param  boolean $html Display HTML output? If yes, output is wrapped in spans. If no, plaintext.
104
	 * @return string|null        If empty, return null. Otherwise, return output HTML/text.
105
	 */
106
	protected function get_item_info( $html = true ) {
107
108
		$output           = NULL;
109
		$field_info_items = $this->additional_info();
110
111
		/**
112
		 * @filter `gravityview_admin_label_item_info` Tap in to modify the field information displayed next to an item
113
		 *
114
		 * @param array $field_info_items Additional information to display in a field
115
		 * @param GravityView_Admin_View_Field $this Field shown in the admin
116
		 */
117
		$field_info_items = apply_filters( 'gravityview_admin_label_item_info', $field_info_items, $this );
118
119
		if ( $html ) {
120
121
			foreach ( $field_info_items as $item ) {
122
123
				if( \GV\Utils::get( $item, 'hide_in_picker', false ) ) {
124
					continue;
125
				}
126
127
				$class = isset( $item['class'] ) ? sanitize_html_class( $item['class'] ) . ' description' : 'description';
128
				// Add the title in case the value's long, in which case, it'll be truncated by CSS.
129
				$output .= '<span class="' . $class . '">';
130
				$output .= esc_html( $item['value'] );
131
				$output .= '</span>';
132
			}
133
134
		} else {
135
136
			$values = wp_list_pluck( $field_info_items, 'value' );
137
138
			$output = esc_html( implode( "\n", $values ) );
139
140
		}
141
142
		return empty( $output ) ? NULL : $output;
143
	}
144
145
	/**
146
	 * Generate HTML for field or a widget modal
147
	 *
148
	 * @return string
149
	 */
150
	function getOutput() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

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

Loading history...
151
152
		$settings_title    = sprintf( __( 'Configure %s Settings', 'gravityview' ), esc_html( rgar( $this->item, 'label', ucfirst( $this->label_type ) ) ) );
153
		$delete_title      = sprintf( __( 'Remove %s', 'gravityview' ), ucfirst( $this->label_type ) );
154
		$single_link_title = __( 'This field links to the Single Entry', 'gravityview' );
155
		$visibility_title = __( 'This field has modified visibility', 'gravityview' );
156
157
		// $settings_html will just be hidden inputs if empty. Otherwise, it'll have an <ul>. Ugly hack, I know.
158
		// TODO: Un-hack this
159
		$hide_settings_link_class = ( empty( $this->item['settings_html'] ) || strpos( $this->item['settings_html'], '<!-- No Options -->' ) > 0 ) ? 'hide-if-js' : '';
160
		$settings_link      = sprintf( '<button class="gv-field-settings %2$s" title="%1$s" aria-label="%1$s"><span class="dashicons-admin-generic dashicons"></span></button>', esc_attr( $settings_title ), $hide_settings_link_class );
161
162
		// When a field label is empty, use the Field ID
163
		$label = empty( $this->title ) ? sprintf( _x( 'Field #%s (No Label)', 'Label in field picker for empty label', 'gravityview' ), $this->id ) : $this->title;
164
165
		// If there's a custom label, and show label is checked, use that as the field heading
166
		if ( ! empty( $this->settings['custom_label'] ) && ! empty( $this->settings['show_label'] ) ) {
167
			$label = $this->settings['custom_label'];
168
		} else if ( ! empty( $this->item['customLabel'] ) ) {
169
			$label = $this->item['customLabel'];
170
		}
171
		$label = esc_attr( $label );
172
173
		$field_icon = '';
174
175
		$form = ! empty( $this->form_id ) ? GVCommon::get_form( $this->form_id ) : false;
176
		$nonexistent_form_field = $form && $this->id && preg_match('/^\d+\.\d+$|^\d+$/', $this->id) && !gravityview_get_field($form, $this->id);
177
178
		if ( $this->item['icon'] && ! \GV\Utils::get( $this->item, 'parent' ) ) {
179
180
			$has_gf_icon = ( false !== strpos( $this->item['icon'], 'gform-icon' ) );
181
			$has_dashicon = ( false !== strpos( $this->item['icon'], 'dashicons' ) );
182
183
			if ( 0 === strpos( $this->item['icon'], 'data:' ) ) {
184
				// Inline icon SVG
185
				$field_icon = '<i class="dashicons background-icon" style="background-image: url(\'' . esc_attr( $this->item['icon'] ) . '\');"></i>';
186
			} elseif( $has_gf_icon && gravityview()->plugin->is_GF_25() ) {
187
				// Gravity Forms icon font
188
				$field_icon = '<i class="gform-icon ' . esc_attr( $this->item['icon'] ) . '"></i>';
189
			} elseif( $has_dashicon ) {
190
				// Dashicon; prefix with "dashicons"
191
				$field_icon = '<i class="dashicons ' . esc_attr( $this->item['icon'] ) . '"></i>';
192
			} else {
193
				// Not dashicon icon
194
				$field_icon = '<i class="' . esc_attr( $this->item['icon'] ) . '"></i>';
195
			}
196
197
			$field_icon = $field_icon . ' ';
198
		} elseif( \GV\Utils::get( $this->item, 'parent' ) ) {
199
			$field_icon = '<i class="gv-icon gv-icon-level-down"></i>' . ' ';
200
		}
201
202
		$output = '<button class="gv-add-field screen-reader-text">' . sprintf( esc_html__( 'Add "%s"', 'gravityview' ), $label ) . '</button>';
203
		$title = esc_attr( sprintf( __( 'Field: %s', 'gravityview' ), $label ) );
204
		if ( ! $nonexistent_form_field ) {
205
			$title .= "\n" . $this->get_item_info( false );
206
		} else {
207
			$output        = '';
208
			$title         = esc_attr( sprintf( __( 'Field: %s', 'gravityview' ), $label ) );
209
			$settings_link = sprintf( '<button disabled class="gv-field-settings %2$s" title="%1$s" aria-label="%1$s"><span class="dashicons-warning dashicons"></span></button>', esc_attr( __( 'Form field no longer exists.', 'gravityview' ) ), $hide_settings_link_class );
210
		}
211
212
		$output .= '<h5 class="selectable gfield field-id-' . esc_attr( $this->id ) . '">';
213
214
		$output .= '<span class="gv-field-controls">' . $settings_link . $this->get_indicator_icons() . '<button class="gv-remove-field" aria-label="' . esc_attr( $delete_title ) . '" title="' . esc_attr( $delete_title ) . '"><span class="dashicons-dismiss dashicons"></span></button></span>';
215
216
		$output .= '<span class="gv-field-label" data-original-title="' . esc_attr( $label ) . '" title="' . $title . '">' . $field_icon . '<span class="gv-field-label-text-container">' . $label . '</span></span>';
217
218
		// Displays only in the field/widget picker
219
		if ( ! $nonexistent_form_field && $field_info = $this->get_item_info() ) {
220
			$output .= '<span class="gv-field-info">' . $field_info . '</span>';
221
		}
222
223
		$output .= '</h5>';
224
225
		$container_class = ! empty( $this->item['parent'] ) ? ' gv-child-field' : '';
226
227
		$container_class .= $nonexistent_form_field ? ' gv-nonexistent-form-field' : '';
228
229
		$container_class .= empty( $this->settings['show_as_link'] ) ? '' : ' has-single-entry-link';
230
231
		$container_class .= empty( $this->settings['only_loggedin'] ) ? '' : ' has-custom-visibility';
232
233
		$data_form_id   = $form ? ' data-formid="' . esc_attr( $this->form_id ) . '"' : '';
234
235
		$data_parent_label = ! empty( $this->item['parent'] ) ? ' data-parent-label="' . esc_attr( $this->item['parent']['label'] ) . '"' : '';
236
237
		$output = '<div data-fieldid="' . esc_attr( $this->id ) . '" ' . $data_form_id . $data_parent_label . ' data-inputtype="' . esc_attr( $this->item['input_type'] ) . '" class="gv-fields' . $container_class . '">' . $output . $this->item['settings_html'] . '</div>';
238
239
		return $output;
240
	}
241
242
	/**
243
	 * Returns array of item icons used to represent field settings state
244
	 *
245
	 * Has `gravityview/admin/indicator_icons` filter for other components to modify displayed icons.
246
	 *
247
	 * @since 2.9.5
248
	 *
249
	 * @return string HTML output of icons
250
	 */
251
	private function get_indicator_icons() {
252
253
		$icons = array(
254
			'show_as_link' => array(
255
				'visible' => ( ! empty( $this->settings['show_as_link'] ) ),
256
				'title' => __( 'This field links to the Single Entry', 'gravityview' ),
257
				'css_class' => 'dashicons dashicons-media-default icon-link-to-single-entry',
258
			),
259
			'only_loggedin' => array(
260
				'visible' => ( \GV\Utils::get( $this->settings, 'only_loggedin' ) || isset( $this->settings['allow_edit_cap'] ) && 'read' !== $this->settings['allow_edit_cap'] ),
261
				'title' => __( 'This field has modified visibility', 'gravityview' ),
262
				'css_class' => 'dashicons dashicons-lock icon-custom-visibility',
263
			),
264
		);
265
266
		$output = '';
267
268
		/**
269
		 * @filter `gravityview/admin/indicator_icons` Modify the icon output to add additional indicator icons
270
		 * @internal This is currently internally used. Consider not relying on it until further notice :-)
271
		 * @param array $icons Array of icons to be shown, with `visible`, `title`, `css_class` keys.
272
		 * @param array $item_settings Settings for the current item (widget or field)
273
		 */
274
		$icons = (array) apply_filters( 'gravityview/admin/indicator_icons', $icons, $this->settings );
275
276
		foreach ( $icons as $icon ) {
277
278
			if ( empty( $icon['css_class'] ) || empty( $icon['title'] ) ) {
279
				continue;
280
			}
281
282
			$css_class = trim( $icon['css_class'] );
283
284
			if ( empty( $icon['visible'] ) ) {
285
				$css_class .= ' hide-if-js';
286
			}
287
288
			$output .= '<span class="' . gravityview_sanitize_html_class( $css_class ) . '" title="' . esc_attr( $icon['title'] ) . '"></span>';
289
		}
290
291
		return $output;
292
	}
293
294
}
295