PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/runtime/lib/collection/PropelObjectCollection.php

http://github.com/propelorm/Propel
PHP | 317 lines | 166 code | 27 blank | 124 comment | 21 complexity | 939d1c7c2dadb44eab1dfe7ac51c30f3 MD5 | raw file
  1. <?php
  2. /**
  3. * This file is part of the Propel package.
  4. * For the full copyright and license information, please view the LICENSE
  5. * file that was distributed with this source code.
  6. *
  7. * @license MIT License
  8. */
  9. /**
  10. * Class for iterating over a list of Propel objects
  11. *
  12. * @author Francois Zaninotto
  13. * @package propel.runtime.collection
  14. */
  15. class PropelObjectCollection extends PropelCollection
  16. {
  17. /**
  18. * Save all the elements in the collection
  19. *
  20. * @param PropelPDO $con
  21. *
  22. * @throws PropelException
  23. */
  24. public function save($con = null)
  25. {
  26. if (!method_exists($this->getModel(), 'save')) {
  27. throw new PropelException('Cannot save objects on a read-only model');
  28. }
  29. if (null === $con) {
  30. $con = $this->getConnection(Propel::CONNECTION_WRITE);
  31. }
  32. $con->beginTransaction();
  33. try {
  34. /** @var $element BaseObject */
  35. foreach ($this as $element) {
  36. $element->save($con);
  37. }
  38. $con->commit();
  39. } catch (Exception $e) {
  40. $con->rollback();
  41. throw $e;
  42. }
  43. }
  44. /**
  45. * Delete all the elements in the collection
  46. *
  47. * @param PropelPDO $con
  48. *
  49. * @throws PropelException
  50. */
  51. public function delete($con = null)
  52. {
  53. if (!method_exists($this->getModel(), 'delete')) {
  54. throw new PropelException('Cannot delete objects on a read-only model');
  55. }
  56. if (null === $con) {
  57. $con = $this->getConnection(Propel::CONNECTION_WRITE);
  58. }
  59. $con->beginTransaction();
  60. try {
  61. /** @var $element BaseObject */
  62. foreach ($this as $element) {
  63. $element->delete($con);
  64. }
  65. $con->commit();
  66. } catch (Exception $e) {
  67. $con->rollback();
  68. throw $e;
  69. }
  70. }
  71. /**
  72. * Get an array of the primary keys of all the objects in the collection
  73. *
  74. * @param boolean $usePrefix
  75. *
  76. * @return array The list of the primary keys of the collection
  77. */
  78. public function getPrimaryKeys($usePrefix = true)
  79. {
  80. $ret = array();
  81. /** @var $obj BaseObject */
  82. foreach ($this as $key => $obj) {
  83. $key = $usePrefix ? ($this->getModel() . '_' . $key) : $key;
  84. $ret[$key] = $obj->getPrimaryKey();
  85. }
  86. return $ret;
  87. }
  88. /**
  89. * Populates the collection from an array
  90. * Each object is populated from an array and the result is stored
  91. * Does not empty the collection before adding the data from the array
  92. *
  93. * @param array $arr
  94. */
  95. public function fromArray($arr)
  96. {
  97. $class = $this->getModel();
  98. foreach ($arr as $element) {
  99. /** @var $obj BaseObject */
  100. $obj = new $class();
  101. $obj->fromArray($element);
  102. $this->append($obj);
  103. }
  104. }
  105. /**
  106. * Get an array representation of the collection
  107. *
  108. * @param string $keyColumn If null, the returned array uses an incremental index.
  109. * Otherwise, the array is indexed using the specified column
  110. * @param boolean $usePrefix If true, the returned array prefixes keys
  111. * with the model class name ('Article_0', 'Article_1', etc).
  112. *
  113. * <code>
  114. * $bookCollection->getArrayCopy();
  115. * array(
  116. * 0 => $book0,
  117. * 1 => $book1,
  118. * )
  119. * $bookCollection->getArrayCopy('Id');
  120. * array(
  121. * 123 => $book0,
  122. * 456 => $book1,
  123. * )
  124. * $bookCollection->getArrayCopy(null, true);
  125. * array(
  126. * 'Book_0' => $book0,
  127. * 'Book_1' => $book1,
  128. * )
  129. * </code>
  130. *
  131. * @return array
  132. */
  133. public function getArrayCopy($keyColumn = null, $usePrefix = false)
  134. {
  135. if (null === $keyColumn && false === $usePrefix) {
  136. return parent::getArrayCopy();
  137. }
  138. $ret = array();
  139. $keyGetterMethod = 'get' . $keyColumn;
  140. foreach ($this as $key => $obj) {
  141. $key = null === $keyColumn ? $key : $obj->$keyGetterMethod();
  142. $key = $usePrefix ? ($this->getModel() . '_' . $key) : $key;
  143. $ret[$key] = $obj;
  144. }
  145. return $ret;
  146. }
  147. /**
  148. * Get an associative array representation of the collection
  149. * The first parameter specifies the column to be used for the key,
  150. * And the seconf for the value.
  151. *
  152. * <code>
  153. * $res = $coll->toKeyValue('Id', 'Name');
  154. * </code>
  155. * <code>
  156. * $res = $coll->toKeyValue(array('RelatedModel', 'Name'), 'Name');
  157. * </code>
  158. *
  159. * @param string|array $keyColumn The name of the column, or a list of columns to call.
  160. * @param string $valueColumn
  161. *
  162. * @return array
  163. */
  164. public function toKeyValue($keyColumn = 'PrimaryKey', $valueColumn = null)
  165. {
  166. $ret = array();
  167. $valueGetterMethod = (null === $valueColumn) ? '__toString' : ('get' . $valueColumn);
  168. if (!is_array($keyColumn)) {
  169. $keyColumn = array($keyColumn);
  170. }
  171. foreach ($this as $obj) {
  172. $ret[$this->getValueForColumns($obj, $keyColumn)] = $obj->$valueGetterMethod();
  173. }
  174. return $ret;
  175. }
  176. /**
  177. * Return the value for a given set of key columns.
  178. *
  179. * Each column will be resolved on the value returned by the previous one.
  180. *
  181. * @param object $object The object to start with.
  182. * @param array $columns The sequence of key columns.
  183. *
  184. * @return mixed
  185. */
  186. protected function getValueForColumns($object, array $columns)
  187. {
  188. $value = $object;
  189. foreach ($columns as $eachKeyColumn) {
  190. $keyGetterMethod = 'get' . $eachKeyColumn;
  191. $value = $value->$keyGetterMethod();
  192. }
  193. return $value;
  194. }
  195. /**
  196. * Makes an additional query to populate the objects related to the collection objects
  197. * by a certain relation
  198. *
  199. * @param string $relation Relation name (e.g. 'Book')
  200. * @param Criteria $criteria Optional Criteria object to filter the related object collection
  201. * @param PropelPDO $con Optional connection object
  202. *
  203. * @return PropelObjectCollection The list of related objects
  204. *
  205. * @throws PropelException
  206. */
  207. public function populateRelation($relation, $criteria = null, $con = null)
  208. {
  209. if (!Propel::isInstancePoolingEnabled()) {
  210. throw new PropelException('populateRelation() needs instance pooling to be enabled prior to populating the collection');
  211. }
  212. $relationMap = $this->getFormatter()->getTableMap()->getRelation($relation);
  213. if ($this->isEmpty()) {
  214. // save a useless query and return an empty collection
  215. $coll = new PropelObjectCollection();
  216. $coll->setModel($relationMap->getRightTable()->getClassname());
  217. return $coll;
  218. }
  219. $symRelationMap = $relationMap->getSymmetricalRelation();
  220. $query = PropelQuery::from($relationMap->getRightTable()->getClassname());
  221. if (null !== $criteria) {
  222. $query->mergeWith($criteria);
  223. }
  224. // query the db for the related objects
  225. $filterMethod = 'filterBy' . $symRelationMap->getName();
  226. $relatedObjects = $query
  227. ->$filterMethod($this)
  228. ->find($con);
  229. if ($relationMap->getType() == RelationMap::ONE_TO_MANY) {
  230. // initialize the embedded collections of the main objects
  231. $relationName = $relationMap->getName();
  232. foreach ($this as $mainObj) {
  233. $mainObj->initRelation($relationName);
  234. }
  235. // associate the related objects to the main objects
  236. $getMethod = 'get' . $symRelationMap->getName();
  237. $addMethod = 'add' . $relationName;
  238. foreach ($relatedObjects as $object) {
  239. $mainObj = $object->$getMethod(); // instance pool is used here to avoid a query
  240. $mainObj->$addMethod($object);
  241. }
  242. $relatedObjects->clearIterator();
  243. } elseif ($relationMap->getType() == RelationMap::MANY_TO_ONE) {
  244. // nothing to do; the instance pool will catch all calls to getRelatedObject()
  245. // and return the object in memory
  246. } else {
  247. throw new PropelException('populateRelation() does not support this relation type');
  248. }
  249. return $relatedObjects;
  250. }
  251. /**
  252. * {@inheritdoc}
  253. */
  254. public function search($element)
  255. {
  256. if ($element instanceof BaseObject) {
  257. if (null !== $elt = $this->getIdenticalObject($element)) {
  258. $element = $elt;
  259. }
  260. }
  261. return parent::search($element);
  262. }
  263. /**
  264. * {@inheritdoc}
  265. */
  266. public function contains($element)
  267. {
  268. if ($element instanceof BaseObject) {
  269. if (null !== $elt = $this->getIdenticalObject($element)) {
  270. $element = $elt;
  271. }
  272. }
  273. return parent::contains($element);
  274. }
  275. private function getIdenticalObject(BaseObject $object)
  276. {
  277. $objectHashCode = null;
  278. foreach ($this as $obj) {
  279. if ($obj instanceof BaseObject) {
  280. if (null === $objectHashCode) {
  281. $objectHashCode = $object->hashCode();
  282. }
  283. if ($obj->hashCode() === $objectHashCode) {
  284. return $obj;
  285. }
  286. }
  287. }
  288. return null;
  289. }
  290. }