mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-10-31 09:18:24 +00:00 
			
		
		
		
	Compare commits
	
		
			16 Commits
		
	
	
		
			fix-tests/
			...
			notificati
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | cb3f09d622 | ||
|  | 5c2c509805 | ||
|  | 9d478c0f01 | ||
|  | 4646795c2c | ||
|  | 18369a6c0a | ||
|  | 0fd9485de5 | ||
| c8f139528a | |||
| 8030792eb6 | |||
|  | 50a4df3d0f | ||
|  | 0907ae1602 | ||
|  | 673a4761e9 | ||
|  | 282db51f06 | ||
|  | bdf691a063 | ||
|  | 18ab10dd45 | ||
| 65198937c0 | |||
| 2699d48533 | 
| @@ -22,6 +22,7 @@ class LoadActivityNotifications extends AbstractFixture implements DependentFixt | ||||
|             'entityRef' => 'activity_gerard depardieu', | ||||
|             'sender' => 'center a_social', | ||||
|             'addressees' => [ | ||||
|                 'center a_social', | ||||
|                 'center a_administrative', | ||||
|                 'center a_direction', | ||||
|                 'multi_center' | ||||
|   | ||||
| @@ -0,0 +1,24 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Chill\ActivityBundle\Notification; | ||||
|  | ||||
| use Chill\MainBundle\Entity\Notification; | ||||
| use Chill\ActivityBundle\Entity\Activity; | ||||
|  | ||||
| final class ActivityNotificationRenderer | ||||
| { | ||||
|     public function supports(Notification $notification, array $options = []): bool | ||||
|     { | ||||
|         return $notification->getRelatedEntityClass() == Activity::class; | ||||
|     } | ||||
|  | ||||
|     public function getTemplate() | ||||
|     { | ||||
|         return '@ChillActivity/Activity/showInNotification.html.twig'; | ||||
|     } | ||||
|  | ||||
|     public function getTemplateData(Notification $notification) | ||||
|     { | ||||
|         return ['notification' => $notification]; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,4 @@ | ||||
|  | ||||
| {{ dump(notification) }} | ||||
|  | ||||
| <a href="{{ path('chill_activity_activity_show', {'id': notification.relatedEntityId })  }}">Go to Activity</a> | ||||
| @@ -1,4 +1,4 @@ | ||||
| services:      | ||||
| services: | ||||
|     chill.activity.security.authorization.activity_voter: | ||||
|         class: Chill\ActivityBundle\Security\Authorization\ActivityVoter | ||||
|         arguments: | ||||
| @@ -6,7 +6,7 @@ services: | ||||
|         tags: | ||||
|             - { name: security.voter } | ||||
|             - { name: chill.role } | ||||
|              | ||||
|  | ||||
|     chill.activity.security.authorization.activity_stats_voter: | ||||
|         class: Chill\ActivityBundle\Security\Authorization\ActivityStatsVoter | ||||
|         arguments: | ||||
| @@ -14,8 +14,8 @@ services: | ||||
|         tags: | ||||
|             - { name: security.voter } | ||||
|             - { name: chill.role } | ||||
|              | ||||
|              | ||||
|  | ||||
|  | ||||
|     chill.activity.timeline: | ||||
|         class: Chill\ActivityBundle\Timeline\TimelineActivityProvider | ||||
|         arguments: | ||||
| @@ -33,3 +33,8 @@ services: | ||||
|         autoconfigure: true | ||||
|         resource: '../Menu/' | ||||
|         tags: ['chill.menu_builder'] | ||||
|  | ||||
|     Chill\ActivityBundle\Notification\: | ||||
|         autowire: true | ||||
|         autoconfigure: true | ||||
|         resource: '../Notification' | ||||
|   | ||||
| @@ -0,0 +1,95 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Chill\MainBundle\Controller; | ||||
|  | ||||
| use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | ||||
| use Chill\MainBundle\Repository\NotificationRepository; | ||||
| use Chill\MainBundle\Notification\NotificationRenderer; | ||||
| use Symfony\Component\Security\Core\Security; | ||||
| use Symfony\Component\Routing\Annotation\Route; | ||||
| use Chill\MainBundle\Pagination\PaginatorFactory; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @Route("/{_locale}/notification") | ||||
|  */ | ||||
| class NotificationController extends AbstractController | ||||
| { | ||||
|     private $security; | ||||
|  | ||||
|     public function __construct(Security $security) | ||||
|     { | ||||
|         $this->security = $security; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @Route("/list/sent", name="chill_main_send_notification_list") | ||||
|      */ | ||||
|     public function sentListAction( | ||||
|         NotificationRepository $notificationRepository, NotificationRenderer $notificationRenderer, | ||||
|         PaginatorFactory $paginatorFactory) | ||||
|     { | ||||
|         $currentUser = $this->security->getUser(); | ||||
|  | ||||
|         $notificationsNbr = $notificationRepository->countAllForAddresseeOrSender(null, $currentUser); | ||||
|         $paginator = $paginatorFactory->create($notificationsNbr); | ||||
|  | ||||
|         $notifications = $notificationRepository->findAllForAddresseeOrSender( | ||||
|             null, | ||||
|             $currentUser, | ||||
|             $paginator->getItemsPerPage(), | ||||
|             $paginator->getCurrentPage()->getFirstItemNumber()); | ||||
|  | ||||
|         $templateData = array(); | ||||
|         foreach ($notifications as $notification) { | ||||
|             $data = [ | ||||
|                 'template' => $notificationRenderer->getTemplate($notification), | ||||
|                 'template_data' => $notificationRenderer->getTemplateData($notification), | ||||
|                 'notification' => $notification | ||||
|             ]; | ||||
|             $templateData[] = $data; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return $this->render('@ChillMain/Notification/show.html.twig', [ | ||||
|             'datas' => $templateData, | ||||
|             'notifications' => $notifications, | ||||
|             'paginator' => $paginator, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @Route("/list/received", name="chill_main_received_notification_list") | ||||
|      */ | ||||
|     public function receivedListAction( | ||||
|         NotificationRepository $notificationRepository, NotificationRenderer $notificationRenderer, | ||||
|         PaginatorFactory $paginatorFactory) | ||||
|     { | ||||
|         $currentUser = $this->security->getUser(); | ||||
|  | ||||
|         $notificationsNbr = $notificationRepository->countAllForAddresseeOrSender($currentUser, null); | ||||
|         $paginator = $paginatorFactory->create($notificationsNbr); | ||||
|  | ||||
|         $notifications = $notificationRepository->findAllForAddresseeOrSender( | ||||
|             $currentUser, | ||||
|             null, | ||||
|             $limit=$paginator->getItemsPerPage(), | ||||
|             $offset= $paginator->getCurrentPage()->getFirstItemNumber()); | ||||
|  | ||||
|         $templateData = array(); | ||||
|         foreach ($notifications as $notification) { | ||||
|             $data = [ | ||||
|                 'template' => $notificationRenderer->getTemplate($notification), | ||||
|                 'template_data' => $notificationRenderer->getTemplateData($notification), | ||||
|                 'notification' => $notification | ||||
|             ]; | ||||
|             $templateData[] = $data; | ||||
|         } | ||||
|  | ||||
|         return $this->render('@ChillMain/Notification/show.html.twig', [ | ||||
|             'datas' => $templateData, | ||||
|             'notifications' => $notifications, | ||||
|             'paginator' => $paginator, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,44 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Chill\MainBundle\Notification; | ||||
|  | ||||
| use Chill\MainBundle\Entity\Notification; | ||||
| use Chill\PersonBundle\Notification\AccompanyingPeriodNotificationRenderer; | ||||
| use Chill\ActivityBundle\Notification\ActivityNotificationRenderer; | ||||
|  | ||||
| final class NotificationRenderer | ||||
| { | ||||
|     private array $renderers; | ||||
|  | ||||
|     public function __construct( | ||||
|         AccompanyingPeriodNotificationRenderer $accompanyingPeriodNotificationRenderer, | ||||
|         ActivityNotificationRenderer $activityNotificationRenderer) | ||||
|     { | ||||
|         // TODO configure automatically | ||||
|         // TODO CREER UNE INTERFACE POUR ETRE SUR QUE LES RENDERERS SONT OK | ||||
|  | ||||
|         $this->renderers[] = $accompanyingPeriodNotificationRenderer; | ||||
|         $this->renderers[] = $activityNotificationRenderer; | ||||
|     } | ||||
|  | ||||
|     private function getRenderer(Notification $notification) | ||||
|     { | ||||
|         foreach ($this->renderers as $renderer) { | ||||
|             if($renderer->supports($notification)) { | ||||
|                 return $renderer; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         throw new \Exception('No renderer for '. $notification); | ||||
|     } | ||||
|  | ||||
|     public function getTemplate(Notification $notification) | ||||
|     { | ||||
|         return $this->getRenderer($notification)->getTemplate(); | ||||
|     } | ||||
|  | ||||
|     public function getTemplateData(Notification $notification) | ||||
|     { | ||||
|         return $this->getRenderer($notification)->getTemplateData($notification); | ||||
|     } | ||||
| } | ||||
| @@ -23,6 +23,8 @@ use Chill\MainBundle\Entity\Notification; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Doctrine\ORM\EntityRepository; | ||||
| use Doctrine\Persistence\ObjectRepository; | ||||
| use Chill\MainBundle\Entity\User; | ||||
| use Doctrine\ORM\Query; | ||||
|  | ||||
| final class NotificationRepository implements ObjectRepository | ||||
| { | ||||
| @@ -59,8 +61,72 @@ final class NotificationRepository implements ObjectRepository | ||||
|         return $this->repository->findBy($criteria, $orderBy, $limit, $offset); | ||||
|     } | ||||
|  | ||||
|     private function queryAllForAddresseeOrSender(?User $addressee=null, ?User $sender=null,  bool $countQuery=False): Query | ||||
|     { | ||||
|         $qb = $this->repository->createQueryBuilder('n'); | ||||
|  | ||||
|         $select = 'n'; | ||||
|         if($countQuery) { | ||||
|             $select = 'count(n)'; | ||||
|         } | ||||
|  | ||||
|         $qb = $qb | ||||
|             ->select($select); | ||||
|  | ||||
|         $params = array(); | ||||
|  | ||||
|         if($addressee !== null) { | ||||
|             $qb = $qb | ||||
|             ->join('n.addressees', 'a') | ||||
|             ->where('a = :addressee'); | ||||
|  | ||||
|             $params['addressee'] = $addressee; | ||||
|         } | ||||
|  | ||||
|         if($sender !== null) { | ||||
|             $qb = $qb | ||||
|                 ->where('n.sender = :sender'); | ||||
|  | ||||
|             $params['sender'] = $sender; | ||||
|         } | ||||
|  | ||||
|         foreach ($params as $key => $value) { | ||||
|             $qb = $qb->setParameter($key, $value); | ||||
|         } | ||||
|  | ||||
|         return $qb->getQuery(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
|     public function  countAllForAddresseeOrSender(?User $addressee, ?User $sender): int | ||||
|     { | ||||
|         $query = $this->queryAllForAddresseeOrSender($addressee, $sender, True); | ||||
|  | ||||
|         return $query->getSingleScalarResult(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Notification[] | ||||
|      */ | ||||
|     public function  findAllForAddresseeOrSender( | ||||
|         ?User $addressee, ?User $sender,  ?int $limit=null, ?int $offset=null): array | ||||
|     { | ||||
|         $query = $this->queryAllForAddresseeOrSender($addressee, $sender, False); | ||||
|  | ||||
|         if($limit) { | ||||
|             $query = $query->setMaxResults($limit); | ||||
|         } | ||||
|  | ||||
|         if($offset) { | ||||
|             $query = $query->setFirstResult($offset); | ||||
|         } | ||||
|  | ||||
|         return $query->getResult(); | ||||
|     } | ||||
|  | ||||
|     public function getClassName() { | ||||
|         return Notification::class; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,42 @@ | ||||
| {% extends "@ChillMain/layout.html.twig"  %} | ||||
|  | ||||
| {% block content %} | ||||
|     <div id="container content"> | ||||
|         <div class="grid-8 centered"> | ||||
|             <h1>{{ "Notifications list" | trans }}</h1> | ||||
|             <!-- TODO : UNREAD & READ --> | ||||
|  | ||||
|             {%for data in datas %} | ||||
|                 {% set notification = data.notification %} | ||||
|  | ||||
|                 <dl class="chill_view_data"> | ||||
|                     <dt class="inline">{{ 'Message'|trans }}</dt> | ||||
|                     <dd>{{ notification.message }}</dd> | ||||
|                 </dl> | ||||
|  | ||||
|                 <dl class="chill_view_data"> | ||||
|                     <dt class="inline">{{ 'Date'|trans }}</dt> | ||||
|                     <dd>{{ notification.date | date('long') }}</dd> | ||||
|                 </dl> | ||||
|  | ||||
|  | ||||
|                 <dl class="chill_view_data"> | ||||
|                     <dt class="inline">{{ 'Sender'|trans }}</dt> | ||||
|                     <dd>{{ notification.sender }}</dd> | ||||
|                 </dl> | ||||
|  | ||||
|                 <dl class="chill_view_data"> | ||||
|                     <dt class="inline">{{ 'Addressees'|trans }}</dt> | ||||
|                     <dd>{{ notification.addressees |join(', ')  }}</dd> | ||||
|                 </dl> | ||||
|  | ||||
|                 <dl class="chill_view_data"> | ||||
|                     <dt class="inline">{{ 'Entity'|trans }}</dt> | ||||
|                     <dd> | ||||
|                         {% include data.template with data.template_data %} | ||||
|                     </dd> | ||||
|                 </dl> | ||||
|             {% endfor %} | ||||
|         </div> | ||||
|     </div> | ||||
| {% endblock content %} | ||||
| @@ -50,7 +50,7 @@ | ||||
|             <div class="row justify-content-center"> | ||||
|                  | ||||
|                 {# Flash messages ! #} | ||||
|                 {% if app.session.flashbag.all()|length > 0 %} | ||||
|                 {% if app.session.flashbag.keys()|length > 0 %} | ||||
|                 <div class="col-8 mt-5 flash_message"> | ||||
|                  | ||||
|                     {% for flashMessage in app.session.flashbag.get('success') %} | ||||
|   | ||||
| @@ -29,7 +29,7 @@ | ||||
|             <div class="col-md-9"> | ||||
|                  | ||||
|                 {# Flash messages ! #} | ||||
|                 {% if app.session.flashbag.all()|length > 0 %} | ||||
|                 {% if app.session.flashbag.keys()|length > 0 %} | ||||
|                 <div class="row justify-content-center mt-5"> | ||||
|                      | ||||
|                     {% for flashMessage in app.session.flashbag.get('success') %} | ||||
|   | ||||
| @@ -26,7 +26,7 @@ use Symfony\Component\HttpFoundation\Request; | ||||
|  | ||||
| /** | ||||
|  * This class provide a set of tests for exports. | ||||
|  *  | ||||
|  * | ||||
|  * The tests provided by this class will check basic things, like | ||||
|  * the type of value are conform to the expected, etc. | ||||
|  * | ||||
| @@ -34,45 +34,45 @@ use Symfony\Component\HttpFoundation\Request; | ||||
|  */ | ||||
| abstract class AbstractExportTest extends WebTestCase | ||||
| { | ||||
|      | ||||
|  | ||||
|     use PrepareClientTrait; | ||||
|  | ||||
|              | ||||
|  | ||||
|     /** | ||||
|      * Create an instance of the report to test | ||||
|      *  | ||||
|      * | ||||
|      * @return \Chill\MainBundle\Export\ExportInterface an instance of the export to test | ||||
|      */ | ||||
|     public abstract function getExport(); | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * Create possible combinaison of data (produced by the form). | ||||
|      *  | ||||
|      * | ||||
|      * This data will be used to generate data providers using this data. | ||||
|      *  | ||||
|      * | ||||
|      * @return array an array of data. Example : `array( array(), array('fields' => array(1,2,3), ...)` where an empty array and `array(1,2,3)` are possible values | ||||
|      */ | ||||
|     public abstract function getFormData(); | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * get the possible modifiers which could apply in combination to this  | ||||
|      * get the possible modifiers which could apply in combination to this | ||||
|      * export. | ||||
|      * .  | ||||
|      *  | ||||
|      * @return array of string[] an array which contains an array of possible modifiers. Example : `array( array('modifier_1', 'modifier_2'), array('modifier_1'), ...)`  | ||||
|      * . | ||||
|      * | ||||
|      * @return array of string[] an array which contains an array of possible modifiers. Example : `array( array('modifier_1', 'modifier_2'), array('modifier_1'), ...)` | ||||
|      */ | ||||
|     abstract public function getModifiersCombination(); | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * Return an array usable as ACL | ||||
|      *  | ||||
|      * | ||||
|      * If this method is overridden, the returned result must be an array | ||||
|      * with this form : | ||||
|      *  | ||||
|      * | ||||
|      * ``` | ||||
|      * array( | ||||
|      *      array(  | ||||
|      *          'center' =>  //center instance  | ||||
|      *      array( | ||||
|      *          'center' =>  //center instance | ||||
|      *          'circles' => array(// array of circles instances ) | ||||
|      *     ) | ||||
|      * ); | ||||
| @@ -84,15 +84,15 @@ abstract class AbstractExportTest extends WebTestCase | ||||
|         if (static::$kernel === null) { | ||||
|             static::bootKernel(); | ||||
|         } | ||||
|          | ||||
|  | ||||
|         $em = static::$kernel->getContainer() | ||||
|             ->get('doctrine.orm.entity_manager'); | ||||
|              | ||||
|  | ||||
|         $centers = $em->getRepository('ChillMainBundle:Center') | ||||
|             ->findAll(); | ||||
|         $circles = $em->getRepository('ChillMainBundle:Scope') | ||||
|             ->findAll(); | ||||
|          | ||||
|  | ||||
|         if (count($centers) === 0) { | ||||
|             throw new \RuntimeException("No center found. Did you forget to " | ||||
|                 . "run `doctrine:fixtures:load` command before ?"); | ||||
| @@ -101,7 +101,7 @@ abstract class AbstractExportTest extends WebTestCase | ||||
|             throw new \RuntimeException("No circle found. Did you forget to " | ||||
|                 . "run `doctrine:fixtures:load` command before ?"); | ||||
|         } | ||||
|          | ||||
|  | ||||
|         return array([ | ||||
|             'center' => $centers[0], | ||||
|             'circles' => [ | ||||
| @@ -115,204 +115,203 @@ abstract class AbstractExportTest extends WebTestCase | ||||
|     public function testGetType() | ||||
|     { | ||||
|         $export = $this->getExport(); | ||||
|          | ||||
|         $this->assertInternalType('string', $export->getType(),  | ||||
|  | ||||
|         $this->assertInternalType('string', $export->getType(), | ||||
|             "Assert that the `getType` method return a string"); | ||||
|         $this->assertNotEmpty($export->getType(), "Assert that the `getType` method" | ||||
|             . " does not return an empty string."); | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * Test that the description is not empty | ||||
|      */ | ||||
|     public function testGetDescription() | ||||
|     { | ||||
|         $export = $this->getExport(); | ||||
|          | ||||
|         $this->assertInternalType('string', $export->getDescription(),  | ||||
|  | ||||
|         $this->assertInternalType('string', $export->getDescription(), | ||||
|             "Assert that the `getDescription` method return a string"); | ||||
|         $this->assertNotEmpty($export->getDescription(),  | ||||
|         $this->assertNotEmpty($export->getDescription(), | ||||
|             "Assert that the `getDescription` method does not return an empty " | ||||
|             . "string."); | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * create data for `ìnitiateQuery` method | ||||
|      */ | ||||
|     public function dataProviderInitiateQuery() | ||||
|     { | ||||
|         $acl = $this->getAcl(); | ||||
|          | ||||
|  | ||||
|         foreach($this->getModifiersCombination() as $modifiers) { | ||||
|              | ||||
|  | ||||
|             foreach($this->getFormData() as $data) { | ||||
|                  | ||||
|  | ||||
|                 yield array($modifiers, $acl, $data); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|  | ||||
|     public function dataProviderGetQueryKeys() | ||||
|     { | ||||
|         foreach($this->getFormData() as $data) { | ||||
|             yield array($data); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      *  | ||||
|      * | ||||
|      * test that the query returned is a QueryBuilder or a NativeQuery. | ||||
|      *  | ||||
|      * | ||||
|      * If the query is a QueryBuilder, test that select and from is not empty. | ||||
|      *  | ||||
|      * If the query is a native sql, test the query is not empty (length is  | ||||
|      * | ||||
|      * If the query is a native sql, test the query is not empty (length is | ||||
|      * > 0). | ||||
|      *  | ||||
|      * | ||||
|      * @dataProvider dataProviderInitiateQuery | ||||
|      */ | ||||
|     public function testInitiateQuery($modifiers, $acl, $data) | ||||
|     { | ||||
|         var_dump($data); | ||||
|         $query = $this->getExport()->initiateQuery($modifiers, $acl, $data); | ||||
|          | ||||
|  | ||||
|         $this->assertTrue($query instanceof QueryBuilder || $query instanceof NativeQuery, | ||||
|             sprintf("Assert that the returned query is an instance of %s or %s",  | ||||
|             sprintf("Assert that the returned query is an instance of %s or %s", | ||||
|                 QueryBuilder::class, Query::class)); | ||||
|          | ||||
|  | ||||
|         if ($query instanceof QueryBuilder) { | ||||
|              | ||||
|  | ||||
|             $this->assertGreaterThanOrEqual(1, count($query->getDQLPart('select')), | ||||
|                 "assert there is at least one 'select' part"); | ||||
|              | ||||
|  | ||||
|             $this->assertGreaterThanOrEqual(1, count($query->getDQLPart('from')), | ||||
|                 "assert there is at least one 'from' part"); | ||||
|              | ||||
|  | ||||
|         } elseif ($query instanceof NativeQuery) { | ||||
|             $this->assertNotEmpty($query->getSQL(),  | ||||
|             $this->assertNotEmpty($query->getSQL(), | ||||
|                 "check that the SQL query is not empty"); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * Test that supportsModifier return : | ||||
|      *  | ||||
|      * | ||||
|      * - an array of string, if the query is a QueryBuilder ; | ||||
|      * - nothing, if the query is a native SQL | ||||
|      *  | ||||
|      * | ||||
|      * @dataProvider dataProviderInitiateQuery | ||||
|      */ | ||||
|     public function testSupportsModifier($modifiers, $acl, $data) | ||||
|     { | ||||
|         $export = $this->getExport(); | ||||
|         $query = $export->initiateQuery($modifiers, $acl, $data); | ||||
|          | ||||
|  | ||||
|         if ($query instanceof QueryBuilder) { | ||||
|             $this->assertContainsOnly('string', $export->supportsModifiers(), | ||||
|                 "Test that the `supportsModifiers` method returns only strings"); | ||||
|         } elseif ($query instanceof NativeQuery) { | ||||
|             $this->assertTrue($export->supportsModifiers() === null ||  | ||||
|             $this->assertTrue($export->supportsModifiers() === null || | ||||
|                 count($export->supportsModifiers()) === 0, | ||||
|                 "Test that the `supportsModifier` methods returns null or an empty array"); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * Test required role is an instance of Role | ||||
|      */ | ||||
|     public function testRequiredRole() | ||||
|     { | ||||
|         $role = $this->getExport()->requiredRole(); | ||||
|          | ||||
|         $this->assertInstanceOf(Role::class, $role,  | ||||
|  | ||||
|         $this->assertInstanceOf(Role::class, $role, | ||||
|             sprintf("test that the returned value of `requiredRole` is an instance " | ||||
|             . "of %s", Role::class)); | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * Test the formatters type are string | ||||
|      */ | ||||
|     public function testGetAllowedFormattersType() | ||||
|     { | ||||
|         $formattersTypes = $this->getExport()->getAllowedFormattersTypes(); | ||||
|          | ||||
|  | ||||
|         $this->assertContainsOnly("string", $formattersTypes, | ||||
|             "Test that the method `getAllowedFormattersTypes` returns an array of string"); | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      * Test that the query keys are strings | ||||
|      *  | ||||
|      * | ||||
|      * @param array $data | ||||
|      * @dataProvider dataProviderGetQueryKeys | ||||
|      */ | ||||
|     public function testGetQueryKeys(array $data) | ||||
|     { | ||||
|         $queryKeys = $this->getExport()->getQueryKeys($data); | ||||
|          | ||||
|  | ||||
|         $this->assertContainsOnly("string", $queryKeys, | ||||
|             "test that the query keys returned by `getQueryKeys` are only strings"); | ||||
|         $this->assertGreaterThanOrEqual(1, count($queryKeys), | ||||
|             "test that there are at least one query key returned"); | ||||
|     } | ||||
|      | ||||
|  | ||||
|     /** | ||||
|      *  | ||||
|      * Test that  | ||||
|      *  | ||||
|      * | ||||
|      * Test that | ||||
|      * | ||||
|      * - the results have a correct form (are arrays or traversable) | ||||
|      * - each key in a row are present in getQueryKeys ; | ||||
|      * - each returned object of the `getLabels` method is callable | ||||
|      * - each result can be converted to string using this callable | ||||
|      * - each of this callable can provide a string for '_header' | ||||
|      *  | ||||
|      * | ||||
|      * @param string[] $modifiers | ||||
|      * @param array $acl | ||||
|      * @param array $data | ||||
|      *  | ||||
|      * | ||||
|      * @dataProvider dataProviderInitiateQuery | ||||
|      */ | ||||
|     public function testGetResultsAndLabels($modifiers, $acl, array $data) | ||||
|     { | ||||
|         // it is more convenient to  group the `getResult` and `getLabels` test | ||||
|         // due to the fact that testing both methods use the same tools. | ||||
|          | ||||
|  | ||||
|         $queryKeys = $this->getExport()->getQueryKeys($data); | ||||
|         $query     = $this->getExport()->initiateQuery($modifiers, $acl, $data); | ||||
|          | ||||
|  | ||||
|         // limit the result for the query for performance reason (only for QueryBuilder, | ||||
|         // not possible in NativeQuery) | ||||
|         if ($query instanceof QueryBuilder) { | ||||
|             $query->setMaxResults(1); | ||||
|         }  | ||||
|          | ||||
|         } | ||||
|  | ||||
|         $results   = $this->getExport()->getResult($query, $data); | ||||
|          | ||||
|         $this->assertInternalType('array', $results,  | ||||
|  | ||||
|         $this->assertInternalType('array', $results, | ||||
|             "assert that the returned result is an array"); | ||||
|          | ||||
|  | ||||
|         if (count($results) === 0) { | ||||
|             $this->markTestIncomplete("The result is empty. We cannot process tests " | ||||
|                 . "on results"); | ||||
|         } | ||||
|          | ||||
|  | ||||
|         // testing the result | ||||
|         $result = $results[0]; | ||||
|          | ||||
|  | ||||
|         $this->assertTrue( $result instanceof \Traversable || is_array($result), | ||||
|             "test that each row in the result is traversable or an array"); | ||||
|          | ||||
|  | ||||
|         foreach ($result as $key => $value) { | ||||
|             $this->assertContains($key, $queryKeys, | ||||
|                 "test that each key is present in `getQueryKeys`"); | ||||
|              | ||||
|  | ||||
|             $closure = $this->getExport()->getLabels($key, array($value), $data); | ||||
|              | ||||
|  | ||||
|             $this->assertTrue(is_callable($closure, false), | ||||
|                 "test that the `getLabels` for key is a callable"); | ||||
|             $this->assertTrue(is_string((string) call_user_func($closure, $value)), | ||||
|                 sprintf("test that the callable return by `getLabels` for key %s " | ||||
|                     . "is a string or an be converted to a string", $key)); | ||||
|              | ||||
|  | ||||
|             $this->assertTrue( | ||||
|                 // conditions | ||||
|                 is_string((string) call_user_func($closure, '_header')) | ||||
| @@ -322,13 +321,13 @@ abstract class AbstractExportTest extends WebTestCase | ||||
|                 sprintf("Test that the callable return by `getLabels` for key %s " | ||||
|                 . "can provide an header", $key) | ||||
|                 ); | ||||
|         }  | ||||
|          | ||||
|         } | ||||
|  | ||||
|     } | ||||
|      | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Test that the translated title of the export is present the list,  | ||||
|      * Test that the translated title of the export is present the list, | ||||
|      * and that the list of exports (under `/fr/exports/`) is still successfull | ||||
|      */ | ||||
|     public function testListExportPage() | ||||
| @@ -338,17 +337,17 @@ abstract class AbstractExportTest extends WebTestCase | ||||
|         $export = $this->getExport(); | ||||
|         $prophet= new \Prophecy\Prophet; | ||||
|         $container = static::$kernel->getContainer(); | ||||
|          | ||||
|  | ||||
|         // store the locale in a request | ||||
|         $request = new Request(); | ||||
|         $request->setLocale('fr'); | ||||
|         $container->get('request_stack')->push($request); | ||||
|         // translate the title | ||||
|         $title  = $container->get('translator')->trans($export->getTitle()); | ||||
|          | ||||
|  | ||||
|         // performs the request to /fr/exports | ||||
|         $crawler = $client->request('GET', '/fr/exports/'); | ||||
|          | ||||
|  | ||||
|         // and finally make tests | ||||
|         $this->assertTrue($client->getResponse()->isSuccessful(), | ||||
|             "test that the response of /fr/exports/ is successful"); | ||||
|   | ||||
| @@ -34,6 +34,10 @@ chill_password_recover: | ||||
|     resource: "@ChillMainBundle/config/routes/password_recover.yaml" | ||||
|     prefix: "public/{_locale}/password" | ||||
|  | ||||
| chill_main_notification: | ||||
|     resource: "@ChillMainBundle/config/routes/notification.yaml" | ||||
|     prefix:   "{_locale}/notification" | ||||
|  | ||||
| chill_crud: | ||||
|     resource: "@ChillMainBundle" | ||||
|     type: CRUD | ||||
|   | ||||
| @@ -33,3 +33,8 @@ services: | ||||
|             $logger: '@Psr\Log\LoggerInterface' | ||||
|             $validator: '@Symfony\Component\Validator\Validator\ValidatorInterface' | ||||
|         tags: ['controller.service_arguments'] | ||||
|  | ||||
|     Chill\MainBundle\Controller\NotificationController: | ||||
|         arguments: | ||||
|             $security: '@Symfony\Component\Security\Core\Security' | ||||
|         tags: ['controller.service_arguments'] | ||||
|   | ||||
| @@ -4,7 +4,11 @@ services: | ||||
|             $logger: '@Psr\Log\LoggerInterface' | ||||
|             $twig: '@Twig\Environment' | ||||
|             $mailer: '@swiftmailer.mailer.default' | ||||
|           # $mailerTransporter: '@swiftmailer.transport' | ||||
|             # $mailerTransporter: '@swiftmailer.transport' | ||||
|             $router: '@Symfony\Component\Routing\RouterInterface' | ||||
|             $translator: '@Symfony\Component\Translation\TranslatorInterface' | ||||
|             $routeParameters: '%chill_main.notifications%' | ||||
|  | ||||
|     Chill\MainBundle\Notification\NotificationRenderer: | ||||
|         autoconfigure: true | ||||
|         autowire: true | ||||
|   | ||||
| @@ -2,13 +2,15 @@ services: | ||||
|     chill_main.paginator_factory: | ||||
|         class: Chill\MainBundle\Pagination\PaginatorFactory | ||||
|         public: true | ||||
|         autowire: true | ||||
|         autoconfigure: true | ||||
|         arguments: | ||||
|             - "@request_stack" | ||||
|             - "@router" | ||||
|             - "%chill_main.pagination.item_per_page%" | ||||
|  | ||||
|     Chill\MainBundle\Pagination\PaginatorFactory: '@chill_main.paginator_factory' | ||||
|              | ||||
|  | ||||
|     chill_main.paginator.twig_extensions: | ||||
|         class: Chill\MainBundle\Pagination\ChillPaginationTwig | ||||
|         tags: | ||||
|   | ||||
| @@ -0,0 +1,6 @@ | ||||
| years_old: >- | ||||
|     {age, plural,  | ||||
|         one {# an} | ||||
|         many {# ans} | ||||
|         other {# ans} | ||||
|     } | ||||
| @@ -252,18 +252,6 @@ final class PersonController extends AbstractController | ||||
|          */ | ||||
|         $person = $form->getData(); | ||||
|  | ||||
|         $periods = $person->getAccompanyingPeriodsOrdered(); | ||||
|         $period = $periods[0]; | ||||
|         $period->setOpeningDate($form['creation_date']->getData()); | ||||
| //        $person = new Person($form['creation_date']->getData()); | ||||
| // | ||||
| //        $person->setFirstName($form['firstName']->getData()) | ||||
| //                ->setLastName($form['lastName']->getData()) | ||||
| //                ->setGender($form['gender']->getData()) | ||||
| //                ->setBirthdate($form['birthdate']->getData()) | ||||
| //                ->setCenter($form['center']->getData()) | ||||
| //                ; | ||||
|  | ||||
|         return $person; | ||||
|     } | ||||
|  | ||||
| @@ -364,7 +352,6 @@ final class PersonController extends AbstractController | ||||
|                 'lastName' => $form['lastName']->getData(), | ||||
|                 'birthdate' => $form['birthdate']->getData(), | ||||
|                 'gender' => $form['gender']->getData(), | ||||
|                 'creation_date' => $form['creation_date']->getData(), | ||||
|                 'form' => $form->createView())); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,39 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Chill\PersonBundle\DataFixtures\ORM; | ||||
|  | ||||
| use Doctrine\Common\DataFixtures\AbstractFixture; | ||||
| use Doctrine\Common\DataFixtures\DependentFixtureInterface; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
| use Chill\MainBundle\DataFixtures\ORM\LoadAbstractNotificationsTrait; | ||||
| use Chill\PersonBundle\DataFixtures\ORM\LoadAccompanyingPeriod; | ||||
|  | ||||
| /** | ||||
|  * Load notififications into database | ||||
|  */ | ||||
| class LoadAccompanyingPeriodNotifications extends AbstractFixture implements DependentFixtureInterface | ||||
| { | ||||
|     use LoadAbstractNotificationsTrait; | ||||
|  | ||||
|     public $notifs = [ | ||||
|         [ | ||||
|             'message' => 'Hello !', | ||||
|             'entityClass' => AccompanyingPeriod::class, | ||||
|             'entityRef' => LoadAccompanyingPeriod::ACCOMPANYING_PERIOD, | ||||
|             'sender' => 'center a_social', | ||||
|             'addressees' => [ | ||||
|                 'center a_social', | ||||
|                 'center a_administrative', | ||||
|                 'center a_direction', | ||||
|                 'multi_center' | ||||
|             ], | ||||
|         ] | ||||
|     ]; | ||||
|  | ||||
|     public function getDependencies() | ||||
|     { | ||||
|         return [ | ||||
|             LoadAccompanyingPeriod::class, | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -183,6 +183,14 @@ class LoadPeople extends AbstractFixture implements OrderedFixtureInterface, Con | ||||
|     private function addAPerson(array $person, ObjectManager $manager) | ||||
|     { | ||||
|         $p = new Person(); | ||||
|         $p->addAccompanyingPeriod( | ||||
|             new AccompanyingPeriod( | ||||
|                 (new \DateTime()) | ||||
|                     ->sub( | ||||
|                         new \DateInterval('P'.\random_int(0, 180).'D') | ||||
|                     ) | ||||
|             ) | ||||
|         ); | ||||
|  | ||||
|         foreach ($person as $key => $value) { | ||||
|             switch ($key) { | ||||
|   | ||||
| @@ -74,6 +74,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac | ||||
|         $loader->load('services/form.yaml'); | ||||
|         $loader->load('services/alt_names.yaml'); | ||||
|         $loader->load('services/household.yaml'); | ||||
|         $loader->load('services/notification.yaml'); | ||||
|         // We can get rid of this file when the service 'chill.person.repository.person' is no more used. | ||||
|         // We should use the PersonRepository service instead of a custom service name. | ||||
|         $loader->load('services/repository.yaml'); | ||||
|   | ||||
| @@ -379,12 +379,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI | ||||
|      */ | ||||
|     private Collection $householdAddresses; | ||||
|  | ||||
|     /** | ||||
|      * Person constructor. | ||||
|      * | ||||
|      * @param \DateTime|null $opening | ||||
|      */ | ||||
|     public function __construct(\DateTime $opening = null) | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->accompanyingPeriodParticipations = new ArrayCollection(); | ||||
|         $this->spokenLanguages = new ArrayCollection(); | ||||
| @@ -393,12 +388,6 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI | ||||
|         $this->otherPhoneNumbers = new ArrayCollection(); | ||||
|         $this->householdParticipations = new ArrayCollection(); | ||||
|         $this->householdAddresses = new ArrayCollection(); | ||||
|  | ||||
|         if ($opening === null) { | ||||
|             $opening = new \DateTime(); | ||||
|         } | ||||
|  | ||||
|         $this->open(new AccompanyingPeriod($opening)); | ||||
|         $this->genderComment = new CommentEmbeddable(); | ||||
|         $this->maritalStatusComment = new CommentEmbeddable(); | ||||
|     } | ||||
| @@ -734,9 +723,13 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI | ||||
|         return $this->birthdate; | ||||
|     } | ||||
|      | ||||
|     public function getAge(): int  | ||||
|     public function getAge(): ?int  | ||||
|     { | ||||
|         return date_diff($this->birthdate, date_create('now'))->format("%y"); | ||||
|         if ($this->birthdate instanceof \DateTimeInterface) { | ||||
|             return date_diff($this->birthdate, date_create('now'))->format("%y"); | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -26,7 +26,7 @@ use Symfony\Component\Form\FormBuilderInterface; | ||||
| use Symfony\Component\OptionsResolver\OptionsResolver; | ||||
| use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; | ||||
| use Symfony\Component\Form\Extension\Core\Type\HiddenType; | ||||
| use Symfony\Component\Form\Extension\Core\Type\DateType; | ||||
| use Chill\MainBundle\Form\Type\ChillDateType; | ||||
| use Chill\MainBundle\Form\Type\CenterType; | ||||
| use Chill\PersonBundle\Form\Type\GenderType; | ||||
| use Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer; | ||||
| @@ -80,9 +80,6 @@ final class CreationPersonType extends AbstractType | ||||
|                         'property_path' => 'birthdate' | ||||
|                     )) | ||||
|                     ->add('gender', HiddenType::class) | ||||
|                     ->add('creation_date', HiddenType::class, array( | ||||
|                         'mapped' => false | ||||
|                     )) | ||||
|                     ->add('form_status', HiddenType::class, array( | ||||
|                         'mapped' => false, | ||||
|                         'data' => $options['form_status'] | ||||
| @@ -99,25 +96,18 @@ final class CreationPersonType extends AbstractType | ||||
|              | ||||
|             $builder->get('birthdate') | ||||
|                     ->addModelTransformer($dateToStringTransformer); | ||||
|             $builder->get('creation_date') | ||||
|                     ->addModelTransformer($dateToStringTransformer); | ||||
|             $builder->get('center') | ||||
|                     ->addModelTransformer($this->centerTransformer); | ||||
|         } else { | ||||
|             $builder | ||||
|                 ->add('firstName') | ||||
|                 ->add('lastName') | ||||
|                 ->add('birthdate', DateType::class, array('required' => false, | ||||
|                     'widget' => 'single_text', 'format' => 'dd-MM-yyyy')) | ||||
|                 ->add('birthdate', ChillDateType::class, [ | ||||
|                     'required' => false, | ||||
|                 ]) | ||||
|                 ->add('gender', GenderType::class, array( | ||||
|                     'required' => true, 'placeholder' => null | ||||
|                 )) | ||||
|                 ->add('creation_date', DateType::class, array( | ||||
|                     'required' => true, | ||||
|                     'widget' => 'single_text', | ||||
|                     'format' => 'dd-MM-yyyy', | ||||
|                     'mapped' => false, | ||||
|                     'data' => new \DateTime())) | ||||
|                 ->add('form_status', HiddenType::class, array( | ||||
|                     'data' => $options['form_status'], | ||||
|                     'mapped' => false | ||||
|   | ||||
| @@ -0,0 +1,24 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Chill\PersonBundle\Notification; | ||||
|  | ||||
| use Chill\MainBundle\Entity\Notification; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
|  | ||||
| final class AccompanyingPeriodNotificationRenderer | ||||
| { | ||||
|     public function supports(Notification $notification) | ||||
|     { | ||||
|         return $notification->getRelatedEntityClass() == AccompanyingPeriod::class; | ||||
|     } | ||||
|  | ||||
|     public function getTemplate() | ||||
|     { | ||||
|         return 'ChillPersonBundle:AccompanyingPeriod:showInNotification.html.twig'; | ||||
|     } | ||||
|  | ||||
|     public function getTemplateData(Notification $notification) | ||||
|     { | ||||
|         return ['notification' => $notification]; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,3 @@ | ||||
| <a href="{{ path('chill_person_accompanying_course_index', {'accompanying_period_id': notification.relatedEntityId })  }}"> | ||||
|     Go to Acc. period. | ||||
| </a> | ||||
| @@ -76,10 +76,10 @@ | ||||
|                         {{ 'Unknown date of birth'|trans }} | ||||
|                     {% else %} | ||||
|                         {{ person.birthdate|format_date('short') }} | ||||
|                         <span class="age"> | ||||
|                           {{ 'years_old'|trans({ 'age': person.age }) }} | ||||
|                         </span> | ||||
|                     {% endif %} | ||||
|                     <span class="age"> | ||||
|                         {{ person.age ~ ((person.age > 1) ? ' ans' : ' an') }} | ||||
|                     </span> | ||||
|                 </div> | ||||
|                  | ||||
|                 {%- if chill_person.fields.nationality == 'visible' -%} | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| {# | ||||
|  * 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 | ||||
|  * published by the Free Software Foundation, either version 3 of the | ||||
|  *  License, or (at your option) any later version. | ||||
| @@ -38,8 +37,6 @@ | ||||
|                 {{ form_row(form.birthdate, { 'label' : 'Date of birth'|trans }) }} | ||||
|                              | ||||
|                 {{ form_row(form.gender, { 'label' : 'Gender'|trans }) }}  | ||||
|                              | ||||
|                 {{ form_row(form.creation_date, { 'label' : 'Creation date'|trans }) }}              | ||||
|                      | ||||
|                 {{ form_rest(form) }} | ||||
|                  | ||||
|   | ||||
| @@ -71,14 +71,15 @@ | ||||
|                         <dd>{{ person|chill_entity_render_string }}</dd> | ||||
|                          | ||||
|                         <dt>{{ 'Date of birth'|trans }}</dt> | ||||
|                         <dd>{{ birthdate|format_date('long')|default( 'Unknown date of birth'|trans ) }}</dd> | ||||
|                         {% if birthdate is empty %} | ||||
|                           <dd>{{ 'Unknown date of birth'|trans }}</dd> | ||||
|                         {% else %} | ||||
|                           <dd>{{ birthdate|format_date('long') }}</dd> | ||||
|                         {% endif %} | ||||
|                          | ||||
|                         <dt>{{ 'Gender'|trans }}</dt> | ||||
|                         <dd>{{ gender|trans }}</dd> | ||||
|                          | ||||
|                         <dt>{{ 'Creation date'|trans }}</dt> | ||||
|                         <dd>{{ creation_date|format_date('long') }}</dd> | ||||
|                          | ||||
|                         {% if form.altNames is defined %} | ||||
|                             {# mark as rendered #} | ||||
|                             {{ form_widget(form.altNames) }} | ||||
| @@ -86,10 +87,13 @@ | ||||
|                     </dl> | ||||
|                      | ||||
|                     {{ form_rest(form) }} | ||||
|                     <button class="btn btn-submit" type="submit"><i class="fa fa-check"></i> {{ 'Confirm the creation'|trans }}</button> | ||||
|                     <ul class="record_actions"> | ||||
|                       <li> | ||||
|                         <button class="sc-button bt-create change-icon" type="submit"><i class="fa fa-check"></i> {{ 'Confirm the creation'|trans }}</button> | ||||
|                       </li> | ||||
|                     </ul> | ||||
|                 {{ form_end(form) }} | ||||
|             </div> | ||||
|  | ||||
|         </div> | ||||
|     </div> | ||||
| </div>     | ||||
|   | ||||
| @@ -152,7 +152,7 @@ class AccompanyingPeriodControllerTest extends WebTestCase | ||||
|      *      with : dateClosing: 2015-02-01 | ||||
|      *      with : the last closing motive in list | ||||
|      * Then the response should redirect to period view | ||||
|      * And the next page should have a `.error` element present in page | ||||
|      * And the next page should have a `.alert-danger` element present in page | ||||
|      *  | ||||
|      * @todo | ||||
|      */ | ||||
| @@ -174,7 +174,7 @@ class AccompanyingPeriodControllerTest extends WebTestCase | ||||
|               '/fr/person/'.$this->person->getId().'/accompanying-period'), | ||||
|               'the server redirects to /accompanying-period page'); | ||||
|         $this->assertGreaterThan(0, $this->client->followRedirect() | ||||
|                 ->filter('.success')->count(), | ||||
|                 ->filter('.alert-success')->count(), | ||||
|               "a 'success' element is shown"); | ||||
|     } | ||||
|      | ||||
| @@ -186,7 +186,7 @@ class AccompanyingPeriodControllerTest extends WebTestCase | ||||
|      *      with : dateClosing: 2014-01-01 | ||||
|      *      with : the last closing motive in list | ||||
|      * Then the response should redirect to period view | ||||
|      * And the next page should have a `.error` element present in page | ||||
|      * And the next page should have a `.alert-danger` element present in page | ||||
|      *  | ||||
|      * @todo | ||||
|      */ | ||||
| @@ -207,8 +207,8 @@ class AccompanyingPeriodControllerTest extends WebTestCase | ||||
|         $this->assertFalse($this->client->getResponse()->isRedirect(), | ||||
|               'the server stays on the /close page'); | ||||
|         $this->assertGreaterThan(0, $crawlerResponse | ||||
|               ->filter('.error')->count(), | ||||
|               "an '.error' element is shown"); | ||||
|               ->filter('.alert-danger')->count(), | ||||
|               "an '.alert-danger' element is shown"); | ||||
|     } | ||||
|      | ||||
|     /** | ||||
| @@ -240,7 +240,7 @@ class AccompanyingPeriodControllerTest extends WebTestCase | ||||
|               '/fr/person/'.$this->person->getId().'/accompanying-period'), | ||||
|               'the server redirects to /accompanying-period page'); | ||||
|         $this->assertGreaterThan(0, $this->client->followRedirect() | ||||
|               ->filter('.success')->count(), | ||||
|               ->filter('.alert-success')->count(), | ||||
|               "a 'success' element is shown"); | ||||
|     } | ||||
|      | ||||
| @@ -275,7 +275,7 @@ class AccompanyingPeriodControllerTest extends WebTestCase | ||||
|          | ||||
|         $this->assertFalse($this->client->getResponse()->isRedirect(), | ||||
|               'the server stay on form page'); | ||||
|         $this->assertGreaterThan(0, $crawler->filter('.error')->count(), | ||||
|         $this->assertGreaterThan(0, $crawler->filter('.alert-danger')->count(), | ||||
|               "an 'error' element is shown"); | ||||
|     } | ||||
|      | ||||
| @@ -310,7 +310,7 @@ class AccompanyingPeriodControllerTest extends WebTestCase | ||||
|          | ||||
|         $this->assertFalse($this->client->getResponse()->isRedirect(), | ||||
|               'the server stay on form page'); | ||||
|         $this->assertGreaterThan(0, $crawler->filter('.error')->count(), | ||||
|         $this->assertGreaterThan(0, $crawler->filter('.alert-danger')->count(), | ||||
|               "an 'error' element is shown"); | ||||
|     } | ||||
|      | ||||
| @@ -351,7 +351,7 @@ class AccompanyingPeriodControllerTest extends WebTestCase | ||||
|          | ||||
|         $this->assertFalse($this->client->getResponse()->isRedirect(), | ||||
|               'the server stay on form page'); | ||||
|         $this->assertGreaterThan(0, $crawlerResponse->filter('.error')->count(), | ||||
|         $this->assertGreaterThan(0, $crawlerResponse->filter('.alert-danger')->count(), | ||||
|               "an 'error' element is shown"); | ||||
|     } | ||||
|      | ||||
| @@ -382,7 +382,7 @@ class AccompanyingPeriodControllerTest extends WebTestCase | ||||
|          | ||||
|         $this->assertFalse($this->client->getResponse()->isRedirect(), | ||||
|               'the server stay on form page'); | ||||
|         $this->assertGreaterThan(0, $crawler->filter('.error')->count(), | ||||
|         $this->assertGreaterThan(0, $crawler->filter('.alert-danger')->count(), | ||||
|               "an 'error' element is shown"); | ||||
|     } | ||||
|      | ||||
| @@ -424,7 +424,7 @@ class AccompanyingPeriodControllerTest extends WebTestCase | ||||
|          | ||||
|         $this->assertFalse($this->client->getResponse()->isRedirect(), | ||||
|               'the server stay on form page'); | ||||
|         $this->assertGreaterThan(0, $crawlerResponse->filter('.error')->count(), | ||||
|         $this->assertGreaterThan(0, $crawlerResponse->filter('.alert-danger')->count(), | ||||
|               "an 'error' element is shown"); | ||||
|     } | ||||
|      | ||||
| @@ -465,7 +465,7 @@ class AccompanyingPeriodControllerTest extends WebTestCase | ||||
|          | ||||
|         $this->assertFalse($this->client->getResponse()->isRedirect(), | ||||
|               'the server stay on form page'); | ||||
|         $this->assertGreaterThan(0, $crawlerResponse->filter('.error')->count(), | ||||
|         $this->assertGreaterThan(0, $crawlerResponse->filter('.alert-danger')->count(), | ||||
|               "an 'error' element is shown"); | ||||
|     } | ||||
|      | ||||
|   | ||||
| @@ -93,8 +93,6 @@ class PersonControllerCreateTest extends WebTestCase | ||||
|               'The page contains a "gender" input'); | ||||
|         $this->assertTrue($form->has(self::BIRTHDATE_INPUT),  | ||||
|               'The page has a "date of birth" input'); | ||||
|         $this->assertTrue($form->has(self::CREATEDATE_INPUT), | ||||
|               'The page contains a "creation date" input'); | ||||
|          | ||||
|         $genderType = $form->get(self::GENDER_INPUT); | ||||
|         $this->assertEquals('radio', $genderType->getType(),  | ||||
| @@ -107,10 +105,6 @@ class PersonControllerCreateTest extends WebTestCase | ||||
|               'gender has "femme" option'); | ||||
|         $this->assertFalse($genderType->hasValue(), 'The gender input is not checked'); | ||||
|          | ||||
|         $today = new \DateTime(); | ||||
|         $this->assertEquals($today->format('d-m-Y'), $form->get(self::CREATEDATE_INPUT) | ||||
|               ->getValue(), 'The creation date input has the current date by default'); | ||||
|          | ||||
|         return $form; | ||||
|     } | ||||
|      | ||||
|   | ||||
| @@ -102,7 +102,6 @@ class PersonControllerUpdateTest extends WebTestCase | ||||
|     public function testHiddenFielsArePresent() | ||||
|     { | ||||
|         $crawler = $this->client->request('GET', $this->editUrl); | ||||
|  | ||||
|         $configurables = array('placeOfBirth', 'phonenumber', 'email', | ||||
|             'countryOfBirth', 'nationality', 'spokenLanguages', 'maritalStatus'); | ||||
|         $form = $crawler->selectButton('Enregistrer')->form(); //; | ||||
| @@ -190,7 +189,7 @@ class PersonControllerUpdateTest extends WebTestCase | ||||
|             'the value '.$field.' is updated in db'); | ||||
|  | ||||
|         $crawler = $this->client->followRedirect(); | ||||
|         $this->assertGreaterThan(0, $crawler->filter('.success')->count(), | ||||
|         $this->assertGreaterThan(0, $crawler->filter('.alert-success')->count(), | ||||
|             'a element .success is shown'); | ||||
|  | ||||
|         if($field == 'birthdate' or $field == 'memo' or $field == 'countryOfBirth' or $field == 'nationality' | ||||
| @@ -245,7 +244,7 @@ class PersonControllerUpdateTest extends WebTestCase | ||||
|  | ||||
|         $this->assertFalse($this->client->getResponse()->isRedirect(), | ||||
|             'the page is not redirected to /general'); | ||||
|         $this->assertGreaterThan(0, $crawler->filter('.error')->count(), | ||||
|         $this->assertGreaterThan(0, $crawler->filter('.alert-danger')->count(), | ||||
|             'a element .error is shown'); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -45,11 +45,12 @@ class PersonTest extends \PHPUnit\Framework\TestCase | ||||
|     public function testGetCurrentAccompanyingPeriod() | ||||
|     { | ||||
|         $d = new \DateTime('yesterday');  | ||||
|         $p = new Person($d); | ||||
|         $p = new Person(); | ||||
|         $p->addAccompanyingPeriod(new AccompanyingPeriod($d)); | ||||
|          | ||||
|         $period = $p->getCurrentAccompanyingPeriod(); | ||||
|          | ||||
|         $this->assertInstanceOf('Chill\PersonBundle\Entity\AccompanyingPeriod', $period); | ||||
|         $this->assertInstanceOf(AccompanyingPeriod::class, $period); | ||||
|         $this->assertTrue($period->isOpen()); | ||||
|         $this->assertEquals($d, $period->getOpeningDate()); | ||||
|          | ||||
| @@ -67,7 +68,8 @@ class PersonTest extends \PHPUnit\Framework\TestCase | ||||
|     public function testAccompanyingPeriodOrderWithUnorderedAccompanyingPeriod() | ||||
|     {        | ||||
|         $d = new \DateTime("2013/2/1"); | ||||
|         $p = new Person($d); | ||||
|         $p = new Person(); | ||||
|         $p->addAccompanyingPeriod(new AccompanyingPeriod($d)); | ||||
|          | ||||
|         $e = new \DateTime("2013/3/1"); | ||||
|         $period = $p->getCurrentAccompanyingPeriod()->setClosingDate($e); | ||||
| @@ -93,7 +95,8 @@ class PersonTest extends \PHPUnit\Framework\TestCase | ||||
|      */ | ||||
|     public function testAccompanyingPeriodOrderSameDateOpening() { | ||||
|         $d = new \DateTime("2013/2/1"); | ||||
|         $p = new Person($d); | ||||
|         $p = new Person(); | ||||
|         $p->addAccompanyingPeriod(new AccompanyingPeriod($d)); | ||||
|          | ||||
|         $g = new \DateTime("2013/4/1");  | ||||
|         $period = $p->getCurrentAccompanyingPeriod()->setClosingDate($g); | ||||
| @@ -120,7 +123,8 @@ class PersonTest extends \PHPUnit\Framework\TestCase | ||||
|      */ | ||||
|     public function testDateCoveringWithCoveringAccompanyingPeriod() { | ||||
|         $d = new \DateTime("2013/2/1"); | ||||
|         $p = new Person($d); | ||||
|         $p = new Person(); | ||||
|         $p->addAccompanyingPeriod(new AccompanyingPeriod($d)); | ||||
|          | ||||
|         $e = new \DateTime("2013/3/1"); | ||||
|         $period = $p->getCurrentAccompanyingPeriod()->setClosingDate($e); | ||||
| @@ -145,7 +149,8 @@ class PersonTest extends \PHPUnit\Framework\TestCase | ||||
|      */ | ||||
|     public function testNotOpenAFileReOpenedLater() { | ||||
|         $d = new \DateTime("2013/2/1"); | ||||
|         $p = new Person($d); | ||||
|         $p = new Person(); | ||||
|         $p->addAccompanyingPeriod(new AccompanyingPeriod($d)); | ||||
|          | ||||
|         $e = new \DateTime("2013/3/1"); | ||||
|         $period = $p->getCurrentAccompanyingPeriod()->setClosingDate($e); | ||||
|   | ||||
| @@ -20,9 +20,11 @@ | ||||
|  | ||||
| namespace Chill\PersonBundle\Tests\Timeline; | ||||
|  | ||||
| use Symfony\Bundle\SecurityBundle\Tests\Functional\WebTestCase; | ||||
| use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; | ||||
| use Chill\PersonBundle\Entity\Person; | ||||
| use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
| use Doctrine\ORM\EntityManagerInterface; | ||||
| use Chill\MainBundle\Test\PrepareClientTrait; | ||||
|  | ||||
| /** | ||||
|  * This class tests entries are shown for closing and opening  | ||||
| @@ -31,22 +33,20 @@ use Chill\PersonBundle\Entity\AccompanyingPeriod; | ||||
|  * @author Julien Fastré <julien.fastre@champs-libres.coop> | ||||
|  * @author Champs Libres <info@champs-libres.coop> | ||||
|  */ | ||||
| class TimelineAccompanyingPeriodTest extends \Chill\PersonBundle\Tests\Controller\AccompanyingPeriodControllerTest | ||||
| class TimelineAccompanyingPeriodTest extends WebTestCase | ||||
| { | ||||
|     public function testEntriesAreShown()  | ||||
|     use PrepareClientTrait; | ||||
|  | ||||
|     /** | ||||
|      * @dataProvider provideDataPersonWithAccompanyingPeriod | ||||
|      */ | ||||
|     public function testEntriesAreShown($personId)  | ||||
|     { | ||||
|         $this->generatePeriods(array( | ||||
|             [ | ||||
|                 'openingDate' => '2014-01-01', | ||||
|                 'closingDate' => '2014-12-31', | ||||
|                 'closingMotive' => $this->getRandomClosingMotive() | ||||
|             ] | ||||
|         )); | ||||
|         $client = $this->getClientAuthenticated(); | ||||
|  | ||||
|         $crawler = $client->request('GET', "/en/person/{$personId}/timeline"); | ||||
|          | ||||
|         $crawler = $this->client->request('GET', '/en/person/' | ||||
|               .$this->person->getId().'/timeline'); | ||||
|          | ||||
|         $this->assertTrue($this->client->getResponse()->isSuccessful(), | ||||
|         $this->assertTrue($client->getResponse()->isSuccessful(), | ||||
|               "the timeline page loads sucessfully"); | ||||
|         $this->assertGreaterThan(0, $crawler->filter('.timeline div')->count(), | ||||
|               "the timeline page contains multiple div inside a .timeline element"); | ||||
| @@ -57,5 +57,34 @@ class TimelineAccompanyingPeriodTest extends \Chill\PersonBundle\Tests\Controlle | ||||
|               $crawler->Filter('.timeline')->text(), | ||||
|               "the text 'Une période d'accompagnement a été fermée' is present"); | ||||
|     } | ||||
|  | ||||
|     public function provideDataPersonWithAccompanyingPeriod() | ||||
|     { | ||||
|         self::bootKernel(); | ||||
|  | ||||
|         $qb = self::$container->get(EntityManagerInterface::class) | ||||
|                               ->createQueryBuilder() | ||||
|                           ; | ||||
|         $personIds = $qb | ||||
|             ->from(Person::class, 'p') | ||||
|             ->join('p.accompanyingPeriodParticipations', 'part') | ||||
|             ->join('part.accompanyingPeriod', 'period') | ||||
|             ->join('p.center', 'center') | ||||
|             ->select('p.id') | ||||
|             ->where($qb->expr()->isNotNull('period.closingDate')) | ||||
|             ->andWhere($qb->expr()->eq('center.name', ':center')) | ||||
|             ->setParameter('center', 'Center A') | ||||
|             ->setMaxResults(1000) | ||||
|             ->getQuery() | ||||
|             ->getResult() | ||||
|         ; | ||||
|  | ||||
|         \shuffle($personIds); | ||||
|  | ||||
|         yield [ \array_pop($personIds)['id'] ]; | ||||
|         yield [ \array_pop($personIds)['id'] ]; | ||||
|         yield [ \array_pop($personIds)['id'] ]; | ||||
|  | ||||
|     } | ||||
|     | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,3 @@ | ||||
| services: | ||||
|     Chill\PersonBundle\Notification\AccompanyingPeriodNotificationRenderer: | ||||
|         autowire: true | ||||
		Reference in New Issue
	
	Block a user