fix folder name

This commit is contained in:
2021-03-18 13:37:13 +01:00
parent a2f6773f5a
commit eaa0ad925f
1578 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
<?php
/*
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
*/
namespace Chill\MainBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Chill\MainBundle\Search\SearchProvider;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class AdvancedSearchType extends AbstractType
{
/**
*
* @var SearchProvider
*/
protected $searchProvider;
public function __construct(SearchProvider $searchProvider)
{
$this->searchProvider = $searchProvider;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->searchProvider
->getHasAdvancedFormByName($options['search_service'])
->createSearchForm($builder)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver
->setRequired('search_service')
->setAllowedTypes('search_service', [ 'string' ])
;
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace Chill\MainBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
class CenterType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class)
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Chill\MainBundle\Entity\Center'
));
}
/**
* @return string
*/
public function getBlockPrefix()
{
return 'chill_mainbundle_center';
}
}

View File

@@ -0,0 +1,112 @@
<?php
/*
* Copyright (C) 2018 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/>.
*/
namespace Chill\MainBundle\Form\ChoiceLoader;
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
use Chill\MainBundle\Repository\PostalCodeRepository;
use Chill\MainBundle\Entity\PostalCode;
/**
* Class PostalCodeChoiceLoader
*
* @package Chill\MainBundle\Form\ChoiceLoader
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class PostalCodeChoiceLoader implements ChoiceLoaderInterface
{
/**
* @var PostalCodeRepository
*/
protected $postalCodeRepository;
/**
* @var array
*/
protected $lazyLoadedPostalCodes = [];
/**
* PostalCodeChoiceLoader constructor.
*
* @param PostalCodeRepository $postalCodeRepository
*/
public function __construct(PostalCodeRepository $postalCodeRepository)
{
$this->postalCodeRepository = $postalCodeRepository;
}
/**
* @param null $value
* @return ChoiceListInterface
*/
public function loadChoiceList($value = null): ChoiceListInterface
{
$list = new \Symfony\Component\Form\ChoiceList\ArrayChoiceList(
$this->lazyLoadedPostalCodes,
function(PostalCode $pc = null) use ($value) {
return \call_user_func($value, $pc);
});
return $list;
}
/**
* @param array $values
* @param null $value
* @return array
*/
public function loadChoicesForValues(array $values, $value = null)
{
$choices = [];
foreach($values as $value) {
if (empty($value)) {
$choices[] = null;
} else {
$choices[] = $this->postalCodeRepository->find($value);
}
}
return $choices;
}
/**
* @param array $choices
* @param null $value
* @return array|string[]
*/
public function loadValuesForChoices(array $choices, $value = null)
{
$values = [];
foreach ($choices as $choice) {
if (NULL === $choice) {
$values[] = null;
continue;
}
$id = \call_user_func($value, $choice);
$values[] = $id;
$this->lazyLoadedPostalCodes[$id] = $choice;
}
return $values;
}
}

View File

@@ -0,0 +1,121 @@
<?php
/*
* Copyright (C) 2019 Champs Libres Cooperative <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/>.
*/
namespace Chill\MainBundle\Form\DataMapper;
use Symfony\Component\Form\DataMapperInterface;
use Chill\MainBundle\Entity\Address;
use Chill\MainBundle\Entity\PostalCode;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
/**
* Add a data mapper to Address.
*
* If the address is incomplete, the data mapper returns null
*/
class AddressDataMapper implements DataMapperInterface
{
/**
*
* @param Address $address
* @param \Iterator $forms
*/
public function mapDataToForms($address, $forms)
{
if (NULL === $address) {
return;
}
if (!$address instanceof Address) {
throw new UnexpectedTypeException($address, Address::class);
}
foreach ($forms as $key => $form) {
/** @var FormInterface $form */
switch ($key) {
case 'streetAddress1':
$form->setData($address->getStreetAddress1());
break;
case 'streetAddress2':
$form->setData($address->getStreetAddress2());
break;
case 'postCode':
$form->setData($address->getPostcode());
break;
case 'validFrom':
$form->setData($address->getValidFrom());
break;
case 'isNoAddress':
$form->setData($address->isNoAddress());
break;
default:
break;
}
}
}
/**
*
* @param \Iterator $forms
* @param Address $address
*/
public function mapFormsToData($forms, &$address)
{
if (!$address instanceof Address) {
$address = new Address();
}
$isNoAddress = false;
foreach ($forms as $key => $form) {
if ($key === 'isNoAddress') {
$isNoAddress = $form->get('isNoAddress')->getData();
}
}
foreach ($forms as $key => $form) {
/** @var FormInterface $form */
switch($key) {
case 'postCode':
if (!$form->getData() instanceof PostalCode && !$isNoAddress) {
$address = null;
return;
}
$address->setPostcode($form->getData());
break;
case 'streetAddress1':
if (empty($form->getData()) && !$isNoAddress) {
$address = null;
return;
}
$address->setStreetAddress1($form->getData());
break;
case 'streetAddress2':
$address->setStreetAddress2($form->getData());
break;
case 'validFrom':
$address->setValidFrom($form->getData());
break;
case 'isNoAddress':
$address->setIsNoAddress($form->getData());
break;
default:
break;
}
}
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace Chill\MainBundle\Form\DataMapper;
use Chill\MainBundle\Entity\Scope;
use Symfony\Component\Form\DataMapperInterface;
use Symfony\Component\Form\FormInterface;
class ScopePickerDataMapper implements DataMapperInterface
{
/**
* @var \Chill\MainBundle\Entity\Scope
*/
private $scope;
public function __construct(Scope $scope = null)
{
$this->scope = $scope;
}
public function mapDataToForms($data, $forms)
{
$forms = iterator_to_array($forms);
if ($this->scope instanceof Scope) {
$forms['scope']->setData($this->scope);
return;
}
if (null === $data) {
return;
}
if ($data instanceof Scope) {
$forms['scope']->setData($data);
}
}
public function mapFormsToData($forms, &$data)
{
$forms = iterator_to_array($forms);
if (isset($forms['scope'])) {
if ($this->scope instanceof Scope) {
$data = $this->scope;
} else {
$data = $forms['scope']->getData();
}
}
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Chill\MainBundle\Form\Extension;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Class CKEditorTypeExtension
*
* @package Chill\MainBundle\Form\Extension
* @author Mathieu Jaumotte mathieu.jaumotte@champs-libres.coop
*/
class CKEditorExtension extends AbstractTypeExtension
{
/**
* Return the class of the Textarea Type being extended.
* @return iterable
*/
public static function getExtendedTypes(): iterable
{
return [TextareaType::class];
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'attr' => [
'class' => 'ck ck-editor snippet-markdown'
]
]);
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace Chill\MainBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Chill\MainBundle\Form\Utils\PermissionsGroupFlagProvider;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class PermissionsGroupType extends AbstractType
{
/**
*
* @var PermissionsGroupFlagProvider[]
*/
protected $flagProviders = [];
const FLAG_SCOPE = 'permissions_group';
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class)
;
$flags = $this->getFlags();
if (count($flags) > 0) {
$builder
->add('flags', ChoiceType::class, [
'choices' => \array_combine($flags, $flags),
'multiple' => true,
'expanded' => true,
'required' => false
]);
}
}
/**
*
* @return array
*/
protected function getFlags(): array
{
$flags = [];
foreach ($this->flagProviders as $flagProvider) {
$flags = \array_merge($flags, $flagProvider->getPermissionsGroupFlags());
}
return $flags;
}
public function addFlagProvider(PermissionsGroupFlagProvider $provider)
{
$this->flagProviders[] = $provider;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Chill\MainBundle\Entity\PermissionsGroup'
));
}
/**
* @return string
*/
public function getBlockPrefix()
{
return 'chill_mainbundle_permissionsgroup';
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace Chill\MainBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
class ScopeType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TranslatableStringFormType::class)
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Chill\MainBundle\Entity\Scope'
));
}
/**
* @return string
*/
public function getBlockPrefix()
{
return 'chill_mainbundle_scope';
}
}

