crudification + corrections on thirdparty

This commit is contained in:
Julien Fastré 2021-10-04 18:25:49 +02:00
parent cc7e38194f
commit 05b9476a71
16 changed files with 313 additions and 212 deletions

View File

@ -209,22 +209,24 @@ class CRUDController extends AbstractController
* This method: * This method:
* *
* 1. Launch `onPreIndex` * 1. Launch `onPreIndex`
* x. check acl. If it does return a response instance, return it * 2. check acl. If it does return a response instance, return it
* x. launch `onPostCheckACL`. If it does return a response instance, return it * 3. launch `onPostCheckACL`. If it does return a response instance, return it
* 1. count the items, using `countEntities` * 4. count the items, using `countEntities`
* 2. build a paginator element from the the number of entities ; * 5. build a paginator element from the the number of entities ;
* 3. Launch `onPreIndexQuery`. If it does return a response instance, return it * 6. Launch `onPreIndexQuery`. If it does return a response instance, return it
* 3. build a query, using `queryEntities` * 7. fetch the results, using `getQueryResult`
* x. fetch the results, using `getQueryResult` *
* x. Launch `onPostIndexFetchQuery`. If it does return a response instance, return it * Internally, this build a query, using `queryEntities`
* 4. create default parameters: *
* 8. Launch `onPostIndexFetchQuery`. If it does return a response instance, return it
* 9. create default parameters:
* *
* The default parameters are: * The default parameters are:
* *
* * entities: the list en entities ; * * entities: the list en entities ;
* * crud_name: the name of the crud ; * * crud_name: the name of the crud ;
* * paginator: a paginator element ; * * paginator: a paginator element ;
* 5. Launch rendering, the parameter is fetch using `getTemplateFor` * 10. Launch rendering, the parameter is fetch using `getTemplateFor`
* The parameters may be personnalized using `generateTemplateParameter`. * The parameters may be personnalized using `generateTemplateParameter`.
* *
* @param string $action * @param string $action
@ -259,16 +261,7 @@ class CRUDController extends AbstractController
return $response; return $response;
} }
$query = $this->queryEntities($action, $request, $paginator); $entities = $this->getQueryResult($action, $request, $totalItems, $paginator);
$response = $this->onPostIndexBuildQuery($action, $request, $totalItems,
$paginator, $query);
if ($response instanceof Response) {
return $response;
}
$entities = $this->getQueryResult($action, $request, $totalItems, $paginator, $query);
$response = $this->onPostIndexFetchQuery($action, $request, $totalItems, $response = $this->onPostIndexFetchQuery($action, $request, $totalItems,
$paginator, $entities); $paginator, $entities);
@ -393,11 +386,12 @@ class CRUDController extends AbstractController
* @param Request $request * @param Request $request
* @param int $totalItems * @param int $totalItems
* @param PaginatorInterface $paginator * @param PaginatorInterface $paginator
* @param mixed $query
* @return mixed * @return mixed
*/ */
protected function getQueryResult(string $action, Request $request, int $totalItems, PaginatorInterface $paginator, $query) protected function getQueryResult(string $action, Request $request, int $totalItems, PaginatorInterface $paginator)
{ {
$query = $this->queryEntities($action, $request, $paginator);
return $query->getQuery()->getResult(); return $query->getQuery()->getResult();
} }

View File

@ -32,12 +32,15 @@
{% endif %} {% endif %}
{% block pagination %}
<div class="crud_index__pagination"> <div class="crud_index__pagination">
{{ chill_pagination(paginator) }} {{ chill_pagination(paginator) }}
</div> </div>
{% endblock %}
{% block list_actions %} {% block list_actions %}
<ul class="record_actions sticky-form-buttons"> <ul class="record_actions sticky-form-buttons">
{% block actions_before %}{% endblock %}
{% block add_new %} {% block add_new %}
<li> <li>
<a href="{{ chill_path_add_return_path('chill_crud_' ~ crud_name ~ '_new') }}" class="btn btn-new">{{ ('crud.'~crud_name~'.index.add_new')|trans( {'%crud_name%': crud_name} ) }}</a> <a href="{{ chill_path_add_return_path('chill_crud_' ~ crud_name ~ '_new') }}" class="btn btn-new">{{ ('crud.'~crud_name~'.index.add_new')|trans( {'%crud_name%': crud_name} ) }}</a>

View File

