CAttributeCollection.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. /**
  3. * This file contains classes implementing attribute collection feature.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CAttributeCollection implements a collection for storing attribute names and values.
  12. *
  13. * Besides all functionalities provided by {@link CMap}, CAttributeCollection
  14. * allows you to get and set attribute values like getting and setting
  15. * properties. For example, the following usages are all valid for a
  16. * CAttributeCollection object:
  17. * <pre>
  18. * $collection->text='text'; // same as: $collection->add('text','text');
  19. * echo $collection->text; // same as: echo $collection->itemAt('text');
  20. * </pre>
  21. *
  22. * The case sensitivity of attribute names can be toggled by setting the
  23. * {@link caseSensitive} property of the collection.
  24. *
  25. * @author Qiang Xue <qiang.xue@gmail.com>
  26. * @package system.collections
  27. * @since 1.0
  28. */
  29. class CAttributeCollection extends CMap
  30. {
  31. /**
  32. * @var boolean whether the keys are case-sensitive. Defaults to false.
  33. */
  34. public $caseSensitive=false;
  35. /**
  36. * Returns a property value or an event handler list by property or event name.
  37. * This method overrides the parent implementation by returning
  38. * a key value if the key exists in the collection.
  39. * @param string $name the property name or the event name
  40. * @return mixed the property value or the event handler list
  41. * @throws CException if the property/event is not defined.
  42. */
  43. public function __get($name)
  44. {
  45. if($this->contains($name))
  46. return $this->itemAt($name);
  47. else
  48. return parent::__get($name);
  49. }
  50. /**
  51. * Sets value of a component property.
  52. * This method overrides the parent implementation by adding a new key value
  53. * to the collection.
  54. * @param string $name the property name or event name
  55. * @param mixed $value the property value or event handler
  56. * @throws CException If the property is not defined or read-only.
  57. */
  58. public function __set($name,$value)
  59. {
  60. $this->add($name,$value);
  61. }
  62. /**
  63. * Checks if a property value is null.
  64. * This method overrides the parent implementation by checking
  65. * if the key exists in the collection and contains a non-null value.
  66. * @param string $name the property name or the event name
  67. * @return boolean whether the property value is null
  68. */
  69. public function __isset($name)
  70. {
  71. if($this->contains($name))
  72. return $this->itemAt($name)!==null;
  73. else
  74. return parent::__isset($name);
  75. }
  76. /**
  77. * Sets a component property to be null.
  78. * This method overrides the parent implementation by clearing
  79. * the specified key value.
  80. * @param string $name the property name or the event name
  81. */
  82. public function __unset($name)
  83. {
  84. $this->remove($name);
  85. }
  86. /**
  87. * Returns the item with the specified key.
  88. * This overrides the parent implementation by converting the key to lower case first if {@link caseSensitive} is false.
  89. * @param mixed $key the key
  90. * @return mixed the element at the offset, null if no element is found at the offset
  91. */
  92. public function itemAt($key)
  93. {
  94. if($this->caseSensitive)
  95. return parent::itemAt($key);
  96. else
  97. return parent::itemAt(strtolower($key));
  98. }
  99. /**
  100. * Adds an item into the map.
  101. * This overrides the parent implementation by converting the key to lower case first if {@link caseSensitive} is false.
  102. * @param mixed $key key
  103. * @param mixed $value value
  104. */
  105. public function add($key,$value)
  106. {
  107. if($this->caseSensitive)
  108. parent::add($key,$value);
  109. else
  110. parent::add(strtolower($key),$value);
  111. }
  112. /**
  113. * Removes an item from the map by its key.
  114. * This overrides the parent implementation by converting the key to lower case first if {@link caseSensitive} is false.
  115. * @param mixed $key the key of the item to be removed
  116. * @return mixed the removed value, null if no such key exists.
  117. */
  118. public function remove($key)
  119. {
  120. if($this->caseSensitive)
  121. return parent::remove($key);
  122. else
  123. return parent::remove(strtolower($key));
  124. }
  125. /**
  126. * Returns whether the specified is in the map.
  127. * This overrides the parent implementation by converting the key to lower case first if {@link caseSensitive} is false.
  128. * @param mixed $key the key
  129. * @return boolean whether the map contains an item with the specified key
  130. */
  131. public function contains($key)
  132. {
  133. if($this->caseSensitive)
  134. return parent::contains($key);
  135. else
  136. return parent::contains(strtolower($key));
  137. }
  138. /**
  139. * Determines whether a property is defined.
  140. * This method overrides parent implementation by returning true
  141. * if the collection contains the named key.
  142. * @param string $name the property name
  143. * @return boolean whether the property is defined
  144. */
  145. public function hasProperty($name)
  146. {
  147. return $this->contains($name) || parent::hasProperty($name);
  148. }
  149. /**
  150. * Determines whether a property can be read.
  151. * This method overrides parent implementation by returning true
  152. * if the collection contains the named key.
  153. * @param string $name the property name
  154. * @return boolean whether the property can be read
  155. */
  156. public function canGetProperty($name)
  157. {
  158. return $this->contains($name) || parent::canGetProperty($name);
  159. }
  160. /**
  161. * Determines whether a property can be set.
  162. * This method overrides parent implementation by always returning true
  163. * because you can always add a new value to the collection.
  164. * @param string $name the property name
  165. * @return boolean true
  166. */
  167. public function canSetProperty($name)
  168. {
  169. return true;
  170. }
  171. /**
  172. * Merges iterable data into the map.
  173. *
  174. * Existing elements in the map will be overwritten if their keys are the same as those in the source.
  175. * If the merge is recursive, the following algorithm is performed:
  176. * <ul>
  177. * <li>the map data is saved as $a, and the source data is saved as $b;</li>
  178. * <li>if $a and $b both have an array indexed at the same string key, the arrays will be merged using this algorithm;</li>
  179. * <li>any integer-indexed elements in $b will be appended to $a and reindexed accordingly;</li>
  180. * <li>any string-indexed elements in $b will overwrite elements in $a with the same index;</li>
  181. * </ul>
  182. *
  183. * @param mixed $data the data to be merged with, must be an array or object implementing Traversable
  184. * @param boolean $recursive whether the merging should be recursive.
  185. *
  186. * @throws CException If data is neither an array nor an iterator.
  187. */
  188. public function mergeWith($data,$recursive=true)
  189. {
  190. if(!$this->caseSensitive && (is_array($data) || $data instanceof Traversable))
  191. {
  192. $d=array();
  193. foreach($data as $key=>$value)
  194. $d[strtolower($key)]=$value;
  195. return parent::mergeWith($d,$recursive);
  196. }
  197. parent::mergeWith($data,$recursive);
  198. }
  199. }