1<?php 2 3 4namespace ComboStrap; 5 6 7use ArrayAccess; 8use ArrayObject; 9use Countable; 10 11/** 12 * Class ArrayCaseInsensitive 13 * @package ComboStrap 14 * 15 * Wrapper around an array to make it case access insensitive 16 */ 17class ArrayCaseInsensitive implements ArrayAccess, \Iterator, Countable 18{ 19 20 /** 21 * A mapping between lower key and original key (ie offset) 22 * @var array 23 */ 24 private array $_keyMapping = array(); 25 /** 26 * @var array 27 */ 28 private array $sourceArray; 29 /** 30 * @var false|mixed 31 */ 32 private $valid; 33 private int $iteratorIndex = 0; 34 /** 35 * @var \ArrayIterator 36 */ 37 private \ArrayIterator $iterator; 38 39 40 public function __construct(array &$source = array()) 41 { 42 $this->sourceArray = &$source; 43 array_walk($source, function ($value, &$key) { 44 $this->_keyMapping[strtolower($key)] = $key; 45 }); 46 47 /** 48 * Iterator 49 */ 50 $this->rewind(); 51 } 52 53 public function offsetSet($offset, $value) 54 { 55 56 if (is_null($offset)) { 57 LogUtility::msg("The offset (key) is null and this is not supported"); 58 } else { 59 if (is_string($offset)) { 60 $lowerCaseOffset = strtolower($offset); 61 $this->_keyMapping[$lowerCaseOffset] = $offset; 62 $this->sourceArray[$offset] = $value; 63 } else { 64 LogUtility::msg("The offset should be a string", LogUtility::LVL_MSG_ERROR); 65 } 66 67 } 68 } 69 70 public function offsetExists($offset): bool 71 { 72 if (is_string($offset)) $offset = strtolower($offset); 73 return isset($this->_keyMapping[$offset]); 74 } 75 76 public function offsetUnset($offset) 77 { 78 if (is_string($offset)) $offset = strtolower($offset); 79 $originalOffset = $this->_keyMapping[$offset]; 80 unset($this->sourceArray[$originalOffset]); 81 unset($this->_keyMapping[$offset]); 82 83 } 84 85 public function offsetGet($offset) 86 { 87 if (is_string($offset)) $offset = strtolower($offset); 88 $sourceOffset = $this->_keyMapping[$offset] ?? null; 89 if ($sourceOffset === null) { 90 return null; 91 } 92 return $this->sourceArray[$sourceOffset] ?? null; 93 } 94 95 function getOriginalArray(): array 96 { 97 return $this->sourceArray; 98 } 99 100 101 public function current() 102 { 103 return $this->iterator->current(); 104 } 105 106 public function next() 107 { 108 $this->iterator->next(); 109 } 110 111 public function key() 112 { 113 return $this->iterator->key(); 114 } 115 116 public function valid(): bool 117 { 118 return $this->iterator->valid(); 119 } 120 121 public function rewind() 122 { 123 $obj = new ArrayObject($this->sourceArray); 124 $this->iterator = $obj->getIterator(); 125 } 126 127 public function count(): int 128 { 129 return sizeof($this->sourceArray); 130 } 131} 132