From 4b8e4a190b5eaaf8d21da2d6b8178baf860e55d1 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Metivier <jean-philippe.metivier@unicaen.fr> Date: Tue, 2 Apr 2024 11:09:55 +0200 Subject: [PATCH] =?UTF-8?q?S=C3=A9paration=20privilege?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/merged/categorie.config.php | 100 +++++++++++++++ config/merged/index.config.php | 2 +- config/unicaen-indicateur.global.php.dist | 3 + documentation/02_privileges.sql | 3 +- .../Controller/CategorieController.php | 23 ++++ .../Controller/CategorieControllerFactory.php | 32 +++++ .../Controller/IndicateurController.php | 5 + src/UnicaenIndicateur/Entity/Db/Categorie.php | 79 ++++++++++++ .../Entity/Db/Indicateur.php | 37 ++++++ ...caenIndicateur.Entity.Db.Categorie.dcm.xml | 16 +++ ...aenIndicateur.Entity.Db.Indicateur.dcm.xml | 7 ++ .../Form/Categorie/CategorieForm.php | 117 ++++++++++++++++++ .../Categorie/CategorieFormAwareTrait.php | 20 +++ .../Form/Categorie/CategorieFormFactory.php | 29 +++++ .../Form/Categorie/CategorieHydrator.php | 37 ++++++ .../Categorie/CategorieHydratorFactory.php | 14 +++ .../Form/Indicateur/IndicateurForm.php | 42 ++++++- .../Form/Indicateur/IndicateurFormFactory.php | 7 +- .../Form/Indicateur/IndicateurHydrator.php | 16 +-- .../Privilege/IndicateurPrivileges.php | 1 + .../Service/Categorie/CategorieService.php | 113 +++++++++++++++++ .../Categorie/CategorieServiceAwareTrait.php | 19 +++ .../Categorie/CategorieServiceFactory.php | 25 ++++ .../Service/Indicateur/IndicateurService.php | 95 +++++++++----- view/unicaen-indicateur/categorie/index.phtml | 38 ++++++ .../unicaen-indicateur/indicateur/index.phtml | 12 +- 26 files changed, 844 insertions(+), 48 deletions(-) create mode 100644 config/merged/categorie.config.php create mode 100644 src/UnicaenIndicateur/Controller/CategorieController.php create mode 100644 src/UnicaenIndicateur/Controller/CategorieControllerFactory.php create mode 100644 src/UnicaenIndicateur/Entity/Db/Categorie.php create mode 100644 src/UnicaenIndicateur/Entity/Db/Mapping/UnicaenIndicateur.Entity.Db.Categorie.dcm.xml create mode 100644 src/UnicaenIndicateur/Form/Categorie/CategorieForm.php create mode 100644 src/UnicaenIndicateur/Form/Categorie/CategorieFormAwareTrait.php create mode 100644 src/UnicaenIndicateur/Form/Categorie/CategorieFormFactory.php create mode 100644 src/UnicaenIndicateur/Form/Categorie/CategorieHydrator.php create mode 100644 src/UnicaenIndicateur/Form/Categorie/CategorieHydratorFactory.php create mode 100644 src/UnicaenIndicateur/Service/Categorie/CategorieService.php create mode 100644 src/UnicaenIndicateur/Service/Categorie/CategorieServiceAwareTrait.php create mode 100644 src/UnicaenIndicateur/Service/Categorie/CategorieServiceFactory.php create mode 100644 view/unicaen-indicateur/categorie/index.phtml diff --git a/config/merged/categorie.config.php b/config/merged/categorie.config.php new file mode 100644 index 0000000..57ddb60 --- /dev/null +++ b/config/merged/categorie.config.php @@ -0,0 +1,100 @@ +<?php + +use Laminas\Router\Http\Literal; +use Laminas\Router\Http\Segment; +use UnicaenIndicateur\Controller\CategorieController; +use UnicaenIndicateur\Controller\CategorieControllerFactory; +use UnicaenIndicateur\Form\Categorie\CategorieForm; +use UnicaenIndicateur\Form\Categorie\CategorieFormFactory; +use UnicaenIndicateur\Form\Categorie\CategorieHydrator; +use UnicaenIndicateur\Form\Categorie\CategorieHydratorFactory; +use UnicaenIndicateur\Provider\Privilege\IndicateurPrivileges; +use UnicaenIndicateur\Service\Categorie\CategorieService; +use UnicaenIndicateur\Service\Categorie\CategorieServiceFactory; +use UnicaenPrivilege\Guard\PrivilegeController; + +return [ + 'bjyauthorize' => [ + 'guards' => [ + PrivilegeController::class => [ + [ + 'controller' => CategorieController::class, + 'action' => [ + 'index', + 'ajouter', + 'modifier', + ], + 'privileges' => [ + IndicateurPrivileges::EDITER_INDICATEUR, + ], + ], + [ + 'controller' => CategorieController::class, + 'action' => [ + 'afficher', + ], + 'privileges' => [ + IndicateurPrivileges::AFFICHER_INDICATEUR, + ], + ], + [ + 'controller' => CategorieController::class, + 'action' => [ + 'supprimer', + ], + 'privileges' => [ + IndicateurPrivileges::DETRUIRE_INDICATEUR, + ], + ], + ], + ], + ], + + 'router' => [ + 'routes' => [ + 'indicateur' => [ + 'type' => Literal::class, + 'options' => [ + 'route' => '/indicateur', + ], + 'may_terminate' => false, + 'child_routes' => [ + 'categorie' => [ + 'type' => Literal::class, + 'options' => [ + 'route' => '/categorie', + 'defaults' => [ + /** @see CategorieController::indexAction() */ + 'controller' => CategorieController::class, + 'action' => 'index', + ], + ], + 'may_terminate' => true, + 'child_routes' => [], + ], + ], + ], + ], + ], + + 'service_manager' => [ + 'factories' => [ + CategorieService::class => CategorieServiceFactory::class, + ], + ], + 'controllers' => [ + 'factories' => [ + CategorieController::class => CategorieControllerFactory::class, + ], + ], + 'form_elements' => [ + 'factories' => [ + CategorieForm::class => CategorieFormFactory::class, + ], + ], + 'hydrators' => [ + 'factories' => [ + CategorieHydrator::class => CategorieHydratorFactory::class, + ], + ], +]; \ No newline at end of file diff --git a/config/merged/index.config.php b/config/merged/index.config.php index 20c50d8..7e2ccf3 100644 --- a/config/merged/index.config.php +++ b/config/merged/index.config.php @@ -17,7 +17,7 @@ return [ 'abonnement' ], 'privileges' => [ - IndicateurPrivileges::AFFICHER_INDICATEUR, + IndicateurPrivileges::INDICATEUR_MES_INDICATEURS, ], ], ], diff --git a/config/unicaen-indicateur.global.php.dist b/config/unicaen-indicateur.global.php.dist index a590ee5..8eea281 100644 --- a/config/unicaen-indicateur.global.php.dist +++ b/config/unicaen-indicateur.global.php.dist @@ -1,5 +1,8 @@ <?php +use UnicaenIndicateur\Controller\IndexController; +use UnicaenPrivilege\Guard\PrivilegeController; + return [ 'navigation' => [ 'default' => [ diff --git a/documentation/02_privileges.sql b/documentation/02_privileges.sql index e51c4e2..7b46e7a 100644 --- a/documentation/02_privileges.sql +++ b/documentation/02_privileges.sql @@ -4,7 +4,8 @@ INSERT INTO unicaen_privilege_privilege(CATEGORIE_ID, CODE, LIBELLE, ORDRE) WITH d(code, lib, ordre) AS ( SELECT 'afficher_indicateur', 'Afficher un indicateur', 1 UNION SELECT 'editer_indicateur', 'Éditer un indicateur', 2 UNION - SELECT 'detruire_indicateur', 'Effacer un indicateur', 3 + SELECT 'detruire_indicateur', 'Effacer un indicateur', 3 UNION + SELECT 'indicateur_mes_indicateurs', 'Affichage du menu - Mes Indicateurs -', 100 ) SELECT cp.id, d.code, d.lib, d.ordre FROM d diff --git a/src/UnicaenIndicateur/Controller/CategorieController.php b/src/UnicaenIndicateur/Controller/CategorieController.php new file mode 100644 index 0000000..3b0231b --- /dev/null +++ b/src/UnicaenIndicateur/Controller/CategorieController.php @@ -0,0 +1,23 @@ +<?php + +namespace UnicaenIndicateur\Controller; + +use Laminas\Mvc\Controller\AbstractActionController; +use Laminas\View\Model\ViewModel; +use UnicaenIndicateur\Form\Categorie\CategorieFormAwareTrait; +use UnicaenIndicateur\Service\Categorie\CategorieServiceAwareTrait; + +class CategorieController extends AbstractActionController +{ + use CategorieServiceAwareTrait; + use CategorieFormAwareTrait; + + public function indexAction(): ViewModel + { + $categories = $this->getCategorieService()->getCategories(); + + return new ViewModel([ + 'categories' => $categories, + ]); + } +} \ No newline at end of file diff --git a/src/UnicaenIndicateur/Controller/CategorieControllerFactory.php b/src/UnicaenIndicateur/Controller/CategorieControllerFactory.php new file mode 100644 index 0000000..d70636e --- /dev/null +++ b/src/UnicaenIndicateur/Controller/CategorieControllerFactory.php @@ -0,0 +1,32 @@ +<?php + +namespace UnicaenIndicateur\Controller; + +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\ContainerInterface; +use Psr\Container\NotFoundExceptionInterface; +use UnicaenIndicateur\Form\Categorie\CategorieForm; +use UnicaenIndicateur\Service\Categorie\CategorieService; + +class CategorieControllerFactory { + + /** + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function __invoke(ContainerInterface $container): CategorieController + { + /** + * @var CategorieService $categorieService + * @var CategorieForm $categorieForm + */ + $categorieService = $container->get(CategorieService::class); +// $categorieForm = $container->get('FormElementManager')->get(CategorieForm::class); + + $controller = new CategorieController(); + $controller->setCategorieService($categorieService); +// $controller->setCategorieForm($categorieForm); + return $controller; + + } +} \ No newline at end of file diff --git a/src/UnicaenIndicateur/Controller/IndicateurController.php b/src/UnicaenIndicateur/Controller/IndicateurController.php index c5a0112..81a5bc7 100644 --- a/src/UnicaenIndicateur/Controller/IndicateurController.php +++ b/src/UnicaenIndicateur/Controller/IndicateurController.php @@ -89,6 +89,10 @@ class IndicateurController extends AbstractActionController { $this->getIndicateurService()->create($indicateur); $this->getIndicateurService()->createView($indicateur); + $count = $this->getIndicateurService()->getCount($indicateur); + $indicateur->setNbElements($count); + $this->getIndicateurService()->update($indicateur); + exit(); } } @@ -107,6 +111,7 @@ class IndicateurController extends AbstractActionController { $namespace = $this->params()->fromQuery('namespace'); $form = $this->getIndicateurForm(); + $form->setOldCode($indicateur->getCode()); $form->setAttribute('action', $this->url()->fromRoute('indicateur/modifier', ['indicateur' => $indicateur->getId()], ['query' => ['namespace' => $namespace]], true)); if ($namespace) { $indicateur->setNamespace($namespace); diff --git a/src/UnicaenIndicateur/Entity/Db/Categorie.php b/src/UnicaenIndicateur/Entity/Db/Categorie.php new file mode 100644 index 0000000..839c014 --- /dev/null +++ b/src/UnicaenIndicateur/Entity/Db/Categorie.php @@ -0,0 +1,79 @@ +<?php + +namespace UnicaenIndicateur\Entity\Db; + +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; + +class Categorie { + + private ?int $id = null; + private ?string $code = null; + private ?string $libelle = null; + private ?string $description = null; + private ?int $ordre = 9999; + + private Collection $indicateurs; + + + public function __construct() + { + $this->indicateurs = new ArrayCollection(); + } + + public function getId() : ?int + { + return $this->id; + } + + public function getCode(): ?string + { + return $this->code; + } + + public function setCode(?string $code): void + { + $this->code = $code; + } + + public function getLibelle(): ?string + { + return $this->libelle; + } + + public function setLibelle(?string $libelle): void + { + $this->libelle = $libelle; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function setDescription(?string $description): void + { + $this->description = $description; + } + + public function getOrdre(): ?int + { + return $this->ordre; + } + + public function setOrdre(?int $ordre): void + { + $this->ordre = $ordre; + } + + public function getIndicateurs(): Collection + { + return $this->indicateurs; + } + + public function setIndicateurs(Collection $indicateurs): void + { + $this->indicateurs = $indicateurs; + } + +} \ No newline at end of file diff --git a/src/UnicaenIndicateur/Entity/Db/Indicateur.php b/src/UnicaenIndicateur/Entity/Db/Indicateur.php index dccec39..f43cf54 100644 --- a/src/UnicaenIndicateur/Entity/Db/Indicateur.php +++ b/src/UnicaenIndicateur/Entity/Db/Indicateur.php @@ -5,6 +5,7 @@ namespace UnicaenIndicateur\Entity\Db; use DateTime; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use UnicaenIndicateur\Entity\Db\Categorie; class Indicateur { @@ -14,8 +15,11 @@ class Indicateur { const ENTITY_ADAPTATIF = 'Adaptatif'; private ?int $id = null; + private ?string $code = null; private ?string $titre = null; private ?string $description = null; + private ?Categorie $categorie = null; + private ?string $requete = null; private ?DateTime $dernierRafraichissement = null; private ?string $viewId = null; @@ -23,6 +27,7 @@ class Indicateur { private ?string $namespace = null; private Collection $abonnements; private Collection $tableaux; + private ?int $nbElements = null; public function __construct() { @@ -35,6 +40,16 @@ class Indicateur { return $this->id; } + public function getCode(): ?string + { + return $this->code; + } + + public function setCode(?string $code): void + { + $this->code = $code; + } + public function getTitre() : ?string { return $this->titre; @@ -55,6 +70,18 @@ class Indicateur { $this->description = $description; } + public function getCategorie(): ?Categorie + { + return $this->categorie; + } + + public function setCategorie(?Categorie $categorie): void + { + $this->categorie = $categorie; + } + + + public function getRequete() : ?string { return $this->requete; @@ -105,6 +132,16 @@ class Indicateur { $this->namespace = $namespace; } + public function getNbElements(): ?int + { + return $this->nbElements; + } + + public function setNbElements(?int $nbElements): void + { + $this->nbElements = $nbElements; + } + /** Abonnements **************************************************************** */ /** diff --git a/src/UnicaenIndicateur/Entity/Db/Mapping/UnicaenIndicateur.Entity.Db.Categorie.dcm.xml b/src/UnicaenIndicateur/Entity/Db/Mapping/UnicaenIndicateur.Entity.Db.Categorie.dcm.xml new file mode 100644 index 0000000..416fc2a --- /dev/null +++ b/src/UnicaenIndicateur/Entity/Db/Mapping/UnicaenIndicateur.Entity.Db.Categorie.dcm.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> + <entity name="UnicaenIndicateur\Entity\Db\Categorie" table="unicaen_indicateur_categorie"> + + <id name="id" type="integer" column="id"> + <generator strategy="IDENTITY"/> + </id> + + <field name="code" type="string" length="255" column="code" nullable="true"/> + <field name="libelle" type="string" length="1024" column="libelle" nullable="false"/> + <field name="description" type="text" column="description" nullable="true"/> + <field name="ordre" type="integer" column="ordre" nullable="false"/> + + <one-to-many target-entity="UnicaenIndicateur\Entity\Db\Indicateur" field="indicateurs" mapped-by="categorie" /> + </entity> +</doctrine-mapping> diff --git a/src/UnicaenIndicateur/Entity/Db/Mapping/UnicaenIndicateur.Entity.Db.Indicateur.dcm.xml b/src/UnicaenIndicateur/Entity/Db/Mapping/UnicaenIndicateur.Entity.Db.Indicateur.dcm.xml index c1f38dd..1c3c60c 100644 --- a/src/UnicaenIndicateur/Entity/Db/Mapping/UnicaenIndicateur.Entity.Db.Indicateur.dcm.xml +++ b/src/UnicaenIndicateur/Entity/Db/Mapping/UnicaenIndicateur.Entity.Db.Indicateur.dcm.xml @@ -6,6 +6,7 @@ <generator strategy="IDENTITY"/> </id> + <field name="code" type="string" length="255" column="code" nullable="false"/> <field name="titre" type="string" length="255" column="titre" nullable="false"/> <field name="description" type="string" length="2047" column="description" nullable="false"/> <field name="requete" type="string" length="4095" column="requete" nullable="false"/> @@ -13,6 +14,12 @@ <field name="viewId" type="string" length="255" column="view_id" nullable="true"/> <field name="entity" type="string" length="255" column="entity" nullable="true"/> <field name="namespace" type="string" length="1024" column="namespace" nullable="true"/> + <field name="nbElements" type="integer" column="nb_elements" nullable="true"/> + + + <many-to-one target-entity="UnicaenIndicateur\Entity\Db\Categorie" field="categorie"> + <join-column name="categorie_id" referenced-column-name="id"/> + </many-to-one> <one-to-many target-entity="UnicaenIndicateur\Entity\Db\Abonnement" field="abonnements" mapped-by="indicateur" /> diff --git a/src/UnicaenIndicateur/Form/Categorie/CategorieForm.php b/src/UnicaenIndicateur/Form/Categorie/CategorieForm.php new file mode 100644 index 0000000..95c04aa --- /dev/null +++ b/src/UnicaenIndicateur/Form/Categorie/CategorieForm.php @@ -0,0 +1,117 @@ +<?php + +namespace UnicaenIndicateur\Form\Categorie; + +use Laminas\Form\Element\Button; +use Laminas\Form\Element\Text; +use Laminas\Form\Form; +use Laminas\InputFilter\Factory; +use Laminas\Validator\Callback; +use Unicaen\Console\Prompt\Number; +use UnicaenIndicateur\Service\Categorie\CategorieServiceAwareTrait; + +class CategorieForm extends Form +{ + use CategorieServiceAwareTrait; + + private ?string $oldCode = null; + + public function setOldCode(?string $oldCode): void + { + $this->oldCode = $oldCode; + } + + public function init(): void + { + // code + $this->add([ + 'type' => Text::class, + 'name' => 'code', + 'options' => [ + 'label' => "Code unique identifiant la catégorie <span class='icon icon-obligatoire' title='champ obligatoire'></span> :", + 'label_options' => ['disable_html_escape' => true,], + ], + 'attributes' => [ + 'id' => 'code', + ], + ]); + // libelle + $this->add([ + 'type' => Text::class, + 'name' => 'libelle', + 'options' => [ + 'label' => "Libellé <span class='icon icon-obligatoire' title='champ obligatoire'></span> :", + 'label_options' => ['disable_html_escape' => true,], + ], + 'attributes' => [ + 'id' => 'libelle', + ], + ]); + // description + $this->add([ + 'name' => 'description', + 'type' => 'textarea', + 'options' => [ + 'label' => 'Description : ', + 'label_attributes' => [ + 'class' => 'control-label', + ], + ], + 'attributes' => [ + 'class' => 'type2 form-control', + ] + ]); + // ordre + $this->add([ + 'type' => Number::class, + 'name' => 'ordre', + 'options' => [ + 'label' => "Ordre <span class='icon icon-obligatoire' title='champ obligatoire'></span> :", + 'label_options' => ['disable_html_escape' => true,], + ], + 'attributes' => [ + 'id' => 'ordre', + 'min' => 0, + 'max' => 9999, + ], + ]); + // submit + $this->add([ + 'type' => Button::class, + 'name' => 'creer', + 'options' => [ + 'label' => '<i class="fas fa-save"></i> Enregistrer', + 'label_options' => ['disable_html_escape' => true,], + ], + 'attributes' => [ + 'type' => 'submit', + 'class' => 'btn btn-primary', + ], + ]); + + + $this->setInputFilter((new Factory())->createInputFilter([ + 'code' => [ + 'required' => true, + 'validators' => [[ + 'name' => Callback::class, + 'options' => [ + 'messages' => [ + Callback::INVALID_VALUE => "Ce code existe déjà", + ], + 'callback' => function ($value, $context = []) { + if ($value == $this->oldCode) return true; +// return ($this->getEntityManager()->getRepository(EtatType::class)->findOneBy(['code'=>$value],[]) == null);; + return ($this->getCategorieService()->getCategorieByCode($value) == null); + }, + //'break_chain_on_failure' => true, + ], + ]], + ], + + 'libelle' => ['required' => true,], + 'description' => ['required' => false,], + 'ordre' => ['required' => true,], + ])); + } +} \ No newline at end of file diff --git a/src/UnicaenIndicateur/Form/Categorie/CategorieFormAwareTrait.php b/src/UnicaenIndicateur/Form/Categorie/CategorieFormAwareTrait.php new file mode 100644 index 0000000..17a85d7 --- /dev/null +++ b/src/UnicaenIndicateur/Form/Categorie/CategorieFormAwareTrait.php @@ -0,0 +1,20 @@ +<?php + +namespace UnicaenIndicateur\Form\Categorie; + +trait CategorieFormAwareTrait +{ + + private CategorieForm $categorieForm; + + public function getCategorieForm(): CategorieForm + { + return $this->categorieForm; + } + + public function setCategorieForm(CategorieForm $categorieForm): void + { + $this->categorieForm = $categorieForm; + } + +} \ No newline at end of file diff --git a/src/UnicaenIndicateur/Form/Categorie/CategorieFormFactory.php b/src/UnicaenIndicateur/Form/Categorie/CategorieFormFactory.php new file mode 100644 index 0000000..3ffedd8 --- /dev/null +++ b/src/UnicaenIndicateur/Form/Categorie/CategorieFormFactory.php @@ -0,0 +1,29 @@ +<?php + +namespace UnicaenIndicateur\Form\Categorie; + +use Interop\Container\ContainerInterface; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; +use UnicaenIndicateur\Service\Categorie\CategorieService; + +class CategorieFormFactory { + + /** + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function __invoke(ContainerInterface $container) : CategorieForm + { + /** + * @var CategorieService $categorieService + * @var CategorieHydrator $hydrator */ + $categorieService = $container->get(CategorieService::class); + $hydrator = $container->get('HydratorManager')->get(CategorieHydrator::class); + + $form = new CategorieForm(); + $form->setCategorieService($categorieService); + $form->setHydrator($hydrator); + return $form; + } +} \ No newline at end of file diff --git a/src/UnicaenIndicateur/Form/Categorie/CategorieHydrator.php b/src/UnicaenIndicateur/Form/Categorie/CategorieHydrator.php new file mode 100644 index 0000000..dcf5ea6 --- /dev/null +++ b/src/UnicaenIndicateur/Form/Categorie/CategorieHydrator.php @@ -0,0 +1,37 @@ +<?php + +namespace UnicaenIndicateur\Form\Categorie; + +use UnicaenIndicateur\Entity\Db\Categorie; +use Laminas\Hydrator\HydratorInterface; + +class CategorieHydrator implements HydratorInterface { + + public function extract($object): array + { + /** @var Categorie $object */ + $data = [ + 'code' => $object->getCode(), + 'libelle' => $object->getLibelle(), + 'description' => $object->getDescription(), + 'ordre' => $object->getOrdre(), + ]; + return $data; + } + + public function hydrate(array $data, object $object) : object + { + $code = (isset($data['code']) AND trim($data['code']) !== '')?trim($data['code']):null; + $libelle = (isset($data['libelle']) AND trim($data['libelle']) !== '')?trim($data['libelle']):null; + $description = (isset($data['description']) AND trim($data['description']) !== '')?trim($data['description']):null; + $ordre = (isset($data['ordre']) AND trim($data['ordre']) !== '')?trim($data['ordre']):null; + + /** @var Categorie $object */ + $object->setCode($code); + $object->setLibelle($libelle); + $object->setDescription($description); + $object->setOrdre($ordre); + return $object; + } + +} \ No newline at end of file diff --git a/src/UnicaenIndicateur/Form/Categorie/CategorieHydratorFactory.php b/src/UnicaenIndicateur/Form/Categorie/CategorieHydratorFactory.php new file mode 100644 index 0000000..c957013 --- /dev/null +++ b/src/UnicaenIndicateur/Form/Categorie/CategorieHydratorFactory.php @@ -0,0 +1,14 @@ +<?php + +namespace UnicaenIndicateur\Form\Categorie; + +use Psr\Container\ContainerInterface; + +class CategorieHydratorFactory +{ + public function __invoke(ContainerInterface $container): CategorieHydrator + { + $hydrator = new CategorieHydrator(); + return $hydrator; + } +} \ No newline at end of file diff --git a/src/UnicaenIndicateur/Form/Indicateur/IndicateurForm.php b/src/UnicaenIndicateur/Form/Indicateur/IndicateurForm.php index 180e967..55ca1eb 100644 --- a/src/UnicaenIndicateur/Form/Indicateur/IndicateurForm.php +++ b/src/UnicaenIndicateur/Form/Indicateur/IndicateurForm.php @@ -2,17 +2,39 @@ namespace UnicaenIndicateur\Form\Indicateur; +use Laminas\Validator\Callback; use UnicaenIndicateur\Entity\Db\Indicateur; use Laminas\Form\Element\Button; use Laminas\Form\Element\Select; use Laminas\Form\Element\Text; use Laminas\Form\Form; use Laminas\InputFilter\Factory; +use UnicaenIndicateur\Service\Indicateur\IndicateurServiceAwareTrait; class IndicateurForm extends Form { + use IndicateurServiceAwareTrait; - public function init() + private ?string $oldCode = null; + + public function setOldCode(?string $oldCode): void + { + $this->oldCode = $oldCode; + } + + public function init(): void { + // code + $this->add([ + 'type' => Text::class, + 'name' => 'code', + 'options' => [ + 'label' => "Code unique identifiant l'indicateur <span class='icon icon-obligatoire' title='champ obligatoire'></span> :", + 'label_options' => [ 'disable_html_escape' => true, ], + ], + 'attributes' => [ + 'id' => 'code', + ], + ]); // libelle $this->add([ 'type' => Text::class, @@ -113,6 +135,24 @@ class IndicateurForm extends Form { $this->setInputFilter((new Factory())->createInputFilter([ + 'code' => [ + 'required' => true, + 'validators' => [[ + 'name' => Callback::class, + 'options' => [ + 'messages' => [ + Callback::INVALID_VALUE => "Ce code existe déjà", + ], + 'callback' => function ($value, $context = []) { + if($value == $this->oldCode) return true; +// return ($this->getEntityManager()->getRepository(EtatType::class)->findOneBy(['code'=>$value],[]) == null);; + return ($this->getIndicateurService()->getIndicateurByCode($value) == null); + }, + //'break_chain_on_failure' => true, + ], + ]], + ], + 'libelle' => [ 'required' => true, ], 'description' => [ 'required' => false, ], 'namespace' => [ 'required' => false, ], diff --git a/src/UnicaenIndicateur/Form/Indicateur/IndicateurFormFactory.php b/src/UnicaenIndicateur/Form/Indicateur/IndicateurFormFactory.php index 983dff5..bd511fa 100644 --- a/src/UnicaenIndicateur/Form/Indicateur/IndicateurFormFactory.php +++ b/src/UnicaenIndicateur/Form/Indicateur/IndicateurFormFactory.php @@ -5,6 +5,7 @@ namespace UnicaenIndicateur\Form\Indicateur; use Interop\Container\ContainerInterface; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; +use UnicaenIndicateur\Service\Indicateur\IndicateurService; class IndicateurFormFactory { @@ -16,10 +17,14 @@ class IndicateurFormFactory { */ public function __invoke(ContainerInterface $container) : IndicateurForm { - /** @var IndicateurHydrator $hydrator */ + /** + * @var IndicateurService $indicateurService + * @var IndicateurHydrator $hydrator */ + $indicateurService = $container->get(IndicateurService::class); $hydrator = $container->get('HydratorManager')->get(IndicateurHydrator::class); $form = new IndicateurForm(); + $form->setIndicateurService($indicateurService); $form->setHydrator($hydrator); $form->init(); return $form; diff --git a/src/UnicaenIndicateur/Form/Indicateur/IndicateurHydrator.php b/src/UnicaenIndicateur/Form/Indicateur/IndicateurHydrator.php index b4fb273..e6de0cc 100644 --- a/src/UnicaenIndicateur/Form/Indicateur/IndicateurHydrator.php +++ b/src/UnicaenIndicateur/Form/Indicateur/IndicateurHydrator.php @@ -7,13 +7,11 @@ use Laminas\Hydrator\HydratorInterface; class IndicateurHydrator implements HydratorInterface { - /** - * @param Indicateur $object - * @return array - */ public function extract($object): array { + /** @var Indicateur $object */ $data = [ + 'code' => $object->getCode(), 'libelle' => $object->getTitre(), 'description' => $object->getDescription(), 'namespace' => $object->getNamespace(), @@ -24,15 +22,13 @@ class IndicateurHydrator implements HydratorInterface { return $data; } - /** - * @param array $data - * @param Indicateur $object - * @return Indicateur - */ - public function hydrate(array $data, $object) : object + public function hydrate(array $data, object $object) : object { + $code = (isset($data['code']) AND trim($data['code']) !== '')?trim($data['code']):null; $namespace = (isset($data['namespace']) AND trim($data['namespace']) !== '')?trim($data['namespace']):null; + /** @var Indicateur $object */ + $object->setCode($code); $object->setTitre($data['libelle']); $object->setDescription($data['description']); $object->setNamespace($namespace); diff --git a/src/UnicaenIndicateur/Provider/Privilege/IndicateurPrivileges.php b/src/UnicaenIndicateur/Provider/Privilege/IndicateurPrivileges.php index dc19cc6..92ec16a 100644 --- a/src/UnicaenIndicateur/Provider/Privilege/IndicateurPrivileges.php +++ b/src/UnicaenIndicateur/Provider/Privilege/IndicateurPrivileges.php @@ -6,6 +6,7 @@ use UnicaenPrivilege\Provider\Privilege\Privileges; class IndicateurPrivileges extends Privileges { + const INDICATEUR_MES_INDICATEURS = 'indicateur-indicateur_mes_indicateurs'; const AFFICHER_INDICATEUR = 'indicateur-afficher_indicateur'; const EDITER_INDICATEUR = 'indicateur-editer_indicateur'; const DETRUIRE_INDICATEUR = 'indicateur-detruire_indicateur'; diff --git a/src/UnicaenIndicateur/Service/Categorie/CategorieService.php b/src/UnicaenIndicateur/Service/Categorie/CategorieService.php new file mode 100644 index 0000000..a42576d --- /dev/null +++ b/src/UnicaenIndicateur/Service/Categorie/CategorieService.php @@ -0,0 +1,113 @@ +<?php + +namespace UnicaenIndicateur\Service\Categorie; + +use Doctrine\ORM\EntityManager; +use Doctrine\ORM\NonUniqueResultException; +use Doctrine\ORM\QueryBuilder; +use DoctrineModule\Persistence\ProvidesObjectManager; +use Laminas\Mvc\Controller\AbstractActionController; +use RuntimeException; +use UnicaenIndicateur\Entity\Db\Categorie; + +/** + * @property EntityManager $objectManager + */ +class CategorieService +{ + use ProvidesObjectManager; + + /** GESTION DES ENTITES ***********************************************************************************************/ + + public function create(Categorie $categorie): Categorie + { + $this->getObjectManager()->persist($categorie); + $this->getObjectManager()->flush($categorie); + return $categorie; + } + + public function update(Categorie $categorie): Categorie + { + $this->getObjectManager()->flush($categorie); + return $categorie; + } + + public function delete(Categorie $categorie): Categorie + { + $this->getObjectManager()->remove($categorie); + $this->getObjectManager()->flush($categorie); + return $categorie; + } + + /** REQUETAGE *****************************************************************************************************/ + + public function createQueryBuilder(): QueryBuilder + { + $qb = $this->getObjectManager()->getRepository(Categorie::class)->createQueryBuilder('categorie') + ->leftJoin('categorie.indicateurs', 'indicateur')->addSelect('indicateur'); + return $qb; + } + + /** @return Categorie[] */ + public function getCategories(string $champ = 'ordre', string $ordre = 'ASC'): array + { + $qb = $this->createQueryBuilder() + ->orderBy('categorie.' . $champ, $ordre); + + $result = $qb->getQuery()->getResult(); + return $result; + } + + public function getCategoriesAsOptions(string $champ = 'ordre', string $ordre = 'ASC'): array + { + $qb = $this->createQueryBuilder() + ->orderBy('categorie.' . $champ, $ordre); + + $result = $qb->getQuery()->getResult(); + + $options = []; + foreach ($result as $item) { + $options[$item->getId()] = $item->getLibelle(); + } + return $options; + } + + public function getCategorie(?int $id): ?Categorie + { + $qb = $this->createQueryBuilder() + ->andWhere('categorie.id = :id')->setParameter('id', $id); + try { + $result = $qb->getQuery()->getOneOrNullResult(); + } catch (NonUniqueResultException $e) { + throw new RuntimeException("Plusieurs [" . Categorie::class . "] partagent le même id [" . $id . "]", $e); + } + return $result; + } + + /** + * @param AbstractActionController $controller + * @param string $paramName + * @return Categorie|null + */ + public function getRequestedCategorie(AbstractActionController $controller, string $paramName = "categorie"): ?Categorie + { + $id = $controller->params()->fromRoute($paramName); + return $this->getCategorie($id); + } + + public function getCategorieByCode(?string $code): ?Categorie + { + $qb = $this->createQueryBuilder() + ->andWhere('categorie.code = :code')->setParameter('code', $code); + try { + $result = $qb->getQuery()->getOneOrNullResult(); + } catch (NonUniqueResultException $e) { + throw new RuntimeException("Plusieurs [" . Categorie::class . "] partagent le même code [" . $code . "]", $e); + } + return $result; + } + + /** FACADE **************************************************************/ + + +} \ No newline at end of file diff --git a/src/UnicaenIndicateur/Service/Categorie/CategorieServiceAwareTrait.php b/src/UnicaenIndicateur/Service/Categorie/CategorieServiceAwareTrait.php new file mode 100644 index 0000000..f620b1f --- /dev/null +++ b/src/UnicaenIndicateur/Service/Categorie/CategorieServiceAwareTrait.php @@ -0,0 +1,19 @@ +<?php + +namespace UnicaenIndicateur\Service\Categorie; + +trait CategorieServiceAwareTrait { + + private CategorieService $categorieService; + + public function getCategorieService(): CategorieService + { + return $this->categorieService; + } + + public function setCategorieService(CategorieService $categorieService): void + { + $this->categorieService = $categorieService; + } + +} \ No newline at end of file diff --git a/src/UnicaenIndicateur/Service/Categorie/CategorieServiceFactory.php b/src/UnicaenIndicateur/Service/Categorie/CategorieServiceFactory.php new file mode 100644 index 0000000..20ab6db --- /dev/null +++ b/src/UnicaenIndicateur/Service/Categorie/CategorieServiceFactory.php @@ -0,0 +1,25 @@ +<?php + +namespace UnicaenIndicateur\Service\Categorie; + +use Doctrine\ORM\EntityManager; +use Interop\Container\ContainerInterface; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; + +class CategorieServiceFactory { + + /** + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function __invoke(ContainerInterface $container) : CategorieService + { + /** @var EntityManager $entityManager */ + $entityManager = $container->get('doctrine.entitymanager.orm_default'); + + $service = new CategorieService(); + $service->setObjectManager($entityManager); + return $service; + } +} \ No newline at end of file diff --git a/src/UnicaenIndicateur/Service/Indicateur/IndicateurService.php b/src/UnicaenIndicateur/Service/Indicateur/IndicateurService.php index 6763fd1..e96c0bb 100644 --- a/src/UnicaenIndicateur/Service/Indicateur/IndicateurService.php +++ b/src/UnicaenIndicateur/Service/Indicateur/IndicateurService.php @@ -3,37 +3,36 @@ namespace UnicaenIndicateur\Service\Indicateur; use DateTime; -use Doctrine\DBAL\Exception as DBA_Exception; use Doctrine\DBAL\Driver\Exception as DBA_Driver_Exception; +use Doctrine\DBAL\Exception as DBA_Exception; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Exception\ORMException; use Doctrine\ORM\NonUniqueResultException; +use Doctrine\ORM\QueryBuilder; use DoctrineModule\Persistence\ProvidesObjectManager; use Exception; +use Laminas\Mvc\Controller\AbstractActionController; use RuntimeException; use UnicaenIndicateur\Entity\Db\Indicateur; -use Laminas\Mvc\Controller\AbstractActionController; /** * @property EntityManager $objectManager */ -class IndicateurService { +class IndicateurService +{ use ProvidesObjectManager; -/** GESTION DES ENTITES ***********************************************************************************************/ + /** GESTION DES ENTITES ***********************************************************************************************/ /** * @param Indicateur $indicateur * @return Indicateur */ - public function create(Indicateur $indicateur) : Indicateur + public function create(Indicateur $indicateur): Indicateur { - try { - $this->getObjectManager()->persist($indicateur); - $this->getObjectManager()->flush($indicateur); - } catch (ORMException $e) { - throw new RuntimeException("Un problème est survenue lors de l'enregistrement en base.", $e); - } + $this->getObjectManager()->persist($indicateur); + $this->getObjectManager()->flush($indicateur); + if ($indicateur->getCode() === null) $indicateur->setCode($indicateur->getId()); return $indicateur; } @@ -41,7 +40,7 @@ class IndicateurService { * @param Indicateur $indicateur * @return Indicateur */ - public function update(Indicateur $indicateur) : Indicateur + public function update(Indicateur $indicateur): Indicateur { try { $this->getObjectManager()->flush($indicateur); @@ -55,7 +54,7 @@ class IndicateurService { * @param Indicateur $indicateur * @return Indicateur */ - public function delete(Indicateur $indicateur) : Indicateur + public function delete(Indicateur $indicateur): Indicateur { try { $this->getObjectManager()->remove($indicateur); @@ -68,7 +67,7 @@ class IndicateurService { /** GESTION DES VUES **********************************************************************************************/ - public function verifierExistanceMaterializedView($viewname) : bool + public function verifierExistanceMaterializedView($viewname): bool { try { $sql = "SELECT EXISTS (SELECT FROM pg_matviews WHERE matviewname='" . $viewname . "')"; @@ -84,7 +83,8 @@ class IndicateurService { * @param Indicateur $indicateur * @return array|null */ - public function fetch(Indicateur $indicateur) : ?array { + public function fetch(Indicateur $indicateur): ?array + { $exist = $this->verifierExistanceMaterializedView($indicateur->getViewId()); if ($exist === false) return null; @@ -122,6 +122,8 @@ class IndicateurService { throw new RuntimeException("Un problème est survenu lors de la récupération de des données de l'indicateur.", 0, $e); } $indicateur->setDernierRafraichissement(new DateTime()); + $count = $this->getCount($indicateur); + $indicateur->setNbElements($count); $this->update($indicateur); } @@ -148,7 +150,7 @@ class IndicateurService { */ public function createView(Indicateur $indicateur) { - $sql = "CREATE MATERIALIZED VIEW ".$indicateur->getViewId(). " AS ".$indicateur->getRequete(); + $sql = "CREATE MATERIALIZED VIEW " . $indicateur->getViewId() . " AS " . $indicateur->getRequete(); try { $query = $this->getObjectManager()->getConnection()->prepare($sql); } catch (DBA_Exception $e) { @@ -160,7 +162,8 @@ class IndicateurService { throw new RuntimeException("Un problème est survenu lors de la récupération de des données de l'indicateur.", 0, $e); } $indicateur->setDernierRafraichissement(new DateTime()); - $this->update($indicateur); + $count = $this->getCount($indicateur); + $indicateur->setNbElements($count); } /** @@ -170,16 +173,25 @@ class IndicateurService { { $this->dropView($indicateur); $this->createView($indicateur); + $count = $this->getCount($indicateur); + $indicateur->setNbElements($count); } /** REQUETAGE *****************************************************************************************************/ + public function createQueryBuilder(): QueryBuilder + { + $qb = $this->getObjectManager()->getRepository(Indicateur::class)->createQueryBuilder('indicateur'); + return $qb; + + } + /** * @param string $attribut * @param string $ordre * @return Indicateur[] */ - public function getIndicateurs(string $attribut = 'id', string $ordre = 'ASC') : array + public function getIndicateurs(string $attribut = 'id', string $ordre = 'ASC'): array { $qb = $this->getObjectManager()->getRepository(Indicateur::class)->createQueryBuilder('indicateur') ->orderBy('indicateur.' . $attribut, $ordre); @@ -192,7 +204,7 @@ class IndicateurService { * @param int|null $id * @return Indicateur|null */ - public function getIndicateur(?int $id) : ?Indicateur + public function getIndicateur(?int $id): ?Indicateur { if ($id === null) return null; @@ -202,7 +214,7 @@ class IndicateurService { try { $result = $qb->getQuery()->getOneOrNullResult(); } catch (NonUniqueResultException $e) { - throw new RuntimeException("Plusieurs Indicateur partagent le même id [".$id."]", $e); + throw new RuntimeException("Plusieurs Indicateur partagent le même id [" . $id . "]", $e); } return $result; } @@ -212,16 +224,28 @@ class IndicateurService { * @param string $paramName * @return Indicateur|null */ - public function getRequestedIndicateur(AbstractActionController $controller, string $paramName = "indicateur") : ?Indicateur + public function getRequestedIndicateur(AbstractActionController $controller, string $paramName = "indicateur"): ?Indicateur { $id = $controller->params()->fromRoute($paramName); return $this->getIndicateur($id); } + public function getIndicateurByCode(string $code): ?Indicateur + { + $qb = $this->createQueryBuilder() + ->andWhere('indicateur.code = :code')->setParameter('code', $code); + try { + $indicateur = $qb->getQuery()->getOneOrNullResult(); + } catch (NonUniqueResultException $e) { + throw new RuntimeException("Plusieurs [" . Indicateur::class . "] partagent le même code [".$code."]",0,$e); + } + return $indicateur; + } + /** * @return Indicateur[] */ - public function getIndicateursByNamespace(?string $namespace) : array + public function getIndicateursByNamespace(?string $namespace): array { $qb = $this->getObjectManager()->getRepository(Indicateur::class)->createQueryBuilder('indicateur') ->andWhere('indicateur.namespace = :namespace') @@ -236,7 +260,7 @@ class IndicateurService { * @return array|null */ - public function getIndicateurData(Indicateur $indicateur) : ?array + public function getIndicateurData(Indicateur $indicateur): ?array { $exist = $this->verifierExistanceMaterializedView($indicateur->getViewId()); if (!$exist) return null; @@ -257,19 +281,19 @@ class IndicateurService { } if ($indicateur->getEntity() === Indicateur::ENTITY_STRUCTURE) { $rubriques = [ - 'Code' => 'code', - 'Libelle' => 'libelle_court', - 'Libelle long' => 'libelle_long', - 'Type' => 'type', + 'Code' => 'code', + 'Libelle' => 'libelle_court', + 'Libelle long' => 'libelle_long', + 'Type' => 'type', ]; } if ($indicateur->getEntity() === Indicateur::ENTITY_AGENT) { $rubriques = [ - 'ID' => 'c_src_individu', - 'SOURCE' => 'c_source', - 'Prenom' => 'prenom', - 'Nom' => 'nom_usage', + 'ID' => 'c_src_individu', + 'SOURCE' => 'c_source', + 'Prenom' => 'prenom', + 'Nom' => 'nom_usage', ]; } @@ -285,5 +309,14 @@ class IndicateurService { return [$rubriques, $data]; } + public function getCount(Indicateur $indicateur): ?int + { + $exist = $this->verifierExistanceMaterializedView($indicateur->getViewId()); + if (!$exist) return null; + + $rawdata = $this->fetch($indicateur); + return count($rawdata); + } + } \ No newline at end of file diff --git a/view/unicaen-indicateur/categorie/index.phtml b/view/unicaen-indicateur/categorie/index.phtml new file mode 100644 index 0000000..f0a7f37 --- /dev/null +++ b/view/unicaen-indicateur/categorie/index.phtml @@ -0,0 +1,38 @@ +<?php + +use UnicaenIndicateur\Entity\Db\Categorie; +use UnicaenIndicateur\Provider\Privilege\IndicateurPrivileges; + +/** + * @see \UnicaenIndicateur\Controller\CategorieController::indexAction() + * @var Categorie[] $categories + */ + +$this->headTitle("Catégories d'indicateur"); + +$canAfficher = $this->isAllowed(IndicateurPrivileges::getResourceId(IndicateurPrivileges::AFFICHER_INDICATEUR)); +$canAjouter = $this->isAllowed(IndicateurPrivileges::getResourceId(IndicateurPrivileges::EDITER_INDICATEUR)); +$canModifier = $this->isAllowed(IndicateurPrivileges::getResourceId(IndicateurPrivileges::EDITER_INDICATEUR)); +$canSupprimer = $this->isAllowed(IndicateurPrivileges::getResourceId(IndicateurPrivileges::DETRUIRE_INDICATEUR)); + +$canIndexIndicateur = $this->isAllowed(IndicateurPrivileges::getResourceId(IndicateurPrivileges::AFFICHER_INDICATEUR)); + +?> + +<div class="row"> + <div class="col-md-9"> + <h1 class="page-header"> + Categories d'indicateur + </h1> + </div> + <div class="col-md-3"> + <?php /** @see \UnicaenIndicateur\Controller\IndicateurController::indexAction() */ ?> + <a href="<?php echo $this->url('indicateurs', [], [], true); ?>" + class="btn btn-secondary"> + <span class="icon icon-listing"></span> + Accéder aux indicateurs + </a> + </div> +</div> + + diff --git a/view/unicaen-indicateur/indicateur/index.phtml b/view/unicaen-indicateur/indicateur/index.phtml index 612ebe6..3ffbf37 100644 --- a/view/unicaen-indicateur/indicateur/index.phtml +++ b/view/unicaen-indicateur/indicateur/index.phtml @@ -58,6 +58,8 @@ $canTableaux = $this->isAllowed(TableaudebordPrivileges::getResourceId(Tableaude <table id="datatable" class="table table-condensed"> <thead> <tr> + <th> Code </th> + <th> Effectif </th> <th> Titre </th> <th> Entity </th> <th> #Abonnement </th> @@ -67,6 +69,8 @@ $canTableaux = $this->isAllowed(TableaudebordPrivileges::getResourceId(Tableaude <tbody> <?php foreach ($indicateurs as $indicateur) : ?> <tr> + <td> <?php echo $indicateur->getCode(); ?> </td> + <td> <?php echo $indicateur->getNbElements(); ?> </td> <td> <?php echo $indicateur->getTitre(); ?> <?php if ($indicateur->getDescription()) : ?> @@ -108,10 +112,12 @@ $canTableaux = $this->isAllowed(TableaudebordPrivileges::getResourceId(Tableaude <?php if ($canDetruire): ?> <?php /** @see IndicateurController::detruireAction() */?> - <a href="<?php echo $this->url("indicateur/detruire", ['indicateur' => $indicateur->getId()], [], true); ?>"> - <span class="icon icon-retirer" title="Détruire l'indicateur"></span></a> + <a href="<?php echo $this->url("indicateur/detruire", ['indicateur' => $indicateur->getId()], [], true); ?>" + class="ajax-modal" data-event="modification" + > + <span class="text-danger icon icon-unchecked" title="Détruire l'indicateur"></span></a> <?php else : ?> - <span class="icon icon-retirer" style="color:lightgray"></span> + <span class="icon icon-unchecked" style="color:lightgray"></span> <?php endif; ?> -- GitLab