Plugin Directory

source: business-directory-plugin/trunk/includes/fields/class-fieldtypes-select.php

Last change on this file was 3230604, checked in by businessdirectoryplugin, 3 months ago

Update to version 6.4.12 from GitHub

File size: 13.4 KB
Line 
1<?php
2/**
3 * Fieldtypes Select
4 *
5 * @package BDP/Includes/Fields/Fieldtypes Select
6 */
7
8/**
9 * Class WPBDP_FieldTypes_Select
10 */
11class WPBDP_FieldTypes_Select extends WPBDP_Form_Field_Type {
12
13        /**
14         * Determines if field is a multiselect fieldtype
15         *
16         * @var bool
17         */
18        private $multiselect = false;
19
20        /**
21         * WPBDP_FieldTypes_Select constructor.
22         */
23        public function __construct( $name = '' ) {
24                if ( empty( $name ) ) {
25                        $name = __( 'Select List', 'business-directory-plugin' );
26                }
27                parent::__construct( $name );
28        }
29
30        public function get_id() {
31                return 'select';
32        }
33
34        public function set_multiple( $val ) {
35                $this->multiselect = (bool) $val;
36        }
37
38        public function is_multiple() {
39                return $this->multiselect;
40        }
41
42        public function convert_input( &$field, $input ) {
43                if ( is_null( $input ) || '' == $input ) {
44                        $input = array();
45                }
46
47                wpbdp_sanitize_value( 'sanitize_text_field', $input );
48
49                $res = is_array( $input ) ? $input : array( $input );
50
51                if ( $field->get_association() == 'category' ) {
52                        $res = array_map( 'intval', $res );
53                }
54
55                return $res;
56        }
57
58        /**
59         * @since 3.4.1
60         */
61        public function convert_csv_input( &$field, $input = '', $import_settings = array() ) {
62                if ( 'tags' == $field->get_association() ) {
63                        $input = str_replace( ';', ',', $input );
64                        return explode( ',', $input );
65                } elseif ( 'meta' != $field->get_association() ) {
66                        return $this->convert_input( $field, $input );
67                }
68
69                if ( ! $input ) {
70                        return array();
71                }
72
73                if ( ! $this->is_multiple() ) {
74                        return array( str_replace( ',', '', $input ) );
75                }
76
77                return explode( ',', $input );
78        }
79
80        public function render_field_inner( &$field, $value, $context, &$extra = null, $field_settings = array() ) { // phpcs:ignore SlevomatCodingStandard.Complexity
81                $options = $field->data( 'options' ) ? $field->data( 'options' ) : array();
82                $value   = is_array( $value ) ? $value : array( $value );
83
84                $html = '';
85
86                if ( $field->get_association() === 'tags' && ! $options ) {
87                        $tags    = get_terms(
88                                array(
89                                        'taxonomy'   => WPBDP_TAGS_TAX,
90                                        'hide_empty' => false,
91                                        'fields'     => 'names',
92                                )
93                        );
94                        $options = array_combine( $tags, $tags );
95                }
96
97                $size = $field->data( 'size', 4 );
98
99                if ( $field->get_association() === 'category' ) {
100                        $args = array(
101                                'taxonomy'         => WPBDP_CATEGORY_TAX,
102                                'show_option_none' => null,
103                                'orderby'          => wpbdp_get_option( 'categories-order-by' ),
104                                'selected'         => ( $this->is_multiple() ? null : ( $value ? end( $value ) : null ) ),
105                                'order'            => wpbdp_get_option( 'categories-sort' ),
106                                'hide_empty'       => $context == 'search' && wpbdp_get_option( 'hide-empty-categories' ) ? 1 : 0,
107                                'hierarchical'     => 1,
108                                'echo'             => 0,
109                                'id'               => 'wpbdp-field-' . $field->get_id(),
110                                'name'             => 'listingfields[' . $field->get_id() . ']',
111                                'class'            => 'wpbdp-js-select2',
112                        );
113
114                        $show_hidden = false;
115
116                        if ( ( 'submit' === $context || 'search' === $context ) && ! $this->is_multiple() ) {
117                                $args['show_option_none'] = esc_html__( '-- Choose One --', 'business-directory-plugin' );
118
119                                $terms_count = (int) wp_count_terms( array( 'taxonomy' => WPBDP_CATEGORY_TAX, 'hide_empty' => false ) );
120
121                                if ( 'submit' == $context ) {
122                                        $args['option_none_value'] = '';
123
124                                        if ( 1 === $terms_count ) {
125                                                $terms = get_terms(
126                                                        array(
127                                                                'taxonomy'   => WPBDP_CATEGORY_TAX,
128                                                                'hide_empty' => false,
129                                                        )
130                                                );
131                                                $term  = reset( $terms );
132
133                                                $show_hidden              = true;
134                                                $args['selected']         = $term->term_id;
135                                                $args['show_option_none'] = false;
136                                                $this->set_multiple( false );
137                                        }
138                                }
139
140                                if ( $terms_count < 10 ) {
141                                        $args['class'] = '';
142                                }
143                        } elseif ( 'search' == $context && $this->is_multiple() ) {
144                                $args['show_option_none'] = esc_html__( '-- Choose Terms --', 'business-directory-plugin' );
145                        }
146
147                        $args = apply_filters( 'wpbdp_field_type_select_categories_args', $args, $field, $value, $context, $extra, $field_settings );
148                        if ( $show_hidden ) {
149                                return $this->add_hidden_field( $args );
150                        }
151
152                        $html .= wp_dropdown_categories( $args );
153
154                        if ( strpos( $args['class'], 'wpbdp-js-select2' ) !== false ) {
155                                // Load assets only when needed.
156                                global $wpbdp;
157                                $wpbdp->assets->enqueue_select2();
158                        }
159
160                        if ( $this->is_multiple() ) {
161                                $html = preg_replace(
162                                        "/\\<select(.*)name=('|\")(.*)('|\")(.*)\\>/uiUs",
163                                        sprintf( '<select name="$3[]" multiple="multiple" $1 $5 size="%d">', $size ),
164                                        $html
165                                );
166
167                                if ( $value ) {
168                                        foreach ( $value as $catid ) {
169                                                $html = preg_replace(
170                                                        "/\\<option(.*)value=('|\"){$catid}('|\")(.*)\\>/uiU",
171                                                        "<option value=\"{$catid}\" selected=\"selected\" $1 $4>",
172                                                        $html
173                                                );
174                                        }
175                                }
176                        }
177
178                        if ( 'search' == $context && $this->is_multiple() ) {
179                                // Disable "Choose Terms".
180                                $html = preg_replace(
181                                        "/\\<option(.*)value=('|\")-1('|\")(.*)\\>/uiU",
182                                        '<option value="-1" disabled="disabled" $1 $4>',
183                                        $html
184                                );
185                        }
186                        return $html;
187                }
188
189                $html = $this->start_select_html( $field );
190
191                if ( $field->data( 'empty_on_search' ) && $context == 'search' ) {
192                        $html .= '<option value="-1"> </option>';
193                }
194
195                $html .= $this->add_empty_option( $field );
196                $html .= $this->add_options_to_field( $options, $value, $field );
197                $html .= '</select>';
198
199                return $html;
200        }
201
202        /**
203         * @since 6.4.4
204         *
205         * @return string
206         */
207        private function start_select_html( $field ) {
208                return sprintf(
209                        '<select id="%s" name="%s" %s class="%s %s" %s>',
210                        'wpbdp-field-' . $field->get_id(),
211                        'listingfields[' . $field->get_id() . ']' . ( $this->is_multiple() ? '[]' : '' ),
212                        $this->is_multiple() ? 'multiple="multiple"' : '',
213                        'inselect',
214                        $field->is_required() ? 'required' : '',
215                        $this->is_multiple() ? sprintf( 'size="%d"', $field->data( 'size', 4 ) ) : ''
216                );
217        }
218
219        /**
220         * @since 6.4.4
221         *
222         * @return string
223         */
224        private function add_empty_option( $field ) {
225                $show_empty_option = $field->data( 'show_empty_option', null );
226
227                if ( is_null( $show_empty_option ) ) {
228                        $show_empty_option = ! $field->has_validator( 'required' );
229                }
230
231                $html = '';
232                if ( $show_empty_option ) {
233                        $default_label      = __( '— None —', 'business-directory-plugin' );
234                        $empty_option_label = $field->data( 'empty_option_label', $default_label );
235                        $html              .= '<option value="">' . esc_html( $empty_option_label ) . '</option>';
236                }
237                return $html;
238        }
239
240        /**
241         * @since 6.4.4
242         *
243         * @return string
244         */
245        private function add_options_to_field( $options, $value, $field ) {
246                $html = '';
247
248                $selected = $this->get_field_selected_value( $field );
249
250                foreach ( $options as $option => $label ) {
251                        $option_data = array(
252                                'label'      => $label,
253                                'attributes' => array(),
254                                'value'      => $option,
255                        );
256
257                        if (
258                                ( ! empty( $selected ) && $option === $selected ) ||
259                                // phpcs:ignore
260                                in_array( $option, $value )
261                        ) {
262                                $option_data['attributes']['selected'] = 'selected';
263                        }
264
265                        $option_data = apply_filters( 'wpbdp_form_field_select_option', $option_data, $field );
266
267                        $html .= sprintf(
268                                '<option value="%s" class="%s" %s>%s</option>',
269                                // phpcs:ignore
270                                $this->is_multiple() && $field->get_association() == 'meta' ? esc_attr( $option_data['label'] ) : esc_attr( $option_data['value'] ),
271                                esc_attr( 'wpbdp-inner-field-option wpbdp-inner-field-option-' . WPBDP_Form_Field_Type::normalize_name( $option_data['label'] ) ),
272                                self::html_attributes( $option_data['attributes'], array( 'value', 'class' ) ),
273                                esc_html( $option_data['label'] )
274                        );
275                }
276                return $html;
277        }
278
279        /**
280         * If only one category, use a hidden field.
281         *
282         * @since 5.10
283         */
284        protected function add_hidden_field( $args ) {
285                $value = $args['selected'];
286                return '<input type="hidden" name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['id'] ) . '" value="' . esc_attr( $value ) . '"/>';
287        }
288
289        public function get_supported_associations() {
290                return array( 'category', 'tags', 'meta', 'region' );
291        }
292
293        public function render_field_settings( &$field = null, $association = null ) {
294                return self::render_admin_settings( $this->get_field_settings( $field, $association ) );
295        }
296
297        protected function get_field_settings( $field = null, $association = null ) {
298                if ( $association != 'meta' && $association != 'tags' ) {
299                        return array();
300                }
301
302                $settings = array();
303
304                $settings['options'][] = esc_html__( 'Field Options (for select lists, radio buttons and checkboxes).', 'business-directory-plugin' ) . '<span class="description">(' . esc_html__( 'required', 'business-directory-plugin' ) . ')</span>';
305
306                $content  = '<span class="description">' . esc_html__( 'One option per line', 'business-directory-plugin' ) . '</span><br />';
307                $content .= '<textarea name="field[x_options]" cols="50" rows="2">';
308
309                if ( $field && $field->data( 'options' ) ) {
310                        $content .= esc_html( implode( "\n", $field->data( 'options' ) ) );
311                }
312                $content .= '</textarea>';
313
314                $settings['options'][] = $content;
315
316                $settings['empty_on_search'][] = esc_html__( 'Allow empty selection on search?', 'business-directory-plugin' );
317
318                $content  = '<span class="description">Empty search selection means users can make this field optional in searching. Turn it off if the field must always be searched on.</span><br />';
319                $content .= '<input type="checkbox" value="1" name="field[x_empty_on_search]" ' . ( ! $field ? ' checked="checked"' : ( $field->data( 'empty_on_search' ) ? ' checked="checked"' : '' ) ) . ' />';
320
321                $settings['empty_on_search'][] = $content;
322
323                return $settings;
324        }
325
326        /**
327         * @return void|WP_Error
328         */
329        public function process_field_settings( &$field ) {
330                if ( ! isset( $_POST['field']['x_options'] ) ) {
331                        return;
332                }
333
334                $options = trim( sanitize_textarea_field( wp_unslash( $_POST['field']['x_options'] ) ) );
335
336                if ( ! $options && $field->get_association() != 'tags' ) {
337                        return new WP_Error( 'wpbdp-invalid-settings', esc_html__( 'Field list of options is required.', 'business-directory-plugin' ) );
338                }
339
340                $options = $options ? array_map( 'trim', explode( "\n", $options ) ) : array();
341
342                if ( 'tags' === $field->get_association() ) {
343                        $tags = get_terms(
344                                array(
345                                        'taxonomy'   => WPBDP_TAGS_TAX,
346                                        'hide_empty' => false,
347                                        'fields'     => 'names',
348                                )
349                        );
350
351                        foreach ( array_diff( $options, $tags ) as $option ) {
352                                wp_insert_term( $option, WPBDP_TAGS_TAX );
353                        }
354                }
355
356                $field->set_data( 'options', $options );
357
358                if ( isset( $_POST['field']['x_empty_on_search'] ) ) {
359                        $empty_on_search = (bool) intval( $_POST['field']['x_empty_on_search'] );
360                        $field->set_data( 'empty_on_search', $empty_on_search );
361                }
362        }
363
364        public function store_field_value( &$field, $post_id, $value ) {
365                if ( $this->is_multiple() && $field->get_association() == 'meta' ) {
366                        if ( $value ) {
367                                $value = implode( "\t", is_array( $value ) ? $value : array( $value ) );
368                        }
369
370                        $this->store_field_selected_value( $field, $post_id, $value );
371                } elseif ( 'meta' == $field->get_association() ) {
372                        $value = is_array( $value ) ? ( ! empty( $value ) ? $value[0] : '' ) : $value;
373                }
374
375                parent::store_field_value( $field, $post_id, $value );
376        }
377
378        public function get_field_value( &$field, $post_id ) {
379                $value = parent::get_field_value( $field, $post_id );
380
381                if ( $this->is_multiple() && $field->get_association() == 'meta' ) {
382                        if ( ! empty( $value ) ) {
383                                return explode( "\t", $value );
384                        }
385                }
386
387                if ( ! $value ) {
388                        return array();
389                }
390
391                $value = is_array( $value ) ? $value : array( $value );
392                return $value;
393        }
394
395        public function get_field_html_value( &$field, $post_id ) {
396                if ( $field->get_association() == 'meta' ) {
397                        $value = $field->value( $post_id );
398
399                        return esc_attr( implode( ', ', $value ) );
400                }
401
402                return parent::get_field_html_value( $field, $post_id );
403        }
404
405        public function get_field_plain_value( &$field, $post_id ) {
406                $value = $field->value( $post_id );
407
408                if ( ! $value ) {
409                        return '';
410                }
411
412                if ( $field->get_association() === 'category' ) {
413                        $args       = array(
414                                'taxonomy'   => WPBDP_CATEGORY_TAX,
415                                'include'    => $value,
416                                'hide_empty' => 0,
417                                'fields'     => 'names',
418                        );
419                        $term_names = get_terms( $args );
420                        return join( ', ', $term_names );
421                } elseif ( $field->get_association() == 'tags' ) {
422                        return join( ', ', $value );
423                } elseif ( $field->get_association() == 'meta' ) {
424                        return esc_attr( implode( ', ', $value ) );
425                }
426
427                return $value;
428        }
429
430        /**
431         * @since 3.4.1
432         */
433        public function get_field_csv_value( &$field, $post_id ) {
434                if ( 'meta' != $field->get_association() ) {
435                        return $field->plain_value( $post_id );
436                }
437
438                $value = $field->value( $post_id );
439                return esc_attr( implode( ',', $value ) );
440        }
441
442        /**
443         * @since 5.0
444         */
445        public function configure_search( &$field, $query, &$search ) {
446                global $wpdb;
447
448                if ( 'meta' != $field->get_association() ) {
449                        return false;
450                }
451
452                $query = array_map( 'preg_quote', array_diff( is_array( $query ) ? $query : array( $query ), array( -1, '' ) ) );
453
454                if ( ! $query ) {
455                        return array();
456                }
457
458                $search_res             = array();
459                list( $alias, $reused ) = $search->join_alias( $wpdb->postmeta, false );
460
461                $search_res['join'] = $wpdb->prepare(
462                        " LEFT JOIN {$wpdb->postmeta} AS {$alias} ON ( {$wpdb->posts}.ID = {$alias}.post_id AND {$alias}.meta_key = %s )",
463                        '_wpbdp[fields][' . $field->get_id() . ']'
464                );
465
466                $pattern             = '(' . implode( '|', $query ) . '){1}([tab]{0,1})';
467                $search_res['where'] = $wpdb->prepare( "{$alias}.meta_value REGEXP %s", $pattern );
468
469                return $search_res;
470        }
471
472        public function is_empty_value( $value ) {
473                return empty( $value ) || ( is_array( $value ) && in_array( -1, $value ) );
474        }
475}
Note: See TracBrowser for help on using the repository browser.