View File

@@ -0,0 +1,103 @@
<?php
/*
* Copyright (C) 2016 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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Chill\MainBundle\Entity\Address;
use Chill\MainBundle\Form\Type\PostalCodeType;
use Chill\MainBundle\Form\DataMapper\AddressDataMapper;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
/**
* A type to create/update Address entity
*
* Options:
*
* - `has_valid_from` (boolean): show if an entry "has valid from" must be
* shown.
* - `null_if_empty` (boolean): replace the address type by null if the street
* or the postCode is empty. This is useful when the address is not required and
* embedded in another form.
*/
class AddressType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('streetAddress1', TextType::class, array(
'required' => !$options['has_no_address'] // true if has no address is false
))
->add('streetAddress2', TextType::class, array(
'required' => false
))
->add('postCode', PostalCodeType::class, array(
'label' => 'Postal code',
'placeholder' => 'Choose a postal code',
'required' => !$options['has_no_address'] // true if has no address is false
))
;
if ($options['has_valid_from']) {
$builder
->add('validFrom', DateType::class, array(
'required' => true,
'widget' => 'single_text',
'format' => 'dd-MM-yyyy'
)
);
}
if ($options['has_no_address']) {
$builder
->add('isNoAddress', ChoiceType::class, [
'required' => true,
'choices' => [
'address.consider homeless' => true,
'address.real address' => false
],
'label' => 'address.address_homeless'
]);
}
if ($options['null_if_empty'] === TRUE) {
$builder->setDataMapper(new AddressDataMapper());
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver
->setDefault('data_class', Address::class)
->setDefined('has_valid_from')
->setAllowedTypes('has_valid_from', 'bool')
->setDefault('has_valid_from', true)
->setDefined('has_no_address')
->setDefault('has_no_address', false)
->setAllowedTypes('has_no_address', 'bool')
->setDefined('null_if_empty')
->setDefault('null_if_empty', false)
->setAllowedTypes('null_if_empty', 'bool')
;
}
}

View File

@@ -0,0 +1,152 @@
<?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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormBuilderInterface;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Center;
use Symfony\Component\Security\Core\Role\Role;
use Chill\MainBundle\Form\Type\DataTransformer\ScopeTransformer;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
/**
* Trait to add an input with reachable scope for a given center and role.
*
* Example usage :
*
* ```
* class AbcType extends Symfony\Component\Form\AbstractType
* {
* use AppendScopeChoiceTypeTrait;
* protected $authorizationHelper;
* protected $translatableStringHelper;
* protected $user;
* protected $om;
*
* public function __construct(AuthorizationHelper $helper,
* TokenStorageInterface $tokenStorage,
* TranslatableStringHelper $translatableStringHelper,
* ObjectManager $om)
* {
* $this->authorizationHelper = $helper;
* $this->user = $tokenStorage->getToken()->getUser();
* $this->translatableStringHelper = $translatableStringHelper;
* $this->om = $om;
* }
*
* public function buildForm(FormBuilder $builder, array $options)
* {
* // ... add your form there
*
* // append the scope using FormEvents: PRE_SET_DATA
* $this->appendScopeChoices($builder, $options['role'],
* $options['center'], $this->user, $this->authorizationHelper,
* $this->translatableStringHelper, $this->om);
* }
*
* public function configureOptions(OptionsResolver $resolver)
* {
* // ... add your options
*
* // add an option 'role' and 'center' to your form (optional)
* $this->appendScopeChoicesOptions($resolver);
* }
*
* }
* ```
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @author Champs Libres <info@champs-libres.coop>
*/
trait AppendScopeChoiceTypeTrait
{
/**
* Append a scope choice field, with the scopes reachable by given
* user for the given role and center.
*
* The field is added on event FormEvents::PRE_SET_DATA
*
* @param FormBuilderInterface $builder
* @param Role $role
* @param Center $center
* @param User $user
* @param AuthorizationHelper $authorizationHelper
* @param TranslatableStringHelper $translatableStringHelper
* @param string $name
*/
protected function appendScopeChoices(FormBuilderInterface $builder,
Role $role, Center $center, User $user,
AuthorizationHelper $authorizationHelper,
TranslatableStringHelper $translatableStringHelper,
ObjectManager $om, $name = 'scope')
{
$reachableScopes = $authorizationHelper
->getReachableScopes($user, $role, $center);
$choices = array();
foreach($reachableScopes as $scope) {
$choices[$scope->getId()] = $translatableStringHelper
->localize($scope->getName());
}
$dataTransformer = new ScopeTransformer($om);
$builder->addEventListener(FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($choices, $name, $dataTransformer, $builder) {
$form = $event->getForm();
$form->add(
$builder
->create($name, ChoiceType::class, array(
'choices' => array_combine(array_values($choices),array_keys($choices)),
'auto_initialize' => false
)
)
->addModelTransformer($dataTransformer)
->getForm()
);
});
}
/**
* Append a `role` and `center` option to the form.
*
* The allowed types are :
* - Chill\MainBundle\Entity\Center for center
* - Symfony\Component\Security\Core\Role\Role for role
*
* @param OptionsResolver $resolver
*/
public function appendScopeChoicesOptions(OptionsResolver $resolver)
{
$resolver
->setRequired(array('center', 'role'))
->setAllowedTypes('center', 'Chill\MainBundle\Entity\Center')
->setAllowedTypes('role', 'Symfony\Component\Security\Core\Role\Role')
;
}
}

View File

