53511b78 by Jeff Balicki

plugin clean up

Signed-off-by: Jeff <jeff@gotenzing.com>
1 parent c91a2ee3
Showing 817 changed files with 0 additions and 5062 deletions
1 <?php
2
3 if ( ! class_exists( 'acf_field_message' ) ) :
4
5 class acf_field_message extends acf_field {
6
7 public $show_in_rest = false;
8
9 /*
10 * __construct
11 *
12 * This function will setup the field type data
13 *
14 * @type function
15 * @date 5/03/2014
16 * @since 5.0.0
17 *
18 * @param n/a
19 * @return n/a
20 */
21
22 function initialize() {
23
24 // vars
25 $this->name = 'message';
26 $this->label = __( 'Message', 'acf' );
27 $this->category = 'layout';
28 $this->description = __( 'Used to display a message to editors alongside other fields. Useful for providing additional context or instructions around your fields.', 'acf' );
29 $this->preview_image = acf_get_url() . '/assets/images/field-type-previews/field-preview-message.png';
30 $this->defaults = array(
31 'message' => '',
32 'esc_html' => 0,
33 'new_lines' => 'wpautop',
34 );
35
36 }
37
38
39 /*
40 * render_field()
41 *
42 * Create the HTML interface for your field
43 *
44 * @param $field - an array holding all the field's data
45 *
46 * @type action
47 * @since 3.6
48 * @date 23/01/13
49 */
50
51 function render_field( $field ) {
52
53 // vars
54 $m = $field['message'];
55
56 // wptexturize (improves "quotes")
57 $m = wptexturize( $m );
58
59 // esc_html
60 if ( $field['esc_html'] ) {
61
62 $m = esc_html( $m );
63
64 }
65
66 // new lines
67 if ( $field['new_lines'] == 'wpautop' ) {
68
69 $m = wpautop( $m );
70
71 } elseif ( $field['new_lines'] == 'br' ) {
72
73 $m = nl2br( $m );
74
75 }
76
77 // return
78 echo acf_esc_html( $m );
79
80 }
81
82
83 /*
84 * render_field_settings()
85 *
86 * Create extra options for your field. This is rendered when editing a field.
87 * The value of $field['name'] can be used (like bellow) to save extra data to the $field
88 *
89 * @param $field - an array holding all the field's data
90 *
91 * @type action
92 * @since 3.6
93 * @date 23/01/13
94 */
95 function render_field_settings( $field ) {
96 acf_render_field_setting(
97 $field,
98 array(
99 'label' => __( 'Message', 'acf' ),
100 'instructions' => '',
101 'type' => 'textarea',
102 'name' => 'message',
103 )
104 );
105
106 acf_render_field_setting(
107 $field,
108 array(
109 'label' => __( 'New Lines', 'acf' ),
110 'instructions' => __( 'Controls how new lines are rendered', 'acf' ),
111 'type' => 'select',
112 'name' => 'new_lines',
113 'choices' => array(
114 'wpautop' => __( 'Automatically add paragraphs', 'acf' ),
115 'br' => __( 'Automatically add &lt;br&gt;', 'acf' ),
116 '' => __( 'No Formatting', 'acf' ),
117 ),
118 )
119 );
120
121 acf_render_field_setting(
122 $field,
123 array(
124 'label' => __( 'Escape HTML', 'acf' ),
125 'instructions' => __( 'Allow HTML markup to display as visible text instead of rendering', 'acf' ),
126 'name' => 'esc_html',
127 'type' => 'true_false',
128 'ui' => 1,
129 )
130 );
131 }
132
133 /*
134 * translate_field
135 *
136 * This function will translate field settings
137 *
138 * @type function
139 * @date 8/03/2016
140 * @since 5.3.2
141 *
142 * @param $field (array)
143 * @return $field
144 */
145
146 function translate_field( $field ) {
147
148 // translate
149 $field['message'] = acf_translate( $field['message'] );
150
151 // return
152 return $field;
153
154 }
155
156
157 /*
158 * load_field()
159 *
160 * This filter is appied to the $field after it is loaded from the database
161 *
162 * @type filter
163 * @since 3.6
164 * @date 23/01/13
165 *
166 * @param $field - the field array holding all the field options
167 *
168 * @return $field - the field array holding all the field options
169 */
170 function load_field( $field ) {
171
172 // remove name to avoid caching issue
173 $field['name'] = '';
174
175 // remove instructions
176 $field['instructions'] = '';
177
178 // remove required to avoid JS issues
179 $field['required'] = 0;
180
181 // set value other than 'null' to avoid ACF loading / caching issue
182 $field['value'] = false;
183
184 // return
185 return $field;
186 }
187
188 }
189
190
191 // initialize
192 acf_register_field_type( 'acf_field_message' );
193
194 endif; // class_exists check
195
196
1 <?php
2
3 if ( ! class_exists( 'acf_field_separator' ) ) :
4
5 class acf_field_separator extends acf_field {
6
7
8 /*
9 * __construct
10 *
11 * This function will setup the field type data
12 *
13 * @type function
14 * @date 5/03/2014
15 * @since 5.0.0
16 *
17 * @param n/a
18 * @return n/a
19 */
20
21 function initialize() {
22
23 // vars
24 $this->name = 'separator';
25 $this->label = __( 'Separator', 'acf' );
26 $this->preview_image = acf_get_url() . '/assets/images/field-type-previews/field-preview-separator.png';
27 $this->category = 'layout';
28
29 }
30
31
32 /*
33 * render_field()
34 *
35 * Create the HTML interface for your field
36 *
37 * @param $field - an array holding all the field's data
38 *
39 * @type action
40 * @since 3.6
41 * @date 23/01/13
42 */
43
44 function render_field( $field ) {
45
46 /* do nothing */
47
48 }
49
50
51 /*
52 * load_field()
53 *
54 * This filter is appied to the $field after it is loaded from the database
55 *
56 * @type filter
57 * @since 3.6
58 * @date 23/01/13
59 *
60 * @param $field - the field array holding all the field options
61 *
62 * @return $field - the field array holding all the field options
63 */
64
65 function load_field( $field ) {
66
67 // remove name to avoid caching issue
68 $field['name'] = '';
69
70 // remove required to avoid JS issues
71 $field['required'] = 0;
72
73 // set value other than 'null' to avoid ACF loading / caching issue
74 $field['value'] = false;
75
76 // return
77 return $field;
78
79 }
80
81 }
82
83
84 // initialize
85 acf_register_field_type( 'acf_field_separator' );
86
87 endif; // class_exists check
88
89
1 <?php
2
3 if ( ! class_exists( 'acf_field_tab' ) ) :
4
5 class acf_field_tab extends acf_field {
6
7 public $show_in_rest = false;
8
9 /*
10 * __construct
11 *
12 * This function will setup the field type data
13 *
14 * @type function
15 * @date 5/03/2014
16 * @since 5.0.0
17 *
18 * @param n/a
19 * @return n/a
20 */
21
22 function initialize() {
23
24 // vars
25 $this->name = 'tab';
26 $this->label = __( 'Tab', 'acf' );
27 $this->category = 'layout';
28 $this->description = __( 'Allows you to group fields into tabbed sections in the edit screen. Useful for keeping fields organized and structured.', 'acf' );
29 $this->preview_image = acf_get_url() . '/assets/images/field-type-previews/field-preview-tabs.png';
30 $this->doc_url = acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/resources/tab/', 'docs', 'field-type-selection' );
31 $this->defaults = array(
32 'placement' => 'top',
33 'endpoint' => 0, // added in 5.2.8
34 );
35
36 }
37
38
39 /*
40 * render_field()
41 *
42 * Create the HTML interface for your field
43 *
44 * @param $field - an array holding all the field's data
45 *
46 * @type action
47 * @since 3.6
48 * @date 23/01/13
49 */
50
51 function render_field( $field ) {
52
53 // vars
54 $atts = array(
55 'href' => '',
56 'class' => 'acf-tab-button',
57 'data-placement' => $field['placement'],
58 'data-endpoint' => $field['endpoint'],
59 'data-key' => $field['key'],
60 );
61
62 if ( isset( $field['settings-type'] ) ) {
63 $atts['class'] .= ' acf-settings-type-' . acf_slugify( $field['settings-type'] );
64 }
65
66 ?>
67 <a <?php echo acf_esc_attrs( $atts ); ?>><?php echo acf_esc_html( $field['label'] ); ?></a>
68 <?php
69
70 }
71
72
73
74 /*
75 * render_field_settings()
76 *
77 * Create extra options for your field. This is rendered when editing a field.
78 * The value of $field['name'] can be used (like bellow) to save extra data to the $field
79 *
80 * @param $field - an array holding all the field's data
81 *
82 * @type action
83 * @since 3.6
84 * @date 23/01/13
85 */
86
87 function render_field_settings( $field ) {
88
89 /*
90 // message
91 $message = '';
92 $message .= '<p>' . __( 'Use "Tab Fields" to better organize your edit screen by grouping fields together.', 'acf') . '</p>';
93 $message .= '<p>' . __( 'All fields following this "tab field" (or until another "tab field" is defined) will be grouped together using this field\'s label as the tab heading.','acf') . '</p>';
94
95
96 // default_value
97 acf_render_field_setting( $field, array(
98 'label' => __('Instructions','acf'),
99 'instructions' => '',
100 'name' => 'notes',
101 'type' => 'message',
102 'message' => $message,
103 ));
104 */
105
106 // preview_size
107 acf_render_field_setting(
108 $field,
109 array(
110 'label' => __( 'Placement', 'acf' ),
111 'type' => 'select',
112 'name' => 'placement',
113 'choices' => array(
114 'top' => __( 'Top aligned', 'acf' ),
115 'left' => __( 'Left aligned', 'acf' ),
116 ),
117 )
118 );
119
120 // endpoint
121 acf_render_field_setting(
122 $field,
123 array(
124 'label' => __( 'New Tab Group', 'acf' ),
125 'instructions' => __( 'Start a new group of tabs at this tab.', 'acf' ),
126 'name' => 'endpoint',
127 'type' => 'true_false',
128 'ui' => 1,
129 )
130 );
131
132 }
133
134
135 /*
136 * load_field()
137 *
138 * This filter is appied to the $field after it is loaded from the database
139 *
140 * @type filter
141 * @since 3.6
142 * @date 23/01/13
143 *
144 * @param $field - the field array holding all the field options
145 *
146 * @return $field - the field array holding all the field options
147 */
148 function load_field( $field ) {
149
150 // remove name to avoid caching issue
151 $field['name'] = '';
152
153 // remove instructions
154 $field['instructions'] = '';
155
156 // remove required to avoid JS issues
157 $field['required'] = 0;
158
159 // set value other than 'null' to avoid ACF loading / caching issue
160 $field['value'] = false;
161
162 // return
163 return $field;
164
165 }
166
167 }
168
169
170 // initialize
171 acf_register_field_type( 'acf_field_tab' );
172
173 endif; // class_exists check
174
175 ?>
1 <?php
2
3 if ( ! class_exists( 'acf_field_text' ) ) :
4
5 class acf_field_text extends acf_field {
6
7
8 /*
9 * initialize
10 *
11 * This function will setup the field type data
12 *
13 * @type function
14 * @date 5/03/2014
15 * @since 5.0.0
16 *
17 * @param n/a
18 * @return n/a
19 */
20
21 function initialize() {
22
23 // vars
24 $this->name = 'text';
25 $this->label = __( 'Text', 'acf' );
26 $this->description = __( 'A basic text input, useful for storing single string values.', 'acf' );
27 $this->preview_image = acf_get_url() . '/assets/images/field-type-previews/field-preview-text.png';
28 $this->doc_url = acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/resources/text/', 'docs', 'field-type-selection' );
29 $this->defaults = array(
30 'default_value' => '',
31 'maxlength' => '',
32 'placeholder' => '',
33 'prepend' => '',
34 'append' => '',
35 );
36
37 }
38
39
40 /*
41 * render_field()
42 *
43 * Create the HTML interface for your field
44 *
45 * @param $field - an array holding all the field's data
46 *
47 * @type action
48 * @since 3.6
49 * @date 23/01/13
50 */
51
52 function render_field( $field ) {
53 $html = '';
54
55 // Prepend text.
56 if ( $field['prepend'] !== '' ) {
57 $field['class'] .= ' acf-is-prepended';
58 $html .= '<div class="acf-input-prepend">' . acf_esc_html( $field['prepend'] ) . '</div>';
59 }
60
61 // Append text.
62 if ( $field['append'] !== '' ) {
63 $field['class'] .= ' acf-is-appended';
64 $html .= '<div class="acf-input-append">' . acf_esc_html( $field['append'] ) . '</div>';
65 }
66
67 // Input.
68 $input_attrs = array();
69 foreach ( array( 'type', 'id', 'class', 'name', 'value', 'placeholder', 'maxlength', 'pattern', 'readonly', 'disabled', 'required' ) as $k ) {
70 if ( isset( $field[ $k ] ) ) {
71 $input_attrs[ $k ] = $field[ $k ];
72 }
73 }
74 $html .= '<div class="acf-input-wrap">' . acf_get_text_input( acf_filter_attrs( $input_attrs ) ) . '</div>';
75
76 // Display.
77 echo $html;
78 }
79
80
81 /*
82 * render_field_settings()
83 *
84 * Create extra options for your field. This is rendered when editing a field.
85 * The value of $field['name'] can be used (like bellow) to save extra data to the $field
86 *
87 * @param $field - an array holding all the field's data
88 *
89 * @type action
90 * @since 3.6
91 * @date 23/01/13
92 */
93 function render_field_settings( $field ) {
94 acf_render_field_setting(
95 $field,
96 array(
97 'label' => __( 'Default Value', 'acf' ),
98 'instructions' => __( 'Appears when creating a new post', 'acf' ),
99 'type' => 'text',
100 'name' => 'default_value',
101 )
102 );
103 }
104
105 /**
106 * Renders the field settings used in the "Validation" tab.
107 *
108 * @since 6.0
109 *
110 * @param array $field The field settings array.
111 * @return void
112 */
113 function render_field_validation_settings( $field ) {
114 acf_render_field_setting(
115 $field,
116 array(
117 'label' => __( 'Character Limit', 'acf' ),
118 'instructions' => __( 'Leave blank for no limit', 'acf' ),
119 'type' => 'number',
120 'name' => 'maxlength',
121 )
122 );
123 }
124
125 /**
126 * Renders the field settings used in the "Presentation" tab.
127 *
128 * @since 6.0
129 *
130 * @param array $field The field settings array.
131 * @return void
132 */
133 function render_field_presentation_settings( $field ) {
134 acf_render_field_setting(
135 $field,
136 array(
137 'label' => __( 'Placeholder Text', 'acf' ),
138 'instructions' => __( 'Appears within the input', 'acf' ),
139 'type' => 'text',
140 'name' => 'placeholder',
141 )
142 );
143
144 acf_render_field_setting(
145 $field,
146 array(
147 'label' => __( 'Prepend', 'acf' ),
148 'instructions' => __( 'Appears before the input', 'acf' ),
149 'type' => 'text',
150 'name' => 'prepend',
151 )
152 );
153
154 acf_render_field_setting(
155 $field,
156 array(
157 'label' => __( 'Append', 'acf' ),
158 'instructions' => __( 'Appears after the input', 'acf' ),
159 'type' => 'text',
160 'name' => 'append',
161 )
162 );
163 }
164
165 /**
166 * validate_value
167 *
168 * Validates a field's value.
169 *
170 * @date 29/1/19
171 * @since 5.7.11
172 *
173 * @param (bool|string) Whether the value is vaid or not.
174 * @param mixed $value The field value.
175 * @param array $field The field array.
176 * @param string $input The HTML input name.
177 * @return (bool|string)
178 */
179 function validate_value( $valid, $value, $field, $input ) {
180
181 // Check maxlength
182 if ( $field['maxlength'] && ( acf_strlen( $value ) > $field['maxlength'] ) ) {
183 return sprintf( __( 'Value must not exceed %d characters', 'acf' ), $field['maxlength'] );
184 }
185
186 // Return.
187 return $valid;
188 }
189
190 /**
191 * Return the schema array for the REST API.
192 *
193 * @param array $field
194 * @return array
195 */
196 function get_rest_schema( array $field ) {
197 $schema = parent::get_rest_schema( $field );
198
199 if ( ! empty( $field['maxlength'] ) ) {
200 $schema['maxLength'] = (int) $field['maxlength'];
201 }
202
203 return $schema;
204 }
205 }
206
207
208 // initialize
209 acf_register_field_type( 'acf_field_text' );
210
211 endif; // class_exists check
212
213
1 <?php
2
3 if ( ! class_exists( 'acf_field_textarea' ) ) :
4
5 class acf_field_textarea extends acf_field {
6
7
8 /*
9 * initialize
10 *
11 * This function will setup the field type data
12 *
13 * @type function
14 * @date 5/03/2014
15 * @since 5.0.0
16 *
17 * @param n/a
18 * @return n/a
19 */
20
21 function initialize() {
22
23 // vars
24 $this->name = 'textarea';
25 $this->label = __( 'Text Area', 'acf' );
26 $this->description = __( 'A basic textarea input for storing paragraphs of text.', 'acf' );
27 $this->preview_image = acf_get_url() . '/assets/images/field-type-previews/field-preview-textarea.png';
28 $this->doc_url = acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/resources/textarea/', 'docs', 'field-type-selection' );
29 $this->defaults = array(
30 'default_value' => '',
31 'new_lines' => '',
32 'maxlength' => '',
33 'placeholder' => '',
34 'rows' => '',
35 );
36
37 }
38
39
40 /*
41 * render_field()
42 *
43 * Create the HTML interface for your field
44 *
45 * @param $field - an array holding all the field's data
46 *
47 * @type action
48 * @since 3.6
49 * @date 23/01/13
50 */
51
52 function render_field( $field ) {
53
54 // vars
55 $atts = array();
56 $keys = array( 'id', 'class', 'name', 'value', 'placeholder', 'rows', 'maxlength' );
57 $keys2 = array( 'readonly', 'disabled', 'required' );
58
59 // rows
60 if ( ! $field['rows'] ) {
61 $field['rows'] = 8;
62 }
63
64 // atts (value="123")
65 foreach ( $keys as $k ) {
66 if ( isset( $field[ $k ] ) ) {
67 $atts[ $k ] = $field[ $k ];
68 }
69 }
70
71 // atts2 (disabled="disabled")
72 foreach ( $keys2 as $k ) {
73 if ( ! empty( $field[ $k ] ) ) {
74 $atts[ $k ] = $k;
75 }
76 }
77
78 // remove empty atts
79 $atts = acf_clean_atts( $atts );
80
81 // return
82 acf_textarea_input( $atts );
83
84 }
85
86
87 /*
88 * render_field_settings()
89 *
90 * Create extra options for your field. This is rendered when editing a field.
91 * The value of $field['name'] can be used (like bellow) to save extra data to the $field
92 *
93 * @param $field - an array holding all the field's data
94 *
95 * @type action
96 * @since 3.6
97 * @date 23/01/13
98 */
99 function render_field_settings( $field ) {
100 acf_render_field_setting(
101 $field,
102 array(
103 'label' => __( 'Default Value', 'acf' ),
104 'instructions' => __( 'Appears when creating a new post', 'acf' ),
105 'type' => 'textarea',
106 'name' => 'default_value',
107 )
108 );
109 }
110
111 /**
112 * Renders the field settings used in the "Validation" tab.
113 *
114 * @since 6.0
115 *
116 * @param array $field The field settings array.
117 * @return void
118 */
119 function render_field_validation_settings( $field ) {
120 acf_render_field_setting(
121 $field,
122 array(
123 'label' => __( 'Character Limit', 'acf' ),
124 'instructions' => __( 'Leave blank for no limit', 'acf' ),
125 'type' => 'number',
126 'name' => 'maxlength',
127 )
128 );
129 }
130
131 /**
132 * Renders the field settings used in the "Presentation" tab.
133 *
134 * @since 6.0
135 *
136 * @param array $field The field settings array.
137 * @return void
138 */
139 function render_field_presentation_settings( $field ) {
140
141 acf_render_field_setting(
142 $field,
143 array(
144 'label' => __( 'Rows', 'acf' ),
145 'instructions' => __( 'Sets the textarea height', 'acf' ),
146 'type' => 'number',
147 'name' => 'rows',
148 'placeholder' => 8,
149 )
150 );
151
152 acf_render_field_setting(
153 $field,
154 array(
155 'label' => __( 'Placeholder Text', 'acf' ),
156 'instructions' => __( 'Appears within the input', 'acf' ),
157 'type' => 'text',
158 'name' => 'placeholder',
159 )
160 );
161
162 acf_render_field_setting(
163 $field,
164 array(
165 'label' => __( 'New Lines', 'acf' ),
166 'instructions' => __( 'Controls how new lines are rendered', 'acf' ),
167 'type' => 'select',
168 'name' => 'new_lines',
169 'choices' => array(
170 'wpautop' => __( 'Automatically add paragraphs', 'acf' ),
171 'br' => __( 'Automatically add &lt;br&gt;', 'acf' ),
172 '' => __( 'No Formatting', 'acf' ),
173 ),
174 )
175 );
176 }
177
178 /*
179 * format_value()
180 *
181 * This filter is applied to the $value after it is loaded from the db and before it is returned to the template
182 *
183 * @type filter
184 * @since 3.6
185 * @date 23/01/13
186 *
187 * @param $value (mixed) the value which was loaded from the database
188 * @param $post_id (mixed) the $post_id from which the value was loaded
189 * @param $field (array) the field array holding all the field options
190 *
191 * @return $value (mixed) the modified value
192 */
193
194 function format_value( $value, $post_id, $field ) {
195
196 // bail early if no value or not for template
197 if ( empty( $value ) || ! is_string( $value ) ) {
198
199 return $value;
200
201 }
202
203 // new lines
204 if ( $field['new_lines'] == 'wpautop' ) {
205
206 $value = wpautop( $value );
207
208 } elseif ( $field['new_lines'] == 'br' ) {
209
210 $value = nl2br( $value );
211
212 }
213
214 // return
215 return $value;
216 }
217
218 /**
219 * validate_value
220 *
221 * Validates a field's value.
222 *
223 * @date 29/1/19
224 * @since 5.7.11
225 *
226 * @param (bool|string) Whether the value is vaid or not.
227 * @param mixed $value The field value.
228 * @param array $field The field array.
229 * @param string $input The HTML input name.
230 * @return (bool|string)
231 */
232 function validate_value( $valid, $value, $field, $input ) {
233
234 // Check maxlength.
235 if ( $field['maxlength'] && ( acf_strlen( $value ) > $field['maxlength'] ) ) {
236 return sprintf( __( 'Value must not exceed %d characters', 'acf' ), $field['maxlength'] );
237 }
238
239 // Return.
240 return $valid;
241 }
242
243 /**
244 * Return the schema array for the REST API.
245 *
246 * @param array $field
247 * @return array
248 */
249 function get_rest_schema( array $field ) {
250 $schema = parent::get_rest_schema( $field );
251
252 if ( ! empty( $field['maxlength'] ) ) {
253 $schema['maxLength'] = (int) $field['maxlength'];
254 }
255
256 return $schema;
257 }
258 }
259
260
261 // initialize
262 acf_register_field_type( 'acf_field_textarea' );
263
264 endif; // class_exists check
265
266
1 <?php
2
3 if ( ! class_exists( 'acf_field_time_picker' ) ) :
4
5 class acf_field_time_picker extends acf_field {
6
7
8 /*
9 * __construct
10 *
11 * This function will setup the field type data
12 *
13 * @type function
14 * @date 5/03/2014
15 * @since 5.0.0
16 *
17 * @param n/a
18 * @return n/a
19 */
20
21 function initialize() {
22
23 // vars
24 $this->name = 'time_picker';
25 $this->label = __( 'Time Picker', 'acf' );
26 $this->category = 'advanced';
27 $this->description = __( 'An interactive UI for picking a time. The time format can be customized using the field settings.', 'acf' );
28 $this->preview_image = acf_get_url() . '/assets/images/field-type-previews/field-preview-time.png';
29 $this->doc_url = acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/resources/time-picker/', 'docs', 'field-type-selection' );
30 $this->defaults = array(
31 'display_format' => 'g:i a',
32 'return_format' => 'g:i a',
33 );
34
35 }
36
37
38 /*
39 * render_field()
40 *
41 * Create the HTML interface for your field
42 *
43 * @param $field - an array holding all the field's data
44 *
45 * @type action
46 * @since 3.6
47 * @date 23/01/13
48 */
49
50 function render_field( $field ) {
51
52 // Set value.
53 $display_value = '';
54
55 if ( $field['value'] ) {
56 $display_value = acf_format_date( $field['value'], $field['display_format'] );
57 }
58
59 // Elements.
60 $div = array(
61 'class' => 'acf-time-picker acf-input-wrap',
62 'data-time_format' => acf_convert_time_to_js( $field['display_format'] ),
63 );
64 $hidden_input = array(
65 'id' => $field['id'],
66 'class' => 'input-alt',
67 'type' => 'hidden',
68 'name' => $field['name'],
69 'value' => $field['value'],
70 );
71 $text_input = array(
72 'class' => $field['class'] . ' input',
73 'type' => 'text',
74 'value' => $display_value,
75 );
76 foreach ( array( 'readonly', 'disabled' ) as $k ) {
77 if ( ! empty( $field[ $k ] ) ) {
78 $hidden_input[ $k ] = $k;
79 $text_input[ $k ] = $k;
80 }
81 }
82
83 // Output.
84 ?>
85 <div <?php echo acf_esc_attrs( $div ); ?>>
86 <?php acf_hidden_input( $hidden_input ); ?>
87 <?php acf_text_input( $text_input ); ?>
88 </div>
89 <?php
90
91 }
92
93
94 /*
95 * render_field_settings()
96 *
97 * Create extra options for your field. This is rendered when editing a field.
98 * The value of $field['name'] can be used (like bellow) to save extra data to the $field
99 *
100 * @type action
101 * @since 3.6
102 * @date 23/01/13
103 *
104 * @param $field - an array holding all the field's data
105 */
106 function render_field_settings( $field ) {
107 $g_i_a = date_i18n( 'g:i a' );
108 $H_i_s = date_i18n( 'H:i:s' );
109
110 echo '<div class="acf-field-settings-split">';
111
112 acf_render_field_setting(
113 $field,
114 array(
115 'label' => __( 'Display Format', 'acf' ),
116 'hint' => __( 'The format displayed when editing a post', 'acf' ),
117 'type' => 'radio',
118 'name' => 'display_format',
119 'other_choice' => 1,
120 'choices' => array(
121 'g:i a' => '<span>' . $g_i_a . '</span><code>g:i a</code>',
122 'H:i:s' => '<span>' . $H_i_s . '</span><code>H:i:s</code>',
123 'other' => '<span>' . __( 'Custom:', 'acf' ) . '</span>',
124 ),
125 )
126 );
127
128 acf_render_field_setting(
129 $field,
130 array(
131 'label' => __( 'Return Format', 'acf' ),
132 'hint' => __( 'The format returned via template functions', 'acf' ),
133 'type' => 'radio',
134 'name' => 'return_format',
135 'other_choice' => 1,
136 'choices' => array(
137 'g:i a' => '<span>' . $g_i_a . '</span><code>g:i a</code>',
138 'H:i:s' => '<span>' . $H_i_s . '</span><code>H:i:s</code>',
139 'other' => '<span>' . __( 'Custom:', 'acf' ) . '</span>',
140 ),
141 )
142 );
143
144 echo '</div>';
145 }
146
147 /*
148 * format_value()
149 *
150 * This filter is appied to the $value after it is loaded from the db and before it is returned to the template
151 *
152 * @type filter
153 * @since 3.6
154 * @date 23/01/13
155 *
156 * @param $value (mixed) the value which was loaded from the database
157 * @param $post_id (mixed) the $post_id from which the value was loaded
158 * @param $field (array) the field array holding all the field options
159 *
160 * @return $value (mixed) the modified value
161 */
162
163 function format_value( $value, $post_id, $field ) {
164
165 return acf_format_date( $value, $field['return_format'] );
166
167 }
168
169 /**
170 * This filter is applied to the $field after it is loaded from the database
171 * and ensures the return and display values are set.
172 *
173 * @type filter
174 * @since 5.11.0
175 * @date 28/09/21
176 *
177 * @param array $field The field array holding all the field options.
178 *
179 * @return array
180 */
181 function load_field( $field ) {
182 if ( empty( $field['display_format'] ) ) {
183 $field['display_format'] = $this->defaults['display_format'];
184 }
185
186 if ( empty( $field['return_format'] ) ) {
187 $field['return_format'] = $this->defaults['return_format'];
188 }
189
190 return $field;
191 }
192
193 /**
194 * Return the schema array for the REST API.
195 *
196 * @param array $field
197 * @return array
198 */
199 public function get_rest_schema( array $field ) {
200 return array(
201 'type' => array( 'string', 'null' ),
202 'description' => 'A `H:i:s` formatted time string.',
203 'required' => ! empty( $field['required'] ),
204 );
205 }
206 }
207
208
209 // initialize
210 acf_register_field_type( 'acf_field_time_picker' );
211
212 endif; // class_exists check
213
214 ?>
1 <?php
2
3 if ( ! class_exists( 'acf_field_url' ) ) :
4
5 class acf_field_url extends acf_field {
6
7
8 /*
9 * initialize
10 *
11 * This function will setup the field type data
12 *
13 * @type function
14 * @date 5/03/2014
15 * @since 5.0.0
16 *
17 * @param n/a
18 * @return n/a
19 */
20
21 function initialize() {
22
23 // vars
24 $this->name = 'url';
25 $this->label = __( 'URL', 'acf' );
26 $this->description = __( 'A text input specifically designed for storing web addresses.', 'acf' );
27 $this->preview_image = acf_get_url() . '/assets/images/field-type-previews/field-preview-url.png';
28 $this->doc_url = acf_add_url_utm_tags( 'https://www.advancedcustomfields.com/resources/url/', 'docs', 'field-type-selection' );
29 $this->defaults = array(
30 'default_value' => '',
31 'placeholder' => '',
32 );
33
34 }
35
36
37 /*
38 * render_field()
39 *
40 * Create the HTML interface for your field
41 *
42 * @param $field - an array holding all the field's data
43 *
44 * @type action
45 * @since 3.6
46 * @date 23/01/13
47 */
48
49 function render_field( $field ) {
50
51 // vars
52 $atts = array();
53 $keys = array( 'type', 'id', 'class', 'name', 'value', 'placeholder', 'pattern' );
54 $keys2 = array( 'readonly', 'disabled', 'required' );
55 $html = '';
56
57 // atts (value="123")
58 foreach ( $keys as $k ) {
59 if ( isset( $field[ $k ] ) ) {
60 $atts[ $k ] = $field[ $k ];
61 }
62 }
63
64 // atts2 (disabled="disabled")
65 foreach ( $keys2 as $k ) {
66 if ( ! empty( $field[ $k ] ) ) {
67 $atts[ $k ] = $k;
68 }
69 }
70
71 // remove empty atts
72 $atts = acf_clean_atts( $atts );
73
74 // render
75 $html .= '<div class="acf-input-wrap acf-url">';
76 $html .= '<i class="acf-icon -globe -small"></i>' . acf_get_text_input( $atts );
77 $html .= '</div>';
78
79 // return
80 echo $html;
81
82 }
83
84
85 /*
86 * render_field_settings()
87 *
88 * Create extra options for your field. This is rendered when editing a field.
89 * The value of $field['name'] can be used (like bellow) to save extra data to the $field
90 *
91 * @type action
92 * @since 3.6
93 * @date 23/01/13
94 *
95 * @param $field - an array holding all the field's data
96 */
97 function render_field_settings( $field ) {
98 acf_render_field_setting(
99 $field,
100 array(
101 'label' => __( 'Default Value', 'acf' ),
102 'instructions' => __( 'Appears when creating a new post', 'acf' ),
103 'type' => 'text',
104 'name' => 'default_value',
105 )
106 );
107 }
108
109 /**
110 * Renders the field settings used in the "Presentation" tab.
111 *
112 * @since 6.0
113 *
114 * @param array $field The field settings array.
115 * @return void
116 */
117 function render_field_presentation_settings( $field ) {
118 acf_render_field_setting(
119 $field,
120 array(
121 'label' => __( 'Placeholder Text', 'acf' ),
122 'instructions' => __( 'Appears within the input', 'acf' ),
123 'type' => 'text',
124 'name' => 'placeholder',
125 )
126 );
127 }
128
129
130 /*
131 * validate_value
132 *
133 * description
134 *
135 * @type function
136 * @date 11/02/2014
137 * @since 5.0.0
138 *
139 * @param $post_id (int)
140 * @return $post_id (int)
141 */
142
143 function validate_value( $valid, $value, $field, $input ) {
144
145 // bail early if empty
146 if ( empty( $value ) ) {
147
148 return $valid;
149
150 }
151
152 if ( strpos( $value, '://' ) !== false ) {
153
154 // url
155
156 } elseif ( strpos( $value, '//' ) === 0 ) {
157
158 // protocol relative url
159
160 } else {
161
162 $valid = __( 'Value must be a valid URL', 'acf' );
163
164 }
165
166 // return
167 return $valid;
168
169 }
170
171 /**
172 * Return the schema array for the REST API.
173 *
174 * @param array $field
175 * @return array
176 */
177 public function get_rest_schema( array $field ) {
178 $schema = parent::get_rest_schema( $field );
179 $schema['format'] = 'uri';
180
181 return $schema;
182 }
183
184 }
185
186
187 // initialize
188 acf_register_field_type( 'acf_field_url' );
189
190 endif; // class_exists check
191
192
1 <?php
2
3 /*
4 * ACF Attachment Form Class
5 *
6 * All the logic for adding fields to attachments
7 *
8 * @class acf_form_attachment
9 * @package ACF
10 * @subpackage Forms
11 */
12
13 if ( ! class_exists( 'acf_form_attachment' ) ) :
14
15 class acf_form_attachment {
16
17 /*
18 * __construct
19 *
20 * This function will setup the class functionality
21 *
22 * @type function
23 * @date 5/03/2014
24 * @since 5.0.0
25 *
26 * @param n/a
27 * @return n/a
28 */
29
30 function __construct() {
31
32 // actions
33 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
34
35 // render
36 add_filter( 'attachment_fields_to_edit', array( $this, 'edit_attachment' ), 10, 2 );
37
38 // save
39 add_filter( 'attachment_fields_to_save', array( $this, 'save_attachment' ), 10, 2 );
40
41 }
42
43
44 /*
45 * admin_enqueue_scripts
46 *
47 * This action is run after post query but before any admin script / head actions.
48 * It is a good place to register all actions.
49 *
50 * @type action (admin_enqueue_scripts)
51 * @date 26/01/13
52 * @since 3.6.0
53 *
54 * @param N/A
55 * @return N/A
56 */
57
58 function admin_enqueue_scripts() {
59
60 // bail early if not valid screen
61 if ( ! acf_is_screen( array( 'attachment', 'upload' ) ) ) {
62 return;
63 }
64
65 // load acf scripts
66 acf_enqueue_scripts(
67 array(
68 'uploader' => true,
69 )
70 );
71
72 // actions
73 if ( acf_is_screen( 'upload' ) ) {
74 add_action( 'admin_footer', array( $this, 'admin_footer' ), 0 );
75 }
76 }
77
78
79 /*
80 * admin_footer
81 *
82 * This function will add acf_form_data to the WP 4.0 attachment grid
83 *
84 * @type action (admin_footer)
85 * @date 11/09/2014
86 * @since 5.0.0
87 *
88 * @param n/a
89 * @return n/a
90 */
91
92 function admin_footer() {
93
94 // render post data
95 acf_form_data(
96 array(
97 'screen' => 'attachment',
98 'post_id' => 0,
99 )
100 );
101
102 ?>
103 <script type="text/javascript">
104
105 // WP saves attachment on any input change, so unload is not needed
106 acf.unload.active = 0;
107
108 </script>
109 <?php
110
111 }
112
113
114 /*
115 * edit_attachment
116 *
117 * description
118 *
119 * @type function
120 * @date 8/10/13
121 * @since 5.0.0
122 *
123 * @param $post_id (int)
124 * @return $post_id (int)
125 */
126
127 function edit_attachment( $form_fields, $post ) {
128
129 // vars
130 $is_page = acf_is_screen( 'attachment' );
131 $post_id = $post->ID;
132 $el = 'tr';
133
134 // get field groups
135 $field_groups = acf_get_field_groups(
136 array(
137 'attachment_id' => $post_id,
138 'attachment' => $post_id, // Leave for backwards compatibility
139 )
140 );
141
142 // render
143 if ( ! empty( $field_groups ) ) {
144
145 // get acf_form_data
146 ob_start();
147
148 acf_form_data(
149 array(
150 'screen' => 'attachment',
151 'post_id' => $post_id,
152 )
153 );
154
155 // open
156 echo '</td></tr>';
157
158 // loop
159 foreach ( $field_groups as $field_group ) {
160
161 // load fields
162 $fields = acf_get_fields( $field_group );
163
164 // override instruction placement for modal
165 if ( ! $is_page ) {
166
167 $field_group['instruction_placement'] = 'field';
168 }
169
170 // render
171 acf_render_fields( $fields, $post_id, $el, $field_group['instruction_placement'] );
172
173 }
174
175 // close
176 echo '<tr class="compat-field-acf-blank"><td>';
177
178 $html = ob_get_contents();
179
180 ob_end_clean();
181
182 $form_fields['acf-form-data'] = array(
183 'label' => '',
184 'input' => 'html',
185 'html' => $html,
186 );
187
188 }
189
190 // return
191 return $form_fields;
192
193 }
194
195
196 /*
197 * save_attachment
198 *
199 * description
200 *
201 * @type function
202 * @date 8/10/13
203 * @since 5.0.0
204 *
205 * @param $post_id (int)
206 * @return $post_id (int)
207 */
208
209 function save_attachment( $post, $attachment ) {
210
211 // bail early if not valid nonce
212 if ( ! acf_verify_nonce( 'attachment' ) ) {
213 return $post;
214 }
215
216 // bypass validation for ajax
217 if ( acf_is_ajax( 'save-attachment-compat' ) ) {
218 acf_save_post( $post['ID'] );
219
220 // validate and save
221 } elseif ( acf_validate_save_post( true ) ) {
222 acf_save_post( $post['ID'] );
223 }
224
225 // return
226 return $post;
227 }
228
229
230 }
231
232 new acf_form_attachment();
233
234 endif;
235
236 ?>
1 <?php
2
3 /*
4 * ACF Comment Form Class
5 *
6 * All the logic for adding fields to comments
7 *
8 * @class acf_form_comment
9 * @package ACF
10 * @subpackage Forms
11 */
12
13 if ( ! class_exists( 'acf_form_comment' ) ) :
14
15 class acf_form_comment {
16
17
18 /*
19 * __construct
20 *
21 * This function will setup the class functionality
22 *
23 * @type function
24 * @date 5/03/2014
25 * @since 5.0.0
26 *
27 * @param n/a
28 * @return n/a
29 */
30
31 function __construct() {
32
33 // actions
34 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
35
36 // render
37 add_filter( 'comment_form_field_comment', array( $this, 'comment_form_field_comment' ), 999, 1 );
38
39 // add_action( 'comment_form_logged_in_after', array( $this, 'add_comment') );
40 // add_action( 'comment_form', array( $this, 'add_comment') );
41
42 // save
43 add_action( 'edit_comment', array( $this, 'save_comment' ), 10, 1 );
44 add_action( 'comment_post', array( $this, 'save_comment' ), 10, 1 );
45
46 }
47
48
49 /*
50 * validate_page
51 *
52 * This function will check if the current page is for a post/page edit form
53 *
54 * @type function
55 * @date 23/06/12
56 * @since 3.1.8
57 *
58 * @param n/a
59 * @return (boolean)
60 */
61
62 function validate_page() {
63
64 // global
65 global $pagenow;
66
67 // validate page
68 if ( $pagenow == 'comment.php' ) {
69
70 return true;
71
72 }
73
74 // return
75 return false;
76 }
77
78
79 /*
80 * admin_enqueue_scripts
81 *
82 * This action is run after post query but before any admin script / head actions.
83 * It is a good place to register all actions.
84 *
85 * @type action (admin_enqueue_scripts)
86 * @date 26/01/13
87 * @since 3.6.0
88 *
89 * @param n/a
90 * @return n/a
91 */
92
93 function admin_enqueue_scripts() {
94
95 // validate page
96 if ( ! $this->validate_page() ) {
97
98 return;
99
100 }
101
102 // load acf scripts
103 acf_enqueue_scripts();
104
105 // actions
106 add_action( 'admin_footer', array( $this, 'admin_footer' ), 10, 1 );
107 add_action( 'add_meta_boxes_comment', array( $this, 'edit_comment' ), 10, 1 );
108
109 }
110
111
112 /*
113 * edit_comment
114 *
115 * This function is run on the admin comment.php page and will render the ACF fields within custom metaboxes to look native
116 *
117 * @type function
118 * @date 19/10/13
119 * @since 5.0.0
120 *
121 * @param $comment (object)
122 * @return n/a
123 */
124
125 function edit_comment( $comment ) {
126
127 // vars
128 $post_id = "comment_{$comment->comment_ID}";
129
130 // get field groups
131 $field_groups = acf_get_field_groups(
132 array(
133 'comment' => get_post_type( $comment->comment_post_ID ),
134 )
135 );
136
137 // render
138 if ( ! empty( $field_groups ) ) {
139
140 // render post data
141 acf_form_data(
142 array(
143 'screen' => 'comment',
144 'post_id' => $post_id,
145 )
146 );
147
148 foreach ( $field_groups as $field_group ) {
149
150 // load fields
151 $fields = acf_get_fields( $field_group );
152
153 // vars
154 $o = array(
155 'id' => 'acf-' . $field_group['ID'],
156 'key' => $field_group['key'],
157 // 'style' => $field_group['style'],
158 'label' => $field_group['label_placement'],
159 'edit_url' => '',
160 'edit_title' => __( 'Edit field group', 'acf' ),
161 // 'visibility' => $visibility
162 );
163
164 // edit_url
165 if ( $field_group['ID'] && acf_current_user_can_admin() ) {
166
167 $o['edit_url'] = admin_url( 'post.php?post=' . $field_group['ID'] . '&action=edit' );
168
169 }
170
171 ?>
172 <div id="acf-<?php echo $field_group['ID']; ?>" class="stuffbox">
173 <h3 class="hndle"><?php echo $field_group['title']; ?></h3>
174 <div class="inside">
175 <?php acf_render_fields( $fields, $post_id, 'div', $field_group['instruction_placement'] ); ?>
176 <script type="text/javascript">
177 if( typeof acf !== 'undefined' ) {
178
179 acf.newPostbox(<?php echo json_encode( $o ); ?>);
180
181 }
182 </script>
183 </div>
184 </div>
185 <?php
186
187 }
188 }
189
190 }
191
192
193 /*
194 * comment_form_field_comment
195 *
196 * description
197 *
198 * @type function
199 * @date 18/04/2016
200 * @since 5.3.8
201 *
202 * @param $post_id (int)
203 * @return $post_id (int)
204 */
205
206 function comment_form_field_comment( $html ) {
207
208 // global
209 global $post;
210
211 // vars
212 $post_id = false;
213
214 // get field groups
215 $field_groups = acf_get_field_groups(
216 array(
217 'comment' => $post->post_type,
218 )
219 );
220
221 // bail early if no field groups
222 if ( ! $field_groups ) {
223 return $html;
224 }
225
226 // enqueue scripts
227 acf_enqueue_scripts();
228
229 // ob
230 ob_start();
231
232 // render post data
233 acf_form_data(
234 array(
235 'screen' => 'comment',
236 'post_id' => $post_id,
237 )
238 );
239
240 echo '<div class="acf-comment-fields acf-fields -clear">';
241
242 foreach ( $field_groups as $field_group ) {
243
244 $fields = acf_get_fields( $field_group );
245
246 acf_render_fields( $fields, $post_id, 'p', $field_group['instruction_placement'] );
247
248 }
249
250 echo '</div>';
251
252 // append
253 $html .= ob_get_contents();
254 ob_end_clean();
255
256 // return
257 return $html;
258
259 }
260
261
262 /*
263 * save_comment
264 *
265 * This function will save the comment data
266 *
267 * @type function
268 * @date 19/10/13
269 * @since 5.0.0
270 *
271 * @param comment_id (int)
272 * @return n/a
273 */
274
275 function save_comment( $comment_id ) {
276
277 // bail early if not valid nonce
278 if ( ! acf_verify_nonce( 'comment' ) ) {
279 return $comment_id;
280 }
281
282 // kses
283 if ( isset( $_POST['acf'] ) ) {
284 $_POST['acf'] = wp_kses_post_deep( $_POST['acf'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized with wp_kses_post_deep().
285 }
286
287 // validate and save
288 if ( acf_validate_save_post( true ) ) {
289 acf_save_post( "comment_{$comment_id}" );
290 }
291
292 }
293
294
295 /*
296 * admin_footer
297 *
298 * description
299 *
300 * @type function
301 * @date 27/03/2015
302 * @since 5.1.5
303 *
304 * @param $post_id (int)
305 * @return $post_id (int)
306 */
307
308 function admin_footer() {
309
310 ?>
311 <script type="text/javascript">
312 (function($) {
313
314 // vars
315 var $spinner = $('#publishing-action .spinner');
316
317
318 // create spinner if not exists (may exist in future WP versions)
319 if( !$spinner.exists() ) {
320
321 // create spinner
322 $spinner = $('<span class="spinner"></span>');
323
324
325 // append
326 $('#publishing-action').prepend( $spinner );
327
328 }
329
330 })(jQuery);
331 </script>
332 <?php
333
334 }
335
336 }
337
338 new acf_form_comment();
339
340 endif;
341
342 ?>
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly.
5 }
6
7 if ( ! class_exists( 'ACF_Form_Gutenberg' ) ) :
8
9 class ACF_Form_Gutenberg {
10
11 /**
12 * __construct
13 *
14 * Setup for class functionality.
15 *
16 * @date 13/12/18
17 * @since 5.8.0
18 *
19 * @param void
20 * @return void
21 */
22
23 function __construct() {
24
25 // Add actions.
26 add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_editor_assets' ) );
27
28 // Ignore validation during meta-box-loader AJAX request.
29 add_action( 'acf/validate_save_post', array( $this, 'acf_validate_save_post' ), 999 );
30 }
31
32 /**
33 * enqueue_block_editor_assets
34 *
35 * Allows a safe way to customize Guten-only functionality.
36 *
37 * @date 14/12/18
38 * @since 5.8.0
39 *
40 * @param void
41 * @return void
42 */
43 function enqueue_block_editor_assets() {
44
45 // Remove edit_form_after_title.
46 add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 20, 0 );
47
48 // Call edit_form_after_title manually.
49 add_action( 'block_editor_meta_box_hidden_fields', array( $this, 'block_editor_meta_box_hidden_fields' ) );
50
51 // Customize editor metaboxes.
52 add_filter( 'filter_block_editor_meta_boxes', array( $this, 'filter_block_editor_meta_boxes' ) );
53
54 // Trigger ACF enqueue scripts as the site editor doesn't trigger this from form-post.php
55 acf_enqueue_scripts(
56 array(
57 'uploader' => true,
58 )
59 );
60 }
61
62 /**
63 * add_meta_boxes
64 *
65 * Modify screen for Gutenberg.
66 *
67 * @date 13/12/18
68 * @since 5.8.0
69 *
70 * @param void
71 * @return void
72 */
73 function add_meta_boxes() {
74
75 // Remove 'edit_form_after_title' action.
76 remove_action( 'edit_form_after_title', array( acf_get_instance( 'ACF_Form_Post' ), 'edit_form_after_title' ) );
77 }
78
79 /**
80 * block_editor_meta_box_hidden_fields
81 *
82 * Modify screen for Gutenberg.
83 *
84 * @date 13/12/18
85 * @since 5.8.0
86 *
87 * @param void
88 * @return void
89 */
90 function block_editor_meta_box_hidden_fields() {
91
92 // Manually call 'edit_form_after_title' function.
93 acf_get_instance( 'ACF_Form_Post' )->edit_form_after_title();
94 }
95
96 /**
97 * filter_block_editor_meta_boxes
98 *
99 * description
100 *
101 * @date 5/4/19
102 * @since 5.7.14
103 *
104 * @param type $var Description. Default.
105 * @return type Description.
106 */
107 function filter_block_editor_meta_boxes( $wp_meta_boxes ) {
108
109 // Globals
110 global $current_screen;
111
112 // Move 'acf_after_title' metaboxes into 'normal' location.
113 if ( isset( $wp_meta_boxes[ $current_screen->id ]['acf_after_title'] ) ) {
114
115 // Extract locations.
116 $locations = $wp_meta_boxes[ $current_screen->id ];
117
118 // Ensure normal location exists.
119 if ( ! isset( $locations['normal'] ) ) {
120 $locations['normal'] = array();
121 }
122 if ( ! isset( $locations['normal']['high'] ) ) {
123 $locations['normal']['high'] = array();
124 }
125
126 // Append metaboxes.
127 foreach ( $locations['acf_after_title'] as $priority => $meta_boxes ) {
128 $locations['normal']['high'] = array_merge( $meta_boxes, $locations['normal']['high'] );
129 }
130
131 // Update original data.
132 $wp_meta_boxes[ $current_screen->id ] = $locations;
133 unset( $wp_meta_boxes[ $current_screen->id ]['acf_after_title'] );
134
135 // Avoid conflicts with saved metabox order.
136 add_filter( 'get_user_option_meta-box-order_' . $current_screen->id, array( $this, 'modify_user_option_meta_box_order' ) );
137 }
138
139 // Return
140 return $wp_meta_boxes;
141 }
142
143 /**
144 * modify_user_option_meta_box_order
145 *
146 * Filters the `meta-box-order_{$post_type}` value by prepending "acf_after_title" data to "normal".
147 * Fixes a bug where metaboxes with position "acf_after_title" do not appear in the block editor.
148 *
149 * @date 11/7/19
150 * @since 5.8.2
151 *
152 * @param array $stored_meta_box_order User's existing meta box order.
153 * @return array Modified array with meta boxes moved around.
154 */
155 function modify_user_option_meta_box_order( $locations ) {
156 if ( ! empty( $locations['acf_after_title'] ) ) {
157 if ( ! empty( $locations['normal'] ) ) {
158 $locations['normal'] = $locations['acf_after_title'] . ',' . $locations['normal'];
159 } else {
160 $locations['normal'] = $locations['acf_after_title'];
161 }
162 unset( $locations['acf_after_title'] );
163 }
164 return $locations;
165 }
166
167 /**
168 * acf_validate_save_post
169 *
170 * Ignore errors during the Gutenberg "save metaboxes" AJAX request.
171 * Allows data to save and prevent UX issues.
172 *
173 * @date 16/12/18
174 * @since 5.8.0
175 *
176 * @param void
177 * @return void
178 */
179 function acf_validate_save_post() {
180
181 // Check if current request came from Gutenberg.
182 if ( isset( $_GET['meta-box-loader'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Verified elsewhere.
183 acf_reset_validation_errors();
184 }
185 }
186 }
187
188 acf_new_instance( 'ACF_Form_Gutenberg' );
189
190 endif;
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 if ( ! class_exists( 'acf_form_nav_menu' ) ) :
8
9 class acf_form_nav_menu {
10
11 /*
12 * __construct
13 *
14 * This function will setup the class functionality
15 *
16 * @type function
17 * @date 5/03/2014
18 * @since 5.0.0
19 *
20 * @param n/a
21 * @return n/a
22 */
23
24 function __construct() {
25
26 // actions
27 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
28 add_action( 'wp_update_nav_menu', array( $this, 'update_nav_menu' ) );
29 add_action( 'acf/validate_save_post', array( $this, 'acf_validate_save_post' ), 5 );
30 add_action( 'wp_nav_menu_item_custom_fields', array( $this, 'wp_nav_menu_item_custom_fields' ), 10, 5 );
31
32 // filters
33 add_filter( 'wp_get_nav_menu_items', array( $this, 'wp_get_nav_menu_items' ), 10, 3 );
34 add_filter( 'wp_edit_nav_menu_walker', array( $this, 'wp_edit_nav_menu_walker' ), 10, 2 );
35
36 }
37
38
39 /*
40 * admin_enqueue_scripts
41 *
42 * This action is run after post query but before any admin script / head actions.
43 * It is a good place to register all actions.
44 *
45 * @type action (admin_enqueue_scripts)
46 * @date 26/01/13
47 * @since 3.6.0
48 *
49 * @param N/A
50 * @return N/A
51 */
52
53 function admin_enqueue_scripts() {
54
55 // validate screen
56 if ( ! acf_is_screen( 'nav-menus' ) ) {
57 return;
58 }
59
60 // load acf scripts
61 acf_enqueue_scripts();
62
63 // actions
64 add_action( 'admin_footer', array( $this, 'admin_footer' ), 1 );
65
66 }
67
68
69 /**
70 * wp_nav_menu_item_custom_fields
71 *
72 * description
73 *
74 * @date 30/7/18
75 * @since 5.6.9
76 *
77 * @param type $var Description. Default.
78 * @return type Description.
79 */
80
81 function wp_nav_menu_item_custom_fields( $item_id, $item, $depth, $args, $id = '' ) {
82
83 // vars
84 $prefix = "menu-item-acf[$item_id]";
85
86 // get field groups
87 $field_groups = acf_get_field_groups(
88 array(
89 'nav_menu_item' => $item->type,
90 'nav_menu_item_id' => $item_id,
91 'nav_menu_item_depth' => $depth,
92 )
93 );
94
95 // render
96 if ( ! empty( $field_groups ) ) {
97
98 // open
99 echo '<div class="acf-menu-item-fields acf-fields -clear">';
100
101 // loop
102 foreach ( $field_groups as $field_group ) {
103
104 // load fields
105 $fields = acf_get_fields( $field_group );
106
107 // bail if not fields
108 if ( empty( $fields ) ) {
109 continue;
110 }
111
112 // change prefix
113 acf_prefix_fields( $fields, $prefix );
114
115 // render
116 acf_render_fields( $fields, $item_id, 'div', $field_group['instruction_placement'] );
117 }
118
119 // close
120 echo '</div>';
121
122 // Trigger append for newly created menu item (via AJAX)
123 if ( acf_is_ajax( 'add-menu-item' ) ) : ?>
124 <script type="text/javascript">
125 (function($) {
126 acf.doAction('append', $('#menu-item-settings-<?php echo $item_id; ?>') );
127 })(jQuery);
128 </script>
129 <?php
130 endif;
131 }
132 }
133
134
135 /*
136 * update_nav_menu
137 *
138 * description
139 *
140 * @type function
141 * @date 26/5/17
142 * @since 5.6.0
143 *
144 * @param $post_id (int)
145 * @return $post_id (int)
146 */
147
148 function update_nav_menu( $menu_id ) {
149
150 // vars
151 $post_id = 'term_' . $menu_id;
152
153 // verify and remove nonce
154 if ( ! acf_verify_nonce( 'nav_menu' ) ) {
155 return $menu_id;
156 }
157
158 // validate and show errors
159 acf_validate_save_post( true );
160
161 // save
162 acf_save_post( $post_id );
163
164 // save nav menu items
165 $this->update_nav_menu_items( $menu_id );
166
167 }
168
169
170 /*
171 * update_nav_menu_items
172 *
173 * description
174 *
175 * @type function
176 * @date 26/5/17
177 * @since 5.6.0
178 *
179 * @param $post_id (int)
180 * @return $post_id (int)
181 */
182
183 function update_nav_menu_items( $menu_id ) {
184
185 // phpcs:disable WordPress.Security.NonceVerification.Missing -- Verified elsewhere.
186 if ( empty( $_POST['menu-item-acf'] ) ) {
187 return;
188 }
189
190 $posted_values = acf_sanitize_request_args( $_POST['menu-item-acf'] );
191
192 foreach ( $posted_values as $post_id => $values ) {
193
194 acf_save_post( $post_id, $values );
195
196 }
197 // phpcs:enable WordPress.Security.NonceVerification.Missing
198 }
199
200
201 /**
202 * wp_get_nav_menu_items
203 *
204 * WordPress does not provide an easy way to find the current menu being edited.
205 * This function listens to when a menu's items are loaded and stores the menu.
206 * Needed on nav-menus.php page for new menu with no items
207 *
208 * @date 23/2/18
209 * @since 5.6.9
210 *
211 * @param type $var Description. Default.
212 * @return type Description.
213 */
214
215 function wp_get_nav_menu_items( $items, $menu, $args ) {
216 acf_set_data( 'nav_menu_id', $menu->term_id );
217 return $items;
218 }
219
220 /**
221 * Called when WP renders a menu edit form.
222 * Used to set global data and customize the Walker class.
223 *
224 * @date 26/5/17
225 * @since 5.6.0
226 *
227 * @param string $class The walker class to use. Default 'Walker_Nav_Menu_Edit'.
228 * @param int $menu_id ID of the menu being rendered.
229 * @return string
230 */
231 function wp_edit_nav_menu_walker( $class, $menu_id = 0 ) {
232
233 // update data (needed for ajax location rules to work)
234 acf_set_data( 'nav_menu_id', $menu_id );
235
236 // Return class.
237 return $class;
238 }
239
240
241 /*
242 * acf_validate_save_post
243 *
244 * This function will loop over $_POST data and validate
245 *
246 * @type action 'acf/validate_save_post' 5
247 * @date 7/09/2016
248 * @since 5.4.0
249 *
250 * @param n/a
251 * @return n/a
252 */
253
254 function acf_validate_save_post() {
255
256 // phpcs:disable WordPress.Security.NonceVerification.Missing -- Verified elsewhere.
257 if ( empty( $_POST['menu-item-acf'] ) ) {
258 return;
259 }
260
261 $posted_values = acf_sanitize_request_args( $_POST['menu-item-acf'] );
262
263 foreach ( $posted_values as $post_id => $values ) {
264
265 // vars
266 $prefix = 'menu-item-acf[' . $post_id . ']';
267
268 // validate
269 acf_validate_values( $values, $prefix );
270
271 }
272 // phpcs:enable // phpcs:disable WordPress.Security.NonceVerification.Missing
273
274 }
275
276 /*
277 * admin_footer
278 *
279 * This function will add some custom HTML to the footer of the edit page
280 *
281 * @type function
282 * @date 11/06/2014
283 * @since 5.0.0
284 *
285 * @param n/a
286 * @return n/a
287 */
288
289 function admin_footer() {
290
291 // vars
292 $nav_menu_id = acf_get_data( 'nav_menu_id' );
293 $post_id = 'term_' . $nav_menu_id;
294
295 // get field groups
296 $field_groups = acf_get_field_groups(
297 array(
298 'nav_menu' => $nav_menu_id,
299 )
300 );
301
302 ?>
303 <div id="tmpl-acf-menu-settings" style="display: none;">
304 <?php
305
306 // data (always needed to save nav menu items)
307 acf_form_data(
308 array(
309 'screen' => 'nav_menu',
310 'post_id' => $post_id,
311 'ajax' => 1,
312 )
313 );
314
315 // render
316 if ( ! empty( $field_groups ) ) {
317
318 // loop
319 foreach ( $field_groups as $field_group ) {
320
321 $fields = acf_get_fields( $field_group );
322
323 echo '<div class="acf-menu-settings -' . $field_group['style'] . '">';
324
325 echo '<h2>' . $field_group['title'] . '</h2>';
326
327 echo '<div class="acf-fields -left -clear">';
328
329 acf_render_fields( $fields, $post_id, 'div', $field_group['instruction_placement'] );
330
331 echo '</div>';
332
333 echo '</div>';
334
335 }
336 }
337
338 ?>
339 </div>
340 <script type="text/javascript">
341 (function($) {
342
343 // append html
344 var html = $('#tmpl-acf-menu-settings').html();
345 $('#tmpl-acf-menu-settings').remove();
346 $('#post-body-content').append( html );
347
348
349 // avoid WP over-writing $_POST data
350 // - https://core.trac.wordpress.org/ticket/41502#ticket
351 $(document).on('submit', '#update-nav-menu', function() {
352
353 // vars
354 var $form = $(this);
355 var $input = $('input[name="nav-menu-data"]');
356
357
358 // decode json
359 var json = $form.serializeArray();
360 var json2 = [];
361
362
363 // loop
364 $.each( json, function( i, pair ) {
365
366 // avoid nesting (unlike WP)
367 if( pair.name === 'nav-menu-data' ) return;
368
369
370 // bail early if is 'acf[' input
371 if( pair.name.indexOf('acf[') > -1 ) return;
372
373
374 // append
375 json2.push( pair );
376
377 });
378
379
380 // update
381 $input.val( JSON.stringify(json2) );
382
383 });
384
385
386 })(jQuery);
387 </script>
388 <?php
389
390 }
391
392 }
393
394 acf_new_instance( 'acf_form_nav_menu' );
395
396 endif;
397 ?>
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 if ( ! class_exists( 'ACF_Form_Post' ) ) :
8
9 class ACF_Form_Post {
10
11 /** @var string The first field groups style CSS. */
12 var $style = '';
13
14 /**
15 * __construct
16 *
17 * Sets up the class functionality.
18 *
19 * @date 5/03/2014
20 * @since 5.0.0
21 *
22 * @param void
23 * @return void
24 */
25 function __construct() {
26
27 // initialize on post edit screens
28 add_action( 'load-post.php', array( $this, 'initialize' ) );
29 add_action( 'load-post-new.php', array( $this, 'initialize' ) );
30
31 // save
32 add_filter( 'wp_insert_post_empty_content', array( $this, 'wp_insert_post_empty_content' ), 10, 2 );
33 add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
34 }
35
36
37 /**
38 * initialize
39 *
40 * Sets up Form functionality.
41 *
42 * @date 19/9/18
43 * @since 5.7.6
44 *
45 * @param void
46 * @return void
47 */
48 function initialize() {
49
50 // globals
51 global $typenow;
52
53 $acf_post_types = acf_get_internal_post_types();
54
55 foreach ( $acf_post_types as $post_type ) {
56 remove_meta_box( 'submitdiv', $post_type, 'side' );
57 }
58
59 // restrict specific post types
60 $restricted = array_merge( $acf_post_types, array( 'acf-taxonomy', 'attachment' ) );
61 if ( in_array( $typenow, $restricted ) ) {
62 return;
63 }
64
65 // enqueue scripts
66 acf_enqueue_scripts(
67 array(
68 'uploader' => true,
69 )
70 );
71
72 // actions
73 add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 10, 2 );
74 }
75
76 /**
77 * add_meta_boxes
78 *
79 * Adds ACF metaboxes for the given $post_type and $post.
80 *
81 * @date 19/9/18
82 * @since 5.7.6
83 *
84 * @param string $post_type The post type.
85 * @param WP_Post $post The post being edited.
86 * @return void
87 */
88 function add_meta_boxes( $post_type, $post ) {
89
90 // Storage for localized postboxes.
91 $postboxes = array();
92
93 // Get field groups for this screen.
94 $field_groups = acf_get_field_groups(
95 array(
96 'post_id' => $post->ID,
97 'post_type' => $post_type,
98 )
99 );
100
101 // Loop over field groups.
102 if ( $field_groups ) {
103 foreach ( $field_groups as $field_group ) {
104
105 // vars
106 $id = "acf-{$field_group['key']}"; // acf-group_123
107 $title = $field_group['title']; // Group 1
108 $context = $field_group['position']; // normal, side, acf_after_title
109 $priority = 'high'; // high, core, default, low
110
111 // Reduce priority for sidebar metaboxes for best position.
112 if ( $context == 'side' ) {
113 $priority = 'core';
114 }
115
116 /**
117 * Filters the metabox priority.
118 *
119 * @date 23/06/12
120 * @since 3.1.8
121 *
122 * @param string $priority The metabox priority (high, core, default, low).
123 * @param array $field_group The field group array.
124 */
125 $priority = apply_filters( 'acf/input/meta_box_priority', $priority, $field_group );
126
127 // Localize data
128 $postboxes[] = array(
129 'id' => $id,
130 'key' => $field_group['key'],
131 'style' => $field_group['style'],
132 'label' => $field_group['label_placement'],
133 'edit' => acf_get_field_group_edit_link( $field_group['ID'] ),
134 );
135
136 // Add the meta box.
137 add_meta_box( $id, acf_esc_html( $title ), array( $this, 'render_meta_box' ), $post_type, $context, $priority, array( 'field_group' => $field_group ) );
138
139 }
140
141 // Set style from first field group.
142 $this->style = acf_get_field_group_style( $field_groups[0] );
143
144 // Localize postboxes.
145 acf_localize_data(
146 array(
147 'postboxes' => $postboxes,
148 )
149 );
150 }
151
152 // remove postcustom metabox (removes expensive SQL query)
153 if ( acf_get_setting( 'remove_wp_meta_box' ) ) {
154 remove_meta_box( 'postcustom', false, 'normal' );
155 }
156
157 // Add hidden input fields.
158 add_action( 'edit_form_after_title', array( $this, 'edit_form_after_title' ) );
159
160 /**
161 * Fires after metaboxes have been added.
162 *
163 * @date 13/12/18
164 * @since 5.8.0
165 *
166 * @param string $post_type The post type.
167 * @param WP_Post $post The post being edited.
168 * @param array $field_groups The field groups added.
169 */
170 do_action( 'acf/add_meta_boxes', $post_type, $post, $field_groups );
171 }
172
173 /**
174 * edit_form_after_title
175 *
176 * Called after the title adn before the content editor.
177 *
178 * @date 19/9/18
179 * @since 5.7.6
180 *
181 * @param void
182 * @return void
183 */
184 function edit_form_after_title() {
185
186 // globals
187 global $post, $wp_meta_boxes;
188
189 // render post data
190 acf_form_data(
191 array(
192 'screen' => 'post',
193 'post_id' => $post->ID,
194 )
195 );
196
197 // render 'acf_after_title' metaboxes
198 do_meta_boxes( get_current_screen(), 'acf_after_title', $post );
199
200 // render dynamic field group style
201 echo '<style type="text/css" id="acf-style">' . $this->style . '</style>';
202 }
203
204 /**
205 * render_meta_box
206 *
207 * Renders the ACF metabox HTML.
208 *
209 * @date 19/9/18
210 * @since 5.7.6
211 *
212 * @param WP_Post $post The post being edited.
213 * @param array metabox The add_meta_box() args.
214 * @return void
215 */
216 function render_meta_box( $post, $metabox ) {
217
218 // vars
219 $id = $metabox['id'];
220 $field_group = $metabox['args']['field_group'];
221
222 // Render fields.
223 $fields = acf_get_fields( $field_group );
224 acf_render_fields( $fields, $post->ID, 'div', $field_group['instruction_placement'] );
225 }
226
227 /**
228 * wp_insert_post_empty_content
229 *
230 * Allows WP to insert a new post without title or post_content if ACF data exists.
231 *
232 * @date 16/07/2014
233 * @since 5.0.1
234 *
235 * @param bool $maybe_empty Whether the post should be considered "empty".
236 * @param array $postarr Array of post data.
237 * @return bool
238 */
239 function wp_insert_post_empty_content( $maybe_empty, $postarr ) {
240
241 // return false and allow insert if '_acf_changed' exists
242 if ( $maybe_empty && acf_maybe_get_POST( '_acf_changed' ) ) {
243 return false;
244 }
245
246 // return
247 return $maybe_empty;
248 }
249
250 /*
251 * allow_save_post
252 *
253 * Checks if the $post is allowed to be saved.
254 * Used to avoid triggering "acf/save_post" on dynamically created posts during save.
255 *
256 * @type function
257 * @date 26/06/2016
258 * @since 5.3.8
259 *
260 * @param WP_Post $post The post to check.
261 * @return bool
262 */
263 function allow_save_post( $post ) {
264
265 // vars
266 $allow = true;
267
268 // restrict post types
269 $restrict = array( 'auto-draft', 'revision', 'acf-field', 'acf-field-group' );
270 if ( in_array( $post->post_type, $restrict ) ) {
271 $allow = false;
272 }
273
274 // disallow if the $_POST ID value does not match the $post->ID
275 $form_post_id = (int) acf_maybe_get_POST( 'post_ID' );
276 if ( $form_post_id && $form_post_id !== $post->ID ) {
277 $allow = false;
278 }
279
280 // revision (preview)
281 if ( $post->post_type == 'revision' ) {
282
283 // allow if doing preview and this $post is a child of the $_POST ID
284 if ( acf_maybe_get_POST( 'wp-preview' ) == 'dopreview' && $form_post_id === $post->post_parent ) {
285 $allow = true;
286 }
287 }
288
289 // return
290 return $allow;
291 }
292
293 /*
294 * save_post
295 *
296 * Triggers during the 'save_post' action to save the $_POST data.
297 *
298 * @type function
299 * @date 23/06/12
300 * @since 1.0.0
301 *
302 * @param int $post_id The post ID
303 * @param WP_POST $post the post object.
304 * @return int
305 */
306
307 function save_post( $post_id, $post ) {
308
309 // bail early if no allowed to save this post type
310 if ( ! $this->allow_save_post( $post ) ) {
311 return $post_id;
312 }
313
314 // verify nonce
315 if ( ! acf_verify_nonce( 'post' ) ) {
316 return $post_id;
317 }
318
319 // validate for published post (allow draft to save without validation)
320 if ( $post->post_status == 'publish' ) {
321
322 // bail early if validation fails
323 if ( ! acf_validate_save_post() ) {
324 return;
325 }
326 }
327
328 // save
329 acf_save_post( $post_id );
330
331 // save revision
332 if ( post_type_supports( $post->post_type, 'revisions' ) ) {
333 acf_save_post_revision( $post_id );
334 }
335
336 // return
337 return $post_id;
338 }
339 }
340
341 acf_new_instance( 'ACF_Form_Post' );
342
343 endif;
344
345
1 <?php
2
3 /*
4 * ACF Taxonomy Form Class
5 *
6 * All the logic for adding fields to taxonomy terms
7 *
8 * @class acf_form_taxonomy
9 * @package ACF
10 * @subpackage Forms
11 */
12
13 if ( ! class_exists( 'acf_form_taxonomy' ) ) :
14
15 class acf_form_taxonomy {
16
17 var $view = 'add';
18
19
20 /*
21 * __construct
22 *
23 * This function will setup the class functionality
24 *
25 * @type function
26 * @date 5/03/2014
27 * @since 5.0.0
28 *
29 * @param n/a
30 * @return n/a
31 */
32
33 function __construct() {
34
35 // actions
36 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
37
38 // save
39 add_action( 'create_term', array( $this, 'save_term' ), 10, 3 );
40 add_action( 'edit_term', array( $this, 'save_term' ), 10, 3 );
41
42 // delete
43 add_action( 'delete_term', array( $this, 'delete_term' ), 10, 4 );
44
45 }
46
47
48 /*
49 * validate_page
50 *
51 * This function will check if the current page is for a post/page edit form
52 *
53 * @type function
54 * @date 23/06/12
55 * @since 3.1.8
56 *
57 * @param n/a
58 * @return (boolean)
59 */
60
61 function validate_page() {
62
63 // global
64 global $pagenow;
65
66 // validate page
67 if ( $pagenow === 'edit-tags.php' || $pagenow === 'term.php' ) {
68
69 return true;
70
71 }
72
73 // return
74 return false;
75 }
76
77
78 /*
79 * admin_enqueue_scripts
80 *
81 * This action is run after post query but before any admin script / head actions.
82 * It is a good place to register all actions.
83 *
84 * @type action (admin_enqueue_scripts)
85 * @date 26/01/13
86 * @since 3.6.0
87 *
88 * @param N/A
89 * @return N/A
90 */
91
92 function admin_enqueue_scripts() {
93
94 // validate page
95 if ( ! $this->validate_page() ) {
96
97 return;
98
99 }
100
101 // vars
102 $screen = get_current_screen();
103 $taxonomy = $screen->taxonomy;
104
105 // load acf scripts
106 acf_enqueue_scripts();
107
108 // actions
109 add_action( 'admin_footer', array( $this, 'admin_footer' ), 10, 1 );
110 add_action( "{$taxonomy}_add_form_fields", array( $this, 'add_term' ), 10, 1 );
111 add_action( "{$taxonomy}_edit_form", array( $this, 'edit_term' ), 10, 2 );
112
113 }
114
115
116 /*
117 * add_term
118 *
119 * description
120 *
121 * @type function
122 * @date 8/10/13
123 * @since 5.0.0
124 *
125 * @param $post_id (int)
126 * @return $post_id (int)
127 */
128
129 function add_term( $taxonomy ) {
130
131 // vars
132 $post_id = 'term_0';
133
134 // update vars
135 $this->view = 'add';
136
137 // get field groups
138 $field_groups = acf_get_field_groups(
139 array(
140 'taxonomy' => $taxonomy,
141 )
142 );
143
144 // render
145 if ( ! empty( $field_groups ) ) {
146
147 // data
148 acf_form_data(
149 array(
150 'screen' => 'taxonomy',
151 'post_id' => $post_id,
152 )
153 );
154
155 // wrap
156 echo '<div id="acf-term-fields" class="acf-fields -clear">';
157
158 // loop
159 foreach ( $field_groups as $field_group ) {
160 $fields = acf_get_fields( $field_group );
161 acf_render_fields( $fields, $post_id, 'div', 'field' );
162 }
163
164 // wrap
165 echo '</div>';
166
167 }
168
169 }
170
171
172 /*
173 * edit_term
174 *
175 * description
176 *
177 * @type function
178 * @date 8/10/13
179 * @since 5.0.0
180 *
181 * @param $post_id (int)
182 * @return $post_id (int)
183 */
184
185 function edit_term( $term, $taxonomy ) {
186
187 // vars
188 $post_id = 'term_' . $term->term_id;
189
190 // update vars
191 $this->view = 'edit';
192
193 // get field groups
194 $field_groups = acf_get_field_groups(
195 array(
196 'taxonomy' => $taxonomy,
197 )
198 );
199
200 // render
201 if ( ! empty( $field_groups ) ) {
202
203 acf_form_data(
204 array(
205 'screen' => 'taxonomy',
206 'post_id' => $post_id,
207 )
208 );
209
210 foreach ( $field_groups as $field_group ) {
211
212 // title
213 if ( $field_group['style'] == 'default' ) {
214 echo '<h2>' . $field_group['title'] . '</h2>';
215 }
216
217 // fields
218 echo '<table class="form-table">';
219 $fields = acf_get_fields( $field_group );
220 acf_render_fields( $fields, $post_id, 'tr', 'field' );
221 echo '</table>';
222
223 }
224 }
225
226 }
227
228
229 /*
230 * admin_footer
231 *
232 * description
233 *
234 * @type function
235 * @date 27/03/2015
236 * @since 5.1.5
237 *
238 * @param $post_id (int)
239 * @return $post_id (int)
240 */
241
242 function admin_footer() {
243
244 ?>
245 <script type="text/javascript">
246 (function($) {
247
248 // Define vars.
249 var view = '<?php echo $this->view; ?>';
250 var $form = $('#' + view + 'tag');
251 var $submit = $('#' + view + 'tag input[type="submit"]:last');
252
253 // Add missing spinner.
254 if( !$submit.next('.spinner').length ) {
255 $submit.after('<span class="spinner"></span>');
256 }
257
258 <?php
259
260 // View: Add.
261 if ( $this->view == 'add' ) :
262 ?>
263
264 // vars
265 var $fields = $('#acf-term-fields');
266 var html = '';
267
268 // Store a copy of the $fields html used later to replace after AJAX request.
269 // Hook into 'prepare' action to allow ACF core helpers to first modify DOM.
270 // Fixes issue where hidden #acf-hidden-wp-editor is initialized again.
271 acf.addAction('prepare', function(){
272 html = $fields.html();
273 }, 6);
274
275 // WP triggers click as primary action
276 $submit.on('click', function( e ){
277
278 // validate
279 var valid = acf.validateForm({
280 form: $form,
281 event: e,
282 reset: true
283 });
284
285 // if not valid, stop event and allow validation to continue
286 if( !valid ) {
287 e.preventDefault();
288 e.stopImmediatePropagation();
289 }
290 });
291
292 // listen to AJAX add-tag complete
293 $(document).ajaxComplete(function(event, xhr, settings) {
294
295 // bail early if is other ajax call
296 if( settings.data.indexOf('action=add-tag') == -1 ) {
297 return;
298 }
299
300 // bail early if response contains error
301 if( xhr.responseText.indexOf('wp_error') !== -1 ) {
302 return;
303 }
304
305 // action for 3rd party customization
306 acf.doAction('remove', $fields);
307
308 // reset HTML
309 $fields.html( html );
310
311 // action for 3rd party customization
312 acf.doAction('append', $fields);
313
314 // reset unload
315 acf.unload.reset();
316 });
317
318 <?php endif; ?>
319
320 })(jQuery);
321 </script>
322 <?php
323
324 }
325
326
327 /*
328 * save_term
329 *
330 * description
331 *
332 * @type function
333 * @date 8/10/13
334 * @since 5.0.0
335 *
336 * @param $post_id (int)
337 * @return $post_id (int)
338 */
339
340 function save_term( $term_id, $tt_id, $taxonomy ) {
341
342 // vars
343 $post_id = 'term_' . $term_id;
344
345 // verify and remove nonce
346 if ( ! acf_verify_nonce( 'taxonomy' ) ) {
347 return $term_id;
348 }
349
350 // valied and show errors
351 acf_validate_save_post( true );
352
353 // save
354 acf_save_post( $post_id );
355
356 }
357
358
359 /*
360 * delete_term
361 *
362 * description
363 *
364 * @type function
365 * @date 15/10/13
366 * @since 5.0.0
367 *
368 * @param $post_id (int)
369 * @return $post_id (int)
370 */
371
372 function delete_term( $term, $tt_id, $taxonomy, $deleted_term ) {
373
374 // bail early if termmeta table exists
375 if ( acf_isset_termmeta() ) {
376 return $term;
377 }
378
379 // globals
380 global $wpdb;
381
382 // vars
383 $search = $taxonomy . '_' . $term . '_%';
384 $_search = '_' . $search;
385
386 // escape '_'
387 // http://stackoverflow.com/questions/2300285/how-do-i-escape-in-sql-server
388 $search = str_replace( '_', '\_', $search );
389 $_search = str_replace( '_', '\_', $_search );
390
391 // delete
392 $result = $wpdb->query(
393 $wpdb->prepare(
394 "DELETE FROM $wpdb->options WHERE option_name LIKE %s OR option_name LIKE %s",
395 $search,
396 $_search
397 )
398 );
399
400 }
401
402 }
403
404 new acf_form_taxonomy();
405
406 endif;
407
408
409 ?>
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 if ( ! class_exists( 'ACF_Form_User' ) ) :
8
9 class ACF_Form_User {
10
11 /** @var string The current view (new, edit, register) */
12 var $view = '';
13
14
15 /*
16 * __construct
17 *
18 * This function will setup the class functionality
19 *
20 * @type function
21 * @date 5/03/2014
22 * @since 5.0.0
23 *
24 * @param n/a
25 * @return n/a
26 */
27
28 function __construct() {
29
30 // enqueue
31 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
32 add_action( 'login_form_register', array( $this, 'login_form_register' ) );
33
34 // render
35 add_action( 'show_user_profile', array( $this, 'render_edit' ) );
36 add_action( 'edit_user_profile', array( $this, 'render_edit' ) );
37 add_action( 'user_new_form', array( $this, 'render_new' ) );
38 add_action( 'register_form', array( $this, 'render_register' ) );
39
40 // save
41 add_action( 'user_register', array( $this, 'save_user' ) );
42 add_action( 'profile_update', array( $this, 'save_user' ) );
43
44 // Perform validation before new user is registered.
45 add_filter( 'registration_errors', array( $this, 'filter_registration_errors' ), 10, 3 );
46 }
47
48
49 /**
50 * admin_enqueue_scripts
51 *
52 * Checks current screen and enqueues scripts
53 *
54 * @date 17/4/18
55 * @since 5.6.9
56 *
57 * @param void
58 * @return void
59 */
60
61 function admin_enqueue_scripts() {
62
63 // bail early if not valid screen
64 if ( ! acf_is_screen( array( 'profile', 'user', 'user-edit', 'profile-network', 'user-network', 'user-edit-network' ) ) ) {
65 return;
66 }
67
68 // enqueue
69 acf_enqueue_scripts();
70 }
71
72
73 /**
74 * login_form_register
75 *
76 * Customizes and enqueues scripts
77 *
78 * @date 17/4/18
79 * @since 5.6.9
80 *
81 * @param void
82 * @return void
83 */
84
85 function login_form_register() {
86
87 // customize action prefix so that "admin_head" = "login_head"
88 acf_enqueue_scripts(
89 array(
90 'context' => 'login',
91 )
92 );
93 }
94
95
96 /*
97 * register_user
98 *
99 * Called during the user register form
100 *
101 * @type function
102 * @date 8/10/13
103 * @since 5.0.0
104 *
105 * @param void
106 * @return void
107 */
108
109 function render_register() {
110
111 // render
112 $this->render(
113 array(
114 'user_id' => 0,
115 'view' => 'register',
116 'el' => 'div',
117 )
118 );
119 }
120
121
122 /*
123 * render_edit
124 *
125 * Called during the user edit form
126 *
127 * @type function
128 * @date 8/10/13
129 * @since 5.0.0
130 *
131 * @param void
132 * @return void
133 */
134
135 function render_edit( $user ) {
136
137 // add compatibility with front-end user profile edit forms such as bbPress
138 if ( ! is_admin() ) {
139 acf_enqueue_scripts();
140 }
141
142 // render
143 $this->render(
144 array(
145 'user_id' => $user->ID,
146 'view' => 'edit',
147 'el' => 'tr',
148 )
149 );
150 }
151
152
153 /*
154 * user_new_form
155 *
156 * description
157 *
158 * @type function
159 * @date 8/10/13
160 * @since 5.0.0
161 *
162 * @param $post_id (int)
163 * @return $post_id (int)
164 */
165
166 function render_new() {
167
168 // Multisite uses a different 'user-new.php' form. Don't render fields here
169 if ( is_multisite() ) {
170 return;
171 }
172
173 // render
174 $this->render(
175 array(
176 'user_id' => 0,
177 'view' => 'add',
178 'el' => 'tr',
179 )
180 );
181 }
182
183
184 /*
185 * render
186 *
187 * This function will render ACF fields for a given $post_id parameter
188 *
189 * @type function
190 * @date 7/10/13
191 * @since 5.0.0
192 *
193 * @param $user_id (int) this can be set to 0 for a new user
194 * @param $user_form (string) used for location rule matching. edit | add | register
195 * @param $el (string)
196 * @return n/a
197 */
198
199 function render( $args = array() ) {
200
201 // Allow $_POST data to persist across form submission attempts.
202 if ( isset( $_POST['acf'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
203 add_filter( 'acf/pre_load_value', array( $this, 'filter_pre_load_value' ), 10, 3 );
204 }
205
206 // defaults
207 $args = wp_parse_args(
208 $args,
209 array(
210 'user_id' => 0,
211 'view' => 'edit',
212 'el' => 'tr',
213 )
214 );
215
216 // vars
217 $post_id = 'user_' . $args['user_id'];
218
219 // get field groups
220 $field_groups = acf_get_field_groups(
221 array(
222 'user_id' => $args['user_id'] ? $args['user_id'] : 'new',
223 'user_form' => $args['view'],
224 )
225 );
226
227 // bail early if no field groups
228 if ( empty( $field_groups ) ) {
229 return;
230 }
231
232 // form data
233 acf_form_data(
234 array(
235 'screen' => 'user',
236 'post_id' => $post_id,
237 'validation' => ( $args['view'] == 'register' ) ? 0 : 1,
238 )
239 );
240
241 // elements
242 $before = '<table class="form-table"><tbody>';
243 $after = '</tbody></table>';
244
245 if ( $args['el'] == 'div' ) {
246 $before = '<div class="acf-user-' . $args['view'] . '-fields acf-fields -clear">';
247 $after = '</div>';
248 }
249
250 // loop
251 foreach ( $field_groups as $field_group ) {
252
253 // vars
254 $fields = acf_get_fields( $field_group );
255
256 // title
257 if ( $field_group['style'] === 'default' ) {
258 echo '<h2>' . $field_group['title'] . '</h2>';
259 }
260
261 // render
262 echo $before;
263 acf_render_fields( $fields, $post_id, $args['el'], $field_group['instruction_placement'] );
264 echo $after;
265 }
266
267 // actions
268 add_action( 'acf/input/admin_footer', array( $this, 'admin_footer' ), 10, 1 );
269 }
270
271
272 /*
273 * admin_footer
274 *
275 * description
276 *
277 * @type function
278 * @date 27/03/2015
279 * @since 5.1.5
280 *
281 * @param $post_id (int)
282 * @return $post_id (int)
283 */
284
285 function admin_footer() {
286
287 // script
288 ?>
289 <script type="text/javascript">
290 (function($) {
291
292 // vars
293 var view = '<?php echo $this->view; ?>';
294
295 // add missing spinners
296 var $submit = $('input.button-primary');
297 if( !$submit.next('.spinner').length ) {
298 $submit.after('<span class="spinner"></span>');
299 }
300
301 })(jQuery);
302 </script>
303 <?php
304
305 }
306
307
308 /*
309 * save_user
310 *
311 * description
312 *
313 * @type function
314 * @date 8/10/13
315 * @since 5.0.0
316 *
317 * @param $post_id (int)
318 * @return $post_id (int)
319 */
320
321 function save_user( $user_id ) {
322
323 // verify nonce
324 if ( ! acf_verify_nonce( 'user' ) ) {
325 return $user_id;
326 }
327
328 // save
329 if ( acf_validate_save_post( true ) ) {
330 acf_save_post( "user_$user_id" );
331 }
332 }
333
334 /**
335 * filter_registration_errors
336 *
337 * Validates $_POST data and appends any errors to prevent new user registration.
338 *
339 * @date 12/7/19
340 * @since 5.8.1
341 *
342 * @param WP_Error $errors A WP_Error object containing any errors encountered during registration.
343 * @param string $sanitized_user_login User's username after it has been sanitized.
344 * @param string $user_email User's email.
345 * @return WP_Error
346 */
347 function filter_registration_errors( $errors, $sanitized_user_login, $user_email ) {
348 if ( ! acf_validate_save_post() ) {
349 $acf_errors = acf_get_validation_errors();
350 foreach ( $acf_errors as $acf_error ) {
351 $errors->add(
352 acf_idify( $acf_error['input'] ),
353 acf_esc_html( acf_punctify( sprintf( __( '<strong>Error</strong>: %s', 'acf' ), $acf_error['message'] ) ) )
354 );
355 }
356 }
357 return $errors;
358 }
359
360 /**
361 * filter_pre_load_value
362 *
363 * Checks if a $_POST value exists for this field to allow persistent values.
364 *
365 * @date 12/7/19
366 * @since 5.8.2
367 *
368 * @param null $null A null placeholder.
369 * @param (int|string) $post_id The post id.
370 * @param array $field The field array.
371 * @return mixed
372 */
373 function filter_pre_load_value( $null, $post_id, $field ) {
374 $field_key = $field['key'];
375 // phpcs:disable WordPress.Security.NonceVerification.Missing -- Verified in save_user().
376 if ( isset( $_POST['acf'][ $field_key ] ) ) {
377 return $_POST['acf'][ $field_key ]; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized elsewhere.
378 }
379 // phpcs:enable WordPress.Security.NonceVerification.Missing
380 return $null;
381 }
382 }
383
384 // instantiate
385 acf_new_instance( 'ACF_Form_User' );
386
387 endif; // class_exists check
388
389 ?>
1 <?php
2
3 /*
4 * ACF Widget Form Class
5 *
6 * All the logic for adding fields to widgets
7 *
8 * @class acf_form_widget
9 * @package ACF
10 * @subpackage Forms
11 */
12
13 if ( ! class_exists( 'acf_form_widget' ) ) :
14
15 #[AllowDynamicProperties]
16 class acf_form_widget {
17
18
19 /*
20 * __construct
21 *
22 * This function will setup the class functionality
23 *
24 * @type function
25 * @date 5/03/2014
26 * @since 5.0.0
27 *
28 * @param n/a
29 * @return n/a
30 */
31
32 function __construct() {
33
34 // vars
35 $this->preview_values = array();
36 $this->preview_reference = array();
37 $this->preview_errors = array();
38
39 // actions
40 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
41 add_action( 'in_widget_form', array( $this, 'edit_widget' ), 10, 3 );
42 add_action( 'acf/validate_save_post', array( $this, 'acf_validate_save_post' ), 5 );
43
44 // filters
45 add_filter( 'widget_update_callback', array( $this, 'save_widget' ), 10, 4 );
46
47 }
48
49
50 /*
51 * admin_enqueue_scripts
52 *
53 * This action is run after post query but before any admin script / head actions.
54 * It is a good place to register all actions.
55 *
56 * @type action (admin_enqueue_scripts)
57 * @date 26/01/13
58 * @since 3.6.0
59 *
60 * @param N/A
61 * @return N/A
62 */
63
64 function admin_enqueue_scripts() {
65
66 // validate screen
67 if ( acf_is_screen( 'widgets' ) || acf_is_screen( 'customize' ) ) {
68
69 // valid
70
71 } else {
72
73 return;
74
75 }
76
77 // load acf scripts
78 acf_enqueue_scripts();
79
80 // actions
81 add_action( 'acf/input/admin_footer', array( $this, 'admin_footer' ), 1 );
82
83 }
84
85
86 /*
87 * acf_validate_save_post
88 *
89 * This function will loop over $_POST data and validate
90 *
91 * @type action 'acf/validate_save_post' 5
92 * @date 7/09/2016
93 * @since 5.4.0
94 *
95 * @param n/a
96 * @return n/a
97 */
98
99 function acf_validate_save_post() {
100
101 // phpcs:disable WordPress.Security.NonceVerification.Missing -- Verified elsewhere.
102 // bail early if not widget
103 if ( ! isset( $_POST['_acf_widget_id'] ) ) {
104 return;
105 }
106
107 // vars
108 $id = sanitize_text_field( $_POST['_acf_widget_id'] );
109 $number = sanitize_text_field( $_POST['_acf_widget_number'] );
110 $prefix = sanitize_text_field( $_POST['_acf_widget_prefix'] );
111 $values = acf_sanitize_request_args( $_POST[ $id ][ $number ]['acf'] );
112
113 // validate
114 acf_validate_values( $values, $prefix );
115 // phpcs:enable WordPress.Security.NonceVerification.Missing
116 }
117
118
119 /*
120 * edit_widget
121 *
122 * This function will render the fields for a widget form
123 *
124 * @type function
125 * @date 11/06/2014
126 * @since 5.0.0
127 *
128 * @param $widget (object)
129 * @param $return (null)
130 * @param $instance (object)
131 * @return $post_id (int)
132 */
133
134 function edit_widget( $widget, $return, $instance ) {
135
136 // vars
137 $post_id = 0;
138 $prefix = 'widget-' . $widget->id_base . '[' . $widget->number . '][acf]';
139
140 // get id
141 if ( $widget->number !== '__i__' ) {
142
143 $post_id = "widget_{$widget->id}";
144
145 }
146
147 // get field groups
148 $field_groups = acf_get_field_groups(
149 array(
150 'widget' => $widget->id_base,
151 )
152 );
153
154 // render
155 if ( ! empty( $field_groups ) ) {
156
157 // render post data
158 acf_form_data(
159 array(
160 'screen' => 'widget',
161 'post_id' => $post_id,
162 'widget_id' => 'widget-' . $widget->id_base,
163 'widget_number' => $widget->number,
164 'widget_prefix' => $prefix,
165 )
166 );
167
168 // wrap
169 echo '<div class="acf-widget-fields acf-fields -clear">';
170
171 // loop
172 foreach ( $field_groups as $field_group ) {
173
174 // load fields
175 $fields = acf_get_fields( $field_group );
176
177 // bail if not fields
178 if ( empty( $fields ) ) {
179 continue;
180 }
181
182 // change prefix
183 acf_prefix_fields( $fields, $prefix );
184
185 // render
186 acf_render_fields( $fields, $post_id, 'div', $field_group['instruction_placement'] );
187
188 }
189
190 // wrap
191 echo '</div>';
192
193 // jQuery selector looks odd, but is necessary due to WP adding an incremental number into the ID
194 // - not possible to find number via PHP parameters
195 if ( $widget->updated ) : ?>
196 <script type="text/javascript">
197 (function($) {
198
199 acf.doAction('append', $('[id^="widget"][id$="<?php echo $widget->id; ?>"]') );
200
201 })(jQuery);
202 </script>
203 <?php
204 endif;
205
206 }
207
208 }
209
210
211 /*
212 * save_widget
213 *
214 * This function will hook into the widget update filter and save ACF data
215 *
216 * @type function
217 * @date 27/05/2015
218 * @since 5.2.3
219 *
220 * @param $instance (array) widget settings
221 * @param $new_instance (array) widget settings
222 * @param $old_instance (array) widget settings
223 * @param $widget (object) widget info
224 * @return $instance
225 */
226
227 function save_widget( $instance, $new_instance, $old_instance, $widget ) {
228
229 // validate nonce if we're not a REST API request.
230 // the $_POST object is not available to us to validate if we're in a REST API call.
231 if ( ! ( function_exists( 'wp_is_json_request' ) && wp_is_json_request() ) ) {
232 if ( ! acf_verify_nonce( 'widget' ) ) {
233 return $instance;
234 }
235 }
236
237 // bail early if not valid (!customize + acf values + nonce).
238 if ( isset( $_POST['wp_customize'] ) || ! isset( $new_instance['acf'] ) ) {
239 return $instance;
240 }
241
242 // save
243 acf_save_post( "widget_{$widget->id}", $new_instance['acf'] );
244
245 // return
246 return $instance;
247
248 }
249
250
251 /*
252 * admin_footer
253 *
254 * This function will add some custom HTML to the footer of the edit page
255 *
256 * @type function
257 * @date 11/06/2014
258 * @since 5.0.0
259 *
260 * @param n/a
261 * @return n/a
262 */
263
264 function admin_footer() {
265 ?>
266 <script type="text/javascript">
267 (function($) {
268
269 // vars
270 acf.set('post_id', 'widgets');
271
272 // Only initialize visible fields.
273 acf.addFilter('find_fields', function( $fields ){
274
275 // not templates
276 $fields = $fields.not('#available-widgets .acf-field');
277
278 // not widget dragging in
279 $fields = $fields.not('.widget.ui-draggable-dragging .acf-field');
280
281 // return
282 return $fields;
283 });
284
285 // on publish
286 $('#widgets-right').on('click', '.widget-control-save', function( e ){
287
288 // vars
289 var $button = $(this);
290 var $form = $button.closest('form');
291
292 // validate
293 var valid = acf.validateForm({
294 form: $form,
295 event: e,
296 reset: true
297 });
298
299 // if not valid, stop event and allow validation to continue
300 if( !valid ) {
301 e.preventDefault();
302 e.stopImmediatePropagation();
303 }
304 });
305
306 // show
307 $('#widgets-right').on('click', '.widget-top', function(){
308 var $widget = $(this).parent();
309 if( $widget.hasClass('open') ) {
310 acf.doAction('hide', $widget);
311 } else {
312 acf.doAction('show', $widget);
313 }
314 });
315
316 $(document).on('widget-added', function( e, $widget ){
317
318 // - use delay to avoid rendering issues with customizer (ensures div is visible)
319 setTimeout(function(){
320 acf.doAction('append', $widget );
321 }, 100);
322 });
323
324 })(jQuery);
325 </script>
326 <?php
327
328 }
329 }
330
331 new acf_form_widget();
332
333 endif;
334
335 ?>
1 <?php
2
3 /**
4 * Determine the current locale desired for the request.
5 *
6 * @since 5.0.0
7 *
8 * @global string $pagenow
9 *
10 * @return string The determined locale.
11 */
12 if ( ! function_exists( 'determine_locale' ) ) :
13 function determine_locale() {
14 /**
15 * Filters the locale for the current request prior to the default determination process.
16 *
17 * Using this filter allows to override the default logic, effectively short-circuiting the function.
18 *
19 * @since 5.0.0
20 *
21 * @param string|null The locale to return and short-circuit, or null as default.
22 */
23 $determined_locale = apply_filters( 'pre_determine_locale', null );
24 if ( ! empty( $determined_locale ) && is_string( $determined_locale ) ) {
25 return $determined_locale;
26 }
27
28 $determined_locale = get_locale();
29
30 if ( function_exists( 'get_user_locale' ) && is_admin() ) {
31 $determined_locale = get_user_locale();
32 }
33
34 // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Copied from WordPress core.
35 if ( function_exists( 'get_user_locale' ) && isset( $_GET['_locale'] ) && 'user' === $_GET['_locale'] ) {
36 $determined_locale = get_user_locale();
37 }
38
39 if ( ! empty( $_GET['wp_lang'] ) && ! empty( $GLOBALS['pagenow'] ) && 'wp-login.php' === $GLOBALS['pagenow'] ) {
40 $determined_locale = sanitize_text_field( $_GET['wp_lang'] );
41 }
42 // phpcs:enable WordPress.Security.NonceVerification.Recommended
43
44 /**
45 * Filters the locale for the current request.
46 *
47 * @since 5.0.0
48 *
49 * @param string $locale The locale.
50 */
51 return apply_filters( 'determine_locale', $determined_locale );
52 }
53 endif;
54
55 /*
56 * acf_get_locale
57 *
58 * Returns the current locale.
59 *
60 * @date 16/12/16
61 * @since 5.5.0
62 *
63 * @param void
64 * @return string
65 */
66 function acf_get_locale() {
67
68 // Determine local.
69 $locale = determine_locale();
70
71 // Fallback to parent language for regions without translation.
72 // https://wpastra.com/docs/complete-list-wordpress-locale-codes/
73 $langs = array(
74 'az_TR' => 'az', // Azerbaijani (Turkey)
75 'zh_HK' => 'zh_TW', // Chinese (Hong Kong)
76 'fr_BE' => 'fr_FR', // French (Belgium)
77 'nn_NO' => 'nb_NO', // Norwegian (Nynorsk)
78 'fa_AF' => 'fa_IR', // Persian (Afghanistan)
79 'ru_UA' => 'ru_RU', // Russian (Ukraine)
80 );
81 if ( isset( $langs[ $locale ] ) ) {
82 $locale = $langs[ $locale ];
83 }
84
85 /**
86 * Filters the determined local.
87 *
88 * @date 8/1/19
89 * @since 5.7.10
90 *
91 * @param string $locale The local.
92 */
93 return apply_filters( 'acf/get_locale', $locale );
94 }
95
96 /**
97 * acf_load_textdomain
98 *
99 * Loads the plugin's translated strings similar to load_plugin_textdomain().
100 *
101 * @date 8/1/19
102 * @since 5.7.10
103 *
104 * @param string $locale The plugin's current locale.
105 * @return void
106 */
107 function acf_load_textdomain( $domain = 'acf' ) {
108
109 /**
110 * Filters a plugin's locale.
111 *
112 * @date 8/1/19
113 * @since 5.7.10
114 *
115 * @param string $locale The plugin's current locale.
116 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
117 */
118 $locale = apply_filters( 'plugin_locale', acf_get_locale(), $domain );
119 $mofile = $domain . '-' . $locale . '.mo';
120
121 // Load from plugin lang folder.
122 return load_textdomain( $domain, acf_get_path( 'lang/' . $mofile ) );
123 }
124
125 /**
126 * _acf_apply_language_cache_key
127 *
128 * Applies the current language to the cache key.
129 *
130 * @date 23/1/19
131 * @since 5.7.11
132 *
133 * @param string $key The cache key.
134 * @return string
135 */
136 function _acf_apply_language_cache_key( $key ) {
137
138 // Get current language.
139 $current_language = acf_get_setting( 'current_language' );
140 if ( $current_language ) {
141 $key = "{$key}:{$current_language}";
142 }
143
144 // Return key.
145 return $key;
146 }
147
148 // Hook into filter.
149 add_filter( 'acf/get_cache_key', '_acf_apply_language_cache_key' );
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 if ( ! class_exists( 'ACF_Legacy_Locations' ) ) :
8
9 class ACF_Legacy_Locations {
10
11 /**
12 * Magic __isset method for backwards compatibility.
13 *
14 * @date 10/4/20
15 * @since 5.9.0
16 *
17 * @param string $key Key name.
18 * @return bool
19 */
20 public function __isset( $key ) {
21 // _doing_it_wrong( __FUNCTION__, __( 'The ACF_Locations class should not be accessed directly.', 'acf' ), '5.9.0' );
22
23 return (
24 $key === 'locations'
25 );
26 }
27
28 /**
29 * Magic __get method for backwards compatibility.
30 *
31 * @date 10/4/20
32 * @since 5.9.0
33 *
34 * @param string $key Key name.
35 * @return mixed
36 */
37 public function __get( $key ) {
38 // _doing_it_wrong( __FUNCTION__, __( 'The ACF_Locations class should not be accessed directly.', 'acf' ), '5.9.0' );
39
40 switch ( $key ) {
41 case 'locations':
42 return call_user_func( 'acf_get_location_types' );
43 }
44 return null;
45 }
46
47 /**
48 * Magic __call method for backwards compatibility.
49 *
50 * @date 10/4/20
51 * @since 5.9.0
52 *
53 * @param string $name The method name.
54 * @param array $arguments The array of arguments.
55 * @return mixed
56 */
57 public function __call( $name, $arguments ) {
58 // _doing_it_wrong( __FUNCTION__, __( 'The ACF_Locations class should not be accessed directly.', 'acf' ), '5.9.0' );
59
60 switch ( $name ) {
61 case 'register_location':
62 return call_user_func_array( 'acf_register_location_type', $arguments );
63 case 'get_location':
64 return call_user_func_array( 'acf_get_location_type', $arguments );
65 case 'get_locations':
66 return call_user_func_array( 'acf_get_location_rule_types', $arguments );
67
68 }
69 }
70 }
71
72 endif; // class_exists check
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 if ( ! class_exists( 'ACF_Local_Meta' ) ) :
8
9 class ACF_Local_Meta {
10
11 /** @var array Storage for meta data. */
12 var $meta = array();
13
14 /** @var mixed Storage for the current post_id. */
15 var $post_id = 0;
16
17 /**
18 * __construct
19 *
20 * Sets up the class functionality.
21 *
22 * @date 8/10/18
23 * @since 5.8.0
24 *
25 * @param void
26 * @return void
27 */
28 function __construct() {
29
30 // add filters
31 add_filter( 'acf/pre_load_post_id', array( $this, 'pre_load_post_id' ), 1, 2 );
32 add_filter( 'acf/pre_load_meta', array( $this, 'pre_load_meta' ), 1, 2 );
33 add_filter( 'acf/pre_load_metadata', array( $this, 'pre_load_metadata' ), 1, 4 );
34 }
35
36 /**
37 * add
38 *
39 * Adds postmeta to storage.
40 * Accepts data in either raw or request format.
41 *
42 * @date 8/10/18
43 * @since 5.8.0
44 *
45 * @param array $meta An array of metdata to store.
46 * @param mixed $post_id The post_id for this data.
47 * @param bool $is_main Makes this postmeta visible to get_field() without a $post_id value.
48 * @return array
49 */
50 function add( $meta = array(), $post_id = 0, $is_main = false ) {
51
52 // Capture meta if supplied meta is from a REQUEST.
53 if ( $this->is_request( $meta ) ) {
54 $meta = $this->capture( $meta, $post_id );
55 }
56
57 // Add to storage.
58 $this->meta[ $post_id ] = $meta;
59
60 // Set $post_id reference when is the "main" postmeta.
61 if ( $is_main ) {
62 $this->post_id = $post_id;
63 }
64
65 // Return meta.
66 return $meta;
67 }
68
69 /**
70 * is_request
71 *
72 * Returns true if the supplied $meta is from a REQUEST (serialized <form> data).
73 *
74 * @date 11/3/19
75 * @since 5.7.14
76 *
77 * @param array $meta An array of metdata to check.
78 * @return bool
79 */
80 function is_request( $meta = array() ) {
81 return acf_is_field_key( key( $meta ) );
82 }
83
84 /**
85 * capture
86 *
87 * Returns a flattened array of meta for the given postdata.
88 * This is achieved by simulating a save whilst capturing all meta changes.
89 *
90 * @date 26/2/19
91 * @since 5.7.13
92 *
93 * @param array $values An array of raw values.
94 * @param mixed $post_id The post_id for this data.
95 * @return array
96 */
97 function capture( $values = array(), $post_id = 0 ) {
98
99 // Reset meta.
100 $this->meta[ $post_id ] = array();
101
102 // Listen for any added meta.
103 add_filter( 'acf/pre_update_metadata', array( $this, 'capture_update_metadata' ), 1, 5 );
104
105 // Simulate update.
106 if ( $values ) {
107 acf_update_values( $values, $post_id );
108 }
109
110 // Remove listener filter.
111 remove_filter( 'acf/pre_update_metadata', array( $this, 'capture_update_metadata' ), 1, 5 );
112
113 // Return meta.
114 return $this->meta[ $post_id ];
115 }
116
117 /**
118 * capture_update_metadata
119 *
120 * Records all meta activity and returns a non null value to bypass DB updates.
121 *
122 * @date 26/2/19
123 * @since 5.7.13
124 *
125 * @param null $null .
126 * @param (int|string) $post_id The post id.
127 * @param string $name The meta name.
128 * @param mixed $value The meta value.
129 * @param bool $hidden If the meta is hidden (starts with an underscore).
130 * @return false.
131 */
132 function capture_update_metadata( $null, $post_id, $name, $value, $hidden ) {
133 $name = ( $hidden ? '_' : '' ) . $name;
134 $this->meta[ $post_id ][ $name ] = $value;
135
136 // Return non null value to escape update process.
137 return true;
138 }
139
140 /**
141 * remove
142 *
143 * Removes postmeta from storage.
144 *
145 * @date 8/10/18
146 * @since 5.8.0
147 *
148 * @param mixed $post_id The post_id for this data.
149 * @return void
150 */
151 function remove( $post_id = 0 ) {
152
153 // unset meta
154 unset( $this->meta[ $post_id ] );
155
156 // reset post_id
157 if ( $post_id === $this->post_id ) {
158 $this->post_id = 0;
159 }
160 }
161
162 /**
163 * pre_load_meta
164 *
165 * Injects the local meta.
166 *
167 * @date 8/10/18
168 * @since 5.8.0
169 *
170 * @param null $null An empty parameter. Return a non null value to short-circuit the function.
171 * @param mixed $post_id The post_id for this data.
172 * @return mixed
173 */
174 function pre_load_meta( $null, $post_id ) {
175 if ( isset( $this->meta[ $post_id ] ) ) {
176 return $this->meta[ $post_id ];
177 }
178 return $null;
179 }
180
181 /**
182 * pre_load_metadata
183 *
184 * Injects the local meta.
185 *
186 * @date 8/10/18
187 * @since 5.8.0
188 *
189 * @param null $null An empty parameter. Return a non null value to short-circuit the function.
190 * @param (int|string) $post_id The post id.
191 * @param string $name The meta name.
192 * @param bool $hidden If the meta is hidden (starts with an underscore).
193 * @return mixed
194 */
195 function pre_load_metadata( $null, $post_id, $name, $hidden ) {
196 $name = ( $hidden ? '_' : '' ) . $name;
197 if ( isset( $this->meta[ $post_id ] ) ) {
198 if ( isset( $this->meta[ $post_id ][ $name ] ) ) {
199 return $this->meta[ $post_id ][ $name ];
200 }
201 return '__return_null';
202 }
203 return $null;
204 }
205
206 /**
207 * pre_load_post_id
208 *
209 * Injects the local post_id.
210 *
211 * @date 8/10/18
212 * @since 5.8.0
213 *
214 * @param null $null An empty parameter. Return a non null value to short-circuit the function.
215 * @param mixed $post_id The post_id for this data.
216 * @return mixed
217 */
218 function pre_load_post_id( $null, $post_id ) {
219 if ( ! $post_id && $this->post_id ) {
220 return $this->post_id;
221 }
222 return $null;
223 }
224 }
225
226 endif; // class_exists check
227
228 /**
229 * acf_setup_meta
230 *
231 * Adds postmeta to storage.
232 *
233 * @date 8/10/18
234 * @since 5.8.0
235 * @see ACF_Local_Meta::add() for list of parameters.
236 *
237 * @return array
238 */
239 function acf_setup_meta( $meta = array(), $post_id = 0, $is_main = false ) {
240 return acf_get_instance( 'ACF_Local_Meta' )->add( $meta, $post_id, $is_main );
241 }
242
243 /**
244 * acf_reset_meta
245 *
246 * Removes postmeta to storage.
247 *
248 * @date 8/10/18
249 * @since 5.8.0
250 * @see ACF_Local_Meta::remove() for list of parameters.
251 *
252 * @return void
253 */
254 function acf_reset_meta( $post_id = 0 ) {
255 return acf_get_instance( 'ACF_Local_Meta' )->remove( $post_id );
256 }
1 <?php
2
3 // Exit if accessed directly.
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 // Register store.
9 acf_register_store( 'location-types' );
10
11 /**
12 * Registers a location type.
13 *
14 * @date 8/4/20
15 * @since 5.9.0
16 *
17 * @param string $class_name The location class name.
18 * @return (ACF_Location|false)
19 */
20 function acf_register_location_type( $class_name ) {
21 $store = acf_get_store( 'location-types' );
22
23 // Check class exists.
24 if ( ! class_exists( $class_name ) ) {
25 $message = sprintf( __( 'Class "%s" does not exist.', 'acf' ), $class_name );
26 _doing_it_wrong( __FUNCTION__, $message, '5.9.0' );
27 return false;
28 }
29
30 // Create instance.
31 $location_type = new $class_name();
32 $name = $location_type->name;
33
34 // Check location type is unique.
35 if ( $store->has( $name ) ) {
36 $message = sprintf( __( 'Location type "%s" is already registered.', 'acf' ), $name );
37 _doing_it_wrong( __FUNCTION__, $message, '5.9.0' );
38 return false;
39 }
40
41 // Add to store.
42 $store->set( $name, $location_type );
43
44 /**
45 * Fires after a location type is registered.
46 *
47 * @date 8/4/20
48 * @since 5.9.0
49 *
50 * @param string $name The location type name.
51 * @param ACF_Location $location_type The location type instance.
52 */
53 do_action( 'acf/registered_location_type', $name, $location_type );
54
55 // Return location type instance.
56 return $location_type;
57 }
58
59 /**
60 * Returns an array of all registered location types.
61 *
62 * @date 8/4/20
63 * @since 5.9.0
64 *
65 * @param void
66 * @return array
67 */
68 function acf_get_location_types() {
69 return acf_get_store( 'location-types' )->get();
70 }
71
72 /**
73 * Returns a location type for the given name.
74 *
75 * @date 18/2/19
76 * @since 5.7.12
77 *
78 * @param string $name The location type name.
79 * @return (ACF_Location|null)
80 */
81 function acf_get_location_type( $name ) {
82 return acf_get_store( 'location-types' )->get( $name );
83 }
84
85 /**
86 * Returns a grouped array of all location rule types.
87 *
88 * @date 8/4/20
89 * @since 5.9.0
90 *
91 * @param void
92 * @return array
93 */
94 function acf_get_location_rule_types() {
95 $types = array();
96
97 // Default categories.
98 $categories = array(
99 'post' => __( 'Post', 'acf' ),
100 'page' => __( 'Page', 'acf' ),
101 'user' => __( 'User', 'acf' ),
102 'forms' => __( 'Forms', 'acf' ),
103 );
104
105 // Loop over all location types and append to $type.
106 $location_types = acf_get_location_types();
107 foreach ( $location_types as $location_type ) {
108
109 // Ignore if not public.
110 if ( ! $location_type->public ) {
111 continue;
112 }
113
114 // Find category label from category name.
115 $category = $location_type->category;
116 if ( isset( $categories[ $category ] ) ) {
117 $category = $categories[ $category ];
118 }
119
120 // Append
121 $types[ $category ][ $location_type->name ] = esc_html( $location_type->label );
122 }
123
124 /**
125 * Filters the location rule types.
126 *
127 * @date 8/4/20
128 * @since 5.9.0
129 *
130 * @param array $types The location rule types.
131 */
132 return apply_filters( 'acf/location/rule_types', $types );
133 }
134
135 /**
136 * Returns a validated location rule with all props.
137 *
138 * @date 8/4/20
139 * @since 5.9.0
140 *
141 * @param array $rule The location rule.
142 * @return array
143 */
144 function acf_validate_location_rule( $rule = array() ) {
145
146 // Apply defaults.
147 $rule = wp_parse_args(
148 $rule,
149 array(
150 'id' => '',
151 'group' => '',
152 'param' => '',
153 'operator' => '==',
154 'value' => '',
155 )
156 );
157
158 /**
159 * Filters the location rule to ensure is valid.
160 *
161 * @date 8/4/20
162 * @since 5.9.0
163 *
164 * @param array $rule The location rule.
165 */
166 $rule = apply_filters( "acf/location/validate_rule/type={$rule['param']}", $rule );
167 $rule = apply_filters( 'acf/location/validate_rule', $rule );
168 return $rule;
169 }
170
171 /**
172 * Returns an array of operators for a given rule.
173 *
174 * @date 30/5/17
175 * @since 5.6.0
176 *
177 * @param array $rule The location rule.
178 * @return array
179 */
180 function acf_get_location_rule_operators( $rule ) {
181 $operators = ACF_Location::get_operators( $rule );
182
183 // Get operators from location type since 5.9.
184 $location_type = acf_get_location_type( $rule['param'] );
185 if ( $location_type ) {
186 $operators = $location_type->get_operators( $rule );
187 }
188
189 /**
190 * Filters the location rule operators.
191 *
192 * @date 30/5/17
193 * @since 5.6.0
194 *
195 * @param array $types The location rule operators.
196 */
197 $operators = apply_filters( "acf/location/rule_operators/type={$rule['param']}", $operators, $rule );
198 $operators = apply_filters( "acf/location/rule_operators/{$rule['param']}", $operators, $rule );
199 $operators = apply_filters( 'acf/location/rule_operators', $operators, $rule );
200 return $operators;
201 }
202
203 /**
204 * Returns an array of values for a given rule.
205 *
206 * @date 30/5/17
207 * @since 5.6.0
208 *
209 * @param array $rule The location rule.
210 * @return array
211 */
212 function acf_get_location_rule_values( $rule ) {
213 $values = array();
214
215 // Get values from location type since 5.9.
216 $location_type = acf_get_location_type( $rule['param'] );
217 if ( $location_type ) {
218 $values = $location_type->get_values( $rule );
219 }
220
221 /**
222 * Filters the location rule values.
223 *
224 * @date 30/5/17
225 * @since 5.6.0
226 *
227 * @param array $types The location rule values.
228 */
229 $values = apply_filters( "acf/location/rule_values/type={$rule['param']}", $values, $rule );
230 $values = apply_filters( "acf/location/rule_values/{$rule['param']}", $values, $rule );
231 $values = apply_filters( 'acf/location/rule_values', $values, $rule );
232 return $values;
233 }
234
235 /**
236 * Returns true if the provided rule matches the screen args.
237 *
238 * @date 30/5/17
239 * @since 5.6.0
240 *
241 * @param array $rule The location rule.
242 * @param array $screen The screen args.
243 * @param array $field The field group array.
244 * @return bool
245 */
246 function acf_match_location_rule( $rule, $screen, $field_group ) {
247 $result = false;
248
249 // Get result from location type since 5.9.
250 $location_type = acf_get_location_type( $rule['param'] );
251 if ( $location_type ) {
252 $result = $location_type->match( $rule, $screen, $field_group );
253 }
254
255 /**
256 * Filters the result.
257 *
258 * @date 30/5/17
259 * @since 5.6.0
260 *
261 * @param bool $result The match result.
262 * @param array $rule The location rule.
263 * @param array $screen The screen args.
264 * @param array $field_group The field group array.
265 */
266 $result = apply_filters( "acf/location/match_rule/type={$rule['param']}", $result, $rule, $screen, $field_group );
267 $result = apply_filters( 'acf/location/match_rule', $result, $rule, $screen, $field_group );
268 $result = apply_filters( "acf/location/rule_match/{$rule['param']}", $result, $rule, $screen, $field_group );
269 $result = apply_filters( 'acf/location/rule_match', $result, $rule, $screen, $field_group );
270 return $result;
271 }
272
273 /**
274 * Returns ann array of screen args to be used against matching rules.
275 *
276 * @date 8/4/20
277 * @since 5.9.0
278 *
279 * @param array $screen The screen args.
280 * @param array $deprecated The field group array.
281 * @return array
282 */
283 function acf_get_location_screen( $screen = array(), $deprecated = false ) {
284
285 // Apply defaults.
286 $screen = wp_parse_args(
287 $screen,
288 array(
289 'lang' => acf_get_setting( 'current_language' ),
290 'ajax' => false,
291 )
292 );
293
294 /**
295 * Filters the result.
296 *
297 * @date 30/5/17
298 * @since 5.6.0
299 *
300 * @param array $screen The screen args.
301 * @param array $deprecated The field group array.
302 */
303 return apply_filters( 'acf/location/screen', $screen, $deprecated );
304 }
305
306 /**
307 * Alias of acf_register_location_type().
308 *
309 * @date 31/5/17
310 * @since 5.6.0
311 *
312 * @param string $class_name The location class name.
313 * @return (ACF_Location|false)
314 */
315 function acf_register_location_rule( $class_name ) {
316 return acf_register_location_type( $class_name );
317 }
318
319 /**
320 * Alias of acf_get_location_type().
321 *
322 * @date 31/5/17
323 * @since 5.6.0
324 *
325 * @param string $class_name The location class name.
326 * @return (ACF_Location|false)
327 */
328 function acf_get_location_rule( $name ) {
329 return acf_get_location_type( $name );
330 }
331
332 /**
333 * Alias of acf_validate_location_rule().
334 *
335 * @date 30/5/17
336 * @since 5.6.0
337 *
338 * @param array $rule The location rule.
339 * @return array
340 */
341 function acf_get_valid_location_rule( $rule ) {
342 return acf_validate_location_rule( $rule );
343 }
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 if ( ! class_exists( 'ACF_Legacy_Location' ) ) :
8
9 abstract class ACF_Legacy_Location {
10
11 /**
12 * Constructor.
13 *
14 * @date 5/03/2014
15 * @since 5.0.0
16 *
17 * @param void
18 * @return void
19 */
20 public function __construct() {
21
22 // Add legacy method filters.
23 if ( method_exists( $this, 'rule_match' ) ) {
24 add_filter( "acf/location/rule_match/{$this->name}", array( $this, 'rule_match' ), 5, 3 );
25 }
26 if ( method_exists( $this, 'rule_operators' ) ) {
27 add_filter( "acf/location/rule_operators/{$this->name}", array( $this, 'rule_operators' ), 5, 2 );
28 }
29 if ( method_exists( $this, 'rule_values' ) ) {
30 add_filter( "acf/location/rule_values/{$this->name}", array( $this, 'rule_values' ), 5, 2 );
31 }
32 }
33
34 /**
35 * Magic __call method for backwards compatibility.
36 *
37 * @date 10/4/20
38 * @since 5.9.0
39 *
40 * @param string $name The method name.
41 * @param array $arguments The array of arguments.
42 * @return mixed
43 */
44 public function __call( $name, $arguments ) {
45
46 // Add backwards compatibility for legacy methods.
47 // - Combine 3x legacy filters cases together (remove first args).
48 switch ( $name ) {
49 case 'rule_match':
50 $method = isset( $method ) ? $method : 'match';
51 $arguments[3] = isset( $arguments[3] ) ? $arguments[3] : false; // Add $field_group param.
52 case 'rule_operators':
53 $method = isset( $method ) ? $method : 'get_operators';
54 case 'rule_values':
55 $method = isset( $method ) ? $method : 'get_values';
56 array_shift( $arguments );
57 return call_user_func_array( array( $this, $method ), $arguments );
58 case 'compare':
59 return call_user_func_array( array( $this, 'compare_to_rule' ), $arguments );
60 }
61 }
62 }
63
64 endif; // class_exists check
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 if ( ! class_exists( 'ACF_Location' ) ) :
8
9 abstract class ACF_Location extends ACF_Legacy_Location {
10
11 /**
12 * The location rule name.
13 *
14 * @since 5.9.0
15 * @var string
16 */
17 public $name = '';
18
19 /**
20 * The location rule label.
21 *
22 * @since 5.9.0
23 * @var string
24 */
25 public $label = '';
26
27 /**
28 * The location rule category.
29 *
30 * Accepts "post", "page", "user", "forms" or a custom label.
31 *
32 * @since 5.9.0
33 * @var string
34 */
35 public $category = 'post';
36
37 /**
38 * Whether or not the location rule is publicly accessible.
39 *
40 * @since 5.0.0
41 * @var bool
42 */
43 public $public = true;
44
45 /**
46 * The object type related to this location rule.
47 *
48 * Accepts an object type discoverable by `acf_get_object_type()`.
49 *
50 * @since 5.9.0
51 * @var string
52 */
53 public $object_type = '';
54
55 /**
56 * The object subtype related to this location rule.
57 *
58 * Accepts a custom post type or custom taxonomy.
59 *
60 * @since 5.9.0
61 * @var string
62 */
63 public $object_subtype = '';
64
65 /**
66 * Constructor.
67 *
68 * @date 8/4/20
69 * @since 5.9.0
70 *
71 * @param void
72 * @return void
73 */
74 public function __construct() {
75 $this->initialize();
76
77 // Call legacy constructor.
78 parent::__construct();
79 }
80
81 /**
82 * Initializes props.
83 *
84 * @date 5/03/2014
85 * @since 5.0.0
86 *
87 * @param void
88 * @return void
89 */
90 public function initialize() {
91 // Set props here.
92 }
93
94 /**
95 * Returns an array of operators for this location.
96 *
97 * @date 9/4/20
98 * @since 5.9.0
99 *
100 * @param array $rule A location rule.
101 * @return array
102 */
103 public static function get_operators( $rule ) {
104 return array(
105 '==' => __( 'is equal to', 'acf' ),
106 '!=' => __( 'is not equal to', 'acf' ),
107 );
108 }
109
110 /**
111 * Returns an array of possible values for this location.
112 *
113 * @date 9/4/20
114 * @since 5.9.0
115 *
116 * @param array $rule A location rule.
117 * @return array
118 */
119 public function get_values( $rule ) {
120 return array();
121 }
122
123 /**
124 * Returns the object_type connected to this location.
125 *
126 * @date 1/4/20
127 * @since 5.9.0
128 *
129 * @param array $rule A location rule.
130 * @return string
131 */
132 public function get_object_type( $rule ) {
133 return $this->object_type;
134 }
135
136 /**
137 * Returns the object_subtype connected to this location.
138 *
139 * @date 1/4/20
140 * @since 5.9.0
141 *
142 * @param array $rule A location rule.
143 * @return string|array
144 */
145 public function get_object_subtype( $rule ) {
146 return $this->object_subtype;
147 }
148
149 /**
150 * Matches the provided rule against the screen args returning a bool result.
151 *
152 * @date 9/4/20
153 * @since 5.9.0
154 *
155 * @param array $rule The location rule.
156 * @param array $screen The screen args.
157 * @param array $field_group The field group settings.
158 * @return bool
159 */
160 public function match( $rule, $screen, $field_group ) {
161 return false;
162 }
163
164 /**
165 * Compares the given value and rule params returning true when they match.
166 *
167 * @date 17/9/19
168 * @since 5.8.1
169 *
170 * @param array $rule The location rule data.
171 * @param mixed $value The value to compare against.
172 * @return bool
173 */
174 public function compare_to_rule( $value, $rule ) {
175 $result = ( $value == $rule['value'] );
176
177 // Allow "all" to match any value.
178 if ( $rule['value'] === 'all' ) {
179 $result = true;
180 }
181
182 // Reverse result for "!=" operator.
183 if ( $rule['operator'] === '!=' ) {
184 return ! $result;
185 }
186 return $result;
187 }
188 }
189
190 endif; // class_exists check