From 25192f4e97de3e337393a12baecd85c352c5d26b Mon Sep 17 00:00:00 2001 From: Andris Causs Date: Wed, 23 Sep 2015 19:46:13 +0100 Subject: [PATCH 01/10] Fixed typo in the use statement of InvalidArgumentException --- src/Server/Exception/InvalidArgumentException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Server/Exception/InvalidArgumentException.php b/src/Server/Exception/InvalidArgumentException.php index da40c839..8ba20474 100644 --- a/src/Server/Exception/InvalidArgumentException.php +++ b/src/Server/Exception/InvalidArgumentException.php @@ -2,7 +2,7 @@ namespace ZF\Apigility\Doctrine\Server\Exception; -use InvalidArgumentExcpetion as PHPInvalidArgumentException; +use InvalidArgumentException as PHPInvalidArgumentException; /** * Class InvalidArgumentException From 238c149d773086f7caa3435d61c6d53e11b6d8d8 Mon Sep 17 00:00:00 2001 From: Tom Anderson Date: Mon, 28 Sep 2015 10:26:07 -0600 Subject: [PATCH 02/10] Added installation note for Apache AllowEncodedSlashes covers https://github.com/zfcampus/zf-apigility-doctrine/pull/230 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4e59a84b..894eac4e 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ and *Server* in your `application.config.php` `ZF\Apigility\Doctrine\Server` has a dependency with `Phpro\DoctrineHydrationModule` to handle entity hydration. See [documentation and instructions](https://github.com/phpro/zf-doctrine-hydration-module) on how to set up this module. +For Apache installations it is recommended the [AllowEncodedSlashes-directive is set to On](http://httpd.apache.org/docs/2.4/mod/core.html#allowencodedslashes) so the configuration can be read. API Resources ------------- From 48fb27a793311ff87712aef906b90fdaa5c9ed20 Mon Sep 17 00:00:00 2001 From: Andrey Oprokidnev Date: Wed, 30 Sep 2015 14:36:40 +0500 Subject: [PATCH 03/10] Some route parameters should be restricted in doctrine resource. --- src/Server/Resource/DoctrineResource.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Server/Resource/DoctrineResource.php b/src/Server/Resource/DoctrineResource.php index 46e7c00d..6ef88b73 100644 --- a/src/Server/Resource/DoctrineResource.php +++ b/src/Server/Resource/DoctrineResource.php @@ -752,8 +752,16 @@ protected function findEntity($id, $method) if (array_key_exists($this->getRouteIdentifierName(), $routeParams)) { unset($routeParams[$this->getRouteIdentifierName()]); } - - foreach ($routeParams as $routeMatchParam => $value) { + + $reservedRouteParams = ['controller','action', + \Zend\Mvc\ModuleRouteListener::MODULE_NAMESPACE,\Zend\Mvc\ModuleRouteListener::ORIGINAL_CONTROLLER + ]; + $allowedRouteParams = array_diff_key($routeParams, array_flip( $reservedRouteParams ) ); + + /** + * Append query selection parameters by route match. + */ + foreach ($allowedRouteParams as $routeMatchParam => $value) { if ($this->getStripRouteParameterSuffix() === substr( $routeMatchParam, -1 * strlen($this->getStripRouteParameterSuffix()) @@ -769,7 +777,7 @@ protected function findEntity($id, $method) // Build query $queryProvider = $this->getQueryProvider($method); $queryBuilder = $queryProvider->createQuery($this->getEvent(), $this->getEntityClass(), null); - + if ($queryBuilder instanceof ApiProblem) { // @codeCoverageIgnoreStart return $queryBuilder; From ecb7ab75ec9a1f06e8516edc7fae7777ddf8776b Mon Sep 17 00:00:00 2001 From: Tom Anderson Date: Tue, 13 Oct 2015 09:20:22 -0600 Subject: [PATCH 04/10] Fix function declaration for zend-hydrator instead of stdlib --- src/Server/Resource/DoctrineResource.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Server/Resource/DoctrineResource.php b/src/Server/Resource/DoctrineResource.php index 46e7c00d..86a84da6 100644 --- a/src/Server/Resource/DoctrineResource.php +++ b/src/Server/Resource/DoctrineResource.php @@ -23,8 +23,8 @@ use Zend\EventManager\EventManagerInterface; use Zend\EventManager\StaticEventManager; use Zend\Stdlib\ArrayUtils; -use Zend\Stdlib\Hydrator\HydratorAwareInterface; -use Zend\Stdlib\Hydrator\HydratorInterface; +use Zend\Hydrator\HydratorAwareInterface; +use Zend\Hydrator\HydratorInterface; use Traversable; use ReflectionClass; From 4246f8ada4cacd2461800d1e5c50828260fdca2d Mon Sep 17 00:00:00 2001 From: Tom Anderson Date: Tue, 13 Oct 2015 12:58:08 -0600 Subject: [PATCH 05/10] Require zf hydrator in composer --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 05cadd8c..f0452391 100644 --- a/composer.json +++ b/composer.json @@ -37,6 +37,7 @@ "require": { "php": ">=5.4", "phpro/zf-doctrine-hydration-module": "^0.1.5", + "zendframework/zend-hydrator": "^1.0", "zfcampus/zf-apigility": "^1.0" }, "prefer-stable": true, From c02c01b9d0066ff26daf6432f0a8e72f0321613e Mon Sep 17 00:00:00 2001 From: Tom Anderson Date: Wed, 28 Oct 2015 20:48:16 -0600 Subject: [PATCH 06/10] Added ORM & ODM modules to composer suggest --- composer.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/composer.json b/composer.json index f0452391..56e07fa4 100644 --- a/composer.json +++ b/composer.json @@ -40,6 +40,10 @@ "zendframework/zend-hydrator": "^1.0", "zfcampus/zf-apigility": "^1.0" }, + "suggest": { + "doctrine/doctrine-orm-module": "For ORM mapping", + "doctrine/doctrine-mongo-odm-module": "For Mongo ODM mapping" + }, "prefer-stable": true, "autoload": { "psr-4": { From 5db683c2b061eabae1120064be58a08b9f3c6f70 Mon Sep 17 00:00:00 2001 From: Tom Anderson Date: Wed, 28 Oct 2015 21:03:01 -0600 Subject: [PATCH 07/10] phpcs fixes --- src/Server/Resource/DoctrineResource.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Server/Resource/DoctrineResource.php b/src/Server/Resource/DoctrineResource.php index 6ef88b73..28bf1eb3 100644 --- a/src/Server/Resource/DoctrineResource.php +++ b/src/Server/Resource/DoctrineResource.php @@ -756,7 +756,7 @@ protected function findEntity($id, $method) $reservedRouteParams = ['controller','action', \Zend\Mvc\ModuleRouteListener::MODULE_NAMESPACE,\Zend\Mvc\ModuleRouteListener::ORIGINAL_CONTROLLER ]; - $allowedRouteParams = array_diff_key($routeParams, array_flip( $reservedRouteParams ) ); + $allowedRouteParams = array_diff_key($routeParams, array_flip($reservedRouteParams)); /** * Append query selection parameters by route match. From e7257639e26817024a0a8e330a83e7d52654440f Mon Sep 17 00:00:00 2001 From: Tom Anderson Date: Tue, 8 Dec 2015 21:08:30 -0700 Subject: [PATCH 08/10] Replaced static event manager with shared event manager, fixed hal collection 'query' parameters in getList.post event --- src/Server/Resource/DoctrineResource.php | 52 ++++++------------- .../Resource/DoctrineResourceFactory.php | 9 +++- 2 files changed, 24 insertions(+), 37 deletions(-) diff --git a/src/Server/Resource/DoctrineResource.php b/src/Server/Resource/DoctrineResource.php index f2229f94..1c97f37b 100644 --- a/src/Server/Resource/DoctrineResource.php +++ b/src/Server/Resource/DoctrineResource.php @@ -2,8 +2,6 @@ namespace ZF\Apigility\Doctrine\Server\Resource; -use Zend\ServiceManager\ServiceManager; -use Zend\ServiceManager\ServiceManagerAwareInterface; use Doctrine\Common\Persistence\ObjectManager; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\EntityManagerInterface; @@ -21,10 +19,10 @@ use Zend\EventManager\EventManager; use Zend\EventManager\EventManagerAwareInterface; use Zend\EventManager\EventManagerInterface; -use Zend\EventManager\StaticEventManager; use Zend\Stdlib\ArrayUtils; -use Zend\Hydrator\HydratorAwareInterface; -use Zend\Hydrator\HydratorInterface; +use Zend\Stdlib\Hydrator\HydratorAwareInterface; +use Zend\Stdlib\Hydrator\HydratorInterface; +use Zend\EventManager\SharedEventManager; use Traversable; use ReflectionClass; @@ -34,34 +32,25 @@ * @package ZF\Apigility\Doctrine\Server\Resource */ class DoctrineResource extends AbstractResourceListener implements - ServiceManagerAwareInterface, ObjectManagerAwareInterface, EventManagerAwareInterface, HydratorAwareInterface { /** - * @var ServiceManager + * @var SharedEventManager Interface */ - protected $serviceManager; + protected $sharedEventManager; - /** - * @param ServiceManager $serviceManager - * - * @return $this - */ - public function setServiceManager(ServiceManager $serviceManager) + public function getSharedEventManager() { - $this->serviceManager = $serviceManager; - - return $this; + return $this->sharedEventManager; } - /** - * @return ServiceManager - */ - public function getServiceManager() + public function setSharedEventManager(SharedEventManager $sharedEventManager) { - return $this->serviceManager; + $this->sharedEventManager = $sharedEventManager; + + return $this; } /** @@ -571,7 +560,8 @@ public function fetchAll($data = array()) // Add event to set extra HAL data $entityClass = $this->getEntityClass(); - StaticEventManager::getInstance()->attach( + + $this->getSharedEventManager()->attach( 'ZF\Rest\RestController', 'getList.post', function (EventInterface $e) use ($queryProvider, $entityClass, $data) { @@ -582,17 +572,9 @@ function (EventInterface $e) use ($queryProvider, $entityClass, $data) { $collection->setItemCountPerPage($halCollection->getPageSize()); $collection->setCurrentPageNumber($halCollection->getPage()); - $halCollection->setAttributes( - array( - 'count' => $collection->getCurrentItemCount(), - 'total' => $collection->getTotalItemCount(), - 'collectionTotal' => $queryProvider->getCollectionTotal($entityClass) - ) - ); - $halCollection->setCollectionRouteOptions( array( - 'query' => ArrayUtils::iteratorToArray($data) + 'query' => $e->getTarget()->getRequest()->getQuery()->toArray() ) ); } @@ -752,12 +734,12 @@ protected function findEntity($id, $method) if (array_key_exists($this->getRouteIdentifierName(), $routeParams)) { unset($routeParams[$this->getRouteIdentifierName()]); } - + $reservedRouteParams = ['controller','action', \Zend\Mvc\ModuleRouteListener::MODULE_NAMESPACE,\Zend\Mvc\ModuleRouteListener::ORIGINAL_CONTROLLER ]; $allowedRouteParams = array_diff_key($routeParams, array_flip($reservedRouteParams)); - + /** * Append query selection parameters by route match. */ @@ -777,7 +759,7 @@ protected function findEntity($id, $method) // Build query $queryProvider = $this->getQueryProvider($method); $queryBuilder = $queryProvider->createQuery($this->getEvent(), $this->getEntityClass(), null); - + if ($queryBuilder instanceof ApiProblem) { // @codeCoverageIgnoreStart return $queryBuilder; diff --git a/src/Server/Resource/DoctrineResourceFactory.php b/src/Server/Resource/DoctrineResourceFactory.php index 8373fce1..ed52c7e4 100644 --- a/src/Server/Resource/DoctrineResourceFactory.php +++ b/src/Server/Resource/DoctrineResourceFactory.php @@ -19,7 +19,6 @@ */ class DoctrineResourceFactory implements AbstractFactoryInterface { - /** * Cache of canCreateServiceWithName lookups * @var array @@ -39,11 +38,13 @@ class DoctrineResourceFactory implements AbstractFactoryInterface public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName) { if (array_key_exists($requestedName, $this->lookupCache)) { + return $this->lookupCache[$requestedName]; } if (!$serviceLocator->has('Config')) { // @codeCoverageIgnoreStart + return false; } // @codeCoverageIgnoreEnd @@ -142,13 +143,14 @@ public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $ /** @var DoctrineResource $listener */ $listener = new $className(); - $listener->setServiceManager($serviceLocator); + $listener->setSharedEventManager($serviceLocator->get('Application')->getEventManager()->getSharedManager()); $listener->setObjectManager($objectManager); $listener->setHydrator($hydrator); $listener->setQueryProviders($queryProviders); $listener->setQueryCreateFilter($queryCreateFilter); $listener->setEntityIdentifierName($restConfig['entity_identifier_name']); $listener->setRouteIdentifierName($restConfig['route_identifier_name']); + if (count($configuredListeners)) { foreach ($configuredListeners as $configuredListener) { $listener->getEventManager()->attach($configuredListener); @@ -184,6 +186,7 @@ protected function loadObjectManager(ServiceLocatorInterface $serviceLocator, $c throw new ServiceNotCreatedException('The object_manager could not be found.'); } // @codeCoverageIgnoreEnd + return $objectManager; } @@ -225,6 +228,7 @@ protected function loadHydrator( } // @codeCoverageIgnoreEnd + return $hydratorManager->get($doctrineConnectedConfig['hydrator']); } @@ -309,6 +313,7 @@ protected function loadConfiguredListeners(ServiceLocatorInterface $serviceLocat foreach ($config['listeners'] as $listener) { $listeners[] = $serviceLocator->get($listener); } + return $listeners; } } From ac07655d952b76da8c80c899f1fce82fbb53426b Mon Sep 17 00:00:00 2001 From: Tom Anderson Date: Wed, 16 Dec 2015 13:54:41 -0700 Subject: [PATCH 09/10] Pass $data to query providers for update and patch --- src/Server/Resource/DoctrineResource.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Server/Resource/DoctrineResource.php b/src/Server/Resource/DoctrineResource.php index 1c97f37b..c084133d 100644 --- a/src/Server/Resource/DoctrineResource.php +++ b/src/Server/Resource/DoctrineResource.php @@ -592,7 +592,7 @@ function (EventInterface $e) use ($queryProvider, $entityClass, $data) { */ public function patch($id, $data) { - $entity = $this->findEntity($id, 'patch'); + $entity = $this->findEntity($id, 'patch', $data); if ($entity instanceof ApiProblem) { // @codeCoverageIgnoreStart @@ -639,7 +639,7 @@ public function replaceList($data) */ public function update($id, $data) { - $entity = $this->findEntity($id, 'update'); + $entity = $this->findEntity($id, 'update', $data); if ($entity instanceof ApiProblem) { // @codeCoverageIgnoreStart @@ -702,7 +702,7 @@ protected function triggerDoctrineEvent($name, $entity, $data = null) * * @return object */ - protected function findEntity($id, $method) + protected function findEntity($id, $method, $data = null) { // Match identiy identifier name(s) with id(s) $ids = explode($this->getMultiKeyDelimiter(), $id); @@ -758,7 +758,7 @@ protected function findEntity($id, $method) // Build query $queryProvider = $this->getQueryProvider($method); - $queryBuilder = $queryProvider->createQuery($this->getEvent(), $this->getEntityClass(), null); + $queryBuilder = $queryProvider->createQuery($this->getEvent(), $this->getEntityClass(), $data); if ($queryBuilder instanceof ApiProblem) { // @codeCoverageIgnoreStart From 7c0de777fd6f5990379044904a5c2210818d00ae Mon Sep 17 00:00:00 2001 From: Tom Anderson Date: Wed, 16 Dec 2015 15:07:32 -0700 Subject: [PATCH 10/10] Rolled back to zend-stdlib 2.4; 2.7 isn't suppored by doctrine-module for hydrators --- composer.json | 17 ++++++++--------- test/src/Server/ORM/CRUD/CRUDTest.php | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/composer.json b/composer.json index ad25e320..3b2c7825 100644 --- a/composer.json +++ b/composer.json @@ -22,23 +22,22 @@ } }, "require-dev": { - "doctrine/doctrine-mongo-odm-module": "^0.9.0", - "doctrine/doctrine-orm-module": "^0.9.0", + "doctrine/doctrine-mongo-odm-module": "^0.9", + "doctrine/doctrine-orm-module": "^0.9", "doctrine/mongodb-odm": "^1", "phpunit/phpunit": "^4.7", "squizlabs/php_codesniffer": "^2.3.0", - "zendframework/zend-form": "^2.5.0", - "zendframework/zend-log": "^2.5.0", - "zendframework/zend-serializer": "^2.5.0", - "zendframework/zend-test": "^2.5.0", - "zendframework/zend-hydrator": "~1", + "zendframework/zend-form": "~2.4", + "zendframework/zend-log": "~2.4", + "zendframework/zend-serializer": "~2.4", + "zendframework/zend-test": "~2.4", + "zendframework/zend-stdlib": "2.4.9", "zfcampus/zf-apigility-admin": "^1.1", - "zendframework/zend-i18n": "^2.5.0" + "zendframework/zend-i18n": "~2.4" }, "require": { "php": ">=5.4", "phpro/zf-doctrine-hydration-module": "^0.1.5", - "zendframework/zend-hydrator": "^1.0", "zfcampus/zf-apigility": "^1.0" }, "suggest": { diff --git a/test/src/Server/ORM/CRUD/CRUDTest.php b/test/src/Server/ORM/CRUD/CRUDTest.php index 782a4d46..dac7616c 100644 --- a/test/src/Server/ORM/CRUD/CRUDTest.php +++ b/test/src/Server/ORM/CRUD/CRUDTest.php @@ -656,7 +656,7 @@ public function testRpcController() $this->getRequest()->setContent(null); $this->dispatch("/test/artist/$artistId/album"); $body = json_decode($this->getResponse()->getBody(), true); - $this->assertEquals(2, $body['count']); + $this->assertEquals(2, $body['total_items']); $this->dispatch("/test/artist/$artistId/album/$albumId"); $body = json_decode($this->getResponse()->getBody(), true);