@@ -0,0 +1,136 @@
<?php
/*
* Copyright (C) 2015 Julien Fastré <julien.fastre@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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Form\Type\DataTransformer\CenterTransformer;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class CenterType extends AbstractType
{
/**
* The user linked with this type.
*
* @var \Chill\MainBundle\Entity\User
*/
protected $user;
/**
* associative array where keys are center.id and
* value are center objects
*
* @var Center[]
*/
protected $reachableCenters = array();
/**
*
* @var CenterTransformer
*/
protected $transformer;
public function __construct(TokenStorageInterface $tokenStorage,
CenterTransformer $transformer)
{
$this->user = $tokenStorage->getToken()->getUser();
$this->transformer = $transformer;
$this->prepareReachableCenterByUser();
}
/**
* return a 'hidden' field if only one center is available.
*
* Return a 'choice' field if more than one center is available.
*
* @return string
* @throws \RuntimeException if the user is not associated with any center
*/
public function getParent()
{
$nbReachableCenters = count($this->reachableCenters);
if ($nbReachableCenters === 0) {
throw new \RuntimeException("The user is not associated with "
. "any center. Associate user with a center");
} elseif ($nbReachableCenters === 1) {
return HiddenType::class;
} else {
return EntityType::class;
}
}
/**
* configure default options, i.e. add choices if user can reach multiple
* centers.
*
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
if (count($this->reachableCenters) > 1) {
$resolver->setDefault('class', Center::class);
$resolver->setDefault('choices', $this->reachableCenters);
}
}
/**
* add a data transformer if user can reach only one center
*
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
if ($this->getParent() === HiddenType::class) {
$builder->addModelTransformer($this->transformer);
}
}
/**
* populate reachableCenters as an associative array where
* keys are center.id and value are center entities.
*
*/
private function prepareReachableCenterByUser()
{
$groupCenters = $this->user->getGroupCenters();
foreach ($groupCenters as $groupCenter) {
$center = $groupCenter->getCenter();
if (!array_key_exists($center->getId(),
$this->reachableCenters)) {
$this->reachableCenters[$center->getId()] = $center;
}
}
}
}

View File

@@ -0,0 +1,61 @@
<?php
/*
* Copyright (C) 2018 Julien Fastré <julien.fastre@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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormInterface;
/**
* Available options :
*
* - `button_add_label`
* - `button_remove_label`
* - `identifier`: an identifier to identify the kind of collecton. Useful if some
* javascript should be launched associated to `add_entry`, `remove_entry` events.
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class ChillCollectionType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver
->setDefaults([
'button_add_label' => 'Add an entry',
'button_remove_label' => 'Remove entry',
'identifier' => ''
]);
}
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['button_add_label'] = $options['button_add_label'];
$view->vars['button_remove_label'] = $options['button_remove_label'];
$view->vars['allow_delete'] = (int) $options['allow_delete'];
$view->vars['allow_add'] = (int) $options['allow_add'];
$view->vars['identifier'] = $options['identifier'];
}
public function getParent()
{
return \Symfony\Component\Form\Extension\Core\Type\CollectionType::class;
}
}

View File

@@ -0,0 +1,50 @@
<?php
/*
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Display the date in a date picker.
*
* Extends the symfony `Symfony\Component\Form\Extension\Core\Type\DateType`
* to automatically create a date picker.
*
* @author Mathieu Jaumotte <jaum_mathieu@collectifs.net>
*/
class ChillDateTimeType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver
->setDefault('date_widget', 'single_text')
->setDefault('date_format', 'dd-MM-yyyy')
->setDefault('time_widget', 'choice')
->setDefault('minutes', range(0, 59, 5))
->setDefault('hours', range(8, 22))
->setDefault('html5', true)
;
}
public function getParent()
{
return DateTimeType::class;
}
}

View File

@@ -0,0 +1,47 @@
<?php
/*
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Display the date in a date picker.
*
* Extends the symfony `Symfony\Component\Form\Extension\Core\Type\DateType`
* to automatically create a date picker.
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class ChillDateType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver
->setDefault('widget', 'single_text')
->setDefault('attr', [ 'class' => 'datepicker' ])
->setDefault('format', 'dd-MM-yyyy')
;
}
public function getParent()
{
return DateType::class;
}
}

View File

@@ -0,0 +1,79 @@
<?php
/*
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class CommentType extends AbstractType
{
/**
* @var \Symfony\Component\Security\Core\User\UserInterface
*/
protected $user;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->user = $tokenStorage->getToken()->getUser();
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('comment', TextareaType::class, [
])
;
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$data = $event->getForm()->getData();
$comment = $event->getData();
if ($data->getComment() !== $comment['comment']) {
$data->setDate(new \DateTime());
$data->setUserId($this->user->getId());
$event->getForm()->setData($data);
}
});
}
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars = array_replace(
$view->vars, [
'hideLabel' => true,
]
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => CommentEmbeddable::class,
]);
}
}

View File

