adding the possibility to remove activities

fix #28
This commit is contained in:
Julien Fastré 2016-06-08 21:26:30 +02:00
parent dfaa4b0968
commit 1e476b39da
10 changed files with 152 additions and 25 deletions

View File

@ -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()
));
}
/**

View File

@ -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);
}
}

View File

@ -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)
)
));
}

View File

@ -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]

View File

@ -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é
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.

View File

@ -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 %}

View File

@ -51,9 +51,18 @@
<li>
<a href="{{ path('chill_activity_activity_show', { 'id': activity.id, 'person_id': person.id }) }}" class="sc-button">{{ 'show'|trans|capitalize }}</a>
</li>
{% if is_granted('CHILL_ACTIVITY_UPDATE', activity) %}
<li>
<a href="{{ path('chill_activity_activity_edit', { 'id': activity.id, 'person_id': person.id }) }}" class="sc-button bt-update">{{ 'Edit' | trans }}</a>
</li>
{% endif %}
{% if is_granted('CHILL_ACTIVITY_DELETE', activity) %}
<li>
<a href="{{ path('chill_activity_activity_delete', { 'id': activity.id, 'person_id' : person.id } ) }}" class="sc-button bt-delete">
{{ 'Delete'|trans }}
</a>
</li>
{% endif %}
</td>
</tr>
{% endfor %}

View File

@ -40,7 +40,19 @@
</dl>
<a class="sc-button bt-update" href="{{ path('chill_activity_activity_edit', { 'id': entity.id, 'person_id': person.id }) }}">
<i class="fa fa-pencil"></i> {{ 'Edit the activity'|trans }}
</a>
<ul class="record_actions">
<li>
<a class="sc-button bt-update" href="{{ path('chill_activity_activity_edit', { 'id': entity.id, 'person_id': person.id }) }}">
<i class="fa fa-pencil"></i> {{ 'Edit the activity'|trans }}
</a>
</li>
{% if is_granted('CHILL_ACTIVITY_DELETE', entity) %}
<li>
<a href="{{ path('chill_activity_activity_delete', { 'id': entity.id, 'person_id' : person.id } ) }}" class="sc-button bt-delete">
{{ 'Delete'|trans }}
</a>
</li>
{% endif %}
</ul>
{% endblock personcontent %}

View File

@ -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()

View File

@ -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)];
}