From 5745cd0bf471771ae532efa2b7cdc15a3530679f Mon Sep 17 00:00:00 2001 From: Yannick ROGER Date: Mon, 13 Oct 2014 11:53:14 +0200 Subject: [PATCH] EZP-22654: Section create and edit --- Controller/PjaxController.php | 16 +- Controller/SectionController.php | 197 ++++++++++++++++++-- Controller/SystemInfoController.php | 13 +- Entity/EnrichedSection.php | 63 +++++++ Entity/Section.php | 37 ++++ Form/Type/SectionType.php | 37 ++++ Helper/SectionHelper.php | 44 ++++- Helper/SectionHelperInterface.php | 57 +++++- Resources/config/routing.yml | 19 +- Resources/config/services.yml | 26 ++- Resources/translations/section.en.xlf | 24 +++ Resources/translations/validators.en.xlf | 19 ++ Resources/views/Section/create.html.twig | 20 ++ Resources/views/Section/edit.html.twig | 24 +++ Resources/views/Section/list.html.twig | 6 +- Resources/views/Section/not_found.html.twig | 18 ++ 16 files changed, 568 insertions(+), 52 deletions(-) create mode 100644 Entity/EnrichedSection.php create mode 100644 Entity/Section.php create mode 100644 Form/Type/SectionType.php create mode 100644 Resources/translations/validators.en.xlf create mode 100644 Resources/views/Section/create.html.twig create mode 100644 Resources/views/Section/edit.html.twig create mode 100644 Resources/views/Section/not_found.html.twig diff --git a/Controller/PjaxController.php b/Controller/PjaxController.php index a5c3a5e5f..c24ecad28 100644 --- a/Controller/PjaxController.php +++ b/Controller/PjaxController.php @@ -10,9 +10,23 @@ use eZ\Publish\Core\MVC\Symfony\Security\User as CoreUser; use eZ\Bundle\EzPublishCoreBundle\Controller; +use Symfony\Component\HttpFoundation\Response; class PjaxController extends Controller { + /** + * To be used when access is denied to a user + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function accessDeniedAction() + { + $response = new Response(); + $response->setStatusCode( $this->getNoAccessStatusCode() ); + + return $response; + } + /** * Returns the HTTP status code to use when the user does not have access to * a resource so that the JS code can detect if the user needs to be @@ -37,7 +51,7 @@ private function isAnonymous() !$user || ( $user instanceof CoreUser - && $user->id == $this->getConfigResolver()->getParameter( "anonymous_user_id" ) + && $user->getAPIUser()->id == $this->getConfigResolver()->getParameter( "anonymous_user_id" ) ) ); } diff --git a/Controller/SectionController.php b/Controller/SectionController.php index ae60e7ac7..fc2eeaa8b 100644 --- a/Controller/SectionController.php +++ b/Controller/SectionController.php @@ -8,21 +8,51 @@ namespace EzSystems\PlatformUIBundle\Controller; +use eZ\Publish\API\Repository\Exceptions\NotFoundException; use eZ\Publish\API\Repository\Exceptions\UnauthorizedException; -use Symfony\Component\HttpFoundation\Response; -use EzSystems\PlatformUIBundle\Controller\PjaxController; +use EzSystems\PlatformUIBundle\Entity\Section; +use eZ\Bundle\EzPublishCoreBundle\Controller; +use EzSystems\PlatformUIBundle\Form\Type\SectionType; +use Symfony\Component\HttpFoundation\Request; use EzSystems\PlatformUIBundle\Helper\SectionHelperInterface; +use eZ\Publish\API\Repository\Exceptions\InvalidArgumentException; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\RouterInterface; +use Symfony\Component\Translation\TranslatorInterface; -class SectionController extends PjaxController +class SectionController extends Controller { /** - * @var EzSystems\PlatformUIBundle\Helper\SectionHelperInterface + * @var \EzSystems\PlatformUIBundle\Helper\SectionHelperInterface */ protected $sectionHelper; - public function __construct( SectionHelperInterface $sectionHelper ) + /** + * @var \EzSystems\PlatformUIBundle\Form\Type\SectionType + */ + protected $sectionType; + + /** + * @var \Symfony\Component\Routing\RouterInterface + */ + private $router; + + /** + * @var \Symfony\Component\Translation\TranslatorInterface + */ + private $translator; + + public function __construct( + SectionHelperInterface $sectionHelper, + SectionType $sectionType, + RouterInterface $router, + TranslatorInterface $translator + ) { $this->sectionHelper = $sectionHelper; + $this->sectionType = $sectionType; + $this->router = $router; + $this->translator = $translator; } /** @@ -32,7 +62,6 @@ public function __construct( SectionHelperInterface $sectionHelper ) */ public function listAction() { - $response = new Response(); try { return $this->render( @@ -40,25 +69,22 @@ public function listAction() array( 'sectionInfoList' => $this->sectionHelper->getSectionList(), 'canCreate' => $this->sectionHelper->canCreate(), - ), - $response + ) ); } catch ( UnauthorizedException $e ) { - $response->setStatusCode( $this->getNoAccessStatusCode() ); + return $this->forward( 'eZPlatformUIBundle:Pjax:accessDenied' ); } - return $response; } /** * Renders the view of a section - * @param int $sectionId + * @param mixed $sectionId * @return \Symfony\Component\HttpFoundation\Response */ public function viewAction( $sectionId ) { - $response = new Response(); try { $section = $this->sectionHelper->loadSection( $sectionId ); @@ -68,14 +94,153 @@ public function viewAction( $sectionId ) array( 'section' => $section, 'contentCount' => $contentCount, - ), - $response + ) ); } catch ( UnauthorizedException $e ) { - $response->setStatusCode( $this->getNoAccessStatusCode() ); + return $this->forward( 'eZPlatformUIBundle:Pjax:accessDenied' ); } - return $response; + } + + /** + * Displays the create form and processes it once submitted. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function createAction( Request $request) + { + $section = new Section(); + + $form = $this->createForm( + $this->sectionType, + $section, + array( + 'action' => $this->router->generate( 'admin_sectioncreate' ), + ) + ); + + $form->handleRequest( $request ); + + if ( $form->isValid() ) + { + try + { + $newSection = $this->sectionHelper->createSection( $section ); + + return $this->redirect( + $this->generateUrl( + 'admin_sectionview', + array( 'sectionId' => $newSection->id ) + ) + ); + } + catch ( UnauthorizedException $e ) + { + return $this->forward( 'eZPlatformUIBundle:Pjax:accessDenied' ); + } + catch ( InvalidArgumentException $e ) + { + $this->addAlreadyExistErrorMessage(); + } + } + + return $this->render( + 'eZPlatformUIBundle:Section:create.html.twig', + array( 'form' => $form->createView() ) + ); + } + + /** + * Displays the edit form and processes it once submitted. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * @param mixed $sectionId + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function editAction( Request $request, $sectionId ) + { + try + { + $sectionToUpdate = $this->sectionHelper->loadSection( $sectionId ); + } + catch ( UnauthorizedException $e ) + { + return $this->forward( 'eZPlatformUIBundle:Pjax:accessDenied' ); + } + catch ( NotFoundException $e ) + { + $response = new Response(); + $response->setStatusCode( 404 ); + + return $this->render( + 'eZPlatformUIBundle:Section:not_found.html.twig', + array( 'sectionId' => $sectionId ), + $response + ); + } + + // Loading API data + $section = new Section(); + $section->identifier = $sectionToUpdate->identifier; + $section->name = $sectionToUpdate->name; + + $form = $this->createForm( + $this->sectionType, + $section, + array( + 'action' => $this->router->generate( + 'admin_sectionedit', array( 'sectionId' => $sectionId ) + ) + ) + ); + + $form->handleRequest( $request ); + + if ( $form->isValid() ) + { + try + { + $updatedSection = $this->sectionHelper->updateSection( $sectionToUpdate, $section ); + + return $this->redirect( + $this->generateUrl( + 'admin_sectionview', + array( 'sectionId' => $updatedSection->id ) + ) + ); + } + catch ( UnauthorizedException $e ) + { + return $this->forward( 'eZPlatformUIBundle:Pjax:accessDenied' ); + } + catch ( InvalidArgumentException $e ) + { + $this->addAlreadyExistErrorMessage(); + } + } + + return $this->render( + 'eZPlatformUIBundle:Section:edit.html.twig', + array( 'form' => $form->createView() ) + ); + } + + /** + * Adds a "Section already exists" message to the flashbag. + */ + private function addAlreadyExistErrorMessage() + { + $this->get( 'session' )->getFlashBag()->add( + 'error', + $this->translator->trans( + 'section.error.id_already_exist', + array(), + 'section' + ) + ); } } diff --git a/Controller/SystemInfoController.php b/Controller/SystemInfoController.php index fc5d3714c..08ed8f85b 100644 --- a/Controller/SystemInfoController.php +++ b/Controller/SystemInfoController.php @@ -10,11 +10,11 @@ use eZ\Publish\Core\MVC\Symfony\Security\Authorization\Attribute as AuthorizationAttribute; use Symfony\Component\HttpFoundation\Response; +use eZ\Bundle\EzPublishCoreBundle\Controller; use Symfony\Component\Security\Core\Exception\AccessDeniedException; -use EzSystems\PlatformUIBundle\Controller\PjaxController; use EzSystems\PlatformUIBundle\Helper\SystemInfoHelperInterface; -class SystemInfoController extends PjaxController +class SystemInfoController extends Controller { /** * @var \EzSystems\PlatformUIBundle\Helper\SystemInfoHelperInterface @@ -33,11 +33,9 @@ public function __construct( SystemInfoHelperInterface $systemInfoHelper ) */ public function infoAction() { - $response = new Response(); if ( !$this->hasAccess() ) { - $response->setStatusCode( $this->getNoAccessStatusCode() ); - return $response; + return $this->forward( 'eZPlatformUIBundle:Pjax:accessDenied' ); } return $this->render( @@ -45,14 +43,15 @@ public function infoAction() array( 'ezplatformInfo' => $this->systemInfoHelper->getEzPlatformInfo(), 'systemInfo' => $this->systemInfoHelper->getSystemInfo(), - ), - $response + ) ); } /** * Renders a PHP info page * + * @throws \Symfony\Component\Security\Core\Exception\AccessDeniedException + * * @return \Symfony\Component\HttpFoundation\Response */ public function phpinfoAction() diff --git a/Entity/EnrichedSection.php b/Entity/EnrichedSection.php new file mode 100644 index 000000000..87f74aabc --- /dev/null +++ b/Entity/EnrichedSection.php @@ -0,0 +1,63 @@ +section = $section; + $this->contentCount = $contentCount; + $this->canEdit = $canEdit; + $this->canDelete = $canDelete; + $this->canAssign = $canAssign; + } +} diff --git a/Entity/Section.php b/Entity/Section.php new file mode 100644 index 000000000..da68577c9 --- /dev/null +++ b/Entity/Section.php @@ -0,0 +1,37 @@ +add( 'name', 'text' ) + ->add( 'identifier', 'text' ) + ->add( 'save', 'submit' ); + } + + public function getName() + { + return 'section'; + } + + public function setDefaultOptions( OptionsResolverInterface $resolver ) + { + $resolver->setDefaults( + array( 'data_class' => 'EzSystems\PlatformUIBundle\Entity\Section' ) + ); + } +} diff --git a/Helper/SectionHelper.php b/Helper/SectionHelper.php index b1d50766d..72cbd2d34 100644 --- a/Helper/SectionHelper.php +++ b/Helper/SectionHelper.php @@ -8,21 +8,22 @@ namespace EzSystems\PlatformUIBundle\Helper; -use EzSystems\PlatformUIBundle\Helper\SectionHelperInterface; use eZ\Publish\API\Repository\SectionService; use eZ\Publish\Core\MVC\Symfony\Security\Authorization\Attribute as AuthorizationAttribute; +use EzSystems\PlatformUIBundle\Entity\EnrichedSection; use Symfony\Component\Security\Core\SecurityContextInterface; use eZ\Publish\API\Repository\Values\Content\Section; +use EzSystems\PlatformUIBundle\Entity\Section as SectionEntity; class SectionHelper implements SectionHelperInterface { /** - * @var eZ\Publish\API\Repository\SectionService + * @var \eZ\Publish\API\Repository\SectionService */ protected $sectionService; /** - * @var Symfony\Component\Security\Core\SecurityContextInterface + * @var \Symfony\Component\Security\Core\SecurityContextInterface */ protected $securityContext; @@ -43,14 +44,15 @@ public function getSectionList() $list = array(); foreach ( $sections as $section ) { - $list[] = array( - 'section' => $section, - 'contentCount' => $this->sectionService->countAssignedContents( $section ), - 'canEdit' => $this->canUser( 'edit' ), - 'canDelete' => $this->canUser( 'edit' ), - 'canAssign' => $this->canUser( 'assign' ), + $list[] = new EnrichedSection( + $section, + $this->sectionService->countAssignedContents( $section ), + $this->canUser( 'edit' ), + $this->canUser( 'edit' ), + $this->canUser( 'assign' ) ); } + return $list; } @@ -94,4 +96,28 @@ public function contentCount( Section $section ) { return $this->sectionService->countAssignedContents( $section ); } + + /** + * {@inheritDoc} + */ + public function createSection( SectionEntity $section ) + { + $sectionCreateStruct = $this->sectionService->newSectionCreateStruct(); + $sectionCreateStruct->identifier = $section->identifier; + $sectionCreateStruct->name = $section->name; + + return $this->sectionService->createSection( $sectionCreateStruct ); + } + + /** + * {@inheritDoc} + */ + public function updateSection( Section $sectionToUpdate, SectionEntity $section) + { + $sectionUpdateStruct = $this->sectionService->newSectionUpdateStruct(); + $sectionUpdateStruct->identifier = $section->identifier; + $sectionUpdateStruct->name = $section->name; + + return $this->sectionService->updateSection( $sectionToUpdate, $sectionUpdateStruct ); + } } diff --git a/Helper/SectionHelperInterface.php b/Helper/SectionHelperInterface.php index cbf1c7982..42d30ca14 100644 --- a/Helper/SectionHelperInterface.php +++ b/Helper/SectionHelperInterface.php @@ -9,19 +9,21 @@ namespace EzSystems\PlatformUIBundle\Helper; use eZ\Publish\API\Repository\Values\Content\Section; +use EzSystems\PlatformUIBundle\Entity\Section as SectionEntity; +/** + * Interface SectionHelperInterface + * + * Provides utility methods to handle section stored in the API + * + * @package EzSystems\PlatformUIBundle\Helper + */ interface SectionHelperInterface { /** - * Returns the section list as an array. Each element of the returned array - * is an associated array containing the following entries: - * - section: the Section object - * - contentCount: the number of contents the section is assigned to - * - canEdit: whether the current user can edit the section - * - canDelete: whether the current user can delete the section - * - canAssign: whether the current user can assign the section to some contents - * - * @return array + * Returns the section list + * + * @return \EzSystems\PlatformUIBundle\Entity\EnrichedSection[] */ public function getSectionList(); @@ -34,7 +36,12 @@ public function canCreate(); /** * Returns a section - * @param int $sectionId + * + * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if section could not be found + * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to read a section + * + * @param mixed $sectionId + * * @return \eZ\Publish\API\Repository\Values\Content\Section */ public function loadSection( $sectionId ); @@ -45,4 +52,34 @@ public function loadSection( $sectionId ); * @return int */ public function contentCount( Section $section ); + + /** + * Creates a new Section in the content repository + * + * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user is + * not allowed to create a section + * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If the new identifier + * already exists + * + * @param \EzSystems\PlatformUIBundle\Entity\Section $section + * + * @return \eZ\Publish\API\Repository\Values\Content\Section The newly created section + */ + public function createSection( SectionEntity $section ); + + /** + * Updates a Section in the content repository + * + * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user is + * not allowed to update a section + * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If the new identifier + * already exists + * + * @param \eZ\Publish\API\Repository\Values\Content\Section $sectionToUpdate + * @param \EzSystems\PlatformUIBundle\Entity\Section $section + * + * @return \eZ\Publish\API\Repository\Values\Content\Section The updated section + */ + public function updateSection( Section $sectionToUpdate, SectionEntity $section ); + } diff --git a/Resources/config/routing.yml b/Resources/config/routing.yml index 0f4b8dcb4..8a0815d4a 100644 --- a/Resources/config/routing.yml +++ b/Resources/config/routing.yml @@ -30,7 +30,7 @@ admin_phpinfo: methods: [GET] admin_sectionlist: - pattern: /pjax/section/list + path: /pjax/section/list defaults: _controller: ezsystems.platformui.controller.section:listAction methods: [GET] @@ -42,3 +42,20 @@ admin_sectionview: methods: [GET] requirements: sectionId: \d+ + +admin_accessdenied: + path: /pjax/accessdenied + defaults: + _controller: ezsystems.platformui.controller.pjax:accessDeniedAction + +admin_sectioncreate: + path: /pjax/section/create + defaults: + _controller: ezsystems.platformui.controller.section:createAction + +admin_sectionedit: + path: /pjax/section/edit/{sectionId} + defaults: + _controller: ezsystems.platformui.controller.section:editAction + requirements: + sectionId: \d+ diff --git a/Resources/config/services.yml b/Resources/config/services.yml index c9ad9fd97..5b36a977a 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -6,6 +6,8 @@ parameters: ezsystems.platformui.helper.section.class: EzSystems\PlatformUIBundle\Helper\SectionHelper ezsystems.platformui.controller.section.class: EzSystems\PlatformUIBundle\Controller\SectionController ezsystems.platformui.controller.template.class: EzSystems\PlatformUIBundle\Controller\TemplateController + ezsystems.platformui.form.type.section.class: EzSystems\PlatformUIBundle\Form\Type\SectionType + ezsystems.platformui.controller.pjax.class: EzSystems\PlatformUIBundle\Controller\PjaxController services: ezsystems.platformui.twig.yui_extension: @@ -36,14 +38,28 @@ services: - @ezsystems.platformui.helper.systeminfo parent: ezpublish.controller.base - ezsystems.platformui.helper.section: - class: %ezsystems.platformui.helper.section.class% - arguments: - - @ezpublish.api.service.section - - @security.context + ezsystems.platformui.controller.pjax: + class: %ezsystems.platformui.controller.pjax.class% + parent: ezpublish.controller.base + ## Section related services ezsystems.platformui.controller.section: class: %ezsystems.platformui.controller.section.class% arguments: - @ezsystems.platformui.helper.section + - @ezsystems.platformui.form.type.section + - @router + - @translator + - @session parent: ezpublish.controller.base + + ezsystems.platformui.helper.section: + class: %ezsystems.platformui.helper.section.class% + arguments: + - @ezpublish.api.service.section + - @security.context + + ezsystems.platformui.form.type.section: + class: %ezsystems.platformui.form.type.section.class% + tags: + - { name: form.section, alias: section } diff --git a/Resources/translations/section.en.xlf b/Resources/translations/section.en.xlf index 909b40e23..1052d28e3 100644 --- a/Resources/translations/section.en.xlf +++ b/Resources/translations/section.en.xlf @@ -50,6 +50,14 @@ section.content.translate Contents in this section + + section.create.title + Creating a new section + + + section.edit.title + Editing the section "%sectionName%" + section.name.label Section name: @@ -62,6 +70,22 @@ section.id.label Section ID: + + section.label.edit + Section edit + + + section.error.id_already_exist + A section with this identifier already exists, please enter a different one + + + section.not_found.title + Section can not be found + + + section.not_found.message + The section with the id "%sectionId%" can not be found. + diff --git a/Resources/translations/validators.en.xlf b/Resources/translations/validators.en.xlf new file mode 100644 index 000000000..ca786d215 --- /dev/null +++ b/Resources/translations/validators.en.xlf @@ -0,0 +1,19 @@ + + + + + + section.validator.identifier.format + Identifier should consist of letters, numbers or '_' with letter prefix. + + + section.validator.identifier.not_blank + The section identifier can not be empty. + + + section.validator.name.not_blank + The section name can not be empty. + + + + diff --git a/Resources/views/Section/create.html.twig b/Resources/views/Section/create.html.twig new file mode 100644 index 000000000..8d71cd3d7 --- /dev/null +++ b/Resources/views/Section/create.html.twig @@ -0,0 +1,20 @@ +{% extends "eZPlatformUIBundle::pjax.html.twig" %} + +{% trans_default_domain "section" %} + +{% block title %}{{ 'section.create.title'|trans }}{% endblock %} + +{% block content %} +
+