@@ -0,0 +1,64 @@
<?php
/*
* Copyright (C) 2015 Julien Fastré <julien.fastre@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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Chill\MainBundle\Entity\PermissionsGroup;
use Chill\MainBundle\Entity\Center;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class ComposedGroupCenterType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('permissionsgroup', EntityType::class, array(
'class' => 'Chill\MainBundle\Entity\PermissionsGroup',
'choice_label' => function(PermissionsGroup $group) {
return $group->getName();
}
))->add('center', EntityType::class, array(
'class' => 'Chill\MainBundle\Entity\Center',
'choice_label' => function(Center $center) {
return $center->getName();
}
))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('data_class', 'Chill\MainBundle\Entity\GroupCenter');
}
public function getBlockPrefix()
{
return 'composed_groupcenter';
}
}

View File

@@ -0,0 +1,122 @@
<?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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Security\RoleProvider;
/**
* Form to Edit/create a role scope. If the role scope does not
* exists in the database, he is generated.
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @author Champs Libres <info@champs-libres.coop>
*/
class ComposedRoleScopeType extends AbstractType
{
/**
*
* @var string[]
*/
private $roles = array();
/**
*
* @var string[]
*/
private $rolesWithoutScope = array();
/**
*
* @var TranslatableStringHelper
*/
private $translatableStringHelper;
/**
*
* @var RoleProvider
*/
private $roleProvider;
public function __construct(
TranslatableStringHelper $translatableStringHelper,
RoleProvider $roleProvider
) {
$this->roles = $roleProvider->getRoles();
$this->rolesWithoutScope = $roleProvider->getRolesWithoutScopes();
$this->translatableStringHelper = $translatableStringHelper;
$this->roleProvider = $roleProvider;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
// store values used in internal function
$translatableStringHelper = $this->translatableStringHelper;
$rolesWithoutScopes = $this->rolesWithoutScope;
//build roles
$values = array();
foreach ($this->roles as $role) {
$values[$role] = $role;
}
$builder
->add('role', ChoiceType::class, array(
'choices' => array_combine(array_values($values),array_keys($values)),
'placeholder' => 'Choose amongst roles',
'choice_attr' => function($role) use ($rolesWithoutScopes) {
if (in_array($role, $rolesWithoutScopes)) {
return array('data-has-scope' => '0');
} else {
return array('data-has-scope' => '1');
}
},
'group_by' => function($role, $key, $index) {
return $this->roleProvider->getRoleTitle($role);
}
))
->add('scope', EntityType::class, array(
'class' => 'ChillMainBundle:Scope',
'choice_label' => function(Scope $scope) use ($translatableStringHelper) {
return $translatableStringHelper->localize($scope->getName());
},
'required' => false,
'data' => null
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('data_class', 'Chill\MainBundle\Entity\RoleScope');
}
}

View File

@@ -0,0 +1,70 @@
<?php
/*
* Copyright (C) 2015 Julien Fastré <julien.fastre@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/>.
*/
namespace Chill\MainBundle\Form\Type\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\Form\Exception\TransformationFailedException;
/**
* Transform a center object to his id, and vice-versa
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class CenterTransformer implements DataTransformerInterface
{
/**
*
* @var ObjectManager
*/
private $om;
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
public function reverseTransform($id)
{
if ($id === NULL) {
return NULL;
}
$center = $this->om->getRepository('ChillMainBundle:Center')
->find($id);
if ($center === NULL) {
throw new TransformationFailedException(sprintf(
'No center found with id %d', $id));
}
return $center;
}
public function transform($center)
{
if ($center === NULL) {
return '';
}
return $center->getId();
}
}

View File

@@ -0,0 +1,92 @@
<?php
/*
* Copyright (C) 2018 Champs Libres Cooperative <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/>.
*/
namespace Chill\MainBundle\Form\Type\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class DateIntervalTransformer implements DataTransformerInterface
{
/**
*
* @param \DateInterval $value
* @throws UnexpectedTypeException
*/
public function transform($value)
{
if (empty($value)) {
return null;
}
if (!$value instanceof \DateInterval) {
throw new UnexpectedTypeException($value, \DateInterval::class);
}
if ($value->d > 0) {
// we check for weeks (weeks are converted to 7 days)
if ($value->d % 7 === 0) {
return [
'n' => $value->d / 7,
'unit' => 'W'
];
} else {
return [
'n' => $value->d,
'unit' => 'D'
];
}
} elseif ($value->m > 0) {
return [
'n' => $value->m,
'unit' => 'M'
];
} elseif ($value->y > 0) {
return [
'n' => $value->y,
'unit' => 'Y'
];
}
throw new TransformationFailedException('the date interval does not '
. 'contains any days, months or years');
}
public function reverseTransform($value)
{
if (empty($value) or empty($value['n'])) {
return null;
}
$string = 'P'.$value['n'].$value['unit'];
try {
return new \DateInterval($string);
} catch (\Exception $e) {
throw new TransformationFailedException("Could not transform value "
. "into DateInterval", 1542, $e);
}
}
}

View File

@@ -0,0 +1,85 @@
<?php
/*
* Chill is a software for social workers
* Copyright (C) 2014 Champs-Libres Coopérative <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/>.
*/
namespace Chill\MainBundle\Form\Type\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Persistence\ObjectManager;
use Doctrine\Common\Collections\ArrayCollection;
class MultipleObjectsToIdTransformer implements DataTransformerInterface
{
/**
* @var ObjectManager
*/
private $em;
/**
* @var string
*/
private $class;
/**
* @param ObjectManager $em
*/
public function __construct(ObjectManager $em, $class)
{
$this->em = $em;
$this->class = $class;
}
/**
* Transforms an object (use) to a string (id).
*
* @param array $array
* @return ArrayCollection
*/
public function transform($array)
{
$ret = array();
foreach ($array as $el) {
$ret[] = ($el->getId());
}
return $ret;
}
/**
* Transforms a string (id) to an object (item).
*
* @param string $id
* @return ArrayCollection
*/
public function reverseTransform($array)
{
$ret = new ArrayCollection();
foreach ($array as $el) {
$ret->add(
$this->em
->getRepository($this->class)
->find($el)
);
}
return $ret;
}
}

View File

@@ -0,0 +1,87 @@
<?php
/*
* Chill is a software for social workers
* Copyright (C) 2014 Champs-Libres Coopérative <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/>.
*/
namespace Chill\MainBundle\Form\Type\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Persistence\ObjectManager;
class ObjectToIdTransformer implements DataTransformerInterface
{
/**
* @var ObjectManager
*/
private $om;
/**
* @var string
*/
private $class;
/**
* @param ObjectManager $om
*/
public function __construct(ObjectManager $om, $class)
{
$this->om = $om;
$this->class = $class;
}
/**
* Transforms an object to a string (id)
*
* @param Object|null $Object
* @return string
*/
public function transform($object)
{
if (!$object) {
return "";
}
return $object->getId();
}
/**
* Transforms a string (id) to an object
*
* @param string $id
* @return Object|null
* @throws TransformationFailedException if object is not found.
*/
public function reverseTransform($id)
{
if (!$id) {
return null;
}
$object = $this->om
->getRepository($this->class)
->find($id)
;
if (! $object) {
throw new TransformationFailedException();
}
return $object;
}
}

View File

@@ -0,0 +1,77 @@
<?php
/*
* Copyright (C) 2015 Julien Fastré <julien.fastre@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/>.
*/
namespace Chill\MainBundle\Form\Type\DataTransformer;
use Symfony\Component\Form\DataTransformerInterface;
use Doctrine\Persistence\ObjectManager;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Chill\MainBundle\Templating\TranslatableStringHelper;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class ScopeTransformer implements DataTransformerInterface
{
/**
*
* @var ObjectManager
*/
protected $om;
/**
*
* @var TranslatableStringHelper
*/
protected $helper;
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
public function transform($scope)
{
if ($scope === NULL) {
return NULL;
}
return $scope->getId();
}
public function reverseTransform($id)
{
if ($id == NULL) {
return NULL;
}
$scope = $this->om->getRepository('ChillMainBundle:Scope')
->find($id);
if ($scope === NULL) {
throw new TransformationFailedException(sprintf("The scope with id "
. "'%d' were not found", $id));
}
return $scope;
}
}

View File

@@ -0,0 +1,108 @@
<?php
/*
* Copyright (C) 2018 Champs Libres Cooperative <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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Form\Type\DataTransformer\DateIntervalTransformer;
use Symfony\Component\Validator\Constraints\GreaterThan;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
/**
* Show a dateInterval type
*
* Options:
*
* - `unit_choices`: an array of available units choices.
*
* The oiriginal `unit_choices` are :
* ```
* [
* 'Days' => 'D',
* 'Weeks' => 'W',
* 'Months' => 'M',
* 'Years' => 'Y'
* ]
* ```
*
* You can remove one or more entries:
*
* ```
* $builder
* ->add('duration', DateIntervalType::class, array(
* 'unit_choices' => [
* 'Years' => 'Y',
* 'Months' => 'M',
* ]
* ));
* ```
*
*/
class DateIntervalType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('n', IntegerType::class, [
'scale' => 0,
'constraints' => [
new GreaterThan([
'value' => 0
])
]
])
->add('unit', ChoiceType::class, [
'choices' => $options['unit_choices'],
])
;
$builder->addModelTransformer(new DateIntervalTransformer());
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver
->setDefined('unit_choices')
->setDefault('unit_choices', [
'Days' => 'D',
'Weeks' => 'W',
'Months' => 'M',
'Years' => 'Y'
])
->setAllowedValues('unit_choices', function($values) {
if (FALSE === is_array($values)) {
throw new InvalidOptionsException("The value `unit_choice` should be an array");
}
$diff = \array_diff(\array_values($values), ['D', 'W', 'M', 'Y']);
if (count($diff) == 0) {
return true;
} else {
throw new InvalidOptionsException(sprintf("The values of the "
. "units should be 'D', 'W', 'M', 'Y', those are invalid: %s",
\implode(', ', $diff)));
}
})
;
}
}

View File

@@ -0,0 +1,74 @@
<?php
/*
* 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/>.
*/
namespace Chill\MainBundle\Form\Type\Export;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Chill\MainBundle\Export\ExportManager;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class AggregatorType extends AbstractType
{
public function __construct()
{
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$exportManager = $options['export_manager'];
$aggregator = $exportManager->getAggregator($options['aggregator_alias']);
$builder
->add('enabled', CheckboxType::class, array(
'value' => true,
'required' => false,
'data' => false
));
$filterFormBuilder = $builder->create('form', FormType::class, array(
'compound' => true,
'required' => false,
'error_bubbling' => false
));
$aggregator->buildForm($filterFormBuilder);
$builder->add($filterFormBuilder);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired('aggregator_alias')
->setRequired('export_manager')
->setDefault('compound', true)
->setDefault('error_bubbling', false)
;
}
}

View File

@@ -0,0 +1,147 @@
<?php
/*
* Chill is a software for social workers
*
* Copyright (C) 2014-2015, 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/>.
*/
namespace Chill\MainBundle\Form\Type\Export;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormBuilderInterface;
use Chill\MainBundle\Export\ExportManager;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Chill\MainBundle\Form\Type\Export\AggregatorType;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Chill\MainBundle\Validator\Constraints\Export\ExportElementConstraint;
use Chill\MainBundle\Export\ExportElementWithValidationInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class ExportType extends AbstractType
{
/**
*
* @var ExportManager
*/
protected $exportManager;
const FILTER_KEY = 'filters';
const AGGREGATOR_KEY = 'aggregators';
const PICK_FORMATTER_KEY = 'pick_formatter';
const EXPORT_KEY = 'export';
public function __construct(ExportManager $exportManager)
{
$this->exportManager = $exportManager;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$export = $this->exportManager->getExport($options['export_alias']);
$exportOptions = array(
'compound' => true,
'constraints' => array(
)
);
// add a contraint if required by export
$exportBuilder = $builder->create(self::EXPORT_KEY/*, FormType::class, $exportOptions*/);
$export->buildForm($exportBuilder);
$builder->add($exportBuilder, null, $exportOptions);
if ($export instanceof \Chill\MainBundle\Export\ExportInterface) {
//add filters
$filters = $this->exportManager->getFiltersApplyingOn($export, $options['picked_centers']);
$filterBuilder = $builder->create(self::FILTER_KEY, FormType::class, array('compound' => true));
foreach($filters as $alias => $filter) {
$filterBuilder->add($alias, FilterType::class, array(
'filter_alias' => $alias,
'export_manager' => $this->exportManager,
'label' => $filter->getTitle(),
'constraints' => array(
new ExportElementConstraint(['element' => $filter])
)
));
}
$builder->add($filterBuilder);
//add aggregators
$aggregators = $this->exportManager
->getAggregatorsApplyingOn($export, $options['picked_centers']);
$aggregatorBuilder = $builder->create(self::AGGREGATOR_KEY, FormType::class,
array('compound' => true));
foreach($aggregators as $alias => $aggregator) {
$aggregatorBuilder->add($alias, AggregatorType::class, array(
'aggregator_alias' => $alias,
'export_manager' => $this->exportManager,
'label' => $aggregator->getTitle(),
'constraints' => array(
new ExportElementConstraint(['element' => $aggregator])
)
));
}
$builder->add($aggregatorBuilder);
}
// add export form
$exportBuilder = $builder->create(self::EXPORT_KEY, FormType::class, array('compound' => true));
$this->exportManager->getExport($options['export_alias'])
->buildForm($exportBuilder);
$builder->add($exportBuilder);
if ($export instanceof \Chill\MainBundle\Export\ExportInterface) {
$builder->add(self::PICK_FORMATTER_KEY, PickFormatterType::class, array(
'export_alias' => $options['export_alias']
));
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired(array('export_alias', 'picked_centers'))
->setAllowedTypes('export_alias', array('string'))
->setDefault('compound', true)
->setDefault('constraints', array(
//new \Chill\MainBundle\Validator\Constraints\Export\ExportElementConstraint()
))
;
}
public function getParent()
{
return FormType::class;
}
}

View File

@@ -0,0 +1,78 @@
<?php
/*
* 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/>.
*/
namespace Chill\MainBundle\Form\Type\Export;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormBuilderInterface;
use Chill\MainBundle\Export\ExportManager;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Chill\MainBundle\Export\ExportElementWithValidationInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Form\Extension\Core\Type\FormType;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class FilterType extends AbstractType
{
const ENABLED_FIELD = 'enabled';
public function __construct()
{
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$exportManager = $options['export_manager'];
$filter = $exportManager->getFilter($options['filter_alias']);
$builder
->add(self::ENABLED_FIELD, CheckboxType::class, array(
'value' => true,
'data' => false,
'required' => false
));
$filterFormBuilder = $builder->create('form', FormType::class, array(
'compound' => true,
'error_bubbling' => false,
'required' => false,
));
$filter->buildForm($filterFormBuilder);
$builder->add($filterFormBuilder);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired('filter_alias')
->setRequired('export_manager')
->setDefault('compound', true)
->setDefault('error_bubbling', false)
;
}
}

View File

@@ -0,0 +1,59 @@
<?php
/*
* Copyright (C) 2016 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/>.
*/
namespace Chill\MainBundle\Form\Type\Export;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormBuilderInterface;
use Chill\MainBundle\Export\ExportManager;
/**
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class FormatterType extends AbstractType
{
/**
*
* @var ExportManager
*/
protected $exportManager;
public function __construct(ExportManager $manager)
{
$this->exportManager = $manager;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired(array('formatter_alias', 'export_alias',
'aggregator_aliases'));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$formatter = $this->exportManager->getFormatter($options['formatter_alias']);
$formatter->buildForm($builder, $options['export_alias'],
$options['aggregator_aliases']);
}
}

View File

@@ -0,0 +1,182 @@
<?php
/*
* Copyright (C) 2016 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/>.
*/
namespace Chill\MainBundle\Form\Type\Export;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Chill\MainBundle\Export\ExportManager;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Center\GroupingCenterInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\CallbackTransformer;
use Doctrine\Common\Collections\Collection;
/**
* Pick centers amongst available centers for the user
*
*/
class PickCenterType extends AbstractType
{
/**
*
* @var \Symfony\Component\Security\Core\User\UserInterface
*/
protected $user;
/**
*
* @var ExportManager
*/
protected $exportManager;
/**
*
* @var GroupingCenterInterface[]
*/
protected $groupingCenters = [];
const CENTERS_IDENTIFIERS = 'c';
/**
*
* @var AuthorizationHelper
*/
protected $authorizationHelper;
public function __construct(TokenStorageInterface $tokenStorage,
ExportManager $exportManager, AuthorizationHelper $authorizationHelper)
{
$this->exportManager = $exportManager;
$this->user = $tokenStorage->getToken()->getUser();
$this->authorizationHelper = $authorizationHelper;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired('export_alias')
;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$export = $this->exportManager->getExport($options['export_alias']);
$centers = $this->authorizationHelper->getReachableCenters($this->user,
$export->requiredRole());
$builder->add(self::CENTERS_IDENTIFIERS, EntityType::class, array(
'class' => 'ChillMainBundle:Center',
'query_builder' => function(EntityRepository $er) use ($centers) {
$qb = $er->createQueryBuilder('c');
$ids = array_map(function(Center $el) { return $el->getId(); },
$centers);
return $qb->where($qb->expr()->in('c.id', $ids));
},
'multiple' => true,
'expanded' => true,
'choice_label' => function(Center $c) { return $c->getName(); },
'data' => count($this->groupingCenters) > 0 ? null : $centers
));
if (count($this->groupingCenters) > 0) {
$groupingBuilder = $builder->create('g', null, [
'compound' => true
]);
foreach ($this->groupingCenters as $key => $gc) {
$choices = $this->buildChoices($centers, $gc);
if (count($choices) > 0) {
$groupingBuilder->add($key, ChoiceType::class, [
'choices' => $choices,
'multiple' => true,
'expanded' => true,
'label' => $gc->getName(),
'required' => false
]);
}
}
if ($groupingBuilder->count() > 0) {
$builder->add($groupingBuilder);
}
}
$builder->addModelTransformer(new CallbackTransformer(
function($data) use ($centers) { return $this->transform($data, $centers); },
function($data) use ($centers) { return $this->reverseTransform($data, $centers); }
));
}
public function addGroupingCenter(GroupingCenterInterface $grouping)
{
$this->groupingCenters[md5($grouping->getName())] = $grouping;
}
protected function buildChoices($reachablesCenters, GroupingCenterInterface $gc)
{
$result = [];
foreach ($gc->getGroups() as $group) {
foreach ($gc->getCentersForGroup($group) as $center) {
if (\in_array($center, $reachablesCenters)) {
$result[$group] = $group;
}
}
}
return $result;
}
protected function transform($data, $centers)
{
return $data;
}
protected function reverseTransform($data, $centers)
{
$picked = $data[self::CENTERS_IDENTIFIERS]
instanceof \Doctrine\Common\Collections\Collection ?
$data[self::CENTERS_IDENTIFIERS]->toArray()
:
$data[self::CENTERS_IDENTIFIERS];
if (\array_key_exists('g', $data)) {
foreach($data['g'] as $gcid => $group) {
$picked =
\array_merge(
\array_intersect(
$this->groupingCenters[$gcid] ->getCentersForGroup($group),
$centers
),
$picked
)
;
}
}
return \array_unique($picked);
}
}

View File

@@ -0,0 +1,70 @@
<?php
/*
* Copyright (C) 2016 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/>.
*/
namespace Chill\MainBundle\Form\Type\Export;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Chill\MainBundle\Export\ExportManager;
/**
* Choose a formatter amongst the available formatters
*
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class PickFormatterType extends AbstractType
{
protected $exportManager;
public function __construct(ExportManager $exportManager)
{
$this->exportManager = $exportManager;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$export = $this->exportManager->getExport($options['export_alias']);
$allowedFormatters = $this->exportManager
->getFormattersByTypes($export->getAllowedFormattersTypes());
//build choices
$choices = array();
foreach($allowedFormatters as $alias => $formatter) {
$choices[$formatter->getName()] = $alias;
}
$builder->add('alias', ChoiceType::class, array(
'choices' => $choices,
'multiple' => false,
'placeholder' => 'Choose a format'
));
//$builder->get('type')->addModelTransformer($transformer);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired(array('export_alias'));
}
}

View File

@@ -0,0 +1,110 @@
<?php
/*
* Copyright (C) 2016 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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Chill\MainBundle\Entity\PostalCode;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Chill\MainBundle\Form\ChoiceLoader\PostalCodeChoiceLoader;
use Symfony\Component\Translation\TranslatorInterface;
/**
* A form to pick between PostalCode
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @author Champs Libres <info@champs-libres.coop>
*/
class PostalCodeType extends AbstractType
{
/**
*
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
/**
*
* @var UrlGeneratorInterface
*/
protected $urlGenerator;
/**
*
* @var PostalCodeChoiceLoader
*/
protected $choiceLoader;
/**
*
* @var TranslatorInterface
*/
protected $translator;
public function __construct(
TranslatableStringHelper $helper,
UrlGeneratorInterface $urlGenerator,
PostalCodeChoiceLoader $choiceLoader,
TranslatorInterface $translator
) {
$this->translatableStringHelper = $helper;
$this->urlGenerator = $urlGenerator;
$this->choiceLoader = $choiceLoader;
$this->translator = $translator;
}
public function getParent()
{
return EntityType::class;
}
public function configureOptions(OptionsResolver $resolver)
{
// create a local copy for usage in Closure
$helper = $this->translatableStringHelper;
$resolver
->setDefault('class', PostalCode::class)
->setDefault('choice_label', function(PostalCode $code) use ($helper) {
return $code->getCode().' '.$code->getName().' ['.
$helper->localize($code->getCountry()->getName()).']';
})
->setDefault('choice_loader', $this->choiceLoader)
->setDefault('placeholder', 'Select a postal code')
;
}
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['attr']['data-postal-code'] = 'data-postal-code';
$view->vars['attr']['data-select-interactive-loading'] = true;
$view->vars['attr']['data-search-url'] = $this->urlGenerator
->generate('chill_main_postal_code_search');
$view->vars['attr']['data-placeholder'] = $this->translator->trans($options['placeholder']);
$view->vars['attr']['data-no-results-label'] = $this->translator->trans('select2.no_results');
$view->vars['attr']['data-error-load-label'] = $this->translator->trans('select2.error_loading');
$view->vars['attr']['data-searching-label'] = $this->translator->trans('select2.searching');
}
}

View File

