class-redux-select.php (7816B)
1 <?php 2 /** 3 * Select Field. 4 * 5 * @package ReduxFramework/Fields 6 * @author Dovy Paukstys & Kevin Provance (kprovance) 7 * @version 4.0.0 8 */ 9 10 defined( 'ABSPATH' ) || exit; 11 12 if ( ! class_exists( 'Redux_Select', false ) ) { 13 14 /** 15 * Class Redux_Select 16 */ 17 class Redux_Select extends Redux_Field { 18 19 /** 20 * Set field defaults. 21 */ 22 public function set_defaults() { 23 $defaults = array( 24 'options' => array(), 25 'width' => '40%', 26 'multi' => false, 27 'sortable' => false, 28 'ajax' => false, 29 'min-input-length' => 1, 30 'placeholder' => '', 31 ); 32 33 $this->field = wp_parse_args( $this->field, $defaults ); 34 } 35 36 /** 37 * Field Render Function. 38 * Takes the vars and outputs the HTML for the field in the settings 39 * 40 * @since ReduxFramework 1.0.0 41 */ 42 public function render() { 43 $sortable = ( isset( $this->field['sortable'] ) && true === (bool) $this->field['sortable'] ) ? ' select2-sortable' : ''; 44 45 if ( ! empty( $sortable ) ) { // Dummy proofing :P. 46 $this->field['multi'] = true; 47 } 48 49 if ( ! empty( $this->field['data'] ) && empty( $this->field['options'] ) ) { 50 if ( empty( $this->field['args'] ) ) { 51 $this->field['args'] = array(); 52 } 53 54 if ( 'elusive-icons' === $this->field['data'] || 'elusive-icon' === $this->field['data'] || 'elusive' === $this->field['data'] ) { 55 $icons_file = Redux_Core::$dir . 'inc/fields/select/elusive-icons.php'; 56 57 /** 58 * Filter 'redux-font-icons-file}' 59 * 60 * @param array $icon_file The File for the icons 61 */ 62 63 // phpcs:ignore WordPress.NamingConventions.ValidHookName 64 $icons_file = apply_filters( 'redux-font-icons-file', $icons_file ); 65 66 /** 67 * Filter 'redux/{opt_name}/field/font/icons/file' 68 * 69 * @param array $icon_file The file for the icons 70 */ 71 72 // phpcs:ignore WordPress.NamingConventions.ValidHookName 73 $icons_file = apply_filters( "redux/{$this->parent->args['opt_name']}/field/font/icons/file", $icons_file ); 74 75 if ( file_exists( $icons_file ) ) { 76 include_once $icons_file; 77 } 78 } 79 80 // First one get with AJAX. 81 $ajax = false; 82 if ( isset( $this->field['ajax'] ) && $this->field['ajax'] ) { 83 $ajax = true; 84 } 85 $this->field['options'] = $this->parent->wordpress_data->get( $this->field['data'], $this->field['args'], $this->parent->args['opt_name'], $this->value, $ajax ); 86 } 87 88 if ( ! empty( $this->field['data'] ) && in_array( $this->field['data'], array( 'elusive-icons', 'elusive-icon', 'elusive', 'dashicons', 'dashicon', 'dash' ), true ) ) { 89 $this->field['class'] .= ' font-icons'; 90 } 91 92 if ( ! empty( $this->field['options'] ) ) { 93 $multi = ( isset( $this->field['multi'] ) && $this->field['multi'] ) ? ' multiple="multiple"' : ''; 94 95 if ( ! empty( $this->field['width'] ) ) { 96 $width = ' style="width:' . esc_attr( $this->field['width'] ) . '"'; 97 } else { 98 $width = ' style="width:40%;"'; 99 } 100 101 $name_brackets = ''; 102 if ( ! empty( $multi ) ) { 103 $name_brackets = '[]'; 104 } 105 106 $placeholder = ( isset( $this->field['placeholder'] ) ) ? esc_attr( $this->field['placeholder'] ) : esc_html__( 'Select an item', 'redux-framework' ); 107 108 $select2_width = 'resolve'; 109 if ( '' !== $multi ) { 110 $select2_width = '100%'; 111 } 112 $this->select2_config['width'] = $select2_width; 113 $this->select2_config['allowClear'] = true; 114 115 if ( isset( $this->field['ajax'] ) && $this->field['ajax'] && isset( $this->field['data'] ) && '' !== $this->field['data'] ) { 116 $this->select2_config['ajax'] = true; 117 $this->select2_config['min-input-length'] = $this->field['min_input_length'] ?? 1; 118 $this->select2_config['action'] = "redux_{$this->parent->args['opt_name']}_select2"; 119 if ( isset( $this->field['args'] ) ) { 120 $this->select2_config['args'] = wp_json_encode( $this->field['args'] ); 121 } 122 $this->select2_config['nonce'] = wp_create_nonce( "redux_{$this->parent->args['opt_name']}_select2" ); 123 $this->select2_config['wp-data'] = $this->field['data']; 124 } 125 126 if ( isset( $this->field['select2'] ) ) { 127 $this->field['select2'] = wp_parse_args( $this->field['select2'], $this->select2_config ); 128 } else { 129 $this->field['select2'] = $this->select2_config; 130 } 131 132 $this->field['select2'] = Redux_Functions::sanitize_camel_case_array_keys( $this->field['select2'] ); 133 134 $select2_data = Redux_Functions::create_data_string( $this->field['select2'] ); 135 136 if ( isset( $this->field['multi'] ) && $this->field['multi'] && isset( $this->field['sortable'] ) && $this->field['sortable'] && ! empty( $this->value ) && is_array( $this->value ) ) { 137 $orig_option = $this->field['options']; 138 $this->field['options'] = array(); 139 140 foreach ( $this->value as $value ) { 141 $this->field['options'][ $value ] = $orig_option[ $value ]; 142 } 143 144 if ( count( $this->field['options'] ) < count( $orig_option ) ) { 145 foreach ( $orig_option as $key => $value ) { 146 if ( ! in_array( $key, $this->field['options'], true ) ) { 147 $this->field['options'][ $key ] = $value; 148 } 149 } 150 } 151 } 152 153 $sortable = ( isset( $this->field['sortable'] ) && $this->field['sortable'] ) ? ' select2-sortable' : ''; 154 155 echo '<select ' . 156 esc_html( $multi ) . ' 157 id="' . esc_attr( $this->field['id'] ) . '-select" 158 data-placeholder="' . esc_attr( $placeholder ) . '" 159 name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . esc_attr( $name_brackets ) . '" 160 class="redux-select-item ' . esc_attr( $this->field['class'] ) . esc_attr( $sortable ) . '"' . 161 $width . ' rows="6"' . esc_attr( $select2_data ) . '>'; // phpcs:ignore WordPress.Security.EscapeOutput 162 163 echo '<option></option>'; 164 165 foreach ( $this->field['options'] as $k => $v ) { 166 if ( is_array( $v ) ) { 167 echo '<optgroup label="' . esc_attr( $k ) . '">'; 168 169 foreach ( $v as $opt => $val ) { 170 $this->make_option( (string) $opt, $val, $k ); 171 } 172 173 echo '</optgroup>'; 174 175 continue; 176 } 177 178 $this->make_option( (string) $k, $v ); 179 } 180 181 echo '</select>'; 182 } else { 183 echo '<strong>' . esc_html__( 'No items of this type were found.', 'redux-framework' ) . '</strong>'; 184 } 185 } 186 187 /** 188 * Compile option HTML. 189 * 190 * @param string $id HTML ID. 191 * @param mixed $value Value array. 192 * @param string $group_name Group name. 193 */ 194 private function make_option( string $id, $value, string $group_name = '' ) { 195 if ( is_array( $this->value ) ) { 196 $selected = ( in_array( $id, $this->value, true ) ) ? ' selected="selected"' : ''; 197 } else { 198 $selected = selected( $this->value, $id, false ); 199 } 200 201 echo '<option value="' . esc_attr( $id ) . '" ' . esc_html( $selected ) . '>' . esc_attr( $value ) . '</option>'; 202 } 203 204 /** 205 * Enqueue Function. 206 * If this field requires any scripts, or css define this function and register/enqueue the scripts/css 207 * 208 * @since ReduxFramework 1.0.0 209 */ 210 public function enqueue() { 211 wp_enqueue_style( 'select2-css' ); 212 213 if ( isset( $this->field['sortable'] ) && $this->field['sortable'] ) { 214 wp_enqueue_script( 'jquery-ui-sortable' ); 215 } 216 217 wp_enqueue_script( 218 'redux-field-select-js', 219 Redux_Core::$url . 'inc/fields/select/redux-select' . Redux_Functions::is_min() . '.js', 220 array( 'jquery', 'select2-js', 'redux-js' ), 221 $this->timestamp, 222 true 223 ); 224 225 if ( $this->parent->args['dev_mode'] ) { 226 wp_enqueue_style( 227 'redux-field-select-css', 228 Redux_Core::$url . 'inc/fields/select/redux-select.css', 229 array(), 230 $this->timestamp 231 ); 232 } 233 } 234 } 235 } 236 237 class_alias( 'Redux_Select', 'ReduxFramework_Select' );