Experimental resource repository

This commit is contained in:
Paweł Jędrzejewski 2012-11-05 01:32:33 +01:00
parent 4293e37e26
commit df19162347
10 changed files with 373 additions and 176 deletions

View file

@ -26,22 +26,31 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
*
* @author Paweł Jędrzejewski <pjedrzejewski@sylius.pl>
*/
abstract class ResourceController extends Controller implements ResourceControllerInterface
class ResourceController extends Controller implements ResourceControllerInterface
{
/**
* Get one resource.
*
* @param Request $request
*
* @return Response
*/
public function getAction(Request $request)
protected $bundlePrefix;
protected $resourceName;
protected $templateNamespace;
public function __construct($bundlePrefix, $resourceName, $templateNamespace)
{
$identifier = $this->getIdentifierValue($request);
$resource = $this->findResourceOr404($identifier);
$this->bundlePrefix = $bundlePrefix;
$this->resourceName = $resourceName;
$this->templateNamespace = $templateNamespace;
}
/**
* Get single resource.
*/
public function getAction()
{
$criteria = $this->getCriteria();
$criteria[$this->getIdentifierName()] = $this->getIdentifierValue();
$resource = $this->findResourceOr404($criteria);
$view = View::create()
->setTemplate($this->getFullTemplateName('show'))
->setTemplate($this->getFullTemplateName('show.html'))
->setTemplateVar($this->getResourceName())
->setData($resource)
;
@ -50,23 +59,37 @@ abstract class ResourceController extends Controller implements ResourceControll
}
/**
* Get all paginated resourcees.
*
* @param Request $request
*
* @return Response
* Get collection (paginated by default) of resources.
*/
public function getCollectionAction(Request $request)
{
$paginator = $this->getManager()->createPaginator();
$paginator->setCurrentPage($request->query->get('page', 1), true, true);
$criteria = $this->getCriteria();
$sorting = $this->getSorting();
$resources = $paginator->getCurrentPageResults();
if ($this->isPaginated()) {
$paginator = $this
->getRepository()
->paginate($criteria, $sorting)
;
$data = $this->isHtmlRequest() ? array(Pluralization::pluralize($this->getResourceName()) => $resources, 'paginator' => $paginator) : $resourcees;
$paginator->setCurrentPage($request->query->get('page', 1), true, true);
$resources = $paginator->getCurrentPageResults();
$pluralName = Pluralization::pluralize($this->getResourceName());
$data = $this->isHtmlRequest() ? array(
$pluralName => $resources,
'paginator' => $paginator
) : $resources;
} else {
$data = $this
->getRepository()
->getCollection($criteria, $sorting)
;
}
$view = View::create()
->setTemplate($this->getFullTemplateName('list'))
->setTemplate($this->getFullTemplateName('list.html'))
->setData($data)
;
@ -86,22 +109,23 @@ abstract class ResourceController extends Controller implements ResourceControll
$form = $this->createResourceForm($resource);
if ($request->isMethod('POST') && $form->bind($request)->isValid()) {
$this->getManipulator()->create($resource);
$this->setFlash('success', sprintf("%s has been created", ucfirst($this->getResourceName())));
$this->getManager()->persist($resource);
return $this->redirectToResource($resource);
}
$htmlView = View::create()
if (!$this->isHtmlRequest()) {
return $this->handleView(View::create($form));
}
$view = View::create()
->setTemplate($this->getFullTemplateName('create.html'))
->setData(array(
$this->getResourceName() => $resource,
'form' => $form->createView()
'form' => $form->createView()
))
;
$view = $this->isHtmlRequest() ? $htmlView : View::create($form);
return $this->handleView($view);
}
@ -124,16 +148,18 @@ abstract class ResourceController extends Controller implements ResourceControll
return $this->redirectToResource($resource);
}
$htmlView = View::create()
->setTemplate($this->getFullTemplateName('update.html'))
if (!$this->isHtmlRequest()) {
return $this->handleView(View::create($form));
}
$view = View::create()
->setTemplate($this->getFullTemplateName('create.html'))
->setData(array(
$this->getResourceName() => $resource,
'form' => $form->createView()
'form' => $form->createView()
))
;
$view = $this->isHtmlRequest() ? $htmlView : View::create($form);
return $this->handleView($view);
}
@ -226,13 +252,23 @@ abstract class ResourceController extends Controller implements ResourceControll
/**
* Get resource manager.
*
* @return ManagerInterface
* @return ResourceManagerInterface
*/
protected function getManager()
{
return $this->get($this->getServiceName('manager'));
}
/**
* Get resource repository.
*
* @return ResourceRepositoryInterface
*/
protected function getRepository()
{
return $this->get($this->getServiceName('repository'));
}
protected function getServiceName($name)
{
return sprintf('%s.%s.%s', $this->getBundlePrefix(), $name, $this->getResourceName());
@ -242,17 +278,15 @@ abstract class ResourceController extends Controller implements ResourceControll
* Tries to find resource with given id.
* Throws special 404 exception when unsuccessful.
*
* @param mixed $id The resource identifier
* @param array $criteria Criteria
*
* @return ResourceInterface
*
* @throws NotFoundHttpException
*/
protected function findResourceOr404($identifier)
protected function findResourceOr404(array $criteria)
{
$criteria = array($this->getIdentifierName() => $this->getIdentifierValue());
if (!$resource = $this->getManager()->findOneBy($criteria)) {
if (!$resource = $this->getRepository()->get($criteria)) {
throw new NotFoundHttpException('Requested resource does not exist');
}
@ -266,25 +300,33 @@ abstract class ResourceController extends Controller implements ResourceControll
protected function getIdentifierValue()
{
if (!$identifier = $this->getRequest()->get($this->getIdentifierName())) {
if (null === $identifier = $this->getRequest()->get($this->getIdentifierName())) {
throw new NotFoundHttpException('No resource identifier supplied');
}
return $identifier;
}
protected function isPaginated()
{
return (Boolean) $this->getRequest()->attributes->get('_sylius.paginate', true);
}
protected function getCriteria()
{
return $this->getRequest()->get('_sylius.criteria', array());
}
protected function getSorting()
{
return $this->getRequest()->get('_sylius.sorting', array());
}
protected function renderResponse($templateName, array $parameters = array())
{
return $this->render($this->getFullTemplateName($templateName), $parameters);
}
/**
* Get full template name.
*
* @param string
*
* @return string
*/
protected function getFullTemplateName($name)
{
$template = $this->getRequest()->attributes->get('_sylius.template');
@ -300,53 +342,38 @@ abstract class ResourceController extends Controller implements ResourceControll
);
}
/**
* Get engine.
*
* @return string
*/
protected function getEngine()
{
return $this->container->getParameter(sprintf('%s.engine', $this->getBundlePrefix()));
}
/**
* Check if request accepts html format.
*
* @return Boolean
*/
protected function isHtmlRequest()
{
return 'html' === $this->getRequest()->getRequestFormat();
}
/**
* Convert view to a response object.
*
* @param View $view
*
* @return Response
*/
protected function handleView(View $view)
{
return $this->get('fos_rest.view_handler')->handle($view);
}
/**
* Get name of the form type to use.
*
* @return string
*/
protected function getResourceFormType()
{
return sprintf('%s_%s', $this->getBundlePrefix(), $this->getResourceName());
}
/**
* Get templates namespace.
*
* @return string
*/
abstract protected function getTemplateNamespace();
abstract protected function getBundlePrefix();
protected function getTemplateNamespace()
{
return $this->templateNamespace;
}
protected function getBundlePrefix()
{
return $this->bundlePrefix;
}
protected function getResourceName()
{
return $this->resourceName;
}
}

View file

@ -20,15 +20,13 @@ use Sylius\Bundle\ResourceBundle\Model\ResourceInterface;
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
abstract class DoctrineResourceManager extends ResourceManager implements DoctrineResourceManagerInterface
class DoctrineResourceManager extends ResourceManager implements DoctrineResourceManagerInterface
{
protected $objectManager;
protected $objectRepository;
public function __construct(ObjectManager $objectManager, $class)
{
$this->objectManager = $objectManager;
$this->objectRepository = $objectManager->getRepository($class);
parent::__construct($class);
}
@ -57,33 +55,8 @@ abstract class DoctrineResourceManager extends ResourceManager implements Doctri
}
}
public function find($id)
{
return $this->objectRepository->find($id);
}
public function findOneBy(array $criteria)
{
return $this->objectRepository->findOneBy($criteria);
}
public function findAll()
{
return $this->objectRepository->findAll();
}
public function findBy(array $criteria)
{
return $this->objectRepository->findBy($criteria);
}
public function getObjectManager()
{
return $this->objectManager;
}
public function getObjectRepository()
{
return $this->objectRepository;
}
}

