diff --git a/framework/base/Dictionary.php b/framework/base/Dictionary.php index d5b36e7..860df39 100644 --- a/framework/base/Dictionary.php +++ b/framework/base/Dictionary.php @@ -1,91 +1,81 @@ * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2011 Yii Software LLC + * @copyright Copyright © 2008-2012 Yii Software LLC * @license http://www.yiiframework.com/license/ */ +namespace yii\base; + /** - * CMap implements a collection that takes key-value pairs. + * Dictionary implements a collection that stores key-value pairs. * * You can access, add or remove an item with a key by using - * {@link itemAt}, {@link add}, and {@link remove}. - * To get the number of the items in the map, use {@link getCount}. - * CMap can also be used like a regular array as follows, - *
- * $map[$key]=$value; // add a key-value pair
- * unset($map[$key]); // remove the value with the specified key
- * if(isset($map[$key])) // if the map contains the key
- * foreach($map as $key=>$value) // traverse the items in the map
- * $n=count($map);  // returns the number of items in the map
- * 
+ * [[itemAt]], [[add]], and [[remove]]. + * + * To get the number of the items in the dictionary, use [[getCount]]. + * + * Because Dictionary implements a set of SPL interfaces, it can be used + * like a regular PHP array as follows, + * + * ~~~php + * $dictionary[$key] = $value; // add a key-value pair + * unset($dictionary[$key]); // remove the value with the specified key + * if (isset($dictionary[$key])) // if the dictionary contains the key + * foreach ($dictionary as $key=>$value) // traverse the items in the dictionary + * $n = count($dictionary); // returns the number of items in the dictionary + * ~~~ * * @author Qiang Xue - * @version $Id: CMap.php 3153 2011-04-01 12:50:06Z qiang.xue $ - * @package system.collections - * @since 1.0 + * @since 2.0 */ class Dictionary extends Component implements \IteratorAggregate, \ArrayAccess, \Countable { /** - * @var array internal data storage + * @var boolean whether this vector is read-only or not. + * If the vector is read-only, adding or moving items will throw an exception. */ - private $_d=array(); + public $readOnly; /** - * @var boolean whether this list is read-only + * @var array internal data storage */ - private $_r=false; + private $_d = array(); /** * Constructor. - * Initializes the list with an array or an iterable object. - * @param array $data the intial data. Default is null, meaning no initialization. - * @param boolean $readOnly whether the list is read-only - * @throws CException If data is not null and neither an array nor an iterator. + * Initializes the dictionary with an array or an iterable object. + * @param mixed $data the initial data to be populated into the dictionary. + * This can be an array or an iterable object. + * @param boolean $readOnly whether the dictionary is read-only + * @throws Exception if data is not well formed (neither an array nor an iterable object) */ - public function __construct($data=null,$readOnly=false) + public function __construct($data = array(), $readOnly = false) { - if($data!==null) + if ($data !== array()) { $this->copyFrom($data); - $this->setReadOnly($readOnly); - } - - /** - * @return boolean whether this map is read-only or not. Defaults to false. - */ - public function getReadOnly() - { - return $this->_r; - } - - /** - * @param boolean $value whether this list is read-only or not - */ - protected function setReadOnly($value) - { - $this->_r=$value; + } + $this->readOnly = $readOnly; } /** - * Returns an iterator for traversing the items in the list. - * This method is required by the interface IteratorAggregate. - * @return CMapIterator an iterator for traversing the items in the list. + * Returns an iterator for traversing the items in the dictionary. + * This method is required by the SPL interface `IteratorAggregate`. + * It will be implicitly called when you use `foreach` to traverse the dictionary. + * @return DictionaryIterator an iterator for traversing the items in the dictionary. */ public function getIterator() { - return new CMapIterator($this->_d); + return new DictionaryIterator($this->_d); } /** - * Returns the number of items in the map. - * This method is required by Countable interface. - * @return integer number of items in the map. + * Returns the number of items in the dictionary. + * This method is required by the SPL `Countable` interface. + * It will be implicitly called when you use `count($dictionary)`. + * @return integer number of items in the dictionary. */ public function count() { @@ -93,8 +83,8 @@ class Dictionary extends Component implements \IteratorAggregate, \ArrayAccess, } /** - * Returns the number of items in the map. - * @return integer the number of items in the map + * Returns the number of items in the dictionary. + * @return integer the number of items in the dictionary */ public function getCount() { @@ -102,6 +92,7 @@ class Dictionary extends Component implements \IteratorAggregate, \ArrayAccess, } /** + * Returns the keys stored in the dictionary. * @return array the key list */ public function getKeys() @@ -111,84 +102,83 @@ class Dictionary extends Component implements \IteratorAggregate, \ArrayAccess, /** * Returns the item with the specified key. - * This method is exactly the same as {@link offsetGet}. * @param mixed $key the key - * @return mixed the element at the offset, null if no element is found at the offset + * @return mixed the element with the specified key. + * Null if the key cannot be found in the dictionary. */ public function itemAt($key) { - if(isset($this->_d[$key])) - return $this->_d[$key]; - else - return null; + return isset($this->_d[$key]) ? $this->_d[$key] : null; } /** - * Adds an item into the map. + * Adds an item into the dictionary. * Note, if the specified key already exists, the old value will be overwritten. * @param mixed $key key * @param mixed $value value - * @throws CException if the map is read-only + * @throws Exception if the dictionary is read-only */ - public function add($key,$value) + public function add($key, $value) { - if(!$this->_r) - { - if($key===null) - $this->_d[]=$value; - else - $this->_d[$key]=$value; + if (!$this->readOnly) { + if ($key === null) { + $this->_d[] = $value; + } + else { + $this->_d[$key] = $value; + } + } + else { + throw new Exception('Dictionary is read only.'); } - else - throw new CException(Yii::t('yii','The map is read only.')); } /** - * Removes an item from the map by its key. + * Removes an item from the dictionary by its key. * @param mixed $key the key of the item to be removed * @return mixed the removed value, null if no such key exists. - * @throws CException if the map is read-only + * @throws Exception if the dictionary is read-only */ public function remove($key) { - if(!$this->_r) - { - if(isset($this->_d[$key])) - { - $value=$this->_d[$key]; + if (!$this->readOnly) { + if (isset($this->_d[$key])) { + $value = $this->_d[$key]; unset($this->_d[$key]); return $value; } - else - { - // it is possible the value is null, which is not detected by isset + else { // the value is null unset($this->_d[$key]); return null; } } - else - throw new CException(Yii::t('yii','The map is read only.')); + else { + throw new Exception('Dictionary is read only.'); + } } /** - * Removes all items in the map. + * Removes all items in the dictionary. */ public function clear() { - foreach(array_keys($this->_d) as $key) + foreach (array_keys($this->_d) as $key) { $this->remove($key); + } } /** + * Returns a value indicating whether the dictionary contains the specified key. * @param mixed $key the key - * @return boolean whether the map contains an item with the specified key + * @return boolean whether the dictionary contains an item with the specified key */ public function contains($key) { - return isset($this->_d[$key]) || array_key_exists($key,$this->_d); + return isset($this->_d[$key]) || array_key_exists($key, $this->_d); } /** + * Returns the dictionary as a PHP array. * @return array the list of items in array */ public function toArray() @@ -197,33 +187,37 @@ class Dictionary extends Component implements \IteratorAggregate, \ArrayAccess, } /** - * Copies iterable data into the map. - * Note, existing data in the map will be cleared first. - * @param mixed $data the data to be copied from, must be an array or object implementing Traversable - * @throws CException If data is neither an array nor an iterator. + * Copies iterable data into the dictionary. + * Note, existing data in the dictionary will be cleared first. + * @param mixed $data the data to be copied from, must be an array or an object implementing `Traversable` + * @throws Exception if data is neither an array nor an iterator. */ public function copyFrom($data) { - if(is_array($data) || $data instanceof Traversable) + if (is_array($data) || $data instanceof Traversable) { - if($this->getCount()>0) + if (($this->_d !== array()) { $this->clear(); - if($data instanceof CMap) - $data=$data->_d; - foreach($data as $key=>$value) - $this->add($key,$value); + } + if ($data instanceof self) { + $data = $data->_d; + } + foreach ($data as $key => $value) { + $this->add($key, $value); + } + } + else { + throw new Exception('Data must be either an array or an object implementing Traversable.'); } - else if($data!==null) - throw new CException(Yii::t('yii','Map data must be an array or an object implementing Traversable.')); } /** - * Merges iterable data into the map. + * Merges iterable data into the dictionary. * - * Existing elements in the map will be overwritten if their keys are the same as those in the source. + * Existing elements in the dictionary will be overwritten if their keys are the same as those in the source. * If the merge is recursive, the following algorithm is performed: *