From 7c2fe8b8db3c903b4260071eab7c2f3a5180642d Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Fri, 25 Sep 2020 13:24:47 -0400 Subject: [PATCH] Update $sanitizer array methods to support a 'keySanitizer' option that enables one to also sanitize associative arrays when needed --- wire/core/Sanitizer.php | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/wire/core/Sanitizer.php b/wire/core/Sanitizer.php index 4487b321..83ec99e6 100644 --- a/wire/core/Sanitizer.php +++ b/wire/core/Sanitizer.php @@ -3820,7 +3820,8 @@ class Sanitizer extends Wire { * @param array $options Optional modifications to default behavior: * - `maxItems` (int): Maximum items allowed in each array (default=0, which means no limit) * - `maxDepth` (int): Max nested array depth (default=0, which means no nesting allowed) Since 3.0.160 - * - `sanitizer` (string): Optionally specify sanitizer as option rather than argument (default='') Since 3.0.165 + * - `sanitizer` (string): Optionally specify sanitizer for array values as option rather than argument (default='') Since 3.0.165 + * - `keySanitizer` (string): Optionally sanitize associative array keys with this method (default='') Since 3.0.167 * - The following options are only used if the provided $value is a string: * - `csv` (bool): Allow conversion of delimited string to array? (default=true) Since 3.0.165 * - `delimiter` (string): Single delimiter to use to identify CSV strings. Overrides the 'delimiters' option when specified (default=null) @@ -3842,6 +3843,7 @@ class Sanitizer extends Wire { 'delimiters' => array('|', ','), 'enclosure' => '"', 'sanitizer' => null, + 'keySanitizer' => null, ); if(is_array($sanitizer) && empty($options)) list($options, $sanitizer) = array($sanitizer, null); @@ -3899,12 +3901,20 @@ class Sanitizer extends Wire { if($options['maxItems'] && count($value) > $options['maxItems']) { $value = array_slice($value, 0, abs($options['maxItems'])); } + + $keySanitizer = $options['keySanitizer']; - if($sanitizer) { - if(!method_exists($this, $sanitizer) && !method_exists($this, "___$sanitizer")) { - throw new WireException("Unknown sanitizer method: $sanitizer"); + if($sanitizer || $keySanitizer) { + foreach(array($sanitizer, $keySanitizer) as $method) { + if($method && !method_exists($this, $method) && !method_exists($this, "___$method")) { + throw new WireException("Unknown sanitizer method: $method"); + } } foreach($value as $k => $v) { + if($keySanitizer && !is_int($k)) { + $k = $this->$keySanitizer($k); + if(!strlen($k)) continue; + } if($options['maxDepth'] > 0 && is_array($v)) { $clean[$k] = $v; // array already sanitized by recursive call } else { @@ -3915,7 +3925,7 @@ class Sanitizer extends Wire { $clean = $value; } - return array_values($clean); + return $keySanitizer ? $clean : array_values($clean); } /** @@ -3930,6 +3940,7 @@ class Sanitizer extends Wire { * - `maxItems` (int): Maximum items allowed in each array (default=0, which means no limit) * - `maxDepth` (int): Max nested array depth (default=0, which means no nesting allowed) * - `sanitizer` (string): Optionally specify sanitizer method name to apply to items (default='') + * - `keySanitizer` (string): Optionally sanitize associative array keys with this method (default='') Since 3.0.167 * @return array * @throws WireException * @since 3.0.165 @@ -3940,6 +3951,7 @@ class Sanitizer extends Wire { 'maxItems' => 0, 'maxDepth' => 0, 'sanitizer' => is_string($options) ? $options : null, + 'keySanitizer' => null, 'csv' => false, ); $options = is_array($options) ? array_merge($defaults, $options) : $defaults;