diff --git a/Controller/ActivityController.php b/Controller/ActivityController.php index f7a6dc80a..b0c09bc2e 100644 --- a/Controller/ActivityController.php +++ b/Controller/ActivityController.php @@ -309,30 +309,68 @@ class ActivityController extends Controller 'delete_form' => $deleteForm->createView(), )); } + /** * Deletes a Activity entity. * */ - public function deleteAction(Request $request, $id) + public function deleteAction(Request $request, $id, $person_id) { - $form = $this->createDeleteForm($id); - $form->handleRequest($request); + $em = $this->getDoctrine()->getManager(); + + /* @var $activity Activity */ + $activity = $em->getRepository('ChillActivityBundle:Activity') + ->find($id); + $person = $activity->getPerson(); - if ($form->isValid()) { - $em = $this->getDoctrine()->getManager(); - $entity = $em->getRepository('ChillActivityBundle:Activity')->find($id); - - if (!$entity) { - throw $this->createNotFoundException('Unable to find Activity entity.'); - } - - $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity); - - $em->remove($entity); - $em->flush(); + if (!$activity) { + throw $this->createNotFoundException('Unable to find Activity entity.'); } + + $this->denyAccessUnlessGranted('CHILL_ACTIVITY_DELETE', $activity); + + $form = $this->createDeleteForm($id, $person); + + if ($request->getMethod() === Request::METHOD_DELETE) { + $form->handleRequest($request); - return $this->redirect($this->generateUrl('activity')); + if ($form->isValid()) { + $logger = $this->get('chill.main.logger'); + + $logger->notice("An activity has been removed", array( + 'by_user' => $this->getUser()->getUsername(), + 'activity_id' => $activity->getId(), + 'person_id' => $activity->getPerson()->getId(), + 'remark' => $activity->getRemark(), + 'scope_id' => $activity->getScope()->getId(), + 'reasons_ids' => $activity->getReasons() + ->map(function ($ar) { return $ar->getId(); }) + ->toArray(), + 'type_id' => $activity->getType()->getId(), + 'duration' => $activity->getDurationTime()->format('U'), + 'date' => $activity->getDate()->format('Y-m-d'), + 'attendee' => $activity->getAttendee() + )); + + $em->remove($activity); + $em->flush(); + + $this->addFlash('success', $this->get('translator') + ->trans("The activity has been successfully removed.")); + + return $this->redirect($this->generateUrl( + 'chill_activity_activity_list', array( + 'person_id' => $person_id + ))); + } + } + + return $this->render('ChillActivityBundle:Activity:confirm_delete.html.twig', array( + 'activity' => $activity, + 'delete_form' => $form->createView() + )); + + } /** diff --git a/DataFixtures/ORM/LoadActivitytACL.php b/DataFixtures/ORM/LoadActivitytACL.php index e9d2d3092..e423f39f6 100644 --- a/DataFixtures/ORM/LoadActivitytACL.php +++ b/DataFixtures/ORM/LoadActivitytACL.php @@ -61,7 +61,7 @@ class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterfac break; } - printf("Adding CHILL_ACTIVITY_UPDATE & CHILL_ACTIVITY_CREATE to %s " + printf("Adding CHILL_ACTIVITY_UPDATE & CHILL_ACTIVITY_CREATE & CHILL_ACTIVITY_DELETE to %s " . "permission group, scope '%s' \n", $permissionsGroup->getName(), $scope->getName()['en']); $roleScopeUpdate = (new RoleScope()) @@ -72,8 +72,14 @@ class LoadActivitytACL extends AbstractFixture implements OrderedFixtureInterfac ->setRole('CHILL_ACTIVITY_CREATE') ->setScope($scope); $permissionsGroup->addRoleScope($roleScopeCreate); + $roleScopeDelete = (new RoleScope()) + ->setRole('CHILL_ACTIVITY_DELETE') + ->setScope($scope); + $permissionsGroup->addRoleScope($roleScopeDelete); + $manager->persist($roleScopeUpdate); $manager->persist($roleScopeCreate); + $manager->persist($roleScopeDelete); } } diff --git a/DependencyInjection/ChillActivityExtension.php b/DependencyInjection/ChillActivityExtension.php index d5a96f21b..20bcbbfed 100644 --- a/DependencyInjection/ChillActivityExtension.php +++ b/DependencyInjection/ChillActivityExtension.php @@ -79,7 +79,8 @@ class ChillActivityExtension extends Extension implements PrependExtensionInterf 'role_hierarchy' => array( ActivityVoter::UPDATE => array(ActivityVoter::SEE), ActivityVoter::CREATE => array(ActivityVoter::SEE), - ActivityVoter::SEE => array(ActivityStatsVoter::STATS) + ActivityVoter::SEE => array(ActivityStatsVoter::STATS), + ActivityVoter::DELETE => array(ActivityVoter::SEE) ) )); } diff --git a/Resources/config/routing/activity.yml b/Resources/config/routing/activity.yml index b2bc76201..6d287eec7 100644 --- a/Resources/config/routing/activity.yml +++ b/Resources/config/routing/activity.yml @@ -37,4 +37,4 @@ chill_activity_activity_update: chill_activity_activity_delete: path: /{_locale}/person/{person_id}/activity/{id}/delete defaults: { _controller: "ChillActivityBundle:Activity:delete" } - methods: [POST, DELETE] + methods: [GET, POST, DELETE] diff --git a/Resources/translations/messages.fr.yml b/Resources/translations/messages.fr.yml index 9660908e0..8672649f3 100644 --- a/Resources/translations/messages.fr.yml +++ b/Resources/translations/messages.fr.yml @@ -53,6 +53,7 @@ Choose a type: Choisir un type CHILL_ACTIVITY_CREATE: Créer une activité CHILL_ACTIVITY_UPDATE: Modifier une activité CHILL_ACTIVITY_SEE: Voir une activité +CHILL_ACTIVITY_DELETE: Supprimer une activité # admin Activity configuration menu: Configuration des activités @@ -86,4 +87,9 @@ ActivityType list: Types d'activités Create a new activity type: Créer un nouveau type d'activité ActivityType creation: Nouveau type d'activité ActivityType: Type d'activité -ActivityType edit: Modifier une activité \ No newline at end of file +ActivityType edit: Modifier une activité + +# activity delete +Remove activity: Supprimer une activité +Are you sure you want to remove the activity about "%name%" ?: Êtes-vous sûr de vouloir supprimer une activité qui concerne "%name%" ? +The activity has been successfully removed.: L'activité a été supprimée. \ No newline at end of file diff --git a/Resources/views/Activity/confirm_delete.html.twig b/Resources/views/Activity/confirm_delete.html.twig new file mode 100644 index 000000000..3d3f9b0ae --- /dev/null +++ b/Resources/views/Activity/confirm_delete.html.twig @@ -0,0 +1,19 @@ +{% extends "ChillPersonBundle::layout.html.twig" %} + +{% set activeRouteKey = 'chill_activity_activity_list' %} +{% set person = activity.person %} + +{% block title 'Remove activity'|trans %} + +{% block personcontent %} + +{{ include('ChillMainBundle:Util:confirmation_template.html.twig', + { + 'title' : 'Remove activity'|trans, + 'confirm_question' : 'Are you sure you want to remove the activity about "%name%" ?'|trans({ '%name%' : person.firstname ~ ' ' ~ person.lastname } ), + 'cancel_route' : 'chill_activity_activity_list', + 'cancel_parameters' : { 'person_id' : activity.person.id, 'id' : activity.id }, + 'form' : delete_form + } ) }} + +{% endblock %} diff --git a/Resources/views/Activity/list.html.twig b/Resources/views/Activity/list.html.twig index cfaf9cf89..16f9ebed9 100644 --- a/Resources/views/Activity/list.html.twig +++ b/Resources/views/Activity/list.html.twig @@ -51,9 +51,18 @@
  • {{ 'show'|trans|capitalize }}
  • + {% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
  • {{ 'Edit' | trans }}
  • + {% endif %} + {% if is_granted('CHILL_ACTIVITY_DELETE', activity) %} +
  • + + {{ 'Delete'|trans }} + +
  • + {% endif %} {% endfor %} diff --git a/Resources/views/Activity/show.html.twig b/Resources/views/Activity/show.html.twig index 292a35aa4..db769ee18 100644 --- a/Resources/views/Activity/show.html.twig +++ b/Resources/views/Activity/show.html.twig @@ -40,7 +40,19 @@ - - {{ 'Edit the activity'|trans }} - + + {% endblock personcontent %} diff --git a/Security/Authorization/ActivityVoter.php b/Security/Authorization/ActivityVoter.php index 0e9ffc2ed..d1318a485 100644 --- a/Security/Authorization/ActivityVoter.php +++ b/Security/Authorization/ActivityVoter.php @@ -33,6 +33,7 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleInterface const CREATE = 'CHILL_ACTIVITY_CREATE'; const SEE = 'CHILL_ACTIVITY_SEE'; const UPDATE = 'CHILL_ACTIVITY_UPDATE'; + const DELETE = 'CHILL_ACTIVITY_DELETE'; /** * @@ -47,7 +48,7 @@ class ActivityVoter extends AbstractChillVoter implements ProvideRoleInterface protected function getSupportedAttributes() { - return array(self::CREATE, self::SEE, self::UPDATE); + return array(self::CREATE, self::SEE, self::UPDATE, self::DELETE); } protected function getSupportedClasses() diff --git a/Tests/Controller/ActivityControllerTest.php b/Tests/Controller/ActivityControllerTest.php index 81c280703..a9f840190 100644 --- a/Tests/Controller/ActivityControllerTest.php +++ b/Tests/Controller/ActivityControllerTest.php @@ -154,6 +154,22 @@ class ActivityControllerTest extends WebTestCase $this->assertGreaterThan(0, $crawler->filter('dd:contains("Foo")')->count(), 'Missing element dd:contains("Foo")'); + + // delete the actvity + $crawler = $client->click($crawler->selectLink("Supprimer")->link()); + + $button = $crawler->selectButton('Supprimer'); + + $form = $button->form(); + + $client->submit($form); + $this->assertTrue($client->getResponse()->isRedirect(sprintf('/en/person/%d/activity/', + $person->getId()))); + + $crawler = $client->followRedirect(); + + $this->assertNotContains('January 25, 2015', $crawler->text()); + } /** @@ -230,10 +246,29 @@ class ActivityControllerTest extends WebTestCase ->getRepository('ChillMainBundle:Center') ->findOneByName($centerName); - $reachableScopes = static::$kernel->getContainer() + // get scope reachable by both role UPDATE and DELETE + $reachableScopesUpdate = static::$kernel->getContainer() ->get('chill.main.security.authorization.helper') ->getReachableScopes($user, new Role('CHILL_ACTIVITY_UPDATE'), $center); + $reachableScopesDelete = static::$kernel->getContainer() + ->get('chill.main.security.authorization.helper') + ->getReachableScopes($user, new Role('CHILL_ACTIVITY_DELETE'), + $center); + $reachableScopesId = array_intersect( + array_map(function ($s) { return $s->getId(); }, $reachableScopesDelete), + array_map(function ($s) { return $s->getId(); }, $reachableScopesUpdate) + ); + if (count($reachableScopesId) === 0) { + throw new \RuntimeException("there are not scope reachable for " + . "both CHILL_ACTIVITY_UPDATE and CHILL_ACTIVITY_DELETE"); + } + + foreach($reachableScopesUpdate as $scope) { + if (in_array($scope->getId(), $reachableScopesId)) { + $reachableScopes[] = $scope; + } + } return $reachableScopes[array_rand($reachableScopes)]; }