{{ 'section.create.title'|trans }}

+
+ + + + {{ form(form) }} + +{% endblock %} diff --git a/Resources/views/Section/edit.html.twig b/Resources/views/Section/edit.html.twig new file mode 100644 index 000000000..04cd332ca --- /dev/null +++ b/Resources/views/Section/edit.html.twig @@ -0,0 +1,24 @@ +{% extends "eZPlatformUIBundle::pjax.html.twig" %} + +{% trans_default_domain "section" %} + +{% block title %} + {{ 'section.edit.title'|trans({ '%sectionName%': form.vars.value.name }) }} +{% endblock %} + +{% block content %} +
+

+ {{ 'section.edit.title'|trans({ '%sectionName%': form.vars.value.name }) }} +

+
+ + + + {{ form(form) }} + +{% endblock %} diff --git a/Resources/views/Section/list.html.twig b/Resources/views/Section/list.html.twig index a0e40c2cb..c7d3abe5f 100644 --- a/Resources/views/Section/list.html.twig +++ b/Resources/views/Section/list.html.twig @@ -8,7 +8,7 @@
-
+ @@ -39,7 +39,7 @@ {% endfor %} @@ -47,7 +47,7 @@
- +

- {{ 'section.new'|trans }} + {{ 'section.new'|trans }}

diff --git a/Resources/views/Section/not_found.html.twig b/Resources/views/Section/not_found.html.twig new file mode 100644 index 000000000..4601f2689 --- /dev/null +++ b/Resources/views/Section/not_found.html.twig @@ -0,0 +1,18 @@ +{% extends "eZPlatformUIBundle::pjax.html.twig" %} + +{% trans_default_domain "section" %} + +{% block title %}{{ 'section.not_found.title'|trans }}{% endblock %} + +{% block content %} +
+

{{ 'section.not_found.title'|trans }}

+
+ + + +{% endblock %}