flush
[m6w6/pq-gateway] / lib / pq / Gateway / Rowset.php
index 2527b029a1f629cad222161c05e73cf84540a216..7c0a3c23395f56428d9c1506dfdc5f86ef089459 100644 (file)
@@ -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;
+       }
 }