* @copyright Leo Feyer 2005-2014 */ class Collection implements \ArrayAccess, \Countable, \IteratorAggregate { /** * Table name * @var string */ protected $strTable; /** * Current index * @var integer */ protected $intIndex = -1; /** * Models * @var array */ protected $arrModels = array(); /** * Create a new collection * * @param array $arrModels An array of models * @param string $strTable The table name * * @throws \InvalidArgumentException */ public function __construct(array $arrModels, $strTable) { $arrModels = array_values($arrModels); foreach ($arrModels as $objModel) { if (!$objModel instanceof \Model) { throw new \InvalidArgumentException('Invalid type: ' . gettype($objModel)); } } $this->arrModels = $arrModels; $this->strTable = $strTable; } /** * Set an object property * * @param string $strKey The property name * @param mixed $varValue The property value */ public function __set($strKey, $varValue) { if ($this->intIndex < 0) { $this->first(); } $this->arrModels[$this->intIndex]->$strKey = $varValue; } /** * Return an object property * * @param string $strKey The property name * * @return mixed|null The property value or null */ public function __get($strKey) { if ($this->intIndex < 0) { $this->first(); } if (isset($this->arrModels[$this->intIndex]->$strKey)) { return $this->arrModels[$this->intIndex]->$strKey; } return null; } /** * Check whether a property is set * * @param string $strKey The property name * * @return boolean True if the property is set */ public function __isset($strKey) { if ($this->intIndex < 0) { $this->first(); } return isset($this->arrModels[$this->intIndex]->$strKey); } /** * Create a new collection from a database result * * @param \Database\Result $objResult The database result object * @param string $strTable The table name * * @return \Model\Collection The model collection */ static public function createFromDbResult(\Database\Result $objResult, $strTable) { $arrModels = array(); while ($objResult->next()) { $strClass = \Model::getClassFromTable($strTable); $e = new \Exception(); var_dump($strClass, $e->getTraceAsString()); $strPk = $strClass::getPk(); /* string(28) "TeamstronachPoliticiansModel" string(1788) "#0 /var/www/vhosts/contao.drei/htdocs/ts3/system/modules/core/library/Contao/Model.php(963): Contao\Model\Collection::createFromDbResult(Object(Contao\Database\Mysqli\Result), 'tl_teamstronach...') #1 /var/www/vhosts/contao.drei/htdocs/ts3/system/modules/core/library/Contao/Model.php(833): Contao\Model::find(Array) #2 /var/www/vhosts/contao.drei/htdocs/ts3/system/modules/teamstronach_politicians/elements/ContentPolitician.php(35): Contao\Model::findBy('id', '3') #3 /var/www/vhosts/contao.drei/htdocs/ts3/system/modules/core/elements/ContentElement.php(159): ContentPolitician->compile() #4 /var/www/vhosts/contao.drei/htdocs/ts3/system/modules/core/library/Contao/Controller.php(456): Contao\ContentElement->generate() #5 /var/www/vhosts/contao.drei/htdocs/ts3/system/modules/core/modules/ModuleArticle.php(205): Contao\Controller->getContentElement(Object(Contao\ContentModel), 'main') #6 /var/www/vhosts/contao.drei/htdocs/ts3/system/modules/core/modules/Module.php(148): Contao\ModuleArticle->compile() #7 /var/www/vhosts/contao.drei/htdocs/ts3/system/modules/core/modules/ModuleArticle.php(59): Contao\Module->generate() #8 /var/www/vhosts/contao.drei/htdocs/ts3/system/modules/core/library/Contao/Controller.php(392): Contao\ModuleArticle->generate(false) #9 /var/www/vhosts/contao.drei/htdocs/ts3/system/modules/core/library/Contao/Controller.php(254): Contao\Controller->getArticle(Object(Contao\ArticleModel), false, false, 'main') #10 /var/www/vhosts/contao.drei/htdocs/ts3/system/modules/core/pages/PageRegular.php(138): Contao\Controller->getFrontendModule('0', 'main') #11 /var/www/vhosts/contao.drei/htdocs/ts3/index.php(249): Contao\PageRegular->generate(Object(Contao\PageModel), true) #12 /var/www/vhosts/contao.drei/htdocs/ts3/index.php(433): Index->run() #13 {main}" */ $intPk = $objResult->$strPk; $objModel = \Model\Registry::getInstance()->fetch($strTable, $intPk); if ($objModel !== null) { $objModel->mergeRow($objResult->row()); $arrModels[] = $objModel; } else { $arrModels[] = new $strClass($objResult); } } return new static($arrModels, $strTable); } /** * Return the current row as associative array * * @return array The current row as array */ public function row() { if ($this->intIndex < 0) { $this->first(); } return $this->arrModels[$this->intIndex]->row(); } /** * Set the current row from an array * * @param array $arrData The row data as array * * @return \Model\Collection The model collection object */ public function setRow(array $arrData) { if ($this->intIndex < 0) { $this->first(); } $this->arrModels[$this->intIndex]->setRow($arrData); return $this; } /** * Save the current model * * @return \Model\Collection The model collection object */ public function save() { if ($this->intIndex < 0) { $this->first(); } $this->arrModels[$this->intIndex]->save(); return $this; } /** * Delete the current model and return the number of affected rows * * @return integer The number of affected rows */ public function delete() { if ($this->intIndex < 0) { $this->first(); } return $this->arrModels[$this->intIndex]->delete(); } /** * Return the models as array * * @return array An array of models */ public function getModels() { return $this->arrModels; } /** * Lazy load related records * * @param string $strKey The property name * * @return \Model|\Model\Collection The model or a model collection if there are multiple rows */ public function getRelated($strKey) { if ($this->intIndex < 0) { $this->first(); } return $this->arrModels[$this->intIndex]->getRelated($strKey); } /** * Return the number of rows in the result set * * @return integer The number of rows */ public function count() { return count($this->arrModels); } /** * Go to the first row * * @return \Model\Collection The model collection object */ public function first() { $this->intIndex = 0; return $this; } /** * Go to the previous row * * @return \Model\Collection|false The model collection object or false if there is no previous row */ public function prev() { if ($this->intIndex < 1) { return false; } --$this->intIndex; return $this; } /** * Return the current model * * @return \Model The model object */ public function current() { if ($this->intIndex < 0) { $this->first(); } return $this->arrModels[$this->intIndex]; } /** * Go to the next row * * @return \Model\Collection|boolean The model collection object or false if there is no next row */ public function next() { if (!isset($this->arrModels[$this->intIndex + 1])) { return false; } ++$this->intIndex; return $this; } /** * Go to the last row * * @return \Model\Collection The model collection object */ public function last() { $this->intIndex = count($this->arrModels) - 1; return $this; } /** * Reset the model * * @return \Model\Collection The model collection object */ public function reset() { $this->intIndex = -1; return $this; } /** * Fetch a column of each row * * @param string $strKey The property name * * @return array An array with all property values */ public function fetchEach($strKey) { $this->reset(); $return = array(); while ($this->next()) { $strPk = $this->current()->getPk(); if ($strKey != 'id' && isset($this->$strPk)) { $return[$this->$strPk] = $this->$strKey; } else { $return[] = $this->$strKey; } } return $return; } /** * Fetch all columns of every row * * @return array An array with all rows and columns */ public function fetchAll() { $this->reset(); $return = array(); while ($this->next()) { $return[] = $this->row(); } return $return; } /** * Check whether an offset exists * * @param integer $offset The offset * * @return boolean True if the offset exists */ public function offsetExists($offset) { return isset($this->arrModels[$offset]); } /** * Retrieve a particular offset * * @param integer $offset The offset * * @return \Model|null The model or null */ public function offsetGet($offset) { return $this->arrModels[$offset]; } /** * Set a particular offset * * @param integer $offset The offset * @param mixed $value The value to set * * @throws \RuntimeException The collection is immutable */ public function offsetSet($offset, $value) { throw new \RuntimeException('This collection is immutable'); } /** * Unset a particular offset * * @param integer $offset The offset * * @throws \RuntimeException The collection is immutable */ public function offsetUnset($offset) { throw new \RuntimeException('This collection is immutable'); } /** * Retrieve the iterator object * * @return \ArrayIterator The iterator object */ public function getIterator() { return new \ArrayIterator($this->arrModels); } }