Overview

Namespaces

  • DSchoenbauer
    • DotNotation
      • Enum
      • Exception

Classes

  • DSchoenbauer\DotNotation\ArrayDotNotation
  • DSchoenbauer\DotNotation\Enum\ExceptionMessage

Interfaces

  • DSchoenbauer\DotNotation\Exception\ExceptionInterface

Exceptions

  • DSchoenbauer\DotNotation\Exception\InvalidArgumentException
  • DSchoenbauer\DotNotation\Exception\PathNotArrayException
  • DSchoenbauer\DotNotation\Exception\PathNotFoundException
  • DSchoenbauer\DotNotation\Exception\TargetNotArrayException
  • DSchoenbauer\DotNotation\Exception\UnexpectedValueException
  • Overview
  • Namespace
  • Class
  1: <?php
  2: 
  3: /*
  4:  * The MIT License
  5:  *
  6:  * Copyright 2016 David Schoenbauer <dschoenbauer@gmail.com>.
  7:  *
  8:  * Permission is hereby granted, free of charge, to any person obtaining a copy
  9:  * of this software and associated documentation files (the "Software"), to deal
 10:  * in the Software without restriction, including without limitation the rights
 11:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12:  * copies of the Software, and to permit persons to whom the Software is
 13:  * furnished to do so, subject to the following conditions:
 14:  *
 15:  * The above copyright notice and this permission notice shall be included in
 16:  * all copies or substantial portions of the Software.
 17:  *
 18:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24:  * THE SOFTWARE.
 25:  */
 26: 
 27: namespace DSchoenbauer\DotNotation;
 28: 
 29: use DSchoenbauer\DotNotation\Exception\PathNotArrayException;
 30: use DSchoenbauer\DotNotation\Exception\PathNotFoundException;
 31: use DSchoenbauer\DotNotation\Exception\TargetNotArrayException;
 32: use DSchoenbauer\DotNotation\Exception\UnexpectedValueException;
 33: 
 34: /**
 35:  * An easier way to deal with complex PHP arrays
 36:  * 
 37:  * @author David Schoenbauer
 38:  * @version 1.0.1
 39:  */
 40: class ArrayDotNotation {
 41: 
 42:     /**
 43:      * Property that houses the data that the dot notation should access
 44:      * @var array
 45:      */
 46:     private $_data = [];
 47: 
 48:     /**
 49:      * An alias for setData 
 50:      * 
 51:      * @see ArrayDotNotation::setData()
 52:      * @since 1.0.0
 53:      * @param array $data Array of data that will be accessed via dot notation.
 54:      */
 55:     public function __construct(array $data = []) {
 56:         $this->setData($data);
 57:     }
 58: 
 59:     /**
 60:      * returns the array
 61:      * 
 62:      * returns the array that the dot notation has been used on.
 63:      * 
 64:      * @since 1.0.0
 65:      * @return array Array of data that will be accessed via dot notation.
 66:      */
 67:     public function getData() {
 68:         return $this->_data;
 69:     }
 70: 
 71:     /**
 72:      * sets the array that the dot notation will be used on.
 73:      * 
 74:      * @since 1.0.0
 75:      * @param array $data Array of data that will be accessed via dot notation.
 76:      * @return $this
 77:      */
 78:     public function setData(array $data) {
 79:         $this->_data = $data;
 80:         return $this;
 81:     }
 82: 
 83:     /**
 84:      * Retrieves a value from an array structure as defined by a dot notation string
 85:      * 
 86:      * Returns a value from an array. 
 87:      * 
 88:      * @since 1.0.0
 89:      * @param string $dotNotation a string of keys concatenated together by a dot that represent different levels of an array
 90:      * @param mixed $defaultValue value to return if the dot notation does not find a valid key
 91:      * @return mixed value found via dot notation in the array of data
 92:      */
 93:     public function get($dotNotation, $defaultValue = null) {
 94:         return $this->recursiveGet($this->getData(), explode('.', $dotNotation), $defaultValue);
 95:     }
 96: 
 97:     /**
 98:      * Recursively works though an array level by level until the final key is found. Once key is found the keys value is returned.
 99:      * @since 1.0.0
100:      * @param array $data array that has value to be retrieved
101:      * @param array $keys array of keys for each level of the array
102:      * @param mixed $defaultValue value to return when a key is not found
103:      * @return mixed value that the keys find in the data array
104:      */
105:     protected function recursiveGet($data, $keys, $defaultValue) {
106:         $key = array_shift($keys);
107:         if (is_array($data) && $key && count($keys) == 0) { //Last Key
108:             return array_key_exists($key, $data) ? $data[$key] : $defaultValue;
109:         } elseif (is_array($data) && array_key_exists($key, $data)) {
110:             return $this->recursiveGet($data[$key], $keys, $defaultValue);
111:         }
112:         return $defaultValue;
113:     }
114: 
115:     /**
116:      * sets a value into a complicated array data structure
117:      * 
118:      * Places a value into a tiered array. A dot notation of "one.two.three" 
119:      * would place the value at ['one' => ['two' => ['three' => 'valueHere' ]]]
120:      * If the array does not exist it will be added. Indexed arrays can be used,
121:      * and referenced by number. i.e. "one.0" would return the first item of the 
122:      * one array.
123:      * 
124:      * @since 1.0.0
125:      * @param string $dotNotation dot notation representation of keys of where to set a value
126:      * @param mixed $value any value to be stored with in a key structure of dot notation
127:      * @return $this
128:      * @throws PathNotArrayException if a value in the dot notation path is not an array
129:      */
130:     public function set($dotNotation, $value) {
131:         $this->recursiveSet($this->_data, explode('.', $dotNotation), $value);
132:         return $this;
133:     }
134: 
135:     /**
136:      * Transverses the keys array until it reaches the appropriate key in the data array and sets that key to the value.
137:      * If the keys don't exist they are created.
138:      * 
139:      * @since 1.0.0
140:      * @param array $data data to be traversed
141:      * @param array $keys the remaining keys of focus for the data array
142:      * @param mixed $value the value to be placed at the final key
143:      * @throws PathNotArrayException if a value in the dot notation path is not an array
144:      */
145:     protected function recursiveSet(array &$data, array $keys, $value) {
146:         $key = array_shift($keys);
147:         if ($key && count($keys) == 0) { //Last Key
148:             $data[$key] = $value;
149:         } else {
150:             if (!array_key_exists($key, $data)) {
151:                 $data[$key] = [];
152:             } elseif (!is_array($data[$key])) {
153:                 throw new Exception\PathNotArrayException($key);
154:             }
155:             $this->recursiveSet($data[$key], $keys, $value);
156:         }
157:     }
158: 
159:     /**
160:      * Merges two arrays together over writing existing values with new values, while adding new array structure to the data 
161:      * 
162:      * @since 1.1.0
163:      * @param string $dotNotation dot notation representation of keys of where to set a value
164:      * @param array $value array to be merged with an existing array
165:      * @return $this
166:      * @throws UnexpectedValueException if a value in the dot notation path is not an array
167:      * @throws TargetNotArrayException if the value in the dot notation target is not an array
168:      */
169:     public function merge($dotNotation, array $value) {
170:         $target = $this->get($dotNotation, []);
171:         if (!is_array($target)) {
172:             throw new Exception\TargetNotArrayException($dotNotation);
173:         }
174:         $this->set($dotNotation, array_merge_recursive($target, $value));
175:         return $this;
176:     }
177: 
178:     /**
179:      * Removes data from the array
180:      * 
181:      * @since 1.1.0
182:      * @param string $dotNotation dot notation representation of keys of where to remove a value
183:      * @return $this
184:      */
185:     public function remove($dotNotation) {
186:         $this->recursiveRemove($this->_data, explode('.', $dotNotation), $dotNotation);
187:         return $this;
188:     }
189: 
190:     /**
191:      * Transverses the keys array until it reaches the appropriate key in the data array and then deletes the value from the key.
192:      * 
193:      * @since 1.1.0
194:      * @param array $data data to be traversed
195:      * @param array $keys the remaining keys of focus for the data array
196:      * @throws UnexpectedValueException if a value in the dot notation path is not an array
197:      */
198:     protected function recursiveRemove(array &$data, array $keys) {
199:         $key = array_shift($keys);
200:         if (!array_key_exists($key, $data)) {
201:             throw new PathNotFoundException($key);
202:         } elseif ($key && count($keys) == 0) { //Last Key
203:             unset($data[$key]);
204:         } elseif (!is_array($data[$key])) {
205:             throw new PathNotArrayException($key);
206:         } else {
207:             $this->recursiveRemove($data[$key], $keys);
208:         }
209:     }
210: 
211: }
212: 
API documentation generated by ApiGen