X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=lib%2Fpq%2FGateway%2FRowset.php;h=c0a337088ee6da3391c3ca53d6326367ec1692c4;hb=b39e14404cfeac177d41b152690b6adbb2b1e4bf;hp=2527b029a1f629cad222161c05e73cf84540a216;hpb=01bd45d05ce58796db7540d60671b8cff5d46bff;p=m6w6%2Fpq-gateway diff --git a/lib/pq/Gateway/Rowset.php b/lib/pq/Gateway/Rowset.php index 2527b02..c0a3370 100644 --- a/lib/pq/Gateway/Rowset.php +++ b/lib/pq/Gateway/Rowset.php @@ -20,18 +20,16 @@ class Rowset implements \SeekableIterator, \Countable, \JsonSerializable protected $rows; /** - * @var string + * @var mixed */ - protected $row; + protected $row = "\\pq\\Gateway\\Row"; /** * @param \pq\Gateway\Table $table * @param \pq\Result $result */ - function __construct(Table $table, \pq\Result $result, $row = "\\pq\\Gateway\\Row") { + function __construct(Table $table, \pq\Result $result = null) { $this->table = $table; - $this->row = $row; - $this->hydrate($result); } @@ -40,7 +38,7 @@ class Rowset implements \SeekableIterator, \Countable, \JsonSerializable * @param \pq\Result $result * @return \pq\Gateway\Rowset */ - function __invoke(\pq\Result $result) { + function __invoke(\pq\Result $result = null) { $that = clone $this; $that->hydrate($result); return $that; @@ -51,23 +49,47 @@ class Rowset implements \SeekableIterator, \Countable, \JsonSerializable * @param \pq\Result $result * @return array */ - protected function hydrate(\pq\Result $result) { + protected function hydrate(\pq\Result $result = null) { $this->index = 0; $this->rows = array(); - $row = $this->row; - if (is_callable($row)) { - while (($data = $result->fetchRow(\pq\Result::FETCH_ASSOC))) { - $this->rows[] = $row($data); - } - } else { - while (($data = $result->fetchRow(\pq\Result::FETCH_ASSOC))) { - $this->rows[] = new $row($this->table, $data); + if ($result) { + $row = $this->getRowPrototype(); + + if (is_callable($row)) { + while (($data = $result->fetchRow(\pq\Result::FETCH_ASSOC))) { + $this->rows[] = $row($data); + } + } elseif ($row) { + while (($data = $result->fetchRow(\pq\Result::FETCH_ASSOC))) { + $this->rows[] = new $row($this->table, $data); + } + } else { + $this->rows = $result->fetchAll(\pq\Result::FETCH_OBJECT); } } + return $this; } + /** + * Set the row prototype + * @param mixed $row + * @return \pq\Gateway\Table + */ + function setRowPrototype($row) { + $this->row = $row; + return $this; + } + + /** + * Get the row prototype + * @return mixed + */ + function getRowPrototype() { + return $this->row; + } + /** * @return \pq\Gateway\Table */ @@ -75,24 +97,75 @@ class Rowset implements \SeekableIterator, \Countable, \JsonSerializable return $this->table; } - function create() { - array_map(function ($row) { - $row->create(); - }, $this->rows); + /** + * Create all rows of this rowset + * @param bool $txn + * @return \pq\Gateway\Rowset + * @throws Exception + */ + function create($txn = true) { + $txn = $txn ? $this->table->getConnection()->startTransaction() : false; + try { + foreach ($this->rows as $row) { + $row->create(); + } + } catch (\Exception $e) { + if ($txn) { + $txn->rollback(); + } + throw $e; + } + if ($txn) { + $txn->commit(); + } return $this; } - function update() { - array_map(function ($row) { - $row->update(); - }, $this->rows); + /** + * Update all rows of this rowset + * @param bool $txn + * @return \pq\Gateway\Rowset + * @throws \Exception + */ + function update($txn = true) { + $txn = $txn ? $this->table->getConnection()->startTransaction() : false; + try { + foreach ($this->rows as $row) { + $row->update(); + } + } catch (\Exception $e) { + if ($txn) { + $txn->rollback(); + } + throw $e; + } + if ($txn) { + $txn->commit(); + } return $this; } - function delete() { - array_map(function ($row) { - $row->delete(); - }, $this->rows); + /** + * Delete all rows of this rowset + * @param type $txn + * @return \pq\Gateway\Rowset + * @throws \Exception + */ + function delete($txn = true) { + $txn = $txn ? $this->table->getConnection()->startTransaction() : false; + try { + foreach ($this->rows as $row) { + $row->delete(); + } + } catch (\Exception $e) { + if ($txn) { + $txn->rollback(); + } + throw $e; + } + if ($txn) { + $txn->commit(); + } return $this; } @@ -111,12 +184,14 @@ class Rowset implements \SeekableIterator, \Countable, \JsonSerializable function rewind() { $this->index = 0; } + /** * @implements \Iterator */ function next() { ++$this->index; } + /** * @implements \Iterator * @return bool @@ -124,13 +199,18 @@ class Rowset implements \SeekableIterator, \Countable, \JsonSerializable function valid() { return $this->index < count($this->rows); } + /** * @implements \Iterator * @return \pq\Gateway\Row */ function current() { + if (!$this->valid()) { + throw new \OutOfBoundsException("Invalid row index {$this->index}"); + } return $this->rows[$this->index]; } + /** * @implements \Iterator * @return int @@ -150,6 +230,8 @@ class Rowset implements \SeekableIterator, \Countable, \JsonSerializable if (!$this->valid()) { throw new \OutOfBoundsException("Invalid seek position ($pos)"); } + + return $this; } /** @@ -168,6 +250,16 @@ class Rowset implements \SeekableIterator, \Countable, \JsonSerializable return $this->rows; } + /** + * Apply a callback on each row of this rowset + * @param callable $cb + * @return \pq\Gateway\Rowset + */ + function apply(callable $cb) { + array_walk($this->rows, $cb, $this); + return $this; + } + /** * Filter by callback * @param callable $cb @@ -175,7 +267,17 @@ class Rowset implements \SeekableIterator, \Countable, \JsonSerializable */ function filter(callable $cb) { $rowset = clone $this; + $rowset->index = 0; $rowset->rows = array_filter($this->rows, $cb); return $rowset; } + + /** + * Append a row to the rowset + * @param \pq\Gateway\Row $row + */ + function append(Row $row) { + $this->rows[] = $row; + return $this; + } }