cs: Fix code style (safe rules only).

This commit is contained in:
Pol Dellaiera
2021-11-23 14:06:38 +01:00
parent 149d7ce991
commit 8f96a1121d
1223 changed files with 65199 additions and 64625 deletions

View File

@@ -1,5 +1,12 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;

View File

@@ -1,325 +1,69 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\Controller;
use Chill\MainBundle\Pagination\PaginatorFactory;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\PersonBundle\Privacy\PrivacyEvent;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Privacy\PrivacyEvent;
use Chill\ReportBundle\Entity\Report;
use Chill\ReportBundle\Form\ReportType;
use DateTime;
use RuntimeException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Role\Role;
/**
* Class ReportController
*
* @package Chill\ReportBundle\Controller
* Class ReportController.
*/
class ReportController extends AbstractController
{
/**
* @var EventDispatcherInterface
*/
protected $eventDispatcher;
/**
* @var AuthorizationHelper
*/
protected $authorizationHelper;
/**
* @var EventDispatcherInterface
*/
protected $eventDispatcher;
/**
* @var PaginatorFactory
*/
protected $paginator;
/**
* ReportController constructor.
*
* @param EventDispatcherInterface $eventDispatcher
* @param AuthorizationHelper $authorizationHelper
* @param PaginatorFactory $paginator
*/
public function __construct(
EventDispatcherInterface $eventDispatcher,
AuthorizationHelper $authorizationHelper,
PaginatorFactory $paginator
)
{
) {
$this->eventDispatcher = $eventDispatcher;
$this->authorizationHelper = $authorizationHelper;
$this->paginator = $paginator;
}
/**
* List all the report entities for a given person.
*
* @param integer $person_id The id of the person.
* @param Request $request The request
* @return Response The web page.
*/
public function listAction($person_id, Request $request)
{
$em = $this->getDoctrine()->getManager();
$person = $em->getRepository('ChillPersonBundle:Person')->find($person_id);
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
$reachableScopes = $this->authorizationHelper
->getReachableScopes($this->getUser(), new Role('CHILL_REPORT_SEE'),
$person->getCenter());
$total = $em
->createQuery("SELECT COUNT(r.id) FROM ChillReportBundle:Report r "
. "WHERE r.person = :person AND r.scope IN (:scopes) ")
->setParameter('person', $person)
->setParameter('scopes', $reachableScopes)
->getSingleScalarResult();
// get the PaginatorFactory
$paginator = $this->paginator->create($total);
$reports = $em->createQuery('SELECT r
FROM ChillReportBundle:Report r
WHERE r.person = :person AND r.scope IN (:scopes)
ORDER BY r.date DESC')
->setParameter('person', $person)
->setParameter('scopes', $reachableScopes)
->setFirstResult($paginator->getCurrentPage()->getFirstItemNumber())
->setMaxResults($paginator->getItemsPerPage())
->getResult()
;
$event = new PrivacyEvent($person, array(
'element_class' => Report::class,
'action' => 'list'
));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
return $this->render('ChillReportBundle:Report:list.html.twig', array(
'reports' => $reports,
'person' => $person,
'paginator' => $paginator
));
}
/**
* Display a form for selecting which type of report to add for a given person
* Create a new report for a given person and of a given type.
*
* @param integer $person_id The id of the person.
* @param Request $request The request
* @return Response The web page.
*/
public function selectReportTypeAction($person_id, Request $request)
{
$em = $this->getDoctrine()->getManager();
$person = $em->getRepository('ChillPersonBundle:Person')
->find($person_id);
if ($person === NULL) {
throw $this->createNotFoundException('Person not found!');
}
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person, 'access denied for person view');
// check access on report creation for a dummy report
$this->denyAccessUnlessGranted('CHILL_REPORT_CREATE',
(new Report())->setPerson($person), 'access denied for report creation');
$cFGroupId = $request->query->get('cFGroup');
if($cFGroupId) {
return $this->redirect(
$this->generateUrl('report_new',
array('person_id' => $person_id, 'cf_group_id' => $cFGroupId)));
}
$cFGroups = $em->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')
->findByEntity('Chill\ReportBundle\Entity\Report');
if(count($cFGroups) === 1 ){
return $this->redirect(
$this->generateUrl('report_new',
array('person_id' => $person_id, 'cf_group_id' => $cFGroups[0]->getId())));
}
$cFGroupsChoice = array();
foreach ($cFGroups as $cFGroup) {
$cFGroupsChoice[$cFGroup->getId()] = $cFGroup->getName($request->getLocale());
}
$form = $this->get('form.factory')
->createNamedBuilder(null, FormType::class, null, array(
'method' => 'GET',
'csrf_protection' => false
))
->add('cFGroup', ChoiceType::class, array(
'choices' => array_combine(array_values($cFGroupsChoice),array_keys($cFGroupsChoice)),
))
->getForm();
$person = $em->getRepository('ChillPersonBundle:Person')->find($person_id);
return $this->render('ChillReportBundle:Report:select_report_type.html.twig', array(
'form' => $form->createView(),
'person' => $person
));
}
/**
* Display a form for selecting which type of report to export
* (a csv file with all the report of this type)
*
* @param Request $request The request
* @return Response The web page.
*/
public function selectReportTypeForExportAction(Request $request)
{
$cFGroupId = $request->query->get('cFGroup');
if($cFGroupId) {
return $this->redirect(
$this->generateUrl('report_export_list',
array('cf_group_id' => $cFGroupId)));
}
$em = $this->getDoctrine()->getManager();
$cFGroups = $em->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')
->findByEntity('Chill\ReportBundle\Entity\Report');
if(count($cFGroups) === 1 ){
return $this->redirect(
$this->generateUrl('report_export_list',
array('cf_group_id' => $cFGroups[0]->getId())));
}
$cFGroupsChoice = array();
foreach ($cFGroups as $cFGroup) {
$cFGroupsChoice[$cFGroup->getId()] = $cFGroup->getName($request->getLocale());
}
$form = $this->get('form.factory')
->createNamedBuilder(null, FormType::class, null, array(
'method' => 'GET',
'csrf_protection' => false
))
->add('cFGroup', ChoiceType::class, array(
'choices' => array_combine(array_values($cFGroupsChoice),array_keys($cFGroupsChoice)),
))
->getForm();
return $this->render('ChillReportBundle:Report:select_report_type_for_export.html.twig', array(
'form' => $form->createView(),
'layout_name' => "@ChillMain/Export/layout.html.twig"
));
}
/**
* Return a csv file with all the reports of a given type
*
* @param integer $cf_group_id The id of the report type to export
* @param Request $request The request
* @return A csv file with all the reports of the selected type
*/
public function exportAction($cf_group_id, Request $request)
{
$em = $this->getDoctrine()->getManager();
$cFGroup = $em->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')->find($cf_group_id);
$reports = $em->getRepository('ChillReportBundle:Report')->findByCFGroup($cFGroup);
$response = $this->render('ChillReportBundle:Report:export.csv.twig', array(
'reports' => $reports,
'cf_group' => $cFGroup
));
$response->headers->set('Content-Type', 'text/csv; charset=utf-8');
$response->headers->set('Content-Disposition', 'attachment; filename="export.csv"');
return $response;
}
/**
* Display a form for creating a new report for a given person and of a given type
*
* @param integer $person_id The id of the person.
* @param integer $cf_group_id The id of the report type.
* @param Request $request The request
* @return Response The web page.
*/
public function newAction($person_id, $cf_group_id, Request $request)
{
$em = $this->getDoctrine()->getManager();
$person = $em->getRepository('ChillPersonBundle:Person')->find($person_id);
$cFGroup = $em
->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')
->find($cf_group_id);
if ($person === NULL) {
throw $this->createNotFoundException("Person not found");
}
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
// check access on report creation for a dummy report
$this->denyAccessUnlessGranted('CHILL_REPORT_CREATE',
(new Report())->setPerson($person), 'access denied for report creation');
if ($cFGroup === NULL){
throw $this->createNotFoundException("custom fields group not found");
}
$entity = new Report();
$entity->setUser($this->get('security.token_storage')->getToken()->getUser());
$entity->setDate(new \DateTime('now'));
$entity->setCFGroup($cFGroup);
$form = $this->createCreateForm($entity, $person, $cFGroup);
return $this->render('ChillReportBundle:Report:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
'person' => $person
));
}
/**
* Create a new report for a given person and of a given type
*
* @param integer $person_id The id of the person.
* @param integer $cf_group_id The id of the report type.
* @param int $person_id The id of the person.
* @param int $cf_group_id The id of the report type.
* @param Request $request The request containing the form data (from the newAction)
*
* @return Response The web page.
*/
public function createAction($person_id, $cf_group_id, Request $request)
@@ -328,12 +72,12 @@ class ReportController extends AbstractController
$entity = new Report();
$cFGroup = $em->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')
->find($cf_group_id);
->find($cf_group_id);
$person = $em->getRepository('ChillPersonBundle:Person')
->find($person_id);
->find($person_id);
if($person === NULL || $cFGroup === NULL) {
if (null === $person || null === $cFGroup) {
throw $this->createNotFoundException();
}
@@ -353,94 +97,38 @@ class ReportController extends AbstractController
$this->get('session')
->getFlashBag()
->add('success',
->add(
'success',
$this->get('translator')
->trans('Success : report created!')
);
return $this->redirect($this->generateUrl('report_view',
array('person_id' => $person_id,'report_id' => $entity->getId())));
return $this->redirect($this->generateUrl(
'report_view',
['person_id' => $person_id, 'report_id' => $entity->getId()]
));
}
$this->get('session')
->getFlashBag()->add('error',
->getFlashBag()->add(
'error',
$this->get('translator')
->trans('The form is not valid. The report has not been created !')
);
return $this->render('ChillReportBundle:Report:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
'person' => $person
));
}
/**
* Creates a form to create a Report entity.
*
* @param Report $entity The entity
* @param integer $person_id The id of the person.
* @param integer $cf_group_id The id of the report type.
*
* @return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(Report $entity, Person $person, $cFGroup)
{
$form = $this->createForm(ReportType::class, $entity, array(
'action' => $this->generateUrl('report_create',
array('person_id' => $person->getId(),
'cf_group_id' => $cFGroup->getId())),
'method' => 'POST',
'cFGroup' => $cFGroup,
'role' => new Role('CHILL_REPORT_CREATE'),
'center' => $person->getCenter()
));
return $form;
}
/**
* Find and display a report.
*
* @param integer $report_id The id of the report.
* @param integer $person_id The id of the person.
* @return Response The web page.
*/
public function viewAction($report_id, $person_id)
{
$em = $this->getDoctrine()->getManager();
$person = $em->getRepository('ChillPersonBundle:Person')->find($person_id);
$entity = $em->getRepository('ChillReportBundle:Report')->find($report_id);
if (!$entity || !$person) {
throw $this->createNotFoundException(
$this->get('translator')->trans('Unable to find this report.'));
}
$this->denyAccessUnlessGranted('CHILL_REPORT_SEE', $entity);
$event = new PrivacyEvent($person, array(
'element_class' => Report::class,
'element_id' => $entity->getId(),
'action' => 'view'
));
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
return $this->render('ChillReportBundle:Report:view.html.twig', array(
return $this->render('ChillReportBundle:Report:new.html.twig', [
'entity' => $entity,
'form' => $form->createView(),
'person' => $person,
));
]);
}
/**
* Display a form to edit an existing Report entity.
*
* @param integer $person_id The id of the person.
* @param integer $report_id The id of the report.
* @param int $person_id The id of the person.
* @param int $report_id The id of the report.
*
* @return Response The web page.
*/
public function editAction($person_id, $report_id, Request $request)
@@ -451,12 +139,15 @@ class ReportController extends AbstractController
if (!$report) {
throw $this->createNotFoundException(
$this->get('translator')->trans('Unable to find this report.'));
$this->get('translator')->trans('Unable to find this report.')
);
}
if(intval($person_id) !== intval($report->getPerson()->getId())) {
throw new \RuntimeException(
$this->get('translator')->trans('This is not the report of the person.'), 1);
if (intval($person_id) !== intval($report->getPerson()->getId())) {
throw new RuntimeException(
$this->get('translator')->trans('This is not the report of the person.'),
1
);
}
$this->denyAccessUnlessGranted('CHILL_REPORT_UPDATE', $report);
@@ -464,47 +155,288 @@ class ReportController extends AbstractController
$person = $report->getPerson();
$editForm = $this->createEditForm($report);
$event = new PrivacyEvent($person, array(
$event = new PrivacyEvent($person, [
'element_class' => Report::class,
'element_id' => $report->getId(),
'action' => 'edit'
));
'action' => 'edit',
]);
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
return $this->render('ChillReportBundle:Report:edit.html.twig', array(
'edit_form' => $editForm->createView(),
return $this->render('ChillReportBundle:Report:edit.html.twig', [
'edit_form' => $editForm->createView(),
'person' => $person,
));
]);
}
/**
* Creates a form to edit a Report entity.
* Return a csv file with all the reports of a given type.
*
* @param Report $entity The report to edit.
* @param integer $person_id The id of the person.
* @return \Symfony\Component\Form\Form The form
* @param int $cf_group_id The id of the report type to export
* @param Request $request The request
*
* @return A csv file with all the reports of the selected type
*/
private function createEditForm(Report $entity)
public function exportAction($cf_group_id, Request $request)
{
$form = $this->createForm(ReportType::class, $entity, array(
'action' => $this->generateUrl('report_update',
array('person_id' => $entity->getPerson()->getId(),
'report_id' => $entity->getId())),
'method' => 'PUT',
'cFGroup' => $entity->getCFGroup(),
'role' => new Role('CHILL_REPORT_UPDATE'),
'center' => $entity->getPerson()->getCenter()
));
$em = $this->getDoctrine()->getManager();
return $form;
$cFGroup = $em->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')->find($cf_group_id);
$reports = $em->getRepository('ChillReportBundle:Report')->findByCFGroup($cFGroup);
$response = $this->render('ChillReportBundle:Report:export.csv.twig', [
'reports' => $reports,
'cf_group' => $cFGroup,
]);
$response->headers->set('Content-Type', 'text/csv; charset=utf-8');
$response->headers->set('Content-Disposition', 'attachment; filename="export.csv"');
return $response;
}
/**
* List all the report entities for a given person.
*
* @param int $person_id The id of the person.
* @param Request $request The request
*
* @return Response The web page.
*/
public function listAction($person_id, Request $request)
{
$em = $this->getDoctrine()->getManager();
$person = $em->getRepository('ChillPersonBundle:Person')->find($person_id);
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
$reachableScopes = $this->authorizationHelper
->getReachableScopes(
$this->getUser(),
new Role('CHILL_REPORT_SEE'),
$person->getCenter()
);
$total = $em
->createQuery('SELECT COUNT(r.id) FROM ChillReportBundle:Report r '
. 'WHERE r.person = :person AND r.scope IN (:scopes) ')
->setParameter('person', $person)
->setParameter('scopes', $reachableScopes)
->getSingleScalarResult();
// get the PaginatorFactory
$paginator = $this->paginator->create($total);
$reports = $em->createQuery('SELECT r
FROM ChillReportBundle:Report r
WHERE r.person = :person AND r.scope IN (:scopes)
ORDER BY r.date DESC')
->setParameter('person', $person)
->setParameter('scopes', $reachableScopes)
->setFirstResult($paginator->getCurrentPage()->getFirstItemNumber())
->setMaxResults($paginator->getItemsPerPage())
->getResult();
$event = new PrivacyEvent($person, [
'element_class' => Report::class,
'action' => 'list',
]);
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
return $this->render('ChillReportBundle:Report:list.html.twig', [
'reports' => $reports,
'person' => $person,
'paginator' => $paginator,
]);
}
/**
* Display a form for creating a new report for a given person and of a given type.
*
* @param int $person_id The id of the person.
* @param int $cf_group_id The id of the report type.
* @param Request $request The request
*
* @return Response The web page.
*/
public function newAction($person_id, $cf_group_id, Request $request)
{
$em = $this->getDoctrine()->getManager();
$person = $em->getRepository('ChillPersonBundle:Person')->find($person_id);
$cFGroup = $em
->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')
->find($cf_group_id);
if (null === $person) {
throw $this->createNotFoundException('Person not found');
}
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person);
// check access on report creation for a dummy report
$this->denyAccessUnlessGranted(
'CHILL_REPORT_CREATE',
(new Report())->setPerson($person),
'access denied for report creation'
);
if (null === $cFGroup) {
throw $this->createNotFoundException('custom fields group not found');
}
$entity = new Report();
$entity->setUser($this->get('security.token_storage')->getToken()->getUser());
$entity->setDate(new DateTime('now'));
$entity->setCFGroup($cFGroup);
$form = $this->createCreateForm($entity, $person, $cFGroup);
return $this->render('ChillReportBundle:Report:new.html.twig', [
'entity' => $entity,
'form' => $form->createView(),
'person' => $person,
]);
}
/**
* Display a form for selecting which type of report to add for a given person.
*
* @param int $person_id The id of the person.
* @param Request $request The request
*
* @return Response The web page.
*/
public function selectReportTypeAction($person_id, Request $request)
{
$em = $this->getDoctrine()->getManager();
$person = $em->getRepository('ChillPersonBundle:Person')
->find($person_id);
if (null === $person) {
throw $this->createNotFoundException('Person not found!');
}
$this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person, 'access denied for person view');
// check access on report creation for a dummy report
$this->denyAccessUnlessGranted(
'CHILL_REPORT_CREATE',
(new Report())->setPerson($person),
'access denied for report creation'
);
$cFGroupId = $request->query->get('cFGroup');
if ($cFGroupId) {
return $this->redirect(
$this->generateUrl(
'report_new',
['person_id' => $person_id, 'cf_group_id' => $cFGroupId]
)
);
}
$cFGroups = $em->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')
->findByEntity('Chill\ReportBundle\Entity\Report');
if (count($cFGroups) === 1) {
return $this->redirect(
$this->generateUrl(
'report_new',
['person_id' => $person_id, 'cf_group_id' => $cFGroups[0]->getId()]
)
);
}
$cFGroupsChoice = [];
foreach ($cFGroups as $cFGroup) {
$cFGroupsChoice[$cFGroup->getId()] = $cFGroup->getName($request->getLocale());
}
$form = $this->get('form.factory')
->createNamedBuilder(null, FormType::class, null, [
'method' => 'GET',
'csrf_protection' => false,
])
->add('cFGroup', ChoiceType::class, [
'choices' => array_combine(array_values($cFGroupsChoice), array_keys($cFGroupsChoice)),
])
->getForm();
$person = $em->getRepository('ChillPersonBundle:Person')->find($person_id);
return $this->render('ChillReportBundle:Report:select_report_type.html.twig', [
'form' => $form->createView(),
'person' => $person,
]);
}
/**
* Display a form for selecting which type of report to export
* (a csv file with all the report of this type).
*
* @param Request $request The request
*
* @return Response The web page.
*/
public function selectReportTypeForExportAction(Request $request)
{
$cFGroupId = $request->query->get('cFGroup');
if ($cFGroupId) {
return $this->redirect(
$this->generateUrl(
'report_export_list',
['cf_group_id' => $cFGroupId]
)
);
}
$em = $this->getDoctrine()->getManager();
$cFGroups = $em->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')
->findByEntity('Chill\ReportBundle\Entity\Report');
if (count($cFGroups) === 1) {
return $this->redirect(
$this->generateUrl(
'report_export_list',
['cf_group_id' => $cFGroups[0]->getId()]
)
);
}
$cFGroupsChoice = [];
foreach ($cFGroups as $cFGroup) {
$cFGroupsChoice[$cFGroup->getId()] = $cFGroup->getName($request->getLocale());
}
$form = $this->get('form.factory')
->createNamedBuilder(null, FormType::class, null, [
'method' => 'GET',
'csrf_protection' => false,
])
->add('cFGroup', ChoiceType::class, [
'choices' => array_combine(array_values($cFGroupsChoice), array_keys($cFGroupsChoice)),
])
->getForm();
return $this->render('ChillReportBundle:Report:select_report_type_for_export.html.twig', [
'form' => $form->createView(),
'layout_name' => '@ChillMain/Export/layout.html.twig',
]);
}
/**
* Web page for editing an existing report.
*
* @param integer $person_id The id of the person.
* @param integer $report_id The id of the report.
* @param int $person_id The id of the person.
* @param int $report_id The id of the report.
*
* @return Response The web page.
*/
public function updateAction($person_id, $report_id, Request $request)
@@ -515,7 +447,8 @@ class ReportController extends AbstractController
if (!$report) {
throw $this->createNotFoundException(
$this->get('translator')->trans('Unable to find this report.'));
$this->get('translator')->trans('Unable to find this report.')
);
}
$this->denyAccessUnlessGranted('CHILL_REPORT_UPDATE', $report);
@@ -528,34 +461,120 @@ class ReportController extends AbstractController
$this->get('session')
->getFlashBag()
->add('success',
->add(
'success',
$this->get('translator')
->trans('Success : report updated!')
);
$person = $report->getPerson();
$event = new PrivacyEvent($person, array(
$event = new PrivacyEvent($person, [
'element_class' => Report::class,
'element_id' => $report->getId(),
'action' => 'update'
));
'action' => 'update',
]);
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
return $this->redirect($this->generateUrl('report_view',
array('person_id' => $report->getPerson()->getId(), 'report_id' => $report_id)));
return $this->redirect($this->generateUrl(
'report_view',
['person_id' => $report->getPerson()->getId(), 'report_id' => $report_id]
));
}
$this->get('session')
->getFlashBag()
->add('error',
->add(
'error',
$this->get('translator')
->trans('The form is not valid. The report has not been updated !')
);
return $this->render('ChillReportBundle:Report:edit.html.twig', array(
'edit_form' => $editForm->createView(),
'person' => $report->getPerson()
));
return $this->render('ChillReportBundle:Report:edit.html.twig', [
'edit_form' => $editForm->createView(),
'person' => $report->getPerson(),
]);
}
/**
* Find and display a report.
*
* @param int $report_id The id of the report.
* @param int $person_id The id of the person.
*
* @return Response The web page.
*/
public function viewAction($report_id, $person_id)
{
$em = $this->getDoctrine()->getManager();
$person = $em->getRepository('ChillPersonBundle:Person')->find($person_id);
$entity = $em->getRepository('ChillReportBundle:Report')->find($report_id);
if (!$entity || !$person) {
throw $this->createNotFoundException(
$this->get('translator')->trans('Unable to find this report.')
);
}
$this->denyAccessUnlessGranted('CHILL_REPORT_SEE', $entity);
$event = new PrivacyEvent($person, [
'element_class' => Report::class,
'element_id' => $entity->getId(),
'action' => 'view',
]);
$this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event);
return $this->render('ChillReportBundle:Report:view.html.twig', [
'entity' => $entity,
'person' => $person,
]);
}
/**
* Creates a form to create a Report entity.
*
* @param Report $entity The entity
* @param mixed $cFGroup
*
* @return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(Report $entity, Person $person, $cFGroup)
{
return $this->createForm(ReportType::class, $entity, [
'action' => $this->generateUrl(
'report_create',
['person_id' => $person->getId(),
'cf_group_id' => $cFGroup->getId(), ]
),
'method' => 'POST',
'cFGroup' => $cFGroup,
'role' => new Role('CHILL_REPORT_CREATE'),
'center' => $person->getCenter(),
]);
}
/**
* Creates a form to edit a Report entity.
*
* @param Report $entity The report to edit.
*
* @return \Symfony\Component\Form\Form The form
*/
private function createEditForm(Report $entity)
{
return $this->createForm(ReportType::class, $entity, [
'action' => $this->generateUrl(
'report_update',
['person_id' => $entity->getPerson()->getId(),
'report_id' => $entity->getId(), ]
),
'method' => 'PUT',
'cFGroup' => $entity->getCFGroup(),
'role' => new Role('CHILL_REPORT_UPDATE'),
'center' => $entity->getPerson()->getCenter(),
]);
}
}

View File

@@ -1,33 +1,21 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\DataFixtures\ORM;
use Chill\CustomFieldsBundle\Entity\CustomField;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Chill\CustomFieldsBundle\Entity\CustomField;
/**
* Load CustomField for Report into database
* Load CustomField for Report into database.
*/
class LoadCustomField extends AbstractFixture implements OrderedFixtureInterface
{
@@ -39,53 +27,52 @@ class LoadCustomField extends AbstractFixture implements OrderedFixtureInterface
public function load(ObjectManager $manager)
{
$cFTypes = [
array('type' => 'text', 'options' => array('maxLength' => '255')),
array('type' => 'text', 'options' => array('maxLength' => '1000')),
array('type' => 'text', 'options' => array('maxLength' => '2000')),
array('type' => 'title', 'options' => array('type' => 'title')),
array('type' => 'title', 'options' => array('type' => 'subtitle')),
array('type' => 'choice', 'options' => array(
['type' => 'text', 'options' => ['maxLength' => '255']],
['type' => 'text', 'options' => ['maxLength' => '1000']],
['type' => 'text', 'options' => ['maxLength' => '2000']],
['type' => 'title', 'options' => ['type' => 'title']],
['type' => 'title', 'options' => ['type' => 'subtitle']],
['type' => 'choice', 'options' => [
'multiple' => false,
'expanded'=> false,
'expanded' => false,
'other' => false,
'choices'=> [
array(
'name' => array(
'choices' => [
[
'name' => [
'fr' => 'Options 1 FR',
'nl' => 'Options 1 NL',
'en' => 'Options 1 EN'),
'en' => 'Options 1 EN', ],
'active' => true,
'slug' => 'el-1-fr'),
array(
'name' => array(
'slug' => 'el-1-fr', ],
[
'name' => [
'fr' => 'Options 2 FR',
'nl' => 'Options 2 NL',
'en' => 'Options 2 EN'),
'en' => 'Options 2 EN', ],
'active' => true,
'slug' => 'el-2-fr'),
array(
'name' => array(
'slug' => 'el-2-fr', ],
[
'name' => [
'fr' => 'Options 2 FR',
'nl' => 'Options 2 NL',
'en' => 'Options 2 EN'),
'en' => 'Options 2 EN', ],
'active' => true,
'slug' => 'el-3-fr')
]
)
)
'slug' => 'el-3-fr', ],
],
],
],
];
for($i=0; $i <= 25; $i++) {
$cFType = $cFTypes[rand(0,sizeof($cFTypes) - 1)];
for ($i = 0; 25 >= $i; ++$i) {
$cFType = $cFTypes[rand(0, sizeof($cFTypes) - 1)];
$customField = (new CustomField())
->setSlug("cf_report_{$i}")
->setType($cFType['type'])
->setOptions($cFType['options'])
->setName(array("fr" => "CustomField {$i}"))
->setOrdering(rand(0,1000) / 1000)
->setCustomFieldsGroup($this->getReference('cf_group_report_'.(rand(0,3))))
;
->setName(['fr' => "CustomField {$i}"])
->setOrdering(rand(0, 1000) / 1000)
->setCustomFieldsGroup($this->getReference('cf_group_report_' . (rand(0, 3))));
$manager->persist($customField);
}
@@ -101,119 +88,108 @@ class LoadCustomField extends AbstractFixture implements OrderedFixtureInterface
$reportLogement = $this->getReference('cf_group_report_logement');
$houseTitle = (new CustomField())
->setSlug('house_title')
->setType('title')
->setOptions(array('type' => 'title'))
->setName(array('fr' => 'Situation de logement'))
->setOrdering(10)
->setCustomFieldsGroup($reportLogement)
;
->setSlug('house_title')
->setType('title')
->setOptions(['type' => 'title'])
->setName(['fr' => 'Situation de logement'])
->setOrdering(10)
->setCustomFieldsGroup($reportLogement);
$manager->persist($houseTitle);
$hasLogement = (new CustomField())
->setSlug('has_logement')
->setName(array('fr' => 'Logement actuel'))
->setType('choice')
->setOptions(array(
'multiple' => FALSE,
'expanded' => TRUE,
'other' => TRUE,
'choices' => [
array(
'name' => ['fr' => 'Locataire d\' un logement'],
'slug' => 'rent_house',
'active' => true
),
array(
'name' => ['fr' => 'Propriétaire d\' un logement'],
'slug' => 'own_house',
'active' => true
),
array(
'name' => ['fr' => 'Par-ci, par là (amis, famille, ...)'],
'slug' => 'here-and-there',
'active' => true
),
array(
'name' => ['fr' => 'A la rue'],
'slug' => 'street',
'active' => true
)
]
))
->setOrdering(20)
->setCustomFieldsGroup($reportLogement)
;
->setSlug('has_logement')
->setName(['fr' => 'Logement actuel'])
->setType('choice')
->setOptions([
'multiple' => false,
'expanded' => true,
'other' => true,
'choices' => [
[
'name' => ['fr' => 'Locataire d\' un logement'],
'slug' => 'rent_house',
'active' => true,
],
[
'name' => ['fr' => 'Propriétaire d\' un logement'],
'slug' => 'own_house',
'active' => true,
],
[
'name' => ['fr' => 'Par-ci, par là (amis, famille, ...)'],
'slug' => 'here-and-there',
'active' => true,
],
[
'name' => ['fr' => 'A la rue'],
'slug' => 'street',
'active' => true,
],
],
])
->setOrdering(20)
->setCustomFieldsGroup($reportLogement);
$manager->persist($hasLogement);
$descriptionLogement = (new CustomField())
->setSlug('house-desc')
->setName(array('fr' => 'Plaintes éventuelles sur le logement'))
->setType('text')
->setOptions(['maxLength' => 1500])
->setOrdering(30)
->setCustomFieldsGroup($reportLogement)
;
->setSlug('house-desc')
->setName(['fr' => 'Plaintes éventuelles sur le logement'])
->setType('text')
->setOptions(['maxLength' => 1500])
->setOrdering(30)
->setCustomFieldsGroup($reportLogement);
$manager->persist($descriptionLogement);
//report problems
$reportEducation = $this->getReference('cf_group_report_education');
$title = (new CustomField())
->setSlug('title')
->setType('title')
->setOptions(array('type' => 'title'))
->setName(array('fr' => 'Éducation'))
->setOrdering(10)
->setCustomFieldsGroup($reportEducation)
;
->setSlug('title')
->setType('title')
->setOptions(['type' => 'title'])
->setName(['fr' => 'Éducation'])
->setOrdering(10)
->setCustomFieldsGroup($reportEducation);
$manager->persist($title);
$educationLevel = (new CustomField())
->setSlug('level')
->setName(array('fr' => 'Niveau du plus haut diplôme'))
->setType('choice')
->setOptions(array(
'multiple' => FALSE,
'expanded' => FALSE,
'other' => FALSE,
'choices' => [
array(
'name' => ['fr' => 'Supérieur'],
'slug' => 'superieur',
'active' => true
),
array(
'name' => ['fr' => 'Secondaire supérieur (CESS)'],
'slug' => 'cess',
'active' => true
),
array(
'name' => ['fr' => 'Secondaire deuxième degré ou inférieur (C2D)'],
'slug' => 'c2d',
'active' => true
),
array(
'name' => ['fr' => 'Primaire'],
'slug' => 'low',
'active' => true
),
array(
'name' => ['fr' => 'Aucun diplome'],
'slug' => 'no',
'active' => true
)
]
))
->setOrdering(20)
->setCustomFieldsGroup($reportEducation)
;
->setSlug('level')
->setName(['fr' => 'Niveau du plus haut diplôme'])
->setType('choice')
->setOptions([
'multiple' => false,
'expanded' => false,
'other' => false,
'choices' => [
[
'name' => ['fr' => 'Supérieur'],
'slug' => 'superieur',
'active' => true,
],
[
'name' => ['fr' => 'Secondaire supérieur (CESS)'],
'slug' => 'cess',
'active' => true,
],
[
'name' => ['fr' => 'Secondaire deuxième degré ou inférieur (C2D)'],
'slug' => 'c2d',
'active' => true,
],
[
'name' => ['fr' => 'Primaire'],
'slug' => 'low',
'active' => true,
],
[
'name' => ['fr' => 'Aucun diplome'],
'slug' => 'no',
'active' => true,
],
],
])
->setOrdering(20)
->setCustomFieldsGroup($reportEducation);
$manager->persist($educationLevel);
}
}

View File

@@ -1,33 +1,21 @@
<?php
/*
* Chill is a software for social workers
/**
* Chill is a software for social workers
*
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\DataFixtures\ORM;
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
/**
* Load CustomFieldsGroup for Report into database
* Load CustomFieldsGroup for Report into database.
*/
class LoadCustomFieldsGroup extends AbstractFixture implements OrderedFixtureInterface
{
@@ -35,55 +23,53 @@ class LoadCustomFieldsGroup extends AbstractFixture implements OrderedFixtureInt
{
return 15000;
}
public function load(ObjectManager $manager)
{
echo "loading customFieldsGroup...\n";
$report = $this->createReport($manager,
array('fr' => 'Situation de logement'),
['summary_fields' => ['has_logement', 'house-desc']]);
$report = $this->createReport(
$manager,
['fr' => 'Situation de logement'],
['summary_fields' => ['has_logement', 'house-desc']]
);
$this->addReference(
'cf_group_report_logement',
$report
);
$report = $this->createReport($manager, array('fr' => 'Alphabétisme'));
'cf_group_report_logement',
$report
);
$report = $this->createReport($manager, ['fr' => 'Alphabétisme']);
$this->addReference('cf_group_report_education', $report);
for($i=0; $i <= 3; $i++) {
$report = $this->createReport($manager, array('fr' => 'ZZ Rapport aléatoire '.$i));
for ($i = 0; 3 >= $i; ++$i) {
$report = $this->createReport($manager, ['fr' => 'ZZ Rapport aléatoire ' . $i]);
$this->addReference('cf_group_report_'.$i, $report);
$this->addReference('cf_group_report_' . $i, $report);
}
$manager->flush();
}
/**
* create a report and persist in the db
*
* @param ObjectManager $manager
* @param array $name
* create a report and persist in the db.
*
* @return CustomFieldsGroup
*/
private function createReport(
ObjectManager $manager,
array $name,
array $options = array())
ObjectManager $manager,
array $name,
array $options = []
)
{
echo $name['fr']." \n";
echo $name['fr'] . " \n";
$cFGroup = (new CustomFieldsGroup())
->setName($name)
->setEntity('Chill\ReportBundle\Entity\Report')
->setOptions($options);
$manager->persist($cFGroup);
return $cFGroup;
}
}
}

View File

@@ -1,36 +1,24 @@
<?php
/*
* Copyright (C) 2015 Julien Fastré <julien.fastre@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\DataFixtures\ORM;
use Chill\MainBundle\DataFixtures\ORM\LoadPermissionsGroup;
use Chill\MainBundle\DataFixtures\ORM\LoadScopes;
use Chill\MainBundle\Entity\RoleScope;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Chill\MainBundle\DataFixtures\ORM\LoadPermissionsGroup;
use Chill\MainBundle\Entity\RoleScope;
use Chill\MainBundle\DataFixtures\ORM\LoadScopes;
/**
* Add a role CHILL_REPORT_UPDATE & CHILL_REPORT_CREATE for all groups except administrative,
* and a role CHILL_REPORT_SEE for administrative
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* and a role CHILL_REPORT_SEE for administrative.
*/
class LoadReportACL extends AbstractFixture implements OrderedFixtureInterface
{
@@ -39,13 +27,13 @@ class LoadReportACL extends AbstractFixture implements OrderedFixtureInterface
return 14999;
}
public function load(ObjectManager $manager)
{
foreach (LoadPermissionsGroup::$refs as $permissionsGroupRef) {
$permissionsGroup = $this->getReference($permissionsGroupRef);
printf("processing permission group %s \n", $permissionsGroup->getName());
foreach (LoadScopes::$references as $scopeRef){
foreach (LoadScopes::$references as $scopeRef) {
$scope = $this->getReference($scopeRef);
printf("processing scope %s \n", $scope->getName()['en']);
//create permission group
@@ -53,36 +41,42 @@ class LoadReportACL extends AbstractFixture implements OrderedFixtureInterface
case 'social':
if ($scope->getName()['en'] === 'administrative') {
printf("denying power on administrative \n");
break 2; // we do not want any power on administrative
}
break;
case 'administrative':
case 'direction':
if (in_array($scope->getName()['en'], array('administrative', 'social'))) {
if (in_array($scope->getName()['en'], ['administrative', 'social'])) {
printf("denying power on %s\n", $scope->getName()['en']);
break 2; // we do not want any power on social or administrative
}
}
break;
}
printf("Adding CHILL_REPORT_UPDATE & CHILL_REPORT_CREATE to %s "
. "permission group, scope '%s' \n",
$permissionsGroup->getName(), $scope->getName()['en']);
printf(
'Adding CHILL_REPORT_UPDATE & CHILL_REPORT_CREATE to %s '
. "permission group, scope '%s' \n",
$permissionsGroup->getName(),
$scope->getName()['en']
);
$roleScopeUpdate = (new RoleScope())
->setRole('CHILL_REPORT_UPDATE')
->setScope($scope);
->setRole('CHILL_REPORT_UPDATE')
->setScope($scope);
$permissionsGroup->addRoleScope($roleScopeUpdate);
$roleScopeCreate = (new RoleScope())
->setRole('CHILL_REPORT_CREATE')
->setScope($scope);
->setRole('CHILL_REPORT_CREATE')
->setScope($scope);
$permissionsGroup->addRoleScope($roleScopeCreate);
$manager->persist($roleScopeUpdate);
$manager->persist($roleScopeCreate);
}
}
$manager->flush();
}
}

View File

@@ -1,46 +1,33 @@
<?php
/*
* Chill is a suite of a modules, Chill is a software for social workers
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\DataFixtures\ORM;
use Chill\CustomFieldsBundle\Entity\CustomField;
use Chill\MainBundle\DataFixtures\ORM\LoadScopes;
use Chill\MainBundle\DataFixtures\ORM\LoadUsers;
use Chill\ReportBundle\Entity\Report;
use DateTime;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Chill\ReportBundle\Entity\Report;
use Chill\MainBundle\DataFixtures\ORM\LoadUsers;
use Faker\Factory as FakerFactory;
use Chill\CustomFieldsBundle\Entity\CustomField;
use Chill\MainBundle\DataFixtures\ORM\LoadScopes;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
/**
* Load reports into DB
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* Load reports into DB.
*/
class LoadReports extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface
{
use \Symfony\Component\DependencyInjection\ContainerAwareTrait;
/**
*
* @var \Faker\Generator
*/
private $faker;
@@ -66,6 +53,26 @@ class LoadReports extends AbstractFixture implements OrderedFixtureInterface, Co
$manager->flush();
}
private function createExpected(ObjectManager $manager)
{
$charline = $this->container->get('doctrine.orm.entity_manager')
->getRepository('ChillPersonBundle:Person')
->findOneBy(['firstName' => 'Charline', 'lastName' => 'DEPARDIEU']);
if (null !== $charline) {
$report = (new Report())
->setPerson($charline)
->setCFGroup($this->getReference('cf_group_report_logement'))
->setDate(new DateTime('2015-01-05'))
->setScope($this->getReference('scope_social'));
$this->fillReport($report);
$manager->persist($report);
} else {
echo 'WARNING: Charline DEPARDIEU not found in database';
}
}
private function createRandom(ObjectManager $manager, $percentage)
{
$people = $this->getPeopleRandom($percentage);
@@ -73,100 +80,57 @@ class LoadReports extends AbstractFixture implements OrderedFixtureInterface, Co
foreach ($people as $person) {
//create a report, set logement or education report
$report = (new Report())
->setPerson($person)
->setCFGroup(rand(0,10) > 5 ?
->setPerson($person)
->setCFGroup(
rand(0, 10) > 5 ?
$this->getReference('cf_group_report_logement') :
$this->getReference('cf_group_report_education')
)
->setScope($this->getScopeRandom())
;
)
->setScope($this->getScopeRandom());
$this->fillReport($report);
$manager->persist($report);
}
}
private function createExpected(ObjectManager $manager)
{
$charline = $this->container->get('doctrine.orm.entity_manager')
->getRepository('ChillPersonBundle:Person')
->findOneBy(array('firstName' => 'Charline', 'lastName' => 'DEPARDIEU'))
;
if (NULL !== $charline) {
$report = (new Report())
->setPerson($charline)
->setCFGroup($this->getReference('cf_group_report_logement'))
->setDate(new \DateTime('2015-01-05'))
->setScope($this->getReference('scope_social'))
;
$this->fillReport($report);
$manager->persist($report);
} else {
print("WARNING: Charline DEPARDIEU not found in database");
}
}
/**
*
* @return \Chill\MainBundle\Entity\Scope
*/
private function getScopeRandom()
{
$ref = LoadScopes::$references[array_rand(LoadScopes::$references)];
return $this->getReference($ref);
}
private function getPeopleRandom($percentage)
{
$people = $this->container->get('doctrine.orm.entity_manager')
->getRepository('ChillPersonBundle:Person')
->findAll()
;
//keep only a part ($percentage) of the people
$selectedPeople = array();
foreach($people as $person) {
if (rand(0,100) < $percentage) {
$selectedPeople[] = $person;
}
}
return $selectedPeople;
}
private function fillReport(Report $report)
{
//setUser
$usernameRef = array_rand(LoadUsers::$refs);
$report->setUser(
$this->getReference($usernameRef)
);
$this->getReference($usernameRef)
);
//set date if null
if ($report->getDate() === NULL) {
if ($report->getDate() === null) {
//set date. 30% of the dates are 2015-05-01
$expectedDate = new \DateTime('2015-01-05');
if (rand(0,100) < 30) {
$expectedDate = new DateTime('2015-01-05');
if (rand(0, 100) < 30) {
$report->setDate($expectedDate);
} else {
$report->setDate($this->faker->dateTimeBetween('-1 year', 'now')
->setTime(0, 0, 0));
->setTime(0, 0, 0));
}
}
//fill data
$datas = array();
$datas = [];
foreach ($report->getCFGroup()->getCustomFields() as $field) {
switch ($field->getType()) {
case 'title' :
$datas[$field->getSlug()] = array();
case 'title':
$datas[$field->getSlug()] = [];
break;
case 'choice' :
case 'choice':
$datas[$field->getSlug()] = $this->getRandomChoice($field);
break;
case 'text' :
case 'text':
$datas[$field->getSlug()] = $this->faker->realText($field->getOptions()['maxLength']);
break;
}
}
@@ -175,11 +139,28 @@ class LoadReports extends AbstractFixture implements OrderedFixtureInterface, Co
return $report;
}
private function getPeopleRandom($percentage)
{
$people = $this->container->get('doctrine.orm.entity_manager')
->getRepository('ChillPersonBundle:Person')
->findAll();
//keep only a part ($percentage) of the people
$selectedPeople = [];
foreach ($people as $person) {
if (rand(0, 100) < $percentage) {
$selectedPeople[] = $person;
}
}
return $selectedPeople;
}
/**
* pick a random choice
* pick a random choice.
*
* @param CustomField $field
* @return string[]|string the array of slug if multiple, a single slug otherwise
* @return string|string[] the array of slug if multiple, a single slug otherwise
*/
private function getRandomChoice(CustomField $field)
{
@@ -188,21 +169,22 @@ class LoadReports extends AbstractFixture implements OrderedFixtureInterface, Co
$other = $field->getOptions()['other'];
//add other if allowed
if($other) {
$choices[] = array('slug' => '_other');
if ($other) {
$choices[] = ['slug' => '_other'];
}
//initialize results
$picked = array();
$picked = [];
if ($multiple) {
$numberSelected = rand(1, count($choices) -1);
for ($i = 0; $i < $numberSelected; $i++) {
$numberSelected = rand(1, count($choices) - 1);
for ($i = 0; $i < $numberSelected; ++$i) {
$picked[] = $this->pickChoice($choices);
}
if ($other) {
$result = array("_other" => NULL, "_choices" => $picked);
$result = ['_other' => null, '_choices' => $picked];
if (in_array('_other', $picked)) {
$result['_other'] = $this->faker->realText(70);
@@ -210,35 +192,38 @@ class LoadReports extends AbstractFixture implements OrderedFixtureInterface, Co
return $result;
}
} else {
$picked = $this->pickChoice($choices);
if ($other) {
$result = array('_other' => NULL, '_choices' => $picked);
$result = ['_other' => null, '_choices' => $picked];
if ($picked === '_other') {
if ('_other' === $picked) {
$result['_other'] = $this->faker->realText(70);
}
return $result;
}
}
}
/**
* pick a choice within a 'choices' options (for choice type)
* @return \Chill\MainBundle\Entity\Scope
*/
private function getScopeRandom()
{
$ref = LoadScopes::$references[array_rand(LoadScopes::$references)];
return $this->getReference($ref);
}
/**
* pick a choice within a 'choices' options (for choice type).
*
* @param array $choices
* @return the slug of the selected choice
*/
private function pickChoice(array $choices)
{
return $choices[array_rand($choices)]['slug'];
}
}

View File

@@ -1,101 +1,72 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Chill\MainBundle\DependencyInjection\MissingBundleException;
use Chill\CustomFieldsBundle\Form\Type\LinkedCustomFieldsType;
use Chill\MainBundle\DependencyInjection\MissingBundleException;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
/**
* This is the class that loads and manages your bundle configuration
* This is the class that loads and manages your bundle configuration.
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html}
*/
class ChillReportExtension extends Extension implements PrependExtensionInterface
{
/**
* {@inheritdoc}
* Declare the entity Report, as a customizable entity (can add custom fields).
*/
public function declareReportAsCustomizable(ContainerBuilder $container)
{
$bundles = $container->getParameter('kernel.bundles');
if (!isset($bundles['ChillCustomFieldsBundle'])) {
throw new MissingBundleException('ChillCustomFieldsBundle');
}
$container->prependExtensionConfig(
'chill_custom_fields',
['customizables_entities' => [
[
'class' => 'Chill\ReportBundle\Entity\Report',
'name' => 'ReportEntity',
'options' => [
'summary_fields' => [
'form_type' => LinkedCustomFieldsType::class,
'form_options' => [
'multiple' => true,
'expanded' => false,
],
],
], ],
],
]
);
}
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config'));
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../config'));
$loader->load('services.yaml');
$loader->load('services/fixtures.yaml');
$loader->load('services/export.yaml');
$loader->load('services/controller.yaml');
}
/**
* Declare the entity Report, as a customizable entity (can add custom fields)
*
* @param ContainerBuilder $container
*/
public function declareReportAsCustomizable(ContainerBuilder $container)
{
$bundles = $container->getParameter('kernel.bundles');
if (!isset($bundles['ChillCustomFieldsBundle'])) {
throw new MissingBundleException('ChillCustomFieldsBundle');
}
$container->prependExtensionConfig('chill_custom_fields',
array('customizables_entities' =>
array(
array(
'class' => 'Chill\ReportBundle\Entity\Report',
'name' => 'ReportEntity',
'options' => array(
'summary_fields' => array(
'form_type' => LinkedCustomFieldsType::class,
'form_options' =>
[
'multiple' => true,
'expanded' => false
]
)
))
)
)
);
}
/**
* declare routes from report bundle
*
* @param ContainerBuilder $container
*/
private function declareRouting(ContainerBuilder $container)
{
$container->prependExtensionConfig('chill_main', array(
'routing' => array(
'resources' => array(
'@ChillReportBundle/config/routes.yaml'
)
)
));
}
protected function prependRoleHierarchy(ContainerBuilder $container)
{
$container->prependExtensionConfig('security', array(
'role_hierarchy' => array(
'CHILL_REPORT_UPDATE' => array('CHILL_REPORT_SEE'),
'CHILL_REPORT_CREATE' => array('CHILL_REPORT_SEE')
)
));
}
/**
* {@inheritdoc}
*
* @param ContainerBuilder $container
*/
public function prepend(ContainerBuilder $container)
{
$this->declareReportAsCustomizable($container);
@@ -103,4 +74,27 @@ class ChillReportExtension extends Extension implements PrependExtensionInterfac
$this->prependRoleHierarchy($container);
}
protected function prependRoleHierarchy(ContainerBuilder $container)
{
$container->prependExtensionConfig('security', [
'role_hierarchy' => [
'CHILL_REPORT_UPDATE' => ['CHILL_REPORT_SEE'],
'CHILL_REPORT_CREATE' => ['CHILL_REPORT_SEE'],
],
]);
}
/**
* declare routes from report bundle.
*/
private function declareRouting(ContainerBuilder $container)
{
$container->prependExtensionConfig('chill_main', [
'routing' => [
'resources' => [
'@ChillReportBundle/config/routes.yaml',
],
],
]);
}
}

View File

@@ -1,20 +1,24 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
* This is the class that validates and merges configuration from your app/config files
* This is the class that validates and merges configuration from your app/config files.
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder('chill_report');

View File

@@ -1,77 +1,33 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Chill\MainBundle\Entity\User;
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
use Chill\MainBundle\Entity\Center;
use Chill\PersonBundle\Entity\Person;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\HasCenterInterface;
use Chill\MainBundle\Entity\HasScopeInterface;
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User;
use Chill\PersonBundle\Entity\Person;
use DateTime;
use Doctrine\ORM\Mapping as ORM;
/**
* Class Report
* Class Report.
*
* @package Chill\ReportBundle\Entity
* @ORM\Entity()
* @ORM\Entity
* @ORM\Table(name="report")
* @ORM\HasLifecycleCallbacks()
* @ORM\HasLifecycleCallbacks
*/
class Report implements HasCenterInterface, HasScopeInterface
{
/**
* @var integer
*
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var User
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
*/
private $user;
/**
* @var Person
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\Person")
*/
private $person;
/**
* @var \DateTime
* @ORM\Column(type="datetime")
*/
private $date;
/**
* @var Scope
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Scope")
*/
private $scope;
/**
* @var array
* @ORM\Column(type="json")
@@ -81,15 +37,85 @@ class Report implements HasCenterInterface, HasScopeInterface
/**
* @var CustomFieldsGroup
* @ORM\ManyToOne(
* targetEntity="Chill\CustomFieldsBundle\Entity\CustomFieldsGroup")
* targetEntity="Chill\CustomFieldsBundle\Entity\CustomFieldsGroup")
*/
private $cFGroup;
/**
* @var DateTime
* @ORM\Column(type="datetime")
*/
private $date;
/**
* Get id
* @var int
*
* @return integer
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var Person
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\Person")
*/
private $person;
/**
* @var Scope
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\Scope")
*/
private $scope;
/**
* @var User
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
*/
private $user;
/**
* @return Center
*/
public function getCenter()
{
return $this->person->getCenter();
}
/**
* Get cFData.
*
* @return array
*/
public function getCFData()
{
return $this->cFData;
}
/**
* Get cFGroup.
*
* @return CustomFieldsGroup
*/
public function getCFGroup()
{
return $this->cFGroup;
}
/**
* Get date.
*
* @return DateTime
*/
public function getDate()
{
return $this->date;
}
/**
* Get id.
*
* @return int
*/
public function getId()
{
@@ -97,43 +123,7 @@ class Report implements HasCenterInterface, HasScopeInterface
}
/**
* Set user
*
* @param User $user
* @return Report
*/
public function setUser(User $user)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* @return User
*/
public function getUser()
{
return $this->user;
}
/**
* Set person
*
* @param Person $person
* @return Report
*/
public function setPerson(Person $person)
{
$this->person = $person;
return $this;
}
/**
* Get person
* Get person.
*
* @return Person
*/
@@ -143,43 +133,7 @@ class Report implements HasCenterInterface, HasScopeInterface
}
/**
* Set date
*
* @param \DateTime $date
* @return Report
*/
public function setDate($date)
{
$this->date = $date;
return $this;
}
/**
* Get date
*
* @return \DateTime
*/
public function getDate()
{
return $this->date;
}
/**
* Set scope
*
* @param string $scope
* @return Report
*/
public function setScope(Scope $scope)
{
$this->scope = $scope;
return $this;
}
/**
* Get scope
* Get scope.
*
* @return Scope
*/
@@ -189,9 +143,18 @@ class Report implements HasCenterInterface, HasScopeInterface
}
/**
* Set cFData
* Get user.
*
* @return User
*/
public function getUser()
{
return $this->user;
}
/**
* Set cFData.
*
* @param array $cFData
* @return Report
*/
public function setCFData(array $cFData)
@@ -202,19 +165,8 @@ class Report implements HasCenterInterface, HasScopeInterface
}
/**
* Get cFData
* Set cFGroup.
*
* @return array
*/
public function getCFData()
{
return $this->cFData;
}
/**
* Set cFGroup
*
* @param CustomFieldsGroup $cFGroup
* @return Report
*/
public function setCFGroup(CustomFieldsGroup $cFGroup)
@@ -225,21 +177,54 @@ class Report implements HasCenterInterface, HasScopeInterface
}
/**
* Get cFGroup
* Set date.
*
* @return CustomFieldsGroup
* @param DateTime $date
*
* @return Report
*/
public function getCFGroup()
public function setDate($date)
{
return $this->cFGroup;
$this->date = $date;
return $this;
}
/**
* @return Center
* Set person.
*
* @return Report
*/
public function getCenter()
public function setPerson(Person $person)
{
return $this->person->getCenter();
$this->person = $person;
return $this;
}
/**
* Set scope.
*
* @param string $scope
*
* @return Report
*/
public function setScope(Scope $scope)
{
$this->scope = $scope;
return $this;
}
/**
* Set user.
*
* @return Report
*/
public function setUser(User $user)
{
$this->user = $user;
return $this;
}
}

View File

@@ -1,42 +1,56 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ReportBundle\Export\Export;
use Chill\MainBundle\Export\ListInterface;
use Chill\CustomFieldsBundle\CustomFields\CustomFieldChoice;
use Chill\CustomFieldsBundle\Entity\CustomField;
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Chill\MainBundle\Export\FormatterInterface;
use Chill\MainBundle\Export\ListInterface;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\ReportBundle\Security\Authorization\ReportVoter;
use Chill\PersonBundle\Export\Declarations;
use Chill\ReportBundle\Entity\Report;
use Chill\ReportBundle\Security\Authorization\ReportVoter;
use Closure;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query;
use Exception;
use LogicException;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Translation\TranslatorInterface;
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
use Chill\MainBundle\Export\ExportElementValidatedInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraints\Callback;
use Chill\MainBundle\Export\FormatterInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\CustomFieldsBundle\Entity\CustomField;
use Chill\ReportBundle\Entity\Report;
use Doctrine\ORM\Query;
use Chill\MainBundle\Entity\Scope;
use Doctrine\ORM\EntityManagerInterface;
use Chill\MainBundle\Entity\User;
use Chill\CustomFieldsBundle\CustomFields\CustomFieldChoice;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use function array_key_exists;
use function array_keys;
use function array_merge;
use function strlen;
use function strtolower;
use function ucfirst;
use function uniqid;
class ReportList implements ListInterface, ExportElementValidatedInterface
{
protected CustomFieldsGroup $customfieldsGroup;
protected TranslatableStringHelper $translatableStringHelper;
protected TranslatorInterface $translator;
protected CustomFieldProvider $customFieldProvider;
protected CustomFieldsGroup $customfieldsGroup;
protected EntityManagerInterface $em;
protected array $fields = [
@@ -45,12 +59,16 @@ class ReportList implements ListInterface, ExportElementValidatedInterface
'person_countryOfBirth', 'person_nationality', 'person_address_street_address_1',
'person_address_street_address_2', 'person_address_valid_from', 'person_address_postcode_label',
'person_address_postcode_code', 'person_address_country_name', 'person_address_country_code',
'report_id', 'report_user', 'report_date', 'report_scope'
'report_id', 'report_user', 'report_date', 'report_scope',
];
protected array $slugs = [];
function __construct(
protected TranslatableStringHelper $translatableStringHelper;
protected TranslatorInterface $translator;
public function __construct(
CustomFieldsGroup $customfieldsGroup,
TranslatableStringHelper $translatableStringHelper,
TranslatorInterface $translator,
@@ -64,14 +82,12 @@ class ReportList implements ListInterface, ExportElementValidatedInterface
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder)
{
$choices = array_combine($this->fields, $this->fields);
$choices = array_combine($this->fields, $this->fields);
foreach ($this->getCustomFields() as $cf) {
$choices
[$this->translatableStringHelper->localize($cf->getName())]
$choices[$this->translatableStringHelper->localize($cf->getName())]
=
$cf->getSlug();
}
@@ -81,8 +97,8 @@ class ReportList implements ListInterface, ExportElementValidatedInterface
'multiple' => true,
'expanded' => true,
'choices' => $choices,
'label' => 'Fields to include in export',
'choice_attr' => function($val, $key, $index) {
'label' => 'Fields to include in export',
'choice_attr' => function ($val, $key, $index) {
// add a 'data-display-target' for address fields
if (substr($val, 0, 8) === 'address_') {
return ['data-display-target' => 'address_date'];
@@ -90,72 +106,41 @@ class ReportList implements ListInterface, ExportElementValidatedInterface
return [];
},
'choice_label' => function(string $key, string $label): string {
'choice_label' => function (string $key, string $label): string {
switch (\substr($key, 0, 7)) {
case 'person_':
return $this->translator->trans(\substr($key, 7, \strlen($key) - 7)).
' ('.$this->translator->trans('Person').')';
return $this->translator->trans(\substr($key, 7, strlen($key) - 7)) .
' (' . $this->translator->trans('Person') . ')';
case 'report_':
return $this->translator->trans(\ucfirst(\substr($key, 7, \strlen($key) - 7))).
' ('.$this->translator->trans('Report').')';
return $this->translator->trans(ucfirst(\substr($key, 7, strlen($key) - 7))) .
' (' . $this->translator->trans('Report') . ')';
default:
return $label.
' ('.$this->translator->trans("Report's question").')';;
return $label .
' (' . $this->translator->trans("Report's question") . ')';
}
},
'constraints' => [new Callback([
'callback' => function($selected, ExecutionContextInterface $context) {
'callback' => function ($selected, ExecutionContextInterface $context) {
if (count($selected) === 0) {
$context->buildViolation('You must select at least one element')
->atPath('fields')
->addViolation();
}
}
])]
},
])],
]);
// add a date field for addresses
$builder->add('address_date', ChillDateType::class, [
'label' => "Address valid at this date",
'data' => new \DateTime(),
'label' => 'Address valid at this date',
'data' => new DateTime(),
'required' => false,
'block_name' => 'list_export_form_address_date'
'block_name' => 'list_export_form_address_date',
]);
}
public function validateForm($data, ExecutionContextInterface $context)
{
// get the field starting with address_
$addressFields = array_filter(
$this->fields,
static fn(string $el): bool => substr($el, 0, 8) === 'address_'
);
// check if there is one field starting with address in data
if (count(array_intersect($data['fields'], $addressFields)) > 0) {
// if a field address is checked, the date must not be empty
if (empty($data['address_date'])) {
$context
->buildViolation("You must set this date if an address is checked")
->atPath('address_date')
->addViolation();
}
}
}
/**
* Get custom fields associated with person
*
* @return CustomField[]
*/
private function getCustomFields()
{
return \array_filter($this->customfieldsGroup
->getCustomFields()->toArray(), function(CustomField $cf) {
return $cf->getType() !== 'title';
});
}
public function getAllowedFormattersTypes()
{
return [FormatterInterface::TYPE_LIST];
@@ -166,92 +151,95 @@ class ReportList implements ListInterface, ExportElementValidatedInterface
return $this->translator->trans(
"Generate list of report '%type%'",
[
'%type%' => $this->translatableStringHelper->localize($this->customfieldsGroup->getName())
'%type%' => $this->translatableStringHelper->localize($this->customfieldsGroup->getName()),
]
);
}
public function getLabels($key, array $values, $data): \Closure
public function getLabels($key, array $values, $data): Closure
{
switch ($key) {
case 'person_birthdate':
case 'report_date':
// for birthdate or report date, we have to transform the string into a date
// to format the date correctly.
return function($value) use ($key) {
if ($value === '_header') {
return $key === 'person_birthdate' ? 'birthdate' : 'report_date';
return function ($value) use ($key) {
if ('_header' === $value) {
return 'person_birthdate' === $key ? 'birthdate' : 'report_date';
}
if (empty($value))
{
return "";
if (empty($value)) {
return '';
}
if ($key === 'person_birthdate') {
$date = \DateTime::createFromFormat('Y-m-d', $value);
if ('person_birthdate' === $key) {
$date = DateTime::createFromFormat('Y-m-d', $value);
} else {
$date = \DateTime::createFromFormat('Y-m-d H:i:s', $value);
$date = DateTime::createFromFormat('Y-m-d H:i:s', $value);
}
// check that the creation could occurs.
if ($date === false) {
throw new \Exception(sprintf("The value %s could "
. "not be converted to %s", $value, \DateTime::class));
if (false === $date) {
throw new Exception(sprintf('The value %s could '
. 'not be converted to %s', $value, DateTime::class));
}
return $date->format('d-m-Y');
};
case 'report_scope':
$qb = $this->em->getRepository(Scope::class)
->createQueryBuilder('s');
$qb->addSelect('s.name')
->addSelect('s.id')
->where($qb->expr()->in('s.id', $values))
;
->where($qb->expr()->in('s.id', $values));
$rows = $qb->getQuery()->getResult(Query::HYDRATE_ARRAY);
$scopes = [];
foreach($rows as $row) {
foreach ($rows as $row) {
$scopes[$row['id']] = $this->translatableStringHelper->localize($row['name']);
}
return function($value) use ($scopes): string {
if ($value === '_header') {
return function ($value) use ($scopes): string {
if ('_header' === $value) {
return 'circle';
}
return $scopes[$value];
};
case 'report_user':
$qb = $this->em->getRepository(User::class)
->createQueryBuilder('u');
$qb->addSelect('u.username')
->addSelect('u.id')
->where($qb->expr()->in('u.id', $values))
;
->where($qb->expr()->in('u.id', $values));
$rows = $qb->getQuery()->getResult(Query::HYDRATE_ARRAY);
$users = [];
foreach($rows as $row) {
foreach ($rows as $row) {
$users[$row['id']] = $row['username'];
}
return function($value) use ($users): string {
if ($value === '_header') {
return function ($value) use ($users): string {
if ('_header' === $value) {
return 'user';
}
return $users[$value];
};
case 'person_gender' :
case 'person_gender':
// for gender, we have to translate men/women statement
return function($value) {
if ($value === '_header') { return 'gender'; }
return function ($value) {
if ('_header' === $value) {
return 'gender';
}
return $this->translator->trans($value);
};
case 'person_countryOfBirth':
case 'person_nationality':
$countryRepository = $this->em
@@ -260,86 +248,49 @@ class ReportList implements ListInterface, ExportElementValidatedInterface
// load all countries in a single query
$countryRepository->findBy(['countryCode' => $values]);
return function($value) use ($key, $countryRepository) {
if ($value === '_header') { return \strtolower($key); }
return function ($value) use ($key, $countryRepository) {
if ('_header' === $value) {
return strtolower($key);
}
if ($value === NULL) {
if (null === $value) {
return $this->translator->trans('no data');
}
$country = $countryRepository->find($value);
return $this->translatableStringHelper->localize(
$country->getName());
$country->getName()
);
};
case 'person_address_country_name':
return function($value) use ($key) {
if ($value === '_header') { return \strtolower($key); }
if ($value === NULL) {
case 'person_address_country_name':
return function ($value) use ($key) {
if ('_header' === $value) {
return strtolower($key);
}
if (null === $value) {
return '';
}
return $this->translatableStringHelper->localize(json_decode($value, true));
};
default:
// for fields which are associated with person
if (in_array($key, $this->fields)) {
return function($value) use ($key) {
if ($value === '_header') { return \strtolower($key); }
return function ($value) use ($key) {
if ('_header' === $value) {
return strtolower($key);
}
return $value;
};
};
}
return $this->getLabelForCustomField($key, $values, $data);
}
}
private function getLabelForCustomField($key, array $values, $data)
{
// for fields which are custom fields
/* @var $cf CustomField */
$cf = $this->em
->getRepository(CustomField::class)
->findOneBy(['slug' => $this->DQLToSlug($key)]);
$cfType = $this->customFieldProvider->getCustomFieldByType($cf->getType());
$defaultFunction = function($value) use ($cf) {
if ($value === '_header') {
return $this->translatableStringHelper->localize($cf->getName());
}
return $this->customFieldProvider
->getCustomFieldByType($cf->getType())
->render(json_decode($value, true), $cf, 'csv');
};
if ($cfType instanceof CustomFieldChoice and $cfType->isMultiple($cf)) {
return function($value) use ($cf, $cfType, $key) {
$slugChoice = $this->extractInfosFromSlug($key)['additionnalInfos']['choiceSlug'];
$decoded = \json_decode($value, true);
if ($value === '_header') {
$label = $cfType->getChoices($cf)[$slugChoice];
return $this->translatableStringHelper->localize($cf->getName())
.' | '.$label;
}
if ($slugChoice === '_other' and $cfType->isChecked($cf, $choiceSlug, $decoded)) {
return $cfType->extractOtherValue($cf, $decoded);
}
return $cfType->isChecked($cf, $slugChoice, $decoded);
};
}
return $defaultFunction;
}
public function getQueryKeys($data)
@@ -353,30 +304,7 @@ class ReportList implements ListInterface, ExportElementValidatedInterface
}
// add the key from slugs and return
return \array_merge($fields, \array_keys($this->slugs));
}
private function slugToDQL($slug, $type = "default", array $additionalInfos = [])
{
$uid = 'slug_' . \uniqid('', true);
$this->slugs[$uid] = [
'slug' => $slug,
'type' => $type,
'additionnalInfos' => $additionalInfos
];
return $uid;
}
private function DQLToSlug($cleanedSlug)
{
return $this->slugs[$cleanedSlug]['slug'];
}
private function extractInfosFromSlug($slug)
{
return $this->slugs[$slug];
return array_merge($fields, array_keys($this->slugs));
}
public function getResult($query, $data)
@@ -389,7 +317,7 @@ class ReportList implements ListInterface, ExportElementValidatedInterface
return $this->translator->trans(
"List for report '%type%'",
[
'%type%' => $this->translatableStringHelper->localize($this->customfieldsGroup->getName())
'%type%' => $this->translatableStringHelper->localize($this->customfieldsGroup->getName()),
]
);
}
@@ -401,12 +329,12 @@ class ReportList implements ListInterface, ExportElementValidatedInterface
public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
{
$centers = array_map(function($el) { return $el['center']; }, $acl);
$centers = array_map(function ($el) { return $el['center']; }, $acl);
// throw an error if any fields are present
if (!\array_key_exists('fields', $data)) {
throw new \Doctrine\DBAL\Exception\InvalidArgumentException("any fields "
. "have been checked");
if (!array_key_exists('fields', $data)) {
throw new \Doctrine\DBAL\Exception\InvalidArgumentException('any fields '
. 'have been checked');
}
$qb = $this->em->createQueryBuilder();
@@ -424,7 +352,9 @@ class ReportList implements ListInterface, ExportElementValidatedInterface
case 'person_nationality':
$suffix = \substr($f, 7);
$qb->addSelect(sprintf('IDENTITY(person.%s) as %s', $suffix, $f));
break;
case 'person_address_street_address_1':
case 'person_address_street_address_2':
case 'person_address_valid_from':
@@ -439,32 +369,42 @@ class ReportList implements ListInterface, ExportElementValidatedInterface
'GET_PERSON_ADDRESS_%s(person.id, :address_date) AS %s',
// get the part after address_
strtoupper(substr($suffix, 8)),
$f));
$f
));
$qb->setParameter('address_date', $data['address_date']);
break;
case 'report_scope':
$qb->addSelect(sprintf('IDENTITY(report.scope) AS %s', 'report_scope'));
break;
case 'report_user':
$qb->addSelect(sprintf('IDENTITY(report.user) AS %s', 'report_user'));
break;
default:
$prefix = \substr($f, 0, 7);
$suffix = \substr($f, 7);
switch($prefix) {
switch ($prefix) {
case 'person_':
$qb->addSelect(sprintf('person.%s as %s', $suffix, $f));
break;
case 'report_':
$qb->addSelect(sprintf('report.%s as %s', $suffix, $f));
break;
default:
throw new \LogicException("this prefix $prefix should "
. "not be encountered. Full field: $f");
throw new LogicException("this prefix {$prefix} should "
. "not be encountered. Full field: {$f}");
}
}
}
// process fields which are custom fields
@@ -478,19 +418,27 @@ class ReportList implements ListInterface, ExportElementValidatedInterface
// if is multiple, split into multiple columns
if ($cfType instanceof CustomFieldChoice and $cfType->isMultiple($cf)) {
foreach($cfType->getChoices($cf) as $choiceSlug => $label) {
$slug = $this->slugToDQL($cf->getSlug(), 'choice', [ 'choiceSlug' => $choiceSlug ]);
foreach ($cfType->getChoices($cf) as $choiceSlug => $label) {
$slug = $this->slugToDQL($cf->getSlug(), 'choice', ['choiceSlug' => $choiceSlug]);
$qb->addSelect(
sprintf('GET_JSON_FIELD_BY_KEY(report.cFData, :slug%s) AS %s',
$slug, $slug));
sprintf(
'GET_JSON_FIELD_BY_KEY(report.cFData, :slug%s) AS %s',
$slug,
$slug
)
);
$qb->setParameter(sprintf('slug%s', $slug), $cf->getSlug());
}
} else {
// not multiple, add a single column
$slug = $this->slugToDQL($cf->getSlug());
$qb->addSelect(
sprintf('GET_JSON_FIELD_BY_KEY(report.cFData, :slug%s) AS %s',
$slug, $slug));
sprintf(
'GET_JSON_FIELD_BY_KEY(report.cFData, :slug%s) AS %s',
$slug,
$slug
)
);
$qb->setParameter(sprintf('slug%s', $slug), $cf->getSlug());
}
}
@@ -514,4 +462,102 @@ class ReportList implements ListInterface, ExportElementValidatedInterface
{
return [Declarations::PERSON_IMPLIED_IN, Declarations::PERSON_TYPE, 'report'];
}
public function validateForm($data, ExecutionContextInterface $context)
{
// get the field starting with address_
$addressFields = array_filter(
$this->fields,
static fn (string $el): bool => substr($el, 0, 8) === 'address_'
);
// check if there is one field starting with address in data
if (count(array_intersect($data['fields'], $addressFields)) > 0) {
// if a field address is checked, the date must not be empty
if (empty($data['address_date'])) {
$context
->buildViolation('You must set this date if an address is checked')
->atPath('address_date')
->addViolation();
}
}
}
private function DQLToSlug($cleanedSlug)
{
return $this->slugs[$cleanedSlug]['slug'];
}
private function extractInfosFromSlug($slug)
{
return $this->slugs[$slug];
}
/**
* Get custom fields associated with person.
*
* @return CustomField[]
*/
private function getCustomFields()
{
return \array_filter($this->customfieldsGroup
->getCustomFields()->toArray(), function (CustomField $cf) {
return $cf->getType() !== 'title';
});
}
private function getLabelForCustomField($key, array $values, $data)
{
// for fields which are custom fields
/* @var $cf CustomField */
$cf = $this->em
->getRepository(CustomField::class)
->findOneBy(['slug' => $this->DQLToSlug($key)]);
$cfType = $this->customFieldProvider->getCustomFieldByType($cf->getType());
$defaultFunction = function ($value) use ($cf) {
if ('_header' === $value) {
return $this->translatableStringHelper->localize($cf->getName());
}
return $this->customFieldProvider
->getCustomFieldByType($cf->getType())
->render(json_decode($value, true), $cf, 'csv');
};
if ($cfType instanceof CustomFieldChoice and $cfType->isMultiple($cf)) {
return function ($value) use ($cf, $cfType, $key) {
$slugChoice = $this->extractInfosFromSlug($key)['additionnalInfos']['choiceSlug'];
$decoded = \json_decode($value, true);
if ('_header' === $value) {
$label = $cfType->getChoices($cf)[$slugChoice];
return $this->translatableStringHelper->localize($cf->getName())
. ' | ' . $label;
}
if ('_other' === $slugChoice and $cfType->isChecked($cf, $choiceSlug, $decoded)) {
return $cfType->extractOtherValue($cf, $decoded);
}
return $cfType->isChecked($cf, $slugChoice, $decoded);
};
}
return $defaultFunction;
}
private function slugToDQL($slug, $type = 'default', array $additionalInfos = [])
{
$uid = 'slug_' . uniqid('', true);
$this->slugs[$uid] = [
'slug' => $slug,
'type' => $type,
'additionnalInfos' => $additionalInfos,
];
return $uid;
}
}

View File

@@ -1,49 +1,46 @@
<?php
/*
*/
namespace Chill\ReportBundle\Export\Export;
use Doctrine\ORM\EntityManagerInterface;
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\ReportBundle\Entity\Report;
use Chill\MainBundle\Export\ExportElementsProviderInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
/**
*
* Chill is a software for social workers
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\Export\Export;
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
use Chill\MainBundle\Export\ExportElementsProviderInterface;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\ReportBundle\Entity\Report;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Translation\TranslatorInterface;
class ReportListProvider implements ExportElementsProviderInterface
{
/**
*
* @var EntityManagerInterface
*/
protected $em;
/**
*
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
/**
*
* @var CustomFieldProvider
*/
protected $customFieldProvider;
/**
* @var EntityManagerInterface
*/
protected $em;
/**
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
/**
*
* @var TranslatorInterface
*/
protected $translator;
function __construct(
EntityManagerInterface $em,
public function __construct(
EntityManagerInterface $em,
TranslatableStringHelper $translatableStringHelper,
TranslatorInterface $translator,
CustomFieldProvider $customFieldProvider
@@ -54,24 +51,22 @@ class ReportListProvider implements ExportElementsProviderInterface
$this->customFieldProvider = $customFieldProvider;
}
public function getExportElements()
{
$groups = $this->em->getRepository(CustomFieldsGroup::class)
->findBy([ 'entity' => Report::class ])
;
->findBy(['entity' => Report::class]);
$reports = [];
foreach ($groups as $group) {
$reports[$group->getId()] = new ReportList(
$group,
$group,
$this->translatableStringHelper,
$this->translator,
$this->customFieldProvider,
$this->em);
$this->em
);
}
return $reports;
}
}

View File

@@ -1,24 +1,21 @@
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\Export\Filter;
use Chill\MainBundle\Export\FilterInterface;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Doctrine\ORM\Query\Expr;
use Chill\MainBundle\Form\Type\ChillDateType;
use DateTime;
use Doctrine\ORM\Query\Expr;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class ReportDateFilter implements FilterInterface
{
public function addRole()
{
return null;
@@ -27,15 +24,18 @@ class ReportDateFilter implements FilterInterface
public function alterQuery(\Doctrine\ORM\QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
$clause = $qb->expr()->between('report.date', ':report_date_filter_date_from',
':report_date_filter_date_to');
$clause = $qb->expr()->between(
'report.date',
':report_date_filter_date_from',
':report_date_filter_date_to'
);
if ($where instanceof Expr\Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->add('where', $where);
$qb->setParameter('report_date_filter_date_from', $data['date_from']);
$qb->setParameter('report_date_filter_date_to', $data['date_to']);
@@ -48,24 +48,24 @@ class ReportDateFilter implements FilterInterface
public function buildForm(\Symfony\Component\Form\FormBuilderInterface $builder)
{
$builder->add('date_from', ChillDateType::class, array(
'label' => "Report is after this date",
'data' => new \DateTime(),
));
$builder->add('date_to', ChillDateType::class, array(
'label' => "Report is before this date",
'data' => new \DateTime(),
));
$builder->add('date_from', ChillDateType::class, [
'label' => 'Report is after this date',
'data' => new DateTime(),
]);
$builder->add('date_to', ChillDateType::class, [
'label' => 'Report is before this date',
'data' => new DateTime(),
]);
}
public function describeAction($data, $format = 'string')
{
return array('Filtered by report\'s date: '
. 'between %date_from% and %date_to%', array(
return ['Filtered by report\'s date: '
. 'between %date_from% and %date_to%', [
'%date_from%' => $data['date_from']->format('d-m-Y'),
'%date_to%' => $data['date_to']->format('d-m-Y')
));
'%date_to%' => $data['date_to']->format('d-m-Y'),
], ];
}
public function getTitle()

View File

@@ -1,69 +1,55 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\Form;
use Chill\CustomFieldsBundle\Form\Type\CustomFieldType;
use Chill\MainBundle\Form\Type\AppendScopeChoiceTypeTrait;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Chill\MainBundle\Form\Type\AppendScopeChoiceTypeTrait;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\Persistence\ObjectManager;
use Chill\CustomFieldsBundle\Form\Type\CustomFieldType;
class ReportType extends AbstractType
{
use AppendScopeChoiceTypeTrait;
/**
*
* @var AuthorizationHelper
*/
protected $authorizationHelper;
/**
*
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
/**
*
* @var \Doctrine\Persistence\ObjectManager
*/
protected $om;
/**
*
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
/**
* @var \Chill\MainBundle\Entity\User
*/
protected $user;
public function __construct(AuthorizationHelper $helper,
public function __construct(
AuthorizationHelper $helper,
TokenStorageInterface $tokenStorage,
TranslatableStringHelper $translatableStringHelper,
ObjectManager $om)
ObjectManager $om
)
{
$this->authorizationHelper = $helper;
$this->user = $tokenStorage->getToken()->getUser();
@@ -71,40 +57,42 @@ class ReportType extends AbstractType
$this->om = $om;
}
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('user')
->add('date', ChillDateType::class,
array('required' => true)
->add(
'date',
ChillDateType::class,
['required' => true]
)
->add('cFData', CustomFieldType::class,
array('attr' => array('class' => 'cf-fields'),
'group' => $options['cFGroup']))
;
->add(
'cFData',
CustomFieldType::class,
['attr' => ['class' => 'cf-fields'],
'group' => $options['cFGroup'], ]
);
$this->appendScopeChoices($builder, $options['role'], $options['center'],
$this->user, $this->authorizationHelper,
$this->translatableStringHelper,
$this->om);
$this->appendScopeChoices(
$builder,
$options['role'],
$options['center'],
$this->user,
$this->authorizationHelper,
$this->translatableStringHelper,
$this->om
);
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Chill\ReportBundle\Entity\Report'
));
$resolver->setDefaults([
'data_class' => 'Chill\ReportBundle\Entity\Report',
]);
$resolver->setRequired(array(
$resolver->setRequired([
'cFGroup',
));
]);
$resolver->setAllowedTypes('cFGroup', 'Chill\CustomFieldsBundle\Entity\CustomFieldsGroup');

View File

@@ -1,13 +1,36 @@
<?php
use Symfony\Component\HttpKernel\Kernel;
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\HttpKernel\Kernel;
class AppKernel extends Kernel
{
/**
* @return string
*/
public function getCacheDir()
{
return sys_get_temp_dir() . '/ChillReportBundle/cache';
}
/**
* @return string
*/
public function getLogDir()
{
return sys_get_temp_dir() . '/ChillReportBundle/logs';
}
public function registerBundles()
{
return array(
return [
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Chill\ReportBundle\ChillReportBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
@@ -19,28 +42,12 @@ class AppKernel extends Kernel
new \Symfony\Bundle\AsseticBundle\AsseticBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(),
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle()
);
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(),
];
}
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
}
/**
* @return string
*/
public function getCacheDir()
{
return sys_get_temp_dir().'/ChillReportBundle/cache';
}
/**
* @return string
*/
public function getLogDir()
{
return sys_get_temp_dir().'/ChillReportBundle/logs';
$loader->load(__DIR__ . '/config/config_' . $this->getEnvironment() . '.yml');
}
}

View File

@@ -1,11 +1,18 @@
<?php
use Doctrine\Common\Annotations\AnnotationRegistry;
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
use Composer\Autoload\ClassLoader;
use Doctrine\Common\Annotations\AnnotationRegistry;
/** @var ClassLoader $loader */
$loader = require __DIR__.'/../../../../../vendor/autoload.php';
$loader = require __DIR__ . '/../../../../../vendor/autoload.php';
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
AnnotationRegistry::registerLoader([$loader, 'loadClass']);
return $loader;

View File

@@ -1,69 +1,58 @@
<?php
/*
* Chill is a suite of a modules, Chill is a software for social workers
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\Search;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Search\AbstractSearch;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Chill\MainBundle\Search\ParsingException;
use Doctrine\ORM\QueryBuilder;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use RuntimeException;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Role\Role;
use Chill\MainBundle\Entity\Scope;
/**
* Search amongst reports
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* Search amongst reports.
*/
class ReportSearch extends AbstractSearch implements ContainerAwareInterface
{
use \Symfony\Component\DependencyInjection\ContainerAwareTrait;
/**
* @var EntityManagerInterface
*/
private $em;
/**
*
* @var AuthorizationHelper
*/
private $helper;
/**
*
* @var \Chill\MainBundle\Entity\User
*/
private $user;
public function __construct(EntityManagerInterface $em,
AuthorizationHelper $helper, TokenStorageInterface $tokenStorage)
public function __construct(
EntityManagerInterface $em,
AuthorizationHelper $helper,
TokenStorageInterface $tokenStorage
)
{
$this->em = $em;
$this->helper = $helper;
if(! $tokenStorage->getToken()->getUser() instanceof \Chill\MainBundle\Entity\User) {
throw new \RuntimeException('an user must be associated with token');
if (!$tokenStorage->getToken()->getUser() instanceof \Chill\MainBundle\Entity\User) {
throw new RuntimeException('an user must be associated with token');
}
$this->user = $tokenStorage->getToken()->getUser();
}
@@ -78,109 +67,103 @@ class ReportSearch extends AbstractSearch implements ContainerAwareInterface
return false;
}
public function renderResult(array $terms, $start = 0, $limit = 50, array $options = array(), $format = 'html')
public function renderResult(array $terms, $start = 0, $limit = 50, array $options = [], $format = 'html')
{
return $this->container->get('templating')->render('ChillReportBundle:Search:results.html.twig', array(
return $this->container->get('templating')->render('ChillReportBundle:Search:results.html.twig', [
'reports' => $this->getReports($terms, $start, $limit),
'total' => $this->count($terms),
'pattern' => $this->recomposePattern($terms, array( 'date'), 'report')
));
}
private function getReports(array $terms, $start, $limit)
{
$qb = $this->buildQuery($terms);
$qb->select('r')
->setMaxResults($limit)
->setFirstResult($start)
->orderBy('r.date', 'desc')
;
$reportQuery = $qb->getQuery();
$reportQuery->setFetchMode("Chill\ReportBundle\Entity\Report", "person", \Doctrine\ORM\Mapping\ClassMetadata::FETCH_EAGER);
return $reportQuery->getResult();
}
private function count(array $terms)
{
$qb = $this->buildQuery($terms);
$qb->select('COUNT(r.id)');
return $qb->getQuery()->getSingleScalarResult();
}
/**
* @param array $terms the terms
* @return \Doctrine\ORM\QueryBuilder
*/
private function buildQuery(array $terms)
{
$query = $this->em->createQueryBuilder();
$query->from('ChillReportBundle:Report', 'r');
//throw a parsing exception if key 'date' and default is set
if (array_key_exists('date', $terms) && $terms['_default'] !== '') {
throw new ParsingException('You may not set a date argument and a date in default');
}
//throw a parsing exception if no argument except report
if (!array_key_exists('date', $terms) && $terms['_default'] === '') {
throw new ParsingException('You must provide either a date:YYYY-mm-dd argument or a YYYY-mm-dd default search');
}
if (array_key_exists('date', $terms)) {
$query->andWhere($query->expr()->eq('r.date', ':date'))
->setParameter('date', $this->parseDate($terms['date']))
;
} elseif (array_key_exists('_default', $terms)) {
$query->andWhere($query->expr()->eq('r.date', ':date'))
->setParameter('date', $this->parseDate($terms['_default']))
;
}
$query->andWhere($this->addACL($query));
return $query;
}
private function addACL(QueryBuilder $qb)
{
//adding join
$qb->join('r.person', 'p');
$role = new Role('CHILL_REPORT_SEE');
$reachableCenters = $this->helper->getReachableCenters($this->user, $role);
$whereElement = $qb->expr()->orX();
$i = 0;
foreach ($reachableCenters as $center) {
$reachableScopesId = array_map(
function (Scope $scope) { return $scope->getId(); },
$this->helper->getReachableScopes($this->user, $role, $center)
);
$whereElement->add(
$qb->expr()->andX(
$qb->expr()->eq('p.center', ':center_'.$i),
$qb->expr()->in('r.scope', ':reachable_scopes_'.$i)
)
)
;
$qb->setParameter('center_'.$i, $center);
$qb->setParameter('reachable_scopes_'.$i, $reachableScopesId);
}
return $whereElement;
'pattern' => $this->recomposePattern($terms, ['date'], 'report'),
]);
}
public function supports($domain, $format = 'html')
{
return $domain === 'report';
return 'report' === $domain;
}
private function addACL(QueryBuilder $qb)
{
//adding join
$qb->join('r.person', 'p');
$role = new Role('CHILL_REPORT_SEE');
$reachableCenters = $this->helper->getReachableCenters($this->user, $role);
$whereElement = $qb->expr()->orX();
$i = 0;
foreach ($reachableCenters as $center) {
$reachableScopesId = array_map(
function (Scope $scope) { return $scope->getId(); },
$this->helper->getReachableScopes($this->user, $role, $center)
);
$whereElement->add(
$qb->expr()->andX(
$qb->expr()->eq('p.center', ':center_' . $i),
$qb->expr()->in('r.scope', ':reachable_scopes_' . $i)
)
);
$qb->setParameter('center_' . $i, $center);
$qb->setParameter('reachable_scopes_' . $i, $reachableScopesId);
}
return $whereElement;
}
/**
* @param array $terms the terms
*
* @return \Doctrine\ORM\QueryBuilder
*/
private function buildQuery(array $terms)
{
$query = $this->em->createQueryBuilder();
$query->from('ChillReportBundle:Report', 'r');
//throw a parsing exception if key 'date' and default is set
if (array_key_exists('date', $terms) && '' !== $terms['_default']) {
throw new ParsingException('You may not set a date argument and a date in default');
}
//throw a parsing exception if no argument except report
if (!array_key_exists('date', $terms) && '' === $terms['_default']) {
throw new ParsingException('You must provide either a date:YYYY-mm-dd argument or a YYYY-mm-dd default search');
}
if (array_key_exists('date', $terms)) {
$query->andWhere($query->expr()->eq('r.date', ':date'))
->setParameter('date', $this->parseDate($terms['date']));
} elseif (array_key_exists('_default', $terms)) {
$query->andWhere($query->expr()->eq('r.date', ':date'))
->setParameter('date', $this->parseDate($terms['_default']));
}
$query->andWhere($this->addACL($query));
return $query;
}
private function count(array $terms)
{
$qb = $this->buildQuery($terms);
$qb->select('COUNT(r.id)');
return $qb->getQuery()->getSingleScalarResult();
}
private function getReports(array $terms, $start, $limit)
{
$qb = $this->buildQuery($terms);
$qb->select('r')
->setMaxResults($limit)
->setFirstResult($start)
->orderBy('r.date', 'desc');
$reportQuery = $qb->getQuery();
$reportQuery->setFetchMode('Chill\\ReportBundle\\Entity\\Report', 'person', \Doctrine\ORM\Mapping\ClassMetadata::FETCH_EAGER);
return $reportQuery->getResult();
}
}

View File

@@ -1,91 +1,78 @@
<?php
/*
* Copyright (C) 2015 Julien Fastré <julien.fastre@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\Security\Authorization;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Security\Authorization\AbstractChillVoter;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Security\ProvideRoleHierarchyInterface;
use Chill\ReportBundle\Entity\Report;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Center;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use function in_array;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class ReportVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
{
const CREATE = 'CHILL_REPORT_CREATE';
const SEE = 'CHILL_REPORT_SEE';
const UPDATE = 'CHILL_REPORT_UPDATE';
const LISTS = 'CHILL_REPORT_LISTS';
public const CREATE = 'CHILL_REPORT_CREATE';
public const LISTS = 'CHILL_REPORT_LISTS';
public const SEE = 'CHILL_REPORT_SEE';
public const UPDATE = 'CHILL_REPORT_UPDATE';
/**
*
* @var AuthorizationHelper
*/
protected $helper;
public function __construct(AuthorizationHelper $helper)
{
$this->helper = $helper;
}
protected function supports($attribute, $subject)
{
if ($subject instanceof Report) {
return \in_array($attribute, [
self::CREATE, self::UPDATE, self::SEE
]);
} elseif ($subject instanceof Center) {
return $attribute === self::LISTS;
}
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
if (!$token->getUser() instanceof User) {
return false;
}
return $this->helper->userHasAccess($token->getUser(), $subject, $attribute);
}
public function getRoles(): array
{
return [self::CREATE, self::UPDATE, self::SEE, self::LISTS];
}
public function getRolesWithHierarchy(): array
{
return ['Report' => $this->getRoles()];
}
public function getRolesWithoutScope(): array
{
return [self::LISTS];
}
public function getRolesWithHierarchy(): array
protected function supports($attribute, $subject)
{
return ['Report' => $this->getRoles()];
if ($subject instanceof Report) {
return in_array($attribute, [
self::CREATE, self::UPDATE, self::SEE,
]);
}
if ($subject instanceof Center) {
return self::LISTS === $attribute;
}
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
if (!$token->getUser() instanceof User) {
return false;
}
return $this->helper->userHasAccess($token->getUser(), $subject, $attribute);
}
}

View File

@@ -1,178 +1,188 @@
<?php
/*
* Copyright (C) 2015 Julien Fastré <julien.fastre@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Chill\PersonBundle\Entity\Person;
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
use Chill\PersonBundle\Entity\Person;
use DateTime;
use RuntimeException;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\BrowserKit\Client;
/**
* This class is much well writtend than ReportControllerTest class, and will
* replace ReportControllerTest in the future.
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @internal
* @coversNothing
*/
class ReportControllerNextTest extends WebTestCase
{
/**
*
* @var Person
*/
protected $person;
/**
*
* @var CustomFieldsGroup
*/
protected $group;
/**
* @var Person
*/
protected $person;
public function setUp()
{
static::bootKernel();
// get person from fixture
$em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager');
->get('doctrine.orm.entity_manager');
$this->person = $em
->getRepository('ChillPersonBundle:Person')
->findOneBy(array(
'lastName' => 'Charline',
'firstName' => 'Depardieu'
)
);
if ($this->person === NULL) {
throw new \RuntimeException("The expected person is not present in the database. "
. "Did you run `php app/console doctrine:fixture:load` before launching tests ? "
->getRepository('ChillPersonBundle:Person')
->findOneBy(
[
'lastName' => 'Charline',
'firstName' => 'Depardieu',
]
);
if (null === $this->person) {
throw new RuntimeException('The expected person is not present in the database. '
. 'Did you run `php app/console doctrine:fixture:load` before launching tests ? '
. "(expecting person is 'Charline Depardieu'");
}
// get custom fields group from fixture
$customFieldsGroups = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')
->findBy(array('entity' => 'Chill\ReportBundle\Entity\Report'))
;
->get('doctrine.orm.entity_manager')
->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')
->findBy(['entity' => 'Chill\ReportBundle\Entity\Report']);
//filter customFieldsGroup to get only "situation de logement"
$filteredCustomFieldsGroupHouse = array_filter($customFieldsGroups,
function(CustomFieldsGroup $group) {
return in_array("Situation de logement", $group->getName());
});
$filteredCustomFieldsGroupHouse = array_filter(
$customFieldsGroups,
function (CustomFieldsGroup $group) {
return in_array('Situation de logement', $group->getName());
}
);
$this->group = $filteredCustomFieldsGroupHouse[0];
}
public function testValidCreate()
{
$client = $this->getAuthenticatedClient();
$form = $this->getReportForm($this->person, $this->group, $client);
$form->get('chill_reportbundle_report[date]')->setValue(
(new \DateTime())->format('d-m-Y'));
$client->submit($form);
$this->assertTrue($client->getResponse()->isRedirect(),
"The next page is a redirection to the new report's view page");
}
public function testUngrantedUserIsDeniedAccessOnListReports()
{
$client = $this->getAuthenticatedClient('center b_social');
$client->request('GET', sprintf('/fr/person/%d/report/list',
$this->person->getId()));
$this->assertEquals(403, $client->getResponse()->getStatusCode(),
'assert that user for center b has a 403 status code when listing'
. 'reports on person from center a');
$client->request('GET', sprintf(
'/fr/person/%d/report/list',
$this->person->getId()
));
$this->assertEquals(
403,
$client->getResponse()->getStatusCode(),
'assert that user for center b has a 403 status code when listing'
. 'reports on person from center a'
);
}
public function testUngrantedUserIsDeniedAccessOnReport()
{
$client = $this->getAuthenticatedClient('center b_social');
$reports = static::$kernel->getContainer()->get('doctrine.orm.entity_manager')
->getRepository('ChillReportBundle:Report')
->findBy(array('person' => $this->person));
->getRepository('ChillReportBundle:Report')
->findBy(['person' => $this->person]);
$report = $reports[0];
$client->request('GET', sprintf('/fr/person/%d/report/%d/view',
$this->person->getId(), $report->getId()));
$this->assertEquals(403, $client->getResponse()->getStatusCode(),
'assert that user for center b has a 403 status code when '
. 'trying to watch a report from person from center a');
$client->request('GET', sprintf(
'/fr/person/%d/report/%d/view',
$this->person->getId(),
$report->getId()
));
$this->assertEquals(
403,
$client->getResponse()->getStatusCode(),
'assert that user for center b has a 403 status code when '
. 'trying to watch a report from person from center a'
);
}
public function testUngrantedUserIsDeniedReportNew()
{
$client = $this->getAuthenticatedClient('center b_social');
$client->request('GET', sprintf('fr/person/%d/report/cfgroup/%d/new',
$this->person->getId(), $this->group->getId()));
$this->assertEquals(403, $client->getResponse()->getStatusCode(),
'assert that user is denied on trying to show a form "new" for'
. ' a person on another center');
}
public function testUngrantedUserIsDeniedReportCreate()
{
$clientCenterA = $this->getAuthenticatedClient('center a_social');
$form = $this->getReportForm($this->person, $this->group, $clientCenterA);
$clientCenterB = $this->getAuthenticatedClient('center b_social');
$clientCenterB->submit($form);
$this->assertEquals(403, $clientCenterB->getResponse()->getStatusCode(),
'assert that user is denied on trying to show a form "new" for'
. ' a person on another center');
$this->assertEquals(
403,
$clientCenterB->getResponse()->getStatusCode(),
'assert that user is denied on trying to show a form "new" for'
. ' a person on another center'
);
}
public function testUngrantedUserIsDeniedReportNew()
{
$client = $this->getAuthenticatedClient('center b_social');
$client->request('GET', sprintf(
'fr/person/%d/report/cfgroup/%d/new',
$this->person->getId(),
$this->group->getId()
));
$this->assertEquals(
403,
$client->getResponse()->getStatusCode(),
'assert that user is denied on trying to show a form "new" for'
. ' a person on another center'
);
}
public function testValidCreate()
{
$client = $this->getAuthenticatedClient();
$form = $this->getReportForm($this->person, $this->group, $client);
$form->get('chill_reportbundle_report[date]')->setValue(
(new DateTime())->format('d-m-Y')
);
$client->submit($form);
$this->assertTrue(
$client->getResponse()->isRedirect(),
"The next page is a redirection to the new report's view page"
);
}
protected function getAuthenticatedClient($username = 'center a_social')
{
return static::createClient(array(), array(
'PHP_AUTH_USER' => $username,
'PHP_AUTH_PW' => 'password',
));
return static::createClient([], [
'PHP_AUTH_USER' => $username,
'PHP_AUTH_PW' => 'password',
]);
}
/**
*
* @param Person $person
* @param CustomFieldsGroup $group
* @param Client $client
* @return \Symfony\Component\DomCrawler\Form
*/
protected function getReportForm(Person $person, CustomFieldsGroup $group, Client $client)
{
$url = sprintf('fr/person/%d/report/cfgroup/%d/new', $person->getId(),
$group->getId());
$url = sprintf(
'fr/person/%d/report/cfgroup/%d/new',
$person->getId(),
$group->getId()
);
$crawler = $client->request('GET', $url);
return $crawler->selectButton('Ajouter le rapport')
->form();
->form();
}
}

View File

@@ -1,290 +1,300 @@
<?php
/*
/**
* Chill is a software for social workers
*
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
* <http://www.champs-libres.coop>, <info@champs-libres.coop>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\DomCrawler\Form;
use Symfony\Component\DomCrawler\Link;
use Symfony\Component\DomCrawler\Crawler;
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
use Chill\PersonBundle\Entity\Person;
use DateTime;
use RuntimeException;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\DomCrawler\Form;
use Symfony\Component\DomCrawler\Link;
/**
* Test the life cycles of controllers, according to
* https://redmine.champs-libres.coop/projects/report/wiki/Test_plan_for_report_lifecycle
* Test the life cycles of controllers, according to
* https://redmine.champs-libres.coop/projects/report/wiki/Test_plan_for_report_lifecycle.
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @internal
* @coversNothing
*/
class ReportControllerTest extends WebTestCase
{
const REPORT_NAME_FIELD = 'cFGroup';
public const REPORT_NAME_FIELD = 'cFGroup';
/**
*
* @var \Chill\PersonBundle\Entity\Person
*/
private static $person;
/**
*
* @var \SClientymfony\Component\BrowserKit\
*/
private static $client;
private static $user;
/**
*
* @var CustomFieldsGroup
*/
private static $group;
/**
*
* @var \Doctrine\ORM\EntityManagerInterface
*/
private static $em;
/**
* @var CustomFieldsGroup
*/
private static $group;
/**
* @var \Chill\PersonBundle\Entity\Person
*/
private static $person;
private static $user;
public static function setUpBeforeClass()
{
static::bootKernel();
static::$em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager');
//get a random person
static::$person = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('ChillPersonBundle:Person')
->findOneBy(array(
'lastName' => 'Charline',
'firstName' => 'Depardieu'
)
);
if (static::$person === NULL) {
throw new \RuntimeException("The expected person is not present in the database. "
. "Did you run `php app/console doctrine:fixture:load` before launching tests ? "
->get('doctrine.orm.entity_manager')
->getRepository('ChillPersonBundle:Person')
->findOneBy(
[
'lastName' => 'Charline',
'firstName' => 'Depardieu',
]
);
if (null === static::$person) {
throw new RuntimeException('The expected person is not present in the database. '
. 'Did you run `php app/console doctrine:fixture:load` before launching tests ? '
. "(expecting person is 'Charline Depardieu'");
}
$customFieldsGroups = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')
->findBy(array('entity' => 'Chill\ReportBundle\Entity\Report'))
;
->get('doctrine.orm.entity_manager')
->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')
->findBy(['entity' => 'Chill\ReportBundle\Entity\Report']);
//filter customFieldsGroup to get only "situation de logement"
$filteredCustomFieldsGroupHouse = array_filter($customFieldsGroups,
function(CustomFieldsGroup $group) {
return in_array("Situation de logement", $group->getName());
});
$filteredCustomFieldsGroupHouse = array_filter(
$customFieldsGroups,
function (CustomFieldsGroup $group) {
return in_array('Situation de logement', $group->getName());
}
);
static::$group = $filteredCustomFieldsGroupHouse[0];
static::$user = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('ChillMainBundle:User')
->findOneBy(array('username' => "center a_social"));
static::$user = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('ChillMainBundle:User')
->findOneBy(['username' => 'center a_social']);
}
public function setUp()
public function setUp()
{
static::$client = static::createClient(array(), array(
'PHP_AUTH_USER' => 'center a_social',
'PHP_AUTH_PW' => 'password',
));
static::$client = static::createClient([], [
'PHP_AUTH_USER' => 'center a_social',
'PHP_AUTH_PW' => 'password',
]);
}
/**
*
* @param type $username
*
* @return Client
*/
public function getAuthenticatedClient($username = 'center a_social')
{
return static::createClient(array(), array(
'PHP_AUTH_USER' => $username,
'PHP_AUTH_PW' => 'password',
));
return static::createClient([], [
'PHP_AUTH_USER' => $username,
'PHP_AUTH_PW' => 'password',
]);
}
/**
* @return type
* @depends testMenu
*/
public function testChooseReportModelPage(Link $link)
{
// When I click on "add a report" link in menu
$client = $this->getAuthenticatedClient();
$crawlerAddAReportPage = $client->click($link);
$form = $crawlerAddAReportPage->selectButton('Créer un nouveau rapport')->form();
$this->assertInstanceOf(
'Symfony\Component\DomCrawler\Form',
$form,
'I can see a form with a button "add a new report" '
);
$this->assertGreaterThan(
1,
count($form->get(self::REPORT_NAME_FIELD)
->availableOptionValues()),
'I can choose between report models'
);
$possibleOptionsValue = $form->get(self::REPORT_NAME_FIELD)
->availableOptionValues();
$form->get(self::REPORT_NAME_FIELD)->setValue(
$possibleOptionsValue[array_rand($possibleOptionsValue)]
);
$client->submit($form);
$this->assertTrue($client->getResponse()->isRedirect());
return $client->followRedirect();
}
/**
* Test that setting a Null date redirect to an error page.
*
* @depends testNewReportPage
*/
public function testInvalidDate(Form $form)
{
$client = $this->getAuthenticatedClient();
$this->markTestSkipped('This test raise an error since symfony 2.7. '
. 'The user is not correctly reloaded from database.');
$filledForm = $this->fillCorrectForm($form);
$filledForm->get('chill_reportbundle_report[date]')->setValue('invalid date value');
$crawler = $client->submit($filledForm);
$this->assertFalse($client->getResponse()->isRedirect());
$this->assertGreaterThan(0, $crawler->filter('.error')->count());
}
/**
* Test that a incorrect value in user will show an error page.
*
* @depends testNewReportPage
*/
public function testInvalidUser(Form $form)
{
$client = $this->getAuthenticatedClient();
$filledForm = $this->fillCorrectForm($form);
$select = $filledForm->get('chill_reportbundle_report[user]')
->disableValidation()
->setValue(-1);
$crawler = $client->submit($filledForm);
$this->assertFalse($client->getResponse()->isRedirect());
$this->assertGreaterThan(0, $crawler->filter('.error')->count());
}
/**
* @depends testValidCreate
*
* @param int $reportId
*/
public function testList($reportId)
{
$client = $this->getAuthenticatedClient();
$crawler = $client->request('GET', sprintf(
'/fr/person/%s/report/list',
static::$person->getId()
));
$this->assertTrue($client->getResponse()->isSuccessful());
$linkSee = $crawler->filter('.bt-view')->links();
$this->assertGreaterThan(0, count($linkSee));
$this->assertRegExp(sprintf(
'|/fr/person/%s/report/[0-9]*/view$|',
static::$person->getId(),
$reportId
), $linkSee[0]->getUri());
$linkUpdate = $crawler->filter('.bt-update')->links();
$this->assertGreaterThan(0, count($linkUpdate));
$this->assertRegExp(sprintf(
'|/fr/person/%s/report/[0-9]*/edit$|',
static::$person->getId(),
$reportId
), $linkUpdate[0]->getUri());
}
/**
* Set up the browser to be at a random person general page (/fr/person/%d/general),
* check if there is a menu link for adding a new report and return this link (as producer)
*
* We assume that :
* check if there is a menu link for adding a new report and return this link (as producer).
*
* We assume that :
* - we are on a "person" page
* - there are more than one report model
*
*/
public function testMenu()
{
$client = $this->getAuthenticatedClient();
$crawlerPersonPage = $client->request('GET', sprintf('/fr/person/%d/general',
static::$person->getId()));
if (! $client->getResponse()->isSuccessful()) {
$crawlerPersonPage = $client->request('GET', sprintf(
'/fr/person/%d/general',
static::$person->getId()
));
if (!$client->getResponse()->isSuccessful()) {
var_dump($crawlerPersonPage->html());
throw new \RuntimeException('the request at person page failed');
throw new RuntimeException('the request at person page failed');
}
$link = $crawlerPersonPage->selectLink("AJOUT D'UN RAPPORT")->link();
$this->assertInstanceOf('Symfony\Component\DomCrawler\Link', $link,
"There is a \"add a report\" link in menu");
$this->assertContains(sprintf("/fr/person/%d/report/select/type/for/creation",
static::$person->getId()), $link->getUri(),
"There is a \"add a report\" link in menu");
$this->assertInstanceOf(
'Symfony\Component\DomCrawler\Link',
$link,
'There is a "add a report" link in menu'
);
$this->assertContains(
sprintf(
'/fr/person/%d/report/select/type/for/creation',
static::$person->getId()
),
$link->getUri(),
'There is a "add a report" link in menu'
);
return $link;
}
/**
*
* @param \Symfony\Component\DomCrawler\Link $link
* @return type
* @depends testMenu
*/
public function testChooseReportModelPage(Link $link)
{
// When I click on "add a report" link in menu
$client = $this->getAuthenticatedClient();
$crawlerAddAReportPage = $client->click($link);
$form = $crawlerAddAReportPage->selectButton("Créer un nouveau rapport")->form();
$this->assertInstanceOf('Symfony\Component\DomCrawler\Form', $form,
'I can see a form with a button "add a new report" ');
$this->assertGreaterThan(1, count($form->get(self::REPORT_NAME_FIELD)
->availableOptionValues()),
"I can choose between report models");
$possibleOptionsValue = $form->get(self::REPORT_NAME_FIELD)
->availableOptionValues();
$form->get(self::REPORT_NAME_FIELD)->setValue(
$possibleOptionsValue[array_rand($possibleOptionsValue)]);
$client->submit($form);
$this->assertTrue($client->getResponse()->isRedirect());
return $client->followRedirect();
}
/**
*
* @param \Symfony\Component\DomCrawler\Crawler $crawlerNewReportPage
* @return type
* @depends testChooseReportModelPage
*/
public function testNewReportPage(Crawler $crawlerNewReportPage)
{
{
$addForm = $crawlerNewReportPage
->selectButton('Ajouter le rapport')
->form();
$this->assertInstanceOf('Symfony\Component\DomCrawler\Form', $addForm,
'I have a report form');
->selectButton('Ajouter le rapport')
->form();
$this->assertInstanceOf(
'Symfony\Component\DomCrawler\Form',
$addForm,
'I have a report form'
);
$this->isFormAsExpected($addForm);
return $addForm;
}
/**
* get a form for report new
*
* @param \Chill\ReportBundle\Tests\Controller\Person $person
* @param CustomFieldsGroup $group
* @param \Symfony\Component\BrowserKit\Client $client
* @return Form
*/
protected function getReportForm(Person $person, CustomFieldsGroup $group,
\Symfony\Component\BrowserKit\Client $client)
{
$url = sprintf('fr/person/%d/report/cfgroup/%d/new', $person->getId(),
$group->getId());
$crawler = $client->request('GET', $url);
return $crawler->selectButton('Ajouter le rapport')
->form();
}
/**
* Test the expected field are present
*
* @param Form $form
* @param boolean $isDefault if the form should be at default values
*
*/
private function isFormAsExpected(Form $form, $isDefault = true)
{
$this->assertTrue($form->has('chill_reportbundle_report[date]'),
'the report form have a field "date"' );
$this->assertTrue($form->has('chill_reportbundle_report[user]'),
'the report form have field "user" ');
$this->assertEquals('select', $form->get('chill_reportbundle_report[user]')
->getType(), "the user field is a select input");
if ($isDefault) {
$date = new \DateTime('now');
$this->assertEquals(
$date->format('d-m-Y'),
$form->get('chill_reportbundle_report[date]')->getValue(),
"the date field contains the current date by default"
);
//resolve the user
$userId = $form->get('chill_reportbundle_report[user]')->getValue();
$this->assertEquals('center a_social', static::$user->getUsername(),
"the user field is the current user by default");
}
}
/**
* fill the form with correct data
*
* @param Form $form
*/
private function fillCorrectForm(Form $form)
{
$form->get('chill_reportbundle_report[date]')->setValue(
(new \DateTime())->format('d-m-Y'));
return $form;
}
/**
* Test that setting a Null date redirect to an error page
*
* Test that setting a Null date redirect to an error page.
*/
public function testNullDate()
{
$client = $this->getAuthenticatedClient();
$form = $this->getReportForm(static::$person, static::$group,
$client);
$form = $this->getReportForm(
static::$person,
static::$group,
$client
);
//var_dump($form);
$filledForm = $this->fillCorrectForm($form);
$filledForm->get('chill_reportbundle_report[date]')->setValue('');
@@ -294,50 +304,52 @@ class ReportControllerTest extends WebTestCase
$this->assertFalse($client->getResponse()->isRedirect());
$this->assertGreaterThan(0, $crawler->filter('.error')->count());
}
/**
* Test that setting a Null date redirect to an error page
*
* @param Form $form
* @depends testNewReportPage
* test the update form.
*
* @depends testValidCreate
*
* @param int $reportId
*/
public function testInvalidDate(Form $form)
public function testUpdate($reportId)
{
$client = $this->getAuthenticatedClient();
$this->markTestSkipped("This test raise an error since symfony 2.7. "
. "The user is not correctly reloaded from database.");
$filledForm = $this->fillCorrectForm($form);
$filledForm->get('chill_reportbundle_report[date]')->setValue('invalid date value');
$crawler = $client->submit($filledForm);
$this->assertFalse($client->getResponse()->isRedirect());
$this->assertGreaterThan(0, $crawler->filter('.error')->count());
$crawler = $client->request(
'GET',
sprintf('/fr/person/%s/report/%s/edit', static::$person->getId(), $reportId)
);
$this->assertTrue($client->getResponse()->isSuccessful());
$form = $crawler
->selectButton('Enregistrer le rapport')
->form();
$form->get('chill_reportbundle_report[date]')->setValue(
(new DateTime('yesterday'))->format('d-m-Y')
);
$client->submit($form);
$this->assertTrue($client->getResponse()->isRedirect(
sprintf(
'/fr/person/%s/report/%s/view',
static::$person->getId(),
$reportId
)
));
$this->assertEquals(new DateTime('yesterday'), static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('ChillReportBundle:Report')
->find($reportId)
->getDate());
}
/**
* Test that a incorrect value in user will show an error page
*
* @depends testNewReportPage
* @param Form $form
*/
public function testInvalidUser(Form $form)
{
$client = $this->getAuthenticatedClient();
$filledForm = $this->fillCorrectForm($form);
$select = $filledForm->get('chill_reportbundle_report[user]')
->disableValidation()
->setValue(-1);
$crawler = $client->submit($filledForm);
$this->assertFalse($client->getResponse()->isRedirect());
$this->assertGreaterThan(0, $crawler->filter('.error')->count());
}
/**
* Test the creation of a report
*
* Test the creation of a report.
*
* depends testNewReportPage
* param Form $form
*/
@@ -349,95 +361,121 @@ class ReportControllerTest extends WebTestCase
$addForm = $this->getReportForm(self::$person, self::$group, $client);
$filledForm = $this->fillCorrectForm($addForm);
$c = $client->submit($filledForm);
$this->assertTrue($client->getResponse()->isRedirect(),
"The next page is a redirection to the new report's view page");
$this->assertTrue(
$client->getResponse()->isRedirect(),
"The next page is a redirection to the new report's view page"
);
$client->followRedirect();
$this->assertRegExp("|/fr/person/".static::$person->getId()."/report/[0-9]*/view$|",
$client->getHistory()->current()->getUri(),
"The next page is a redirection to the new report's view page");
$matches = array();
preg_match('|/report/([0-9]*)/view$|',
$client->getHistory()->current()->getUri(), $matches);
$this->assertRegExp(
'|/fr/person/' . static::$person->getId() . '/report/[0-9]*/view$|',
$client->getHistory()->current()->getUri(),
"The next page is a redirection to the new report's view page"
);
$matches = [];
preg_match(
'|/report/([0-9]*)/view$|',
$client->getHistory()->current()->getUri(),
$matches
);
return $matches[1];
}
/**
* Test the view of a report.
*
* @depends testValidCreate
* @param int $reportId
*/
public function testList($reportId)
{
$client = $this->getAuthenticatedClient();
$crawler = $client->request('GET', sprintf('/fr/person/%s/report/list',
static::$person->getId()));
$this->assertTrue($client->getResponse()->isSuccessful());
$linkSee = $crawler->filter('.bt-view')->links();
$this->assertGreaterThan(0, count($linkSee));
$this->assertRegExp(sprintf('|/fr/person/%s/report/[0-9]*/view$|',
static::$person->getId(), $reportId), $linkSee[0]->getUri());
$linkUpdate = $crawler->filter('.bt-update')->links();
$this->assertGreaterThan(0, count($linkUpdate));
$this->assertRegExp(sprintf('|/fr/person/%s/report/[0-9]*/edit$|',
static::$person->getId(), $reportId), $linkUpdate[0]->getUri());
}
/**
* Test the view of a report
*
* @depends testValidCreate
*
* @param int $reportId
*/
public function testView($reportId)
{
$client = $this->getAuthenticatedClient();
$client->request('GET',
sprintf('/fr/person/%s/report/%s/view', static::$person->getId(), $reportId));
$this->assertTrue($client->getResponse()->isSuccessful(),
'the page is shown');
$client->request(
'GET',
sprintf('/fr/person/%s/report/%s/view', static::$person->getId(), $reportId)
);
$this->assertTrue(
$client->getResponse()->isSuccessful(),
'the page is shown'
);
}
/**
* test the update form
*
* @depends testValidCreate
* @param int $reportId
* get a form for report new.
*
* @param \Chill\ReportBundle\Tests\Controller\Person $person
*
* @return Form
*/
public function testUpdate($reportId)
protected function getReportForm(
Person $person,
CustomFieldsGroup $group,
\Symfony\Component\BrowserKit\Client $client
)
{
$client = $this->getAuthenticatedClient();
$crawler = $client->request('GET',
sprintf('/fr/person/%s/report/%s/edit', static::$person->getId(), $reportId));
$this->assertTrue($client->getResponse()->isSuccessful());
$form = $crawler
->selectButton('Enregistrer le rapport')
->form();
$form->get('chill_reportbundle_report[date]')->setValue(
(new \DateTime('yesterday'))->format('d-m-Y'));
$client->submit($form);
$this->assertTrue($client->getResponse()->isRedirect(
sprintf('/fr/person/%s/report/%s/view',
static::$person->getId(), $reportId)));
$url = sprintf(
'fr/person/%d/report/cfgroup/%d/new',
$person->getId(),
$group->getId()
);
$crawler = $client->request('GET', $url);
$this->assertEquals(new \DateTime('yesterday'), static::$kernel->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('ChillReportBundle:Report')
->find($reportId)
->getDate());
return $crawler->selectButton('Ajouter le rapport')
->form();
}
/**
* fill the form with correct data.
*/
private function fillCorrectForm(Form $form)
{
$form->get('chill_reportbundle_report[date]')->setValue(
(new DateTime())->format('d-m-Y')
);
return $form;
}
/**
* Test the expected field are present.
*
* @param bool $isDefault if the form should be at default values
*/
private function isFormAsExpected(Form $form, $isDefault = true)
{
$this->assertTrue(
$form->has('chill_reportbundle_report[date]'),
'the report form have a field "date"'
);
$this->assertTrue(
$form->has('chill_reportbundle_report[user]'),
'the report form have field "user" '
);
$this->assertEquals('select', $form->get('chill_reportbundle_report[user]')
->getType(), 'the user field is a select input');
if ($isDefault) {
$date = new DateTime('now');
$this->assertEquals(
$date->format('d-m-Y'),
$form->get('chill_reportbundle_report[date]')->getValue(),
'the date field contains the current date by default'
);
//resolve the user
$userId = $form->get('chill_reportbundle_report[user]')->getValue();
$this->assertEquals(
'center a_social',
static::$user->getUsername(),
'the user field is the current user by default'
);
}
}
}

View File

@@ -1,9 +1,20 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
/**
* @internal
* @coversNothing
*/
class ChillReportExtensionTest extends KernelTestCase
{
/*
@@ -11,19 +22,20 @@ class ChillReportExtensionTest extends KernelTestCase
*/
public function testDeclareReportAsCustomizable()
{
self::bootKernel(array('environment' => 'test'));
self::bootKernel(['environment' => 'test']);
$customizablesEntities = static::$kernel->getContainer()
->getParameter('chill_custom_fields.customizables_entities');
->getParameter('chill_custom_fields.customizables_entities');
$reportFounded = false;
foreach ($customizablesEntities as $customizablesEntity) {
if($customizablesEntity['class'] === 'Chill\ReportBundle\Entity\Report') {
if ('Chill\ReportBundle\Entity\Report' === $customizablesEntity['class']) {
$reportFounded = true;
}
}
if(! $reportFounded) {
throw new Exception("Class Chill\ReportBundle\Entity\Report not found in chill_custom_fields.customizables_entities", 1);
if (!$reportFounded) {
throw new Exception('Class Chill\\ReportBundle\\Entity\\Report not found in chill_custom_fields.customizables_entities', 1);
}
}
}

View File

@@ -1,126 +1,115 @@
<?php
/*
* Chill is a suite of a modules, Chill is a software for social workers
* Copyright (C) 2014, Champs Libres Cooperative SCRLFS, <http://www.champs-libres.coop>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\Tests\Search;
use DateTime;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* Test for report search
* Test for report search.
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @internal
* @coversNothing
*/
class ReportSearchTest extends WebTestCase
{
public function testSearchExpectedDefault()
{
$client = $this->getAuthenticatedClient();
$crawler = $client->request('GET', '/fr/search', array(
'q' => '@report 2015-01-05'
));
$this->assertTrue($client->getResponse()->isSuccessful());
$this->assertRegExp('/Situation de logement/i', $crawler->text());
}
public function testNamedSearch()
{
$client = $this->getAuthenticatedClient();
$crawler = $client->request('GET', '/fr/search', array(
'q' => '@report '.(new \DateTime('tomorrow'))->format('Y-m-d'), //there should be any result for future. And future is tomorrow
'name' => 'report'
));
$crawler = $client->request('GET', '/fr/search', [
'q' => '@report ' . (new DateTime('tomorrow'))->format('Y-m-d'), //there should be any result for future. And future is tomorrow
'name' => 'report',
]);
$this->assertTrue($client->getResponse()->isSuccessful());
}
public function testSearchByDate()
{
$client = $this->getAuthenticatedClient();
$crawler = $client->request('GET', '/fr/search', array(
'q' => '@report date:2015-01-05'
));
$crawler = $client->request('GET', '/fr/search', [
'q' => '@report date:2015-01-05',
]);
$this->assertTrue($client->getResponse()->isSuccessful());
$this->assertRegExp('/Situation de logement/i', $crawler->text());
}
public function testSearchDoubleDate()
{
$client = $this->getAuthenticatedClient();
$crawler = $client->request('GET', '/fr/search', array(
'q' => '@report date:2014-05-01 2014-05-06'
));
$crawler = $client->request('GET', '/fr/search', [
'q' => '@report date:2014-05-01 2014-05-06',
]);
$this->assertGreaterThan(0, $crawler->filter('.error')->count());
}
public function testSearchEmtpy()
{
$client = $this->getAuthenticatedClient();
$crawler = $client->request('GET', '/fr/search', array(
'q' => '@report '
));
$crawler = $client->request('GET', '/fr/search', [
'q' => '@report ',
]);
$this->assertGreaterThan(0, $crawler->filter('.error')->count());
}
public function testSearchExpectedDefault()
{
$client = $this->getAuthenticatedClient();
$crawler = $client->request('GET', '/fr/search', [
'q' => '@report 2015-01-05',
]);
$this->assertTrue($client->getResponse()->isSuccessful());
$this->assertRegExp('/Situation de logement/i', $crawler->text());
}
/**
* Test that the user do not see unauthorized results
*
* We test for that that :
* Test that the user do not see unauthorized results.
*
* We test for that that :
* - we do not see any unauthorized scope mention
*/
public function testUsersDoNotSeeUnauthorizedResults()
{
$clientSocial = $this->getAuthenticatedClient();
$clientAdministrative = $this->getAuthenticatedClient('center a_administrative');
$params = array('q' => '@report date:2015-01-05');
$params = ['q' => '@report date:2015-01-05'];
$crawlerSocial = $clientSocial->request('GET', '/fr/search', $params);
$crawlerAdministrative = $clientAdministrative->request('GET', '/fr/search', $params);
$this->assertNotContains('social', $crawlerAdministrative->filter('.content')
->text());
->text());
$this->assertNotContains('administrative', $crawlerAdministrative->filter('.content')
->text());
->text());
}
/**
*
* @param mixed $username
*
* @return \Symfony\Component\BrowserKit\Client
*/
private function getAuthenticatedClient($username = 'center a_social')
{
return static::createClient(array(), array(
'PHP_AUTH_USER' => $username,
'PHP_AUTH_PW' => 'password',
));
return static::createClient([], [
'PHP_AUTH_USER' => $username,
'PHP_AUTH_PW' => 'password',
]);
}
}

View File

@@ -1,122 +1,56 @@
<?php
/*
* Copyright (C) 2015 Julien Fastré <julien.fastre@champs-libres.coop>
/**
* Chill is a software for social workers
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\Tests\Security\Authorization;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Chill\MainBundle\Test\PrepareUserTrait;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Test\PrepareCenterTrait;
use Chill\MainBundle\Test\PrepareScopeTrait;
use Chill\ReportBundle\Entity\Report;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Test\PrepareUserTrait;
use Chill\PersonBundle\Entity\Person;
use Chill\ReportBundle\Entity\Report;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @internal
* @coversNothing
*/
class ReportVoterTest extends KernelTestCase
{
use PrepareUserTrait, PrepareCenterTrait, PrepareScopeTrait;
{
use PrepareUserTrait;
use PrepareCenterTrait;
use PrepareScopeTrait;
/**
*
* @var \Chill\ReportBundle\Security\Authorization\ReportVoter
*/
protected $voter;
/**
*
* @var \Prophecy\Prophet
*/
protected $prophet;
/**
* @var \Chill\ReportBundle\Security\Authorization\ReportVoter
*/
protected $voter;
public static function setUpBeforeClass()
{
}
public function setUp()
{
static::bootKernel();
$this->voter = static::$kernel->getContainer()
->get('chill.report.security.authorization.report_voter');
->get('chill.report.security.authorization.report_voter');
$this->prophet = new \Prophecy\Prophet();
}
/**
* @dataProvider dataProvider
* @param type $expectedResult
* @param Report $report
* @param User $user
* @param type $action
* @param type $message
*/
public function testAccess($expectedResult, Report $report, $action,
$message, User $user = null)
{
$token = $this->prepareToken($user);
$result = $this->voter->vote($token, $report, [$action]);
$this->assertEquals($expectedResult, $result, $message);
}
/**
* prepare a person
*
* The only properties set is the center, others properties are ignored.
*
* @param Center $center
* @return Person
*/
protected function preparePerson(Center $center)
{
return (new Person())
->setCenter($center)
;
}
/**
* prepare a token interface with correct rights
*
* if $permissions = null, user will be null (no user associated with token
*
* @param User $user
* @return \Symfony\Component\Security\Core\Authentication\Token\TokenInterface
*/
protected function prepareToken(User $user = null)
{
$token = $this->prophet->prophesize();
$token
->willImplement('\Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
if ($user === NULL) {
$token->getUser()->willReturn(null);
} else {
$token->getUser()->willReturn($user);
}
return $token->reveal();
}
public function dataProvider()
{
$centerA = $this->prepareCenter(1, 'center A');
@@ -124,70 +58,120 @@ class ReportVoterTest extends KernelTestCase
$scopeA = $this->prepareScope(1, 'scope default');
$scopeB = $this->prepareScope(2, 'scope B');
$scopeC = $this->prepareScope(3, 'scope C');
$userA = $this->prepareUser(array(
array(
'center' => $centerA,
'permissionsGroup' => array(
$userA = $this->prepareUser([
[
'center' => $centerA,
'permissionsGroup' => [
['scope' => $scopeB, 'role' => 'CHILL_REPORT_SEE'],
['scope' => $scopeA, 'role' => 'CHILL_REPORT_UPDATE']
)
),
array(
'center' => $centerB,
'permissionsGroup' => array(
['scope' => $scopeA, 'role' => 'CHILL_REPORT_SEE'],
)
)
));
$reportA = (new Report)
->setScope($scopeA)
->setPerson($this->preparePerson($centerA))
;
['scope' => $scopeA, 'role' => 'CHILL_REPORT_UPDATE'],
],
],
[
'center' => $centerB,
'permissionsGroup' => [
['scope' => $scopeA, 'role' => 'CHILL_REPORT_SEE'],
],
],
]);
$reportA = (new Report())
->setScope($scopeA)
->setPerson($this->preparePerson($centerA));
$reportB = (new Report())
->setScope($scopeB)
->setPerson($this->preparePerson($centerA))
;
->setScope($scopeB)
->setPerson($this->preparePerson($centerA));
$reportC = (new Report())
->setScope($scopeC)
->setPerson($this->preparePerson($centerB))
;
return array(
array(
->setScope($scopeC)
->setPerson($this->preparePerson($centerB));
return [
[
VoterInterface::ACCESS_DENIED,
$reportA,
'CHILL_REPORT_SEE',
"assert is denied to a null user",
null
),
array(
'assert is denied to a null user',
null,
],
[
VoterInterface::ACCESS_GRANTED,
$reportA,
'CHILL_REPORT_SEE',
"assert access is granted to a user with inheritance UPDATE > SEE",
$userA
),
array(
'assert access is granted to a user with inheritance UPDATE > SEE',
$userA,
],
[
VoterInterface::ACCESS_GRANTED,
$reportB,
'CHILL_REPORT_SEE',
"assert access is granted to a user without inheritance",
$userA
),
array(
'assert access is granted to a user without inheritance',
$userA,
],
[
VoterInterface::ACCESS_DENIED,
$reportC,
'CHILL_REPORT_SEE',
'assert access is denied to a report',
$userA
)
);
$userA,
],
];
}
/**
* @dataProvider dataProvider
*
* @param type $expectedResult
* @param User $user
* @param type $action
* @param type $message
*/
public function testAccess(
$expectedResult,
Report $report,
$action,
$message,
?User $user = null
)
{
$token = $this->prepareToken($user);
$result = $this->voter->vote($token, $report, [$action]);
$this->assertEquals($expectedResult, $result, $message);
}
/**
* prepare a person.
*
* The only properties set is the center, others properties are ignored.
*
* @return Person
*/
protected function preparePerson(Center $center)
{
return (new Person())
->setCenter($center);
}
/**
* prepare a token interface with correct rights.
*
* if $permissions = null, user will be null (no user associated with token
*
* @param User $user
*
* @return \Symfony\Component\Security\Core\Authentication\Token\TokenInterface
*/
protected function prepareToken(?User $user = null)
{
$token = $this->prophet->prophesize();
$token
->willImplement('\Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
if (null === $user) {
$token->getUser()->willReturn(null);
} else {
$token->getUser()->willReturn($user);
}
return $token->reveal();
}
}

View File

@@ -1,182 +1,88 @@
<?php
/*
/**
* Chill is a software for social workers
* Copyright (C) 2015 Champs Libres <info@champs-libres.coop>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\ReportBundle\Tests\Timeline;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Tests\TestHelper as MainTestHelper;
use Chill\PersonBundle\Entity\Person;
use Chill\ReportBundle\Entity\Report;
use Chill\MainBundle\Tests\TestHelper as MainTestHelper;
use Chill\MainBundle\Entity\Scope;
use DateTime;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
/**
* Test a report is shown into timeline
* Test a report is shown into timeline.
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @author Champs Libres <info@champs-libres.coop>
* @internal
* @coversNothing
*/
class TimelineProviderTest extends WebTestCase
{
/**
*
* @var \Doctrine\ORM\EntityManager
*/
private static $em;
/**
*
* @var Person
*/
private $person;
/**
*
* @var Report
*/
private $report;
/**
* Create a person with a report associated with the person
* Create a person with a report associated with the person.
*/
public function setUp()
{
static::bootKernel();
static::$em = static::$kernel->getContainer()
->get('doctrine.orm.entity_manager');
->get('doctrine.orm.entity_manager');
$center = static::$em->getRepository('ChillMainBundle:Center')
->findOneBy(array('name' => 'Center A'));
$person = (new Person(new \DateTime('2015-05-01')))
->setGender(Person::FEMALE_GENDER)
->setFirstName('Nelson')
->setLastName('Mandela')
->setCenter($center);
->findOneBy(['name' => 'Center A']);
$person = (new Person(new DateTime('2015-05-01')))
->setGender(Person::FEMALE_GENDER)
->setFirstName('Nelson')
->setLastName('Mandela')
->setCenter($center);
static::$em->persist($person);
$this->person = $person;
$scopesSocial = array_filter(static::$em
->getRepository('ChillMainBundle:Scope')
->findAll(),
function(Scope $scope) { return $scope->getName()['en'] === 'social'; })
;
$report = (new Report)
->setUser(static::$em->getRepository('ChillMainBundle:User')
->findOneByUsername('center a_social'))
->setDate(new \DateTime('2015-05-02'))
->setPerson($this->person)
->setCFGroup($this->getHousingCustomFieldsGroup())
->setCFData(['has_logement' => 'own_house',
'house-desc' => 'blah blah'])
->setScope(end($scopesSocial));
$scopesSocial = array_filter(
static::$em
->getRepository('ChillMainBundle:Scope')
->findAll(),
function (Scope $scope) { return $scope->getName()['en'] === 'social'; }
);
$report = (new Report())
->setUser(static::$em->getRepository('ChillMainBundle:User')
->findOneByUsername('center a_social'))
->setDate(new DateTime('2015-05-02'))
->setPerson($this->person)
->setCFGroup($this->getHousingCustomFieldsGroup())
->setCFData(['has_logement' => 'own_house',
'house-desc' => 'blah blah', ])
->setScope(end($scopesSocial));
static::$em->persist($report);
$this->report = $report;
static::$em->flush();
}
/**
* Test that a report is shown in timeline
*/
public function testTimelineReport()
{
$client = static::createClient(array(),
MainTestHelper::getAuthenticatedClientOptions()
);
$crawler = $client->request('GET', '/fr/person/'.$this->person->getId()
.'/timeline');
$this->assertTrue($client->getResponse()->isSuccessful(),
'The page timeline is loaded successfully');
$this->assertContains('a ajouté un rapport', $crawler->text(),
'the page contains the text "a publié un rapport"');
}
public function testTimelineReportWithSummaryField()
{
//load the page
$client = static::createClient(array(),
MainTestHelper::getAuthenticatedClientOptions()
);
$crawler = $client->request('GET', '/fr/person/'.$this->person->getId()
.'/timeline');
//performs tests
$this->assertTrue($client->getResponse()->isSuccessful(),
'The page timeline is loaded successfully');
$this->assertGreaterThan(0, $crawler->filter('.report_entry .summary')
->count(),
'the page contains a .report .summary element');
$this->assertContains('blah blah', $crawler->filter('.report_entry .summary')
->text(),
'the page contains the text "blah blah"');
$this->assertContains('Propriétaire', $crawler->filter('.report_entry .summary')
->text(),
'the page contains the mention "Propriétaire"');
}
public function testReportIsNotVisibleToUngrantedUsers()
{
$client = static::createClient(array(),
MainTestHelper::getAuthenticatedClientOptions('center a_administrative')
);
$crawler = $client->request('GET', '/fr/person/'.$this->person->getId()
.'/timeline');
$this->assertEquals(0, $crawler->filter('.report_entry .summary')
->count(),
'the page does not contains a .report .summary element');
static::$em->flush();
}
/**
* get a random custom fields group
*
* @return \Chill\CustomFieldsBundle\Entity\CustomFieldsGroup
*/
private function getHousingCustomFieldsGroup()
{
$groups = static::$em
->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')
->findAll();
foreach ($groups as $group) {
if ($group->getName()['fr'] === 'Situation de logement') {
return $group;
}
}
return $groups[rand(0, count($groups) -1)];
}
public function tearDown()
{
//static::$em->refresh($this->person);
@@ -184,4 +90,102 @@ class TimelineProviderTest extends WebTestCase
// static::$em->remove($this->person);
//static::$em->remove($this->report);
}
public function testReportIsNotVisibleToUngrantedUsers()
{
$client = static::createClient(
[],
MainTestHelper::getAuthenticatedClientOptions('center a_administrative')
);
$crawler = $client->request('GET', '/fr/person/' . $this->person->getId()
. '/timeline');
$this->assertEquals(
0,
$crawler->filter('.report_entry .summary')
->count(),
'the page does not contains a .report .summary element'
);
}
/**
* Test that a report is shown in timeline.
*/
public function testTimelineReport()
{
$client = static::createClient(
[],
MainTestHelper::getAuthenticatedClientOptions()
);
$crawler = $client->request('GET', '/fr/person/' . $this->person->getId()
. '/timeline');
$this->assertTrue(
$client->getResponse()->isSuccessful(),
'The page timeline is loaded successfully'
);
$this->assertContains(
'a ajouté un rapport',
$crawler->text(),
'the page contains the text "a publié un rapport"'
);
}
public function testTimelineReportWithSummaryField()
{
//load the page
$client = static::createClient(
[],
MainTestHelper::getAuthenticatedClientOptions()
);
$crawler = $client->request('GET', '/fr/person/' . $this->person->getId()
. '/timeline');
//performs tests
$this->assertTrue(
$client->getResponse()->isSuccessful(),
'The page timeline is loaded successfully'
);
$this->assertGreaterThan(
0,
$crawler->filter('.report_entry .summary')
->count(),
'the page contains a .report .summary element'
);
$this->assertContains(
'blah blah',
$crawler->filter('.report_entry .summary')
->text(),
'the page contains the text "blah blah"'
);
$this->assertContains(
'Propriétaire',
$crawler->filter('.report_entry .summary')
->text(),
'the page contains the mention "Propriétaire"'
);
}
/**
* get a random custom fields group.
*
* @return \Chill\CustomFieldsBundle\Entity\CustomFieldsGroup
*/
private function getHousingCustomFieldsGroup()
{
$groups = static::$em
->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')
->findAll();
foreach ($groups as $group) {
if ($group->getName()['fr'] === 'Situation de logement') {
return $group;
}
}
return $groups[rand(0, count($groups) - 1)];
}
}

View File

@@ -1,7 +1,14 @@
<?php
if (!is_file($autoloadFile = __DIR__.'/../vendor/autoload.php')) {
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
if (!is_file($autoloadFile = __DIR__ . '/../vendor/autoload.php')) {
throw new \LogicException('Could not find autoload.php in vendor/. Did you run "composer install --dev"?');
}
require $autoloadFile;
require $autoloadFile;

View File

@@ -1,33 +1,42 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\ReportBundle\Timeline;
use Chill\MainBundle\Timeline\TimelineProviderInterface;
use Doctrine\ORM\EntityManager;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Role\Role;
use Doctrine\ORM\Mapping\ClassMetadata;
use Chill\PersonBundle\Entity\Person;
use Chill\MainBundle\Entity\Scope;
use Chill\CustomFieldsBundle\Service\CustomFieldsHelper;
use Chill\ReportBundle\Entity\Report;
use Symfony\Component\Security\Core\Security;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Timeline\TimelineProviderInterface;
use Chill\MainBundle\Timeline\TimelineSingleQuery;
use Chill\PersonBundle\Entity\Person;
use Chill\ReportBundle\Entity\Report;
use Doctrine\ORM\EntityManager;
use LogicException;
use Symfony\Component\Security\Core\Security;
use UnexpectedValueException;
use function array_fill;
use function array_merge;
use function implode;
use function strtr;
/**
* Provide report for inclusion in timeline
* Provide report for inclusion in timeline.
*/
class TimelineReportProvider implements TimelineProviderInterface
{
protected CustomFieldsHelper $customFieldsHelper;
protected EntityManager $em;
protected AuthorizationHelper $helper;
protected CustomFieldsHelper $customFieldsHelper;
protected bool $showEmptyValues;
private Security $security;
@@ -46,10 +55,6 @@ class TimelineReportProvider implements TimelineProviderInterface
$this->showEmptyValues = $showEmptyValues;
}
/**
*
* {@inheritDoc}
*/
public function fetchQuery($context, array $args)
{
$this->checkContext($context);
@@ -58,15 +63,140 @@ class TimelineReportProvider implements TimelineProviderInterface
[$where, $parameters] = $this->getWhereClause($context, $args);
return TimelineSingleQuery::fromArray([
'id' => $report->getTableName()
.'.'.$report->getColumnName('id'),
'type' => 'report',
'date' => $report->getTableName()
.'.'.$report->getColumnName('date'),
'FROM' => $this->getFromClause($context),
'WHERE' => $where,
'parameters' => $parameters
]);
'id' => $report->getTableName()
. '.' . $report->getColumnName('id'),
'type' => 'report',
'date' => $report->getTableName()
. '.' . $report->getColumnName('date'),
'FROM' => $this->getFromClause($context),
'WHERE' => $where,
'parameters' => $parameters,
]);
}
public function getEntities(array $ids)
{
$reports = $this->em->getRepository('ChillReportBundle:Report')
->findBy(['id' => $ids]);
$result = [];
foreach ($reports as $report) {
$result[$report->getId()] = $report;
}
return $result;
}
public function getEntityTemplate($entity, $context, array $args)
{
$this->checkContext($context);
return [
'template' => 'ChillReportBundle:Timeline:report.html.twig',
'template_data' => [
'report' => $entity,
'context' => $context,
'custom_fields_in_summary' => $this->getFieldsToRender($entity, $context),
],
];
}
public function supportsType($type)
{
return 'report' === $type;
}
protected function getFieldsToRender(Report $entity, $context, array $args = [])
{
//gather all custom fields which should appears in summary
$gatheredFields = [];
if (array_key_exists('summary_fields', $entity->getCFGroup()->getOptions())) {
// keep in memory title
$title = null;
$subtitle = null;
foreach ($entity->getCFGroup()->getCustomFields() as $customField) {
if (in_array(
$customField->getSlug(),
$entity->getCFGroup()->getOptions()['summary_fields']
)) {
// if we do not want to show empty values
if (false === $this->showEmptyValues) {
if ($customField->getType() === 'title') {
$options = $customField->getOptions();
switch ($options['type']) {
case 'title': $title = $customField;
break;
case 'subtitle': $subtitle = $customField;
break;
}
} else {
if ($this->customFieldsHelper->isEmptyValue($entity->getCFData(), $customField)
=== false) {
if (null !== $title) {
$gatheredFields[] = $title;
$title = null;
}
if (null !== $subtitle) {
$gatheredFields[] = $subtitle;
$subtitle = null;
}
$gatheredFields[] = $customField;
}
}
} else {
$gatheredFields[] = $customField;
}
}
}
}
return $gatheredFields;
}
/**
* check if the context is supported.
*
* @param string $context
*
* @throws LogicException if the context is not supported
*/
private function checkContext($context)
{
if ('person' !== $context && 'center' !== $context) {
throw new LogicException("The context '{$context}' is not "
. "supported. Currently only 'person' and 'center' is supported");
}
}
private function getFromClause(string $context): string
{
$report = $this->em->getClassMetadata(Report::class);
$person = $this->em->getClassMetadata(Person::class);
$reportPersonId = $report
->getAssociationMapping('person')['joinColumns'][0]['name'];
$personId = $report
->getAssociationMapping('person')['joinColumns'][0]['referencedColumnName'];
$clause = '{report} ' .
'JOIN {person} ON {report}.{person_id} = {person}.{id_person} ';
return strtr(
$clause,
[
'{report}' => $report->getTableName(),
'{person}' => $person->getTableName(),
'{person_id}' => $reportPersonId,
'{id_person}' => $personId,
]
);
}
private function getWhereClause(string $context, array $args): array
@@ -74,10 +204,12 @@ class TimelineReportProvider implements TimelineProviderInterface
switch ($context) {
case 'person':
return $this->getWhereClauseForPerson($context, $args);
case 'center':
return $this->getWhereClauseForCenter($context, $args);
default:
throw new \UnexpectedValueException("This context $context is not implemented");
throw new UnexpectedValueException("This context {$context} is not implemented");
}
}
@@ -96,14 +228,15 @@ class TimelineReportProvider implements TimelineProviderInterface
$parameters = [];
// the clause, that will be joined with an "OR"
$centerScopesClause = "({person}.{center_id} = ? ".
"AND {report}.{scopes_id} IN ({scopes_ids}))";
$centerScopesClause = '({person}.{center_id} = ? ' .
'AND {report}.{scopes_id} IN ({scopes_ids}))';
// container for formatted clauses
$formattedClauses = [];
$askedCenters = $args['centers'];
foreach ($reachableCenters as $center) {
if (FALSE === \in_array($center, $askedCenters)) {
if (false === \in_array($center, $askedCenters)) {
continue;
}
@@ -111,6 +244,7 @@ class TimelineReportProvider implements TimelineProviderInterface
$parameters[] = $center->getId();
// loop over scopes
$scopeIds = [];
foreach ($this->helper->getReachableScopes($this->security->getUser(), $role, $center) as $scope) {
if (\in_array($scope->getId(), $scopeIds)) {
continue;
@@ -118,20 +252,20 @@ class TimelineReportProvider implements TimelineProviderInterface
$scopeIds[] = $scope->getId();
}
$formattedClauses[] = \strtr($centerScopesClause, [
'{scopes_ids}' => \implode(', ', \array_fill(0, \count($scopeIds), '?'))
$formattedClauses[] = strtr($centerScopesClause, [
'{scopes_ids}' => implode(', ', array_fill(0, \count($scopeIds), '?')),
]);
// append $scopeIds to parameters
$parameters = \array_merge($parameters, $scopeIds);
$parameters = array_merge($parameters, $scopeIds);
}
if (0 === count($formattedClauses)) {
return [ 'FALSE = TRUE', [] ];
return ['FALSE = TRUE', []];
}
return [
\strtr(
\implode(' OR ', $formattedClauses),
strtr(
implode(' OR ', $formattedClauses),
[
'{person}' => $person->getTableName(),
'{center_id}' => $personCenterId,
@@ -139,7 +273,7 @@ class TimelineReportProvider implements TimelineProviderInterface
'{scopes_id}' => $reportScopeId,
]
),
$parameters
$parameters,
];
}
@@ -152,10 +286,10 @@ class TimelineReportProvider implements TimelineProviderInterface
$reportScopeId = $report->getAssociationMapping('scope')['joinColumns'][0]['name'];
$personCenterId = $person->getAssociationMapping('center')['joinColumns'][0]['name'];
// parameters for the query, will be filled later
$parameters = [ $args['person']->getId() ];
$parameters = [$args['person']->getId()];
// this is the final clause that we are going to fill
$clause = "{report}.{person_id} = ? AND {report}.{scopes_id} IN ({scopes_ids})";
$clause = '{report}.{person_id} = ? AND {report}.{scopes_id} IN ({scopes_ids})';
// iterate over reachable scopes
$scopes = $this->helper->getReachableScopes($this->security->getUser(), $role, $args['person']->getCenter());
@@ -169,150 +303,23 @@ class TimelineReportProvider implements TimelineProviderInterface
if (1 === count($parameters)) {
// nothing change, we simplify the clause
$clause = "{report}.{person_id} = ? AND FALSE = TRUE";
$clause = '{report}.{person_id} = ? AND FALSE = TRUE';
}
return [
\strtr(
strtr(
$clause,
[
'{report}' => $report->getTableName(),
'{person_id}' => $reportPersonId,
'{scopes_id}' => $reportScopeId,
'{scopes_ids}' => \implode(', ',
\array_fill(0, \count($parameters)-1, '?'))
'{scopes_ids}' => implode(
', ',
array_fill(0, \count($parameters) - 1, '?')
),
]
),
$parameters
$parameters,
];
}
private function getFromClause(string $context): string
{
$report = $this->em->getClassMetadata(Report::class);
$person = $this->em->getClassMetadata(Person::class);
$reportPersonId = $report
->getAssociationMapping('person')['joinColumns'][0]['name']
;
$personId = $report
->getAssociationMapping('person')['joinColumns'][0]['referencedColumnName']
;
$clause = "{report} ".
"JOIN {person} ON {report}.{person_id} = {person}.{id_person} ";
return \strtr($clause,
[
'{report}' => $report->getTableName(),
'{person}' => $person->getTableName(),
'{person_id}' => $reportPersonId,
'{id_person}' => $personId
]
);
}
/**
*
* {@inheritDoc}
*/
public function getEntities(array $ids)
{
$reports = $this->em->getRepository('ChillReportBundle:Report')
->findBy(array('id' => $ids));
$result = array();
foreach($reports as $report) {
$result[$report->getId()] = $report;
}
return $result;
}
/**
*
* {@inheritDoc}
*/
public function getEntityTemplate($entity, $context, array $args)
{
$this->checkContext($context);
return array(
'template' => 'ChillReportBundle:Timeline:report.html.twig',
'template_data' => array(
'report' => $entity,
'context' => $context,
'custom_fields_in_summary' => $this->getFieldsToRender($entity, $context),
)
);
}
protected function getFieldsToRender(Report $entity, $context, array $args = array())
{
//gather all custom fields which should appears in summary
$gatheredFields = array();
if (array_key_exists('summary_fields', $entity->getCFGroup()->getOptions())) {
// keep in memory title
$title = null;
$subtitle = null;
foreach ($entity->getCFGroup()->getCustomFields() as $customField) {
if (in_array($customField->getSlug(),
$entity->getCFGroup()->getOptions()['summary_fields'])) {
// if we do not want to show empty values
if ($this->showEmptyValues === false) {
if ($customField->getType() === 'title') {
$options = $customField->getOptions();
switch($options['type']) {
case 'title': $title = $customField; break;
case 'subtitle': $subtitle = $customField; break;
}
} else {
if ($this->customFieldsHelper->isEmptyValue($entity->getCFData(), $customField)
=== false) {
if ($title !== NULL) {
$gatheredFields[] = $title;
$title = null;
}
if ($subtitle !== NULL) {
$gatheredFields[] = $subtitle;
$subtitle = null;
}
$gatheredFields[] = $customField;
}
}
} else {
$gatheredFields[] = $customField;
}
}
}
}
return $gatheredFields;
}
/**
*
* {@inheritDoc}
*/
public function supportsType($type)
{
return $type === 'report';
}
/**
* check if the context is supported
*
* @param string $context
* @throws \LogicException if the context is not supported
*/
private function checkContext($context)
{
if ($context !== 'person' && $context !== 'center') {
throw new \LogicException("The context '$context' is not "
. "supported. Currently only 'person' and 'center' is supported");
}
}
}

View File

@@ -1,30 +1,36 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\Migrations\Report;
use Doctrine\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
class Version20141129012050 extends AbstractMigration
{
public function up(Schema $schema): void
{
$this->addSql("CREATE SEQUENCE Report_id_seq INCREMENT BY 1 MINVALUE 1 START 1;");
$this->addSql("CREATE TABLE Report (id INT NOT NULL, user_id INT DEFAULT NULL, person_id INT DEFAULT NULL, date TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, scope VARCHAR(255) DEFAULT NULL, cFData JSON NOT NULL, cFGroup_id INT DEFAULT NULL, PRIMARY KEY(id));");
$this->addSql("CREATE INDEX IDX_C38372B2A76ED395 ON Report (user_id);");
$this->addSql("CREATE INDEX IDX_C38372B2217BBB47 ON Report (person_id);");
$this->addSql("CREATE INDEX IDX_C38372B216D2C9F0 ON Report (cFGroup_id);");
$this->addSql("ALTER TABLE Report ADD CONSTRAINT FK_C38372B2A76ED395 FOREIGN KEY (user_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE;");
$this->addSql("ALTER TABLE Report ADD CONSTRAINT FK_C38372B2217BBB47 FOREIGN KEY (person_id) REFERENCES Person (id) NOT DEFERRABLE INITIALLY IMMEDIATE;");
$this->addSql("ALTER TABLE Report ADD CONSTRAINT FK_C38372B216D2C9F0 FOREIGN KEY (cFGroup_id) REFERENCES CustomFieldsGroup (id) NOT DEFERRABLE INITIALLY IMMEDIATE;");
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
}
public function up(Schema $schema): void
{
$this->addSql('CREATE SEQUENCE Report_id_seq INCREMENT BY 1 MINVALUE 1 START 1;');
$this->addSql('CREATE TABLE Report (id INT NOT NULL, user_id INT DEFAULT NULL, person_id INT DEFAULT NULL, date TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, scope VARCHAR(255) DEFAULT NULL, cFData JSON NOT NULL, cFGroup_id INT DEFAULT NULL, PRIMARY KEY(id));');
$this->addSql('CREATE INDEX IDX_C38372B2A76ED395 ON Report (user_id);');
$this->addSql('CREATE INDEX IDX_C38372B2217BBB47 ON Report (person_id);');
$this->addSql('CREATE INDEX IDX_C38372B216D2C9F0 ON Report (cFGroup_id);');
$this->addSql('ALTER TABLE Report ADD CONSTRAINT FK_C38372B2A76ED395 FOREIGN KEY (user_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE;');
$this->addSql('ALTER TABLE Report ADD CONSTRAINT FK_C38372B2217BBB47 FOREIGN KEY (person_id) REFERENCES Person (id) NOT DEFERRABLE INITIALLY IMMEDIATE;');
$this->addSql('ALTER TABLE Report ADD CONSTRAINT FK_C38372B216D2C9F0 FOREIGN KEY (cFGroup_id) REFERENCES CustomFieldsGroup (id) NOT DEFERRABLE INITIALLY IMMEDIATE;');
}
}

View File

@@ -1,62 +1,78 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\Migrations\Report;
use Doctrine\Migrations\AbstractMigration;
use Chill\MainBundle\Entity\Scope;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
use RuntimeException;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Chill\MainBundle\Entity\Scope;
/**
* Add a scope to report
* Add a scope to report.
*/
class Version20150622233319 extends AbstractMigration
implements ContainerAwareInterface
class Version20150622233319 extends AbstractMigration implements ContainerAwareInterface
{
/**
*
* @var ContainerInterface
*/
private $container;
public function setContainer(ContainerInterface $container = null)
public function down(Schema $schema): void
{
if ($container === NULL) {
throw new \RuntimeException('Container is not provided. This migration '
$this->abortIf(
$this->connection->getDatabasePlatform()->getName() != 'postgresql',
'Migration can only be executed safely on \'postgresql\'.'
);
$this->addSql('ALTER TABLE Report DROP CONSTRAINT FK_report_scope');
$this->addSql('DROP INDEX IDX_report_scope');
$this->addSql('ALTER TABLE Report ADD scope VARCHAR(255) DEFAULT NULL');
$this->addSql('ALTER TABLE Report DROP scope_id');
}
public function setContainer(?ContainerInterface $container = null)
{
if (null === $container) {
throw new RuntimeException('Container is not provided. This migration '
. 'need container to set a default center');
}
$this->container = $container;
}
/**
* @param Schema $schema
*/
public function up(Schema $schema): void
{
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql',
'Migration can only be executed safely on \'postgresql\'.');
$this->abortIf(
$this->connection->getDatabasePlatform()->getName() != 'postgresql',
'Migration can only be executed safely on \'postgresql\'.'
);
$this->addSql('ALTER TABLE report ADD scope_id INT DEFAULT NULL');
/*
* Before the upgrade to symfony version 4, this code worked.
*
*
* But it doesn't work any more after the migration and currently this
* code should note be necessary.
*
*
* This code is kept for reference, and may be re-activated if needed, but
* the probability that this will happens is near 0
*
*
//add a default scope
$scopes = $this->container->get('doctrine.orm.default_entity_manager')
->getRepository('ChillMainBundle:Scope')
->findAll();
if (count($scopes) > 0) {
$defaultScopeId = $scopes[0]->getId();
} else {
@@ -64,7 +80,7 @@ class Version20150622233319 extends AbstractMigration
$nbReports = $this->container->get('doctrine.orm.default_entity_manager')
->createQuery('SELECT count(r.id) FROM ChillReportBundle:Report r')
->getSingleScalarResult();
if ($nbReports > 0) {
//create a default scope
$scope = new Scope();
@@ -90,27 +106,13 @@ class Version20150622233319 extends AbstractMigration
$this->addSql('ALTER TABLE report ADD CONSTRAINT FK_report_scope '
. 'FOREIGN KEY (scope_id) '
. 'REFERENCES scopes (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
if (isset($defaultScopeId)){
$this->addSql('UPDATE report SET scope_id = :id', array(
'id' => $defaultScopeId
));
if (isset($defaultScopeId)) {
$this->addSql('UPDATE report SET scope_id = :id', [
'id' => $defaultScopeId,
]);
}
$this->addSql('ALTER TABLE report ALTER COLUMN scope_id SET NOT NULL');
$this->addSql('CREATE INDEX IDX_report_scope ON report (scope_id)');
}
/**
* @param Schema $schema
*/
public function down(Schema $schema): void
{
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql',
'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('ALTER TABLE Report DROP CONSTRAINT FK_report_scope');
$this->addSql('DROP INDEX IDX_report_scope');
$this->addSql('ALTER TABLE Report ADD scope VARCHAR(255) DEFAULT NULL');
$this->addSql('ALTER TABLE Report DROP scope_id');
}
}