Add CommentEmbeddable to Activity : remoke remark field (Ref #21)

This commit is contained in:
Jean-Francois Monfort 2021-03-11 14:27:46 +01:00
parent cde3c900df
commit f35cb679b7
14 changed files with 240 additions and 210 deletions

View File

@ -41,22 +41,22 @@ use Chill\ActivityBundle\Form\ActivityType;
*/ */
class ActivityController extends AbstractController class ActivityController extends AbstractController
{ {
/** /**
* @var EventDispatcherInterface * @var EventDispatcherInterface
*/ */
protected $eventDispatcher; protected $eventDispatcher;
/** /**
* @var AuthorizationHelper * @var AuthorizationHelper
*/ */
protected $authorizationHelper; protected $authorizationHelper;
/** /**
* @var LoggerInterface * @var LoggerInterface
*/ */
protected $logger; protected $logger;
/** /**
* ActivityController constructor. * ActivityController constructor.
* *
@ -72,7 +72,7 @@ class ActivityController extends AbstractController
$this->authorizationHelper = $authorizationHelper; $this->authorizationHelper = $authorizationHelper;
$this->logger = $logger; $this->logger = $logger;
} }
/** /**
* Lists all Activity entities. * Lists all Activity entities.
* *
@ -97,13 +97,13 @@ class ActivityController extends AbstractController
array('person' => $person, 'scope' => $reachableScopes), array('person' => $person, 'scope' => $reachableScopes),
array('date' => 'DESC') array('date' => 'DESC')
); );
$event = new PrivacyEvent($person, array( $event = new PrivacyEvent($person, array(
'element_class' => Activity::class, 'element_class' => Activity::class,
'action' => 'list' 'action' => 'list'
)); ));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
return $this->render('ChillActivityBundle:Activity:list.html.twig', array( return $this->render('ChillActivityBundle:Activity:list.html.twig', array(
'activities' => $activities, 'activities' => $activities,
'person' => $person 'person' => $person
@ -241,14 +241,14 @@ class ActivityController extends AbstractController
$this->denyAccessUnlessGranted('CHILL_ACTIVITY_SEE', $entity); $this->denyAccessUnlessGranted('CHILL_ACTIVITY_SEE', $entity);
$deleteForm = $this->createDeleteForm($id, $person); $deleteForm = $this->createDeleteForm($id, $person);
$event = new PrivacyEvent($person, array( $event = new PrivacyEvent($person, array(
'element_class' => Activity::class, 'element_class' => Activity::class,
'element_id' => $entity->getId(), 'element_id' => $entity->getId(),
'action' => 'show' 'action' => 'show'
)); ));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
return $this->render('ChillActivityBundle:Activity:show.html.twig', array( return $this->render('ChillActivityBundle:Activity:show.html.twig', array(
'person' => $person, 'person' => $person,
'entity' => $entity, 'entity' => $entity,
@ -281,7 +281,7 @@ class ActivityController extends AbstractController
$editForm = $this->createEditForm($entity); $editForm = $this->createEditForm($entity);
$deleteForm = $this->createDeleteForm($id, $person); $deleteForm = $this->createDeleteForm($id, $person);
$event = new PrivacyEvent($person, array( $event = new PrivacyEvent($person, array(
'element_class' => Activity::class, 'element_class' => Activity::class,
'element_id' => $entity->getId(), 'element_id' => $entity->getId(),
@ -339,7 +339,7 @@ class ActivityController extends AbstractController
$deleteForm = $this->createDeleteForm($id, $person); $deleteForm = $this->createDeleteForm($id, $person);
$editForm = $this->createEditForm($entity); $editForm = $this->createEditForm($entity);
$editForm->handleRequest($request); $editForm->handleRequest($request);
$event = new PrivacyEvent($person, array( $event = new PrivacyEvent($person, array(
'element_class' => Activity::class, 'element_class' => Activity::class,
'element_id' => $entity->getId(), 'element_id' => $entity->getId(),
@ -356,7 +356,7 @@ class ActivityController extends AbstractController
$this->get('translator') $this->get('translator')
->trans('Success : activity updated!') ->trans('Success : activity updated!')
); );
return $this->redirect($this->generateUrl('chill_activity_activity_show', array('id' => $id, 'person_id' => $person_id))); return $this->redirect($this->generateUrl('chill_activity_activity_show', array('id' => $id, 'person_id' => $person_id)));
} }
@ -400,12 +400,12 @@ class ActivityController extends AbstractController
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isValid()) { if ($form->isValid()) {
$this->logger->notice("An activity has been removed", array( $this->logger->notice("An activity has been removed", array(
'by_user' => $this->getUser()->getUsername(), 'by_user' => $this->getUser()->getUsername(),
'activity_id' => $activity->getId(), 'activity_id' => $activity->getId(),
'person_id' => $activity->getPerson()->getId(), 'person_id' => $activity->getPerson()->getId(),
'remark' => $activity->getRemark(), 'comment' => $activity->getComment()->getComment(),
'scope_id' => $activity->getScope()->getId(), 'scope_id' => $activity->getScope()->getId(),
'reasons_ids' => $activity->getReasons() 'reasons_ids' => $activity->getReasons()
->map(function ($ar) { return $ar->getId(); }) ->map(function ($ar) { return $ar->getId(); })

View File

@ -2,20 +2,20 @@
/* /*
* Chill is a software for social workers * Chill is a software for social workers
* *
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS, * Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop> * <http://www.champs-libres.coop>, <info@champs-libres.coop>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the * published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version. * License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -41,25 +41,25 @@ use Symfony\Component\DependencyInjection\ContainerAwareInterface;
class LoadActivity extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface class LoadActivity extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface
{ {
use \Symfony\Component\DependencyInjection\ContainerAwareTrait; use \Symfony\Component\DependencyInjection\ContainerAwareTrait;
/** /**
* @var \Faker\Generator * @var \Faker\Generator
*/ */
private $faker; private $faker;
public function __construct() public function __construct()
{ {
$this->faker = FakerFactory::create('fr_FR'); $this->faker = FakerFactory::create('fr_FR');
} }
public function getOrder() public function getOrder()
{ {
return 16400; return 16400;
} }
/** /**
* Return a random scope * Return a random scope
* *
* @return \Chill\MainBundle\Entity\Scope * @return \Chill\MainBundle\Entity\Scope
*/ */
private function getRandomScope() private function getRandomScope()
@ -67,10 +67,10 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface, C
$scopeRef = LoadScopes::$references[array_rand(LoadScopes::$references)]; $scopeRef = LoadScopes::$references[array_rand(LoadScopes::$references)];
return $this->getReference($scopeRef); return $this->getReference($scopeRef);
} }
/** /**
* Return a random activityType * Return a random activityType
* *
* @return \Chill\ActivityBundle\Entity\ActivityType * @return \Chill\ActivityBundle\Entity\ActivityType
*/ */
private function getRandomActivityType() private function getRandomActivityType()
@ -78,27 +78,27 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface, C
$typeRef = LoadActivityType::$references[array_rand(LoadActivityType::$references)]; $typeRef = LoadActivityType::$references[array_rand(LoadActivityType::$references)];
return $this->getReference($typeRef); return $this->getReference($typeRef);
} }
/** /**
* Return a random activityReason * Return a random activityReason
* *
* @return \Chill\ActivityBundle\Entity\ActivityReason * @return \Chill\ActivityBundle\Entity\ActivityReason
*/ */
private function getRandomActivityReason(array $excludingIds) private function getRandomActivityReason(array $excludingIds)
{ {
$reasonRef = LoadActivityReason::$references[array_rand(LoadActivityReason::$references)]; $reasonRef = LoadActivityReason::$references[array_rand(LoadActivityReason::$references)];
if (in_array($this->getReference($reasonRef)->getId(), $excludingIds)) { if (in_array($this->getReference($reasonRef)->getId(), $excludingIds)) {
// we have a reason which should be excluded. Find another... // we have a reason which should be excluded. Find another...
return $this->getRandomActivityReason($excludingIds); return $this->getRandomActivityReason($excludingIds);
} }
return $this->getReference($reasonRef); return $this->getReference($reasonRef);
} }
/** /**
* Return a random user * Return a random user
* *
* @return \Chill\MainBundle\Entity\User * @return \Chill\MainBundle\Entity\User
*/ */
private function getRandomUser() private function getRandomUser()
@ -106,7 +106,7 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface, C
$userRef = array_rand(LoadUsers::$refs); $userRef = array_rand(LoadUsers::$refs);
return $this->getReference($userRef); return $this->getReference($userRef);
} }
public function newRandomActivity($person) public function newRandomActivity($person)
{ {
$activity = (new Activity()) $activity = (new Activity())
@ -117,24 +117,24 @@ class LoadActivity extends AbstractFixture implements OrderedFixtureInterface, C
->setType($this->getRandomActivityType()) ->setType($this->getRandomActivityType())
->setScope($this->getRandomScope()) ->setScope($this->getRandomScope())
->setAttendee($this->faker->boolean()) ->setAttendee($this->faker->boolean())
->setRemark('A remark'); ;
$usedId = array(); $usedId = array();
for ($i = 0; $i < rand(0, 4); $i++) { for ($i = 0; $i < rand(0, 4); $i++) {
$reason = $this->getRandomActivityReason($usedId); $reason = $this->getRandomActivityReason($usedId);
$usedId[] = $reason->getId(); $usedId[] = $reason->getId();
$activity->addReason($reason); $activity->addReason($reason);
} }
return $activity; return $activity;
} }
public function load(ObjectManager $manager) public function load(ObjectManager $manager)
{ {
$persons = $this->container->get('doctrine.orm.entity_manager') $persons = $this->container->get('doctrine.orm.entity_manager')
->getRepository('ChillPersonBundle:Person') ->getRepository('ChillPersonBundle:Person')
->findAll(); ->findAll();
foreach($persons as $person) { foreach($persons as $person) {
$activityNbr = rand(0,3); $activityNbr = rand(0,3);
for($i = 0; $i < $activityNbr; $i ++) { for($i = 0; $i < $activityNbr; $i ++) {

View File

@ -75,12 +75,6 @@ class Activity implements HasCenterInterface, HasScopeInterface
*/ */
private $durationTime; private $durationTime;
/**
* @var string
* @ORM\Column(type="text")
*/
private $remark;
/** /**
* @var boolean * @var boolean
* @ORM\Column(type="boolean") * @ORM\Column(type="boolean")
@ -204,29 +198,6 @@ class Activity implements HasCenterInterface, HasScopeInterface
return $this->durationTime; return $this->durationTime;
} }
/**
* Set remark
*
* @param string $remark
* @return Activity
*/
public function setRemark($remark)
{
$this->remark = $remark;
return $this;
}
/**
* Get remark
*
* @return string
*/
public function getRemark()
{
return $this->remark;
}
/** /**
* Set attendee * Set attendee
* *

View File

@ -93,10 +93,6 @@ class ActivityType extends AbstractType
'required' => true 'required' => true
)) ))
->add('durationTime', ChoiceType::class, $durationTimeOptions) ->add('durationTime', ChoiceType::class, $durationTimeOptions)
->add('remark', TextareaType::class, array(
'required' => false,
'empty_data' => ''
))
->add('attendee', ChoiceType::class, array( ->add('attendee', ChoiceType::class, array(
'expanded' => true, 'expanded' => true,
'required' => false, 'required' => false,

View File

@ -32,10 +32,9 @@
{{ form_row(edit_form.date) }} {{ form_row(edit_form.date) }}
{{ form_row(edit_form.durationTime) }} {{ form_row(edit_form.durationTime) }}
{{ form_row(edit_form.type) }} {{ form_row(edit_form.type) }}
{{ form_row(edit_form.remark) }}
{{ form_row(edit_form.attendee) }} {{ form_row(edit_form.attendee) }}
{{ form_row(edit_form.reasons) }} {{ form_row(edit_form.reasons) }}
{{ form_row(form.comment) }} {{ form_row(edit_form.comment) }}
{{ form_widget(edit_form) }} {{ form_widget(edit_form) }}
<ul class="record_actions sticky-form-buttons"> <ul class="record_actions sticky-form-buttons">

View File

@ -1,16 +1,16 @@
{# {#
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop> * Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the * published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version. * License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
#} #}
@ -22,10 +22,10 @@
{% block personcontent %} {% block personcontent %}
<h2>{{ 'Activity list' |trans }}</h2> <h2>{{ 'Activity list' |trans }}</h2>
{% if activities|length == 0 %} {% if activities|length == 0 %}
<p class="chill-no-data-statement"> <p class="chill-no-data-statement">
{{ "There isn't any activities."|trans }} {{ "There isn't any activities."|trans }}
<a href="{{ path('chill_activity_activity_new', {'person_id': person.id}) }}" class="sc-button bt-create button-small"></a> <a href="{{ path('chill_activity_activity_new', {'person_id': person.id}) }}" class="sc-button bt-create button-small"></a>
</p> </p>
{% else %} {% else %}
@ -45,9 +45,9 @@
<td>{% if activity.date %}{{ activity.date|format_date('long') }}{% endif %}</td> <td>{% if activity.date %}{{ activity.date|format_date('long') }}{% endif %}</td>
<td>{{ activity.durationTime|date('H:i') }}</td> <td>{{ activity.durationTime|date('H:i') }}</td>
<td> <td>
{% if activity.remark is not empty %} {% if activity.comment.comment is not empty %}
<blockquote class="chill-user-quote"> <blockquote class="chill-user-quote">
{{ activity.remark|slice(0, 250) }} {# {{ activity.comment.comment|slice(0, 250) }} {#
sf4 check: if 'slice' could replace 'truncate' filter ? sf4 check: if 'slice' could replace 'truncate' filter ?
truncate come with twig-extensions, in conflict with twig 3 truncate come with twig-extensions, in conflict with twig 3
#} #}
@ -81,7 +81,7 @@
</tbody> </tbody>
</table> </table>
{% endif %} {% endif %}
<ul class="record_actions"> <ul class="record_actions">
<li> <li>
<a href="{{ path('chill_activity_activity_new', {'person_id': person.id}) }}" class="sc-button bt-create"> <a href="{{ path('chill_activity_activity_new', {'person_id': person.id}) }}" class="sc-button bt-create">

View File

@ -33,7 +33,6 @@
{{ form_row(form.date) }} {{ form_row(form.date) }}
{{ form_row(form.durationTime) }} {{ form_row(form.durationTime) }}
{{ form_row(form.type) }} {{ form_row(form.type) }}
{{ form_row(form.remark) }}
{{ form_row(form.attendee) }} {{ form_row(form.attendee) }}
{{ form_row(form.reasons) }} {{ form_row(form.reasons) }}
{{ form_row(form.comment) }} {{ form_row(form.comment) }}

View File

@ -25,8 +25,6 @@
<dd>{{ entity.durationTime|date('H:i') }}</dd> <dd>{{ entity.durationTime|date('H:i') }}</dd>
<dt class="inline">{{ 'Type'|trans }}</dt> <dt class="inline">{{ 'Type'|trans }}</dt>
<dd>{{ entity.type.name | localize_translatable_string }}</dd> <dd>{{ entity.type.name | localize_translatable_string }}</dd>
<dt class="inline">{{ 'Remark'|trans }}</dt>
<dd>{% if entity.remark is empty %}<span class="chill-no-data-statement">{{ 'No remarks'|trans }}</span>{% else %}<blockquote class="chill-user-quote">{{ entity.remark|nl2br }}</blockquote>{% endif %}</dd>
<dt class="inline">{{ 'Attendee'|trans }}</dt> <dt class="inline">{{ 'Attendee'|trans }}</dt>
<dd>{% if entity.attendee is not null %}{% if entity.attendee %}{{ 'present'|trans|capitalize }} {% else %} {{ 'not present'|trans|capitalize }}{% endif %}{% else %}{{ 'None'|trans|capitalize }}{% endif %}</dd> <dd>{% if entity.attendee is not null %}{% if entity.attendee %}{{ 'present'|trans|capitalize }} {% else %} {{ 'not present'|trans|capitalize }}{% endif %}{% else %}{{ 'None'|trans|capitalize }}{% endif %}</dd>

View File

@ -4,17 +4,16 @@
<h3>{{ activity.date|format_date('long') }}<span class="activity"> / {{ 'Activity'|trans }}</span></h3> <h3>{{ activity.date|format_date('long') }}<span class="activity"> / {{ 'Activity'|trans }}</span></h3>
<div class="statement"> <div class="statement">
<span class="statement">{{ '%user% has done an %activity_type%'|trans( <span class="statement">{{ '%user% has done an %activity_type%'|trans(
{ {
'%user%' : user, '%user%' : user,
'%activity_type%': activity.type.name|localize_translatable_string, '%activity_type%': activity.type.name|localize_translatable_string,
'%date%' : activity.date|format_date('long') } '%date%' : activity.date|format_date('long') }
) }}</span> ) }}</span>
{% if is_granted(constant('Chill\\ActivityBundle\\Security\\Authorization\\ActivityVoter::SEE_DETAILS'), activity) %} {% if is_granted(constant('Chill\\ActivityBundle\\Security\\Authorization\\ActivityVoter::SEE_DETAILS'), activity) %}
<dl class="chill_view_data"> <dl class="chill_view_data">
<dt class="inline">{{ 'Remark'|trans }}</dt> <dd>{% if activity.comment.comment is empty %}{{ 'No comments'|trans }}{% else %}<blockquote class="chill-user-quote">{{ activity.comment.comment|nl2br }}</blockquote>{% endif %}</dd>
<dd>{% if activity.remark is empty %}{{ 'No remarks'|trans }}{% else %}<blockquote class="chill-user-quote">{{ activity.remark|nl2br }}</blockquote>{% endif %}</dd>
<dt class="inline">{{ 'Reasons'|trans }}</dt> <dt class="inline">{{ 'Reasons'|trans }}</dt>
{%- if activity.reasons is empty -%} {%- if activity.reasons is empty -%}
@ -25,9 +24,9 @@
</dl> </dl>
{% endif %} {% endif %}
</div> </div>
<ul class="record_actions"> <ul class="record_actions">
<li> <li>
<a href="{{ path('chill_activity_activity_show', { 'person_id': person.id, 'id': activity.id} ) }}" class="sc-button bt-view"> <a href="{{ path('chill_activity_activity_show', { 'person_id': person.id, 'id': activity.id} ) }}" class="sc-button bt-view">

View File

@ -8,7 +8,7 @@ use Symfony\Component\HttpFoundation\Response;
class ActivityControllerTest extends WebTestCase class ActivityControllerTest extends WebTestCase
{ {
/** /**
* @dataProvider getSecuredPagesUnauthenticated * @dataProvider getSecuredPagesUnauthenticated
*/ */
@ -22,9 +22,9 @@ class ActivityControllerTest extends WebTestCase
$this->assertTrue($client->getResponse()->isRedirect('http://localhost/login'), $this->assertTrue($client->getResponse()->isRedirect('http://localhost/login'),
sprintf('the page "%s" does not redirect to http://localhost/login', $url)); sprintf('the page "%s" does not redirect to http://localhost/login', $url));
} }
/** /**
* *
* @dataProvider getSecuredPagesAuthenticated * @dataProvider getSecuredPagesAuthenticated
* @param type $client * @param type $client
* @param type $url * @param type $url
@ -35,19 +35,19 @@ class ActivityControllerTest extends WebTestCase
$this->assertEquals(403, $client->getResponse()->getStatusCode()); $this->assertEquals(403, $client->getResponse()->getStatusCode());
} }
public function getSecuredPagesAuthenticated() public function getSecuredPagesAuthenticated()
{ {
static::bootKernel(); static::bootKernel();
$person = $this->getPersonFromFixtures(); $person = $this->getPersonFromFixtures();
$activities = $this->getActivitiesForPerson($person); $activities = $this->getActivitiesForPerson($person);
$user = $this->createFakeUser(); $user = $this->createFakeUser();
return array( return array(
array( array(
$this->getAuthenticatedClient('center b_social'), $this->getAuthenticatedClient('center b_social'),
@ -71,19 +71,19 @@ class ActivityControllerTest extends WebTestCase
) )
); );
} }
/** /**
* Provide a client unauthenticated and * Provide a client unauthenticated and
* *
*/ */
public function getSecuredPagesUnauthenticated() public function getSecuredPagesUnauthenticated()
{ {
static::bootKernel(); static::bootKernel();
$person = $this->getPersonFromFixtures(); $person = $this->getPersonFromFixtures();
$activities = $this->getActivitiesForPerson($person); $activities = $this->getActivitiesForPerson($person);
return array( return array(
[ sprintf('fr/person/%d/activity/', $person->getId()) ], [ sprintf('fr/person/%d/activity/', $person->getId()) ],
[ sprintf('fr/person/%d/activity/new', $person->getId()) ], [ sprintf('fr/person/%d/activity/new', $person->getId()) ],
@ -102,11 +102,11 @@ class ActivityControllerTest extends WebTestCase
// Create a new entry in the database // Create a new entry in the database
$crawler = $client->request('GET', sprintf('en/person/%d/activity/', $crawler = $client->request('GET', sprintf('en/person/%d/activity/',
$person->getId())); $person->getId()));
$this->assertEquals(200, $client->getResponse()->getStatusCode(), $this->assertEquals(200, $client->getResponse()->getStatusCode(),
"Unexpected HTTP status code for GET /activity/"); "Unexpected HTTP status code for GET /activity/");
$crawler = $client->click($crawler->selectLink('Ajouter une nouvelle activité') $crawler = $client->click($crawler->selectLink('Ajouter une nouvelle activité')
->link()); ->link());
$reason1 = $this->getRandomActivityReason(); $reason1 = $this->getRandomActivityReason();
$reason2 = $this->getRandomActivityReason(array($reason1->getId())); $reason2 = $this->getRandomActivityReason(array($reason1->getId()));
@ -115,7 +115,7 @@ class ActivityControllerTest extends WebTestCase
'chill_activitybundle_activity'=> array( 'chill_activitybundle_activity'=> array(
'date' => '15-01-2015', 'date' => '15-01-2015',
'durationTime' => 600, 'durationTime' => 600,
'remark' => 'blabla', // 'remark' => 'blabla',
'scope' => $this->getRandomScope('center a_social', 'Center A')->getId(), 'scope' => $this->getRandomScope('center a_social', 'Center A')->getId(),
'type' => $this->getRandomActivityType()->getId() 'type' => $this->getRandomActivityType()->getId()
) )
@ -123,30 +123,30 @@ class ActivityControllerTest extends WebTestCase
$form['chill_activitybundle_activity[reasons]']->select(array ($reason1->getId(), $reason2->getId())); $form['chill_activitybundle_activity[reasons]']->select(array ($reason1->getId(), $reason2->getId()));
$client->submit($form); $client->submit($form);
$this->assertTrue($client->getResponse()->isRedirect()); $this->assertTrue($client->getResponse()->isRedirect());
$crawler = $client->followRedirect(); $crawler = $client->followRedirect();
// Check data in the show view // Check data in the show view
$this->assertGreaterThan(0, $crawler->filter('dd:contains("January 15, 2015")')->count(), $this->assertGreaterThan(0, $crawler->filter('dd:contains("January 15, 2015")')->count(),
'Missing element dd:contains("January 15, 2015")'); 'Missing element dd:contains("January 15, 2015")');
// Edit the entity // Edit the entity
$crawler = $client->click($crawler->selectLink("Modifier l'activité")->link()); $crawler = $client->click($crawler->selectLink("Modifier l'activité")->link());
$form = $crawler->selectButton("Sauver l'activité")->form(array( $form = $crawler->selectButton("Sauver l'activité")->form(array(
'chill_activitybundle_activity' => array( 'chill_activitybundle_activity' => array(
'date' => '25-01-2015', 'date' => '25-01-2015',
'remark' => 'Foo' // 'remark' => 'Foo'
) )
)); ));
$client->submit($form); $client->submit($form);
$this->assertTrue($client->getResponse()->isRedirect()); $this->assertTrue($client->getResponse()->isRedirect());
$crawler = $client->followRedirect(); $crawler = $client->followRedirect();
// check that new data are present // check that new data are present
$this->assertGreaterThan(0, $this->assertGreaterThan(0,
$crawler->filter('dd:contains("January 25, 2015")')->count(), $crawler->filter('dd:contains("January 25, 2015")')->count(),
@ -154,26 +154,26 @@ class ActivityControllerTest extends WebTestCase
$this->assertGreaterThan(0, $this->assertGreaterThan(0,
$crawler->filter('dd:contains("Foo")')->count(), $crawler->filter('dd:contains("Foo")')->count(),
'Missing element dd:contains("Foo")'); 'Missing element dd:contains("Foo")');
// delete the actvity // delete the actvity
$crawler = $client->click($crawler->selectLink("Supprimer")->link()); $crawler = $client->click($crawler->selectLink("Supprimer")->link());
$button = $crawler->selectButton('Supprimer'); $button = $crawler->selectButton('Supprimer');
$form = $button->form(); $form = $button->form();
$client->submit($form); $client->submit($form);
$this->assertTrue($client->getResponse()->isRedirect(sprintf('/en/person/%d/activity/', $this->assertTrue($client->getResponse()->isRedirect(sprintf('/en/person/%d/activity/',
$person->getId()))); $person->getId())));
$crawler = $client->followRedirect(); $crawler = $client->followRedirect();
$this->assertNotContains('January 25, 2015', $crawler->text()); $this->assertNotContains('January 25, 2015', $crawler->text());
} }
/** /**
* *
* @return \Symfony\Component\BrowserKit\Client * @return \Symfony\Component\BrowserKit\Client
*/ */
private function getAuthenticatedClient($username = 'center a_social') private function getAuthenticatedClient($username = 'center a_social')
@ -183,48 +183,48 @@ class ActivityControllerTest extends WebTestCase
'PHP_AUTH_PW' => 'password', 'PHP_AUTH_PW' => 'password',
)); ));
} }
/** /**
* *
* @return \Chill\PersonBundle\Entity\Person * @return \Chill\PersonBundle\Entity\Person
*/ */
private function getPersonFromFixtures() private function getPersonFromFixtures()
{ {
$em = static::$kernel->getContainer() $em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager'); ->get('doctrine.orm.entity_manager');
$person = $em->getRepository('ChillPersonBundle:Person') $person = $em->getRepository('ChillPersonBundle:Person')
->findOneBy(array( ->findOneBy(array(
'firstName' => 'Depardieu', 'firstName' => 'Depardieu',
'lastName' => 'Gérard' 'lastName' => 'Gérard'
)); ));
if ($person === NULL) { if ($person === NULL) {
throw new \RuntimeException("We need a person with firstname Gérard and" throw new \RuntimeException("We need a person with firstname Gérard and"
. " lastname Depardieu. Did you add fixtures ?"); . " lastname Depardieu. Did you add fixtures ?");
} }
return $person; return $person;
} }
private function getActivitiesForPerson(\Chill\PersonBundle\Entity\Person $person) private function getActivitiesForPerson(\Chill\PersonBundle\Entity\Person $person)
{ {
$em = static::$kernel->getContainer() $em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager'); ->get('doctrine.orm.entity_manager');
$activities = $em->getRepository('ChillActivityBundle:Activity') $activities = $em->getRepository('ChillActivityBundle:Activity')
->findBy(array('person' => $person)); ->findBy(array('person' => $person));
if (count($activities) === 0) { if (count($activities) === 0) {
throw new \RuntimeException("We need activities associated with this " throw new \RuntimeException("We need activities associated with this "
. "person. Did you forget to add fixtures ?"); . "person. Did you forget to add fixtures ?");
} }
return $activities; return $activities;
} }
/** /**
* *
* @param string $username * @param string $username
* @param string $centerName * @param string $centerName
* @return \Chill\MainBundle\Entity\Scope * @return \Chill\MainBundle\Entity\Scope
@ -235,46 +235,46 @@ class ActivityControllerTest extends WebTestCase
->get('doctrine.orm.entity_manager') ->get('doctrine.orm.entity_manager')
->getRepository('ChillMainBundle:User') ->getRepository('ChillMainBundle:User')
->findOneByUsername($username); ->findOneByUsername($username);
if ($user === NULL) { if ($user === NULL) {
throw new \RuntimeException("The user with username $username " throw new \RuntimeException("The user with username $username "
. "does not exists in database. Did you add fixtures ?"); . "does not exists in database. Did you add fixtures ?");
} }
$center = static::$kernel->getContainer() $center = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager') ->get('doctrine.orm.entity_manager')
->getRepository('ChillMainBundle:Center') ->getRepository('ChillMainBundle:Center')
->findOneByName($centerName); ->findOneByName($centerName);
// get scope reachable by both role UPDATE and DELETE // get scope reachable by both role UPDATE and DELETE
$reachableScopesUpdate = static::$kernel->getContainer() $reachableScopesUpdate = static::$kernel->getContainer()
->get('chill.main.security.authorization.helper') ->get('chill.main.security.authorization.helper')
->getReachableScopes($user, new Role('CHILL_ACTIVITY_UPDATE'), ->getReachableScopes($user, new Role('CHILL_ACTIVITY_UPDATE'),
$center); $center);
$reachableScopesDelete = static::$kernel->getContainer() $reachableScopesDelete = static::$kernel->getContainer()
->get('chill.main.security.authorization.helper') ->get('chill.main.security.authorization.helper')
->getReachableScopes($user, new Role('CHILL_ACTIVITY_DELETE'), ->getReachableScopes($user, new Role('CHILL_ACTIVITY_DELETE'),
$center); $center);
$reachableScopesId = array_intersect( $reachableScopesId = array_intersect(
array_map(function ($s) { return $s->getId(); }, $reachableScopesDelete), array_map(function ($s) { return $s->getId(); }, $reachableScopesDelete),
array_map(function ($s) { return $s->getId(); }, $reachableScopesUpdate) array_map(function ($s) { return $s->getId(); }, $reachableScopesUpdate)
); );
if (count($reachableScopesId) === 0) { if (count($reachableScopesId) === 0) {
throw new \RuntimeException("there are not scope reachable for " throw new \RuntimeException("there are not scope reachable for "
. "both CHILL_ACTIVITY_UPDATE and CHILL_ACTIVITY_DELETE"); . "both CHILL_ACTIVITY_UPDATE and CHILL_ACTIVITY_DELETE");
} }
foreach($reachableScopesUpdate as $scope) { foreach($reachableScopesUpdate as $scope) {
if (in_array($scope->getId(), $reachableScopesId)) { if (in_array($scope->getId(), $reachableScopesId)) {
$reachableScopes[] = $scope; $reachableScopes[] = $scope;
} }
} }
return $reachableScopes[array_rand($reachableScopes)]; return $reachableScopes[array_rand($reachableScopes)];
} }
/** /**
* *
* @param int[] $excludeIds An array of id to exclude * @param int[] $excludeIds An array of id to exclude
* @return \Chill\ActivityBundle\Entity\ActivityReason * @return \Chill\ActivityBundle\Entity\ActivityReason
*/ */
@ -284,18 +284,18 @@ class ActivityControllerTest extends WebTestCase
->get('doctrine.orm.entity_manager') ->get('doctrine.orm.entity_manager')
->getRepository('ChillActivityBundle:ActivityReason') ->getRepository('ChillActivityBundle:ActivityReason')
->findAll(); ->findAll();
$reason = $reasons[array_rand($reasons)]; $reason = $reasons[array_rand($reasons)];
if (in_array($reason->getId(), $excludeIds)) { if (in_array($reason->getId(), $excludeIds)) {
return $this->getRandomActivityReason($excludeIds); return $this->getRandomActivityReason($excludeIds);
} }
return $reason; return $reason;
} }
/** /**
* *
* @return \Chill\ActivityBundle\Entity\ActivityType * @return \Chill\ActivityBundle\Entity\ActivityType
*/ */
private function getRandomActivityType() private function getRandomActivityType()
@ -304,21 +304,21 @@ class ActivityControllerTest extends WebTestCase
->get('doctrine.orm.entity_manager') ->get('doctrine.orm.entity_manager')
->getRepository('ChillActivityBundle:ActivityType') ->getRepository('ChillActivityBundle:ActivityType')
->findAll(); ->findAll();
return $types[array_rand($types)]; return $types[array_rand($types)];
} }
/** /**
* create a user without any permissions on CHILL_ACTIVITY_* but with * create a user without any permissions on CHILL_ACTIVITY_* but with
* permissions on center. * permissions on center.
* *
* @return \Chill\MainBundle\Entity\User a fake user within a group without activity * @return \Chill\MainBundle\Entity\User a fake user within a group without activity
*/ */
private function createFakeUser() private function createFakeUser()
{ {
$container = static::$kernel->getContainer(); $container = static::$kernel->getContainer();
$em = $container->get('doctrine.orm.entity_manager'); $em = $container->get('doctrine.orm.entity_manager');
//get the social PermissionGroup, and remove CHILL_ACTIVITY_* //get the social PermissionGroup, and remove CHILL_ACTIVITY_*
$socialPermissionGroup = $em $socialPermissionGroup = $em
->getRepository('ChillMainBundle:PermissionsGroup') ->getRepository('ChillMainBundle:PermissionsGroup')
@ -331,14 +331,14 @@ class ActivityControllerTest extends WebTestCase
$withoutActivityPermissionGroup->addRoleScope($roleScope); $withoutActivityPermissionGroup->addRoleScope($roleScope);
} }
} }
//create groupCenter //create groupCenter
$groupCenter = new \Chill\MainBundle\Entity\GroupCenter(); $groupCenter = new \Chill\MainBundle\Entity\GroupCenter();
$groupCenter->setCenter($em->getRepository('ChillMainBundle:Center') $groupCenter->setCenter($em->getRepository('ChillMainBundle:Center')
->findOneBy(array('name' => 'Center A'))) ->findOneBy(array('name' => 'Center A')))
->setPermissionsGroup($withoutActivityPermissionGroup); ->setPermissionsGroup($withoutActivityPermissionGroup);
$em->persist($withoutActivityPermissionGroup); $em->persist($withoutActivityPermissionGroup);
$em->persist($groupCenter); $em->persist($groupCenter);
//create user //create user
$faker = \Faker\Factory::create(); $faker = \Faker\Factory::create();
$username = $faker->name; $username = $faker->name;
@ -348,11 +348,11 @@ class ActivityControllerTest extends WebTestCase
->encodePassword($user, 'password')) ->encodePassword($user, 'password'))
->setUsername($username) ->setUsername($username)
->addGroupCenter($groupCenter); ->addGroupCenter($groupCenter);
$em->persist($user); $em->persist($user);
$em->flush(); $em->flush();
return $user; return $user;
} }
} }

View File

@ -27,7 +27,7 @@ use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Form\Extension\Core\Type\FormType; use Symfony\Component\Form\Extension\Core\Type\FormType;
/** /**
* *
* *
* @author Julien Fastré <julien.fastre@champs-libres.coop> * @author Julien Fastré <julien.fastre@champs-libres.coop>
*/ */
@ -38,19 +38,19 @@ class ActivityTypeTest extends KernelTestCase
* @var \Symfony\Component\Form\FormBuilderInterface * @var \Symfony\Component\Form\FormBuilderInterface
*/ */
protected $formBuilder; protected $formBuilder;
/** /**
* *
* @var \Symfony\Component\DependencyInjection\ContainerInterface * @var \Symfony\Component\DependencyInjection\ContainerInterface
*/ */
protected $container; protected $container;
/** /**
* *
* @var \Symfony\Component\Security\Core\User\UserInterface * @var \Symfony\Component\Security\Core\User\UserInterface
*/ */
protected $user; protected $user;
/** /**
* *
* @var \Chill\MainBundle\Entity\Center * @var \Chill\MainBundle\Entity\Center
@ -60,26 +60,26 @@ class ActivityTypeTest extends KernelTestCase
public function setUp() public function setUp()
{ {
self::bootKernel(); self::bootKernel();
$this->container = self::$kernel->getContainer(); $this->container = self::$kernel->getContainer();
$prophet = new \Prophecy\Prophet; $prophet = new \Prophecy\Prophet;
$this->formBuilder = $this->container $this->formBuilder = $this->container
->get('form.factory') ->get('form.factory')
->createBuilder(FormType::class, null, array( ->createBuilder(FormType::class, null, array(
'csrf_protection' => false, 'csrf_protection' => false,
'csrf_field_name' => '_token' 'csrf_field_name' => '_token'
)); ));
$request = new \Symfony\Component\HttpFoundation\Request(); $request = new \Symfony\Component\HttpFoundation\Request();
$request->setLocale('fr'); $request->setLocale('fr');
self::$kernel->getContainer() self::$kernel->getContainer()
->get('request_stack') ->get('request_stack')
->push($request); ->push($request);
$this->user = $this->container->get('doctrine.orm.entity_manager') $this->user = $this->container->get('doctrine.orm.entity_manager')
->getRepository('ChillMainBundle:User') ->getRepository('ChillMainBundle:User')
->findOneBy(array('username' => 'center a_social')); ->findOneBy(array('username' => 'center a_social'));
@ -91,9 +91,9 @@ class ActivityTypeTest extends KernelTestCase
$token->getUser()->willReturn($this->user); $token->getUser()->willReturn($this->user);
$this->container->get('security.token_storage') $this->container->get('security.token_storage')
->setToken($token->reveal()); ->setToken($token->reveal());
} }
public function testForm() public function testForm()
{ {
$form = $this->formBuilder $form = $this->formBuilder
@ -102,15 +102,15 @@ class ActivityTypeTest extends KernelTestCase
'role' => new Role('CHILL_ACTIVITY_CREATE') 'role' => new Role('CHILL_ACTIVITY_CREATE')
)) ))
->getForm(); ->getForm();
$form->submit(array()); $form->submit(array());
$this->assertTrue($form->isSynchronized()); $this->assertTrue($form->isSynchronized());
$this->assertTrue($form->isValid()); $this->assertTrue($form->isValid());
$this->assertInstanceOf(Activity::class, $form->getData()['activity']); $this->assertInstanceOf(Activity::class, $form->getData()['activity']);
} }
public function testFormSubmitting() public function testFormSubmitting()
{ {
$form = $this->formBuilder $form = $this->formBuilder
@ -119,35 +119,35 @@ class ActivityTypeTest extends KernelTestCase
'role' => new Role('CHILL_ACTIVITY_CREATE') 'role' => new Role('CHILL_ACTIVITY_CREATE')
)) ))
->getForm(); ->getForm();
$form->submit(array( 'activity' => array( $form->submit(array( 'activity' => array(
'date' => '9-3-2015', 'date' => '9-3-2015',
'durationTime' => 300, 'durationTime' => 300,
'remark' => 'blabla', // 'remark' => 'blabla',
'attendee' => true 'attendee' => true
))); )));
// var_dump($form->getErrors()->count()); var_dump($form->isValid()); // var_dump($form->getErrors()->count()); var_dump($form->isValid());
// foreach($form->getErrors() as $e) { fwrite(STDOUT, var_dump($e->getMessage())); } // foreach($form->getErrors() as $e) { fwrite(STDOUT, var_dump($e->getMessage())); }
// var_dump($form->getErrors()); // var_dump($form->getErrors());
$this->assertTrue($form->isSynchronized(), "Test the form is synchronized"); $this->assertTrue($form->isSynchronized(), "Test the form is synchronized");
$this->assertTrue($form->isValid(), "test the form is valid"); $this->assertTrue($form->isValid(), "test the form is valid");
$this->assertInstanceOf(Activity::class, $form->getData()['activity']); $this->assertInstanceOf(Activity::class, $form->getData()['activity']);
// test the activity // test the activity
/* @var $activity Activity */ /* @var $activity Activity */
$activity = $form->getData()['activity']; $activity = $form->getData()['activity'];
$this->assertEquals('09-03-2015', $activity->getDate()->format('d-m-Y'), $this->assertEquals('09-03-2015', $activity->getDate()->format('d-m-Y'),
"Test the date is correct"); "Test the date is correct");
$this->assertEquals('00:05', $activity->getDurationTime()->format('H:i'), $this->assertEquals('00:05', $activity->getDurationTime()->format('H:i'),
"Test the formatted hour is correct"); "Test the formatted hour is correct");
$this->assertEquals(true, $activity->getAttendee()); $this->assertEquals(true, $activity->getAttendee());
$this->assertEquals('blabla', $activity->getRemark()); // $this->assertEquals('blabla', $activity->getRemark());
} }
/** /**
* Test that the form correctly build even with a durationTime which is not in * Test that the form correctly build even with a durationTime which is not in
* the listed in the possible durationTime * the listed in the possible durationTime
@ -156,50 +156,50 @@ class ActivityTypeTest extends KernelTestCase
{ {
$activity = new Activity(); $activity = new Activity();
$activity->setDurationTime(\DateTime::createFromFormat('U', 60)); $activity->setDurationTime(\DateTime::createFromFormat('U', 60));
$builder = $this->container $builder = $this->container
->get('form.factory') ->get('form.factory')
->createBuilder(FormType::class, array('activity' => $activity), array( ->createBuilder(FormType::class, array('activity' => $activity), array(
'csrf_protection' => false, 'csrf_protection' => false,
'csrf_field_name' => '_token' 'csrf_field_name' => '_token'
)); ));
$form = $builder $form = $builder
->add('activity', ActivityType::class, array( ->add('activity', ActivityType::class, array(
'center' => $this->center, 'center' => $this->center,
'role' => new Role('CHILL_ACTIVITY_CREATE') 'role' => new Role('CHILL_ACTIVITY_CREATE')
)) ))
->getForm(); ->getForm();
$form->submit(array( 'activity' => array( $form->submit(array( 'activity' => array(
'date' => '9-3-2015', 'date' => '9-3-2015',
'durationTime' => 60, 'durationTime' => 60,
'remark' => 'blabla', // 'remark' => 'blabla',
'attendee' => true 'attendee' => true
))); )));
$this->assertTrue($form->isSynchronized()); $this->assertTrue($form->isSynchronized());
$this->assertTrue($form->isValid()); $this->assertTrue($form->isValid());
// test the activity // test the activity
/* @var $activity Activity */ /* @var $activity Activity */
$activity = $form->getData()['activity']; $activity = $form->getData()['activity'];
$this->assertEquals('00:01', $activity->getDurationTime()->format('H:i'), $this->assertEquals('00:01', $activity->getDurationTime()->format('H:i'),
"Test the formatted hour is correct"); "Test the formatted hour is correct");
// test the view : we want to be sure that the entry with 60 seconds exists // test the view : we want to be sure that the entry with 60 seconds exists
$view = $form->createView(); $view = $form->createView();
$this->assertTrue(isset($view['activity']['durationTime'])); $this->assertTrue(isset($view['activity']['durationTime']));
// map all the values in an array // map all the values in an array
$values = array_map(function($choice) { return $choice->value; }, $values = array_map(function($choice) { return $choice->value; },
$view['activity']['durationTime']->vars['choices']); $view['activity']['durationTime']->vars['choices']);
$this->assertContains(60, $values); $this->assertContains(60, $values);
} }
} }

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Activity;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20210304154629 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE activity ADD comment_comment TEXT DEFAULT NULL');
$this->addSql('ALTER TABLE activity ADD comment_userId INT DEFAULT NULL');
$this->addSql('ALTER TABLE activity ADD comment_date TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE activity DROP comment_comment');
$this->addSql('ALTER TABLE activity DROP comment_userId');
$this->addSql('ALTER TABLE activity DROP comment_date');
}
}

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Activity;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20210311114250 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('UPDATE activity SET comment_comment = remark');
$this->addSql('ALTER TABLE activity DROP remark');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
}
}

View File

@ -11,8 +11,8 @@ attendee: présence de la personne
list_reasons: liste des sujets list_reasons: liste des sujets
user_username: nom de l'utilisateur user_username: nom de l'utilisateur
circle_name: nom du cercle circle_name: nom du cercle
Remark: Notes Remark: Commentaire
No remarks: Aucune note No comments: Aucun commentaire
Add a new activity: Ajouter une nouvelle activité Add a new activity: Ajouter une nouvelle activité
Activity list: Liste des activités Activity list: Liste des activités
present: présent present: présent
@ -112,7 +112,7 @@ The activity has been successfully removed.: L'activité a été supprimée.
# exports # exports
Count activities: Nombre d'activités Count activities: Nombre d'activités
Count activities by various parameters.: Compte le nombre d'activités enregistrées en fonction de différents paramètres. Count activities by various parameters.: Compte le nombre d'activités enregistrées en fonction de différents paramètres.
Sum activity duration: Total de la durée des activités Sum activity duration: Total de la durée des activités
Sum activities duration by various parameters.: Additionne la durée des activités en fonction de différents paramètres. Sum activities duration by various parameters.: Additionne la durée des activités en fonction de différents paramètres.
List activities: Liste les activités List activities: Liste les activités