Created
March 25, 2014 15:50
-
-
Save joshuaadickerson/9764759 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Every method is chainable | |
| * Instead of throwing errors, it throws exceptions | |
| * All exceptions should show the name of the method throwing it to make it easier to debug | |
| * | |
| * @todo throw exceptions if argument is not the appropriate type | |
| */ | |
| class ArrayChainable extends \ArrayObject | |
| { | |
| // parent::$container | |
| /** | |
| * @see array_change_key_case | |
| * @link http://www.php.net/manual/en/function.array-change-key-case.php | |
| * | |
| * @param int $case CASE_UPPER or CASE_LOWER | |
| * @return \ArrayChainable | |
| */ | |
| public function changeKeyCase($case) | |
| { | |
| $this->container = array_change_key_case($this->container, $case); | |
| return $this; | |
| } | |
| /** | |
| * @see array_chunk | |
| * @link http://www.php.net/manual/en/function.array-chunk.php | |
| * | |
| * @param int $size | |
| * @param bool $preserve_keys = false | |
| * @return \ArrayChainable | |
| * @throws ArrayException when $size is less than 1 | |
| */ | |
| public function chunk($size, $preserve_keys = false) | |
| { | |
| if ($size < 1) | |
| { | |
| throw new ArrayException('ArrayChainable::chunk() $size must be greater than 0'); | |
| } | |
| $this->container = array_chunk($this->container, (int) $size, (bool) $preserve_keys); | |
| return $this; | |
| } | |
| //array array_column ( array $array , mixed $column_key [, mixed $index_key = null ] ) | |
| public function column($column_key, $index_key = null) | |
| { | |
| $this->container = array_column($this->container, $column_key, $index_key); | |
| return $this; | |
| } | |
| // array array_combine ( array $keys , array $values ) | |
| public function combine(array $values) | |
| { | |
| $num_keys = count($this->container); | |
| $num_values = count($values); | |
| // The number of keys and values must match | |
| if ($num_keys !== $num_values) | |
| { | |
| throw new ArrayException('ArrayChainable::combine() the number of elements in the keys array is ' . $num_keys . ' and the number of elements in the values array is ' . $num_values . '. They must be equal.'); | |
| } | |
| $this->container = array_combine($this->container, $values); | |
| return $this; | |
| } | |
| // @todo return an array or change $container? | |
| // @todo throw an exception (meaning it requires going through it manually) or return E_WARNING? | |
| // @todo allow for recursive? | |
| public function count_values() | |
| { | |
| $count_values = array(); | |
| foreach ($this->container as $key => $value) | |
| { | |
| if (!is_int($value) || !is_string($value)) | |
| { | |
| throw new ArrayException('ArrayChainable::count_values() the value at ' . $key . ' is not an integer or string.'); | |
| } | |
| $count_values[$value]++; | |
| } | |
| $this->container = $count_values; | |
| return $this; | |
| } | |
| public function diff_assoc() | |
| { | |
| if (func_num_args() < 1) | |
| { | |
| throw new ArrayException('ArrayChainable::diff_assoc() must have at least one argument.'); | |
| } | |
| $arrays = func_get_args(); | |
| $this->container = call_user_func_array('array_diff_assoc', array_unshift($this->container, $arrays)); | |
| return $this; | |
| } | |
| public function diff_key() | |
| { | |
| if (func_num_args() < 1) | |
| { | |
| throw new ArrayException('ArrayChainable::diff_key() must have at least one argument.'); | |
| } | |
| $arrays = func_get_args(); | |
| $this->container = call_user_func_array('array_diff_key', array_unshift($this->container, $arrays)); | |
| return $this; | |
| } | |
| // array array_diff_uassoc ( array $array1 , array $array2 [, array $... ], callable $key_compare_func ) | |
| // @todo ew, the argument order is ugly | |
| public function diff_uassoc() | |
| { | |
| if (func_num_args() < 1) | |
| { | |
| throw new ArrayException('ArrayChainable::diff_uassoc() must have at least one argument.'); | |
| } | |
| $arrays = func_get_args(); | |
| if (!is_callable(end($arrays))) | |
| { | |
| throw new ArrayException('The last argument must be a callback.'); | |
| } | |
| $this->container = call_user_func_array('array_diff_uassoc', array_unshift($this->container, $arrays)); | |
| return $this; | |
| } | |
| // array array_diff_ukey ( array $array1 , array $array2 [, array $... ], callable $key_compare_func ) | |
| // @todo ew, the argument order is ugly | |
| public function diff_ukey() | |
| { | |
| if (func_num_args() < 1) | |
| { | |
| throw new ArrayException('ArrayChainable::diff_ukey() must have at least one argument.'); | |
| } | |
| $arrays = func_get_args(); | |
| if (!is_callable(end($arrays))) | |
| { | |
| throw new ArrayException('The last argument must be a callback.'); | |
| } | |
| $this->container = call_user_func_array('array_diff_ukey', array_unshift($this->container, $arrays)); | |
| return $this; | |
| } | |
| public function diff() | |
| { | |
| if (func_num_args() < 1) | |
| { | |
| throw new ArrayException('ArrayChainable::diff() must have at least one argument.'); | |
| } | |
| $arrays = func_get_args(); | |
| $this->container = call_user_func_array('array_diff', array_unshift($this->container, $arrays)); | |
| return $this; | |
| } | |
| public function fill_keys(array $keys, $value) | |
| { | |
| $this->container = array_fill_keys($keys, $value); | |
| return $this; | |
| } | |
| // array array_fill ( int $start_index , int $num , mixed $value ) | |
| public function fill($start_index, $num, $value) | |
| { | |
| if ((int) $num < 1) | |
| { | |
| throw new ArrayException('ArrayChainable::fill() $num must be greater than 0; "' . $num . '" given.'); | |
| } | |
| $this->container = array_fill((int) $start_index, (int) $num, $value); | |
| return $this; | |
| } | |
| // array array_filter ( array $array [, callable $callback ] ) | |
| public function filter($callback = null) | |
| { | |
| $this->container = array_filter($this->container, $callback); | |
| return $this; | |
| } | |
| public function flip() | |
| { | |
| $this->container = array_flip($this->container); | |
| return $this; | |
| } | |
| // array array_intersect_assoc ( array $array1 , array $array2 [, array $... ] ) | |
| public function intersect_assoc() | |
| { | |
| if (func_num_args() < 1) | |
| { | |
| throw new ArrayException('ArrayChainable::intersect_assoc() must have at least one argument.'); | |
| } | |
| $arrays = array_unshift($this->container, func_get_args()); | |
| $this->container = call_user_func_array('array_intersect_assoc', $arrays); | |
| return $this; | |
| } | |
| // array array_intersect_assoc ( array $array1 , array $array2 [, array $... ] ) | |
| public function intersect_key() | |
| { | |
| if (func_num_args() < 1) | |
| { | |
| throw new ArrayException('ArrayChainable::intersect_key() must have at least one argument.'); | |
| } | |
| $arrays = array_unshift($this->container, func_get_args()); | |
| $this->container = call_user_func_array('array_intersect_key', $arrays); | |
| return $this; | |
| } | |
| public function intersect_uassoc() | |
| { | |
| if (func_num_args() < 1) | |
| { | |
| throw new ArrayException('ArrayChainable::intersect_uassoc() must have at least one argument.'); | |
| } | |
| $arrays = func_get_args(); | |
| if (!is_callable(end($arrays))) | |
| { | |
| throw new ArrayException('The last argument must be a callback.'); | |
| } | |
| $this->container = call_user_func_array('array_intersect_uassoc', array_unshift($this->container, $arrays)); | |
| return $this; | |
| } | |
| public function intersect_ukey() | |
| { | |
| if (func_num_args() < 1) | |
| { | |
| throw new ArrayException('ArrayChainable::intersect_ukey() must have at least one argument.'); | |
| } | |
| $arrays = func_get_args(); | |
| if (!is_callable(end($arrays))) | |
| { | |
| throw new ArrayException('ArrayChainable::intersect_ukey() the last argument must be a callback.'); | |
| } | |
| $this->container = call_user_func_array('array_intersect_ukey', array_unshift($this->container, $arrays)); | |
| return $this; | |
| } | |
| public function intersect() | |
| { | |
| if (func_num_args() < 1) | |
| { | |
| throw new ArrayException('ArrayChainable::intersect() must have at least one argument.'); | |
| } | |
| $arrays = array_unshift($this->container, func_get_args()); | |
| $this->container = call_user_func_array('array_intersect', $arrays); | |
| return $this; | |
| } | |
| // skip array_key_exists() as it is already done via ArrayObject::offsetExists() | |
| public function keys($search_value = null, $strict = false) | |
| { | |
| $this->container = array_keys($this->container, $search_value, (bool) $strict); | |
| return $this; | |
| } | |
| // array array_map ( callable $callback , array $array1 [, array $... ] ) | |
| public function map() | |
| { | |
| if (func_num_args() < 2) | |
| { | |
| throw new ArrayException('ArrayChainable::map() must have at least two arguments'); | |
| } | |
| $args = func_get_args(); | |
| $callback = shift($args); | |
| if (!is_callable($callback)) | |
| { | |
| throw new ArrayException('ArrayChainable::map() the first argument must be a callback.'); | |
| } | |
| $this->container = call_user_func_array('array_intersect_uassoc', array_merge(array($callback, $this->container), $args)); | |
| return $this; | |
| } | |
| // @todo even though array_merge_recursive() only requires one argument, maybe throw an exception if only one is given? | |
| public function merge_recursive() | |
| { | |
| $arrays = array_unshift($this->container, func_get_args()); | |
| $this->container = call_user_func_array('array_merge_recursive', $arrays); | |
| return $this; | |
| } | |
| // @todo even though array_merge() only requires one argument, maybe throw an exception if only one is given? | |
| public function merge() | |
| { | |
| $arrays = array_unshift($this->container, func_get_args()); | |
| $this->container = call_user_func_array('array_merge', $arrays); | |
| return $this; | |
| } | |
| public function multisort() | |
| { | |
| $arrays = array_unshift($this->container, func_get_args()); | |
| $result = call_user_func_array('array_multisort', $arrays); | |
| if (!$result) | |
| { | |
| throw new ArrayException('ArrayChainable::multisort() failed to sort the array'); | |
| } | |
| $this->container = $arrays[0]; | |
| return $this; | |
| } | |
| public function pad($size, $value) | |
| { | |
| $this->container = array_pad($this->container, (int) $size, $value); | |
| return $this; | |
| } | |
| // skipping array_pop | |
| public function push() | |
| { | |
| $this->container = array_merge($this->container, func_get_args()); | |
| return $this; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| class ArrayException extends \Exception | |
| { | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| class SuperArray extends ArrayChainable | |
| { | |
| public function pop() | |
| { | |
| return array_pop($this->container); | |
| } | |
| public function key_exists($key) | |
| { | |
| return array_key_exists($key, $this->container); | |
| } | |
| public function product() | |
| { | |
| return array_product($this->container); | |
| } | |
| public function push() | |
| { | |
| $this->container = array_merge($this->container, func_get_args()); | |
| return $this->count(); | |
| } | |
| public function rand($num = 1) | |
| { | |
| $num = (int) $num; | |
| $count = $this->count(); | |
| if ($num > $count) | |
| { | |
| throw new ArrayException('SuperArray::rand() $num cannot be greater than the number of elements in the array. Number of elements is ' . $count . ' and $num is ' . $num); | |
| } | |
| return array_rand($this->container, (int) $num); | |
| } | |
| public function reduce(callable $callback, $initial = null) | |
| { | |
| return array_reduce($this->container, $callback, $initial); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment