diff --git a/src/ZfrRest/Mvc/Router/Http/Matcher/CollectionSubPathMatcher.php b/src/ZfrRest/Mvc/Router/Http/Matcher/CollectionSubPathMatcher.php index b9461f5..e36fe75 100644 --- a/src/ZfrRest/Mvc/Router/Http/Matcher/CollectionSubPathMatcher.php +++ b/src/ZfrRest/Mvc/Router/Http/Matcher/CollectionSubPathMatcher.php @@ -99,7 +99,11 @@ protected function findItem($data, array $identifierNames, $identifier) $data = new ArrayCollection(ArrayUtils::iteratorToArray($data)); } - $found = $data->matching(new Criteria(Criteria::expr()->eq(reset($identifierNames), $identifier))); + $criteria = new Criteria(); + + $criteria->andWhere($criteria->expr()->eq(reset($identifierNames), $identifier)); + + $found = $data->matching($criteria); return $found->isEmpty() ? null : $found->first(); } @@ -128,7 +132,8 @@ protected function filterAssociation(ResourceInterface $resource, Request $reque $criteria = new Criteria(); $classMetadata = $resource->getMetadata()->getClassMetadata(); - // @todo do we really need this part? This filtering is not safe. + // @todo do we really need this part? This filtering is not safe by default + // @fixme to be removed before merge foreach ($request->getQuery() as $parameterName => $parameterValue) { if ($classMetadata->hasField($parameterName)) { $criteria->expr()->eq($parameterName, $parameterValue); diff --git a/src/ZfrRest/Mvc/Router/Http/ResourceGraphRoute.php b/src/ZfrRest/Mvc/Router/Http/ResourceGraphRoute.php index 641a381..f365cdd 100644 --- a/src/ZfrRest/Mvc/Router/Http/ResourceGraphRoute.php +++ b/src/ZfrRest/Mvc/Router/Http/ResourceGraphRoute.php @@ -121,18 +121,15 @@ public function match(Request $request) $uri = $request->getUri(); $path = $uri->getPath(); - $matchedPath = rtrim($path, '/'); // If the route is not even contained within the URI, we can return early... - if (strpos($matchedPath, $this->route) === false && strpos($path, $this->route) === false) { + if (strpos($path, $this->route) === false) { return null; } - if ($matchedPath === $this->route || $path === $this->route) { - return $this->buildRouteMatch($this->getResource(), $path); - } + $subPath = substr($path, strlen($this->route)); - if (! $match = $this->subPathMatcher->matchSubPath($this->getResource(), $path, $request)) { + if (! $match = $this->subPathMatcher->matchSubPath($this->getResource(), $subPath, $request)) { return null; } diff --git a/tests/ZfrRestTest/Mvc/Router/Http/ResourceGraphRouteFunctionalTest.php b/tests/ZfrRestTest/Mvc/Router/Http/ResourceGraphRouteFunctionalTest.php index 6f565d4..2e0a95b 100644 --- a/tests/ZfrRestTest/Mvc/Router/Http/ResourceGraphRouteFunctionalTest.php +++ b/tests/ZfrRestTest/Mvc/Router/Http/ResourceGraphRouteFunctionalTest.php @@ -18,11 +18,13 @@ namespace ZfrRestTest\Mvc; +use Doctrine\ORM\Tools\SchemaTool; use PHPUnit_Framework_TestCase as TestCase; use Zend\Http\Request; use ZfrRest\Factory\ResourceGraphRouteFactory; use ZfrRest\Http\Exception; use ZfrRest\Mvc\Router\Http\ResourceGraphRoute; +use ZfrRestTest\Asset\Annotation\Tweet; use ZfrRestTest\Util\ServiceManagerFactory; /** @@ -35,6 +37,11 @@ */ class ResourceGraphRouteFunctionalTest extends TestCase { + /** + * @var \Zend\ServiceManager\ServiceManager + */ + protected $serviceManager; + /** * @var \Doctrine\Common\Persistence\ObjectManager */ @@ -50,23 +57,18 @@ class ResourceGraphRouteFunctionalTest extends TestCase */ protected function setUp() { - $serviceManager = ServiceManagerFactory::getServiceManager(); - $this->objectManager = $serviceManager->get('Doctrine\\ORM\\EntityManager'); - $routeFactory = new ResourceGraphRouteFactory(); + $this->serviceManager = ServiceManagerFactory::getServiceManager(); + /* @var $objectManager \Doctrine\Common\Persistence\ObjectManager */ + $objectManager = $this->serviceManager->get('Doctrine\\ORM\\EntityManager'); - $serviceManager->setService( + $this->serviceManager->setService( 'ZfrRestTest\Asset\Repository\PageRepository', - $this->objectManager->getRepository('ZfrRestTest\Asset\Annotation\Page') + $objectManager->getRepository('ZfrRestTest\Asset\Annotation\Page') ); - - $routeFactory->setCreationOptions( - array( - 'route' => '/foo/bar/', - 'resource' => 'ZfrRestTest\Asset\Repository\PageRepository', - ) + $this->serviceManager->setService( + 'ZfrRestTest\Asset\Repository\TweetRepository', + $objectManager->getRepository('ZfrRestTest\Asset\Annotation\Tweet') ); - - $this->router = $routeFactory->createService($serviceManager->get('RoutePluginManager')); } /** @@ -75,7 +77,7 @@ protected function setUp() */ public function testRetrievesChildClassMetadata() { - $match = $this->router->match($this->createRequest('/foo/bar/')); + $match = $this->createRoute()->match($this->createRequest('/foo/bar/')); $this->assertInstanceOf('Zend\\Mvc\\Router\\RouteMatch', $match); @@ -96,7 +98,7 @@ public function testRetrievesChildClassMetadata() */ public function testMatchesSlashes($path, $shouldMatch) { - $match = $this->router->match($this->createRequest($path)); + $match = $this->createRoute()->match($this->createRequest($path)); if ($shouldMatch) { $this->assertInstanceOf('Zend\\Mvc\\Router\\RouteMatch', $match); @@ -105,6 +107,39 @@ public function testMatchesSlashes($path, $shouldMatch) } } + /** + * Verifying that the resource route is able to find single items in selectables + */ + public function testMatchesSimpleCollectionItem() + { + $tweet = new Tweet(); + $tweet->setContent('42!'); + + $objectManager = $this->getObjectManager(); + + $objectManager->persist($tweet); + $objectManager->flush(); + $objectManager->clear(); + + $match = $this + ->createRoute('/tweets/', 'ZfrRestTest\Asset\Repository\TweetRepository') + ->match($this->createRequest('/tweets/' . $tweet->getId())); + + $this->assertInstanceOf('Zend\\Mvc\\Router\\RouteMatch', $match); + + /* @var $resource \ZfrRest\Resource\ResourceInterface */ + $resource = $match->getParam('resource'); + + + $this->assertInstanceOf('ZfrRest\\Resource\\ResourceInterface', $resource); + + /* @var $data \ZfrRestTest\Asset\Annotation\Tweet */ + $data = $resource->getData(); + + $this->assertInstanceOf('ZfrRestTest\Asset\Annotation\Tweet', $data); + $this->assertSame($tweet->getId(), $data->getId()); + } + /** * @param string $uri * @param array $query @@ -124,6 +159,40 @@ private function createRequest($uri, array $query = array()) return $request; } + /** + * @param string $path + * @param string $serviceName + * + * @return ResourceGraphRoute + */ + private function createRoute($path = '/foo/bar/', $serviceName = 'ZfrRestTest\Asset\Repository\PageRepository') + { + $routeFactory = new ResourceGraphRouteFactory(); + + $routeFactory->setCreationOptions( + array( + 'route' => $path, + 'resource' => $serviceName, + ) + ); + + return $routeFactory->createService($this->serviceManager->get('RoutePluginManager')); + } + + /** + * @return \Doctrine\Common\Persistence\ObjectManager + */ + private function getObjectManager() + { + /* @var $entityManager \Doctrine\ORM\EntityManager */ + $entityManager = $this->serviceManager->get('Doctrine\\ORM\\EntityManager'); + $schemaTool = new SchemaTool($entityManager); + + $schemaTool->createSchema($entityManager->getMetadataFactory()->getAllMetadata()); + + return $entityManager; + } + /** * @return array */ diff --git a/tests/testing.config.php b/tests/testing.config.php index 61b9edc..3fa874d 100644 --- a/tests/testing.config.php +++ b/tests/testing.config.php @@ -42,6 +42,21 @@ ) ) ), + 'connection' => array( + 'orm_default' => array( + 'params' => array( + 'host' => null, + 'port' => null, + 'user' => null, + 'password' => null, + 'dbname' => null, + 'driver' => 'pdo_sqlite', + 'driverClass' => 'Doctrine\DBAL\Driver\PDOSqlite\Driver', + 'path' => null, + 'memory' => true, + ), + ), + ), ), 'controllers' => array(