View file

@ -21,5 +21,4 @@ use Sylius\Bundle\ResourceBundle\Manager\ResourceManagerInterface;
interface DoctrineResourceManagerInterface extends ResourceManagerInterface
{
function getObjectManager();
function getObjectRepository();
}

View file

@ -1,30 +0,0 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\ResourceBundle\Manager\Doctrine\ORM;
use Doctrine\ORM\EntityManager;
use Pagerfanta\Adapter\DoctrineORMAdapter;
use Pagerfanta\Pagerfanta;
use Sylius\Bundle\ResourceBundle\Manager\Doctrine\DoctrineResourceManager;
/**
* Doctrine ORM driver resource manager.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class ResourceManager extends DoctrineResourceManager
{
public function createPaginator()
{
return new Pagerfanta(new DoctrineORMAdapter($this->objectRepository->createQueryBuilder('r')));
}
}

View file

@ -27,13 +27,6 @@ interface ResourceManagerInterface
*/
function create();
/**
* Creates a new Pagerfanta instance to paginate the resources.
*
* @return PagerfantaInterface
*/
function createPaginator();
/**
* Persist.
*
@ -50,40 +43,6 @@ interface ResourceManagerInterface
*/
function remove(ResourceInterface $resource, $commit = true);
/**
* Finds resource by id.
*
* @param mixed Identifier
*
* @return ResourceInterface
*/
function find($id);
/**
* Finds resource by criteria.
*
* @param array $criteria
*
* @return ResourceInterface
*/
function findOneBy(array $criteria);
/**
* Find all.
*
* @return Collection
*/
function findAll();
/**
* Finds resources by criteria.
*
* @param array $criteria
*
* @return array
*/
function findBy(array $criteria);
/**
* Get resource class name.
*

View file

@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\ResourceBundle\Repository\Doctrine;
use Doctrine\Common\Persistence\ObjectRepository;
use Sylius\Bundle\ResourceBundle\Repository\ResourceRepository;
/**
* Base Doctrine resource manager class.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
abstract class DoctrineResourceRepository extends ResourceRepository implements DoctrineResourceRepositoryInterface
{
protected $objectRepository;
public function __construct(ObjectRepository $objectRepository, $class)
{
$this->objectRepository = $objectRepository;
parent::__construct($class);
}
public function getObjectRepository()
{
return $this->objectRepository;
}
}

View file

@ -0,0 +1,24 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\ResourceBundle\Repository\Doctrine;
use Sylius\Bundle\ResourceBundle\Repository\ResourceRepositoryInterface;
/**
* Doctrine resource manager interface.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
interface DoctrineResourceRepositoryInterface extends ResourceRepositoryInterface
{
function getObjectRepository();
}

View file

@ -0,0 +1,122 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\ResourceBundle\Repository\Doctrine\ORM;
use Doctrine\ORM\QueryBuilder;
use Pagerfanta\Adapter\DoctrineORMAdapter;
use Pagerfanta\Pagerfanta;
use Sylius\Bundle\ResourceBundle\Repository\Doctrine\DoctrineResourceRepository;
/**
* Doctrine ORM driver resource manager.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class ResourceRepository extends DoctrineResourceRepository
{
/**
* {@inheritdoc}
*/
public function get(array $criteria)
{
return $this
->getQueryBuilder($criteria, array())
->getQuery()
->getOneOrNullResult()
;
}
/**
* {@inheritdoc}
*/
public function getCollection(array $criteria = array(), array $sorting = array(), $limit = null)
{
$queryBuilder = $this->getQueryBuilder($criteria, $sorting);
if (null !== $limit) {
$queryBuilder->setMaxResults($limit);
}
return $queryBuilder
->getQuery()
->execute()
;
}
/**
* {@inheritdoc}
*/
public function paginate(array $criteria = array(), array $sorting = array())
{
return new Pagerfanta(new DoctrineORMAdapter($this->getQueryBuilder($criteria, $sorting)));
}
protected function getQueryBuilder(array $criteria, array $sorting)
{
$queryBuilder = $this->getBasicQueryBuilder();
$this->filter($queryBuilder, $criteria);
$this->sort($queryBuilder, $sorting);
return $queryBuilder;
}
protected function filter(QueryBuilder $queryBuilder, array $criteria)
{
$reflectionClass = new \ReflectionClass($this->getClass());
$properties = array_keys($reflectionClass->getDefaultProperties());
$i = 0;
foreach ($criteria as $property => $condition) {
if (!is_array($condition)) {
$condition = array('=', $condition);
}
list($comparison, $value) = $condition;
if (in_array($property, $properties) && in_array($comparison, array('=', '!=', '>', '<', '>=', '<='))) {
$formula = sprintf("%s.%s %s :PARAM%d", $this->getAlias(), $property, $comparison, $i);
$queryBuilder
->andWhere($formula)
->setParameter('PARAM'.$i, $value)
;
$i++;
}
}
}
protected function sort(QueryBuilder $queryBuilder, array $sorting)
{
$acceptedOrders = array('asc', 'desc');
foreach ($sorting as $property => $order) {
if (in_array(strtolower($order), $acceptedOrders)) {
$queryBuilder->orderBy($this->getAlias().'.'.$property, $order);
}
}
}
protected function getBasicQueryBuilder()
{
return $this
->getObjectRepository()
->createQueryBuilder($this->getAlias())
;
}
protected function getAlias()
{
return 'r';
}
}

View file

@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\ResourceBundle\Repository;
/**
* Base resource repository class.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
abstract class ResourceRepository implements ResourceRepositoryInterface
{
protected $class;
public function __construct($class)
{
$this->class = $class;
}
public function getClass()
{
return $this->class;
}
}

View file

@ -0,0 +1,54 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\ResourceBundle\Repository;
use Sylius\Bundle\ResourceBundle\Model\ResourceInterface;
/**
* Resource repository interface.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
interface ResourceRepositoryInterface
{
/**
* Finds resource by identifier.
*
* @param array $criteria
*
* @return ResourceInterface
*/
function get(array $criteria);
/**
* Finds resource by criteria.
*
* @param array $criteria
*
* @return ResourceInterface
*/
function getCollection(array $criteria = array(), array $sorting = array(), $limit = null);
/**
* Creates a new Pagerfanta instance to paginate the resources.
*
* @return PagerfantaInterface
*/
function paginate(array $criteria = array(), array $sorting = array());
/**
* Get resource class name.
*
* @return string
*/
function getClass();
}