@@ -0,0 +1,162 @@
<?php
/*
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Form\DataMapper\ScopePickerDataMapper;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Role\Role;
/**
* Allow to pick amongst available scope for the current
* user.
*
* options :
*
* - `center`: the center of the entity
* - `role` : the role of the user
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class ScopePickerType extends AbstractType
{
/**
* @var AuthorizationHelper
*/
protected $authorizationHelper;
/**
* @var TokenStorageInterface
*/
protected $tokenStorage;
/**
* @var EntityRepository
*/
protected $scopeRepository;
/**
* @var TranslatableStringHelper
*/
protected $translatableStringHelper;
public function __construct(
AuthorizationHelper $authorizationHelper,
TokenStorageInterface $tokenStorage,
EntityRepository $scopeRepository,
TranslatableStringHelper $translatableStringHelper
) {
$this->authorizationHelper = $authorizationHelper;
$this->tokenStorage = $tokenStorage;
$this->scopeRepository = $scopeRepository;
$this->translatableStringHelper = $translatableStringHelper;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$query = $this->buildAccessibleScopeQuery($options['center'], $options['role']);
$items = $query->getQuery()->execute();
if (1 !== count($items)) {
$builder->add('scope', EntityType::class, [
'class' => Scope::class,
'placeholder' => 'Choose the circle',
'choice_label' => function (Scope $c) {
return $this->translatableStringHelper->localize($c->getName());
},
'query_builder' => function () use ($options) {
return $this->buildAccessibleScopeQuery($options['center'], $options['role']);
},
]);
$builder->setDataMapper(new ScopePickerDataMapper());
} else {
$builder->add('scope', HiddenType::class, [
'data' => $items[0]->getId(),
]);
$builder->setDataMapper(new ScopePickerDataMapper($items[0]));
}
}
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars = array_replace(
$view->vars, [
'hideLabel' => true,
]
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver
// create `center` option
->setRequired('center')
->setAllowedTypes('center', [Center::class])
// create ``role` option
->setRequired('role')
->setAllowedTypes('role', ['string', Role::class]);
}
/**
* @return \Doctrine\ORM\QueryBuilder
*/
protected function buildAccessibleScopeQuery(Center $center, Role $role)
{
$roles = $this->authorizationHelper->getParentRoles($role);
$roles[] = $role;
$qb = $this->scopeRepository->createQueryBuilder('s');
$qb
// jointure to center
->join('s.roleScopes', 'rs')
->join('rs.permissionsGroups', 'pg')
->join('pg.groupCenters', 'gc')
// add center constraint
->where($qb->expr()->eq('IDENTITY(gc.center)', ':center'))
->setParameter('center', $center->getId())
// role constraints
->andWhere($qb->expr()->in('rs.role', ':roles'))
->setParameter(
'roles', \array_map(
function (Role $role) {
return $role->getRole();
},
$roles
)
)
// user contraint
->andWhere(':user MEMBER OF gc.users')
->setParameter('user', $this->tokenStorage->getToken()->getUser());
return $qb;
}
}

View File

@@ -0,0 +1,51 @@
<?php
/*
* Chill is a software for social workers
* Copyright (C) 2014 Champs-Libres Coopérative <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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
/**
* Extends choice to allow adding select2 library on widget
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class Select2ChoiceType extends AbstractType
{
public function getBlockPrefix()
{
return 'select2_choice';
}
public function getParent()
{
return ChoiceType::class;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
array(
'attr' => array('class' => 'select2 '),
));
}
}

View File

@@ -0,0 +1,88 @@
<?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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Form\FormBuilderInterface;
use Chill\MainBundle\Form\Type\DataTransformer\ObjectToIdTransformer;
use Doctrine\Persistence\ObjectManager;
use Chill\MainBundle\Form\Type\Select2ChoiceType;
/**
* Extends choice to allow adding select2 library on widget
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
* @author Marc Ducobu <marc.ducobu@champs-libres.coop>
*/
class Select2CountryType extends AbstractType
{
/**
* @var RequestStack
*/
private $requestStack;
/**
* @var ObjectManager
*/
private $em;
public function __construct(RequestStack $requestStack,ObjectManager $em)
{
$this->requestStack = $requestStack;
$this->em = $em;
}
public function getBlockPrefix()
{
return 'select2_chill_country';
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new ObjectToIdTransformer($this->em,'Chill\MainBundle\Entity\Country');
$builder->addModelTransformer($transformer);
}
public function getParent()
{
return Select2ChoiceType::class;
}
public function configureOptions(OptionsResolver $resolver)
{
$locale = $this->requestStack->getCurrentRequest()->getLocale();
$countries = $this->em->getRepository('Chill\MainBundle\Entity\Country')->findAll();
$choices = array();
foreach ($countries as $c) {
$choices[$c->getId()] = $c->getName()[$locale];
}
asort($choices, SORT_STRING | SORT_FLAG_CASE);
$resolver->setDefaults(array(
'class' => 'Chill\MainBundle\Entity\Country',
'choices' => array_combine(array_values($choices),array_keys($choices))
));
}
}

View File

