diff --git a/.gitignore b/.gitignore index bdfc625..93344bf 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ phpunit.xml clover.xml tmp/ vendor/ - +composer.lock +composer.phar diff --git a/.travis.yml b/.travis.yml index f257ea5..01e2d49 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,26 @@ language: php php: + - 5.3.3 - 5.3 - 5.4 + - 5.5 + +matrix: + allow_failures: + - php: 5.5 before_script: - composer self-update - - composer update --prefer-source + - composer update --prefer-source --dev script: - - phpunit + - ./vendor/bin/phpunit --coverage-clover ./build/logs/clover.xml --exclude-group Performance + - ./vendor/bin/phpunit --group=Functional + - ./vendor/bin/phpcs --standard=PSR2 ./src/ ./tests/ + +after_script: + - php vendor/bin/coveralls -v notifications: irc: "irc.freenode.org#zftalk.modules" diff --git a/composer.json b/composer.json index ed82834..5909795 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,10 @@ "doctrine/doctrine-module": "~0.8" }, "require-dev": { - "doctrine/doctrine-orm-module": "~0.8" + "doctrine/doctrine-orm-module": "~0.8", + "phpunit/phpunit": "~3.7", + "squizlabs/php_codesniffer": "1.4.*", + "satooshi/php-coveralls": "~0.6" }, "autoload": { "psr-0": { diff --git a/config/module.config.php b/config/module.config.php index a2c2821..0f239d0 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -25,12 +25,13 @@ 'factories' => array( 'ZfrRest\Mvc\View\Http\SelectModelListener' => 'ZfrRest\Factory\SelectModelListenerFactory', - 'ZfrRest\Mvc\View\Http\CreateResourcePayloadListener' => 'ZfrRest\Factory\CreateResourcePayloadListenerFactory', 'ZfrRest\Options\ModuleOptions' => 'ZfrRest\Factory\ModuleOptionsFactory', 'ZfrRest\Resource\Metadata\CacheProvider' => 'ZfrRest\Factory\ResourceMetadataCacheFactory', 'ZfrRest\Resource\Metadata\MetadataFactory' => 'ZfrRest\Factory\ResourceMetadataFactoryFactory', 'ZfrRest\Serializer\DecoderPluginManager' => 'ZfrRest\Factory\DecoderPluginManagerFactory', 'ZfrRest\View\Model\ModelPluginManager' => 'ZfrRest\Factory\ModelPluginManagerFactory', + 'ZfrRest\Mvc\View\Http\CreateResourcePayloadListener' + => 'ZfrRest\Factory\CreateResourcePayloadListenerFactory', ) ), diff --git a/src/ZfrRest/Controller/CacheController.php b/src/ZfrRest/Controller/CacheController.php index d270343..58fdce1 100644 --- a/src/ZfrRest/Controller/CacheController.php +++ b/src/ZfrRest/Controller/CacheController.php @@ -39,11 +39,11 @@ public function clearCacheAction() try { /** @var $cache \Doctrine\Common\Cache\CacheProvider */ $cache = $this->serviceLocator->get('ZfrRest\Resource\Metadata\CacheProvider'); - } catch(Exception $e) { + } catch (Exception $e) { return "\nNo cache to clear. Are you sure you set ZfrRest cache correctly?\n\n"; } - if($cache->flushAll()) { + if ($cache->flushAll()) { return "\nThe cache were successfully cleared\n\n"; } diff --git a/src/ZfrRest/Factory/CreateResourcePayloadListenerFactory.php b/src/ZfrRest/Factory/CreateResourcePayloadListenerFactory.php index 1dd51f1..82ed562 100644 --- a/src/ZfrRest/Factory/CreateResourcePayloadListenerFactory.php +++ b/src/ZfrRest/Factory/CreateResourcePayloadListenerFactory.php @@ -35,6 +35,9 @@ class CreateResourcePayloadListenerFactory implements FactoryInterface */ public function createService(ServiceLocatorInterface $serviceLocator) { - return new CreateResourcePayloadListener($serviceLocator->get('HydratorManager')); + /* @var $hydratorManager \Zend\Stdlib\Hydrator\HydratorPluginManager */ + $hydratorManager = $serviceLocator->get('HydratorManager'); + + return new CreateResourcePayloadListener($hydratorManager); } } diff --git a/src/ZfrRest/Factory/DecoderPluginManagerFactory.php b/src/ZfrRest/Factory/DecoderPluginManagerFactory.php index 038e440..e89e2e1 100644 --- a/src/ZfrRest/Factory/DecoderPluginManagerFactory.php +++ b/src/ZfrRest/Factory/DecoderPluginManagerFactory.php @@ -36,10 +36,10 @@ class DecoderPluginManagerFactory implements FactoryInterface */ public function createService(ServiceLocatorInterface $serviceLocator) { - $config = $serviceLocator->get('Config'); - $config = $config['zfr_rest']['decoders']; + /* @var $options \ZfrRest\Options\ModuleOptions */ + $options = $serviceLocator->get('ZfrRest\Options\ModuleOptions'); - $decoderPluginManager = new DecoderPluginManager(new Config($config)); + $decoderPluginManager = new DecoderPluginManager(new Config($options->getDecoders())); $decoderPluginManager->setServiceLocator($serviceLocator); return $decoderPluginManager; diff --git a/src/ZfrRest/Factory/Exception/RuntimeException.php b/src/ZfrRest/Factory/Exception/RuntimeException.php index 1775680..4b72196 100644 --- a/src/ZfrRest/Factory/Exception/RuntimeException.php +++ b/src/ZfrRest/Factory/Exception/RuntimeException.php @@ -18,7 +18,9 @@ namespace ZfrRest\Factory\Exception; +use Exception; use RuntimeException as BaseRuntimeException; +use Zend\ServiceManager\ServiceLocatorInterface; use ZfrRest\Exception\ExceptionInterface; /** @@ -29,4 +31,83 @@ */ class RuntimeException extends BaseRuntimeException implements ExceptionInterface { + /** + * @param ServiceLocatorInterface $serviceLocator + * + * @return self + */ + public static function pluginManagerExpected(ServiceLocatorInterface $serviceLocator) + { + return new self( + sprintf('A hydrator plugin manager was expected, but "%s" was given', get_class($serviceLocator)) + ); + } + + /** + * @param string $resourceName + * @param Exception|null $previous + * + * @return self + */ + public static function missingResource($resourceName, Exception $previous = null) + { + return new self(sprintf('Resource "%s" cannot be found in the service locator', $resourceName), 0, $previous); + } + + /** + * @param string $serviceName + * @param Exception|null $previous + * + * @return self + */ + public static function missingObjectManager($serviceName, Exception $previous = null) + { + return new self(sprintf('The object manager key is not valid, "%s" given', $serviceName), 0, $previous); + } + + /** + * @param string $serviceName + * @param mixed $objectManager + * + * @return self + */ + public static function invalidObjectManager($serviceName, $objectManager) + { + return new self( + sprintf( + 'Invalid ObjectManager retrieved for service "%s", instance of "%s" found', + $serviceName, + is_object($objectManager) ? get_class($objectManager) : gettype($objectManager) + ) + ); + } + + /** + * @param string $serviceName + * @param mixed $cache + * + * @return self + */ + public static function invalidCache($serviceName, $cache) + { + return new self( + sprintf( + 'Invalid CacheInterface retrieved for service "%s", instance of "%s" found', + $serviceName, + is_object($cache) ? get_class($cache) : gettype($cache) + ) + ); + } + + /** + * @param string $driverClass + * + * @return self + */ + public static function invalidDriverClass($driverClass) + { + return new self( + sprintf('Unrecognized driver class "%s" given', $driverClass) + ); + } } diff --git a/src/ZfrRest/Factory/ModelPluginManagerFactory.php b/src/ZfrRest/Factory/ModelPluginManagerFactory.php index 9a0586d..4608d4b 100644 --- a/src/ZfrRest/Factory/ModelPluginManagerFactory.php +++ b/src/ZfrRest/Factory/ModelPluginManagerFactory.php @@ -36,10 +36,10 @@ class ModelPluginManagerFactory implements FactoryInterface */ public function createService(ServiceLocatorInterface $serviceLocator) { - $config = $serviceLocator->get('Config'); - $config = $config['zfr_rest']['models']; + /* @var $options \ZfrRest\Options\ModuleOptions */ + $options = $serviceLocator->get('ZfrRest\Options\ModuleOptions'); - $modelPluginManager = new ModelPluginManager(new Config($config)); + $modelPluginManager = new ModelPluginManager(new Config($options->getModels())); $modelPluginManager->setServiceLocator($serviceLocator); return $modelPluginManager; diff --git a/src/ZfrRest/Factory/ModuleOptionsFactory.php b/src/ZfrRest/Factory/ModuleOptionsFactory.php index 01c76da..0b7c7f0 100644 --- a/src/ZfrRest/Factory/ModuleOptionsFactory.php +++ b/src/ZfrRest/Factory/ModuleOptionsFactory.php @@ -36,6 +36,7 @@ class ModuleOptionsFactory implements FactoryInterface public function createService(ServiceLocatorInterface $serviceLocator) { $config = $serviceLocator->get('Config'); + return new ModuleOptions($config['zfr_rest']); } } diff --git a/src/ZfrRest/Factory/PaginatorHydratorFactory.php b/src/ZfrRest/Factory/PaginatorHydratorFactory.php index 43e011e..f529906 100644 --- a/src/ZfrRest/Factory/PaginatorHydratorFactory.php +++ b/src/ZfrRest/Factory/PaginatorHydratorFactory.php @@ -22,6 +22,7 @@ use Zend\ServiceManager\ServiceLocatorInterface; use Zend\Stdlib\Hydrator\HydratorPluginManager; use ZfrRest\Stdlib\Hydrator\PaginatorHydrator; +use ZfrRest\Factory\Exception\RuntimeException; /** * PaginatorHydratorFactory @@ -33,14 +34,15 @@ class PaginatorHydratorFactory implements FactoryInterface { /** * {@inheritDoc} + * + * @return PaginatorHydrator + * + * @throws RuntimeException */ public function createService(ServiceLocatorInterface $serviceLocator) { - if (!$serviceLocator instanceof HydratorPluginManager) { - throw new Exception\RuntimeException(sprintf( - 'A hydrator plugin manager was expected, but "%s" was given', - get_class($serviceLocator) - )); + if (! $serviceLocator instanceof HydratorPluginManager) { + throw RuntimeException::pluginManagerExpected($serviceLocator); } return new PaginatorHydrator($serviceLocator); diff --git a/src/ZfrRest/Factory/ResourceGraphRouteFactory.php b/src/ZfrRest/Factory/ResourceGraphRouteFactory.php index 88ad925..aacbc39 100644 --- a/src/ZfrRest/Factory/ResourceGraphRouteFactory.php +++ b/src/ZfrRest/Factory/ResourceGraphRouteFactory.php @@ -18,12 +18,17 @@ namespace ZfrRest\Factory; +use Zend\ServiceManager\AbstractPluginManager; +use Zend\ServiceManager\Exception\ServiceNotFoundException; use Zend\ServiceManager\FactoryInterface; use Zend\ServiceManager\MutableCreationOptionsInterface; use Zend\ServiceManager\ServiceLocatorInterface; use ZfrRest\Factory\Exception\RuntimeException; use ZfrRest\Mvc\Router\Http\ResourceGraphRoute; +/** + * Factory responsible of instantiating an {@see \ZfrRest\Mvc\Router\Http\ResourceGraphRoute} + */ class ResourceGraphRouteFactory implements FactoryInterface, MutableCreationOptionsInterface { /** @@ -50,23 +55,28 @@ public function setCreationOptions(array $creationOptions) /** * {@inheritDoc} + * + * @return ResourceGraphRoute + * + * @throws RuntimeException */ public function createService(ServiceLocatorInterface $serviceLocator) { - /** @var $parentLocator \Zend\ServiceManager\ServiceManager */ + if (! $serviceLocator instanceof AbstractPluginManager) { + throw RuntimeException::pluginManagerExpected($serviceLocator); + } + $parentLocator = $serviceLocator->getServiceLocator(); - if (!$parentLocator->has($this->creationOptions['resource'])) { - throw new RuntimeException(sprintf( - 'Resource "%s" cannot be found from service locator', - $this->creationOptions['resource'] - )); + try { + $resource = $parentLocator->get($this->creationOptions['resource']); + } catch (ServiceNotFoundException $exception) { + throw RuntimeException::missingResource($this->creationOptions['resource'], $exception); } - return new ResourceGraphRoute( - $parentLocator->get('ZfrRest\Resource\Metadata\MetadataFactory'), - $parentLocator->get($this->creationOptions['resource']), - $this->creationOptions['route'] - ); + /* @var $metadataFactory \Metadata\MetadataFactoryInterface */ + $metadataFactory = $parentLocator->get('ZfrRest\Resource\Metadata\MetadataFactory'); + + return new ResourceGraphRoute($metadataFactory, $resource, $this->creationOptions['route']); } } diff --git a/src/ZfrRest/Factory/ResourceMetadataCacheFactory.php b/src/ZfrRest/Factory/ResourceMetadataCacheFactory.php index 1545456..7132b91 100644 --- a/src/ZfrRest/Factory/ResourceMetadataCacheFactory.php +++ b/src/ZfrRest/Factory/ResourceMetadataCacheFactory.php @@ -21,6 +21,9 @@ use Zend\ServiceManager\FactoryInterface; use Zend\ServiceManager\ServiceLocatorInterface; +/** + * Factory responsible of instantiating a doctrine cache for metadata + */ class ResourceMetadataCacheFactory implements FactoryInterface { /** diff --git a/src/ZfrRest/Factory/ResourceMetadataFactoryFactory.php b/src/ZfrRest/Factory/ResourceMetadataFactoryFactory.php index c1ae2fa..7e26a5e 100644 --- a/src/ZfrRest/Factory/ResourceMetadataFactoryFactory.php +++ b/src/ZfrRest/Factory/ResourceMetadataFactoryFactory.php @@ -20,13 +20,16 @@ use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Annotations\AnnotationRegistry; +use Doctrine\Common\Persistence\ObjectManager; use Metadata\Cache\CacheInterface; use Metadata\Driver\DriverChain; use Metadata\Driver\FileLocator; use Metadata\MetadataFactory; +use Zend\ServiceManager\Exception\ServiceNotFoundException; use Zend\ServiceManager\FactoryInterface; use Zend\ServiceManager\ServiceLocatorInterface; use ZfrRest\Factory\Exception\RuntimeException; +use ZfrRest\Resource\Metadata\Driver\AnnotationDriver; use ZfrRest\Resource\Metadata\Driver\PhpDriver; use ZfrRest\Resource\Metadata\Driver\ResourceMetadataDriverInterface; @@ -47,55 +50,45 @@ public function createService(ServiceLocatorInterface $serviceLocator) $moduleOptions = $serviceLocator->get('ZfrRest\Options\ModuleOptions'); $resourceOptions = $moduleOptions->getResourceMetadata(); - $objectManager = $moduleOptions->getObjectManager(); - if (!$serviceLocator->has($objectManager)) { - throw new RuntimeException(sprintf( - 'The object manager key is not valid, %s given', - $objectManager - )); + try { + /* @var $objectManager \Doctrine\Common\Persistence\ObjectManager */ + $objectManager = $serviceLocator->get($moduleOptions->getObjectManager()); + } catch (ServiceNotFoundException $exception) { + throw RuntimeException::missingObjectManager($moduleOptions->getObjectManager(), $exception); } - $doctrineMetadataFactory = $serviceLocator->get($objectManager)->getMetadataFactory(); + if (! $objectManager instanceof ObjectManager) { + throw RuntimeException::invalidObjectManager($moduleOptions->getObjectManager(), $objectManager); + } + + $doctrineMetadataFactory = $objectManager->getMetadataFactory(); $driversOptions = $resourceOptions->getDrivers(); + /* @var $metadataDrivers ResourceMetadataDriverInterface[] */ $metadataDrivers = array(); // The annotation driver does not need to be added twice foreach ($driversOptions as $driverOptions) { - $class = $driverOptions['class']; - - if ($class === 'ZfrRest\Resource\Metadata\Driver\AnnotationDriver') { - // Add the path to the annotations - AnnotationRegistry::registerAutoloadNamespace( - 'ZfrRest\Resource\Annotation', - __DIR__ . '/../..' - ); - - $metadataDrivers[] = new $class(new AnnotationReader(), $doctrineMetadataFactory); - - break; + switch ($driverOptions['class']) { + case 'ZfrRest\Resource\Metadata\Driver\AnnotationDriver': + //AnnotationRegistry::registerAutoloadNamespace('ZfrRest\Resource\Annotation', __DIR__ . '/../..'); + $metadataDrivers[] = new AnnotationDriver(new AnnotationReader(), $doctrineMetadataFactory); + break; + case 'ZfrRest\Resource\Metadata\Driver\PhpDriver': + $metadataDrivers[] = new PhpDriver( + new FileLocator($driverOptions['paths']), + $doctrineMetadataFactory + ); + break; + default: + throw RuntimeException::invalidDriverClass($driverOptions['class']); } } - - // We need to handle both drivers differently, as the FileDriver needs all the paths to work properly - $filePaths = array(); - - foreach ($driversOptions as $driverOptions) { - $class = $driverOptions['class']; - - if ($class === 'ZfrRest\Resource\Metadata\Driver\PhpDriver') { - $filePaths = array_merge($filePaths, $driverOptions['paths']); - } - } - - if (!empty($filePaths)) { - $metadataDrivers[] = new PhpDriver(new FileLocator($filePaths), $doctrineMetadataFactory); - } - $resourceMetadataFactory = new MetadataFactory(new DriverChain($metadataDrivers)); // We need to inject the resource metadata factory into each driver to allow them to retrieve // metadata from one driver to another + // @todo this part should be removed foreach ($metadataDrivers as $metadataDriver) { if ($metadataDriver instanceof ResourceMetadataDriverInterface) { $metadataDriver->setResourceMetadataFactory($resourceMetadataFactory); @@ -109,6 +102,7 @@ public function createService(ServiceLocatorInterface $serviceLocator) $resourceMetadataFactory->setCache($cache); } + return $resourceMetadataFactory; } } diff --git a/src/ZfrRest/Factory/SelectModelListenerFactory.php b/src/ZfrRest/Factory/SelectModelListenerFactory.php index 926e22f..a917ec9 100644 --- a/src/ZfrRest/Factory/SelectModelListenerFactory.php +++ b/src/ZfrRest/Factory/SelectModelListenerFactory.php @@ -35,6 +35,9 @@ class SelectModelListenerFactory implements FactoryInterface */ public function createService(ServiceLocatorInterface $serviceLocator) { - return new SelectModelListener($serviceLocator->get('ZfrRest\View\Model\ModelPluginManager')); + /* @var $modelPluginManager \ZfrRest\View\Model\ModelPluginManager */ + $modelPluginManager = $serviceLocator->get('ZfrRest\View\Model\ModelPluginManager'); + + return new SelectModelListener($modelPluginManager); } } diff --git a/src/ZfrRest/Http/Exception/Client/BadRequestException.php b/src/ZfrRest/Http/Exception/Client/BadRequestException.php index 52529cf..c31e7a5 100644 --- a/src/ZfrRest/Http/Exception/Client/BadRequestException.php +++ b/src/ZfrRest/Http/Exception/Client/BadRequestException.php @@ -18,6 +18,7 @@ namespace ZfrRest\Http\Exception\Client; +use Zend\InputFilter\InputFilterInterface; use ZfrRest\Http\Exception\ClientException; /** @@ -42,4 +43,14 @@ public function __construct($message = '', $errors = '') { parent::__construct(400, $message, $errors); } + + /** + * @param InputFilterInterface $inputFilter + * + * @return self + */ + public static function invalidInput(InputFilterInterface $inputFilter) + { + return new self('Invalid data provided', $inputFilter->getMessages()); + } } diff --git a/src/ZfrRest/Http/Exception/Client/ConflictException.php b/src/ZfrRest/Http/Exception/Client/ConflictException.php index efaa895..655d4d8 100644 --- a/src/ZfrRest/Http/Exception/Client/ConflictException.php +++ b/src/ZfrRest/Http/Exception/Client/ConflictException.php @@ -31,7 +31,8 @@ class ConflictException extends ClientException /** * @var string */ - protected $message = 'The request could not be processed because of conflict in the request, such as an edit conflict'; + protected $message = + 'The request could not be processed because of conflict in the request, such as an edit conflict'; /** diff --git a/src/ZfrRest/Http/Exception/ClientException.php b/src/ZfrRest/Http/Exception/ClientException.php index 6a33ece..9343039 100644 --- a/src/ZfrRest/Http/Exception/ClientException.php +++ b/src/ZfrRest/Http/Exception/ClientException.php @@ -44,10 +44,9 @@ public function __construct($statusCode, $message = '', $errors = '') { // Client errors code are 4xx if ($statusCode < 400 || $statusCode > 499) { - throw new InvalidArgumentException(sprintf( - 'Status code for client errors must be between 400 and 499, %s given', - $statusCode - )); + throw new InvalidArgumentException( + sprintf('Status code for client errors must be between 400 and 499, %s given', $statusCode) + ); } parent::__construct($statusCode, $message, $errors); diff --git a/src/ZfrRest/Http/Exception/Server/InternalServerErrorException.php b/src/ZfrRest/Http/Exception/Server/InternalServerErrorException.php index b29941b..603018a 100644 --- a/src/ZfrRest/Http/Exception/Server/InternalServerErrorException.php +++ b/src/ZfrRest/Http/Exception/Server/InternalServerErrorException.php @@ -18,6 +18,7 @@ namespace ZfrRest\Http\Exception\Server; +use Exception; use ZfrRest\Http\Exception\ServerException; /** @@ -42,4 +43,50 @@ public function __construct($message = '', $errors = '') { parent::__construct(500, $message, $errors); } + + /** + * @return self + */ + public static function missingInputFilter() + { + return new self('No input filter class was given, although controller is configured to auto validate'); + } + + /** + * @param string $inputFilterName + * @param Exception|null $previous + * + * @return self + * + * @todo should handle also $previous exception + */ + public static function invalidInputFilter($inputFilterName, Exception $previous = null) + { + return new self( + sprintf('An invalid input filter class name was given when validating data ("%s" given)', $inputFilterName) + ); + } + + /** + * @return self + */ + public static function missingHydrator() + { + return new self('No hydrator was given, although controller is configured to auto hydrate'); + } + + /** + * @param string $hydratorName + * @param Exception|null $previous + * + * @return self + * + * @todo should handle also $previous exception + */ + public static function invalidHydrator($hydratorName, Exception $previous = null) + { + return new self( + sprintf('An invalid hydrator class name was given when hydrating data ("%s" given)', $hydratorName) + ); + } } diff --git a/src/ZfrRest/Http/Exception/Server/NotImplementedException.php b/src/ZfrRest/Http/Exception/Server/NotImplementedException.php index 18760f3..bd0e21a 100644 --- a/src/ZfrRest/Http/Exception/Server/NotImplementedException.php +++ b/src/ZfrRest/Http/Exception/Server/NotImplementedException.php @@ -31,8 +31,8 @@ class NotImplementedException extends ServerException /** * @var string */ - protected $message = 'The server either does not recognize the request method, or it lacks the ability to fulfill the request'; - + protected $message = + 'The server either does not recognize the request method, or it lacks the ability to fulfill the request'; /** * @param string $message diff --git a/src/ZfrRest/Http/Exception/Server/ServiceUnavailableException.php b/src/ZfrRest/Http/Exception/Server/ServiceUnavailableException.php index 22bf4c0..7570cb2 100644 --- a/src/ZfrRest/Http/Exception/Server/ServiceUnavailableException.php +++ b/src/ZfrRest/Http/Exception/Server/ServiceUnavailableException.php @@ -31,7 +31,8 @@ class ServiceUnavailableException extends ServerException /** * @var string */ - protected $message = 'The server is currently unavailable (because it is overloaded or down for maintenance). Please try again later'; + protected $message = + 'The server is currently unavailable (because it is overloaded or down for maintenance). Please try again later'; /** diff --git a/src/ZfrRest/Http/Exception/ServerException.php b/src/ZfrRest/Http/Exception/ServerException.php index b02dc1c..13ea7a4 100644 --- a/src/ZfrRest/Http/Exception/ServerException.php +++ b/src/ZfrRest/Http/Exception/ServerException.php @@ -44,10 +44,9 @@ public function __construct($statusCode, $message = '', $errors = '') { // Server errors code are 5xx if ($statusCode < 500 || $statusCode > 599) { - throw new InvalidArgumentException(sprintf( - 'Status code for server errors must be between 500 and 599, %s given', - $statusCode - )); + throw new InvalidArgumentException( + sprintf('Status code for server errors must be between 500 and 599, %s given', $statusCode) + ); } parent::__construct($statusCode, $message, $errors); diff --git a/src/ZfrRest/Module.php b/src/ZfrRest/Module.php index cf12b72..adb3f14 100644 --- a/src/ZfrRest/Module.php +++ b/src/ZfrRest/Module.php @@ -41,9 +41,10 @@ class Module implements /** * {@inheritDoc} */ - public function onBootstrap(EventInterface $e) + public function onBootstrap(EventInterface $event) { - $application = $e->getTarget(); + /* @var $application \Zend\Mvc\Application */ + $application = $event->getTarget(); $serviceManager = $application->getServiceManager(); $eventManager = $application->getEventManager(); diff --git a/src/ZfrRest/Mvc/Controller/AbstractRestfulController.php b/src/ZfrRest/Mvc/Controller/AbstractRestfulController.php index af94e4e..bd04447 100644 --- a/src/ZfrRest/Mvc/Controller/AbstractRestfulController.php +++ b/src/ZfrRest/Mvc/Controller/AbstractRestfulController.php @@ -27,11 +27,13 @@ use Zend\Stdlib\RequestInterface; use Zend\Stdlib\ResponseInterface; use ZfrRest\Http\Exception\Client; +use ZfrRest\Http\Exception\Client\BadRequestException; use ZfrRest\Http\Exception\Server; +use ZfrRest\Http\Exception\Server\InternalServerErrorException; use ZfrRest\Resource\ResourceInterface; /** - * Abstract RESTful controller. It is responsible for dispatching a HTTP request to a function, or throwing an + * Abstract REST-ful controller. It is responsible for dispatching a HTTP request to a function, or throwing an * exception if the method is not implemented. * * By default, AbstractRestfulController handles the "big four" methods (GET, DELETE, PUT and POST). You can add @@ -59,12 +61,12 @@ public function dispatch(RequestInterface $request, ResponseInterface $response /** * Execute the request. Try to match the HTTP verb to an action * - * @param MvcEvent $e + * @param MvcEvent $event * @return mixed * @throws Client\NotFoundException If the resource cannot be found * @throws Client\MethodNotAllowedException If the method to handle the request is not implemented */ - public function onDispatch(MvcEvent $e) + public function onDispatch(MvcEvent $event) { $method = strtolower($this->getRequest()->getMethod()); $handler = 'handle' . ucfirst($method) . 'Method'; @@ -74,7 +76,7 @@ public function onDispatch(MvcEvent $e) } /** @var \ZfrRest\Resource\ResourceInterface $resource */ - $resource = $e->getRouteMatch()->getParam('resource', null); + $resource = $event->getRouteMatch()->getParam('resource', null); // We should always have a resource, otherwise throw an 404 exception if (null === $resource) { @@ -83,7 +85,7 @@ public function onDispatch(MvcEvent $e) $return = $this->$handler($resource); - $e->setResult($return); + $event->setResult($return); return $return; } @@ -181,13 +183,13 @@ protected function handlePutMethod(ResourceInterface $resource) /** * Automatically create an InputFilter object, and validate data against it. * - * @param string $inputFilterClass + * @param string $inputFilterName * @param array $data * @throws Server\InternalServerErrorException If the input filter class is not valid * @throws Client\BadRequestException If input filter create validation errors * @return array */ - protected function validateData($inputFilterClass, array $data) + protected function validateData($inputFilterName, array $data) { /** @var $moduleOptions \ZfrRest\Options\ModuleOptions */ $moduleOptions = $this->serviceLocator->get('ZfrRest\Options\ModuleOptions'); @@ -197,26 +199,22 @@ protected function validateData($inputFilterClass, array $data) return $data; } - if (empty($inputFilterClass)) { - throw new Server\InternalServerErrorException(sprintf( - 'No input filter class was given, although controller is configured to auto validate' - )); + if (empty($inputFilterName)) { + throw InternalServerErrorException::missingInputFilter(); } + $inputFilterManager = $this->serviceLocator->get('InputFilterManager'); + try { - $inputFilterManager = $this->serviceLocator->get('InputFilterManager'); - $inputFilter = $inputFilterManager->get($inputFilterClass); - } catch (ServiceNotFoundException $e) { - throw new Server\InternalServerErrorException(sprintf( - 'An invalid input filter class name was given when validating data ("%s" given)', - (string) $inputFilterClass - )); + $inputFilter = $inputFilterManager->get($inputFilterName); + } catch (ServiceNotFoundException $exception) { + throw InternalServerErrorException::invalidInputFilter($inputFilterName, $exception); } /** @param \Zend\InputFilter\InputFilterInterface $inputFilter */ $inputFilter->setData($data); if (!$inputFilter->isValid()) { - throw new Client\BadRequestException('', $inputFilter->getMessages()); + throw BadRequestException::invalidInput($inputFilter); } // Return validated and filtered values @@ -227,13 +225,13 @@ protected function validateData($inputFilterClass, array $data) * Automatically create a Hydrator object, and hydrate object. If ZfrRest was configured to not hydrate * automatically, then this method only returns untouched data as array * - * @param string $hydratorClass + * @param string $hydratorName * @param array $data * @param ResourceInterface $resource * @throws Server\InternalServerErrorException * @return array|object */ - public function hydrateData($hydratorClass, array $data, ResourceInterface $resource) + public function hydrateData($hydratorName, array $data, ResourceInterface $resource) { /** @var $moduleOptions \ZfrRest\Options\ModuleOptions */ $moduleOptions = $this->serviceLocator->get('ZfrRest\Options\ModuleOptions'); @@ -243,20 +241,16 @@ public function hydrateData($hydratorClass, array $data, ResourceInterface $reso return $data; } - if (empty($hydratorClass)) { - throw new Server\InternalServerErrorException(sprintf( - 'No hydrator class was given, although controller is configured to auto hydrate' - )); + if (empty($hydratorName)) { + throw InternalServerErrorException::missingHydrator(); } + $hydratorManager = $this->serviceLocator->get('HydratorManager'); + try { - $hydratorManager = $this->serviceLocator->get('HydratorManager'); - $hydrator = $hydratorManager->get($hydratorClass); - } catch (ServiceNotFoundException $e) { - throw new Server\InternalServerErrorException(sprintf( - 'An invalid hydrator class name was given when hydrating data ("%s" given)', - (string) $hydratorClass - )); + $hydrator = $hydratorManager->get($hydratorName); + } catch (ServiceNotFoundException $exception) { + throw InternalServerErrorException::invalidHydrator($hydratorName, $exception); } /** @param \Zend\Stdlib\Hydrator\HydratorInterface $hydrator */ diff --git a/src/ZfrRest/Mvc/Exception/RuntimeException.php b/src/ZfrRest/Mvc/Exception/RuntimeException.php index ed0de50..088a604 100644 --- a/src/ZfrRest/Mvc/Exception/RuntimeException.php +++ b/src/ZfrRest/Mvc/Exception/RuntimeException.php @@ -18,6 +18,7 @@ namespace ZfrRest\Mvc\Exception; +use Doctrine\Common\Persistence\Mapping\ClassMetadata; use RuntimeException as BaseRuntimeException; use ZfrRest\Exception\ExceptionInterface; @@ -29,4 +30,33 @@ */ class RuntimeException extends BaseRuntimeException implements ExceptionInterface { + /** + * @param ClassMetadata $classMetadata + * + * @return self + */ + public static function missingCollectionMetadata(ClassMetadata $classMetadata) + { + return new self( + sprintf( + 'Collection metadata not found. Do you have a @Collection annotation for the resource "%s"?', + $classMetadata->getName() + ) + ); + } + + /** + * @param mixed $resource + * + * @return self + */ + public static function unsupportedResourceType($resource) + { + return new self( + sprintf( + 'Resource "%s" is not supported: either specify an ObjectRepository instance, or an entity class name', + is_object($resource) ? get_class($resource) : gettype($resource) + ) + ); + } } diff --git a/src/ZfrRest/Mvc/HttpExceptionListener.php b/src/ZfrRest/Mvc/HttpExceptionListener.php index 108cf1a..cef0a85 100644 --- a/src/ZfrRest/Mvc/HttpExceptionListener.php +++ b/src/ZfrRest/Mvc/HttpExceptionListener.php @@ -43,14 +43,14 @@ public function attach(EventManagerInterface $events) /** * Get the exception and optionally set status code and reason message * - * @param MvcEvent $e + * @param MvcEvent $event * @return void */ - public function onDispatchError(MvcEvent $e) + public function onDispatchError(MvcEvent $event) { /** @var $response HttpResponse */ - $response = $e->getResponse(); - $exception = $e->getParam('exception'); + $response = $event->getResponse(); + $exception = $event->getParam('exception'); // We just deal with our Http error codes here ! if (!$exception instanceof AbstractHttpException || !$response instanceof HttpResponse) { @@ -65,6 +65,6 @@ public function onDispatchError(MvcEvent $e) 'errors' => $exception->getErrors() ); - $e->setResult(array_filter($data)); + $event->setResult(array_filter($data)); } } diff --git a/src/ZfrRest/Mvc/HttpMethodOverrideListener.php b/src/ZfrRest/Mvc/HttpMethodOverrideListener.php index 32df7ca..b18b3a3 100644 --- a/src/ZfrRest/Mvc/HttpMethodOverrideListener.php +++ b/src/ZfrRest/Mvc/HttpMethodOverrideListener.php @@ -46,12 +46,12 @@ public function attach(EventManagerInterface $events) /** * Check if the X-HTTP-Method-Override exist in the request, and if so, change the method * - * @param MvcEvent $e + * @param MvcEvent $event * @return void */ - public function overrideHttpMethod(MvcEvent $e) + public function overrideHttpMethod(MvcEvent $event) { - $request = $e->getRequest(); + $request = $event->getRequest(); if (!$request instanceof HttpRequest) { return; diff --git a/src/ZfrRest/Mvc/Router/Http/ResourceGraphRoute.php b/src/ZfrRest/Mvc/Router/Http/ResourceGraphRoute.php index bfad6d2..69dd8db 100644 --- a/src/ZfrRest/Mvc/Router/Http/ResourceGraphRoute.php +++ b/src/ZfrRest/Mvc/Router/Http/ResourceGraphRoute.php @@ -22,11 +22,12 @@ use Doctrine\Common\Collections\Selectable; use Doctrine\Common\Persistence\ObjectRepository; use DoctrineModule\Paginator\Adapter\Selectable as SelectableAdapter; -use Metadata\MetadataFactory; +use Metadata\MetadataFactoryInterface; use Zend\Mvc\Router\Http\RouteInterface; use Zend\Mvc\Router\Http\RouteMatch; use Zend\Stdlib\RequestInterface as Request; use ZfrRest\Mvc\Exception; +use ZfrRest\Mvc\Exception\RuntimeException; use ZfrRest\Paginator\ResourcePaginator; use ZfrRest\Resource\Resource; use ZfrRest\Resource\ResourceInterface; @@ -39,7 +40,7 @@ class ResourceGraphRoute implements RouteInterface { /** - * @var MetadataFactory + * @var MetadataFactoryInterface */ protected $metadataFactory; @@ -64,11 +65,11 @@ class ResourceGraphRoute implements RouteInterface /** - * @param MetadataFactory $metadataFactory - * @param mixed $resource - * @param string $route + * @param MetadataFactoryInterface $metadataFactory + * @param mixed $resource + * @param string $route */ - public function __construct(MetadataFactory $metadataFactory, $resource, $route) + public function __construct(MetadataFactoryInterface $metadataFactory, $resource, $route) { $this->metadataFactory = $metadataFactory; $this->route = (string) $route; @@ -199,11 +200,12 @@ protected function matchAssociation(ResourceInterface $resource, $path) return null; } - $refl = $classMetadata->getReflectionClass(); - $reflProperty = $refl->getProperty($associationName); - $reflProperty->setAccessible(true); + $reflectionClass = $classMetadata->getReflectionClass(); + $reflectionProperty = $reflectionClass->getProperty($associationName); - $data = $reflProperty->getValue($resource->getData()); + $reflectionProperty->setAccessible(true); + + $data = $reflectionProperty->getValue($resource->getData()); $resourceMetadata = $resourceMetadata->getAssociationMetadata($associationName); $resource = new Resource($data, $resourceMetadata); @@ -241,7 +243,7 @@ protected function buildRouteMatch(ResourceInterface $resource, $path) } } - // @TODO: for now, collection is always wrapped around a ResourcePaginator, but the goal is to make this configurable + // @TODO: for now, collection is always wrapped around a ResourcePaginator, should instead be configurable $data = new ResourcePaginator($resourceMetadata, new SelectableAdapter($data, $criteria)); $resource = new Resource($data, $resourceMetadata); @@ -250,10 +252,7 @@ protected function buildRouteMatch(ResourceInterface $resource, $path) // If returned $data is a collection, then we use the controller specified in Collection mapping if ($resource->isCollection()) { if (null === $collectionMetadata) { - throw new Exception\RuntimeException(sprintf( - 'Collection metadata is not found. Do you have a @Collection annotation or PHP config for the resource "%s"?', - $classMetadata->getName() - )); + throw Exception\RuntimeException::missingCollectionMetadata($classMetadata); } $controllerName = $collectionMetadata->getControllerName(); @@ -261,10 +260,13 @@ protected function buildRouteMatch(ResourceInterface $resource, $path) $controllerName = $resourceMetadata->getControllerName(); } - return new RouteMatch(array( - 'resource' => $resource, - 'controller' => $controllerName - ), strlen($path)); + return new RouteMatch( + array( + 'resource' => $resource, + 'controller' => $controllerName + ), + strlen($path) + ); } /** @@ -277,9 +279,7 @@ protected function buildRouteMatch(ResourceInterface $resource, $path) */ protected function buildErrorRouteMatch(ResourceInterface $resource, $path) { - return new RouteMatch(array( - 'controller' => $resource->getMetadata()->getControllerName() - ), strlen($path)); + return new RouteMatch(array('controller' => $resource->getMetadata()->getControllerName()), strlen($path)); } /** @@ -306,11 +306,7 @@ private function initializeResource() } elseif (is_string($resource)) { $metadata = $this->metadataFactory->getMetadataForClass($resource); } else { - throw new Exception\RuntimeException(sprintf( - '%s is trying to initialize a resource, but this resource is not supported ("%s" given). Either ' . - 'specify an ObjectRepository instance, or an entity class name', - get_class($resource) - )); + throw RuntimeException::unsupportedResourceType($resource); } $this->resource = new Resource($resource, $metadata->getOutsideClassMetadata()); diff --git a/src/ZfrRest/Mvc/View/Http/CreateResourcePayloadListener.php b/src/ZfrRest/Mvc/View/Http/CreateResourcePayloadListener.php index 958d9e9..1bbf789 100644 --- a/src/ZfrRest/Mvc/View/Http/CreateResourcePayloadListener.php +++ b/src/ZfrRest/Mvc/View/Http/CreateResourcePayloadListener.php @@ -53,33 +53,42 @@ public function __construct(HydratorPluginManager $hydratorPluginManager) public function attach(EventManagerInterface $events) { $sharedManager = $events->getSharedManager(); - $sharedManager->attach('Zend\Stdlib\DispatchableInterface', MvcEvent::EVENT_DISPATCH, array($this, 'createPayload'), -40); + + $sharedManager->attach( + 'Zend\Stdlib\DispatchableInterface', + MvcEvent::EVENT_DISPATCH, + array($this, 'createPayload'), + -40 + ); } /** * The logic is as follow: extract the resource metadata, use the bound hydrator to extract data, and set the * data as new result * - * @param MvcEvent $e + * @param MvcEvent $event * @return void */ - public function createPayload(MvcEvent $e) + public function createPayload(MvcEvent $event) { - $result = $e->getResult(); + $result = $event->getResult(); + if ($result instanceof ModelInterface || $result instanceof ResponseInterface || empty($result)) { return; } /** @var \ZfrRest\Resource\ResourceInterface $resource */ - $resource = $e->getRouteMatch()->getParam('resource'); + $resource = $event->getRouteMatch()->getParam('resource'); $resourceMetadata = $resource->getMetadata(); - if (is_array($result) || $result instanceof Traversable) { - $hydrator = $this->hydratorPluginManager->get($resourceMetadata->getCollectionMetadata()->getHydratorName()); + if ($result instanceof Traversable || is_array($result)) { + $hydratorName = $resourceMetadata->getCollectionMetadata()->getHydratorName(); } else { - $hydrator = $this->hydratorPluginManager->get($resourceMetadata->getHydratorName()); + $hydratorName = $resourceMetadata->getHydratorName(); } - $e->setResult($hydrator->extract($result)); + $hydrator = $this->hydratorPluginManager->get($hydratorName); + + $event->setResult($hydrator->extract($result)); } } diff --git a/src/ZfrRest/Mvc/View/Http/SelectModelListener.php b/src/ZfrRest/Mvc/View/Http/SelectModelListener.php index 855b52d..3289f43 100644 --- a/src/ZfrRest/Mvc/View/Http/SelectModelListener.php +++ b/src/ZfrRest/Mvc/View/Http/SelectModelListener.php @@ -60,30 +60,34 @@ public function attach(EventManagerInterface $events) $sharedManager = $events->getSharedManager(); $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, array($this, 'injectErrorModel'), 80); - $sharedManager->attach('Zend\Stdlib\DispatchableInterface', MvcEvent::EVENT_DISPATCH, array($this, 'selectModel'), -60); + $sharedManager->attach( + 'Zend\Stdlib\DispatchableInterface', + MvcEvent::EVENT_DISPATCH, + array($this, 'selectModel'), + -60 + ); } /** * Select the correct ModelInterface instance by matching the values of the Accept header to a ModelInterface * - * @param MvcEvent $e + * @param MvcEvent $event * @return void */ - public function selectModel(MvcEvent $e) + public function selectModel(MvcEvent $event) { - $result = $e->getResult(); + $result = $event->getResult(); // If a view model was already set, or if the application errored with no produced result, no // view model replacement should happen - if ( - $result instanceof ModelInterface + if ($result instanceof ModelInterface || $result instanceof ResponseInterface - || (!isset($result) && $e->getError()) + || (!isset($result) && $event->getError()) ) { return; } - $request = $e->getRequest(); + $request = $event->getRequest(); if (!$request instanceof HttpRequest) { return; } @@ -95,7 +99,7 @@ public function selectModel(MvcEvent $e) $model->setVariables($result); } - $e->setResult($model); + $event->setResult($model); } /** @@ -106,14 +110,14 @@ public function selectModel(MvcEvent $e) * Otherwise (if we have a JsonModel or FeedModel or anything else...) we just set the view model and stop * propagation so that the response only contains the error message and status code * - * @param MvcEvent $e + * @param MvcEvent $event * @return void */ - public function injectErrorModel(MvcEvent $e) + public function injectErrorModel(MvcEvent $event) { - $this->selectModel($e); + $this->selectModel($event); - $result = $e->getResult(); + $result = $event->getResult(); if (!$result instanceof ModelInterface) { return; } @@ -125,8 +129,8 @@ public function injectErrorModel(MvcEvent $e) } // Otherwise, we stop propagation and set the view model - $e->setViewModel($result); - $e->stopPropagation(); + $event->setViewModel($result); + $event->stopPropagation(); } /** diff --git a/src/ZfrRest/Options/ModuleOptions.php b/src/ZfrRest/Options/ModuleOptions.php index 0602b5d..e490480 100644 --- a/src/ZfrRest/Options/ModuleOptions.php +++ b/src/ZfrRest/Options/ModuleOptions.php @@ -28,11 +28,6 @@ */ class ModuleOptions extends AbstractOptions { - /** - * {@inheritDoc} - */ - protected $__strictMode__ = false; - /** * Key of the object manager fetched from the service locator * @@ -61,8 +56,23 @@ class ModuleOptions extends AbstractOptions */ protected $resourceMetadataOptions; + /** + * Plugin manager configuration for the content decoders + * + * @var array + */ + protected $decoders = array(); + + /** + * Plugin manager configuration for the view models + * + * @var array + */ + protected $models = array(); + /** * @param string $objectManager + * * @return void */ public function setObjectManager($objectManager) @@ -80,6 +90,7 @@ public function getObjectManager() /** * @param array $options + * * @return void */ public function setListeners(array $options) @@ -97,6 +108,7 @@ public function getListeners() /** * @param array $options + * * @return void */ public function setControllerBehaviours(array $options) @@ -114,6 +126,7 @@ public function getControllerBehaviours() /** * @param array $options + * * @return void */ public function setResourceMetadata(array $options) @@ -128,4 +141,40 @@ public function getResourceMetadata() { return $this->resourceMetadataOptions; } + + /** + * @param array $decoders + * + * @return void + */ + public function setDecoders(array $decoders) + { + $this->decoders = $decoders; + } + + /** + * @return array + */ + public function getDecoders() + { + return $this->decoders; + } + + /** + * @param array $models + * + * @return void + */ + public function setModels(array $models) + { + $this->models = $models; + } + + /** + * @return array + */ + public function getModels() + { + return $this->models; + } } diff --git a/src/ZfrRest/Options/ResourceMetadataOptions.php b/src/ZfrRest/Options/ResourceMetadataOptions.php index f2b828a..5aff50b 100644 --- a/src/ZfrRest/Options/ResourceMetadataOptions.php +++ b/src/ZfrRest/Options/ResourceMetadataOptions.php @@ -52,14 +52,7 @@ class ResourceMetadataOptions extends AbstractOptions */ public function setCache($cache) { - if (!is_subclass_of($cache, 'Doctrine\Common\Cache\Cache')) { - throw new Exception\RuntimeException(sprintf( - 'Cache must implement Doctrine\Common\Cache\Cache, %s given', - $cache - )); - } - - $this->cache = $cache; + $this->cache = (string) $cache; } /** @@ -81,15 +74,6 @@ public function getCache() */ public function setDrivers(array $drivers) { - foreach ($drivers as $driver) { - if (!is_subclass_of($driver['class'], 'Metadata\Driver\DriverInterface')) { - throw new Exception\RuntimeException(sprintf( - 'Driver class should implements Metadata\Driver\DriverInterface, %s given', - $driver['class'] - )); - } - } - $this->drivers = $drivers; } diff --git a/src/ZfrRest/Resource/Metadata/Driver/AnnotationDriver.php b/src/ZfrRest/Resource/Metadata/Driver/AnnotationDriver.php index 42fa827..e64da11 100644 --- a/src/ZfrRest/Resource/Metadata/Driver/AnnotationDriver.php +++ b/src/ZfrRest/Resource/Metadata/Driver/AnnotationDriver.php @@ -21,11 +21,13 @@ use ReflectionClass; use Doctrine\Common\Annotations\Reader as AnnotationReader; use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory as DoctrineMetadataFactory; -use Metadata\ClassMetadata; use Metadata\Driver\DriverInterface; use Metadata\MetadataFactoryInterface as ResourceMetadataFactory; use Metadata\PropertyMetadata; use ZfrRest\Resource\Metadata\Annotation; +use ZfrRest\Resource\Metadata\Annotation\AnnotationInterface; +use ZfrRest\Resource\Metadata\Annotation\Resource; +use ZfrRest\Resource\Metadata\Annotation\Collection; use ZfrRest\Resource\Metadata\CollectionResourceMetadata; use ZfrRest\Resource\Metadata\ResourceMetadata; @@ -102,7 +104,10 @@ public function loadMetadataForClass(ReflectionClass $class) // We first load the metadata for the entity, and we then loop through the annotations defined // at the association level so that the user can override some properties - $resourceAssociationMetadata = $this->resourceMetadataFactory->getMetadataForClass($targetClass)->getRootClassMetadata(); + $resourceAssociationMetadata = $this + ->resourceMetadataFactory + ->getMetadataForClass($targetClass) + ->getRootClassMetadata(); $this->processMetadata($resourceAssociationMetadata, $propertyAnnotations); $resourceMetadata->associations[$associationName] = $resourceAssociationMetadata; @@ -116,53 +121,74 @@ public function loadMetadataForClass(ReflectionClass $class) } /** - * @param ClassMetadata $metadata - * @param Annotation\AnnotationInterface[] $annotations + * @param ResourceMetadata $metadata + * @param AnnotationInterface[] $annotations */ - private function processMetadata(ClassMetadata $metadata, array $annotations) + private function processMetadata(ResourceMetadata $metadata, array $annotations) { foreach ($annotations as $annotation) { - if (!($annotation instanceof Annotation\AnnotationInterface)) { + if (!($annotation instanceof AnnotationInterface)) { continue; } // Resource annotation - if ($annotation instanceof Annotation\Resource) { - $values = $annotation->getValue(); - - foreach ($values as $key => $value) { - // Ignore null values in order to make cascading work as expected - if (null === $value) { - continue; - } - - $propertyMetadata = new PropertyMetadata($metadata, $key); - $propertyMetadata->setValue($metadata, $value); - - $metadata->addPropertyMetadata($propertyMetadata); - } + if ($annotation instanceof Resource) { + $this->processResourceMetadata($metadata, $annotation); } // Collection annotation - if ($annotation instanceof Annotation\Collection) { - $values = $annotation->getValue(); - $collectionMetadata = new CollectionResourceMetadata($metadata->getClassName()); + if ($annotation instanceof Collection) { + $this->processCollectionMetadata($metadata, $annotation); + } + } + } - foreach ($values as $key => $value) { - $propertyMetadata = new PropertyMetadata($collectionMetadata, $key); + /** + * @param ResourceMetadata $metadata + * @param Resource $annotation + */ + private function processResourceMetadata(ResourceMetadata $metadata, Resource $annotation) + { + $values = $annotation->getValue(); - // If the value is null, then we reuse the value defined at "resource-level" - if (null === $value && isset($metadata->propertyMetadata[$key])) { - $propertyMetadata->setValue($collectionMetadata, $metadata->propertyMetadata[$key]->getValue($metadata)); - } else { - $propertyMetadata->setValue($collectionMetadata, $value); - } + foreach ($values as $key => $value) { + // Ignore null values in order to make cascading work as expected + if (null === $value) { + continue; + } - $collectionMetadata->addPropertyMetadata($propertyMetadata); - } + $propertyMetadata = new PropertyMetadata($metadata, $key); + $propertyMetadata->setValue($metadata, $value); + + $metadata->addPropertyMetadata($propertyMetadata); + } + } - $metadata->collectionMetadata = $collectionMetadata; + /** + * @param ResourceMetadata $metadata + * @param Collection $annotation + */ + private function processCollectionMetadata(ResourceMetadata $metadata, Collection $annotation) + { + $values = $annotation->getValue(); + $collectionMetadata = new CollectionResourceMetadata($metadata->getClassName()); + + foreach ($values as $key => $value) { + $propertyMetadata = new PropertyMetadata($collectionMetadata, $key); + + // If the value is null, then we reuse the value defined at "resource-level" + if (null === $value && isset($metadata->propertyMetadata[$key])) { + $propertyMetadata->setValue( + $collectionMetadata, + $metadata->propertyMetadata[$key]->getValue($metadata) + ); + } else { + $propertyMetadata->setValue($collectionMetadata, $value); } + + $collectionMetadata->addPropertyMetadata($propertyMetadata); } + + $metadata->collectionMetadata = $collectionMetadata; } } diff --git a/src/ZfrRest/Resource/Metadata/Driver/PhpDriver.php b/src/ZfrRest/Resource/Metadata/Driver/PhpDriver.php index f09a9bf..30232c8 100644 --- a/src/ZfrRest/Resource/Metadata/Driver/PhpDriver.php +++ b/src/ZfrRest/Resource/Metadata/Driver/PhpDriver.php @@ -84,7 +84,10 @@ protected function loadMetadataFromFile(ReflectionClass $class, $file) // We first load the metadata for the entity, and we then loop through the annotations defined // at the association level so that the user can override some properties - $resourceAssociationMetadata = $this->resourceMetadataFactory->getMetadataForClass($targetClass)->getRootClassMetadata(); + $resourceAssociationMetadata = $this + ->resourceMetadataFactory + ->getMetadataForClass($targetClass) + ->getRootClassMetadata(); $this->processMetadata($resourceAssociationMetadata, $associationConfig); $resourceMetadata->associations[$associationName] = $resourceAssociationMetadata; @@ -118,13 +121,13 @@ private function processMetadata(ClassMetadata $metadata, array $data) // Resource metadata if ($key === 'resource') { - foreach ($values as $key => $value) { + foreach ($values as $name => $value) { // Ignore null values in order to make cascading work as expected if (null === $value) { continue; } - $propertyMetadata = new PropertyMetadata($metadata, $key); + $propertyMetadata = new PropertyMetadata($metadata, $name); $propertyMetadata->setValue($metadata, $value); $metadata->addPropertyMetadata($propertyMetadata); @@ -135,12 +138,15 @@ private function processMetadata(ClassMetadata $metadata, array $data) if ($key === 'collection') { $collectionMetadata = new CollectionResourceMetadata($metadata->getClassName()); - foreach ($values as $key => $value) { - $propertyMetadata = new PropertyMetadata($collectionMetadata, $key); + foreach ($values as $name => $value) { + $propertyMetadata = new PropertyMetadata($collectionMetadata, $name); // If the value is null, then we reuse the value defined at "resource-level" - if (null === $value && isset($metadata->propertyMetadata[$key])) { - $propertyMetadata->setValue($collectionMetadata, $metadata->propertyMetadata[$key]->getValue($metadata)); + if (null === $value && isset($metadata->propertyMetadata[$name])) { + $propertyMetadata->setValue( + $collectionMetadata, + $metadata->propertyMetadata[$name]->getValue($metadata) + ); } else { $propertyMetadata->setValue($collectionMetadata, $value); } diff --git a/src/ZfrRest/Resource/Metadata/Driver/ResourceMetadataDriverInterface.php b/src/ZfrRest/Resource/Metadata/Driver/ResourceMetadataDriverInterface.php index 41eb9bd..25cd689 100644 --- a/src/ZfrRest/Resource/Metadata/Driver/ResourceMetadataDriverInterface.php +++ b/src/ZfrRest/Resource/Metadata/Driver/ResourceMetadataDriverInterface.php @@ -30,5 +30,10 @@ */ interface ResourceMetadataDriverInterface { + /** + * @param MetadataFactoryInterface $metadataFactory + * + * @return void + */ public function setResourceMetadataFactory(MetadataFactoryInterface $metadataFactory); } diff --git a/src/ZfrRest/Resource/Metadata/ResourceMetadata.php b/src/ZfrRest/Resource/Metadata/ResourceMetadata.php index a1e31cd..2a16bca 100644 --- a/src/ZfrRest/Resource/Metadata/ResourceMetadata.php +++ b/src/ZfrRest/Resource/Metadata/ResourceMetadata.php @@ -67,13 +67,6 @@ class ResourceMetadata extends ClassMetadata implements ResourceMetadataInterfac */ public function createResource() { - if (!class_exists($this->name)) { - throw new Exception\RuntimeException(sprintf( - 'Impossible to create a new resource because the class "%s" does not exist', - $this->name - )); - } - $args = func_get_args(); if (empty($args)) { diff --git a/src/ZfrRest/Resource/Resource.php b/src/ZfrRest/Resource/Resource.php index 02fe109..17c68c8 100644 --- a/src/ZfrRest/Resource/Resource.php +++ b/src/ZfrRest/Resource/Resource.php @@ -49,8 +49,9 @@ public function __construct($data, ResourceMetadataInterface $metadata) $this->data = $data; $this->metadata = $metadata; - $refl = $metadata->getClassMetadata()->getReflectionClass(); - if (!$this->isCollection() && !$refl->isInstance($data)) { + $reflectionClass = $metadata->getClassMetadata()->getReflectionClass(); + + if (!$this->isCollection() && ! $reflectionClass->isInstance($data)) { throw InvalidResourceException::invalidResourceProvided($data, $metadata); } } diff --git a/src/ZfrRest/Serializer/DecoderPluginManager.php b/src/ZfrRest/Serializer/DecoderPluginManager.php index 1f789aa..7641980 100644 --- a/src/ZfrRest/Serializer/DecoderPluginManager.php +++ b/src/ZfrRest/Serializer/DecoderPluginManager.php @@ -20,6 +20,7 @@ use Zend\ServiceManager\AbstractPluginManager; use Symfony\Component\Serializer\Encoder\DecoderInterface; +use ZfrRest\Serializer\Exception\RuntimeException; /** * DecoderPluginManager @@ -52,14 +53,9 @@ class DecoderPluginManager extends AbstractPluginManager */ public function validatePlugin($plugin) { - if ($plugin instanceof DecoderInterface) { - return; + if (! $plugin instanceof DecoderInterface) { + throw RuntimeException::invalidDecoderPlugin($plugin); } - - throw new Exception\RuntimeException(sprintf( - 'Plugin of type %s is invalid; must implement Symfony\Component\Serializer\Encoder\DecoderInterface', - (is_object($plugin) ? get_class($plugin) : gettype($plugin)) - )); } /** diff --git a/src/ZfrRest/Serializer/Exception/RuntimeException.php b/src/ZfrRest/Serializer/Exception/RuntimeException.php index 2ae7ddf..5d3ffdb 100644 --- a/src/ZfrRest/Serializer/Exception/RuntimeException.php +++ b/src/ZfrRest/Serializer/Exception/RuntimeException.php @@ -29,4 +29,18 @@ */ class RuntimeException extends BaseRuntimeException implements ExceptionInterface { + /** + * @param mixed $plugin + * + * @return self + */ + public static function invalidDecoderPlugin($plugin) + { + return new self( + sprintf( + 'Plugin of type %s is invalid; must implement Symfony\Component\Serializer\Encoder\DecoderInterface', + (is_object($plugin) ? get_class($plugin) : gettype($plugin)) + ) + ); + } } diff --git a/src/ZfrRest/View/Exception/RuntimeException.php b/src/ZfrRest/View/Exception/RuntimeException.php index f03db25..9caa8ab 100644 --- a/src/ZfrRest/View/Exception/RuntimeException.php +++ b/src/ZfrRest/View/Exception/RuntimeException.php @@ -29,4 +29,18 @@ */ class RuntimeException extends BaseRuntimeException implements ExceptionInterface { + /** + * @param mixed $plugin + * + * @return self + */ + public static function invalidViewModelPlugin($plugin) + { + return new self( + sprintf( + 'Plugin of type %s is invalid; must implement Zend\View\ViewModel', + (is_object($plugin) ? get_class($plugin) : gettype($plugin)) + ) + ); + } } diff --git a/src/ZfrRest/View/Model/ModelPluginManager.php b/src/ZfrRest/View/Model/ModelPluginManager.php index 4c36266..8be73ef 100644 --- a/src/ZfrRest/View/Model/ModelPluginManager.php +++ b/src/ZfrRest/View/Model/ModelPluginManager.php @@ -20,7 +20,7 @@ use Zend\ServiceManager\AbstractPluginManager; use Zend\View\Model\ModelInterface; -use ZfrRest\View\Exception; +use ZfrRest\View\Exception\RuntimeException; /** * ModelPluginManager. It allows to retrieve a view model from a format. @@ -47,14 +47,9 @@ class ModelPluginManager extends AbstractPluginManager */ public function validatePlugin($plugin) { - if ($plugin instanceof ModelInterface) { - return; + if (! $plugin instanceof ModelInterface) { + throw RuntimeException::invalidViewModelPlugin($plugin); } - - throw new Exception\RuntimeException(sprintf( - 'Plugin of type %s is invalid; must implement Zend\View\ViewModel', - (is_object($plugin) ? get_class($plugin) : gettype($plugin)) - )); } /** diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php index e771b8d..f3c7931 100644 --- a/tests/Bootstrap.php +++ b/tests/Bootstrap.php @@ -16,18 +16,35 @@ * and is licensed under the MIT license. */ -if ( - !($loader = @include __DIR__ . '/../vendor/autoload.php') - && !($loader = @include __DIR__ . '/../../../autoload.php') -) { - throw new RuntimeException('vendor/autoload.php could not be found. Did you run `php composer.phar install`?'); +use ZfrRestTest\Util\ServiceManagerFactory; + +ini_set('error_reporting', E_ALL); + +$files = array(__DIR__ . '/../vendor/autoload.php', __DIR__ . '/../../../autoload.php'); + +foreach ($files as $file) { + if (file_exists($file)) { + $loader = require $file; + + break; + } +} + +if (! isset($loader)) { + throw new RuntimeException('vendor/autoload.php could not be found. Did you install via composer?'); } -/* @var $loader \Composer\Autoload\ClassLoader */ $loader->add('ZfrRestTest\\', __DIR__); -if (!$config = @include __DIR__ . '/TestConfiguration.php') { - $config = require __DIR__ . '/TestConfiguration.php.dist'; +$configFiles = array(__DIR__ . '/TestConfiguration.php', __DIR__ . '/TestConfiguration.php.dist'); + +foreach ($configFiles as $configFile) { + if (file_exists($configFile)) { + $config = require $configFile; + + break; + } } -\ZfrRestTest\Util\ServiceManagerFactory::setConfig($config); +ServiceManagerFactory::setApplicationConfig($config); +unset($file, $file, $loader, $configFiles, $configFile, $config); diff --git a/tests/ZfrRestTest/Asset/Annotation/Tweet.php b/tests/ZfrRestTest/Asset/Annotation/Tweet.php index e14fe1f..68a2cbe 100644 --- a/tests/ZfrRestTest/Asset/Annotation/Tweet.php +++ b/tests/ZfrRestTest/Asset/Annotation/Tweet.php @@ -73,16 +73,16 @@ public function getId() } /** - * @param \Application\Entity\User $user + * @param User|null $user * @return void */ - public function setUser($user) + public function setUser(User $user = null) { $this->user = $user; } /** - * @return \Application\Entity\User + * @return User|null */ public function getUser() { diff --git a/tests/ZfrRestTest/Http/Exception/ClientExceptionTest.php b/tests/ZfrRestTest/Http/Exception/ClientExceptionTest.php index 126e547..4f1df1e 100644 --- a/tests/ZfrRestTest/Http/Exception/ClientExceptionTest.php +++ b/tests/ZfrRestTest/Http/Exception/ClientExceptionTest.php @@ -23,26 +23,30 @@ class ClientExceptionTest extends TestCase { - public function testThrowExceptionIfStatusCodeIsNotInRange() + public function testThrowExceptionIfStatusCodeIsOverRange() { $this->setExpectedException( 'InvalidArgumentException', 'Status code for client errors must be between 400 and 499, 500 given' ); - $exception = new Exception\ClientException(500); + new Exception\ClientException(500); + } + public function testThrowExceptionIfStatusCodeIsBelowRange() + { $this->setExpectedException( 'InvalidArgumentException', 'Status code for client errors must be between 400 and 499, 399 given' ); - $exception = new Exception\ClientException(399); + new Exception\ClientException(399); } public function testAlwaysContainDefaultMessage() { $exception = new Exception\ClientException(401); + $this->assertContains('A client error occurred', $exception->getMessage()); } } diff --git a/tests/ZfrRestTest/Http/Exception/ServerExceptionTest.php b/tests/ZfrRestTest/Http/Exception/ServerExceptionTest.php index fc7ffee..10a764a 100644 --- a/tests/ZfrRestTest/Http/Exception/ServerExceptionTest.php +++ b/tests/ZfrRestTest/Http/Exception/ServerExceptionTest.php @@ -23,21 +23,24 @@ class ServerExceptionTest extends TestCase { - public function testThrowExceptionIfStatusCodeIsNotInRange() + public function testThrowExceptionIfStatusCodeIsOverRange() { $this->setExpectedException( 'InvalidArgumentException', 'Status code for server errors must be between 500 and 599, 600 given' ); - $exception = new Exception\ServerException(600); + new Exception\ServerException(600); + } + public function testThrowExceptionIfStatusCodeIsBelowRange() + { $this->setExpectedException( 'InvalidArgumentException', 'Status code for server errors must be between 500 and 599, 499 given' ); - $exception = new Exception\ServerException(499); + new Exception\ServerException(499); } public function testAlwaysContainDefaultMessage() diff --git a/tests/ZfrRestTest/Mvc/Asset/DummyController.php b/tests/ZfrRestTest/Mvc/Asset/DummyController.php index c07c841..c88028a 100644 --- a/tests/ZfrRestTest/Mvc/Asset/DummyController.php +++ b/tests/ZfrRestTest/Mvc/Asset/DummyController.php @@ -31,9 +31,7 @@ class DummyController extends AbstractRestfulController */ public function get($resource) { - return new ViewModel(array( - 'resource' => $resource - )); + return new ViewModel(array('resource' => $resource)); } /** @@ -45,8 +43,6 @@ public function get($resource) */ public function post($data, ResourceMetadataInterface $metadata, ResourceInterface $resource) { - return new ViewModel(array( - 'resource' => $resource - )); + return new ViewModel(array('resource' => $resource)); } } diff --git a/tests/ZfrRestTest/Mvc/Controller/AbstractRestfulControllerFunctionalTest.php b/tests/ZfrRestTest/Mvc/Controller/AbstractRestfulControllerFunctionalTest.php index 9712de6..dc98174 100644 --- a/tests/ZfrRestTest/Mvc/Controller/AbstractRestfulControllerFunctionalTest.php +++ b/tests/ZfrRestTest/Mvc/Controller/AbstractRestfulControllerFunctionalTest.php @@ -19,11 +19,7 @@ namespace ZfrRestTest\Mvc\Controller; use PHPUnit_Framework_TestCase as TestCase; -use Zend\Console\Request as ConsoleRequest; -use Zend\EventManager\EventManager; use Zend\Http\Request as HttpRequest; -use Zend\Mvc\MvcEvent; -use ZfrRestTest\Mvc\Asset\DummyController; use ZfrRestTest\Util\ServiceManagerFactory; /** diff --git a/tests/ZfrRestTest/Mvc/HttpExceptionListenerTest.php b/tests/ZfrRestTest/Mvc/HttpExceptionListenerTest.php index 4e0f34f..a607cd8 100644 --- a/tests/ZfrRestTest/Mvc/HttpExceptionListenerTest.php +++ b/tests/ZfrRestTest/Mvc/HttpExceptionListenerTest.php @@ -87,7 +87,10 @@ public function testAssertWWWAuthenticateHeaderIsAutomaticallyAddedWhenUnauthori $this->httpExceptionListener->onDispatchError($this->event); $this->assertEquals(401, $this->response->getStatusCode()); - $this->assertEquals('You are not authorized to access to the requested resource', $this->response->getReasonPhrase()); + $this->assertEquals( + 'You are not authorized to access to the requested resource', + $this->response->getReasonPhrase() + ); $this->assertTrue($this->response->getHeaders()->has('WWWAuthenticate')); } } diff --git a/tests/ZfrRestTest/Mvc/View/Http/CreateResourcePayloadListenerTest.php b/tests/ZfrRestTest/Mvc/View/Http/CreateResourcePayloadListenerTest.php index d7c7ba8..c020443 100644 --- a/tests/ZfrRestTest/Mvc/View/Http/CreateResourcePayloadListenerTest.php +++ b/tests/ZfrRestTest/Mvc/View/Http/CreateResourcePayloadListenerTest.php @@ -19,6 +19,7 @@ namespace ZfrRestTest\Mvc\View\Http; use PHPUnit_Framework_TestCase as TestCase; +use ReflectionClass; use Zend\Http\Request as HttpRequest; use Zend\Mvc\Router\Http\RouteMatch; use Zend\Stdlib\Hydrator\HydratorPluginManager; @@ -65,15 +66,15 @@ public function testCanCreatePayload() $classMetadata = $this->getMock('Doctrine\\Common\\Persistence\\Mapping\\ClassMetadata'); $resourceMetadata = new ResourceMetadata('stdClass'); + $reflectionClass = new ReflectionClass($data); + $resourceMetadata->hydrator = 'Zend\Stdlib\Hydrator\ObjectProperty'; $resourceMetadata->classMetadata = $classMetadata; - $reflectionClass = $this->getMock('ReflectionClass', array(), array(), '', false); - $reflectionClass->expects($this->any())->method('isInstance')->will($this->returnValue(true)); + $classMetadata->expects($this->any())->method('getReflectionClass')->will($this->returnValue($reflectionClass)); $resource = new Resource($data, $resourceMetadata); - $routeMatch = new RouteMatch(array('resource' => $resource)); $this->event->setRouteMatch($routeMatch); diff --git a/tests/ZfrRestTest/Resource/Metadata/CollectionResourceMetadataTest.php b/tests/ZfrRestTest/Resource/Metadata/CollectionResourceMetadataTest.php index 9f73419..a692a49 100644 --- a/tests/ZfrRestTest/Resource/Metadata/CollectionResourceMetadataTest.php +++ b/tests/ZfrRestTest/Resource/Metadata/CollectionResourceMetadataTest.php @@ -22,14 +22,14 @@ use ZfrRest\Resource\Metadata\CollectionResourceMetadata; /** - * Tests for {@see \ZfrRest\Resource\Metadata\ResourceMetadata} + * Tests for {@see \ZfrRest\Resource\Metadata\CollectionResourceMetadata} * * @author Marco Pivetta */ class CollectionResourceMetadataTest extends TestCase { /** - * @covers \ZfrRest\Resource\CollectionResourceMetadata + * @covers \ZfrRest\Resource\Metadata\CollectionResourceMetadata */ public function testResourceMetadata() { @@ -52,7 +52,7 @@ public function testResourceMetadata() } /** - * @covers \ZfrRest\Resource\CollectionResourceMetadata + * @covers \ZfrRest\Resource\Metadata\CollectionResourceMetadata */ public function testAssertHasDefaultHydrator() { diff --git a/tests/ZfrRestTest/Resource/Metadata/Driver/AnnotationDriverTest.php b/tests/ZfrRestTest/Resource/Metadata/Driver/AnnotationDriverTest.php index b2e7e5e..a4cf6c7 100644 --- a/tests/ZfrRestTest/Resource/Metadata/Driver/AnnotationDriverTest.php +++ b/tests/ZfrRestTest/Resource/Metadata/Driver/AnnotationDriverTest.php @@ -29,7 +29,9 @@ public function testExtractAnnotation() $resourceMetadataFactory = $serviceManager->get('ZfrRest\Resource\Metadata\MetadataFactory'); /** @var \ZfrRest\Resource\Metadata\ResourceMetadataInterface $resourceMetadata */ - $resourceMetadata = $resourceMetadataFactory->getMetadataForClass('ZfrRestTest\Asset\Annotation\User')->getRootClassMetadata(); + $resourceMetadata = $resourceMetadataFactory + ->getMetadataForClass('ZfrRestTest\Asset\Annotation\User') + ->getRootClassMetadata(); $this->assertEquals('ZfrRestTest\Asset\Annotation\User', $resourceMetadata->getClassName()); $this->assertEquals('ZfrRestTest\Asset\Controller\UserController', $resourceMetadata->getControllerName()); @@ -56,6 +58,9 @@ public function testExtractAnnotation() $this->assertEquals('DoctrineModule\Stdlib\Hydrator\DoctrineObject', $tweetMetadata->getHydratorName()); // Note that this one has been overriden by the User class at the association level - $this->assertEquals('Application\Controller\UserTweetListController', $tweetMetadata->getCollectionMetadata()->getControllerName()); + $this->assertEquals( + 'Application\Controller\UserTweetListController', + $tweetMetadata->getCollectionMetadata()->getControllerName() + ); } } diff --git a/tests/ZfrRestTest/Resource/Metadata/ResourceMetadataTest.php b/tests/ZfrRestTest/Resource/Metadata/ResourceMetadataTest.php index 4a347b3..22147ba 100644 --- a/tests/ZfrRestTest/Resource/Metadata/ResourceMetadataTest.php +++ b/tests/ZfrRestTest/Resource/Metadata/ResourceMetadataTest.php @@ -19,6 +19,7 @@ namespace ZfrRestTest\Resource\Metadata; use PHPUnit_Framework_TestCase as TestCase; +use ReflectionClass; use ZfrRest\Resource\Metadata\ResourceMetadata; /** @@ -29,7 +30,7 @@ class ResourceMetadataTest extends TestCase { /** - * @covers \ZfrRest\Resource\ResourceMetadata + * @covers \ZfrRest\Resource\Metadata\ResourceMetadata */ public function testResourceMetadata() { @@ -63,7 +64,7 @@ public function testResourceMetadata() } /** - * @covers \ZfrRest\Resource\ResourceMetadata + * @covers \ZfrRest\Resource\Metadata\ResourceMetadata */ public function testAssertHasDefaultHydrator() { @@ -72,16 +73,15 @@ public function testAssertHasDefaultHydrator() } /** - * @covers \ZfrRest\Resource\ResourceMetadata + * @covers \ZfrRest\Resource\Metadata\ResourceMetadata */ public function testCanCreateEmptyResource() { $resourceMetadata = new ResourceMetadata('stdClass'); $metadata = $this->getMock('Doctrine\\Common\\Persistence\\Mapping\\ClassMetadata'); $resourceMetadata->classMetadata = $metadata; + $reflectionClass = new ReflectionClass('stdClass'); - $reflectionClass = $this->getMock('ReflectionClass', array(), array(), '', false); - $reflectionClass->expects($this->any())->method('isInstance')->will($this->returnValue(true)); $metadata->expects($this->any())->method('getReflectionClass')->will($this->returnValue($reflectionClass)); $resource = $resourceMetadata->createResource(); @@ -92,7 +92,7 @@ public function testCanCreateEmptyResource() } /** - * @covers \ZfrRest\Resource\ResourceMetadata + * @covers \ZfrRest\Resource\Metadata\ResourceMetadata */ public function testCanCreateEmptyResourceWithParameter() { diff --git a/tests/ZfrRestTest/Resource/ResourceTest.php b/tests/ZfrRestTest/Resource/ResourceTest.php index 4e1e276..b78ac68 100644 --- a/tests/ZfrRestTest/Resource/ResourceTest.php +++ b/tests/ZfrRestTest/Resource/ResourceTest.php @@ -19,6 +19,7 @@ namespace ZfrRestTest\Resource; use PHPUnit_Framework_TestCase as TestCase; +use ReflectionClass; use ZfrRest\Resource\Resource; /** @@ -30,23 +31,19 @@ class ResourceTest extends TestCase { /** * @covers \ZfrRest\Resource\Resource::__construct - * @covers \ZfrRest\Resource\Resource::getResource + * @covers \ZfrRest\Resource\Resource::getData * @covers \ZfrRest\Resource\Resource::getMetadata * @covers \ZfrRest\Resource\Resource::isCollection * * @dataProvider collectionResourceProvider + * + * @param string $className + * @param mixed $instance + * @param bool $isCollection */ - public function testResource($instance, $isCollection) + public function testResource($className, $instance, $isCollection) { - $metadata = $this->createMetadata(); - - $metadata - ->getClassMetadata() - ->getReflectionClass() - ->expects($this->any()) - ->method('isInstance') - ->will($this->returnValue( ! $isCollection)); - + $metadata = $this->createMetadata(new ReflectionClass($className)); $resource = new Resource($instance, $metadata); $this->assertSame($instance, $resource->getData()); @@ -56,18 +53,11 @@ public function testResource($instance, $isCollection) /** * @covers \ZfrRest\Resource\Resource::__construct - * @covers \ZfrRest\Exception\InvalidResourceException::invalidResourceProvided + * @covers \ZfrRest\Resource\Exception\InvalidResourceException::invalidResourceProvided */ public function testDisallowsInvalidResource() { - $metadata = $this->createMetadata(); - - $metadata - ->getClassMetadata() - ->getReflectionClass() - ->expects($this->any()) - ->method('isInstance') - ->will($this->returnValue(false)); + $metadata = $this->createMetadata(new ReflectionClass($this)); $this->setExpectedException('ZfrRest\\Resource\\Exception\\InvalidResourceException'); @@ -82,22 +72,23 @@ public function testDisallowsInvalidResource() public function collectionResourceProvider() { return array( - array($this->getMock('Iterator'), true), - array($this->getMock('Doctrine\\Common\\Collections\\Selectable'), true), - array($this->getMock('Doctrine\\Common\\Collections\\Collection'), true), - array(array(), true), - array(new \stdClass(), false), + array('stdClass', $this->getMock('Iterator'), true), + array('stdClass', $this->getMock('Doctrine\\Common\\Collections\\Selectable'), true), + array('stdClass', $this->getMock('Doctrine\\Common\\Collections\\Collection'), true), + array('stdClass', array(), true), + array('stdClass', new \stdClass(), false), ); } /** + * @param ReflectionClass $reflectionClass + * * @return \PHPUnit_Framework_MockObject_MockObject|\ZfrRest\Resource\Metadata\ResourceMetadataInterface */ - private function createMetadata() + private function createMetadata(ReflectionClass $reflectionClass) { $resourceMetadata = $this->getMock('ZfrRest\\Resource\\Metadata\\ResourceMetadataInterface'); $metadata = $this->getMock('Doctrine\\Common\\Persistence\\Mapping\\ClassMetadata'); - $reflectionClass = $this->getMock('ReflectionClass', array(), array(), '', false); $resourceMetadata->expects($this->any())->method('getClassMetadata')->will($this->returnValue($metadata)); $metadata->expects($this->any())->method('getReflectionClass')->will($this->returnValue($reflectionClass)); diff --git a/tests/ZfrRestTest/Serializer/DecoderPluginManagerTest.php b/tests/ZfrRestTest/Serializer/DecoderPluginManagerTest.php index b081b01..95cafce 100644 --- a/tests/ZfrRestTest/Serializer/DecoderPluginManagerTest.php +++ b/tests/ZfrRestTest/Serializer/DecoderPluginManagerTest.php @@ -21,6 +21,7 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\ServiceManager\ServiceManager; use Zend\Mvc\Service\ServiceManagerConfig; +use ZfrRest\Options\ModuleOptions; use ZfrRest\Serializer\DecoderPluginManager; class DecoderPluginManagerTest extends TestCase @@ -51,19 +52,19 @@ public function testCanRetrieveEncodersFromDefaultFormat() public function testCanRetrievePluginManagerWithServiceManager() { $serviceManager = new ServiceManager( - new ServiceManagerConfig(array( - 'factories' => array( - 'DecoderPluginManager' => 'ZfrRest\Factory\DecoderPluginManagerFactory', - ), - )) - ); - $serviceManager->setService('Config', array( - 'zfr_rest' => array( - 'decoders' => array() + new ServiceManagerConfig( + array( + 'factories' => array( + 'DecoderPluginManager' => 'ZfrRest\Factory\DecoderPluginManagerFactory', + ), + ) ) - )); + ); + + $serviceManager->setService('ZfrRest\Options\ModuleOptions', new ModuleOptions()); $decoderPluginManager = $serviceManager->get('DecoderPluginManager'); + $this->assertInstanceOf('ZfrRest\Serializer\DecoderPluginManager', $decoderPluginManager); } } diff --git a/tests/ZfrRestTest/Util/ServiceManagerFactory.php b/tests/ZfrRestTest/Util/ServiceManagerFactory.php index b0ef421..a148f3d 100644 --- a/tests/ZfrRestTest/Util/ServiceManagerFactory.php +++ b/tests/ZfrRestTest/Util/ServiceManagerFactory.php @@ -23,40 +23,54 @@ use Zend\Mvc\Service\ServiceManagerConfig; /** - * Utility used to retrieve a freshly bootstrapped application's service manager + * Base test case to be used when a new service manager instance is required * * @license MIT * @link https://github.com/zf-fr/ZfrRest * @author Marco Pivetta */ -class ServiceManagerFactory +abstract class ServiceManagerFactory { /** * @var array */ - protected static $config; + private static $config = array(); /** + * @static * @param array $config */ - public static function setConfig(array $config) + public static function setApplicationConfig(array $config) { static::$config = $config; } /** - * Builds a new service manager + * @static + * @return array */ - public static function getServiceManager() + public static function getApplicationConfig() { - $serviceManager = new ServiceManager(new ServiceManagerConfig( - isset(static::$config['service_manager']) ? static::$config['service_manager'] : array() - )); - $serviceManager->setService('ApplicationConfig', static::$config); - $serviceManager->setFactory('ServiceListener', 'Zend\Mvc\Service\ServiceListenerFactory'); + return static::$config; + } + + /** + * @param array|null $config + * @return ServiceManager + */ + public static function getServiceManager(array $config = null) + { + $config = $config ?: static::getApplicationConfig(); + $serviceManager = new ServiceManager( + new ServiceManagerConfig( + isset($config['service_manager']) ? $config['service_manager'] : array() + ) + ); + $serviceManager->setService('ApplicationConfig', $config); - /** @var $moduleManager \Zend\ModuleManager\ModuleManager */ + /* @var $moduleManager \Zend\ModuleManager\ModuleManagerInterface */ $moduleManager = $serviceManager->get('ModuleManager'); + $moduleManager->loadModules(); return $serviceManager; diff --git a/tests/ZfrRestTest/View/Model/ModelPluginManagerTest.php b/tests/ZfrRestTest/View/Model/ModelPluginManagerTest.php index d687da3..a49d122 100644 --- a/tests/ZfrRestTest/View/Model/ModelPluginManagerTest.php +++ b/tests/ZfrRestTest/View/Model/ModelPluginManagerTest.php @@ -21,6 +21,7 @@ use PHPUnit_Framework_TestCase as TestCase; use Zend\ServiceManager\ServiceManager; use Zend\Mvc\Service\ServiceManagerConfig; +use ZfrRest\Options\ModuleOptions; use ZfrRest\View\Model\ModelPluginManager; class ModelPluginManagerTest extends TestCase @@ -49,19 +50,18 @@ public function testCanRetrieveModelFromDefaultFormat() public function testCanRetrievePluginManagerWithServiceManager() { $serviceManager = new ServiceManager( - new ServiceManagerConfig(array( - 'factories' => array( - 'ModelPluginManager' => 'ZfrRest\Factory\ModelPluginManagerFactory', + new ServiceManagerConfig( + array( + 'factories' => array( + 'ModelPluginManager' => 'ZfrRest\Factory\ModelPluginManagerFactory', + ) ) - )) - ); - $serviceManager->setService('Config', array( - 'zfr_rest' => array( - 'models' => array() ) - )); + ); + $serviceManager->setService('ZfrRest\Options\ModuleOptions', new ModuleOptions()); $modelPluginManager = $serviceManager->get('ModelPluginManager'); + $this->assertInstanceOf('ZfrRest\View\Model\ModelPluginManager', $modelPluginManager); } }