use standard SplObserver
authorMichael Wallner <mike@php.net>
Tue, 16 Sep 2014 16:36:52 +0000 (18:36 +0200)
committerMichael Wallner <mike@php.net>
Tue, 16 Sep 2014 16:37:56 +0000 (18:37 +0200)
composer.json
lib/pq/Gateway/Row.php
lib/pq/Gateway/Table.php
lib/pq/Gateway/Table/LockInterface.php [deleted file]
lib/pq/Gateway/Table/OptimisticLock.php
lib/pq/Gateway/Table/PessimisticLock.php
tests/lib/pq/Gateway/RowTest.php

index b5f8bed7bdb3f4d277fe19cd1ee0f8914eda87c7..575daa8576a78bb9603a6919621b29c89e5bfc26 100644 (file)
@@ -2,8 +2,8 @@
        "name": "m6w6/pq-gateway",
        "type": "library",
        "description": "Table/row gateway for ext-pq",
-       "keywords": ["postgres", "orm", "gateway", "pq"],
-       "homepage": "http://bitbucket.org/mike_php_net/pq-gateway",
+       "keywords": ["postgres", "postgresql", "orm", "gateway", "pq"],
+       "homepage": "http://bitbucket.org/m6w6/pq-gateway",
        "license": "BSD-2-Clause",
        "authors": [
                {
index cda8d4af67a0ba857a6854b4f8c262f016f5e34d..78ec4c4e9c2d38e6ef82c118a07c3bf19eb6772f 100644 (file)
@@ -253,6 +253,7 @@ class Row implements \JsonSerializable
         * @return \pq\Gateway\Row
         */
        function create() {
+               $this->table->notify($this, "create");
                $rowset = $this->table->create($this->changes());
                if (!count($rowset)) {
                        throw new \UnexpectedValueException("No row created");
@@ -267,11 +268,9 @@ class Row implements \JsonSerializable
         * @return \pq\Gateway\Row
         */
        function update() {
-               $criteria = $this->criteria();
-               if (($lock = $this->getTable()->getLock())) {
-                       $lock->onUpdate($this, $criteria);
-               }
-               $rowset = $this->table->update($criteria, $this->changes());
+               $where = $this->criteria();
+               $this->table->notify($this, "update", $where);
+               $rowset = $this->table->update($where, $this->changes());
                if (!count($rowset)) {
                        throw new \UnexpectedValueException("No row updated");
                }
@@ -285,6 +284,7 @@ class Row implements \JsonSerializable
         * @return \pq\Gateway\Row
         */
        function delete() {
+               $this->table->notify($this, "delete");
                $rowset = $this->table->delete($this->criteria(), "*");
                if (!count($rowset)) {
                        throw new \UnexpectedValueException("No row deleted");
index e4adbb7a532642e23005871f27c6e16ea100f436..42977dc0d6c9d7b555afe9c42e5283a2246b5319 100644 (file)
@@ -6,7 +6,7 @@ use \pq\Query\Expr as QueryExpr;
 use \pq\Query\Writer as QueryWriter;
 use \pq\Query\Executor as QueryExecutor;
 
-class Table
+class Table implements \SplSubject
 {
        /**
         * @var \pq\Connection
@@ -69,9 +69,9 @@ class Table
        protected $metadataCache;
        
        /**
-        * @var \pq\Gateway\Table\LockInterface
+        * @var \SplObjectStorage
         */
-       protected $lock;
+       protected $observers;
        
        /**
         * @param string $table
@@ -101,6 +101,7 @@ class Table
                        throw new \InvalidArgumentException("Table must have a name");
                }
                $this->conn = $conn ?: static::$defaultConnection ?: new \pq\Connection;
+               $this->observers = new \SplObjectStorage;
        }
        
        /**
@@ -266,21 +267,32 @@ class Table
        }
 
        /**
-        * Set a lock provider
-        * @param \pq\Gateway\Table\LockInterface $lock
+        * Attach an observer
+        * @param \SplObserver
         * @return \pq\Gateway\Table
         */
-       function setLock(Table\LockInterface $lock) {
-               $this->lock = $lock;
+       function attach(\SplObserver $observer) {
+               $this->observers->attach($observer);
                return $this;
        }
        
        /**
-        * Get any set lock provider
-        * @return \pq\Gateway\Table\LockIntferace
+        * Detach an observer
+        * @param \SplObserver
+        * @return \pq\Gateway\Table
         */
-       function getLock() {
-               return $this->lock;
+       function detach(\SplObserver $observer) {
+               $this->observers->attach($observer);
+               return $this;
+       }
+
+       /**
+        * Implements \SplSubject
+        */
+       function notify(\pq\Gateway\Row $row = null, $event = null, array &$where = null) {
+               foreach ($this->observers as $observer) {
+                       $observer->update($this, $row, $event, $where);
+               }
        }
        
        /**
diff --git a/lib/pq/Gateway/Table/LockInterface.php b/lib/pq/Gateway/Table/LockInterface.php
deleted file mode 100644 (file)
index de64c57..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php
-
-namespace pq\Gateway\Table;
-
-use \pq\Gateway\Row;
-
-/**
- * Lazy row lock on update
- */
-interface LockInterface
-{
-       function onUpdate(Row $row, array &$where);
-}
index 8c2ec7b9741cb52b57e4c6bee3fdf9294726a81b..4b22f575e6a4e30216b1e66831e8e7137e63d16a 100644 (file)
@@ -7,7 +7,7 @@ use \pq\Gateway\Row;
 /**
  * An optimistic row lock implementation using a versioning column
  */
-class OptimisticLock implements LockInterface
+class OptimisticLock implements \SplObserver
 {
        /**
         * The name of the versioning column
@@ -23,12 +23,15 @@ class OptimisticLock implements LockInterface
        }
        
        /**
-        * @inheritdoc
+        * @param \pq\Gateway\Table $table
         * @param \pq\Gateway\Row $row
+        * @param string $event create/update/delete
         * @param array $where reference to the criteria
         */
-       function onUpdate(Row $row, array &$where) {
-               $where["{$this->column}="] = $row->getData()[$this->column];
-               $row->{$this->column}->mod(+1);
+       function update(\SplSubject $table, Row $row = null, $event = null, array &$where = null) {
+               if ($event === "update") {
+                       $where["{$this->column}="] = $row->getData()[$this->column];
+                       $row->{$this->column}->mod(+1);
+               }
        }
 }
index 2076dbd2b7dc05aa06b7124a7088de4d0eb843b0..04781578bc242f2de70cbae4b55411ccb6155b2c 100644 (file)
@@ -7,29 +7,23 @@ use \pq\Gateway\Row;
 /**
  * A pessimistic row lock implementation using an additional SELECT FOR UPDATE
  */
-class PessimisticLock implements LockInterface
+class PessimisticLock implements \SplObserver
 {
        /**
-        * @inheritdoc
+        * @param \pq\Gateway\Table $table
         * @param \pq\Gateway\Row $row
-        * @param array $ignore
+        * @param string $event create/update/delete
+        * @param array $where reference to the criteria
         * @throws \UnexpectedValueException if the row has already been modified
         */
-       function onUpdate(Row $row, array &$ignore) {
-               $where = array();
-               foreach ($row->getIdentity() as $col => $val) {
-                       if (isset($val)) {
-                               $where["$col="] = $val;
-                       } else {
-                               $where["$col IS"] = new QueryExpr("NULL");
+       function update(\SplSubject $table, Row $row = null, $event = null, array &$where = null) {
+               if ($event === "update") {
+                       if (1 != count($rowset = $table->find($where, null, 0, 0, "update nowait"))) {
+                               throw new \UnexpectedValueException("Failed to select a single row");
+                       }
+                       if ($rowset->current()->getData() != $row->getData()) {
+                               throw new \UnexpectedValueException("Row has already been modified");
                        }
-               }
-               
-               if (1 != count($rowset = $row->getTable()->find($where, null, 0, 0, "update nowait"))) {
-                       throw new \UnexpectedValueException("Failed to select a single row");
-               }
-               if ($rowset->current()->getData() != $row->getData()) {
-                       throw new \UnexpectedValueException("Row has already been modified");
                }
        }
 }
\ No newline at end of file
index c4adf8ce6a1482b041e84082bf051874e2bab073..7b88e1993b298c894b2746622613068aaa684628 100644 (file)
@@ -53,7 +53,7 @@ class RowTest extends \PHPUnit_Framework_TestCase {
        }
        
        function testPessimisticLock() {
-               $this->table->setLock(new Table\PessimisticLock);
+               $this->table->attach(new Table\PessimisticLock);
                $txn = $this->table->getConnection()->startTransaction();
                $row = $this->table->find(null, null, 1)->current();
                $row->data = "foo";
@@ -63,7 +63,7 @@ class RowTest extends \PHPUnit_Framework_TestCase {
        }
        
        function testPessimisticLockFail() {
-               $this->table->setLock(new Table\PessimisticLock);
+               $this->table->attach(new Table\PessimisticLock);
                $txn = $this->table->getConnection()->startTransaction();
                $row = $this->table->find(null, null, 1)->current();
                $row->data = "foo";
@@ -77,7 +77,7 @@ class RowTest extends \PHPUnit_Framework_TestCase {
        }
        
        function testOptimisticLock() {
-               $this->table->setLock(new Table\OptimisticLock("counter"));
+               $this->table->attach(new Table\OptimisticLock("counter"));
                $row = $this->table->find(null, null, 1)->current();
                $cnt = $row->counter->get();
                $row->data = "foo";
@@ -87,7 +87,7 @@ class RowTest extends \PHPUnit_Framework_TestCase {
        }
        
        function testOptimisticLockFail() {
-               $this->table->setLock(new Table\OptimisticLock("counter"));
+               $this->table->attach(new Table\OptimisticLock("counter"));
                $row = $this->table->find(null, null, 1)->current();
                $row->data = "foo";
                executeInConcurrentTransaction(