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 79 if (is_string($offset)) $offset = strtolower($offset); 80 $originalOffset = $this->_keyMapping[$offset] ?? null; 81 unset($this->sourceArray[$originalOffset]); 82 unset($this->_keyMapping[$offset]); 83 84 } 85 86 public function offsetGet($offset) 87 { 88 if (is_string($offset)) $offset = strtolower($offset); 89 $sourceOffset = $this->_keyMapping[$offset] ?? null; 90 if ($sourceOffset === null) { 91 return null; 92 } 93 return $this->sourceArray[$sourceOffset] ?? null; 94 } 95 96 function getOriginalArray(): array 97 { 98 return $this->sourceArray; 99 } 100 101 102 public function current() 103 { 104 return $this->iterator->current(); 105 } 106 107 public function next() 108 { 109 $this->iterator->next(); 110 } 111 112 public function key() 113 { 114 return $this->iterator->key(); 115 } 116 117 public function valid(): bool 118 { 119 return $this->iterator->valid(); 120 } 121 122 public function rewind() 123 { 124 $obj = new ArrayObject($this->sourceArray); 125 $this->iterator = $obj->getIterator(); 126 } 127 128 public function count(): int 129 { 130 return sizeof($this->sourceArray); 131 } 132} 133