@@ -0,0 +1,50 @@
<?php
/*
* Chill is a software for social workers
* Copyright (C) 2014 Champs-Libres Coopérative <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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
/**
* Extends choice to allow adding select2 library on widget
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class Select2EntityType extends AbstractType
{
public function getBlockPrefix()
{
return 'select2_entity';
}
public function getParent()
{
return EntityType::class;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->replaceDefaults(
array('attr' => array('class' => 'select2 '))
);
}
}

View File

@@ -0,0 +1,85 @@
<?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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Form\FormBuilderInterface;
use Chill\MainBundle\Form\Type\DataTransformer\MultipleObjectsToIdTransformer;
use Doctrine\Persistence\ObjectManager;
use Chill\MainBundle\Form\Type\Select2ChoiceType;
/**
* Extends choice to allow adding select2 library on widget for languages (multiple)
*/
class Select2LanguageType extends AbstractType
{
/**
* @var RequestStack
*/
private $requestStack;
/**
* @var ObjectManager
*/
private $em;
public function __construct(RequestStack $requestStack,ObjectManager $em)
{
$this->requestStack = $requestStack;
$this->em = $em;
}
public function getBlockPrefix()
{
return 'select2_chill_language';
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new MultipleObjectsToIdTransformer($this->em,'Chill\MainBundle\Entity\Language');
$builder->addModelTransformer($transformer);
}
public function getParent()
{
return Select2ChoiceType::class;
}
public function configureOptions(OptionsResolver $resolver)
{
$locale = $this->requestStack->getCurrentRequest()->getLocale();
$languages = $this->em->getRepository('Chill\MainBundle\Entity\Language')->findAll();
$choices = array();
foreach ($languages as $l) {
$choices[$l->getId()] = $l->getName()[$locale];
}
asort($choices, SORT_STRING | SORT_FLAG_CASE);
$resolver->setDefaults(array(
'class' => 'Chill\MainBundle\Entity\Language',
'choices' => array_combine(array_values($choices),array_keys($choices))
));
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Chill\MainBundle\Form\Type;
/*
* TODO
*/
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Translation\Translator;
use Symfony\Component\Form\Extension\Core\Type\TextType;
class TranslatableStringFormType extends AbstractType
{
private $availableLanguages; // The langauges availaible
private $frameworkTranslatorFallback; // The langagues used for the translation
public function __construct(array $availableLanguages, Translator $translator) {
$this->availableLanguages = $availableLanguages;
$this->frameworkTranslatorFallback = $translator->getFallbackLocales();
}
public function buildForm(FormBuilderInterface $builder, array $options) {
foreach ($this->availableLanguages as $lang) {
$builder->add($lang, TextType::class,
array('required' => (in_array($lang,
$this->frameworkTranslatorFallback))));
}
}
public function getBlockPrefix()
{
return 'translatable_string';
}
}

View File

@@ -0,0 +1,112 @@
<?php
/*
* Copyright (C) 2017 Champs Libres Cooperative <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/>.
*/
namespace Chill\MainBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Chill\MainBundle\Security\Authorization\AuthorizationHelper;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Chill\MainBundle\Entity\User;
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
use Symfony\Component\Security\Core\Role\Role;
/**
* Pick a user available for the given role and center.
*
* Options :
*
* - `role` : the role the user can reach
* - `center`: the center a user can reach
*
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*/
class UserPickerType extends AbstractType
{
/**
*
* @var AuthorizationHelper
*/
protected $authorizationHelper;
/**
*
* @var TokenStorageInterface
*/
protected $tokenStorage;
/**
*
* @var \Chill\MainBundle\Repository\UserRepository
*/
protected $userRepository;
public function __construct(
AuthorizationHelper $authorizationHelper,
TokenStorageInterface $tokenStorage,
EntityRepository $userRepository
) {
$this->authorizationHelper = $authorizationHelper;
$this->tokenStorage = $tokenStorage;
$this->userRepository = $userRepository;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver
// create `center` option
->setRequired('center')
->setAllowedTypes('center', [\Chill\MainBundle\Entity\Center::class ])
// create ``role` option
->setRequired('role')
->setAllowedTypes('role', ['string', \Symfony\Component\Security\Core\Role\Role::class ])
;
$resolver
->setDefault('having_permissions_group_flag', null)
->setAllowedTypes('having_permissions_group_flag', ['string', 'null'])
->setDefault('class', User::class)
->setDefault('placeholder', 'Choose an user')
->setDefault('choice_label', function(User $u) {
return $u->getUsername();
})
->setNormalizer('choices', function(Options $options) {
$users = $this->authorizationHelper
->findUsersReaching($options['role'], $options['center']);
if (NULL !== $options['having_permissions_group_flag']) {
return $this->userRepository
->findUsersHavingFlags($options['having_permissions_group_flag'], $users)
;
}
return $users;
})
;
}
public function getParent()
{
return EntityType::class;
}
}

View File

@@ -0,0 +1,111 @@
<?php
namespace Chill\MainBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Regex;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Symfony\Component\Validator\Constraints\Callback;
use Psr\Log\LoggerInterface;
class UserPasswordType extends AbstractType
{
/**
*
* @var UserPasswordEncoderInterface
*/
protected $passwordEncoder;
/**
*
* @var LoggerInterface
*/
protected $chillLogger;
public function __construct(
UserPasswordEncoderInterface $passwordEncoder,
LoggerInterface $chillLogger
) {
$this->passwordEncoder = $passwordEncoder;
$this->chillLogger = $chillLogger;
}
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('new_password', RepeatedType::class, array(
'type' => PasswordType::class,
'required' => false,
'options' => array(),
'first_options' => array(
'label' => 'Password'
),
'second_options' => array(
'label' => 'Repeat the password'
),
'invalid_message' => "The password fields must match",
'constraints' => array(
new Length(array(
'min' => 9,
'minMessage' => 'The password must be greater than {{ limit }} characters'
)),
new NotBlank(),
new Regex(array(
'pattern' => "/((?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%!,;:+\"'-\/{}~=µ\(\)£]).{6,})/",
'message' => "The password must contains one letter, one "
. "capitalized letter, one number and one special character "
. "as *[@#$%!,;:+\"'-/{}~=µ()£]). Other characters are allowed."
))
)
))
->add('actual_password', PasswordType::class, [
'label' => 'Your actual password',
'mapped' => false,
'constraints' => [
new Callback([
'callback' => function($password, ExecutionContextInterface $context, $payload) use ($options) {
if (TRUE === $this->passwordEncoder->isPasswordValid($options['user'], $password)) {
return;
}
// password problem :-)
$this->chillLogger
->notice("incorrect password when trying to change password", [
'username' => $options['user']->getUsername()
]);
$context->addViolation('Incorrect password');
}
])
]
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver
->setRequired('user')
->setAllowedTypes('user', \Chill\MainBundle\Entity\User::class)
;
}
/**
* @return string
*/
public function getBlockPrefix()
{
return 'chill_mainbundle_user_password';
}
}

View File

@@ -0,0 +1,93 @@
<?php
namespace Chill\MainBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Regex;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Chill\MainBundle\Form\UserPasswordType;
class UserType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('username')
->add('email')
;
if ($options['is_creation']) {
$builder->add('plainPassword', RepeatedType::class, array(
'mapped' => false,
'type' => PasswordType::class,
'required' => false,
'options' => array(),
'first_options' => array(
'label' => 'Password'
),
'second_options' => array(
'label' => 'Repeat the password'
),
'invalid_message' => "The password fields must match",
'constraints' => array(
new Length(array(
'min' => 9,
'minMessage' => 'The password must be greater than {{ limit }} characters'
)),
new NotBlank(),
new Regex(array(
'pattern' => "/((?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%!,;:+\"'-\/{}~=µ\(\)£]).{6,})/",
'message' => "The password must contains one letter, one "
. "capitalized letter, one number and one special character "
. "as *[@#$%!,;:+\"'-/{}~=µ()£]). Other characters are allowed."
))
)
));
} else {
$builder->add($builder
->create('enabled', ChoiceType::class, array(
'choices' => array(
'Disabled, the user is not allowed to login' => 0,
'Enabled, the user is active' => 1
),
'expanded' => false,
'multiple' => false,
))
);
}
}
/**
* @param OptionsResolverInterface $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Chill\MainBundle\Entity\User'
));
$resolver
->setDefaults(array('is_creation' => false))
->addAllowedValues('is_creation', array(true, false))
;
}
/**
* @return string
*/
public function getBlockPrefix()
{
return 'chill_mainbundle_user';
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Chill\MainBundle\Form\Utils;
/**
*
*
*/
interface PermissionsGroupFlagProvider
{
/**
* Return an array of flags
*
* @return string[] an array. Keys are ignored.
*/
public function getPermissionsGroupFlags(): array;
}