<?php
/**
* TypedArrayObject is an extension of the ArrayObject class
* that adds type checking for each element added into the list.
*
* @package CompleteArrayObject
* @author Omar Ramos
* @version 1.0
* @copyright Copyright (C) 2009 Omar Ramos. All rights reserved.
* @license GNU Lesser General Public License, see http://www.gnu.org/licenses/lgpl.html
*/
class TypedArrayObject extends ArrayObject
{
protected $_type;
protected $_isBasicType;
/**
* Constructor Function
* This constructor function is a little special since you
* can instantiate the class in four ways:
*
* 1. Provide no arguments to the constructor and you can
* create a new, untyped instance of the class which will
* behave essentially the same as the default ArrayObject.
*
* 2. Give the constructor a string for the first
* argument and it will automatically use that value as the type.
* Useful for creating a new typed instance.
*
* 3. Give the constructor an array and it will
* use that array to start the list.
*
* 4. Give the constructor an array and a type and it will
* instantiate the class with that list and use that type when
* adding new items to the list.
*
* @param array $array
* @param string $type
*/
public function __construct($array = array(), $type = null)
{
$basicTypes = array('string', 'array', 'resource',
'float', 'double', 'real',
'int', 'integer', 'long',
'bool', 'boolean');
if (is_string($array)) {
$this->_type = $array;
$type = $array;
$this->_isBasicType = in_array(strtolower($type), $basicTypes);
$array = array();
}
elseif (is_array($array)) {
if (!empty($type))
{
$this->_type = (string) $type;
$this->_isBasicType = in_array(strtolower($type), $basicTypes);
foreach($array as $item)
{
$this->typeCheck($item);
}
}
else
{
$this->_type = null;
$this->_isBasicType = null;
}
}
parent::__construct($array);
}
/**
* @desc Overriding ArrayObject::append to add typechecking
* @param mixed $value - a value to append to the array
*
* @return int $count
*/
public function append($value)
{
$this->typeCheck($value);
parent::append($value);
return $this->count();
}
/**
* @desc Overriding ArrayObject::offsetSet to add typechecking; this method is called when values are set using the []
* @param mixed $index - the index of the array element to set
* @param mixed $value - the value to set
*
* @return void
*/
public function offsetSet($index, $value)
{
$this->typeCheck($value);
parent::offsetSet($index, $value);
}
/**
* @desc Overriding ArrayObject::exchangeArray to add typechecking
* @param array $array
*/
public function exchangeArray($array)
{
foreach($array as $value)
{
$this->typeCheck($value);
}
parent::exchangeArray($array);
}
/**
* @desc Type checking method
* @param mixed $val
*/
protected function typeCheck($val)
{
$type = $this->_type;
if (is_null($type))
{
return true;
}
if (!$this->_isBasicType)
{
// If it isn't a basic type then it should be an object
if (is_object($val))
{
if (!($val instanceof $type))
{
$this->typeExceptionMessage($val);
return;
}
}
else
{
$this->typeExceptionMessage($val);
return;
}
}
else
{
switch(strtolower($type))
{
case 'string':
if (!is_string($val))
{
$this->typeExceptionMessage($val);
}
break;
case 'array':
if (!is_array($val))
{
$this->typeExceptionMessage($val);
}
break;
case 'resource':
if (!is_resource($val))
{
$this->typeExceptionMessage($val);
}
break;
case 'float':
case 'double':
case 'real':
if (!is_float($val))
{
$this->typeExceptionMessage($val);
}
break;
case 'int':
case 'integer':
case 'long':
if (!is_int($val))
{
$this->typeExceptionMessage($val);
}
break;
case 'bool':
case 'boolean':
if (!is_bool($val))
{
$this->typeExceptionMessage($val);
}
break;
}
}
return true;
}
/**
* @desc Throws new InvalidArgumentException
*
* @throws InvalidArgumentException
*/
protected function typeExceptionMessage($val)
{
if (is_object($val))
{
throw new InvalidArgumentException("Value: " . get_class($val) . " supplied to " . get_class($this) . " is not of type: " . $this->_type);
}
else
{
throw new InvalidArgumentException("Value: " . $val . " supplied to " . get_class($this) . " is not of type: " . $this->_type);
}
}
/**
* @desc ToString Method
*
* @return string
*/
public function __toString()
{
return "<pre>" . print_r($this, true) . "</pre>";
}
}
/**
* CompleteArrayObject is an extension of the TypedArrayObject class that
* introduces some useful methods.
*
* @package CompleteArrayObject
* @author Omar Ramos
* @version 1.0
* @copyright Copyright (C) 2009 Omar Ramos. All rights reserved.
* @license GNU Lesser General Public License, see http://www.gnu.org/licenses/lgpl.html
*/
class CompleteArrayObject extends TypedArrayObject
{
/**
* @var string
*/
protected $_sortField;
/**
* @var string
*/
protected $_sortDirection;
/**
* Constructor Function
* This constructor function is a little special since you
* can instantiate the class in four ways:
*
* 1. Provide no arguments to the constructor and you can
* create a new, untyped instance of the class which will
* basically be an ArrayObject with all of the extra methods
* in this class available to it.
*
* 2. Give the constructor a string for the first
* argument and it will automatically use that value as the type.
* Useful for creating a new typed instance.
*
* 3. Give the constructor an array and it will
* use that array to start the list.
*
* 4. Give the constructor an array and a type and it will
* instantiate the class with that list and use that type when
* adding new items to the list.
*
* @param array $array
* @param string $type
*/
public function __construct($array = array(), $type = null)
{
if (is_string($array)) {
$type = $array;
$array = array();
}
elseif (is_array($array)) {
if (!empty($type)) {
$type = (string) $type;
} else {
$type = null;
}
}
parent::__construct($array, $type);
}
/**
* @desc Pops the last element off the end
* of the list and returns it, shortening
* the list by one element.
*
* @return mixed $popped
*/
public function pop()
{
$array = $this->getArrayCopy();
$popped = array_pop($array);
$this->exchangeArray($array);
return $popped;
}
/**
* @desc Pushes a new element onto the end
* of the list. lengthening the list by
* one element.
*
* @return int $count
*/
public function push($value)
{
$this->append($value);
}
/**
* @desc Shifts the first element off the
* beginning of the list and returns it,
* shortening the list by one element.
*
* @return mixed $popped
*/
public function shift()
{
$this->reverse();
$shifted = $this->pop();
$this->reverse();
return $shifted;
}
/**
* @desc Unshifts a new element onto the
* beginning of the list. lengthening the list by
* one element.
*
* @param mixed $value
* @return int $count
*/
public function unshift($value)
{
$this->reverse();
$count = $this->append($value);
$this->reverse();
return $count;
}
/**
* @desc Extracts a slice of the internal
* lists and returns it as a new CompleteArrayObject
*
* @param int $offset
* @param int $length
* @param boolean $preserve_keys
* @return CompleteArrayObject
*/
public function slice($offset, $length = 0, $preserve_keys = false)
{
$array = $this->getArrayCopy();
$slice = array_slice($array, (int) $offset, (int) $length, (bool) $preserve_keys);
return new self($slice);
}
/**
* @desc Removes a portion of the internal list
* and replaces it with something else. To add multiple
* values at the same time wrap your values in an array.
*
* @param int $offset
* @param int $length
* @param mixed $replacement
* @return CompleteArrayObject - containing the removed/replaced values
*/
public function splice($offset, $length = 0, $replacement = null)
{
$array = $this->getArrayCopy();
if (!empty($replacement)) {
if (is_array($replacement)) {
$spliced = array_splice($array, (int) $offset, (int) $length, $replacement);
} else {
$spliced = array_splice($array, (int) $offset, (int) $length, array($replacement));
}
} else {
$spliced = array_splice($array, (int) $offset, (int) $length);
}
$this->exchangeArray($array);
return new self($spliced);
}
/**
* @desc Shuffles the internal list
*
* @return boolean
*/
public function shuffle()
{
$array = $this->getArrayCopy();
$boolean = shuffle($array);
$this->exchangeArray($array);
return $boolean;
}
/**
* @desc Sort an array in reverse order and
* maintain index association.
*
* @return void
*/
public function arsort()
{
$array = $this->getArrayCopy();
arsort($array);
$this->exchangeArray($array);
}
/**
* @desc Sort an array by key in reverse order.
*
* @return void
*/
public function krsort()
{
$array = $this->getArrayCopy();
krsort($array);
$this->exchangeArray($array);
}
/**
* Convenience method for clearing
* the contents of the internal list.
*
* @return void
*/
public function clear()
{
$this->exchangeArray(array());
}
/**
* @desc Convenience method for checking
* whether the internal list is currently
* empty or not.
*
* @return boolean
*/
public function cleared()
{
return $this->count() == 0;
}
/**
* @desc Rearrange the list in reverse order
*
* @return void
*/
public function reverse()
{
$array = $this->getArrayCopy();
$array = array_reverse($array, true);
$this->exchangeArray($array);
}
/**
* This method takes in a field name and a sort
* direction and sorts array or object values
* using uasort.
*
* @param string $fieldName
* @param string $sortDirection - Valid values are 'asc', 'desc', 'ascending', and 'descending'
*
*/
public function sortByField($fieldName, $sortDirection = 'asc')
{
$this->_sortField = $fieldName;
$validDirections = array('asc', 'desc', 'ascending', 'descending');
if (in_array(strtolower($sortDirection), $validDirections)) {
$this->_sortDirection = substr($sortDirection, 0, 4);
}
else {
throw new InvalidArgumentException("Value: " . $sortDirection . " supplied to " . get_class($this) ."::sortByField is invalid. Expected: 'asc', 'desc', 'ascending', or 'descending'");
}
$array = $this->getArrayCopy();
uasort($array, array(&$this, '_fieldCompare'));
$this->exchangeArray($array);
}
/**
* This is the method that does the field comparing
* for objects and arrays
*/
protected function _fieldCompare($a, $b)
{
$sortField = $this->_sortField;
if (is_array($a) && is_array($b))
{
$al = $a[$sortField];
$bl = $b[$sortField];
}
elseif (is_object($a) && is_object($b))
{
$avars = get_object_vars($a);
$bvars = get_object_vars($b);
$ain = array_key_exists($sortField, get_object_vars($a));
$bin = array_key_exists($sortField, get_object_vars($b));
if ($ain && $bin)
{
$al = $a->$sortField;
$bl = $b->$sortField;
}
else
{
$get = 'get' . ucfirst($sortField);
if (method_exists($a, $get) && method_exists($b, $get))
{
$al = $a->$get();
$bl = $b->$get();
}
else
{
throw new InvalidArgumentException("Method: " . $get . "() supplied does not exist in ". get_class($a) ." or " . get_class($b) . ".");
}
}
}
else
{
$al = $a;
$al = $b;
}
if ($al == $bl) {
return 0;
}
if ($this->_sortDirection == 'asc') {
return ($al > $bl) ? -1 : +1;
}
if ($this->_sortDirection == 'desc') {
return ($al > $bl) ? +1 : -1;
}
}
/**
* @desc Creates a filtered key/values list determined by
* the field name given. Then this list is filtered for
* unique values and a new CompleteArrayObject instance
* is created.
*
* If field name is not provided, then the method will
* assume that the value is scalar and should be
* added to the list.
*
* @param string $fieldName
* @return CompleteArrayObject
*/
public function uniqueByField($fieldName = null)
{
$fieldValuesArray = $this->_fieldValuesArray($fieldName);
$array = array_unique($fieldValuesArray);
return new self($array);
}
/**
* @desc Convenience method for uniqueByField
* for CompleteArrayObjects that do not contain
* array or object values.
*
* @return CompleteArrayObject
*/
public function unique()
{
return $this->uniqueByField(null);
}
/**
* @desc Calculates the product of all the values in
* a particular array or object field
*
* @param string $fieldName
* @return float $product
*/
public function productByField($fieldName = null)
{
$fieldValuesArray = $this->_fieldValuesArray($fieldName);
$product = array_product($fieldValuesArray);
return $product;
}
/**
* @desc Convenience method for productByField
* for CompleteArrayObjects that do not contain
* array or object values.
*
* @return float $product
*/
public function product()
{
return $this->productByField(null);
}
/**
* @desc Calculates the sum of all the values in
* a particular array or object field
*
* @param string $fieldName
* @return float $sum
*/
public function sumByField($fieldName = null)
{
$fieldValuesArray = $this->_fieldValuesArray($fieldName);
$sum = array_sum($fieldValuesArray);
return $sum;
}
/**
* @desc Convenience method for sumByField
* for CompleteArrayObjects that do not contain
* array or object values.
*
* @return float $sum
*/
public function sum()
{
return $this->sumByField(null);
}
/**
* @desc Calculates the average of all the values in
* a particular array or object field
*
* @param string $fieldName
* @param integer $precision
* @return float $average
*/
public function avgByField($fieldName = null, $precision = 2)
{
$fieldValuesArray = $this->_fieldValuesArray($fieldName);
$count = count($fieldValuesArray);
$sum = array_sum($fieldValuesArray);
$average = round($sum / $count, (int) $precision);
return $average;
}
/**
* @desc Convenience method for avgByField
* for CompleteArrayObjects that do not contain
* array or object values.
*
* @param integer $precision
* @return float $average
*/
public function avg($precision = 2)
{
return $this->avgByField(null, $precision);
}
/**
* @desc Returns the maximum of all the values in
* a particular array or object field
*
* @param string $fieldName
* @return float $max
*/
public function maxByField($fieldName = null)
{
$fieldValuesArray = $this->_fieldValuesArray($fieldName);
$max = max($fieldValuesArray);
return $max;
}
/**
* @desc Convenience method for maxByField
* for CompleteArrayObjects that do not contain
* array or object values.
*
* @return float $max
*/
public function max()
{
return $this->maxByField(null);
}
/**
* @desc Returns the minimum of all the values in
* a particular array or object field
*
* @param string $fieldName
* @return float $min
*/
public function minByField($fieldName = null)
{
$fieldValuesArray = $this->_fieldValuesArray($fieldName);
$min = min($fieldValuesArray);
return $min;
}
/**
* @desc Convenience method for minByField
* for CompleteArrayObjects that do not contain
* array or object values.
*
* @return float $min
*/
public function min()
{
return $this->minByField(null);
}
/**
* @desc Returns the count of all occurrences of a
* particular value in a particular array or
* object field
*
* @param mixed $value
* @param string $fieldName
* @return integer $occurrences
*/
public function occurrencesByField($value, $fieldName = null)
{
$fieldValuesArray = $this->_fieldValuesArray($fieldName);
$occurrences = 0;
foreach($fieldValuesArray as $fieldValue)
{
if ($value == $fieldValue)
{
$occurrences++;
}
}
return $occurrences;
}
/**
* @desc Convenience method for CompleteArrayObjects
* that do not contain array or object values
*
* @param mixed $value
* @return integer $occurrences
*/
public function occurrences($value)
{
return $this->occurrencesByField($value, null);
}
/**
* @desc Given a field name, this method
* will return the value of the mode for that field wrapped in a
* CompleteArrayObject (this is because multiple values can be
* valid modes in a list). If return_count is true, then only
* the number of occurrences for the mode will be returned.
* If return_count is null, then this method will return
* the entire list of values grouped by occurrences and sorted
* in reverse key order (most occurrences first).
*
* The return_count flag switches between returning
* the value of the mode, or the number of occurrences
* of the mode.
*
* @param string $fieldName
* @param boolean $return_count
* @return mixed
*/
public function modeByField($fieldName = null, $return_count = false)
{
$fieldValuesArray = $this->_fieldValuesArray($fieldName);
$uniqueValues = array_unique($fieldValuesArray);
$occurrencesList = array();
foreach($uniqueValues as $value)
{
// This initializes each possible value
// with a starting value of 0
$occurrencesList[$value] = 0;
}
foreach($fieldValuesArray as $value)
{
$occurrencesList[$value]++;
}
if (is_null($return_count))
{
$occurrencesList = $this->group($occurrencesList);
$occurrencesList->krsort();
return $occurrencesList;
}
$modeCount = max($occurrencesList);
$modeValues = array_flip(array_keys($occurrencesList, $modeCount));
$modeValuesByOccurrence = array();
$modeValuesByOccurrence[$modeCount] = new self();
foreach($modeValues as $key => $value)
{
$modeValuesByOccurrence[$modeCount][] = $key;
}
if ($return_count)
{
return $modeCount;
}
if ($modeValuesByOccurrence[$modeCount]->count() == 1)
{
return $modeValuesByOccurrence[$modeCount]->shift();
}
return new self($modeValuesByOccurrence);
}
/**
* @desc Convenience method for modeByField method
* above. Useful only for CompleteArrayObjects
* where the values are not arrays or objects so there is
* no need to provide a field name.
*
* The return_count flag switches between returning
* the value of the mode, or the number of occurrences
* of the mode.
*
* @param boolean $return_count
* @return mixed
*/
public function mode($return_count = false)
{
return $this->modeByField(null, $return_count);
}
/**
* @desc Given a field name, this method
* calculates the minimum and maximum values
* for that field and then computes the difference
* (range) and returns the result.
*
* @return float
*/
public function rangeByField($fieldName = null)
{
$max = $this->maxByField($fieldName);
$min = $this->minByField($fieldName);
$range = $max - $min;
return $range;
}
/**
* @desc Convenience method for rangeByField
* above. Useful only for CompleteArrayObjects
* where the values are all numeric so there is
* no need to provide a field name.
*
* @return float
*/
public function range()
{
return $this->rangeByField(null);
}
/**
* @desc Filters all of the values in the current list
* according to the $value, $operator and $fieldName provided.
*
* Keys are preserved and if $exchange_array is set to true
* then the filtered list will replace the current list within
* the object.
*
* The method attempts to compare $value numerically if a
* numeric value is given and by string if a string is given.
* The string comparison is not case-sensitive.
*
* @param string $pattern
* @param string $operator
* @param string $fieldName
* @param boolean $exchange_array
* @return CompleteArrayObject
*/
public function filterByValue($value, $operator = '==', $fieldName = null, $exchange_array = false)
{
$array = $this->getArrayCopy();
$validOperators = array('==', '===', '!=', '!==', '<>', '<', '>', '<=', '>=');
$validOperator = in_array($operator, $validOperators);
$fieldValuesArray = $this->_fieldValuesArray($fieldName);
if ($validOperator)
{
$matchingKeys = array();
foreach($fieldValuesArray as $fieldKey => $fieldValue)
{
if (is_string($value))
{
$compared = strcasecmp($value, $fieldValue);
}
switch($operator)
{
case '==':
if (is_string($value))
{
if ($compared === 0)
{
$matchingKeys[] = $fieldKey;
}
}
elseif($fieldValue == $value)
{
$matchingKeys[] = $fieldKey;
}
break;
case '===':
if (is_string($value))
{
if ($compared === 0)
{
$matchingKeys[] = $fieldKey;
}
}
elseif($fieldValue === $value)
{
$matchingKeys[] = $fieldKey;
}
break;
case '!=':
case '<>':
if (is_string($value))
{
if ($compared != 0)
{
$matchingKeys[] = $fieldKey;
}
}
elseif($fieldValue != $value)
{
$matchingKeys[] = $fieldKey;
}
break;
case '!==':
if (is_string($value))
{
if ($compared !== 0)
{
$matchingKeys[] = $fieldKey;
}
}
elseif($fieldValue !== $value)
{
$matchingKeys[] = $fieldKey;
}
break;
case '<':
if (is_string($value))
{
if ($compared > 0)
{
$matchingKeys[] = $fieldKey;
}
}
elseif($fieldValue < $value)
{
$matchingKeys[] = $fieldKey;
}
break;
case '>':
if (is_string($value))
{
if ($compared < 0)
{
$matchingKeys[] = $fieldKey;
}
}
elseif($fieldValue > $value)
{
$matchingKeys[] = $fieldKey;
}
break;
case '<=':
if (is_string($value))
{
if ($compared > 0 || $compared === 0)
{
$matchingKeys[] = $fieldKey;
}
}
elseif($fieldValue <= $value)
{
$matchingKeys[] = $fieldKey;
}
break;
case '>=':
if (is_string($value))
{
if ($compared < 0 || $compared === 0)
{
$matchingKeys[] = $fieldKey;
}
}
elseif($fieldValue >= $value)
{
$matchingKeys[] = $fieldKey;
}
break;
}
}
$filteredArray = array();
foreach($matchingKeys as $matchingKey)
{
$filteredArray[$matchingKey] = $array[$matchingKey];
}
if ($exchange_array)
{
$this->exchangeArray($filteredArray);
return $this;
}
return new self($filteredArray, $this->getType());
}
throw new InvalidArgumentException("Operator Value: " . $operator . " supplied to " . get_class($this) ."::filterByValue is invalid. Expected: '==', '===', '!=', '!==', '<>', '<', '>', '<=', or '>='");
}
/**
* @desc Filters all of the values in the current list
* according to the $pattern and $fieldName provided.
* If $invert is true the returned object will contain
* all of the values that do not match the pattern.
* Keys are preserved and if $exchange_array is set to true
* then the filtered list will replace the current list within
* the object.
*
* @param string $pattern
* @param string $fieldName
* @param boolean $invert
* @param boolean $exchange_array
* @return CompleteArrayObject
*/
public function filterByRegex($pattern, $fieldName = null, $invert = false, $exchange_array = false)
{
$array = $this->getArrayCopy();
$fieldValuesArray = $this->_fieldValuesArray($fieldName);
$matchingKeys = preg_grep($pattern, $fieldValuesArray, $invert);
$filteredArray = array();
foreach($matchingKeys as $matchingKey => $matchingValue)
{
$filteredArray[$matchingKey] = $array[$matchingKey];
}
if ($exchange_array)
{
$this->exchangeArray($filteredArray);
return $this;
}
return new self($filteredArray, $this->getType());
}
/**
* @desc Groups all values in the list by the field name
* Each field name contains a list of all items that had that
* value.
*
* @param string $fieldName
* @param string $key
* @return CompleteArrayObject
*/
public function groupByField($fieldName = null, $key = null, $array = null)
{
if (is_null($array))
{
$array = $this->getArrayCopy();
}
if ($array instanceof ArrayObject)
{
$array = $array->getArrayCopy();
}
if (!is_array($array))
{
$array = (array) $array;
}
$children = array();
// first pass - collect children
foreach ($array as $itemkey => $item)
{
// Assigns the item's field name value to $pt
if (is_object($item))
{
if (array_key_exists($fieldName, get_object_vars($item)))
{
$pt = $item->$fieldName;
}
else
{
$get = 'get' . ucfirst($fieldName);
$pt = $item->$get();
}
}
if (is_array($item))
{
$pt = $item[$fieldName];
}
if (is_null($fieldName))
{
$pt = $item;
}
// Checks to see if the field name's value already exists
// in $children array. If so, then $list is
// set to that array, else a new array is created.
$list = @$children[$pt] ? $children[$pt] : new self();
// Add the current item to the end of the list
// array.
if (is_null($key))
{
$list[] = $item;
}
elseif ($key === true)
{
$list[] = $itemkey;
}
elseif (is_object($item))
{
if (array_key_exists($key, get_object_vars($item)))
{
$list[$item->$key] = $item;
}
else
{
$get = 'get' . ucfirst($key);
$list[$item->$get()] = $item;
}
}
elseif (is_array($item))
{
$list[$item[$key]] = $item;
}
// Assign $list as the value for when the key is
// equal to the current parent id.
$children[$pt] = $list;
}
return new self($children);
}
/**
* @desc Convenience method for groupByField
* above. Mostly useful for CompleteArrayObjects
* or arrays that are associative where you would
* like the keys grouped by the values.
*
* @param array $array
* @return CompleteArrayObject
*/
public function group($array = null)
{
return $this->groupByField(null, true, $array);
}
/**
* @desc Returns a new CompleteArrayObject containing
* the keys associated with a particular
* field name and value
*
* @param string $fieldName
* @param mixed $value
* @param boolean $allow_nulls
* @return CompleteArrayObject
*/
public function keys($fieldName = null, $value = null, $allow_nulls = false)
{
if (is_null($fieldName))
{
$array = $this->getArrayCopy();
}
else
{
$array = $this->_fieldValuesArray($fieldName);
}
if (!$allow_nulls)
{
if (is_null($value))
{
return new self(array_keys($array));
}
}
return new self(array_keys($array, $value));
}
/**
* @desc Creates a new CompleteArrayObject
* from all the values contained in the field
* name.
*
* @return CompleteArrayObject
*/
public function values($fieldName = null)
{
if (is_null($fieldName))
{
$array = $this->getArrayCopy();
}
else
{
$array = $this->_fieldValuesArray($fieldName);
}
return new self(array_values($array));
}
/**
* @desc Performs a natsort on the
* internal list and then reverses the list
*
* @return void
*/
public function natrsort()
{
$this->natsort();
$this->reverse();
}
/**
* @desc Performs a natcasesort on the
* internal list and then reverses the list
*
* @return void
*/
public function natcasersort()
{
$this->natcasesort();
$this->reverse();
}
/**
* @desc Changes the casing for the keys
* used in the list to either upper or lowercase.
* Use the CASE_UPPER or CASE_LOWER constants for
* the value of $case
*
* @param const $case
* @return void
*/
public function changeKeyCase($case = CASE_LOWER)
{
$array = $this->getArrayCopy();
$this->exchangeArray(array_change_key_case($array, $case));
}
/**
* @desc Returns the internal list with the
* result of the function provided mapped to
* each value for the field name provided.
*
* @param string $function
* @param string $fieldName
* @return void
*/
public function map($function, $fieldName = null)
{
$array = $this->getArrayCopy();
foreach($array as $key => $item)
{
if (is_object($item))
{
if (array_key_exists($fieldName, get_object_vars($item)))
{
$item->$fieldName = $function($item->$fieldName);
}
else
{
$get = 'get' . ucfirst($fieldName);
$set = 'set' . ucfirst($fieldName);
$item->$set($function($item->$get()));
}
continue;
}
if (is_array($item))
{
$array[$key] = $function($item[$fieldName]);
continue;
}
if (is_null($fieldName))
{
$array = array_map($function, $array);
continue;
}
}
return $this->exchangeArray($array);
}
/**
* @desc Sets the type for the class
* Exchanges the current array after changing
* the type so that an exception will be thrown
* if the new type is incompatible with any
* items already in the internal list.
*
* @param string $type
* @return void
*/
public function setType($type)
{
if (is_string($type)) {
$array = $this->getArrayCopy();
$this->_type = $type;
$this->exchangeArray($array);
}
}
/**
* @desc Gets the type for the class
*
* @return string
*/
public function getType()
{
return $this->_type;
}
/**
* @desc Java-like convenience method for append
*
* @param mixed $value
* @return void
*/
public function add($value)
{
$this->append($value);
}
/**
* @desc Java-like convenience method for offsetGet
*
* @param string $key
* @return mixed
*/
public function get($key)
{
return $this->offsetGet($key);
}
/**
* @desc Java-like convenience method for offsetSet
*
* @param string $key
* @param mixed $value
* @return void
*/
public function set($key, $value)
{
$this->offsetSet($key, $value);
}
/**
* @desc Java-like convenience method for offsetSet
*
* @param string $key
* @param mixed $value
* @return void
*/
public function put($key, $value)
{
$this->offsetSet($key, $value);
}
/**
* @desc Java-like convenience method for offsetExists
*
* @param string $key
* @return boolean
*/
public function exists($key)
{
return $this->offsetExists($key);
}
/**
* @desc Java-like convenience method for offsetUnset
*
* @param string $key
* @return void
*/
public function remove($key)
{
$this->offsetUnset($key);
}
/**
* @desc Java-like convenience method for getArrayCopy
*
* @return array
*/
public function toArray()
{
return $this->getArrayCopy();
}
/**
* @desc Returns the JSON String representation
* of the current list.
*
* @return string
*/
public function toJson()
{
return json_encode($this->getArrayCopy());
}
/**
* @desc Returns a CompleteArrayObject
* from a JSON string
*
* @param string $json
* @return CompleteArrayObject
*/
public static function fromJson($json)
{
$array = json_decode($json, true);
foreach($array as $key => $item)
{
if (is_array($item))
{
$array[$key] = new self($item);
}
}
return new self($array);
}
/**
* @desc Iterates through the list and creates
* a new array of values using the field name
* as a guide.
*
* @param string $fieldName
* @return array
*/
protected function _fieldValuesArray($fieldName = null)
{
$array = $this->getArrayCopy();
$fieldValuesArray = array();
foreach($array as $key => $item)
{
if (is_object($item))
{
if (empty($fieldName))
{
$this->typeExceptionMessage($item);
}
if (array_key_exists($fieldName, get_object_vars($item)))
{
$fieldValuesArray[$key] = $item->$fieldName;
}
else
{
$get = 'get' . ucfirst($fieldName);
$fieldValuesArray[$key] = $item->$get();
}
continue;
}
if (is_array($item))
{
$fieldValuesArray[$key] = $item[$fieldName];
continue;
}
if (is_null($fieldName))
{
$fieldValuesArray[$key] = $item;
continue;
}
}
return $fieldValuesArray;
}
/**
* @desc ToString Method
*
* @return string
*/
public function __toString()
{
return "<pre>" . print_r($this, true) . "</pre>";
}
}