@ -2,6 +2,11 @@
namespace Chill\ThirdPartyBundle\Controller; namespace Chill\ThirdPartyBundle\Controller;
use Chill\MainBundle\CRUD\Controller\AbstractCRUDController;
use Chill\MainBundle\CRUD\Controller\CRUDController;
use Chill\MainBundle\Pagination\PaginatorInterface;
use Chill\ThirdPartyBundle\Repository\ThirdPartyACLAwareRepositoryInterface;
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
@ -16,12 +21,7 @@ use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\Role;
use Chill\MainBundle\Pagination\PaginatorFactory; use Chill\MainBundle\Pagination\PaginatorFactory;
/** final class ThirdPartyController extends CRUDController
* Routes for operations on ThirdParties.
*
* @Route("/{_locale}/thirdparty/thirdparty")
*/
class ThirdPartyController extends Controller
{ {
/** /**
* *
@ -41,37 +41,33 @@ class ThirdPartyController extends Controller
*/ */
protected $paginatorFactory; protected $paginatorFactory;
protected ThirdPartyACLAwareRepositoryInterface $thirdPartyACLAwareRepository;
public function __construct( public function __construct(
AuthorizationHelper $authorizationHelper, AuthorizationHelper $authorizationHelper,
TranslatorInterface $translator, TranslatorInterface $translator,
PaginatorFactory $paginatorFactory PaginatorFactory $paginatorFactory,
ThirdPartyACLAwareRepositoryInterface $thirdPartyACLAwareRepository
) { ) {
$this->authorizationHelper = $authorizationHelper; $this->authorizationHelper = $authorizationHelper;
$this->translator = $translator; $this->translator = $translator;
$this->paginatorFactory = $paginatorFactory; $this->paginatorFactory = $paginatorFactory;
$this->thirdPartyACLAwareRepository = $thirdPartyACLAwareRepository;
} }
protected function countEntities(string $action, Request $request): int
/**
* @Route("/index", name="chill_3party_3party_index")
*/
public function indexAction()
{ {
$this->denyAccessUnlessGranted(ThirdPartyVoter::SHOW); return $this->thirdPartyACLAwareRepository->countThirdParties(ThirdPartyVoter::SHOW);
$repository = $this->getDoctrine()->getManager()
->getRepository(ThirdParty::class);
$nbThirdParties = $repository->count([]); //$repository->countByMemberOfCenters($centers);
$pagination = $this->paginatorFactory->create($nbThirdParties);
$thirdParties = $repository->findAll();
return $this->render('ChillThirdPartyBundle:ThirdParty:index.html.twig', array(
'third_parties' => $thirdParties,
'pagination' => $pagination
));
} }
protected function getQueryResult(string $action, Request $request, int $totalItems, PaginatorInterface $paginator)
{
return $this->thirdPartyACLAwareRepository
->listThirdParties(ThirdPartyVoter::class, ['name' => 'ASC'], $paginator->getItemsPerPage(),
$paginator->getCurrentPageFirstItemNumber());
}
/** /**
* @Route("/new", name="chill_3party_3party_new") * @Route("/new", name="chill_3party_3party_new")
*/ */

View File

@ -2,6 +2,9 @@
namespace Chill\ThirdPartyBundle\DependencyInjection; namespace Chill\ThirdPartyBundle\DependencyInjection;
use Chill\ThirdPartyBundle\Controller\ThirdPartyController;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use Chill\ThirdPartyBundle\Form\ThirdPartyType;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\HttpKernel\DependencyInjection\Extension;
@ -37,6 +40,7 @@ class ChillThirdPartyExtension extends Extension implements PrependExtensionInte
$loader->load('services/menu.yaml'); $loader->load('services/menu.yaml');
$loader->load('services/fixtures.yaml'); $loader->load('services/fixtures.yaml');
$loader->load('services/serializer.yaml'); $loader->load('services/serializer.yaml');
$loader->load('services/repository.yaml');
} }
public function prepend(ContainerBuilder $container) public function prepend(ContainerBuilder $container)
@ -54,6 +58,25 @@ class ChillThirdPartyExtension extends Extension implements PrependExtensionInte
'@ChillThirdPartyBundle/config/routes.yaml' '@ChillThirdPartyBundle/config/routes.yaml'
) )
], ],
'cruds' => [
[
'class' => ThirdParty::class,
'controller' => ThirdPartyController::class,
'name' => '3party_3party',
'base_path' => '/3party/3party',
'form_class' => ThirdPartyType::class,
'actions' => [
'index' => [
'template' => '@ChillThirdParty/ThirdParty/index.html.twig',
'role' => ThirdPartyVoter::SHOW,
],
'new' => [
'role' => ThirdPartyVoter::CREATE,
]
]
]
],
'apis' => [ 'apis' => [
[ [
'class' => \Chill\ThirdPartyBundle\Entity\ThirdParty::class, 'class' => \Chill\ThirdPartyBundle\Entity\ThirdParty::class,

View File

@ -40,7 +40,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
* center. * center.
* *
* @ORM\Table(name="chill_3party.third_party") * @ORM\Table(name="chill_3party.third_party")
* @ORM\Entity(repositoryClass="Chill\ThirdPartyBundle\Repository\ThirdPartyRepository") * @ORM\Entity
* @DiscriminatorMap(typeProperty="type", mapping={ * @DiscriminatorMap(typeProperty="type", mapping={
* "thirdparty"=ThirdParty::class * "thirdparty"=ThirdParty::class
* }) * })

View File

@ -60,7 +60,7 @@ class MenuBuilder implements LocalMenuBuilderInterface
->addChild( ->addChild(
$this->translator->trans('Third parties'), $this->translator->trans('Third parties'),
[ [
'route' => 'chill_3party_3party_index', 'route' => 'chill_crud_3party_3party_index',
]) ])
->setExtras([ ->setExtras([
'order' => 112 'order' => 112

View File

@ -2,22 +2,52 @@
namespace Chill\ThirdPartyBundle\Repository; namespace Chill\ThirdPartyBundle\Repository;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\ThirdPartyBundle\Entity\ThirdParty; use Chill\ThirdPartyBundle\Entity\ThirdParty;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Security\Core\Security;
/** final class ThirdPartyACLAwareRepository implements ThirdPartyACLAwareRepositoryInterface
* @Author Mathieu Jaumotte mathieu.jaumotte@champs-libres.coop
*/
class ThirdPartyACLAwareRepository implements ThirdPartyACLAwareRepositoryInterface
{ {
private Security $security;
private AuthorizationHelper $authorizationHelper;
private ThirdPartyRepository $thirdPartyRepository;
public function findByThirdparty( public function __construct(Security $security, AuthorizationHelper $authorizationHelper, ThirdPartyRepository $thirdPartyRepository)
ThirdParty $thirdparty, {
$this->security = $security;
$this->authorizationHelper = $authorizationHelper;
$this->thirdPartyRepository = $thirdPartyRepository;
}
public function listThirdParties(
string $role, string $role,
?array $orderBy = [], ?array $orderBy = [],
int $limit = null, ?int $limit = null,
int $offset = null ?int $offset = null
): array { ): array {
$qb = $this->buildQuery($role);
// TODO: Implement findByThirdparty() method. foreach ($orderBy as $sort => $direction) {
$qb->addOrderBy('tp.'.$sort, $direction);
}
$qb->setFirstResult($offset)
->setMaxResults($limit);
return $qb->getQuery()->getResult();
}
public function countThirdParties(
string $role
): int {
$qb = $this->buildQuery($role);
$qb->select('count(tp)');
return $qb->getQuery()->getSingleScalarResult();
}
public function buildQuery(): QueryBuilder {
return $this->thirdPartyRepository->createQueryBuilder('tp');
} }
} }

View File

@ -6,8 +6,16 @@ use Chill\ThirdPartyBundle\Entity\ThirdParty;
interface ThirdPartyACLAwareRepositoryInterface interface ThirdPartyACLAwareRepositoryInterface
{ {
public function findByThirdparty( public function countThirdParties(string $role): int;
ThirdParty $thirdparty,
/**
* @param string $role
* @param array|null $orderBy
* @param int|null $limit
* @param int|null $offset
* @return array|ThirdParty[]
*/
public function listThirdParties(
string $role, string $role,
?array $orderBy = [], ?array $orderBy = [],
int $limit = null, int $limit = null,

View File

@ -2,18 +2,21 @@
namespace Chill\ThirdPartyBundle\Repository; namespace Chill\ThirdPartyBundle\Repository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\Query; use Doctrine\ORM\Query;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Chill\ThirdPartyBundle\Entity\ThirdParty; use Chill\ThirdPartyBundle\Entity\ThirdParty;
use Doctrine\Persistence\ObjectRepository;
class ThirdPartyRepository extends ServiceEntityRepository final class ThirdPartyRepository implements ObjectRepository
{ {
public function __construct(ManagerRegistry $registry) private EntityRepository $repository;
public function __construct(EntityManagerInterface $em)
{ {
parent::__construct($registry, ThirdParty::class); $this->repository = $em->getRepository(ThirdParty::class);
} }
/** /**
@ -147,4 +150,45 @@ class ThirdPartyRepository extends ServiceEntityRepository
); );
} }
} }
public function find($id): ?ThirdParty
{
return $this->repository->find($id);
}
/**
* @return array|ThirdParty[]
*/
public function findAll(): array
{
return $this->repository->findAll();
}
/**
* @param array $criteria
* @param array|null $orderBy
* @param null $limit
* @param null $offset
* @return array|ThirdParty[]
*/
public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array
{
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
}
public function findOneBy(array $criteria): ?ThirdParty
{
return $this->repository->findOneBy($criteria);
}
public function getClassName(): string
{
return ThirdParty::class;
}
public function createQueryBuilder(string $alias, ?string $indexBy = null): QueryBuilder
{
return $this->repository->createQueryBuilder($alias, $indexBy);
}
} }

View File

@ -2,13 +2,20 @@
{% block title 'List of third parties'|trans %} {% block title 'List of third parties'|trans %}
{% set third_parties = entities %}
{% block content %} {% block content %}
{% embed '@ChillMain/CRUD/_index.html.twig' %}
{% block index_header %}
<h1>{{ 'List of third parties'|trans }}</h1>
{% endblock %}
{% block table_entities %}
<div class="thirdparty-list my-5"> <div class="thirdparty-list my-5">
{#
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-10 col-xxl"> <div class="col-md-10 col-xxl">
<h1>{{ 'List of third parties'|trans }}</h1>
{% if third_parties|length == 0 %} {% if third_parties|length == 0 %}
<p class="chill-no-data-statement">{{ 'No third parties'|trans }}</p> <p class="chill-no-data-statement">{{ 'No third parties'|trans }}</p>
{% else %} {% else %}
@ -19,11 +26,12 @@
</div> </div>
</div> </div>
#}
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-10 col-xxl"> <div>
<label class="counter"> <label class="counter">
<span>{{ pagination.totalItems }}</span> {{ 'third parties'|trans }} <span>{{ paginator.totalItems }}</span> {{ 'third parties'|trans }}
</label> </label>
<table class="table table-bordered border-dark table-striped align-middle"> <table class="table table-bordered border-dark table-striped align-middle">
@ -83,27 +91,18 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
{% if third_parties|length < pagination.getTotalItems %}
{{ chill_pagination(pagination, 'long') }}
{% endif %}
{% endif %}
<ul class="record_actions sticky-form-buttons">
<li class="cancel">
{{ chill_items_per_page(pagination) }}
</li>
{% if is_granted('CHILL_3PARTY_3PARTY_CREATE') %}
<li>
<a href="{{ chill_path_add_return_path('chill_3party_3party_new') }}" class="btn btn-create">
{{ "New third party"|trans }}
</a>
</li>
{% endif %}
</ul>
</div> </div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
{% block actions_before %}
<li class="cancel">
{{ chill_items_per_page(paginator) }}
</li>
{% endblock %}
{% endembed %}
{% endblock %}
{% block css %}
{{ encore_entry_link_tags('page_3party_3party_index') }}
{% endblock %}

View File

@ -1,9 +1,12 @@
module.exports = function(encore, entries) module.exports = function(encore, entries)
{ {
entries.push(__dirname + '/Resources/public/chill/index.js');
// Aliases are used when webpack is trying to resolve modules path // Aliases are used when webpack is trying to resolve modules path
encore.addAliases({ encore.addAliases({
ChillThirdPartyAssets: __dirname + '/Resources/public' ChillThirdPartyAssets: __dirname + '/Resources/public'
}); });
encore.addEntry(
'page_3party_3party_index',
__dirname + '/Resources/public/page/index/index.js'
);
}; };

View File

@ -6,8 +6,3 @@ services:
tags: tags:
- { name: 'serializer.normalizer', priority: 64 } - { name: 'serializer.normalizer', priority: 64 }
Chill\ThirdPartyBundle\Repository\:
autowire: true
resource: '../Repository/'
tags:
- { name: 'doctrine.repository_service' }

View File

@ -1,7 +1,5 @@
services: services:
Chill\ThirdPartyBundle\Controller\ThirdPartyController: Chill\ThirdPartyBundle\Controller\:
arguments: resource: './../Controller'
$authorizationHelper: '@Chill\MainBundle\Security\Authorization\AuthorizationHelper' autowire: true
$translator: '@Symfony\Component\Translation\TranslatorInterface' autoconfigure: true
$paginatorFactory: '@Chill\MainBundle\Pagination\PaginatorFactory'
tags: ['controller.service_arguments']

View File

@ -0,0 +1,8 @@
---
services:
Chill\ThirdPartyBundle\Repository\:
autowire: true
autoconfigure: true
resource: '../Repository/'
Chill\ThirdPartyBundle\Repository\ThirdPartyACLAwareRepositoryInterface: '@Chill\ThirdPartyBundle\Repository\ThirdPartyACLAwareRepository'