diff --git a/phpstan.neon b/phpstan.neon index 0678015..819a577 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -4,7 +4,6 @@ parameters: - '#Method Muffin\\Webservice\\Query::endpoint\(\) should return \$this\(Muffin\\Webservice\\Query\)|Muffin\\Webservice\\Model\\Endpoint but returns Cake\Datasource\RepositoryInterface#' - '#Call to an undefined method Cake\\Datasource\\RepositoryInterface::callFinder\(\)#' - '#Call to an undefined method Cake\\Datasource\\RepositoryInterface::dispatchEvent\(\)#' - - '#Method Muffin\\Webservice\\Query::offset\(\) should return \$this\(Cake\\Datasource\\QueryInterface\) but returns \$this\(Muffin\\Webservice\\Query\)#' - '#Return type \(array\) of method Muffin\\Webservice\\Query::aliasField\(\) should be compatible with return type \(string\) of method Cake\\Datasource\\QueryInterface::aliasField\(\)#' - '#Call to an undefined method Cake\\Datasource\\RepositoryInterface::getName\(\)#' - '#Call to an undefined method Traversable::count\(\)#' diff --git a/src/Model/Endpoint.php b/src/Model/Endpoint.php index 48fc896..820eea2 100644 --- a/src/Model/Endpoint.php +++ b/src/Model/Endpoint.php @@ -1106,6 +1106,12 @@ public function save(EntityInterface $resource, $options = []) return false; } + $event = $this->dispatchEvent('Model.afterSave', compact('resource', 'options')); + + if ($event->isStopped()) { + return $event->getResult(); + } + if (($resource->isNew()) && ($result instanceof EntityInterface)) { return $result; } @@ -1127,9 +1133,23 @@ public function save(EntityInterface $resource, $options = []) */ public function delete(EntityInterface $resource, $options = []) { - return (bool)$this->query()->delete()->where([ + $event = $this->dispatchEvent('Model.beforeDelete', compact('resource', 'options')); + + if ($event->isStopped()) { + return $event->getResult(); + } + + $result = (bool)$this->query()->delete()->where([ $this->getPrimaryKey() => $resource->get($this->getPrimaryKey()) ])->execute(); + + $event = $this->dispatchEvent('Model.afterDelete', compact('resource', 'options')); + + if ($event->isStopped()) { + return $event->getResult(); + } + + return $result; } /** diff --git a/tests/TestCase/Model/EndpointAfterSaveCallbackTest.php b/tests/TestCase/Model/EndpointAfterSaveCallbackTest.php new file mode 100644 index 0000000..4e4aa0e --- /dev/null +++ b/tests/TestCase/Model/EndpointAfterSaveCallbackTest.php @@ -0,0 +1,119 @@ +connection = new Connection([ + 'name' => 'test', + 'service' => 'Test' + ]); + $this->endpoint = new CallbackEndpoint([ + 'connection' => $this->connection, + 'primaryKey' => 'id', + 'displayField' => 'title', + 'schema' => [ + 'id' => ['type' => 'int'], + 'title' => ['type' => 'string'], + 'body' => ['type' => 'string'], + ] + ]); + } + + /** + * Test afterSave return altered data + */ + public function testAfterSave() + { + $resource = new Resource([ + 'id' => 4, + 'title' => 'Loads of fun', + 'body' => 'Woot' + ]); + + $savedResource = $this->endpoint->save($resource); + $this->assertInstanceOf('\Muffin\Webservice\Model\Resource', $savedResource); + $this->assertEquals([ + 'id' => 4, + 'title' => 'Loads of sun', + 'body' => 'Woot' + ], $savedResource->toArray()); + + $newResource = $this->endpoint->get(4); + $this->assertInstanceOf('\Muffin\Webservice\Model\Resource', $newResource); + $this->assertEquals([ + 'id' => 4, + 'title' => 'Loads of fun', + 'body' => 'Woot' + ], $newResource->toArray()); + } + + /** + * Test beforeDelete and afterDelete return altered data + * + */ + public function testBeforeAndAfterDelete() + { + $resource1 = new Resource([ + 'id' => 4, + 'title' => 'Loads of sun', + 'body' => 'Woot' + ]); + $resource2 = new Resource([ + 'id' => 5, + 'title' => 'I love sun', + 'body' => 'Woot' + ]); + $resource3 = new Resource([ + 'id' => 6, + 'title' => 'I need sun', + 'body' => 'Woot' + ]); + $savedResource = $this->endpoint->save($resource1); + $this->assertInstanceOf('\Muffin\Webservice\Model\Resource', $savedResource); + $savedResource = $this->endpoint->save($resource2); + $this->assertInstanceOf('\Muffin\Webservice\Model\Resource', $savedResource); + $savedResource = $this->endpoint->save($resource3); + $this->assertInstanceOf('\Muffin\Webservice\Model\Resource', $savedResource); + + $resource = $this->endpoint->get(4); + $deletedResource = $this->endpoint->delete($resource); + $this->assertTrue($deletedResource); + + $editedResource = $this->endpoint->get(5); + $this->assertEquals([ + 'id' => 5, + 'title' => 'I love fun', + 'body' => 'Woot' + ], $editedResource->toArray()); + + $editedResource2 = $this->endpoint->get(6); + $this->assertEquals([ + 'id' => 6, + 'title' => 'I need fun', + 'body' => 'Woot' + ], $editedResource2->toArray()); + } +} diff --git a/tests/test_app/Model/Endpoint/CallbackEndpoint.php b/tests/test_app/Model/Endpoint/CallbackEndpoint.php new file mode 100644 index 0000000..3f73503 --- /dev/null +++ b/tests/test_app/Model/Endpoint/CallbackEndpoint.php @@ -0,0 +1,60 @@ +get('title')) { + $entity->set('title', 'Loads of sun'); + } + + return $entity; + } + + /** + * Test beforeDelete Callback + * @param Event $event + * @param EntityInterface $entity + * @return EntityInterface + */ + public function beforeDelete(Event $event, EntityInterface $entity) + { + $entity = $this->get(5); + if ($entity->get('title')) { + $entity->set('title', 'I love fun'); + } + + return $entity; + } + + /** + * Test afterDelete Callback + * @param Event $event + * @param EntityInterface $entity + * @return EntityInterface + */ + public function afterDelete(Event $event, EntityInterface $entity) + { + $entity = $this->get(6); + if ($entity->get('title')) { + $entity->set('title', 'I need fun'); + } + + return $entity; + } +}