mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-07-01 14:36:13 +00:00
Merge remote-tracking branch 'ChillCustomFields/sf4' into sf4
This commit is contained in:
commit
5ea4b4efe1
32
src/Bundle/ChillCustomFields/.gitignore
vendored
Normal file
32
src/Bundle/ChillCustomFields/.gitignore
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
/web/bundles/
|
||||
/app/cache/*
|
||||
!/app/cache/dev/security/nonces/index
|
||||
!/app/cache/prod/security/nonces/index
|
||||
/app/logs/*
|
||||
/vendor/
|
||||
/app/config/parameters.ini
|
||||
/app/config/parameters.yml
|
||||
/app/bootstrap*
|
||||
/src/Acme/
|
||||
/output/
|
||||
/web/uploads/images/*
|
||||
!/web/uploads/images/index.html
|
||||
/src/Progracqteur/WikipedaleBundle/DataFixtures/ORM/Files/*
|
||||
.gitignore~
|
||||
*~
|
||||
composer.phar
|
||||
composer.lock
|
||||
/nbproject/private/
|
||||
parameters.yml
|
||||
app/config/parameters.yml
|
||||
Tests/Fixtures/App/app/config/parameters.yml
|
||||
.DS_Store
|
||||
*bower_components
|
||||
bin/*
|
||||
/tmp/*
|
||||
src/Chill/CustomFieldsBundle/vendor/*
|
||||
bootstrap.php.cache
|
||||
#the file created by composer to store creds
|
||||
auth.json
|
||||
Tests/Fixtures/App/app/config/parameters.yml
|
||||
|
68
src/Bundle/ChillCustomFields/.gitlab-ci.yml
Normal file
68
src/Bundle/ChillCustomFields/.gitlab-ci.yml
Normal file
@ -0,0 +1,68 @@
|
||||
.test_definition: &test_definition
|
||||
services:
|
||||
- chill/database:latest
|
||||
|
||||
before_script:
|
||||
- echo "PHP version is $(php --version)"
|
||||
- composer config github-oauth.github.com $GITHUB_TOKEN
|
||||
- if [ $CI_BUILD_REF_NAME = "1.0" ] ; then export COMPOSER_ROOT_VERSION="1.0-dev"; else export COMPOSER_ROOT_VERSION="dev-master"; fi
|
||||
- php -d memory_limit=-1 /usr/local/bin/composer install --no-interaction
|
||||
- cp Resources/test/Fixtures/App/app/config/parameters.gitlab-ci.yml Resources/test/Fixtures/App/app/config/parameters.yml
|
||||
- php Resources/test/Fixtures/App/app/console --env=test cache:warmup
|
||||
- php Resources/test/Fixtures/App/app/console doctrine:migrations:migrate --env=test --no-interaction
|
||||
- php Resources/test/Fixtures/App/app/console doctrine:fixtures:load --env=test --no-interaction
|
||||
|
||||
stages:
|
||||
- deploy
|
||||
- test
|
||||
- build-doc
|
||||
- deploy-doc
|
||||
|
||||
test:php-7.2:
|
||||
stage: test
|
||||
image: chill/ci-image:php-7.2
|
||||
<<: *test_definition
|
||||
script: vendor/bin/phpunit
|
||||
|
||||
deploy-packagist:
|
||||
stage: deploy
|
||||
image: chill/ci-image:php-7.2
|
||||
before_script:
|
||||
# test that PACKAGIST USERNAME and PACKAGIST_TOKEN variable are set
|
||||
- if [ -z ${PACKAGIST_USERNAME+x} ]; then echo "Please set PACKAGIST_USERNAME variable"; exit -1; fi
|
||||
- if [ -z ${PACKAGIST_TOKEN+x} ]; then echo "Please set PACKAGIST_TOKEN variable"; exit -1; fi
|
||||
script:
|
||||
- STATUSCODE=$(curl -XPOST -H'content-type:application/json' "https://packagist.org/api/update-package?username=$PACKAGIST_USERNAME&apiToken=$PACKAGIST_TOKEN" -d"{\"repository\":{\"url\":\"$CI_PROJECT_URL.git\"}}" --silent --output /dev/stderr --write-out "%{http_code}")
|
||||
- if [ $STATUSCODE = "202" ]; then exit 0; else exit $STATUSCODE; fi
|
||||
|
||||
# deploy documentation
|
||||
api-doc-build:
|
||||
stage: build-doc
|
||||
environment: api-doc
|
||||
image: chill/ci-image:php-7.2
|
||||
before_script:
|
||||
- mkdir api-doc
|
||||
script: apigen generate --destination api-doc/$CI_BUILD_REF_NAME/$CI_PROJECT_NAME
|
||||
artifacts:
|
||||
paths:
|
||||
- "api-doc/"
|
||||
name: api
|
||||
expire_in: '2h'
|
||||
only:
|
||||
- master
|
||||
- tags
|
||||
|
||||
api-doc-deploy:
|
||||
stage: deploy-doc
|
||||
image: pallet/swiftclient:latest
|
||||
before_script:
|
||||
# test that CONTAINER_API variable is set
|
||||
- if [ -z ${CONTAINER_API+x} ]; then echo "Please set CONTAINER_API variable"; exit -1; fi
|
||||
# go to api-doc to have and url with PROJECT/BUILD
|
||||
- cd api-doc
|
||||
# upload, and keep files during 1 year
|
||||
script: "swift upload --header \"X-Delete-After: 31536000\" $CONTAINER_API $CI_BUILD_REF_NAME/$CI_PROJECT_NAME"
|
||||
only:
|
||||
- master
|
||||
- tags
|
||||
|
5
src/Bundle/ChillCustomFields/CHANGELOG.md
Normal file
5
src/Bundle/ChillCustomFields/CHANGELOG.md
Normal file
@ -0,0 +1,5 @@
|
||||
Master branch
|
||||
=============
|
||||
|
||||
- fix error on export: error when field definition has changed
|
||||
|
15
src/Bundle/ChillCustomFields/ChillCustomFieldsBundle.php
Normal file
15
src/Bundle/ChillCustomFields/ChillCustomFieldsBundle.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CustomFieldsBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
use Chill\CustomFieldsBundle\DependencyInjection\CustomFieldCompilerPass;
|
||||
|
||||
class ChillCustomFieldsBundle extends Bundle
|
||||
{
|
||||
public function build(\Symfony\Component\DependencyInjection\ContainerBuilder $container)
|
||||
{
|
||||
parent::build($container);
|
||||
$container->addCompilerPass(new CustomFieldCompilerPass());
|
||||
}
|
||||
}
|
@ -0,0 +1,264 @@
|
||||
<?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\CustomFieldsBundle\Command;
|
||||
|
||||
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
use Symfony\Component\Yaml\Parser;
|
||||
use Symfony\Component\Yaml\Exception\ParseException;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
|
||||
/**
|
||||
* Class for the command 'chill:custom_fields:populate_group' that
|
||||
* Create custom fields from a yml file
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
* @author Marc Ducobu <marc.ducobu@champs-libres.coop>
|
||||
*/
|
||||
class CreateFieldsOnGroupCommand extends Command
|
||||
{
|
||||
const ARG_PATH = 'path';
|
||||
const ARG_DELETE = 'delete';
|
||||
|
||||
/**
|
||||
* @var CustomFieldProvider
|
||||
*/
|
||||
private $customFieldProvider;
|
||||
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
private $entityManager;
|
||||
|
||||
/**
|
||||
* @var ValidatorInterface
|
||||
*/
|
||||
private $validator;
|
||||
|
||||
private $availableLanguages;
|
||||
private $customizablesEntities;
|
||||
|
||||
/**
|
||||
* CreateFieldsOnGroupCommand constructor.
|
||||
*
|
||||
* @param CustomFieldProvider $customFieldProvider
|
||||
* @param EntityManager $entityManager
|
||||
* @param ValidatorInterface $validator
|
||||
* @param $availableLanguages
|
||||
* @param $customizablesEntities
|
||||
*/
|
||||
public function __construct(
|
||||
CustomFieldProvider $customFieldProvider,
|
||||
EntityManager $entityManager,
|
||||
ValidatorInterface $validator,
|
||||
$availableLanguages,
|
||||
$customizablesEntities
|
||||
) {
|
||||
$this->customFieldProvider = $customFieldProvider;
|
||||
$this->entityManager = $entityManager;
|
||||
$this->validator = $validator;
|
||||
$this->availableLanguages = $availableLanguages;
|
||||
$this->customizablesEntities = $customizablesEntities;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('chill:custom_fields:populate_group')
|
||||
->setDescription('Create custom fields from a yml file')
|
||||
->addArgument(self::ARG_PATH, InputOption::VALUE_REQUIRED,
|
||||
'Path to description file')
|
||||
->addOption(self::ARG_DELETE, null, InputOption::VALUE_NONE,
|
||||
'If set, delete existing fields');
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the existing custom fields for a given customFieldGroup
|
||||
*
|
||||
* @param CustomFieldsGroup $customFieldsGroup : The custom field group
|
||||
*/
|
||||
protected function deleteFieldsForCFGroup($customFieldsGroup)
|
||||
{
|
||||
$em = $this->entityManager;
|
||||
|
||||
foreach ($customFieldsGroup->getCustomFields() as $field) {
|
||||
$em->remove($field);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return int|null|void
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$helper = $this->getHelperSet()->get('question');
|
||||
|
||||
$em = $this->entityManager;
|
||||
|
||||
$customFieldsGroups = $em
|
||||
->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')
|
||||
->findAll();
|
||||
|
||||
if (count($customFieldsGroups) === 0) {
|
||||
$output->writeln('<error>There aren\'t any CustomFieldsGroup recorded'
|
||||
. ' Please create at least one.</error>');
|
||||
}
|
||||
|
||||
$table = new Table($output);
|
||||
$table
|
||||
->setHeaders(array_merge(
|
||||
['id', 'entity'],
|
||||
$this->availableLanguages
|
||||
))
|
||||
->setRows($this->_prepareRows($customFieldsGroups))
|
||||
->render()
|
||||
;
|
||||
|
||||
$question = new Question(
|
||||
"Enter the customfieldGroup's id on which the custom fields should be added: ");
|
||||
$question->setNormalizer(
|
||||
function($answer) use ($customFieldsGroups) {
|
||||
foreach ($customFieldsGroups as $customFieldsGroup) {
|
||||
if ($answer == $customFieldsGroup->getId()) {
|
||||
return $customFieldsGroup;
|
||||
}
|
||||
}
|
||||
throw new \RunTimeException('The id does not match an existing '
|
||||
. 'CustomFieldsGroup');
|
||||
}
|
||||
);
|
||||
$customFieldsGroup = $helper->ask($input, $output, $question);
|
||||
|
||||
|
||||
if ($input->getOption(self::ARG_DELETE)) {
|
||||
$this->deleteFieldsForCFGroup($customFieldsGroup);
|
||||
}
|
||||
|
||||
$fieldsInput = $this->_parse($input->getArgument(self::ARG_PATH),
|
||||
$output);
|
||||
|
||||
$fields = $this->_addFields($customFieldsGroup, $fieldsInput, $output);
|
||||
}
|
||||
|
||||
private function _prepareRows ($customFieldsGroups)
|
||||
{
|
||||
$rows = array();
|
||||
$languages = $this->availableLanguages;
|
||||
//gather entitites and create an array to access them easily
|
||||
$customizableEntities = array();
|
||||
foreach ($this->customizablesEntities as $entry) {
|
||||
$customizableEntities[$entry['class']] = $entry['name'];
|
||||
}
|
||||
|
||||
array_walk($customFieldsGroups,
|
||||
function(CustomFieldsGroup $customFieldGroup, $key)
|
||||
use ($languages, &$rows, $customizableEntities) {
|
||||
//set id and entity
|
||||
$row = array(
|
||||
$customFieldGroup->getId(),
|
||||
$customizableEntities[$customFieldGroup->getEntity()]
|
||||
);
|
||||
|
||||
foreach ($languages as $lang) {
|
||||
//todo replace with service to find lang when available
|
||||
$row[] = (isset($customFieldGroup->getName()[$lang])) ?
|
||||
$customFieldGroup->getName()[$lang] :
|
||||
'Not available in this language';
|
||||
}
|
||||
$rows[] = $row;
|
||||
}
|
||||
);
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
private function _parse($path, OutputInterface $output)
|
||||
{
|
||||
$parser = new Parser();
|
||||
|
||||
if (!file_exists($path)) {
|
||||
throw new \RunTimeException("file does not exist");
|
||||
}
|
||||
|
||||
try {
|
||||
$values = $parser->parse(file_get_contents($path));
|
||||
} catch (ParseException $ex) {
|
||||
throw new \RunTimeException("The yaml file is not valid", 0, $ex);
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
private function _addFields(CustomFieldsGroup $group, $values, OutputInterface $output)
|
||||
{
|
||||
|
||||
$em = $this->entityManager;
|
||||
|
||||
$languages = $this->availableLanguages;
|
||||
|
||||
foreach($values['fields'] as $slug => $field) {
|
||||
//check the cf type exists
|
||||
$cfType = $this->customFieldProvider->getCustomFieldByType($field['type']);
|
||||
if ($cfType === NULL) {
|
||||
throw new \RunTimeException('the type '.$field['type'].' '
|
||||
. 'does not exists');
|
||||
}
|
||||
|
||||
$cf = new CustomField();
|
||||
$cf->setSlug($slug)
|
||||
->setName($field['name'])
|
||||
->setOptions(isset($field['options']) ? $field['options'] : array() )
|
||||
->setOrdering($field['ordering'])
|
||||
->setType($field['type'])
|
||||
->setCustomFieldsGroup($group);
|
||||
|
||||
//add to table
|
||||
$names = array();
|
||||
foreach ($languages as $lang) {
|
||||
//todo replace with service to find lang when available
|
||||
$names[] = (isset($cf->getName()[$lang])) ?
|
||||
$cf->getName()[$lang] :
|
||||
'Not available in this language';
|
||||
}
|
||||
|
||||
if ($this->validator->validate($cf)) {
|
||||
$em->persist($cf);
|
||||
$output->writeln("<info>Adding Custom Field of type "
|
||||
.$cf->getType()."\t with slug ".$cf->getSlug().
|
||||
"\t and names : ".implode($names, ', ')."</info>");
|
||||
} else {
|
||||
throw new \RunTimeException("Error in field ".$slug);
|
||||
}
|
||||
}
|
||||
|
||||
$em->flush();
|
||||
}
|
||||
}
|
38
src/Bundle/ChillCustomFields/Controller/AdminController.php
Normal file
38
src/Bundle/ChillCustomFields/Controller/AdminController.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?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\CustomFieldsBundle\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Class AdminController
|
||||
* Controller for the custom fields configuration section (in admin section)
|
||||
*
|
||||
* @package Chill\CustomFieldsBundle\Controller
|
||||
*/
|
||||
class AdminController extends AbstractController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
return $this->render('ChillCustomFieldsBundle:Admin:layout.html.twig');
|
||||
}
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
|
||||
use Chill\CustomFieldsBundle\Form\CustomFieldType;
|
||||
|
||||
|
||||
/**
|
||||
* Class CustomFieldController
|
||||
*
|
||||
* @package Chill\CustomFieldsBundle\Controller
|
||||
*/
|
||||
class CustomFieldController extends AbstractController
|
||||
{
|
||||
|
||||
/**
|
||||
* Creates a new CustomField entity.
|
||||
*
|
||||
*/
|
||||
public function createAction(Request $request)
|
||||
{
|
||||
$entity = new CustomField();
|
||||
$form = $this->createCreateForm($entity, $request->query->get('type', null));
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isValid()) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->persist($entity);
|
||||
$em->flush();
|
||||
|
||||
$this->addFlash('success', $this->get('translator')
|
||||
->trans('The custom field has been created'));
|
||||
|
||||
return $this->redirect($this->generateUrl('customfieldsgroup_show',
|
||||
array('id' => $entity->getCustomFieldsGroup()->getId())));
|
||||
}
|
||||
|
||||
$this->addFlash('error', $this->get('translator')
|
||||
->trans("The custom field form contains errors"));
|
||||
|
||||
return $this->render('ChillCustomFieldsBundle:CustomField:new.html.twig', array(
|
||||
'entity' => $entity,
|
||||
'form' => $form->createView(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a form to create a CustomField entity.
|
||||
*
|
||||
* @param CustomField $entity The entity
|
||||
* @param string
|
||||
* @return \Symfony\Component\Form\Form The form
|
||||
*/
|
||||
private function createCreateForm(CustomField $entity, $type)
|
||||
{
|
||||
$form = $this->createForm(CustomFieldType::class, $entity, array(
|
||||
'action' => $this->generateUrl('customfield_create',
|
||||
array('type' => $type)),
|
||||
'method' => 'POST',
|
||||
'type' => $type,
|
||||
'group_widget' => ($entity->getCustomFieldsGroup()) ? 'hidden' :'entity'
|
||||
));
|
||||
|
||||
$form->add('submit', SubmitType::class, array('label' => 'Create'));
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a form to create a new CustomField entity.
|
||||
*
|
||||
*/
|
||||
public function newAction(Request $request)
|
||||
{
|
||||
$entity = new CustomField();
|
||||
|
||||
//add the custom field group if defined in URL
|
||||
$cfGroupId = $request->query->get('customFieldsGroup', null);
|
||||
|
||||
if ($cfGroupId !== null) {
|
||||
$cfGroup = $this->getDoctrine()->getManager()
|
||||
->getRepository(CustomFieldsGroup::class)
|
||||
->find($cfGroupId);
|
||||
if (!$cfGroup) {
|
||||
throw $this->createNotFoundException('CustomFieldsGroup with id '
|
||||
. $cfGroupId.' is not found !');
|
||||
}
|
||||
$entity->setCustomFieldsGroup($cfGroup);
|
||||
}
|
||||
|
||||
$form = $this->createCreateForm($entity, $request->query->get('type'));
|
||||
|
||||
return $this->render('ChillCustomFieldsBundle:CustomField:new.html.twig', array(
|
||||
'entity' => $entity,
|
||||
'form' => $form->createView(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and displays a CustomField entity.
|
||||
*
|
||||
* @deprecated is not used since there is no link to show action
|
||||
*/
|
||||
public function showAction($id)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$entity = $em->getRepository(CustomField::class)->find($id);
|
||||
|
||||
if (!$entity) {
|
||||
throw $this->createNotFoundException('Unable to find CustomField entity.');
|
||||
}
|
||||
|
||||
return $this->render('ChillCustomFieldsBundle:CustomField:show.html.twig', array(
|
||||
'entity' => $entity, ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a form to edit an existing CustomField entity.
|
||||
*
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$entity = $em->getRepository(CustomField::class)->find($id);
|
||||
|
||||
if (!$entity) {
|
||||
throw $this->createNotFoundException('Unable to find CustomField entity.');
|
||||
}
|
||||
|
||||
$editForm = $this->createEditForm($entity, $entity->getType());
|
||||
|
||||
return $this->render('ChillCustomFieldsBundle:CustomField:edit.html.twig', array(
|
||||
'entity' => $entity,
|
||||
'edit_form' => $editForm->createView(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a form to edit a CustomField entity.
|
||||
*
|
||||
* @param CustomField $entity The entity
|
||||
*
|
||||
* @return \Symfony\Component\Form\Form The form
|
||||
*/
|
||||
private function createEditForm(CustomField $entity, $type)
|
||||
{
|
||||
$form = $this->createForm(CustomFieldType::class, $entity, array(
|
||||
'action' => $this->generateUrl('customfield_update', array('id' => $entity->getId())),
|
||||
'method' => 'PUT',
|
||||
'type' => $type,
|
||||
'group_widget' => 'hidden'
|
||||
));
|
||||
|
||||
$form->add('submit', SubmitType::class, array('label' => 'Update'));
|
||||
|
||||
return $form;
|
||||
}
|
||||
/**
|
||||
* Edits an existing CustomField entity.
|
||||
*
|
||||
*/
|
||||
public function updateAction(Request $request, $id)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$entity = $em->getRepository('ChillCustomFieldsBundle:CustomField')->find($id);
|
||||
|
||||
if (!$entity) {
|
||||
throw $this->createNotFoundException('Unable to find CustomField entity.');
|
||||
}
|
||||
|
||||
$editForm = $this->createEditForm($entity, $entity->getType());
|
||||
$editForm->handleRequest($request);
|
||||
|
||||
if ($editForm->isValid()) {
|
||||
$em->flush();
|
||||
|
||||
$this->addFlash('success', $this->get('translator')
|
||||
->trans("The custom field has been updated"));
|
||||
|
||||
return $this->redirect($this->generateUrl('customfield_edit', array('id' => $id)));
|
||||
}
|
||||
|
||||
$this->addFlash('error', $this->get('translator')
|
||||
->trans("The custom field form contains errors"));
|
||||
|
||||
return $this->render('ChillCustomFieldsBundle:CustomField:edit.html.twig', array(
|
||||
'entity' => $entity,
|
||||
'edit_form' => $editForm->createView(),
|
||||
));
|
||||
}
|
||||
}
|
@ -0,0 +1,429 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Controller;
|
||||
|
||||
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Doctrine\ORM\Query;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Chill\CustomFieldsBundle\Form\DataTransformer\CustomFieldsGroupToIdTransformer;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomFieldsDefaultGroup;
|
||||
use Chill\CustomFieldsBundle\Form\CustomFieldsGroupType;
|
||||
use Chill\CustomFieldsBundle\Form\CustomFieldType;
|
||||
use Chill\CustomFieldsBundle\Form\Type\CustomFieldType as FormTypeCustomField;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* Class CustomFieldsGroupController
|
||||
*
|
||||
* @package Chill\CustomFieldsBundle\Controller
|
||||
*/
|
||||
class CustomFieldsGroupController extends AbstractController
|
||||
{
|
||||
|
||||
/**
|
||||
* @var CustomFieldProvider
|
||||
*/
|
||||
private $customfieldProvider;
|
||||
|
||||
/**
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
private $translator;
|
||||
|
||||
/**
|
||||
* CustomFieldsGroupController constructor.
|
||||
*
|
||||
* @param CustomFieldProvider $customFieldProvider
|
||||
* @param TranslatorInterface $translator
|
||||
*/
|
||||
public function __construct(
|
||||
CustomFieldProvider $customFieldProvider,
|
||||
TranslatorInterface $translator
|
||||
) {
|
||||
$this->customfieldProvider = $customFieldProvider;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all CustomFieldsGroup entities.
|
||||
*
|
||||
*/
|
||||
public function indexAction()
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$cfGroups = $em->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')->findAll();
|
||||
$defaultGroups = $this->getDefaultGroupsId();
|
||||
|
||||
$makeDefaultFormViews = array();
|
||||
foreach ($cfGroups as $group) {
|
||||
if (!in_array($group->getId(), $defaultGroups)){
|
||||
$makeDefaultFormViews[$group->getId()] = $this->createMakeDefaultForm($group)->createView();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('ChillCustomFieldsBundle:CustomFieldsGroup:index.html.twig', array(
|
||||
'entities' => $cfGroups,
|
||||
'default_groups' => $defaultGroups,
|
||||
'make_default_forms' => $makeDefaultFormViews
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of CustomFieldsGroupId which are marked as default
|
||||
* for their entity
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
private function getDefaultGroupsId()
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$customFieldsGroupIds = $em->createQuery('SELECT g.id FROM '
|
||||
. 'ChillCustomFieldsBundle:CustomFieldsDefaultGroup d '
|
||||
. 'JOIN d.customFieldsGroup g')
|
||||
->getResult(Query::HYDRATE_SCALAR);
|
||||
|
||||
$result = array();
|
||||
foreach ($customFieldsGroupIds as $row) {
|
||||
$result[] = $row['id'];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* create a form to make the group default
|
||||
*
|
||||
* @param CustomFieldsGroup $group
|
||||
* @return \Symfony\Component\Form\Form
|
||||
*/
|
||||
private function createMakeDefaultForm(CustomFieldsGroup $group = null)
|
||||
{
|
||||
return $this->createFormBuilder($group, array(
|
||||
'method' => 'POST',
|
||||
'action' => $this->generateUrl('customfieldsgroup_makedefault')
|
||||
))
|
||||
->add('id', HiddenType::class)
|
||||
->add('submit', SubmitType::class, array('label' => 'Make default'))
|
||||
->getForm();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new CustomFieldsGroup entity.
|
||||
*
|
||||
*/
|
||||
public function createAction(Request $request)
|
||||
{
|
||||
$entity = new CustomFieldsGroup();
|
||||
$form = $this->createCreateForm($entity);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isValid()) {
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->persist($entity);
|
||||
$em->flush();
|
||||
|
||||
$this->addFlash('success', $this->translator
|
||||
->trans("The custom fields group has been created"));
|
||||
|
||||
return $this->redirect($this->generateUrl('customfieldsgroup_show', array('id' => $entity->getId())));
|
||||
}
|
||||
|
||||
$this->addFlash('error', $this->translator
|
||||
->trans("The custom fields group form contains errors"));
|
||||
|
||||
return $this->render('ChillCustomFieldsBundle:CustomFieldsGroup:new.html.twig', array(
|
||||
'entity' => $entity,
|
||||
'form' => $form->createView(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a form to create a CustomFieldsGroup entity.
|
||||
*
|
||||
* @param CustomFieldsGroup $entity The entity
|
||||
*
|
||||
* @return \Symfony\Component\Form\Form The form
|
||||
*/
|
||||
private function createCreateForm(CustomFieldsGroup $entity)
|
||||
{
|
||||
$form = $this->createForm(CustomFieldsGroupType::class, $entity, array(
|
||||
'action' => $this->generateUrl('customfieldsgroup_create'),
|
||||
'method' => 'POST',
|
||||
));
|
||||
|
||||
$form->add('submit', SubmitType::class, array('label' => 'Create'));
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a form to create a new CustomFieldsGroup entity.
|
||||
*
|
||||
*/
|
||||
public function newAction()
|
||||
{
|
||||
$entity = new CustomFieldsGroup();
|
||||
$form = $this->createCreateForm($entity);
|
||||
|
||||
return $this->render('ChillCustomFieldsBundle:CustomFieldsGroup:new.html.twig', array(
|
||||
'entity' => $entity,
|
||||
'form' => $form->createView(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and displays a CustomFieldsGroup entity.
|
||||
*
|
||||
*/
|
||||
public function showAction($id)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$entity = $em->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')->find($id);
|
||||
|
||||
if (!$entity) {
|
||||
throw $this->createNotFoundException('Unable to find CustomFieldsGroup entity.');
|
||||
}
|
||||
|
||||
$options = $this->getOptionsAvailable($entity->getEntity());
|
||||
|
||||
return $this->render('ChillCustomFieldsBundle:CustomFieldsGroup:show.html.twig', array(
|
||||
'entity' => $entity,
|
||||
'create_field_form' => $this->createCreateFieldForm($entity)->createView(),
|
||||
'options' => $options
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of available key option for custom fields group
|
||||
* on the given entity
|
||||
*
|
||||
* @param string $entity the entity to filter
|
||||
*/
|
||||
private function getOptionsAvailable($entity)
|
||||
{
|
||||
$options = $this->getParameter('chill_custom_fields.'
|
||||
. 'customizables_entities');
|
||||
|
||||
foreach($options as $key => $definition) {
|
||||
if ($definition['class'] == $entity) {
|
||||
foreach ($definition['options'] as $key => $value) {
|
||||
yield $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
// [$entity->getEntity()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a form to edit an existing CustomFieldsGroup entity.
|
||||
*
|
||||
*/
|
||||
public function editAction($id)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$entity = $em->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')->find($id);
|
||||
|
||||
if (!$entity) {
|
||||
throw $this->createNotFoundException('Unable to find CustomFieldsGroup entity.');
|
||||
}
|
||||
|
||||
$editForm = $this->createEditForm($entity);
|
||||
|
||||
return $this->render('ChillCustomFieldsBundle:CustomFieldsGroup:edit.html.twig', array(
|
||||
'entity' => $entity,
|
||||
'edit_form' => $editForm->createView(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a form to edit a CustomFieldsGroup entity.
|
||||
*
|
||||
* @param CustomFieldsGroup $entity The entity
|
||||
*
|
||||
* @return \Symfony\Component\Form\Form The form
|
||||
*/
|
||||
private function createEditForm(CustomFieldsGroup $entity)
|
||||
{
|
||||
$form = $this->createForm(CustomFieldsGroupType::class, $entity, array(
|
||||
'action' => $this->generateUrl('customfieldsgroup_update', array('id' => $entity->getId())),
|
||||
'method' => 'PUT',
|
||||
));
|
||||
$form->add('submit', SubmitType::class, array('label' => 'Update'));
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
private function createCreateFieldForm(CustomFieldsGroup $customFieldsGroup)
|
||||
{
|
||||
|
||||
$fieldChoices = array();
|
||||
foreach ($this->customfieldProvider->getAllFields()
|
||||
as $key => $customType) {
|
||||
$fieldChoices[$key] = $customType->getName();
|
||||
}
|
||||
|
||||
$customfield = (new CustomField())
|
||||
->setCustomFieldsGroup($customFieldsGroup);
|
||||
|
||||
$builder = $this->get('form.factory')
|
||||
->createNamedBuilder(null, FormType::class, $customfield, array(
|
||||
'method' => 'GET',
|
||||
'action' => $this->generateUrl('customfield_new'),
|
||||
'csrf_protection' => false
|
||||
))
|
||||
->add('type', ChoiceType::class, array(
|
||||
'choices' => array_combine(array_values($fieldChoices),array_keys($fieldChoices)),
|
||||
))
|
||||
->add('customFieldsGroup', HiddenType::class)
|
||||
->add('submit', SubmitType::class);
|
||||
$builder->get('customFieldsGroup')
|
||||
->addViewTransformer(new CustomFieldsGroupToIdTransformer(
|
||||
$this->getDoctrine()->getManager()));
|
||||
|
||||
return $builder->getForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits an existing CustomFieldsGroup entity.
|
||||
*
|
||||
*/
|
||||
public function updateAction(Request $request, $id)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$entity = $em->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')->find($id);
|
||||
|
||||
if (!$entity) {
|
||||
throw $this->createNotFoundException('Unable to find CustomFieldsGroup entity.');
|
||||
}
|
||||
|
||||
$editForm = $this->createEditForm($entity);
|
||||
$editForm->handleRequest($request);
|
||||
|
||||
if ($editForm->isValid()) {
|
||||
$em->flush();
|
||||
|
||||
$this->addFlash('success', $this->translator
|
||||
->trans("The custom fields group has been updated"));
|
||||
|
||||
return $this->redirect($this->generateUrl('customfieldsgroup_edit', array('id' => $id)));
|
||||
}
|
||||
|
||||
$this->addFlash('error', $this->translator
|
||||
->trans("The custom fields group form contains errors"));
|
||||
|
||||
return $this->render('ChillCustomFieldsBundle:CustomFieldsGroup:edit.html.twig', array(
|
||||
'entity' => $entity,
|
||||
'edit_form' => $editForm->createView(),
|
||||
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the CustomField Group with id $cFGroupId as default
|
||||
*/
|
||||
public function makeDefaultAction(Request $request)
|
||||
{
|
||||
|
||||
$form = $this->createMakeDefaultForm(null);
|
||||
$form->handleRequest($request);
|
||||
|
||||
$cFGroupId = $form->get('id')->getData();
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$cFGroup = $em->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')->findOneById($cFGroupId);
|
||||
|
||||
if(!$cFGroup) {
|
||||
throw $this
|
||||
->createNotFoundException("customFieldsGroup not found with "
|
||||
. "id $cFGroupId");
|
||||
}
|
||||
|
||||
$cFDefaultGroup = $em->getRepository('ChillCustomFieldsBundle:CustomFieldsDefaultGroup')
|
||||
->findOneByEntity($cFGroup->getEntity());
|
||||
|
||||
if($cFDefaultGroup) {
|
||||
$em->remove($cFDefaultGroup);
|
||||
$em->flush(); /*this is necessary, if not doctrine
|
||||
* will not remove old entity before adding a new one,
|
||||
* and this leads to violation constraint of unique entity
|
||||
* in postgresql
|
||||
*/
|
||||
}
|
||||
|
||||
$newCFDefaultGroup = new CustomFieldsDefaultGroup();
|
||||
$newCFDefaultGroup->setCustomFieldsGroup($cFGroup);
|
||||
$newCFDefaultGroup->setEntity($cFGroup->getEntity());
|
||||
|
||||
$em->persist($newCFDefaultGroup);
|
||||
$em->flush();
|
||||
|
||||
$this->addFlash('success', $this->translator
|
||||
->trans("The default custom fields group has been changed"));
|
||||
|
||||
return $this->redirect($this->generateUrl('customfieldsgroup'));
|
||||
}
|
||||
|
||||
/**
|
||||
* This function render the customFieldsGroup as a form.
|
||||
*
|
||||
* This function is for testing purpose !
|
||||
*
|
||||
* The route which call this action is not in Resources/config/routing.yml,
|
||||
* but in Tests/Fixtures/App/app/config.yml
|
||||
*
|
||||
* @param int $id
|
||||
*/
|
||||
public function renderFormAction($id, Request $request)
|
||||
{
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
|
||||
$entity = $em->getRepository('ChillCustomFieldsBundle:CustomFieldsGroup')->find($id);
|
||||
|
||||
if (!$entity) {
|
||||
throw $this->createNotFoundException('Unable to find CustomFieldsGroups entity.');
|
||||
}
|
||||
|
||||
$form = $this->createForm(FormTypeCustomField::class, null, array('group' => $entity));
|
||||
$form->add('submit_dump', SubmitType::class, array('label' => 'POST AND DUMP'));
|
||||
$form->add('submit_render', SubmitType::class, array('label' => 'POST AND RENDER'));
|
||||
$form->handleRequest($request);
|
||||
|
||||
$this->get('twig.loader')
|
||||
->addPath(__DIR__.'/../Tests/Fixtures/App/app/Resources/views/',
|
||||
$namespace = 'test');
|
||||
|
||||
if ($form->isSubmitted()) {
|
||||
if ($form->get('submit_render')->isClicked()) {
|
||||
return $this->render('ChillCustomFieldsBundle:CustomFieldsGroup:render_for_test.html.twig', array(
|
||||
'fields' => $form->getData(),
|
||||
'customFieldsGroup' => $entity
|
||||
));
|
||||
}
|
||||
|
||||
//dump($form->getData());
|
||||
//dump(json_enccode($form->getData()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $this
|
||||
->render('@test/CustomField/simple_form_render.html.twig', array(
|
||||
'form' => $form->createView()
|
||||
));
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?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\CustomFieldsBundle\CustomFields;
|
||||
|
||||
use Chill\CustomFieldsBundle\CustomFields\CustomFieldInterface;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
abstract class AbstractCustomField implements CustomFieldInterface
|
||||
{
|
||||
public function isEmptyValue($value, CustomField $customField)
|
||||
{
|
||||
return (empty($value) and $value !== FALSE);
|
||||
}
|
||||
|
||||
}
|
413
src/Bundle/ChillCustomFields/CustomFields/CustomFieldChoice.php
Normal file
413
src/Bundle/ChillCustomFields/CustomFields/CustomFieldChoice.php
Normal file
@ -0,0 +1,413 @@
|
||||
<?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\CustomFieldsBundle\CustomFields;
|
||||
|
||||
use Chill\CustomFieldsBundle\Form\Type\ChoicesListType;
|
||||
use Chill\CustomFieldsBundle\Form\Type\ChoicesType;
|
||||
use Chill\CustomFieldsBundle\Form\Type\ChoiceWithOtherType;
|
||||
use Chill\CustomFieldsBundle\CustomFields\CustomFieldInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Chill\CustomFieldsBundle\Form\DataTransformer\CustomFieldDataTransformer;
|
||||
use Symfony\Bridge\Twig\TwigEngine;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
* @author Marc Ducobu <marc@champs-libes.coop>
|
||||
*/
|
||||
class CustomFieldChoice extends AbstractCustomField
|
||||
{
|
||||
const ALLOW_OTHER = 'other';
|
||||
const OTHER_VALUE_LABEL = 'otherValueLabel';
|
||||
const MULTIPLE = 'multiple';
|
||||
const EXPANDED = 'expanded';
|
||||
const CHOICES = 'choices';
|
||||
|
||||
private $defaultLocales;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TwigEngine
|
||||
*/
|
||||
private $templating;
|
||||
|
||||
/**
|
||||
* @var TranslatableStringHelper Helper that find the string in current locale from an array of translation
|
||||
*/
|
||||
private $translatableStringHelper;
|
||||
|
||||
/**
|
||||
* CustomFieldChoice constructor.
|
||||
*
|
||||
* @param TranslatorInterface $translator
|
||||
* @param TwigEngine $templating
|
||||
* @param TranslatableStringHelper $translatableStringHelper
|
||||
*/
|
||||
public function __construct(
|
||||
TranslatorInterface $translator,
|
||||
TwigEngine $templating,
|
||||
TranslatableStringHelper $translatableStringHelper)
|
||||
{
|
||||
$this->defaultLocales = $translator->getFallbackLocales();
|
||||
$this->templating = $templating;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, CustomField $customField)
|
||||
{
|
||||
//prepare choices
|
||||
$choices = array();
|
||||
$customFieldOptions = $customField->getOptions();
|
||||
|
||||
foreach($customFieldOptions[self::CHOICES] as $persistedChoices) {
|
||||
if ($persistedChoices['active']){
|
||||
$choices[$persistedChoices['slug']] = $this->translatableStringHelper->localize($persistedChoices['name']);
|
||||
}
|
||||
}
|
||||
|
||||
//prepare $options
|
||||
$options = array(
|
||||
'multiple' => $customFieldOptions[self::MULTIPLE],
|
||||
'choices' => array_combine(array_values($choices),array_keys($choices)),
|
||||
'required' => $customField->isRequired(),
|
||||
'label' => $this->translatableStringHelper->localize($customField->getName())
|
||||
);
|
||||
|
||||
//if allow_other = true
|
||||
if ($customFieldOptions[self::ALLOW_OTHER] == true) {
|
||||
$otherValueLabel = null;
|
||||
if(array_key_exists(self::OTHER_VALUE_LABEL, $customFieldOptions)) {
|
||||
$otherValueLabel = $this->translatableStringHelper->localize(
|
||||
$customFieldOptions[self::OTHER_VALUE_LABEL]
|
||||
);
|
||||
}
|
||||
|
||||
$builder->add(
|
||||
$builder
|
||||
->create(
|
||||
$customField->getSlug(),
|
||||
ChoiceWithOtherType::class,
|
||||
$options,
|
||||
array('other_value_label'=> $otherValueLabel)
|
||||
)
|
||||
->addModelTransformer(new CustomFieldDataTransformer($this, $customField)));
|
||||
|
||||
} else { //if allow_other = false
|
||||
//we add the 'expanded' to options
|
||||
$options['expanded'] = $customFieldOptions[self::EXPANDED];
|
||||
|
||||
$builder->add(
|
||||
$builder->create($customField->getSlug(), ChoiceType::class, $options)
|
||||
->addModelTransformer(new CustomFieldDataTransformer($this, $customField))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function buildOptionsForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$builder
|
||||
->add(self::MULTIPLE, ChoiceType::class, array(
|
||||
'expanded' => true,
|
||||
'multiple' => false,
|
||||
'choices' => array(
|
||||
'Multiple' => '1',
|
||||
'Unique' => '0'),
|
||||
'empty_data' => '0',
|
||||
'label' => 'Multiplicity'
|
||||
))
|
||||
->add(self::EXPANDED, ChoiceType::class, array(
|
||||
'expanded' => true,
|
||||
'multiple' => false,
|
||||
'choices' => array(
|
||||
'Expanded' => '1',
|
||||
'Non expanded' => '0'),
|
||||
'empty_data' => '0',
|
||||
'label' => 'Choice display'
|
||||
))
|
||||
->add(self::ALLOW_OTHER, ChoiceType::class, array(
|
||||
'label' => 'Allow other',
|
||||
'choices' => array(
|
||||
'No' => '0',
|
||||
'Yes' => '1'),
|
||||
'empty_data' => '0',
|
||||
'expanded' => true,
|
||||
'multiple' => false
|
||||
))
|
||||
->add(self::OTHER_VALUE_LABEL, TranslatableStringFormType::class, array(
|
||||
'label' => 'Other value label (empty if use by default)'))
|
||||
->add(self::CHOICES, ChoicesType::class, array(
|
||||
'entry_type' => ChoicesListType::class,
|
||||
'allow_add' => true
|
||||
));
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
||||
public function deserialize($serialized, CustomField $customField)
|
||||
{
|
||||
// we always have to adapt to what the current data should be
|
||||
$options = $customField->getOptions();
|
||||
|
||||
if ($options[self::MULTIPLE]) {
|
||||
return $this->deserializeToMultiple($serialized, $options[self::ALLOW_OTHER]);
|
||||
} else {
|
||||
return $this->deserializeToUnique($serialized, $options[self::ALLOW_OTHER]);
|
||||
}
|
||||
return $serialized;
|
||||
}
|
||||
|
||||
private function deserializeToUnique($serialized, $allowOther)
|
||||
{
|
||||
$value = $this->guessValue($serialized);
|
||||
|
||||
// set in a single value. We must have a single string
|
||||
$fixedValue = is_array($value) ?
|
||||
// check if the array has an element, if not replace by empty string
|
||||
count($value) > 0 ? end($value) : ''
|
||||
:
|
||||
$value;
|
||||
|
||||
if ($allowOther) {
|
||||
return $this->deserializeWithAllowOther($serialized, $fixedValue);
|
||||
} else {
|
||||
return $fixedValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* deserialized the data from the database to a multiple
|
||||
* field
|
||||
*
|
||||
* @param mixed $serialized
|
||||
* @param boolean $allowOther
|
||||
*/
|
||||
private function deserializeToMultiple($serialized, $allowOther)
|
||||
{
|
||||
$value = $this->guessValue($serialized);
|
||||
|
||||
// set in an array : we want a multiple
|
||||
$fixedValue = is_array($value) ? $value : array($value);
|
||||
|
||||
if ($allowOther) {
|
||||
return $this->deserializeWithAllowOther($serialized, $fixedValue);
|
||||
} else {
|
||||
return $fixedValue;
|
||||
}
|
||||
}
|
||||
|
||||
private function deserializeWithAllowOther($serialized, $value)
|
||||
{
|
||||
$existingOther = isset($serialized['_other']) ? $serialized['_other'] : '';
|
||||
|
||||
return array(
|
||||
'_other' => $existingOther,
|
||||
'_choices' => $value
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Guess the value from the representation of it.
|
||||
*
|
||||
* If the value had an 'allow_other' = true option, the returned value
|
||||
* **is not** the content of the _other field, but the `_other` string.
|
||||
*
|
||||
* @param array|string $value
|
||||
* @return mixed
|
||||
* @throws \LogicException if the case is not covered by this
|
||||
*/
|
||||
private function guessValue($value)
|
||||
{
|
||||
if ($value === NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!is_array($value)) {
|
||||
return $value;
|
||||
} else {
|
||||
// we have a field with "allow other"
|
||||
if (array_key_exists('_choices', $value)) {
|
||||
return $value['_choices'];
|
||||
} else {
|
||||
// we have a field with "multiple"
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
throw \LogicException("This case is not expected.");
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'Choices';
|
||||
}
|
||||
|
||||
public function isEmptyValue($value, CustomField $customField)
|
||||
{
|
||||
if ($value === NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// if multiple choice OR multiple/single choice with other
|
||||
if (is_array($value))
|
||||
{
|
||||
// if allow other
|
||||
if (array_key_exists('_choices', $value)) {
|
||||
if ($value['_choices'] === NULL) {
|
||||
return true;
|
||||
}
|
||||
return empty($value['_choices']);
|
||||
} else { // we do not have 'allow other'
|
||||
if (count($value) === 1){
|
||||
return empty($value[0]);
|
||||
} else {
|
||||
return empty($value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return empty($value);
|
||||
}
|
||||
|
||||
throw \LogicException("This case is not expected.");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @internal this function is able to receive data whichever is the value of "other", "multiple"
|
||||
* @param mixed $value
|
||||
* @param CustomField $customField
|
||||
* @return string html representation
|
||||
*/
|
||||
public function render($value, CustomField $customField, $documentType = 'html')
|
||||
{
|
||||
//extract the data. They are under a _choice key if they are stored with allow_other
|
||||
$data = (isset($value['_choices'])) ? $value['_choices'] : $value;
|
||||
$selected = (is_array($data)) ? $data : array($data);
|
||||
$choices = $customField->getOptions()[self::CHOICES];
|
||||
|
||||
if (in_array('_other', $selected)){
|
||||
$choices[] = array('name' => $value['_other'], 'slug' => '_other');
|
||||
}
|
||||
|
||||
$template = 'ChillCustomFieldsBundle:CustomFieldsRendering:choice.html.twig';
|
||||
if($documentType == 'csv') {
|
||||
$template = 'ChillCustomFieldsBundle:CustomFieldsRendering:choice.csv.twig';
|
||||
}
|
||||
|
||||
return $this->templating
|
||||
->render($template,
|
||||
array(
|
||||
'choices' => $choices,
|
||||
'selected' => $selected,
|
||||
'multiple' => $customField->getOptions()[self::MULTIPLE],
|
||||
'expanded' => $customField->getOptions()[self::EXPANDED],
|
||||
'locales' => $this->defaultLocales
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function serialize($value, CustomField $customField)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getChoices(CustomField $cf)
|
||||
{
|
||||
if ($cf->getOptions()[self::MULTIPLE]) {
|
||||
$choices = array();
|
||||
|
||||
foreach ($cf->getOptions()[self::CHOICES] as $choice) {
|
||||
if ($choices['active'] === false) {
|
||||
continue;
|
||||
}
|
||||
$choices[$choice["slug"]] = $this->translatableStringHelper
|
||||
->localize($choice["name"]);
|
||||
}
|
||||
|
||||
if ($this->allowOtherChoice($cf)) {
|
||||
$labels = $cf->getOptions()[self::OTHER_VALUE_LABEL];
|
||||
if (!is_array($labels) or count($labels) === 0) {
|
||||
$labels['back'] = 'other value';
|
||||
}
|
||||
$choices['_other'] = $this->translatableStringHelper
|
||||
->localize($labels);
|
||||
}
|
||||
|
||||
return $choices;
|
||||
} else {
|
||||
return [
|
||||
$cf->getSlug() => $this->translatableStringHelper->localize($cf->getName())
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the choice given in $choiceSlug is checked inside $data.
|
||||
*
|
||||
* Used in list exports.
|
||||
*
|
||||
* @param CustomField $cf
|
||||
* @param string $choiceSlug the slug of the choice we want to know if it was checked
|
||||
* @param array|string $data the data of the field
|
||||
* @return boolean
|
||||
*/
|
||||
public function isChecked(CustomField $cf, $choiceSlug, $data)
|
||||
{
|
||||
if ($data === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($cf->getOptions()[self::MULTIPLE]) {
|
||||
if ($cf->getOptions()[self::ALLOW_OTHER]) {
|
||||
return \in_array($choiceSlug, $this->deserialize($data, $cf)['_choices']);
|
||||
} else {
|
||||
return \in_array($choiceSlug, $this->deserialize($data, $cf));
|
||||
}
|
||||
} else {
|
||||
if ($cf->getOptions()[self::ALLOW_OTHER]) {
|
||||
return $this->deserialize($data, $cf)['_choices'] === $choiceSlug;
|
||||
} else {
|
||||
return $this->deserialize($data, $cf) === $choiceSlug;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function isMultiple(CustomField $cf)
|
||||
{
|
||||
return $cf->getOptions()[self::MULTIPLE];
|
||||
}
|
||||
|
||||
public function allowOtherChoice(CustomField $cf)
|
||||
{
|
||||
return $cf->getOptions()[self::ALLOW_OTHER];
|
||||
}
|
||||
|
||||
public function extractOtherValue(CustomField $cf, array $data = null)
|
||||
{
|
||||
return $data['_other'];
|
||||
}
|
||||
}
|
241
src/Bundle/ChillCustomFields/CustomFields/CustomFieldDate.php
Normal file
241
src/Bundle/ChillCustomFields/CustomFields/CustomFieldDate.php
Normal file
@ -0,0 +1,241 @@
|
||||
<?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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\CustomFieldsBundle\CustomFields;
|
||||
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
|
||||
use Symfony\Component\Validator\Constraints\LessThanOrEqual;
|
||||
use Symfony\Bundle\TwigBundle\TwigEngine;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Validator\Constraints\Callback;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Chill\CustomFieldsBundle\Form\DataTransformer\CustomFieldDataTransformer;
|
||||
|
||||
/**
|
||||
* Create a custom date number.
|
||||
*
|
||||
* The date may have a min and max value.
|
||||
*
|
||||
* The date is stored as an unix timestamp.
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldDate extends AbstractCustomField
|
||||
{
|
||||
/**
|
||||
* key for the minimal value of the field
|
||||
*/
|
||||
const MIN = 'min';
|
||||
const MAX = 'max';
|
||||
const FORMAT = 'format';
|
||||
const DATE_FORMAT = \DateTime::RFC3339;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TwigEngine
|
||||
*/
|
||||
private $templating = NULL;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
private $translatableStringHelper = NULL;
|
||||
|
||||
public function __construct(TwigEngine $templating, TranslatableStringHelper $translatableStringHelper)
|
||||
{
|
||||
$this->templating = $templating;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, CustomField $customField)
|
||||
{
|
||||
$fieldOptions = $this->prepareFieldOptions($customField);
|
||||
|
||||
$builder->add(
|
||||
$builder
|
||||
->create(
|
||||
$customField->getSlug(),
|
||||
ChillDateType::class,
|
||||
$fieldOptions)
|
||||
->addModelTransformer(
|
||||
new CustomFieldDataTransformer($this, $customField)
|
||||
)
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* prepare the options'form field
|
||||
*
|
||||
* @param CustomField $customField
|
||||
* @param string $type
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function prepareFieldOptions(CustomField $customField)
|
||||
{
|
||||
$options = $customField->getOptions();
|
||||
|
||||
/**
|
||||
* @var mixed[] the formField options
|
||||
*/
|
||||
$fieldOptions = array();
|
||||
|
||||
// add required
|
||||
$fieldOptions['required'] = False;
|
||||
|
||||
//add label
|
||||
$fieldOptions['label'] = $this->translatableStringHelper->localize($customField->getName());
|
||||
|
||||
// add constraints if required
|
||||
if ($options[self::MIN] !== NULL) {
|
||||
$fieldOptions['constraints'][] = new Callback(
|
||||
function($timestamp, ExecutionContextInterface $context) use ($options) {
|
||||
if ($timestamp === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$value = \DateTime::createFromFormat(self::DATE_FORMAT, $timestamp);
|
||||
$after = new \DateTime($options[self::MIN]);
|
||||
|
||||
if ($value < $after) {
|
||||
$context
|
||||
->buildViolation('This date must be after or equal to %date%', [
|
||||
'%date%' => $after->format('d-m-Y')
|
||||
])
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
if ($options[self::MAX] !== NULL) {
|
||||
$fieldOptions['constraints'][] = new Callback(
|
||||
function($timestamp, ExecutionContextInterface $context) use ($options) {
|
||||
if ($timestamp === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$value = \DateTime::createFromFormat(self::DATE_FORMAT, $timestamp);
|
||||
$before = new \DateTime($options[self::MAX]);
|
||||
|
||||
if ($value > $before) {
|
||||
$context
|
||||
->buildViolation('This date must be before or equal to %date%', [
|
||||
'%date%' => $before->format('d-m-Y')
|
||||
])
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return $fieldOptions;
|
||||
}
|
||||
|
||||
public function buildOptionsForm(FormBuilderInterface $builder)
|
||||
{
|
||||
$validatorFunction = function($value, ExecutionContextInterface $context) {
|
||||
try {
|
||||
$date = new \DateTime($value);
|
||||
} catch (\Exception $e) {
|
||||
$context->buildViolation('The expression "%expression%" is invalid', [
|
||||
'%expression%' => $value
|
||||
])
|
||||
->addViolation()
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
return $builder
|
||||
->add(self::MIN, TextType::class, array(
|
||||
'label' => 'Greater or equal than (expression like 1 day ago, 2 years ago, +1 month, today, tomorrow, or date with format YYYY-mm-dd)',
|
||||
'required' => false,
|
||||
'constraints' => [ new Callback($validatorFunction) ]
|
||||
))
|
||||
->add(self::MAX, TextType::class, array(
|
||||
'label' => 'Lesser or equal than (expression like 1 day ago, 2 years ago, +1 month, today, tomorrow, or date with format YYYY-mm-dd)',
|
||||
'required' => false,
|
||||
'constraints' => [ new Callback($validatorFunction) ]
|
||||
))
|
||||
->add(self::FORMAT, ChoiceType::class, [
|
||||
'label' => 'Format',
|
||||
'choices' => [
|
||||
'medium' => 'medium',
|
||||
'long' => 'long',
|
||||
'short' => 'short'
|
||||
]
|
||||
])
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
public function deserialize($serialized, CustomField $customField)
|
||||
{
|
||||
if (empty($serialized)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return \DateTime::createFromFormat(self::DATE_FORMAT, $serialized);
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'Date field';
|
||||
}
|
||||
|
||||
public function render($value, CustomField $customField, $documentType = 'html')
|
||||
{
|
||||
switch ($documentType) {
|
||||
case 'csv':
|
||||
$date = $this->deserialize($value, $customField);
|
||||
if (NULL === $date) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $date->format('Y-m-d');
|
||||
default:
|
||||
$template = 'ChillCustomFieldsBundle:CustomFieldsRendering:date.'
|
||||
.$documentType.'.twig';
|
||||
|
||||
return $this->templating
|
||||
->render($template, array(
|
||||
'value' => $this->deserialize($value, $customField),
|
||||
'format' => $customField->getOptions()[self::FORMAT]
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public function serialize($date, CustomField $customField)
|
||||
{
|
||||
if ($date === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $date->format(self::DATE_FORMAT);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CustomFieldsBundle\CustomFields;
|
||||
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
interface CustomFieldInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Return a form type to edit the custom field. This form is shown to the
|
||||
* user.
|
||||
*
|
||||
* @param \Chill\CustomFieldsBundle\CustomField\FormBuilderInterface $builder
|
||||
* @param \Chill\CustomFieldsBundle\CustomField\CustomField $customField
|
||||
* @return \Symfony\Component\Form\FormTypeInterface the form type
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, CustomField $customField);
|
||||
|
||||
/**
|
||||
* Transform the value into a format that can be stored in DB
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param \Chill\CustomFieldsBundle\CustomField\CustomField $customField
|
||||
*/
|
||||
public function serialize($value, CustomField $customField);
|
||||
|
||||
/**
|
||||
* Transform the representation of the value, stored in db, into the
|
||||
* value which may be used in the process.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param \Chill\CustomFieldsBundle\CustomField\CustomField $customField
|
||||
*/
|
||||
public function deserialize($serialized, CustomField $customField);
|
||||
|
||||
/**
|
||||
* Return a repsentation of the value of the CustomField.
|
||||
*
|
||||
* @param mixed $value the raw value, **not deserialized** (= as stored in the db)
|
||||
* @param \Chill\CustomFieldsBundle\CustomField\CustomField $customField
|
||||
* @return string an html representation of the value
|
||||
*/
|
||||
public function render($value, CustomField $customField, $documentType = 'html');
|
||||
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* Return a formType which allow to edit option for the custom type.
|
||||
* This FormType is shown in admin
|
||||
*
|
||||
* @param \Chill\CustomFieldsBundle\CustomField\FormBuilderInterface $builder
|
||||
* @return \Symfony\Component\Form\FormTypeInterface|null the form type
|
||||
*/
|
||||
public function buildOptionsForm(FormBuilderInterface $builder);
|
||||
|
||||
/**
|
||||
* Return if the value can be considered as empty
|
||||
*
|
||||
* @param mixed $value the value passed throug the deserialize function
|
||||
* @param CustomField $customField
|
||||
*/
|
||||
public function isEmptyValue($value, CustomField $customField);
|
||||
}
|
@ -0,0 +1,162 @@
|
||||
<?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\CustomFieldsBundle\CustomFields;
|
||||
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Chill\CustomFieldsBundle\EntityRepository\CustomFieldLongChoice\OptionRepository;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomFieldLongChoice\Option;
|
||||
use Chill\CustomFieldsBundle\Form\DataTransformer\CustomFieldDataTransformer;
|
||||
use Symfony\Bridge\Twig\TwigEngine;
|
||||
use Chill\MainBundle\Form\Type\Select2ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldLongChoice extends AbstractCustomField
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var OptionRepository
|
||||
*/
|
||||
private $optionRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
private $translatableStringHelper;
|
||||
|
||||
/**
|
||||
* @var TwigEngine
|
||||
*/
|
||||
private $templating;
|
||||
|
||||
const KEY = 'key';
|
||||
|
||||
public function __construct(OptionRepository $optionRepository,
|
||||
TranslatableStringHelper $translatableStringHelper,
|
||||
TwigEngine $twigEngine)
|
||||
{
|
||||
$this->optionRepository = $optionRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
$this->templating = $twigEngine;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, CustomField $customField)
|
||||
{
|
||||
$options = $customField->getOptions();
|
||||
$entries = $this->optionRepository->findFilteredByKey($options[self::KEY],
|
||||
false, true);
|
||||
//create a local copy of translatable string helper
|
||||
$translatableStringHelper = $this->translatableStringHelper;
|
||||
$builder->add($customField->getSlug(), Select2ChoiceType::class, array(
|
||||
'choices' => $entries,
|
||||
'choice_label' => function(Option $option) use ($translatableStringHelper) {
|
||||
return $translatableStringHelper->localize($option->getText());
|
||||
},
|
||||
'choice_value' => function ($key) use ($entries) {
|
||||
if ($key === NULL) {
|
||||
return null;
|
||||
}
|
||||
return $key->getId();
|
||||
},
|
||||
'multiple' => false,
|
||||
'expanded' => false,
|
||||
'required' => $customField->isRequired(),
|
||||
'placeholder' => 'Choose a value',
|
||||
'group_by' => function(Option $option) use ($translatableStringHelper) {
|
||||
if ($option->hasParent()) {
|
||||
return $translatableStringHelper->localize($option->getParent()->getText());
|
||||
} else {
|
||||
return $translatableStringHelper->localize($option->getText());
|
||||
}
|
||||
},
|
||||
'label' => $translatableStringHelper->localize($customField->getName())
|
||||
));
|
||||
$builder->get($customField->getSlug())
|
||||
->addModelTransformer(new CustomFieldDataTransformer($this, $customField));
|
||||
|
||||
}
|
||||
|
||||
public function buildOptionsForm(FormBuilderInterface $builder)
|
||||
{
|
||||
//create a selector between different keys
|
||||
$keys = $this->optionRepository->getKeys();
|
||||
$choices = array();
|
||||
foreach ($keys as $key) {
|
||||
$choices[$key] = $key;
|
||||
}
|
||||
|
||||
return $builder->add(self::KEY, ChoiceType::class, array(
|
||||
'choices' => array_combine(array_values($choices),array_keys($choices)),
|
||||
'label' => 'Options key',
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
public function deserialize($serialized, \Chill\CustomFieldsBundle\Entity\CustomField $customField)
|
||||
{
|
||||
if ($serialized === NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return $this->optionRepository->find($serialized);
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'Long choice field';
|
||||
}
|
||||
|
||||
public function render($value, \Chill\CustomFieldsBundle\Entity\CustomField $customField, $documentType = 'html')
|
||||
{
|
||||
$option = $this->deserialize($value, $customField);
|
||||
$template = 'ChillCustomFieldsBundle:CustomFieldsRendering:choice_long.'
|
||||
.$documentType.'.twig';
|
||||
|
||||
return $this->templating
|
||||
->render($template, array(
|
||||
'values' => $option === NULL ? array() : array($option)
|
||||
));
|
||||
}
|
||||
|
||||
public function serialize($value, \Chill\CustomFieldsBundle\Entity\CustomField $customField)
|
||||
{
|
||||
if ($value === NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!$value instanceof Option) {
|
||||
throw new \LogicException('the value should be an instance of '
|
||||
. 'Chill\CustomFieldsBundle\Entity\CustomFieldLongChoice\Option, '
|
||||
. is_object($value) ? get_class($value) : gettype($value).' given');
|
||||
}
|
||||
|
||||
// we place the id in array, to allow in the future multiple select
|
||||
return $value->getId();
|
||||
}
|
||||
|
||||
}
|
186
src/Bundle/ChillCustomFields/CustomFields/CustomFieldNumber.php
Normal file
186
src/Bundle/ChillCustomFields/CustomFields/CustomFieldNumber.php
Normal file
@ -0,0 +1,186 @@
|
||||
<?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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\CustomFieldsBundle\CustomFields;
|
||||
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
|
||||
use Symfony\Component\Validator\Constraints\LessThanOrEqual;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Bundle\TwigBundle\TwigEngine;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
|
||||
use Chill\CustomFieldsBundle\CustomFields\CustomFieldInterface;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
|
||||
/**
|
||||
* Create a custom field number.
|
||||
*
|
||||
* This number may have a min and max value, and a precision.
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
* @author Marc Ducobu <marc@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldNumber extends AbstractCustomField
|
||||
{
|
||||
/**
|
||||
* key for the minimal value of the field
|
||||
*/
|
||||
const MIN = 'min';
|
||||
const MAX = 'max';
|
||||
const SCALE = 'scale';
|
||||
const POST_TEXT = 'post_text';
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TwigEngine
|
||||
*/
|
||||
private $templating = NULL;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
private $translatableStringHelper = NULL;
|
||||
|
||||
public function __construct(TwigEngine $templating, TranslatableStringHelper $translatableStringHelper)
|
||||
{
|
||||
$this->templating = $templating;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, CustomField $customField)
|
||||
{
|
||||
$options = $customField->getOptions();
|
||||
|
||||
//select the type depending to the SCALE
|
||||
$type = ($options[self::SCALE] === 0 or $options[self::SCALE] === NULL)?
|
||||
IntegerType::class : NumberType::class;
|
||||
//'integer' : 'number';
|
||||
|
||||
$fieldOptions = $this->prepareFieldOptions($customField, $type);
|
||||
|
||||
$builder->add($customField->getSlug(), $type, $fieldOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* prepare the options'form field
|
||||
*
|
||||
* @param CustomField $customField
|
||||
* @param string $type
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function prepareFieldOptions(CustomField $customField, $type)
|
||||
{
|
||||
$options = $customField->getOptions();
|
||||
|
||||
/**
|
||||
* @var mixed[] the formField options
|
||||
*/
|
||||
$fieldOptions = array();
|
||||
|
||||
// add required
|
||||
$fieldOptions['required'] = False;
|
||||
|
||||
//add label
|
||||
$fieldOptions['label'] = $this->translatableStringHelper->localize($customField->getName());
|
||||
|
||||
// add constraints if required
|
||||
if ($options[self::MIN] !== NULL) {
|
||||
$fieldOptions['constraints'][] = new GreaterThanOrEqual(array('value' => $options[self::MIN]));
|
||||
}
|
||||
if ($options[self::MAX] !== NULL) {
|
||||
$fieldOptions['constraints'][] = new LessThanOrEqual(array('value' => $options[self::MAX]));
|
||||
}
|
||||
|
||||
// add precision to options if required
|
||||
if ($type === 'number') {
|
||||
$fieldOptions['scale'] = $options[self::SCALE];
|
||||
}
|
||||
|
||||
if (!empty($options[self::POST_TEXT])) {
|
||||
$fieldOptions['post_text'] = $options[self::POST_TEXT];
|
||||
}
|
||||
|
||||
return $fieldOptions;
|
||||
}
|
||||
|
||||
public function buildOptionsForm(FormBuilderInterface $builder)
|
||||
{
|
||||
return $builder
|
||||
->add(self::MIN, NumberType::class, array(
|
||||
'scale' => 2,
|
||||
'label' => 'Greater or equal than',
|
||||
'required' => false
|
||||
))
|
||||
->add(self::MAX, NumberType::class, array(
|
||||
'scale' => 2,
|
||||
'label' => 'Lesser or equal than',
|
||||
'required' => false
|
||||
))
|
||||
->add(self::SCALE, IntegerType::class, array(
|
||||
'scale' => 0,
|
||||
'label' => 'Precision',
|
||||
'constraints' => array(
|
||||
new GreaterThanOrEqual(array('value' => 0))
|
||||
)
|
||||
))
|
||||
->add(self::POST_TEXT, TextType::class, array(
|
||||
'label' => 'Text after the field'
|
||||
))
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
public function deserialize($serialized, CustomField $customField)
|
||||
{
|
||||
return $serialized;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'Number field';
|
||||
}
|
||||
|
||||
public function render($value, CustomField $customField, $documentType = 'html')
|
||||
{
|
||||
$template = 'ChillCustomFieldsBundle:CustomFieldsRendering:number.'
|
||||
.$documentType.'.twig';
|
||||
$options = $customField->getOptions();
|
||||
|
||||
return $this->templating
|
||||
->render($template, array(
|
||||
'number' => $value,
|
||||
'scale' => $options[self::SCALE],
|
||||
'post' => $options[self::POST_TEXT]
|
||||
));
|
||||
}
|
||||
|
||||
public function serialize($value, CustomField $customField)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
}
|
138
src/Bundle/ChillCustomFields/CustomFields/CustomFieldText.php
Normal file
138
src/Bundle/ChillCustomFields/CustomFields/CustomFieldText.php
Normal file
@ -0,0 +1,138 @@
|
||||
<?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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\CustomFieldsBundle\CustomFields;
|
||||
|
||||
use Chill\CustomFieldsBundle\CustomFields\CustomFieldInterface;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Bundle\TwigBundle\TwigEngine;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
|
||||
/**
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
* @author Marc Ducobu <marc@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldText extends AbstractCustomField
|
||||
{
|
||||
|
||||
private $requestStack;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TwigEngine
|
||||
*/
|
||||
private $templating;
|
||||
|
||||
/**
|
||||
* @var TranslatableStringHelper Helper that find the string in current locale from an array of translation
|
||||
*/
|
||||
private $translatableStringHelper;
|
||||
|
||||
|
||||
public function __construct(RequestStack $requestStack, TwigEngine $templating,
|
||||
TranslatableStringHelper $translatableStringHelper)
|
||||
{
|
||||
$this->requestStack = $requestStack;
|
||||
$this->templating = $templating;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
const MAX_LENGTH = 'maxLength';
|
||||
const MULTIPLE_CF_INLINE ='multipleCFInline';
|
||||
|
||||
/**
|
||||
* Create a form according to the maxLength option
|
||||
*
|
||||
* if maxLength < 256 THEN the form type is 'text'
|
||||
* if not, THEN the form type is textarea
|
||||
*
|
||||
* @param FormBuilderInterface $builder
|
||||
* @param CustomField $customField
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, CustomField $customField)
|
||||
{
|
||||
$options = $customField->getOptions();
|
||||
|
||||
$type = ($options[self::MAX_LENGTH] < 256) ? TextType::class
|
||||
: TextareaType::class;
|
||||
|
||||
$attrArray = array();
|
||||
|
||||
if(array_key_exists(self::MULTIPLE_CF_INLINE, $options) and
|
||||
$options[self::MULTIPLE_CF_INLINE]) {
|
||||
$attrArray['class'] = 'multiple-cf-inline';
|
||||
}
|
||||
|
||||
$builder->add($customField->getSlug(), $type, array(
|
||||
'label' => $this->translatableStringHelper->localize($customField->getName()),
|
||||
'required' => false,
|
||||
'attr' => $attrArray
|
||||
));
|
||||
}
|
||||
|
||||
public function render($value, CustomField $customField, $documentType = 'html')
|
||||
{
|
||||
$template = 'ChillCustomFieldsBundle:CustomFieldsRendering:text.html.twig';
|
||||
if($documentType == 'csv') {
|
||||
$template = 'ChillCustomFieldsBundle:CustomFieldsRendering:text.csv.twig';
|
||||
}
|
||||
|
||||
return $this->templating
|
||||
->render($template, array('text' => $value));
|
||||
}
|
||||
|
||||
public function serialize($value, CustomField $customField)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function deserialize($serialized, CustomField $customField)
|
||||
{
|
||||
return $serialized;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'Text field';
|
||||
}
|
||||
|
||||
public function buildOptionsForm(FormBuilderInterface $builder)
|
||||
{
|
||||
return $builder
|
||||
->add(self::MAX_LENGTH, IntegerType::class, array('empty_data' => 256))
|
||||
->add(self::MULTIPLE_CF_INLINE, ChoiceType::class, array(
|
||||
'choices' => array(
|
||||
'Multiple boxes on the line' => '1',
|
||||
'One box on the line' => '0'
|
||||
),
|
||||
'label' => 'Box appearance',
|
||||
'expanded' => True
|
||||
))
|
||||
;
|
||||
}
|
||||
}
|
115
src/Bundle/ChillCustomFields/CustomFields/CustomFieldTitle.php
Normal file
115
src/Bundle/ChillCustomFields/CustomFields/CustomFieldTitle.php
Normal file
@ -0,0 +1,115 @@
|
||||
<?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\CustomFieldsBundle\CustomFields;
|
||||
|
||||
use Chill\CustomFieldsBundle\CustomFields\CustomFieldInterface;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Bundle\TwigBundle\TwigEngine;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Chill\CustomFieldsBundle\Form\Type\CustomFieldsTitleType;
|
||||
|
||||
class CustomFieldTitle extends AbstractCustomField
|
||||
{
|
||||
const TYPE = 'type';
|
||||
const TYPE_TITLE = 'title';
|
||||
const TYPE_SUBTITLE = 'subtitle';
|
||||
|
||||
private $requestStack;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TwigEngine
|
||||
*/
|
||||
private $templating;
|
||||
|
||||
/**
|
||||
* @var TranslatableStringHelper Helper that find the string in current locale from an array of translation
|
||||
*/
|
||||
private $translatableStringHelper;
|
||||
|
||||
public function __construct(RequestStack $requestStack, TwigEngine $templating,
|
||||
TranslatableStringHelper $translatableStringHelper)
|
||||
{
|
||||
$this->requestStack = $requestStack;
|
||||
$this->templating = $templating;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, CustomField $customField)
|
||||
{
|
||||
$builder->add($customField->getSlug(), CustomFieldsTitleType::class, array(
|
||||
'label' => false,
|
||||
'attr' => array(
|
||||
'class' => 'cf-title',
|
||||
'title' => $this->translatableStringHelper->localize($customField->getName()),
|
||||
self::TYPE => $customField->getOptions()[self::TYPE ]
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
public function render($value, CustomField $customField, $documentType = 'html')
|
||||
{
|
||||
return $this->templating
|
||||
->render('ChillCustomFieldsBundle:CustomFieldsRendering:title.html.twig',
|
||||
array(
|
||||
'title' => $customField->getName(),
|
||||
'type' => $customField->getOptions()[self::TYPE]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function serialize($value, CustomField $customField)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function deserialize($serialized, CustomField $customField)
|
||||
{
|
||||
return $serialized;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'Title';
|
||||
}
|
||||
|
||||
public function isEmptyValue($value, CustomField $customField)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function buildOptionsForm(FormBuilderInterface $builder)
|
||||
{
|
||||
return $builder->add(self::TYPE, ChoiceType::class,
|
||||
array(
|
||||
'choices' => array(
|
||||
'Main title' => self::TYPE_TITLE,
|
||||
'Subtitle' => self::TYPE_SUBTITLE
|
||||
),
|
||||
'label' => 'Title level',
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
181
src/Bundle/ChillCustomFields/DataFixtures/ORM/LoadOption.php
Normal file
181
src/Bundle/ChillCustomFields/DataFixtures/ORM/LoadOption.php
Normal file
@ -0,0 +1,181 @@
|
||||
<?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\CustomFieldsBundle\DataFixtures\ORM;
|
||||
|
||||
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomFieldLongChoice\Option;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
error_reporting(0);
|
||||
/**
|
||||
* Load some Options
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class LoadOption extends AbstractFixture implements OrderedFixtureInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var \Faker\Generator
|
||||
*/
|
||||
public $fakerFr;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Faker\Generator
|
||||
*/
|
||||
public $fakerEn;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Faker\Generator
|
||||
*/
|
||||
public $fakerNl;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->fakerFr = \Faker\Factory::create('fr_FR');
|
||||
$this->fakerEn = \Faker\Factory::create('en_EN');
|
||||
$this->fakerNl = \Faker\Factory::create('nl_NL');
|
||||
}
|
||||
|
||||
public function getOrder()
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
echo "Loading Options \n";
|
||||
|
||||
// load companies
|
||||
$this->loadingCompanies($manager);
|
||||
$this->loadingWords($manager);
|
||||
|
||||
$manager->flush();
|
||||
|
||||
}
|
||||
|
||||
private function loadingWords(\Doctrine\Persistence\ObjectManager $manager)
|
||||
{
|
||||
echo "Loading some words...\n";
|
||||
|
||||
$parents = array(
|
||||
array(
|
||||
'fr' => 'Categorie 1',
|
||||
'nl' => 'Categorie 1',
|
||||
'en' => 'Category 1'
|
||||
),
|
||||
array(
|
||||
'fr' => 'Categorie 2',
|
||||
'nl' => 'Categorie 2',
|
||||
'en' => 'Category 2'
|
||||
)
|
||||
);
|
||||
|
||||
foreach ($parents as $text) {
|
||||
$parent = (new Option())
|
||||
->setText($text)
|
||||
->setKey('word')
|
||||
;
|
||||
$manager->persist($parent);
|
||||
|
||||
//Load children
|
||||
$expected_nb_children = rand(10, 50);
|
||||
for ($i=0; $i < $expected_nb_children; $i++) {
|
||||
$manager->persist($this->createChildOption($parent, array(
|
||||
'fr' => $this->fakerFr->word,
|
||||
'nl' => $this->fakerNl->word,
|
||||
'en' => $this->fakerEn->word
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function loadingCompanies(\Doctrine\Persistence\ObjectManager $manager)
|
||||
{
|
||||
echo "Loading companies \n";
|
||||
$companiesParents = array(
|
||||
array(
|
||||
'fr' => 'Grandes Entreprises',
|
||||
'nl' => 'Grotes Bedrijven',
|
||||
'en' => 'Big Companies'
|
||||
),
|
||||
array(
|
||||
'fr' => 'Moyennes Entreprises',
|
||||
'nl' => 'Middelbare Bedrijven',
|
||||
'en' => 'Middle Companies'
|
||||
),
|
||||
array(
|
||||
'fr' => 'Petites Entreprises',
|
||||
'nl' => 'Kleine Bedrijven',
|
||||
'en' => 'Little Companies'
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
foreach ($companiesParents as $text) {
|
||||
|
||||
$parent = (new Option())
|
||||
->setText($text)
|
||||
->setKey('company')
|
||||
;
|
||||
$manager->persist($parent);
|
||||
|
||||
//Load children
|
||||
$expected_nb_children = rand(10, 50);
|
||||
for ($i=0; $i < $expected_nb_children; $i++) {
|
||||
|
||||
$companyName = $this->fakerFr->company;
|
||||
|
||||
$manager->persist(
|
||||
$this->createChildOption($parent, array(
|
||||
'fr' => $companyName,
|
||||
'nl' => $companyName,
|
||||
'en' => $companyName
|
||||
)));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private $counter = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Option $parent
|
||||
* @param array $text
|
||||
* @return Option
|
||||
*/
|
||||
private function createChildOption(Option $parent, array $text)
|
||||
{
|
||||
$this->counter ++;
|
||||
|
||||
return (new Option())
|
||||
->setText($text)
|
||||
->setParent($parent)
|
||||
->setActive(true)
|
||||
->setInternalKey($parent->getKey().'-'.$this->counter);
|
||||
;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CustomFieldsBundle\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;
|
||||
|
||||
/**
|
||||
* 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 ChillCustomFieldsExtension extends Extension implements PrependExtensionInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
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->load('services.yaml');
|
||||
$loader->load('services/fixtures.yaml');
|
||||
$loader->load('services/controller.yaml');
|
||||
$loader->load('services/command.yaml');
|
||||
|
||||
//add at least a blank array at 'customizable_entities' options
|
||||
//$customizable_entities = (isset($config['customizables_entities'])
|
||||
// && $config['customizables_entities'] !== FALSE)
|
||||
// ? $config['customizables_entities'] : array();
|
||||
|
||||
$container->setParameter('chill_custom_fields.customizables_entities',
|
||||
$config['customizables_entities']);
|
||||
$container->setParameter('chill_custom_fields.show_empty_values',
|
||||
$config['show_empty_values_in_views']);
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see \Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface::prepend()
|
||||
*/
|
||||
public function prepend(ContainerBuilder $container)
|
||||
{
|
||||
// add form layout to twig resources
|
||||
$twigConfig['form_themes'][] = 'ChillCustomFieldsBundle:Form:fields.html.twig';
|
||||
$container->prependExtensionConfig('twig', $twigConfig);
|
||||
|
||||
//add routes for custom bundle
|
||||
$container->prependExtensionConfig('chill_main', array(
|
||||
'routing' => array(
|
||||
'resources' => array(
|
||||
'@ChillCustomFieldsBundle/config/routes.yaml'
|
||||
)
|
||||
)
|
||||
));
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CustomFieldsBundle\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
|
||||
*
|
||||
* 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_custom_fields');
|
||||
$rootNode = $treeBuilder->getRootNode('chill_custom_fields');
|
||||
|
||||
$classInfo = "The class which may receive custom fields";
|
||||
$nameInfo = "The name which will appears in the user interface. May be translatable";
|
||||
$optionsInfo = "Options available for custom fields groups referencing this class";
|
||||
$optionsFormType = "The name of the form to append";
|
||||
$optionsFormOptionsInfos = "the arguments to pass the form";
|
||||
$customizableEntitiesInfo = "A list of customizable entities";
|
||||
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('customizables_entities')
|
||||
->info($customizableEntitiesInfo)
|
||||
->defaultValue(array())
|
||||
->prototype('array')
|
||||
->children()
|
||||
->scalarNode('class')->isRequired()->info($classInfo)
|
||||
->end()
|
||||
->scalarNode('name') ->isRequired()->info($nameInfo)
|
||||
->end()
|
||||
->arrayNode('options')
|
||||
->info($optionsInfo)
|
||||
->defaultValue(array())
|
||||
->useAttributeAsKey('key')
|
||||
->prototype('array')
|
||||
->children()
|
||||
->scalarNode('form_type')
|
||||
->isRequired()
|
||||
->info($optionsFormType)
|
||||
->end()
|
||||
->variableNode('form_options')
|
||||
->info($optionsFormOptionsInfos)
|
||||
->defaultValue(array())
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->booleanNode('show_empty_values_in_views')
|
||||
->info('Show the empty value for custom fields in the views, timeline, ...')
|
||||
->defaultValue(true)
|
||||
->end()
|
||||
->end()
|
||||
;
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Chill\CustomFieldsBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldCompilerPass implements CompilerPassInterface
|
||||
{
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
if (!$container->hasDefinition('chill.custom_field.provider')) {
|
||||
throw new \LogicException('service chill.custom_field.provider '
|
||||
. 'is not defined.');
|
||||
}
|
||||
|
||||
$definition = $container->getDefinition(
|
||||
'chill.custom_field.provider'
|
||||
);
|
||||
|
||||
$taggedServices = $container->findTaggedServiceIds(
|
||||
'chill.custom_field'
|
||||
);
|
||||
|
||||
foreach ($taggedServices as $id => $tagAttributes) {
|
||||
foreach ($tagAttributes as $attributes) {
|
||||
$definition->addMethodCall(
|
||||
'addCustomField',
|
||||
array(new Reference($id), $attributes["type"])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
312
src/Bundle/ChillCustomFields/Entity/CustomField.php
Normal file
312
src/Bundle/ChillCustomFields/Entity/CustomField.php
Normal file
@ -0,0 +1,312 @@
|
||||
<?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\CustomFieldsBundle\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* CustomField
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="customfield")
|
||||
* @ORM\HasLifecycleCallbacks()
|
||||
*/
|
||||
class CustomField
|
||||
{
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Id
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=255)
|
||||
*/
|
||||
private $slug;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=255)
|
||||
*/
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $active = true;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* @ORM\Column(type="json_array")
|
||||
*/
|
||||
private $options = array();
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* @ORM\Column(type="json_array")
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*
|
||||
* @ORM\Column(type="float")
|
||||
*/
|
||||
private $ordering;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $required = FALSE;
|
||||
|
||||
const ONE_TO_ONE = 1;
|
||||
const ONE_TO_MANY = 2;
|
||||
|
||||
/**
|
||||
* @var CustomFieldsGroup
|
||||
*
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="Chill\CustomFieldsBundle\Entity\CustomFieldsGroup",
|
||||
* inversedBy="customFields")
|
||||
*/
|
||||
private $customFieldGroup;
|
||||
|
||||
|
||||
/**
|
||||
* Get id
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function getSlug()
|
||||
{
|
||||
return $this->slug;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
function getOptions()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set type
|
||||
*
|
||||
* @param string $type
|
||||
* @return CustomField
|
||||
*/
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set active
|
||||
*
|
||||
* @param boolean $active
|
||||
* @return CustomField
|
||||
*/
|
||||
public function setActive($active)
|
||||
{
|
||||
$this->active = $active;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the custom field is active
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isActive()
|
||||
{
|
||||
return $this->active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get customFieldGroup
|
||||
*
|
||||
* @return CustomFieldsGroup
|
||||
*/
|
||||
public function getCustomFieldsGroup()
|
||||
{
|
||||
return $this->customFieldGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set customFieldGroup
|
||||
*
|
||||
* @param CustomFieldsGroup $customFieldGroup
|
||||
* @return CustomField
|
||||
*/
|
||||
public function setCustomFieldsGroup(CustomFieldsGroup $customFieldGroup = null)
|
||||
{
|
||||
$this->customFieldGroup = $customFieldGroup;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name
|
||||
*
|
||||
* @param array $name
|
||||
* @return CustomField
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getName($locale = null)
|
||||
{
|
||||
if ($locale) {
|
||||
if (isset($this->name[$locale])) {
|
||||
return $this->name[$locale];
|
||||
} else {
|
||||
foreach ($this->name as $name) {
|
||||
if (!empty($name)) {
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
|
||||
} else {
|
||||
return $this->name;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set order
|
||||
*
|
||||
* @param float $order
|
||||
* @return CustomField
|
||||
*/
|
||||
public function setOrdering($order)
|
||||
{
|
||||
$this->ordering = $order;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get order
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getOrdering()
|
||||
{
|
||||
return $this->ordering;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set options
|
||||
*
|
||||
* @param array $options
|
||||
* @return CustomField
|
||||
*/
|
||||
public function setOptions(array $options)
|
||||
{
|
||||
$this->options = $options;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $slug
|
||||
* @return $this
|
||||
*/
|
||||
public function setSlug($slug)
|
||||
{
|
||||
$this->slug = $slug;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* alias for isRequired
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function getRequired()
|
||||
{
|
||||
return $this->isRequired();
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if the field required
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isRequired()
|
||||
{
|
||||
return $this->required;
|
||||
}
|
||||
|
||||
public function setRequired($required)
|
||||
{
|
||||
$this->required = $required;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,210 @@
|
||||
<?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\CustomFieldsBundle\Entity\CustomFieldLongChoice;
|
||||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(
|
||||
* repositoryClass="Chill\CustomFieldsBundle\EntityRepository\CustomFieldLongChoice\OptionRepository")
|
||||
* @ORM\Table(name="custom_field_long_choice_options")
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class Option
|
||||
{
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Id
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @ORM\Column(type="string", length=15)
|
||||
*/
|
||||
private $key;
|
||||
|
||||
/**
|
||||
* A json representation of text (multilingual)
|
||||
*
|
||||
* @var array
|
||||
* @ORM\Column(type="json_array")
|
||||
*/
|
||||
private $text;
|
||||
|
||||
/**
|
||||
* @var Collection
|
||||
* @ORM\OneToMany(
|
||||
* targetEntity="Chill\CustomFieldsBundle\Entity\CustomFieldLongChoice\Option",
|
||||
* mappedBy="parent")
|
||||
*/
|
||||
private $children;
|
||||
|
||||
/**
|
||||
* @var Option
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="Chill\CustomFieldsBundle\Entity\CustomFieldLongChoice\Option",
|
||||
* inversedBy="children")
|
||||
* @ORM\JoinColumn(nullable=true)
|
||||
*/
|
||||
private $parent;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @ORM\Column(type="string", length=50, name="internal_key")
|
||||
*/
|
||||
private $internalKey = '';
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private $active = true;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getKey()
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getText()
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getChildren()
|
||||
{
|
||||
return $this->children;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Option
|
||||
*/
|
||||
public function getParent()
|
||||
{
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @return $this
|
||||
*/
|
||||
public function setKey($key)
|
||||
{
|
||||
$this->key = $key;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $text
|
||||
* @return $this
|
||||
*/
|
||||
public function setText(array $text)
|
||||
{
|
||||
$this->text = $text;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Option|null $parent
|
||||
* @return $this
|
||||
*/
|
||||
public function setParent(Option $parent = null)
|
||||
{
|
||||
$this->parent = $parent;
|
||||
$this->key = $parent->getKey();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasParent()
|
||||
{
|
||||
return $this->parent === NULL ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getInternalKey()
|
||||
{
|
||||
return $this->internalKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isActive()
|
||||
{
|
||||
return $this->active;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getActive()
|
||||
{
|
||||
return $this->isActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $internal_key
|
||||
* @return $this
|
||||
*/
|
||||
public function setInternalKey($internal_key)
|
||||
{
|
||||
$this->internalKey = $internal_key;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $active
|
||||
* @return $this
|
||||
*/
|
||||
public function setActive($active)
|
||||
{
|
||||
$this->active = $active;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
120
src/Bundle/ChillCustomFields/Entity/CustomFieldsDefaultGroup.php
Normal file
120
src/Bundle/ChillCustomFields/Entity/CustomFieldsDefaultGroup.php
Normal file
@ -0,0 +1,120 @@
|
||||
<?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\CustomFieldsBundle\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* CustomFieldsDefaultGroup
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(
|
||||
* name="customfieldsdefaultgroup",
|
||||
* uniqueConstraints={@ORM\UniqueConstraint(
|
||||
* name="unique_entity",
|
||||
* columns={"entity"}
|
||||
* )})
|
||||
*/
|
||||
class CustomFieldsDefaultGroup
|
||||
{
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Id
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=255)
|
||||
*/
|
||||
private $entity;
|
||||
|
||||
/**
|
||||
* @var CustomFieldsGroup
|
||||
*
|
||||
* @ORM\ManyToOne(
|
||||
* targetEntity="Chill\CustomFieldsBundle\Entity\CustomFieldsGroup")
|
||||
*
|
||||
* sf4 check: option inversedBy="customFields" return inconsistent error mapping !!
|
||||
*/
|
||||
private $customFieldsGroup;
|
||||
|
||||
/**
|
||||
* Get id
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set entity
|
||||
*
|
||||
* @param string $entity
|
||||
* @return CustomFieldsDefaultGroup
|
||||
*/
|
||||
public function setEntity($entity)
|
||||
{
|
||||
$this->entity = $entity;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get entity
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEntity()
|
||||
{
|
||||
return $this->entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set customFieldsGroup
|
||||
*
|
||||
* @param CustomFieldsGroup $customFieldsGroup *
|
||||
* @return CustomFieldsDefaultGroup
|
||||
*/
|
||||
public function setCustomFieldsGroup($customFieldsGroup)
|
||||
{
|
||||
$this->customFieldsGroup = $customFieldsGroup;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get customFieldsGroup
|
||||
*
|
||||
* @return CustomFieldsGroup
|
||||
*/
|
||||
public function getCustomFieldsGroup()
|
||||
{
|
||||
return $this->customFieldsGroup;
|
||||
}
|
||||
}
|
239
src/Bundle/ChillCustomFields/Entity/CustomFieldsGroup.php
Normal file
239
src/Bundle/ChillCustomFields/Entity/CustomFieldsGroup.php
Normal file
@ -0,0 +1,239 @@
|
||||
<?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\CustomFieldsBundle\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
|
||||
/**
|
||||
* CustomFieldGroup
|
||||
*
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="customfieldsgroup")
|
||||
*/
|
||||
class CustomFieldsGroup
|
||||
{
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* @ORM\Id
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* @ORM\Column(type="json_array")
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(type="string", length=255)
|
||||
*/
|
||||
private $entity;
|
||||
|
||||
/**
|
||||
* The custom fields of the group.
|
||||
* The custom fields are asc-ordered regarding to their property "ordering".
|
||||
*
|
||||
* @var Collection $customFields
|
||||
*
|
||||
* @ORM\OneToMany(
|
||||
* targetEntity="Chill\CustomFieldsBundle\Entity\CustomField",
|
||||
* mappedBy="customFieldGroup")
|
||||
* @ORM\OrderBy({"ordering" = "ASC"})
|
||||
*/
|
||||
private $customFields;
|
||||
|
||||
/**
|
||||
* The custom fields of the group that are active.
|
||||
* This variable if null, if this informations has not been computed.
|
||||
*
|
||||
* @var array|null
|
||||
*/
|
||||
private $activeCustomFields = null;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* @ORM\Column(type="json_array")
|
||||
*/
|
||||
private $options = array();
|
||||
|
||||
|
||||
/**
|
||||
* CustomFieldsGroup constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->customFields = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add customField
|
||||
*
|
||||
* @param CustomField $customField
|
||||
* @return CustomFieldsGroup
|
||||
*/
|
||||
public function addCustomField(CustomField $customField)
|
||||
{
|
||||
$this->customFields[] = $customField;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove customField
|
||||
*
|
||||
* @param CustomField $customField
|
||||
*/
|
||||
public function removeCustomField(CustomField $customField)
|
||||
{
|
||||
$this->customFields->removeElement($customField);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getCustomFields()
|
||||
{
|
||||
return $this->customFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the custom
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getActiveCustomFields()
|
||||
{
|
||||
if($this->activeCustomFields === null) {
|
||||
$this->activeCustomFields = array();
|
||||
foreach ($this->customFields as $cf) {
|
||||
if($cf->isActive()) {
|
||||
array_push($this->activeCustomFields, $cf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->activeCustomFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get id
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name
|
||||
*
|
||||
* @param array $name
|
||||
* @return CustomFieldsGroup
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getName($language = null)
|
||||
{
|
||||
//TODO set this in a service, PLUS twig function
|
||||
if ($language) {
|
||||
if (isset($this->name[$language])) {
|
||||
return $this->name[$language];
|
||||
} else {
|
||||
foreach ($this->name as $name) {
|
||||
if (!empty($name)) {
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
|
||||
} else {
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set entity
|
||||
*
|
||||
* @param string $entity
|
||||
* @return CustomFieldsGroup
|
||||
*/
|
||||
public function setEntity($entity)
|
||||
{
|
||||
$this->entity = $entity;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get entity
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEntity()
|
||||
{
|
||||
return $this->entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* get options array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* set options array
|
||||
*
|
||||
* @param array $options
|
||||
* @return CustomFieldsGroup
|
||||
*/
|
||||
public function setOptions(array $options)
|
||||
{
|
||||
$this->options = $options;
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -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\CustomFieldsBundle\EntityRepository\CustomFieldLongChoice;
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomFieldLongChoice\Option;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class OptionRepository extends EntityRepository
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @param string $key
|
||||
* @return Option[]
|
||||
*/
|
||||
public function findFilteredByKey($key, $includeParents = true, $active = true)
|
||||
{
|
||||
$qb = $this->createQueryBuilder('option');
|
||||
$qb->where('option.key = :key');
|
||||
|
||||
if ($active === true){
|
||||
$qb->andWhere('option.active = true');
|
||||
}
|
||||
|
||||
if ($includeParents === false) {
|
||||
$qb->andWhere('option.parent IS NOT NULL');
|
||||
|
||||
if ($active === TRUE) {
|
||||
$qb->join('option.parent', 'p');
|
||||
$qb->andWhere('p.active = true');
|
||||
}
|
||||
}
|
||||
|
||||
$qb->setParameter('key', $key);
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getKeys()
|
||||
{
|
||||
$keys = $this->createQueryBuilder('option')
|
||||
->select('option.key')
|
||||
->distinct()
|
||||
->getQuery()
|
||||
->getScalarResult();
|
||||
|
||||
return array_map(function($r) {
|
||||
return $r['key'];
|
||||
}, $keys);
|
||||
}
|
||||
|
||||
}
|
138
src/Bundle/ChillCustomFields/Form/CustomFieldType.php
Normal file
138
src/Bundle/ChillCustomFields/Form/CustomFieldType.php
Normal file
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
|
||||
use Chill\CustomFieldsBundle\Form\DataTransformer\CustomFieldsGroupToIdTransformer;
|
||||
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
|
||||
|
||||
class CustomFieldType extends AbstractType
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var CustomFieldProvider
|
||||
*/
|
||||
private $customFieldProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
private $translatableStringHelper;
|
||||
|
||||
/**
|
||||
* @var ObjectManager
|
||||
*/
|
||||
private $om;
|
||||
|
||||
|
||||
public function __construct(
|
||||
CustomFieldProvider $compiler,
|
||||
ObjectManager $om,
|
||||
TranslatableStringHelper $translatableStringHelper
|
||||
) {
|
||||
$this->customFieldProvider = $compiler;
|
||||
$this->om = $om;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
/**
|
||||
* @param FormBuilderInterface $builder
|
||||
* @param array $options
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
|
||||
$customFieldsList = array();
|
||||
|
||||
foreach ($this->customFieldProvider->getAllFields() as $key => $field) {
|
||||
$customFieldsList[$key] = $field->getName();
|
||||
}
|
||||
|
||||
$builder
|
||||
->add('name', TranslatableStringFormType::class)
|
||||
->add('active', CheckboxType::class, array('required' => false));
|
||||
|
||||
if ($options['group_widget'] === 'entity') {
|
||||
$builder->add('customFieldsGroup', EntityType::class, array(
|
||||
'class' => 'ChillCustomFieldsBundle:CustomFieldsGroup',
|
||||
'choice_label' => function($g) {
|
||||
return $this->translatableStringHelper->localize($g->getName());
|
||||
}
|
||||
));
|
||||
} elseif ($options['group_widget'] === 'hidden') {
|
||||
$builder->add('customFieldsGroup', HiddenType::class);
|
||||
$builder->get('customFieldsGroup')
|
||||
->addViewTransformer(new CustomFieldsGroupToIdTransformer($this->om));
|
||||
} else {
|
||||
throw new \LogicException('The value of group_widget is not handled');
|
||||
}
|
||||
|
||||
$builder
|
||||
->add('ordering', NumberType::class)
|
||||
->add('required', CheckboxType::class, array(
|
||||
'required' => false,
|
||||
//'expanded' => TRUE,
|
||||
'label' => 'Required field'
|
||||
))
|
||||
->add('type', HiddenType::class, array('data' => $options['type']))
|
||||
->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event)
|
||||
{
|
||||
$customField = $event->getData();
|
||||
$form = $event->getForm();
|
||||
|
||||
// check if the customField object is "new"
|
||||
// If no data is passed to the form, the data is "null".
|
||||
// This should be considered a new "customField"
|
||||
if (!$customField || null === $customField->getId()) {
|
||||
$form->add('slug', TextType::class);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$builder->add(
|
||||
$this->customFieldProvider
|
||||
->getCustomFieldByType($options['type'])
|
||||
->buildOptionsForm(
|
||||
$builder
|
||||
->create('options', null, array('compound' => true))
|
||||
->setRequired(false)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OptionsResolverInterface $resolver
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults(array(
|
||||
'data_class' => 'Chill\CustomFieldsBundle\Entity\CustomField'
|
||||
));
|
||||
|
||||
$resolver->setRequired(array('type', 'group_widget'))
|
||||
->addAllowedValues('type', array_keys($this->customFieldProvider->getAllFields()))
|
||||
->addAllowedValues('group_widget', array('hidden', 'entity'))
|
||||
->setDefault('group_widget', 'entity');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'custom_field_choice';
|
||||
}
|
||||
}
|
108
src/Bundle/ChillCustomFields/Form/CustomFieldsGroupType.php
Normal file
108
src/Bundle/ChillCustomFields/Form/CustomFieldsGroupType.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
|
||||
|
||||
|
||||
class CustomFieldsGroupType extends AbstractType
|
||||
{
|
||||
|
||||
|
||||
private $customizableEntities; //TODO : add comment about this variable
|
||||
|
||||
/**
|
||||
* @var \Symfony\Component\Translation\TranslatorInterface
|
||||
*/
|
||||
private $translator;
|
||||
|
||||
public function __construct(array $customizableEntities, TranslatorInterface $translator)
|
||||
{
|
||||
$this->customizableEntities = $customizableEntities;
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FormBuilderInterface $builder
|
||||
* @param array $options
|
||||
*/
|
||||
//TODO : details about the function
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
//prepare translation
|
||||
$entities = array();
|
||||
$customizableEntities = array(); //TODO : change name too close than $this->customizableEntities
|
||||
|
||||
foreach($this->customizableEntities as $key => $definition) {
|
||||
$entities[$definition['class']] = $this->translator->trans($definition['name']);
|
||||
$customizableEntities[$definition['class']] = $definition;
|
||||
}
|
||||
|
||||
$builder
|
||||
->add('name', TranslatableStringFormType::class)
|
||||
->add('entity', ChoiceType::class, array(
|
||||
'choices' => array_combine(array_values($entities),array_keys($entities)),
|
||||
))
|
||||
;
|
||||
|
||||
$builder->addEventListener(FormEvents::POST_SET_DATA,
|
||||
function(FormEvent $event) use ($customizableEntities, $builder){
|
||||
$form = $event->getForm();
|
||||
$group = $event->getData();
|
||||
|
||||
//stop the function if entity is not set
|
||||
if ($group->getEntity() === NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (count($customizableEntities[$group->getEntity()]['options']) > 0) {
|
||||
$optionBuilder = $builder
|
||||
->getFormFactory()
|
||||
->createBuilderForProperty(
|
||||
'Chill\CustomFieldsBundle\Entity\CustomFieldsGroup',
|
||||
'options'
|
||||
)
|
||||
->create('options', null, array(
|
||||
'compound' => true,
|
||||
'auto_initialize' => false,
|
||||
'required' => false)
|
||||
);
|
||||
}
|
||||
|
||||
foreach($customizableEntities[$group->getEntity()]['options'] as $key => $option) {
|
||||
$optionBuilder
|
||||
->add($key, $option['form_type'], $option['form_options'])
|
||||
;
|
||||
}
|
||||
if (isset($optionBuilder) && $optionBuilder->count() > 0) {
|
||||
$form->add($optionBuilder->getForm());
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OptionsResolverInterface $resolver
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults(array(
|
||||
'data_class' => 'Chill\CustomFieldsBundle\Entity\CustomFieldsGroup'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'custom_fields_group';
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Form\DataTransformer;
|
||||
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Chill\CustomFieldsBundle\CustomFields\CustomFieldInterface;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldDataTransformer implements DataTransformerInterface
|
||||
{
|
||||
private $customFieldDefinition;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Chill\CustomFieldsBundle\Entity\CustomField
|
||||
*/
|
||||
private $customField;
|
||||
|
||||
public function __construct(CustomFieldInterface $customFieldDefinition,
|
||||
CustomField $customField)
|
||||
{
|
||||
$this->customFieldDefinition = $customFieldDefinition;
|
||||
$this->customField = $customField;
|
||||
}
|
||||
|
||||
public function reverseTransform($value)
|
||||
{
|
||||
return $this->customFieldDefinition->serialize($value,
|
||||
$this->customField);
|
||||
}
|
||||
|
||||
public function transform($value)
|
||||
{
|
||||
return $this->customFieldDefinition->deserialize($value,
|
||||
$this->customField);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Form\DataTransformer;
|
||||
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
|
||||
|
||||
class CustomFieldsGroupToIdTransformer implements DataTransformerInterface
|
||||
{
|
||||
/**
|
||||
* @var ObjectManager
|
||||
*/
|
||||
private $om;
|
||||
|
||||
/**
|
||||
* @param ObjectManager $om
|
||||
*/
|
||||
public function __construct(ObjectManager $om)
|
||||
{
|
||||
$this->om = $om;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms an custom_field_group to a string (id)
|
||||
*
|
||||
* @param CustomFieldsGroup|null $customFieldsGroup
|
||||
* @return string
|
||||
*/
|
||||
public function transform($customFieldsGroup)
|
||||
{
|
||||
if (null === $customFieldsGroup) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (!$customFieldsGroup instanceof CustomFieldsGroup) {
|
||||
throw new TransformationFailedException(sprintf('Transformation failed: '
|
||||
. 'the expected type of the transforme function is an '
|
||||
. 'object of type Chill\CustomFieldsBundle\Entity\CustomFieldsGroup, '
|
||||
. '%s given (value : %s)', gettype($customFieldsGroup),
|
||||
$customFieldsGroup));
|
||||
}
|
||||
|
||||
return $customFieldsGroup->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a string (id) to an object (CustomFieldsGroup).
|
||||
*
|
||||
* @param string $id
|
||||
* @return CustomFieldsGroup|null
|
||||
* @throws TransformationFailedException if object (report) is not found.
|
||||
*/
|
||||
public function reverseTransform($id)
|
||||
{
|
||||
if (!$id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($id instanceof CustomFieldsGroup) {
|
||||
throw new TransformationFailedException(sprintf(
|
||||
'The transformation failed: the expected argument on '
|
||||
. 'reverseTransform is an object of type int,'
|
||||
. 'Chill\CustomFieldsBundle\Entity\CustomFieldsGroup, '
|
||||
. 'given', gettype($id)));
|
||||
}
|
||||
|
||||
$customFieldsGroup = $this->om
|
||||
->getRepository('ChillCustomFieldsBundle:customFieldsGroup')->find($id)
|
||||
;
|
||||
|
||||
if (null === $customFieldsGroup) {
|
||||
throw new TransformationFailedException(sprintf(
|
||||
'Le group avec le numéro "%s" ne peut pas être trouvé!',
|
||||
$id
|
||||
));
|
||||
}
|
||||
|
||||
return $customFieldsGroup;
|
||||
}
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Form\DataTransformer;
|
||||
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
||||
class JsonCustomFieldToArrayTransformer implements DataTransformerInterface {
|
||||
/**
|
||||
* @var ObjectManager
|
||||
*/
|
||||
private $om;
|
||||
|
||||
/**
|
||||
* @param ObjectManager $om
|
||||
*/
|
||||
public function __construct(ObjectManager $om)
|
||||
{
|
||||
$this->om = $om;
|
||||
|
||||
$customFields = $this->om
|
||||
->getRepository('ChillCustomFieldsBundle:CustomField')
|
||||
->findAll();
|
||||
|
||||
$customFieldsLablels = array_map(
|
||||
function($e) { return $e->getLabel(); },
|
||||
$customFields);
|
||||
|
||||
$customFieldsByLabel = array_combine($customFieldsLablels, $customFields);
|
||||
|
||||
$this->customField = $customFieldsByLabel;
|
||||
}
|
||||
|
||||
public function transform($customFieldsJSON)
|
||||
{
|
||||
echo $customFieldsJSON;
|
||||
|
||||
if($customFieldsJSON === null) { // lors de la creation
|
||||
$customFieldsArray = array();
|
||||
} else {
|
||||
$customFieldsArray = json_decode($customFieldsJSON,true);
|
||||
}
|
||||
|
||||
/*
|
||||
echo "<br> - 4 - <br>";
|
||||
|
||||
var_dump($customFieldsArray);
|
||||
|
||||
echo "<br> - 5 - <br>";
|
||||
*/
|
||||
|
||||
$customFieldsArrayRet = array();
|
||||
|
||||
foreach ($customFieldsArray as $key => $value) {
|
||||
$traited = false;
|
||||
if(array_key_exists($key, $this->customField)) {
|
||||
$type = $this->customField[$key]->getType();
|
||||
if(strpos($type,'ManyToOne') === 0) {
|
||||
if(strpos($type,'ManyToOnePersist') ===0) {
|
||||
$entityClass = substr($type, 17, -1);
|
||||
} else {
|
||||
$entityClass = substr($type, 10, -1);
|
||||
}
|
||||
|
||||
$customFieldsArrayRet[$key] = $this->om
|
||||
->getRepository('ChillCustomFieldsBundle:' . $entityClass)
|
||||
->findOneById($value);
|
||||
$traited = true;
|
||||
} else if ($type === 'ManyToMany(Adress)') {
|
||||
$customFieldsArrayRet[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if(! $traited) {
|
||||
$customFieldsArrayRet[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
var_dump($customFieldsArrayRet);
|
||||
|
||||
return $customFieldsArrayRet;
|
||||
}
|
||||
|
||||
public function reverseTransform($customFieldsArray)
|
||||
{
|
||||
/*
|
||||
echo "<br> - - 7 - <br>";
|
||||
|
||||
|
||||
var_dump(array_keys($customFieldsArray));
|
||||
|
||||
echo "<br> - - 8 - <br>";
|
||||
|
||||
var_dump(array_keys($this->customField));
|
||||
|
||||
echo "<br> - - 9 - <br>";
|
||||
*/
|
||||
|
||||
//var_dump($customFieldsArray);
|
||||
|
||||
$customFieldsArrayRet = array();
|
||||
|
||||
foreach ($customFieldsArray as $key => $value) {
|
||||
$traited = false;
|
||||
if(array_key_exists($key, $this->customField)) {
|
||||
$type = $this->customField[$key]->getType();
|
||||
if(strpos($type,'ManyToOne') === 0) {
|
||||
// pour le manytoone() faire
|
||||
// un update du form en js ? : http://symfony.com/fr/doc/current/cookbook/form/form_collections.html
|
||||
//
|
||||
//$entityClass = substr($type, 10, -1);
|
||||
//echo $entityClasss;
|
||||
if(strpos($type, 'ManyToOnePersist') === 0) {
|
||||
// PEUT ETRE A FAIRE SI SEULEMENT $value->getId() ne renvoie rien...
|
||||
//
|
||||
//
|
||||
$this->om->persist($value); // pas bon ici
|
||||
// LE PERSIST NE SERT QUE LA PREMIERE FOIS
|
||||
// plutot le mettre dans une var temporaire de adress
|
||||
// et faire le persist qd fait sur l'obj parent
|
||||
// regarder : http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html
|
||||
// ou : http://symfony.com/doc/current/cookbook/doctrine/event_listeners_subscribers.html
|
||||
// dans yml :
|
||||
// lifecycleCallbacks:
|
||||
// prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersist ]
|
||||
$this->om->flush(); // sinon l'id pose pbm
|
||||
}
|
||||
|
||||
$customFieldsArrayRet[$key] = $value->getId();
|
||||
$traited = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(! $traited) {
|
||||
$customFieldsArrayRet[$key] = $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//echo json_encode($customFieldsArrayRet);
|
||||
|
||||
return json_encode($customFieldsArrayRet);
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?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\CustomFieldsBundle\Form\Extension;
|
||||
|
||||
use Symfony\Component\Form\AbstractTypeExtension;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||
|
||||
/**
|
||||
* This extension create the possibility to add some text
|
||||
* after the input.
|
||||
*
|
||||
* This can be used to print the units of the field, or some text.
|
||||
*
|
||||
* This class must be extended by Extension class specifics to each input.
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
abstract class PostTextExtension extends AbstractTypeExtension
|
||||
{
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefined(array('post_text'));
|
||||
}
|
||||
|
||||
public function buildView(FormView $view, FormInterface $form, array $options)
|
||||
{
|
||||
if (array_key_exists('post_text', $options)) {
|
||||
//set the post text variable to the view
|
||||
$view->vars['post_text'] = $options['post_text'];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
<?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\CustomFieldsBundle\Form\Extension;
|
||||
|
||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||
|
||||
/**
|
||||
* This class add the PostTextExtension to integer fields
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class PostTextIntegerExtension extends PostTextExtension
|
||||
{
|
||||
public function getExtendedType()
|
||||
{
|
||||
return IntegerType::class;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
<?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\CustomFieldsBundle\Form\Extension;
|
||||
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
|
||||
/**
|
||||
* This class add the PostTextExtension to number fields
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class PostTextNumberExtension extends PostTextExtension
|
||||
{
|
||||
public function getExtendedType()
|
||||
{
|
||||
return NumberType::class;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
namespace Chill\CustomFieldsBundle\Form\Type;
|
||||
|
||||
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\TextType;
|
||||
|
||||
/**
|
||||
* Return a choice widget with an "other" option
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*
|
||||
*/
|
||||
class ChoiceWithOtherType extends AbstractType
|
||||
{
|
||||
private $otherValueLabel = 'Other value';
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see \Symfony\Component\Form\AbstractType::buildForm()
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
|
||||
//add an 'other' entry in choices array
|
||||
$options['choices'][$this->otherValueLabel] = '_other';
|
||||
//ChoiceWithOther must always be expanded
|
||||
$options['expanded'] = true;
|
||||
// adding a default value for choice
|
||||
$options['empty_data'] = null;
|
||||
|
||||
$builder
|
||||
->add('_other', TextType::class, array('required' => false))
|
||||
->add('_choices', ChoiceType::class, $options)
|
||||
;
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see \Symfony\Component\Form\AbstractType::configureOptions()
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver
|
||||
->setRequired(array('choices'))
|
||||
->setAllowedTypes('choices', array('array'))
|
||||
->setDefaults(array(
|
||||
'multiple' => false
|
||||
))
|
||||
;
|
||||
}
|
||||
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'choice_with_other';
|
||||
}
|
||||
}
|
55
src/Bundle/ChillCustomFields/Form/Type/ChoicesListType.php
Normal file
55
src/Bundle/ChillCustomFields/Form/Type/ChoicesListType.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
namespace Chill\CustomFieldsBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
|
||||
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
|
||||
|
||||
class ChoicesListType extends AbstractType
|
||||
{
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see \Symfony\Component\Form\AbstractType::buildForm()
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->add('name', TranslatableStringFormType::class)
|
||||
->add('active', CheckboxType::class, array(
|
||||
'required' => false
|
||||
))
|
||||
->add('slug', HiddenType::class)
|
||||
->addEventListener(FormEvents::SUBMIT, function(FormEvent $event) {
|
||||
$form = $event->getForm();
|
||||
$data = $event->getData();
|
||||
|
||||
$formData = $form->getData();
|
||||
|
||||
if (NULL === $formData['slug']) {
|
||||
$slug = uniqid(rand(), true);
|
||||
|
||||
$data['slug'] = $slug;
|
||||
$event->setData($data);
|
||||
} else {
|
||||
$data['slug'] = $formData['slug'];
|
||||
$event->setData($data);
|
||||
}
|
||||
})
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* @see \Symfony\Component\Form\FormTypeInterface::getName()
|
||||
*/
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'cf_choices_list';
|
||||
}
|
||||
|
||||
}
|
24
src/Bundle/ChillCustomFields/Form/Type/ChoicesType.php
Normal file
24
src/Bundle/ChillCustomFields/Form/Type/ChoicesType.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
namespace Chill\CustomFieldsBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*
|
||||
*/
|
||||
class ChoicesType extends AbstractType
|
||||
{
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'cf_choices';
|
||||
}
|
||||
|
||||
public function getParent()
|
||||
{
|
||||
return CollectionType::class;
|
||||
}
|
||||
}
|
71
src/Bundle/ChillCustomFields/Form/Type/CustomFieldType.php
Normal file
71
src/Bundle/ChillCustomFields/Form/Type/CustomFieldType.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Chill\CustomFieldsBundle\Form\DataTransformer\JsonCustomFieldToArrayTransformer;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use Chill\CustomFieldsBundle\Form\AdressType;
|
||||
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
|
||||
use Chill\CustomFieldsBundle\Form\DataTransformer\CustomFieldDataTransformer;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Chill\CustomFieldsBundle\CustomFields\CustomFieldTitle;
|
||||
|
||||
class CustomFieldType extends AbstractType
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ObjectManager
|
||||
*/
|
||||
private $om;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var CustomFieldCompiler
|
||||
*/
|
||||
private $customFieldCompiler;
|
||||
|
||||
/**
|
||||
* @param ObjectManager $om
|
||||
*/
|
||||
public function __construct(ObjectManager $om, CustomFieldProvider $compiler)
|
||||
{
|
||||
$this->om = $om;
|
||||
$this->customFieldCompiler = $compiler;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
foreach ($options['group']->getActiveCustomFields() as $cf) {
|
||||
$this->customFieldCompiler
|
||||
->getCustomFieldByType($cf->getType())
|
||||
->buildForm($builder, $cf);
|
||||
$builder->get($cf->getSlug())->setRequired($cf->isRequired());
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(\Symfony\Component\OptionsResolver\OptionsResolver $resolver)
|
||||
{
|
||||
$resolver
|
||||
->setRequired(array('group'))
|
||||
->addAllowedTypes('group', array('Chill\CustomFieldsBundle\Entity\CustomFieldsGroup'))
|
||||
;
|
||||
}
|
||||
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'custom_field';
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<?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\CustomFieldsBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class CustomFieldsTitleType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'custom_field_title';
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 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\CustomFieldsBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormEvent;
|
||||
use Symfony\Component\Form\FormEvents;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
|
||||
/**
|
||||
* This type create a Choice field with custom fields as choices.
|
||||
*
|
||||
* This type can only be associated with a customFieldsGroup type. The field
|
||||
* is populated when the data (a customFieldsGroup entity) is associated with
|
||||
* the form
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class LinkedCustomFieldsType extends AbstractType
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var TranslatableStringHelper
|
||||
*/
|
||||
private $translatableStringHelper;
|
||||
|
||||
/**
|
||||
* The name for the choice field
|
||||
*
|
||||
* Extracted from builder::getName
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $choiceName = 'choice';
|
||||
|
||||
/**
|
||||
* the option of the form.
|
||||
*
|
||||
* @internal options are stored at the class level to be reused by appendChoice, after data are setted
|
||||
* @var array
|
||||
*/
|
||||
private $options = array();
|
||||
|
||||
public function __construct(TranslatableStringHelper $helper)
|
||||
{
|
||||
$this->translatableStringHelper = $helper;
|
||||
}
|
||||
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$this->choiceName = $builder->getName();
|
||||
$this->options = $options;
|
||||
|
||||
$builder->addEventListener(FormEvents::POST_SET_DATA,
|
||||
array($this, 'appendChoice'))
|
||||
;
|
||||
}
|
||||
|
||||
public function getParent()
|
||||
{
|
||||
return ChoiceType::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* append Choice on POST_SET_DATA event
|
||||
*
|
||||
* Choices are extracted from custom_field_group (the data associated
|
||||
* with the root form)
|
||||
*
|
||||
* @param FormEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function appendChoice(FormEvent $event)
|
||||
{
|
||||
$rootForm = $this->getRootForm($event->getForm());
|
||||
$group = $rootForm->getData();
|
||||
|
||||
if ($group === NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
$choices = array();
|
||||
foreach($group->getCustomFields() as $customFields) {
|
||||
$choices[$customFields->getSlug()] =
|
||||
$this->translatableStringHelper
|
||||
->localize($customFields->getName());
|
||||
}
|
||||
|
||||
$options = array_merge($this->options, array(
|
||||
'choices' => $choices,
|
||||
));
|
||||
|
||||
$event->getForm()->getParent()->add($this->choiceName, ChoiceType::class,
|
||||
$options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the root form (i.e. produced from CustomFieldsGroupType::getForm)
|
||||
*
|
||||
* @param FormInterface $form
|
||||
* @return FormInterface
|
||||
*/
|
||||
private function getRootForm(FormInterface $form)
|
||||
{
|
||||
if ($form->getParent() === NULL) {
|
||||
return $form;
|
||||
} else {
|
||||
return $this->getRootForm($form->getParent());
|
||||
}
|
||||
}
|
||||
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return 'custom_fields_group_linked_custom_fields';
|
||||
}
|
||||
|
||||
}
|
661
src/Bundle/ChillCustomFields/LICENSE.txt
Normal file
661
src/Bundle/ChillCustomFields/LICENSE.txt
Normal file
@ -0,0 +1,661 @@
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
9
src/Bundle/ChillCustomFields/README.md
Normal file
9
src/Bundle/ChillCustomFields/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
CustomFields
|
||||
============
|
||||
|
||||
The bundle for adding custom fields to Chill. This bundle is part of the Chill project.
|
||||
|
||||
Documentation & installation
|
||||
============================
|
||||
|
||||
Read documentation here : http://chill.readthedocs.org
|
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\HttpKernel\Kernel;
|
||||
use Symfony\Component\Config\Loader\LoaderInterface;
|
||||
|
||||
class AppKernel extends Kernel
|
||||
{
|
||||
public function registerBundles()
|
||||
{
|
||||
return array(
|
||||
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
|
||||
new Chill\CustomFieldsBundle\ChillCustomFieldsBundle(),
|
||||
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
|
||||
new Symfony\Bundle\MonologBundle\MonologBundle(),
|
||||
new Symfony\Bundle\TwigBundle\TwigBundle(),
|
||||
new \Symfony\Bundle\AsseticBundle\AsseticBundle(),
|
||||
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
|
||||
new \Chill\MainBundle\ChillMainBundle,
|
||||
new \Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(),
|
||||
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(),
|
||||
new Chill\PersonBundle\ChillPersonBundle(),
|
||||
#add here all the required bundle (some bundle are not required)
|
||||
);
|
||||
}
|
||||
|
||||
public function registerContainerConfiguration(LoaderInterface $loader)
|
||||
{
|
||||
$loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCacheDir()
|
||||
{
|
||||
return sys_get_temp_dir().'/CustomFieldsBundle/cache';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLogDir()
|
||||
{
|
||||
return $this->getRootDir().'/../logs';
|
||||
}
|
||||
}
|
||||
|
2
src/Bundle/ChillCustomFields/Resources/test/Fixtures/App/app/DoctrineMigrations/.gitignore
vendored
Normal file
2
src/Bundle/ChillCustomFields/Resources/test/Fixtures/App/app/DoctrineMigrations/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
@ -0,0 +1,7 @@
|
||||
{% if inputKeys is defined %}
|
||||
{% for key in inputKeys %}
|
||||
{{ form_row(form[key]) }}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{{ form(form) }}
|
||||
{% endif %}
|
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>{% block title %}Welcome!{% endblock %}</title>
|
||||
{% block stylesheets %}{% endblock %}
|
||||
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
|
||||
{% block javascripts_head %}<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
{% block body %}{% endblock %}
|
||||
{% block javascripts %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
use Doctrine\Common\Annotations\AnnotationRegistry;
|
||||
use Composer\Autoload\ClassLoader;
|
||||
|
||||
/** @var ClassLoader $loader */
|
||||
$loader = require __DIR__.'/../../../../../vendor/autoload.php';
|
||||
|
||||
AnnotationRegistry::registerLoader(array($loader, 'loadClass'));
|
||||
|
||||
return $loader;
|
@ -0,0 +1,76 @@
|
||||
imports:
|
||||
- { resource: parameters.yml }
|
||||
|
||||
framework:
|
||||
secret: Not very secret
|
||||
router: { resource: "%kernel.root_dir%/config/routing.yml" }
|
||||
form: true
|
||||
csrf_protection: true
|
||||
session: ~
|
||||
default_locale: fr
|
||||
translator: { fallback: fr }
|
||||
profiler: { only_exceptions: false }
|
||||
templating:
|
||||
engines: ['twig']
|
||||
|
||||
doctrine:
|
||||
dbal:
|
||||
driver: pdo_pgsql
|
||||
host: "%database_host%"
|
||||
port: "%database_port%"
|
||||
dbname: "%database_name%"
|
||||
user: "%database_user%"
|
||||
password: "%database_password%"
|
||||
charset: UTF8
|
||||
orm:
|
||||
auto_generate_proxy_classes: "%kernel.debug%"
|
||||
auto_mapping: true
|
||||
|
||||
# Assetic Configuration
|
||||
assetic:
|
||||
debug: "%kernel.debug%"
|
||||
use_controller: false
|
||||
bundles: [ ]
|
||||
#java: /usr/bin/java
|
||||
filters:
|
||||
cssrewrite: ~
|
||||
|
||||
chill_main:
|
||||
available_languages: [ fr, nl, en ]
|
||||
|
||||
security:
|
||||
providers:
|
||||
chain_provider:
|
||||
chain :
|
||||
providers: [in_memory, users]
|
||||
in_memory:
|
||||
memory:
|
||||
users:
|
||||
admin: { password: olala, roles: 'ROLE_ADMIN' }
|
||||
users:
|
||||
entity:
|
||||
class: Chill\MainBundle\Entity\User
|
||||
property: username
|
||||
|
||||
encoders:
|
||||
Chill\MainBundle\Entity\User:
|
||||
algorithm: bcrypt
|
||||
Symfony\Component\Security\Core\User\User: plaintext
|
||||
|
||||
firewalls:
|
||||
dev:
|
||||
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||
security: false
|
||||
|
||||
default:
|
||||
anonymous: ~
|
||||
form_login:
|
||||
csrf_parameter: _csrf_token
|
||||
csrf_token_id: authenticate
|
||||
csrf_provider: form.csrf_provider
|
||||
logout: ~
|
||||
access_control:
|
||||
#disable authentication for tests
|
||||
#- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||
#- { path: ^/admin, roles: ROLE_ADMIN }
|
||||
#- { path: ^/, roles: ROLE_USER }
|
@ -0,0 +1,11 @@
|
||||
imports:
|
||||
- { resource: config.yml } #here we import a config.yml file, this is not required
|
||||
|
||||
framework:
|
||||
test: ~
|
||||
session:
|
||||
storage_id: session.storage.filesystem
|
||||
|
||||
chill_custom_fields:
|
||||
customizables_entities:
|
||||
- { class: TEST, name: test }
|
@ -0,0 +1,8 @@
|
||||
# config/config_test.yml
|
||||
imports:
|
||||
- { resource: config.yml } #here we import a config.yml file, this is not required
|
||||
|
||||
framework:
|
||||
test: ~
|
||||
session:
|
||||
storage_id: session.storage.filesystem
|
@ -0,0 +1,9 @@
|
||||
|
||||
#required by ConfigCustomizablesEntitiesTest::testNotEmptyConfig
|
||||
|
||||
imports:
|
||||
- { resource: config_test.yml }
|
||||
|
||||
chill_custom_fields:
|
||||
customizables_entities:
|
||||
- { class: Test\With\A\Dummy\Entity, name: test }
|
@ -0,0 +1,7 @@
|
||||
parameters:
|
||||
database_host: chill__database
|
||||
database_port: 5432
|
||||
database_name: postgres
|
||||
database_user: postgres
|
||||
database_password: postgres
|
||||
locale: fr
|
@ -0,0 +1,7 @@
|
||||
parameters:
|
||||
database_host: 127.0.0.1
|
||||
database_port: 5434
|
||||
database_name: symfony
|
||||
database_user: symfony
|
||||
database_password: symfony
|
||||
locale: fr
|
@ -0,0 +1,10 @@
|
||||
cl_custom_fields:
|
||||
resource: .
|
||||
type: chill_routes
|
||||
|
||||
chill_main:
|
||||
resource: "@ChillMainBundle/Resources/config/routing.yml"
|
||||
|
||||
test_custom_field_form_render:
|
||||
path: /customfieldsgroup/test/render/{id}
|
||||
defaults: { _controller: ChillCustomFieldsBundle:CustomFieldsGroup:renderForm }
|
@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Debug\Debug;
|
||||
|
||||
// if you don't want to setup permissions the proper way, just uncomment the following PHP line
|
||||
// read https://symfony.com/doc/current/setup.html#checking-symfony-application-configuration-and-setup
|
||||
// for more information
|
||||
//umask(0000);
|
||||
|
||||
set_time_limit(0);
|
||||
|
||||
require __DIR__.'/autoload.php';
|
||||
|
||||
$input = new ArgvInput();
|
||||
$env = $input->getParameterOption(array('--env', '-e'), getenv('SYMFONY_ENV') ?: 'dev');
|
||||
$debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(array('--no-debug', '')) && $env !== 'prod';
|
||||
|
||||
if ($debug) {
|
||||
Debug::enable();
|
||||
}
|
||||
|
||||
$kernel = new AppKernel($env, $debug);
|
||||
$application = new Application($kernel);
|
||||
$application->run($input);
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Debug\Debug;
|
||||
|
||||
// If you don't want to setup permissions the proper way, just uncomment the following PHP line
|
||||
// read http://symfony.com/doc/current/book/installation.html#configuration-and-setup for more information
|
||||
//umask(0000);
|
||||
|
||||
// This check prevents access to debug front controllers that are deployed by accident to production servers.
|
||||
// Feel free to remove this, extend it, or make something more sophisticated.
|
||||
if (isset($_SERVER['HTTP_CLIENT_IP'])
|
||||
|| isset($_SERVER['HTTP_X_FORWARDED_FOR'])
|
||||
|| !(in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', 'fe80::1', '::1')) || php_sapi_name() === 'cli-server')
|
||||
) {
|
||||
header('HTTP/1.0 403 Forbidden');
|
||||
exit('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.');
|
||||
}
|
||||
|
||||
$loader = require_once __DIR__.'/../app/bootstrap.php.cache';
|
||||
Debug::enable();
|
||||
|
||||
require_once __DIR__.'/../app/AppKernel.php';
|
||||
|
||||
$kernel = new AppKernel('dev', true);
|
||||
$kernel->loadClassCache();
|
||||
$request = Request::createFromGlobals();
|
||||
$response = $kernel->handle($request);
|
||||
$response->send();
|
||||
$kernel->terminate($request, $response);
|
@ -0,0 +1,31 @@
|
||||
{#
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
<info@champs-libres.coop> / <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/>.
|
||||
#}
|
||||
|
||||
{% extends "@ChillMain/Admin/layoutWithVerticalMenu.html.twig" %}
|
||||
|
||||
{% block vertical_menu_content %}
|
||||
{{ chill_menu('admin_custom_fields', {
|
||||
'layout': '@ChillCustomFields/Admin/menu.html.twig',
|
||||
}) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block layout_wvm_content %}
|
||||
{% block admin_content %}<!-- block personcontent empty -->
|
||||
<h1>{{ 'CustomFields configuration' |trans }}</h1>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
@ -0,0 +1,20 @@
|
||||
{#
|
||||
* Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
|
||||
<info@champs-libres.coop> / <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/>.
|
||||
#}
|
||||
|
||||
{% extends "@ChillMain/Menu/verticalMenu.html.twig" %}
|
||||
{% block v_menu_title %}{{ 'Custom fields configuration menu'|trans }}{% endblock %}
|
@ -0,0 +1,49 @@
|
||||
{#
|
||||
* 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/>.
|
||||
#}
|
||||
{% extends "@ChillCustomFields/Admin/layout.html.twig" %}
|
||||
|
||||
{% block title %}{{ 'CustomField edit'|trans }}{% endblock title %}
|
||||
|
||||
{% block admin_content %}
|
||||
<h1>{{ 'CustomField edit'|trans }}</h1>
|
||||
|
||||
<h2>{{ 'General informations'|trans }}</h2>
|
||||
{{ form_start(edit_form) }}
|
||||
{{ form_row(edit_form.name) }}
|
||||
{{ form_row(edit_form.active) }}
|
||||
{% if edit_form.customFieldsGroup is defined %}
|
||||
{{ form_row(edit_form.customFieldsGroup) }}
|
||||
{% endif %}
|
||||
{{ form_row(edit_form.ordering) }}
|
||||
{{ form_row(edit_form.required) }}
|
||||
{% if edit_form.options is not empty %}
|
||||
<h2>{{ 'Options'|trans }}</h2>
|
||||
{% for option in edit_form.options %}
|
||||
{{ form_row(option) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{{ form_row(edit_form.submit, {'attr': { 'class': 'sc-button btn-update' } } ) }}
|
||||
{{ form_end(edit_form) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('customfieldsgroup_show', { 'id': entity.customFieldsGroup.id }) }}" class="sc-button btn-reset">
|
||||
{{ 'Back to the group'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
@ -0,0 +1,7 @@
|
||||
{% extends '::base.html.twig' %}
|
||||
|
||||
{% block javascripts_head %}<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>{% endblock %}
|
||||
|
||||
{% block body -%}
|
||||
{{ form(form) }}
|
||||
{% endblock %}
|
@ -0,0 +1,56 @@
|
||||
{#
|
||||
* 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/>.
|
||||
#}
|
||||
{% extends "@ChillCustomFields/Admin/layout.html.twig" %}
|
||||
|
||||
{% block title %}{{ 'CustomField creation'|trans }}{% endblock title %}
|
||||
|
||||
{% block admin_content %}
|
||||
<h1>{{ 'CustomField creation'|trans }}</h1>
|
||||
|
||||
<h2>{{ 'General informations'|trans }}</h2>
|
||||
{{ form_start(form) }}
|
||||
{{ form_row(form.name) }}
|
||||
{{ form_row(form.active) }}
|
||||
{{ form_row(form.slug) }}
|
||||
{% if form.customFieldsGroup is defined %}
|
||||
{{ form_row(form.customFieldsGroup) }}
|
||||
{% endif %}
|
||||
{{ form_row(form.ordering) }}
|
||||
{{ form_row(form.required) }}
|
||||
{% if form.options is not empty %}
|
||||
<h2>{{ 'Options'|trans }}</h2>
|
||||
{% for option in form.options %}
|
||||
{{ form_row(option) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{{ form_row(form.submit, {'attr': { 'class': 'sc-button btn-create' } } ) }}
|
||||
{{ form_end(form) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
{% if entity.customFieldsGroup is not null %}
|
||||
<a href="{{ path('customfieldsgroup_show', { 'id': entity.customFieldsGroup.id }) }}" class="sc-button btn-reset">
|
||||
{{ 'Back to the group'|trans }}
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{{ path('customfieldsgroup') }}" class="sc-button btn-reset">
|
||||
{{ 'Back to the list'|trans }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
@ -0,0 +1 @@
|
||||
{{ customField.name|localize_translatable_string }}
|
@ -0,0 +1,56 @@
|
||||
{#
|
||||
* 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/>.
|
||||
#}
|
||||
{% extends "@ChillCustomFields/Admin/layout.html.twig" %}
|
||||
|
||||
{% block admin_content %}
|
||||
<h1>CustomField</h1>
|
||||
|
||||
<table class="record_properties">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td>{{ entity.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Label</th>
|
||||
<td>{{ entity.name(app.request.locale) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<td>{{ entity.type }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Active</th>
|
||||
<td>{{ entity.active }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('customfield') }}">
|
||||
Back to the list
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('customfield_edit', { 'id': entity.id }) }}">
|
||||
Edit
|
||||
</a>
|
||||
</li>
|
||||
<li>{{ form(delete_form) }}</li>
|
||||
</ul>
|
||||
{% endblock %}
|
@ -0,0 +1,45 @@
|
||||
{#
|
||||
* 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/>.
|
||||
#}
|
||||
{% extends "@ChillCustomFields/Admin/layout.html.twig" %}
|
||||
|
||||
{% block title %}{{ 'CustomFieldsGroup edit'|trans }}{% endblock %}
|
||||
|
||||
{% block admin_content %}
|
||||
<h1>{{ 'CustomFieldsGroup edit'|trans }}</h1>
|
||||
|
||||
{{ form_start(edit_form) }}
|
||||
{{ form_row(edit_form.name) }}
|
||||
{{ form_row(edit_form.entity) }}
|
||||
{% if edit_form.options is defined %}
|
||||
{{ form_row(edit_form.options) }}
|
||||
{% endif %}
|
||||
{{ form_row(edit_form.submit, { 'attr': { 'class': 'sc-button bt-edit' } } ) }}
|
||||
{{ form_end(edit_form) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('customfieldsgroup') }}" class="sc-button bt-cancel">
|
||||
{{ 'Back to the list'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('customfieldsgroup_show', { 'id' : entity.id }) }}" class="sc-button bt-cancel">
|
||||
{{ 'show'|trans|capitalize }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
@ -0,0 +1,67 @@
|
||||
{#
|
||||
* 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/>.
|
||||
#}
|
||||
{% extends "@ChillCustomFields/Admin/layout.html.twig" %}
|
||||
|
||||
{% block title %}{{ 'CustomFieldsGroup list'|trans }}{% endblock %}
|
||||
|
||||
{% block admin_content %}
|
||||
<h1>{{ 'CustomFieldsGroup list'|trans }}</h1>
|
||||
|
||||
<table class="records_list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'Name'|trans }}</th>
|
||||
<th>{{ 'Entity'|trans }}</th>
|
||||
<th>{{ 'Is default ?'|trans }} <i class="fa fa-info-circle" title="{{ 'Some module select default groups for some usage. Example: the default person group is shown under person page.'|trans|escape('html_attr') }}"></i></th>
|
||||
<th>{{ 'Actions'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for entity in entities %}
|
||||
<tr>
|
||||
<td><a href="{{ path('customfieldsgroup_show', { 'id': entity.id }) }}">{{ entity.name|localize_translatable_string }}</a></td>
|
||||
<td>{{ entity.entity|trans }}</td>
|
||||
<td style="text-align: center;">
|
||||
{%- if entity.id in default_groups -%}
|
||||
<i class="fa fa-star"></i>
|
||||
{%- else -%}
|
||||
{{ form_start(make_default_forms[entity.id]) }}
|
||||
{{ form_widget(make_default_forms[entity.id].submit, { 'attr' : { 'class' : 'sc-button bt-action' } } ) }}
|
||||
{{ form_end(make_default_forms[entity.id]) }}
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('customfieldsgroup_show', { 'id': entity.id }) }}" class="sc-button">{{ 'show'|trans|capitalize }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('customfieldsgroup_edit', { 'id': entity.id }) }}" class="sc-button btn-edit">{{ 'edit'|trans|capitalize }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
<a href="{{ path('customfieldsgroup_new') }}" class="sc-button bt-create">
|
||||
{{ 'Create a new group'|trans }}
|
||||
</a>
|
||||
</p>
|
||||
{% endblock %}
|
@ -0,0 +1,32 @@
|
||||
{#
|
||||
* 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/>.
|
||||
#}
|
||||
{% extends "@ChillCustomFields/Admin/layout.html.twig" %}
|
||||
|
||||
{% block admin_content %}
|
||||
<h1>{{ 'CustomFieldsGroup creation'|trans }}</h1>
|
||||
|
||||
{{ form_start(form) }}
|
||||
{{ form_row(form.name) }}
|
||||
{{ form_row(form.entity) }}
|
||||
<p>
|
||||
{{ form_widget(form.submit, { 'attr' : { 'class': 'sc-button bt-create' } } ) }}
|
||||
<a href="{{ path('customfieldsgroup') }}" class="sc-button bt-cancel">
|
||||
{{ 'Back to the list'|trans }}
|
||||
</a>
|
||||
</p>
|
||||
{{ form_end(form) }}
|
||||
{% endblock %}
|
@ -0,0 +1,86 @@
|
||||
{#- a customField element will be stored in title variable -#}
|
||||
{%- set title = null -%}
|
||||
{#- a customField element will be stored in subtitle variable -#}
|
||||
{%- set subtitle = null -%}
|
||||
{%- set type = constant('Chill\\CustomFieldsBundle\\CustomFields\\CustomFieldTitle::TYPE') -%}
|
||||
{%- set type_subtitle = constant('Chill\\CustomFieldsBundle\\CustomFields\\CustomFieldTitle::TYPE_SUBTITLE') -%}
|
||||
{%- set type_title = constant('Chill\\CustomFieldsBundle\\CustomFields\\CustomFieldTitle::TYPE_TITLE') -%}
|
||||
{# a variable to store that "something has been printed #}
|
||||
{%- set something_has_been_printed = false -%}
|
||||
{%- set title_div_opened = false -%}
|
||||
{%- set subtitle_div_opened = false -%}
|
||||
{% for customField in cFGroup.activeCustomFields %}
|
||||
{% if customField.type == 'title' %}
|
||||
{%- if show_empty == true %}
|
||||
{%- if customField.options[type] == type_title -%}
|
||||
{%- if title_div_opened == false -%}
|
||||
<div class="cf_title_box">
|
||||
{%- set title_div_opened = true -%}
|
||||
{%- else -%}
|
||||
{%- if subtitle_div_opened == true -%}
|
||||
</div> <!-- closing cf_subtitle_box -->
|
||||
{%- set title_div_opened = false -%}
|
||||
{%- endif -%}
|
||||
</div><div class="cf_title_box">
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
{%- if subtitle_div_opened == false -%}
|
||||
<div class="cf_subtitle_box">
|
||||
{%- set subtitle_div_opened = true -%}
|
||||
{%- else -%}
|
||||
</div><div class="cf_subtitle_box">
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{{ chill_custom_field_widget(cFData , customField) }}
|
||||
{%- else -%}
|
||||
{# we keep the customfield in memory, and print it only if 'something' has been filled after the title #}
|
||||
{%- if customField.options[type] == type_title -%}
|
||||
{%- set title = customField -%}
|
||||
{# we have to reset the title hierarchy if we misused titles hierarchy #}
|
||||
{%- set subtitle = null -%}
|
||||
{%- elseif customField.options[type] == type_subtitle -%}
|
||||
{%- set subtitle = customField -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{% else %}
|
||||
{%- if show_empty == true or (chill_custom_field_is_empty(cFData, customField) == false) -%}
|
||||
{%- if title is not empty -%}
|
||||
{%- if title_div_opened == false -%}
|
||||
<div class="cf_title_box">
|
||||
{%- set title_div_opened = true -%}
|
||||
{%- else -%}
|
||||
{%- if subtitle_div_opened == true -%}
|
||||
</div> <!-- closing cf_subtitle_box -->
|
||||
{%- set title_div_opened = false -%}
|
||||
{%- endif -%}
|
||||
</div><div class="cf_title_box">
|
||||
{%- endif -%}
|
||||
{{ chill_custom_field_widget(cFData, title) }}
|
||||
{%- set title = null -%}
|
||||
{%- endif -%}
|
||||
{%- if subtitle is not empty -%}
|
||||
{%- if subtitle_div_opened == false -%}
|
||||
<div class="cf_subtitle_box">
|
||||
{%- set subtitle_div_opened = true -%}
|
||||
{%- else -%}
|
||||
</div><div class="cf_subtitle_box">
|
||||
{%- endif -%}
|
||||
{{ chill_custom_field_widget(cFData, subtitle) }}
|
||||
{%- set subtitle = null -%}
|
||||
{%- endif -%}
|
||||
<dt class="custom_fields_group_rendering">{{ chill_custom_field_label(customField) }}</dt>
|
||||
<dd class="custom_fields_group_rendering">{{ chill_custom_field_widget(cFData , customField) }}</dd>
|
||||
{%- set something_has_been_printed = true -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{% endfor %}
|
||||
{%- if subtitle_div_opened == true -%}
|
||||
</div> <!-- closing cf_subtitle_box -->
|
||||
{%- endif -%}
|
||||
{%- if title_div_opened == true -%}
|
||||
</div> <!-- closing cf_title_box -->
|
||||
{%- endif -%}
|
||||
{% if something_has_been_printed == false %}
|
||||
<dt class="custom_field_no_data custom_fields_group_rendering">{{ 'Empty data'|trans }}</dt>
|
||||
<dd class="custom_field_no_data custom_fields_group_rendering">{{ 'No data to show' | trans }}</dd>
|
||||
{% endif %}
|
@ -0,0 +1,7 @@
|
||||
<dl class="custom_fields_group_rendering">
|
||||
<span class="custom_fields_group_name">{{ customFieldsGroup.name(app.request.locale) }}</span>
|
||||
{% for customField in customFieldsGroup.customFields %}
|
||||
<dt>{{ chill_custom_field_label(customField) }}</dt>
|
||||
<dd>{{ chill_custom_field_widget(fields, customField) }}</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
@ -0,0 +1,116 @@
|
||||
{#
|
||||
* 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/>.
|
||||
#}
|
||||
{% extends "@ChillCustomFields/Admin/layout.html.twig" %}
|
||||
|
||||
{% block title %}{{ 'CustomFieldsGroup details'|trans }}{% endblock %}
|
||||
|
||||
{% block admin_content %}
|
||||
<h1>{{ 'CustomFieldsGroup details'|trans }}</h1>
|
||||
|
||||
<table class="record_properties">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{{ 'Name'|trans }}</th>
|
||||
<td>{{ entity.getName|localize_translatable_string }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ 'Entity'|trans }}</th>
|
||||
<td>{{ entity.entity|trans }}</td>
|
||||
</tr>
|
||||
{%- for key in options -%}
|
||||
<tr>
|
||||
<th>{{ key ~ '_label'|trans }}</th>
|
||||
<td>
|
||||
{%- if entity.options[key] is not defined -%}
|
||||
{{ 'No value defined for this option'|trans }}
|
||||
{%- elseif entity.options[key] is iterable -%}
|
||||
{{ entity.options[key]|join(', ') }}
|
||||
{% else %}
|
||||
{{ entity.options[key] }}
|
||||
{%- endif -%}
|
||||
</td>
|
||||
</tr>
|
||||
{%- else -%}
|
||||
<!-- no option available for this entity -->
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('customfieldsgroup') }}" class="sc-button bt-cancel">
|
||||
{{ 'Back to the list'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('customfieldsgroup_edit', { 'id': entity.id }) }}" class="sc-button bt-edit">
|
||||
{{ 'Edit'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>{{ 'Fields associated with this group'|trans }}</h2>
|
||||
|
||||
{%- if entity.customFields|length > 0 -%}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'ordering'|trans|capitalize }}</th>
|
||||
<th>{{ 'label_field'|trans|capitalize }}</th>
|
||||
<th>{{ 'type'|trans|capitalize }}</th>
|
||||
<th>{{ 'active'|trans|capitalize }}</th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%- for field in entity.customFields -%}
|
||||
<tr>
|
||||
<td>{{ field.ordering }}</td>
|
||||
<td>{{ field.name|localize_translatable_string }}</td>
|
||||
<td>{{ field.type|trans }}</td>
|
||||
<td style="text-align:center;">
|
||||
{%- if field.active -%}
|
||||
<i class="fa fa-check-square-o"></i>
|
||||
{%- else -%}
|
||||
<i class="fa fa-square-o"></i>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td style="text-align:center">
|
||||
<a href="{{ path('customfield_edit', { 'id' : field.id }) }}" class="sc-button bt-edit">{{ 'edit'|trans|capitalize }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ form_start(create_field_form) }}
|
||||
<div class="grid-4">
|
||||
{{ form_widget(create_field_form.type) }}
|
||||
</div>
|
||||
{{ form_widget(create_field_form.submit, { 'attr': { 'class': 'sc-button bt-create' }, 'label': 'Add a new field' } ) }}
|
||||
{{ form_end(create_field_form) }}
|
||||
{%- else -%}
|
||||
<p>
|
||||
{{ 'Any field is currently associated with this group'|trans }}
|
||||
</p>
|
||||
{{ form_start(create_field_form) }}
|
||||
<div class="grid-4">
|
||||
{{ form_widget(create_field_form.type) }}
|
||||
</div>
|
||||
{{ form_widget(create_field_form.submit, { 'attr': { 'class': 'sc-button bt-create' }, 'label': 'Create a new field' } ) }}
|
||||
{{ form_end(create_field_form) }}
|
||||
{%- endif -%}
|
||||
{% endblock %}
|
@ -0,0 +1,13 @@
|
||||
{% if selected|length > 0 %}
|
||||
{%- for choice in choices -%}
|
||||
{% if choice['slug'] in selected %}
|
||||
{%- if choice['slug'] is not same as('_other') -%}
|
||||
{{ choice['name']|localize_translatable_string|csv_cell }}
|
||||
{%- else -%}
|
||||
{{ choice['name']|csv_cell }}
|
||||
{%- endif -%}
|
||||
{% endif %}
|
||||
{%- endfor -%}
|
||||
{% else %}
|
||||
{{ 'None'|trans }}
|
||||
{% endif %}
|
@ -0,0 +1,29 @@
|
||||
{% if selected|length > 0 %}
|
||||
<ul class="custom_fields choice">
|
||||
{%- for choice in choices -%}
|
||||
{% if choice['slug'] in selected %}
|
||||
{%- set is_selected = true -%}
|
||||
{%- else -%}
|
||||
{%- set is_selected = false -%}
|
||||
{%- endif -%}
|
||||
|
||||
{%- if is_selected -%}
|
||||
<li class="{% if is_selected or expanded == 1 %} selected {% endif %}">
|
||||
{%- if is_selected -%}
|
||||
<i class="fa fa-check-square-o"></i>
|
||||
{%- else -%}
|
||||
<i class="fa fa-square-o"></i>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if choice['slug'] is not same as('_other') -%}
|
||||
{{ choice['name']|localize_translatable_string }}
|
||||
{%- else -%}
|
||||
{{ choice['name'] }}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
{% else %}
|
||||
<div class="custom_fields_choice empty">{{ 'None'|trans }}</div>
|
||||
{% endif %}
|
@ -0,0 +1 @@
|
||||
{% if values|length == 1 %}{{ values[0].text|localize_translatable_string|default("")|csv_cell }}{% elseif values|length ==0 %}{{ 'emtpy'|csv_cell }}{% else %}{{ 'pas de rendu multiple'|csv_cell }}{% endif %}
|
@ -0,0 +1,11 @@
|
||||
{% if values|length > 0 %}
|
||||
<ul class="custom_fields long_choice {% if values|length == 1 %}unique{% endif %}">
|
||||
{%- for value in values -%}
|
||||
<li class="long_choice_item long_choice-key-{{ value.key }} long_choice-ikey-{{ value.internalKey }} long_choice-parent-ikey-{{ value.parent.internalKey }}">
|
||||
<i class="fa fa-check-square-o"></i> {{ value.text|localize_translatable_string }}
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
{% else %}
|
||||
<div class="custom_fields_choice long_choice empty">{{ 'None'|trans }}</div>
|
||||
{% endif %}
|
@ -0,0 +1 @@
|
||||
{% if value is not empty %}{{ value|format_date(format)}}{% endif %}
|
@ -0,0 +1 @@
|
||||
{% if number is not empty %}{{ number|number_format(scale)|csv_cell }}{% endif %}
|
@ -0,0 +1 @@
|
||||
{% if number is not empty %}{{ number|number_format(scale) }} {{ post|default('') }}{% endif %}
|
@ -0,0 +1 @@
|
||||
{% if text is not empty %}{{ text|csv_cell}}{% else %}{{ 'None'|trans }}{% endif %}
|
@ -0,0 +1 @@
|
||||
{% if text is not empty %}{{ text|nl2br }}{% else %}<span class="custom_fields_text empty">{{ 'None'|trans }}</span>{% endif %}
|
@ -0,0 +1,5 @@
|
||||
{% if type == "title"%}
|
||||
<h2>{{ title | localize_translatable_string }}</h2>
|
||||
{% else %}
|
||||
<h3>{{ title | localize_translatable_string }}</h3>
|
||||
{% endif %}
|
@ -0,0 +1,111 @@
|
||||
{#
|
||||
* 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/>.
|
||||
#}
|
||||
|
||||
{# CustomFields Title #}
|
||||
{% block custom_field_title_widget %}
|
||||
<span class="cf-{{ form.vars.attr.type }}">
|
||||
{{ form.vars.attr.title }}
|
||||
</span>
|
||||
{% endblock custom_field_title_widget %}
|
||||
|
||||
{# CustomFields Choice #}
|
||||
{# render an alement in a choice list #}
|
||||
{% block cf_choices_list_widget %}
|
||||
{{ form_row(form.name) }}
|
||||
{{ form_row(form.active) }}
|
||||
{{ form_row(form.slug) }}
|
||||
{% endblock cf_choices_list_widget %}
|
||||
|
||||
{# CFChoice : render the different elements in a choice list #}
|
||||
{% block cf_choices_row %}
|
||||
<h3>{{ 'Choices'|trans }}</h3>
|
||||
|
||||
<div id="{{ form.vars.id }}" data-prototype="{{- form_row(form.vars.prototype.children.name)
|
||||
~ form_row(form.vars.prototype.children.active)
|
||||
~ form_row(form.vars.prototype.children.slug) -}}">
|
||||
<table><tbody>
|
||||
{% for choice in form %}
|
||||
<tr><td>
|
||||
{{ form_row(choice.name) }}
|
||||
{{ form_row(choice.active) }}
|
||||
{{ form_row(choice.slug) }}
|
||||
</td></tr>
|
||||
{% endfor %}
|
||||
</tbody></table>
|
||||
</div>
|
||||
|
||||
|
||||
{# we use javascrit to add an additional element. All functions are personnalized with the id ( = form.vars.id) #}
|
||||
<script type="text/javascript">
|
||||
function addElementInDiv(div_id) {
|
||||
var div = $('#' + div_id);console.log(div);
|
||||
var prototype = div.data('prototype');console.log(prototype);
|
||||
var index = div.data('index');console.log(index);
|
||||
var add_element_link = $('#' + div_id + '_add_element_link');
|
||||
var new_fields = prototype.replace(/__name__label__/g, index);
|
||||
var new_fields = prototype.replace(/__name__/g, index);
|
||||
|
||||
div.data('index', index + 1);
|
||||
console.log(index);
|
||||
add_element_link.before(new_fields);
|
||||
}
|
||||
|
||||
function initializeCFChoiceOptionsChoices(div_id) {
|
||||
var add_element_link = $('<a id="' + div_id + '_add_element_link"" href="#" class="sc-button bt-submit">{{ 'Add an element'|trans }}</a>');
|
||||
var div = $('#' + div_id);
|
||||
div.append(add_element_link);
|
||||
div.data('index', div.find('td').length);
|
||||
console.log(div.data('index'));
|
||||
|
||||
add_element_link.on('click', function (e) {
|
||||
e.preventDefault();
|
||||
addElementInDiv(div_id);
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function(event) {
|
||||
jQuery(document).ready(initializeCFChoiceOptionsChoices('{{ form.vars.id }}'));
|
||||
});
|
||||
</script>
|
||||
{% endblock cf_choices_row %}
|
||||
|
||||
{# extend the number type to add post_text extension #}
|
||||
{% block number_widget %}
|
||||
{%- if post_text is defined and post_text is not empty-%}
|
||||
<div class="input_with_post_text">
|
||||
{%- endif -%}
|
||||
{{ block('form_widget') }}
|
||||
{%- if post_text is defined and post_text is not empty-%}
|
||||
<span class="post_text">{{ post_text }}</span>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{% endblock %}
|
||||
|
||||
{# extend the number type to add post_text extension #}
|
||||
{% block integer_widget %}
|
||||
{%- if post_text is defined and post_text is not empty-%}
|
||||
<div class="input_with_post_text">
|
||||
{%- endif -%}
|
||||
{{ block('form_widget') }}
|
||||
{%- if post_text is defined and post_text is not empty-%}
|
||||
<span class="post_text">{{ post_text }}</span>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{% endblock %}
|
||||
|
||||
{# The choice_with_other_widget widget is defined in the main bundle #}
|
||||
|
103
src/Bundle/ChillCustomFields/Service/CustomFieldProvider.php
Normal file
103
src/Bundle/ChillCustomFields/Service/CustomFieldProvider.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Service;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Receive all the services tagged with 'chill.custom_field'.
|
||||
*
|
||||
* The services tagged with 'chill.custom_field' are services used to declare
|
||||
* a new custom field type. The tag must contain a 'type' variable (that must
|
||||
* be unique), this type is used to identify this custom field in the form
|
||||
* declration
|
||||
*
|
||||
* For example (in services.yml) :
|
||||
* services:
|
||||
* chill.icp2.type:
|
||||
* tags:
|
||||
* - { name: 'chill.custom_field', type: 'ICPC2' }
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldProvider implements ContainerAwareInterface
|
||||
{
|
||||
/** @var array $servicesByType The services indexes by the type */
|
||||
private $servicesByType = array();
|
||||
|
||||
/** @var Container $container The container */
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* Add a new custom field to the provider
|
||||
*
|
||||
* @param type $serviceName The name of the service (declared in service.yml)
|
||||
* @param type $type The type of the service (that is used in the form to
|
||||
* add this type)
|
||||
*/
|
||||
public function addCustomField($serviceName, $type)
|
||||
{
|
||||
$this->servicesByType[$type] = $serviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a custom field stored in the provider. The custom field is identified
|
||||
* by its type.
|
||||
*
|
||||
* @param string $type The type of the wanted service
|
||||
* @return CustomFieldInterface
|
||||
*/
|
||||
public function getCustomFieldByType($type)
|
||||
{
|
||||
if (isset($this->servicesByType[$type])) {
|
||||
return $this->servicesByType[$type];
|
||||
} else {
|
||||
throw new \LogicException('the custom field with type '.$type.' '
|
||||
. 'is not found');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-PHPdoc)
|
||||
* @see \Symfony\Component\DependencyInjection\ContainerAwareInterface::setContainer()
|
||||
*/
|
||||
public function setContainer(ContainerInterface $container = null)
|
||||
{
|
||||
if ($container === null) {
|
||||
throw new \LogicException('container should not be null');
|
||||
}
|
||||
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the custom fields known by the provider
|
||||
*
|
||||
* @return array Array of the known custom fields indexed by the type.
|
||||
*/
|
||||
public function getAllFields()
|
||||
{
|
||||
return $this->servicesByType;
|
||||
}
|
||||
}
|
90
src/Bundle/ChillCustomFields/Service/CustomFieldsHelper.php
Normal file
90
src/Bundle/ChillCustomFields/Service/CustomFieldsHelper.php
Normal file
@ -0,0 +1,90 @@
|
||||
<?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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Service;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
|
||||
/**
|
||||
* Helpers for manipulating custom fields.
|
||||
*
|
||||
* Herlpers for getting a certain custom field, for getting the raw value
|
||||
* of a custom field and for rendering the value of a custom field.
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*
|
||||
*/
|
||||
class CustomFieldsHelper
|
||||
{
|
||||
/** @var EntityManagerInterface $em The entity manager */
|
||||
private $em;
|
||||
|
||||
/** @var CustomFieldProvider $provider Provider of all the declared custom
|
||||
* fields */
|
||||
private $provider;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param EntityManagerInterface $em The entity manager
|
||||
* @param CustomFieldProvider $provider The customfield provider that
|
||||
* contains all the declared custom fields
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $em,
|
||||
CustomFieldProvider $provider)
|
||||
{
|
||||
$this->em = $em;
|
||||
$this->provider = $provider;
|
||||
}
|
||||
|
||||
public function isEmptyValue(array $fields, CustomField $customField)
|
||||
{
|
||||
$slug = $customField->getSlug();
|
||||
$rawValue = (isset($fields[$slug])) ? $fields[$slug] : null;
|
||||
$customFieldType = $this->provider->getCustomFieldByType($customField->getType());
|
||||
|
||||
$deserializedValue = $customFieldType->deserialize($rawValue, $customField);
|
||||
|
||||
return $customFieldType->isEmptyValue($deserializedValue, $customField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the value of a custom field
|
||||
*
|
||||
* @param array $fields the **raw** array, as stored in the db
|
||||
* @param CustomField $customField the customField entity
|
||||
* @param string $documentType The type of document in which the rendered value is displayed ('html' or 'csv').
|
||||
* @throws CustomFieldsHelperException if slug is missing
|
||||
* @return The representation of the value the customField.
|
||||
*/
|
||||
public function renderCustomField(array $fields, CustomField $customField, $documentType='html')
|
||||
{
|
||||
$slug = $customField->getSlug();
|
||||
$rawValue = (isset($fields[$slug])) ? $fields[$slug] : null;
|
||||
$customFieldType = $this->provider->getCustomFieldByType($customField->getType());
|
||||
|
||||
return $customFieldType->render($rawValue, $customField, $documentType);
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
<?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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Service;
|
||||
|
||||
class CustomFieldsHelperException extends \Exception
|
||||
{
|
||||
public static function customFieldsGroupNotFound($entity)
|
||||
{
|
||||
return new CustomFieldsHelperException("The customFieldsGroups associated with $entity are not found");
|
||||
}
|
||||
|
||||
public static function slugIsMissing()
|
||||
{
|
||||
return new CustomFieldsHelperException("The slug is missing");
|
||||
}
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
<?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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Templating\Twig;
|
||||
|
||||
use Chill\CustomFieldsBundle\Service\CustomFieldsHelper;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* Add the following Twig Extension :
|
||||
* * chill_custom_field_widget : to render the value of the custom field,
|
||||
* * chill_custom_field_label : to render the label of the custom field,
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldRenderingTwig extends AbstractExtension implements ContainerAwareInterface
|
||||
{
|
||||
|
||||
/** @var Container $container The container */
|
||||
private $container;
|
||||
|
||||
/** @var array $defaultParams The default parameters */
|
||||
private $defaultParams = array(
|
||||
'label_layout' => 'ChillCustomFieldsBundle:CustomField:render_label.html.twig'
|
||||
);
|
||||
|
||||
/**
|
||||
* @var CustomFieldsHelper
|
||||
*/
|
||||
private $customFieldsHelper;
|
||||
|
||||
public function __construct(CustomFieldsHelper $customFieldsHelper)
|
||||
{
|
||||
$this->customFieldsHelper = $customFieldsHelper;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-PHPdoc)
|
||||
* @see \Symfony\Component\DependencyInjection\ContainerAwareInterface::setContainer()
|
||||
*/
|
||||
public function setContainer(ContainerInterface $container = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-PHPdoc)
|
||||
* @see Twig_Extension::getFunctions()
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new TwigFunction('chill_custom_field_widget', array(
|
||||
$this,
|
||||
'renderWidget'
|
||||
), array(
|
||||
'is_safe' => array(
|
||||
'html'
|
||||
)
|
||||
)),
|
||||
new TwigFunction('chill_custom_field_label', array(
|
||||
$this,
|
||||
'renderLabel'
|
||||
), array(
|
||||
'is_safe' => array(
|
||||
'html'
|
||||
)
|
||||
)),
|
||||
new TwigFunction('chill_custom_field_is_empty', array(
|
||||
$this,
|
||||
'isEmptyValue'
|
||||
))
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function isEmptyValue($fields, CustomField $customField)
|
||||
{
|
||||
return $this->customFieldsHelper
|
||||
->isEmptyValue($fields, $customField);
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Twig_ExtensionInterface::getName()
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'chill_custom_fields_rendering';
|
||||
}
|
||||
|
||||
/**
|
||||
* Twig Extension that is used to render the label of a custom field.
|
||||
*
|
||||
* @param CustomField $customField Either a customField OR a customizable_entity OR the FQDN of the entity
|
||||
* @param array $params The parameters for rendering. Currently, 'label_layout' allow to choose a different label. Default is 'ChillCustomFieldsBundle:CustomField:render_label.html.twig'
|
||||
* @return string HTML representation of the custom field label.
|
||||
*/
|
||||
public function renderLabel(CustomField $customField, array $params = array())
|
||||
{
|
||||
$resolvedParams = array_merge($this->defaultParams, $params);
|
||||
|
||||
return $this->container->get('templating')
|
||||
->render($resolvedParams['label_layout'], array('customField' => $customField));
|
||||
}
|
||||
|
||||
/**
|
||||
* Twig extension that is used to render the value of a custom field.
|
||||
*
|
||||
* The presentation of the value is influenced by the document type.
|
||||
*
|
||||
* @param array $fields The array raw, as stored in the db
|
||||
* @param CustomField $customField Either a customField OR a customizable_entity OR the FQDN of the entity
|
||||
* @param string $documentType The type of the document (csv, html)
|
||||
* @param string $slug The slug of the custom field ONLY necessary if the first argument is NOT a CustomField instance
|
||||
* @return string HTML representation of the custom field value, as described in the CustomFieldInterface. Is HTML safe
|
||||
*/
|
||||
public function renderWidget(array $fields, CustomField $customField, $documentType='html')
|
||||
{
|
||||
return $this->customFieldsHelper
|
||||
->renderCustomField($fields, $customField, $documentType);
|
||||
}
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
<?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/>.
|
||||
*/
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Templating\Twig;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* Add the following Twig Extension :
|
||||
* * chill_custom_fields_group_widget : to render the value of a custom field
|
||||
* * group
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
* @author Marc Ducobu <marc.ducobu@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldsGroupRenderingTwig extends AbstractExtension implements ContainerAwareInterface
|
||||
{
|
||||
|
||||
/** @var Container $container The container */
|
||||
private $container;
|
||||
|
||||
/** @var array $defaultParams The default parameters */
|
||||
private $defaultParams = array(
|
||||
'layout' => 'ChillCustomFieldsBundle:CustomFieldsGroup:render.html.twig',
|
||||
'show_empty' => True
|
||||
);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param boolean $showEmptyValues whether the empty values must be rendered
|
||||
*/
|
||||
public function __construct($showEmptyValues)
|
||||
{
|
||||
$this->defaultParams['show_empty'] = $showEmptyValues;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-PHPdoc)
|
||||
* @see \Symfony\Component\DependencyInjection\ContainerAwareInterface::setContainer()
|
||||
*/
|
||||
public function setContainer(ContainerInterface $container = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-PHPdoc)
|
||||
* @see Twig_Extension::getFunctions()
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return [
|
||||
new TwigFunction('chill_custom_fields_group_widget', array(
|
||||
$this,
|
||||
'renderWidget'
|
||||
), array(
|
||||
'is_safe' => array(
|
||||
'html'
|
||||
)
|
||||
)),
|
||||
];
|
||||
}
|
||||
|
||||
/* (non-PHPdoc)
|
||||
* @see Twig_ExtensionInterface::getName()
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'chill_custom_fields_group_rendering';
|
||||
}
|
||||
|
||||
/**
|
||||
* Twig extension that is used to render the value of a custom field group.
|
||||
*
|
||||
* The presentation of the value is influenced by the document type.
|
||||
*
|
||||
* @param array $fields The array raw, as stored in the db
|
||||
* @param CustomFieldsGroud $customFielsGroup The custom field group
|
||||
* @param string $documentType The type of the document (csv, html)
|
||||
* @param array $params The parameters for rendering :
|
||||
* - layout : allow to choose a different layout by default :
|
||||
* ChillCustomFieldsBundle:CustomFieldsGroup:render.html.twig
|
||||
* - show_empty : force show empty field
|
||||
* @return string HTML representation of the custom field group value, as described in
|
||||
* the CustomFieldInterface. Is HTML safe
|
||||
*/
|
||||
public function renderWidget(array $fields, $customFielsGroup, $documentType='html', array $params = array())
|
||||
{
|
||||
$resolvedParams = array_merge($this->defaultParams, $params);
|
||||
|
||||
return $this->container->get('templating')
|
||||
->render($resolvedParams['layout'], array(
|
||||
'cFGroup' => $customFielsGroup,
|
||||
'cFData' => $fields,
|
||||
'show_empty' => $resolvedParams['show_empty']));
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* 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\CustomFieldsBundle\Tests\Config;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
|
||||
/**
|
||||
* Test the option Customizables_entities
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class ConfigCustomizablesEntitiesTest extends KernelTestCase
|
||||
{
|
||||
/**
|
||||
* Test that the config does work if the option
|
||||
* chill_custom_fields.customizables_entities IS NOT present
|
||||
*
|
||||
* In this case, parameter 'chill_custom_fields.customizables_entities'
|
||||
* should be an empty array in container
|
||||
*/
|
||||
public function testNotPresentInConfig()
|
||||
{
|
||||
self::bootKernel(array('environment' => 'test'));
|
||||
$customizableEntities = static::$kernel->getContainer()
|
||||
->getParameter('chill_custom_fields.customizables_entities');
|
||||
|
||||
$this->assertInternalType('array', $customizableEntities);
|
||||
$this->assertCount(1, $customizableEntities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the 'chill_custom_fields.customizables_entities' is filled
|
||||
* correctly with a minimal configuration.
|
||||
*
|
||||
* @internal use a custom config environment
|
||||
*/
|
||||
public function testNotEmptyConfig()
|
||||
{
|
||||
self::bootKernel(array('environment' => 'test_customizable_entities_test_not_empty_config'));
|
||||
$customizableEntities = static::$kernel->getContainer()
|
||||
->getParameter('chill_custom_fields.customizables_entities');
|
||||
|
||||
$this->assertInternalType('array', $customizableEntities);
|
||||
$this->assertCount(2, $customizableEntities);
|
||||
|
||||
foreach($customizableEntities as $key => $config) {
|
||||
$this->assertInternalType('array', $config);
|
||||
$this->assertArrayHasKey('name', $config);
|
||||
$this->assertArrayHasKey('class', $config);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Tests\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
|
||||
class CustomFieldControllerTest extends WebTestCase
|
||||
{
|
||||
/*
|
||||
public function testCompleteScenario()
|
||||
{
|
||||
// Create a new client to browse the application
|
||||
$client = static::createClient();
|
||||
|
||||
// Create a new entry in the database
|
||||
$crawler = $client->request('GET', '/customfield/');
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode(), "Unexpected HTTP status code for GET /customfield/");
|
||||
$crawler = $client->click($crawler->selectLink('Create a new entry')->link());
|
||||
|
||||
// Fill in the form and submit it
|
||||
$form = $crawler->selectButton('Create')->form(array(
|
||||
'cl_customfieldsbundle_customfield[field_name]' => 'Test',
|
||||
// ... other fields to fill
|
||||
));
|
||||
|
||||
$client->submit($form);
|
||||
$crawler = $client->followRedirect();
|
||||
|
||||
// Check data in the show view
|
||||
$this->assertGreaterThan(0, $crawler->filter('td:contains("Test")')->count(), 'Missing element td:contains("Test")');
|
||||
|
||||
// Edit the entity
|
||||
$crawler = $client->click($crawler->selectLink('Edit')->link());
|
||||
|
||||
$form = $crawler->selectButton('Update')->form(array(
|
||||
'cl_customfieldsbundle_customfield[field_name]' => 'Foo',
|
||||
// ... other fields to fill
|
||||
));
|
||||
|
||||
$client->submit($form);
|
||||
$crawler = $client->followRedirect();
|
||||
|
||||
// Check the element contains an attribute with value equals "Foo"
|
||||
$this->assertGreaterThan(0, $crawler->filter('[value="Foo"]')->count(), 'Missing element [value="Foo"]');
|
||||
|
||||
// Delete the entity
|
||||
$client->submit($crawler->selectButton('Delete')->form());
|
||||
$crawler = $client->followRedirect();
|
||||
|
||||
// Check the entity has been delete on the list
|
||||
$this->assertNotRegExp('/Foo/', $client->getResponse()->getContent());
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CustomFieldsBundle\Tests\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
use Symfony\Bundle\FrameworkBundle\Client;
|
||||
|
||||
class CustomFieldsGroupControllerTest extends WebTestCase
|
||||
{
|
||||
|
||||
public function testCompleteScenario()
|
||||
{
|
||||
self::bootKernel(array('environment' => 'test_customizable_entities_test_not_empty_config'));
|
||||
// Create a new client to browse the application
|
||||
$client = static::createClient(array(), array(
|
||||
'PHP_AUTH_USER' => 'admin',
|
||||
'PHP_AUTH_PW' => 'olala',
|
||||
));
|
||||
|
||||
//create the entity
|
||||
$this->createCustomFieldsGroup($client);
|
||||
|
||||
// Edit the entity
|
||||
$this->editCustomFieldsGroup($client);
|
||||
}
|
||||
|
||||
private function createCustomFieldsGroup(Client &$client)
|
||||
{
|
||||
// Create a new entry in the database
|
||||
$crawler = $client->request('GET', '/fr/admin/customfieldsgroup/');
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode(),
|
||||
"Unexpected HTTP status code for GET /customfieldsgroup/");
|
||||
|
||||
$crawler = $client->click($crawler->selectLink('Créer un nouveau groupe')->link());
|
||||
|
||||
// Fill in the form and submit it
|
||||
$form = $crawler->selectButton('Créer')->form(array(
|
||||
'custom_fields_group[name][fr]' => 'Test',
|
||||
'custom_fields_group[entity]' => 'Chill\PersonBundle\Entity\Person'
|
||||
));
|
||||
|
||||
$crawler = $client->submit($form);
|
||||
|
||||
$crawler = $client->followRedirect();
|
||||
|
||||
// Check data in the show view
|
||||
$this->assertGreaterThan(0, $crawler->filter('td:contains("Test")')->count(),
|
||||
'Missing element td:contains("Test")');
|
||||
}
|
||||
|
||||
private function editCustomFieldsGroup(Client $client)
|
||||
{
|
||||
$crawler = $client->request('GET', '/fr/admin/customfieldsgroup/');
|
||||
$links = $crawler->selectLink('Modifier');
|
||||
|
||||
$this->assertGreaterThan(0, $links->count(),
|
||||
"We can't find a 'Modifier' link on the index page");
|
||||
$crawler = $client->click($links->last()->link());
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$form = $crawler->selectButton('Mettre à jour')->form(array(
|
||||
'custom_fields_group[name][fr]' => 'Foo',
|
||||
));
|
||||
|
||||
$client->submit($form);
|
||||
$crawler = $client->followRedirect();
|
||||
|
||||
// Check the element contains an attribute with value equals "Foo"
|
||||
$this->assertGreaterThan(0, $crawler->filter('[value="Foo"]')->count(),
|
||||
'Missing element [value="Foo"]');
|
||||
}
|
||||
}
|
86
src/Bundle/ChillCustomFields/Tests/CustomFieldTestHelper.php
Normal file
86
src/Bundle/ChillCustomFields/Tests/CustomFieldTestHelper.php
Normal file
@ -0,0 +1,86 @@
|
||||
<?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\CustomFieldsBundle\Tests;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
/**
|
||||
* Give useful method to prepare tests regarding custom fields
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
trait CustomFieldTestHelper
|
||||
{
|
||||
|
||||
/**
|
||||
* Prepare a crawler containing the rendering of a customField
|
||||
*
|
||||
* @internal This method will mock a customFieldGroup containing $field, and
|
||||
* rendering the customfield, using Type\CustomFieldType, to a simple form row
|
||||
*
|
||||
* @param CustomField $field
|
||||
* @param KernelTestCase $testCase
|
||||
* @param KernelInterface $kernel
|
||||
* @param type $locale
|
||||
* @return Crawler
|
||||
*/
|
||||
public function getCrawlerForField(CustomField $field, $locale = 'en')
|
||||
{
|
||||
$kernel = static::$kernel;
|
||||
|
||||
//check a kernel is accessible
|
||||
$customFieldsGroup = $this->createMock('Chill\CustomFieldsBundle\Entity\CustomFieldsGroup');
|
||||
$customFieldsGroup->expects($this->once())
|
||||
->method('getActiveCustomFields')
|
||||
->will($this->returnValue(array($field)));
|
||||
|
||||
$request = $this->createMock('Symfony\Component\HttpFoundation\Request');
|
||||
$request->expects($this->any())
|
||||
->method('getLocale')
|
||||
->will($this->returnValue($locale));
|
||||
|
||||
$kernel->getContainer()->get('request_stack')->push($request);
|
||||
|
||||
$builder = $kernel->getContainer()->get('form.factory')->createBuilder();
|
||||
$form = $builder->add('tested', 'custom_field',
|
||||
array('group' => $customFieldsGroup))
|
||||
->getForm();
|
||||
|
||||
$kernel->getContainer()->get('twig.loader')
|
||||
->addPath($kernel->getContainer()->getParameter('kernel.root_dir').
|
||||
'/Resources/views/', $namespace = 'test');
|
||||
|
||||
$content = $kernel
|
||||
->getContainer()->get('templating')
|
||||
->render('@test/CustomField/simple_form_render.html.twig', array(
|
||||
'form' => $form->createView(),
|
||||
'inputKeys' => array('tested')
|
||||
));
|
||||
|
||||
$crawler = new Crawler();
|
||||
$crawler->addHtmlContent($content);
|
||||
|
||||
return $crawler;
|
||||
}
|
||||
}
|
@ -0,0 +1,468 @@
|
||||
<?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\CustomFieldsBundle\Tests;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Chill\CustomFieldsBundle\CustomFields\CustomFieldChoice;
|
||||
|
||||
/**
|
||||
* This class cover the test of CustomFieldChoice.
|
||||
*
|
||||
* Function currently covered:
|
||||
*
|
||||
* - deserialize
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldsChoiceTest extends KernelTestCase
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Chill\CustomFieldsBundle\Service\CustomFieldProvider
|
||||
*/
|
||||
private $cfProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Chill\CustomFieldsBundle\CustomFields\CustomFieldChoice
|
||||
*/
|
||||
private $cfChoice;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
static::bootKernel();
|
||||
|
||||
$this->cfProvider = static::$kernel->getContainer()
|
||||
->get('chill.custom_field.provider');
|
||||
$this->cfChoice = $this->cfProvider->getCustomFieldByType('choice');
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param array $options
|
||||
* @return CustomField
|
||||
*/
|
||||
private function generateCustomField($options)
|
||||
{
|
||||
return (new CustomField())
|
||||
->setActive(true)
|
||||
->setSlug('slug')
|
||||
->setOptions($options)
|
||||
->setType('choice')
|
||||
;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
//
|
||||
// test function deserialize
|
||||
//
|
||||
////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Test if the representation of the data is deserialized to a single text.
|
||||
*
|
||||
* If the value is in _other, the _other value should not be returned.
|
||||
*
|
||||
* @param type $data
|
||||
* @dataProvider serializedRepresentationDataProvider
|
||||
*/
|
||||
public function testDeserializeSingleChoiceWithoutOther($data)
|
||||
{
|
||||
$customField = $this->generateCustomField(array(
|
||||
CustomFieldChoice::ALLOW_OTHER => false,
|
||||
CustomFieldChoice::MULTIPLE => false
|
||||
));
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
|
||||
$this->assertSame('my-value', $deserialized);
|
||||
}
|
||||
|
||||
|
||||
public function testDeserializeSingleChoiceWithoutOtherDataIsNull()
|
||||
{
|
||||
$customField = $this->generateCustomField(array(
|
||||
CustomFieldChoice::ALLOW_OTHER => false,
|
||||
CustomFieldChoice::MULTIPLE => false
|
||||
));
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize(null, $customField);
|
||||
$this->assertSame(null, $deserialized);
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize('', $customField);
|
||||
$this->assertSame('', $deserialized);
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize(array(null), $customField);
|
||||
$this->assertSame(null, $deserialized);
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize(array('_other' => null, '_choices' => null), $customField);
|
||||
$this->assertSame(null, $deserialized);
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize(array('_other' => null, '_choices' => ''), $customField);
|
||||
$this->assertSame('', $deserialized);
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize(array(null), $customField);
|
||||
$this->assertSame(null, $deserialized);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the representation of the data is deserialized to a single text
|
||||
* with an "allow_other" field.
|
||||
*
|
||||
* If the value is in _other, the _other value should be in the _other field.
|
||||
*
|
||||
* @param type $data
|
||||
* @dataProvider serializedRepresentationDataProvider
|
||||
*/
|
||||
public function testDeserializeSingleChoiceWithOther($data)
|
||||
{
|
||||
$customField = $this->generateCustomField(array(
|
||||
CustomFieldChoice::ALLOW_OTHER => true,
|
||||
CustomFieldChoice::MULTIPLE => false
|
||||
));
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
|
||||
$this->assertSame(array('_other' => '', '_choices' => 'my-value'), $deserialized);
|
||||
}
|
||||
|
||||
/**
|
||||
* Other cases :
|
||||
*
|
||||
* - Test if the selected value is '_other
|
||||
* - Test with null data
|
||||
*
|
||||
* @param type $data
|
||||
*/
|
||||
public function testDeserializeSingleChoiceWithOtherOtherCases()
|
||||
{
|
||||
$customField = $this->generateCustomField(array(
|
||||
CustomFieldChoice::ALLOW_OTHER => true,
|
||||
CustomFieldChoice::MULTIPLE => false
|
||||
));
|
||||
|
||||
// from a single to a single
|
||||
$data = array('_other' => 'something', '_choices' => '_other');
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
$this->assertSame(array('_other' => 'something', '_choices' => '_other'), $deserialized);
|
||||
|
||||
|
||||
// from a multiple to a single
|
||||
$data = array('_other' => 'something', '_choices' => array('some', '_other'));
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
$this->assertSame(array('_other' => 'something', '_choices' => '_other'), $deserialized);
|
||||
|
||||
//test with null data
|
||||
//from a single to a single :
|
||||
$data = array('_other' => 'something', '_choices' => null);
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
$this->assertSame(array('_other' => 'something', '_choices' => null), $deserialized);
|
||||
|
||||
$data = array('_other' => 'something', '_choices' => '');
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
$this->assertSame(array('_other' => 'something', '_choices' => ''), $deserialized);
|
||||
|
||||
// from a multiple to a signle
|
||||
$data = array('_other' => 'something', '_choices' => array());
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
$this->assertSame(array('_other' => 'something', '_choices' => ''), $deserialized);
|
||||
|
||||
$data = array('_other' => 'something', '_choices' => array(''));
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
$this->assertSame(array('_other' => 'something', '_choices' => ''), $deserialized);
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize(array('_other' => null, '_choices' => null), $customField);
|
||||
$this->assertSame(array('_other' => '', '_choices' => null), $deserialized);
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize(array('_other' => null, '_choices' => ''), $customField);
|
||||
$this->assertSame(array('_other' => '', '_choices' => ''), $deserialized);
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize(array(null), $customField);
|
||||
$this->assertSame(array('_other' => '', '_choices' => null), $deserialized);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the representation of the data is deserialized to an array text
|
||||
* with an "allow_other" field.
|
||||
*
|
||||
* This test does not covers the case when the selected value is `_other`
|
||||
*
|
||||
* @param type $data
|
||||
* @dataProvider serializedRepresentationDataProvider
|
||||
*/
|
||||
public function testDeserializeMultipleChoiceWithOther($data)
|
||||
{
|
||||
$customField = $this->generateCustomField(array(
|
||||
CustomFieldChoice::ALLOW_OTHER => true,
|
||||
CustomFieldChoice::MULTIPLE => true
|
||||
));
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
|
||||
$this->assertSame(array('_other' => '', '_choices' => array('my-value')),
|
||||
$deserialized);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the representation of the data is deserialized to an array text
|
||||
* with an "allow_other" field.
|
||||
*
|
||||
* This test covers :
|
||||
* - the case when the selected value is `_other`
|
||||
* - result is null
|
||||
*
|
||||
* @param type $data
|
||||
*/
|
||||
public function testDeserializeMultipleChoiceWithOtherOtherCases()
|
||||
{
|
||||
$customField = $this->generateCustomField(array(
|
||||
CustomFieldChoice::ALLOW_OTHER => true,
|
||||
CustomFieldChoice::MULTIPLE => true
|
||||
));
|
||||
|
||||
// selected value is _other
|
||||
// from single to multiple
|
||||
$data = array('_other' => 'something', '_choices' => '_other');
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
|
||||
$this->assertSame(array('_other' => 'something', '_choices' => array('_other')),
|
||||
$deserialized);
|
||||
|
||||
// from multiple to multiple
|
||||
$data = array('_other' => 'something', '_choices' => array('_other', 'something'));
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
|
||||
$this->assertSame(array('_other' => 'something', '_choices' => array('_other', 'something')),
|
||||
$deserialized);
|
||||
|
||||
// test with null value
|
||||
// from single to multiple
|
||||
$data = array('_other' => '', '_choices' => '');
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
|
||||
$this->assertSame(array('_other' => '', '_choices' => array('')),
|
||||
$deserialized);
|
||||
|
||||
// from multiple to multiple
|
||||
$data = array('_other' => '', '_choices' => array());
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
|
||||
$this->assertSame(array('_other' => '', '_choices' => array()),
|
||||
$deserialized);
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize(array('_other' => null, '_choices' => null), $customField);
|
||||
$this->assertSame(array('_other' => '', '_choices' => array(null)), $deserialized);
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize(array('_other' => null, '_choices' => ''), $customField);
|
||||
$this->assertSame(array('_other' => '', '_choices' => array('')), $deserialized);
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize(array(null), $customField);
|
||||
$this->assertSame(array('_other' => '', '_choices' => array(null)), $deserialized);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the representation of the data is deserialized to an array text
|
||||
* **without** an "allow_other" field.
|
||||
*
|
||||
*
|
||||
* @param type $data
|
||||
* @dataProvider serializedRepresentationDataProvider
|
||||
*/
|
||||
public function testDeserializeMultipleChoiceWithoutOther($data)
|
||||
{
|
||||
$customField = $this->generateCustomField(array(
|
||||
CustomFieldChoice::ALLOW_OTHER => false,
|
||||
CustomFieldChoice::MULTIPLE => true
|
||||
));
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
|
||||
$this->assertSame(array('my-value'), $deserialized);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the representation of the data is deserialized to an array text
|
||||
* **without** an "allow_other" field.
|
||||
*
|
||||
* Covered cases :
|
||||
* - NULL values
|
||||
*
|
||||
*
|
||||
* @param type $data
|
||||
*/
|
||||
public function testDeserializeMultipleChoiceWithoutOtherOtherCases()
|
||||
{
|
||||
$customField = $this->generateCustomField(array(
|
||||
CustomFieldChoice::ALLOW_OTHER => false,
|
||||
CustomFieldChoice::MULTIPLE => true
|
||||
));
|
||||
|
||||
// from single to multiple
|
||||
$data = 'my-value';
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
$this->assertSame(array('my-value'), $deserialized);
|
||||
|
||||
// from multiple to multiple
|
||||
$data = array('my-value');
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
$this->assertSame(array('my-value'), $deserialized);
|
||||
|
||||
// from multiple
|
||||
$data = array(null);
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
$this->assertSame(array(null), $deserialized);
|
||||
|
||||
$data = array('_other' => null, '_choices' => array(null));
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
$this->assertSame(array(null), $deserialized);
|
||||
|
||||
//from single
|
||||
$data = array('_other' => null, '_choices' => null);
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
$this->assertSame(array(null), $deserialized);
|
||||
}
|
||||
|
||||
public function serializedRepresentationDataProvider()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
// multiple => false, allow_other => false
|
||||
'my-value'
|
||||
),
|
||||
array(
|
||||
// multiple => true, allow_ther => false
|
||||
array('my-value')
|
||||
),
|
||||
array(
|
||||
// multiple => false, allow_other => true, current value not in other
|
||||
array('_other' => '', '_choices' => 'my-value')
|
||||
),
|
||||
array(
|
||||
// multiple => true, allow_other => true, current value not in other
|
||||
array('_other' => '', '_choices'=> array('my-value'))
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////
|
||||
//
|
||||
// test function isEmptyValue
|
||||
//
|
||||
////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* test the not empty with the not-empty data provider
|
||||
*
|
||||
* @param mixed $data
|
||||
* @dataProvider serializedRepresentationDataProvider
|
||||
*/
|
||||
public function testIsEmptyValueNotEmpty($data)
|
||||
{
|
||||
$customField = $this->generateCustomField(array(
|
||||
CustomFieldChoice::ALLOW_OTHER => false,
|
||||
CustomFieldChoice::MULTIPLE => true
|
||||
));
|
||||
|
||||
$deserialized = $this->cfChoice->deserialize($data, $customField);
|
||||
$isEmpty = $this->cfChoice->isEmptyValue($deserialized, $customField);
|
||||
|
||||
$this->assertFalse($isEmpty);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @dataProvider emptyDataProvider
|
||||
* @param mixed $data deserialized data
|
||||
*/
|
||||
public function testIsEmptyValueEmpty($data)
|
||||
{
|
||||
$customField = $this->generateCustomField(array(
|
||||
CustomFieldChoice::ALLOW_OTHER => false,
|
||||
CustomFieldChoice::MULTIPLE => true
|
||||
));
|
||||
|
||||
$isEmpty = $this->cfChoice->isEmptyValue($data, $customField);
|
||||
|
||||
$this->assertTrue($isEmpty);
|
||||
}
|
||||
|
||||
/**
|
||||
* provide empty data in different possible representations.
|
||||
* Those data are supposed to be deserialized.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function emptyDataProvider()
|
||||
{
|
||||
return array(
|
||||
// 0
|
||||
array(
|
||||
// signle
|
||||
''
|
||||
),
|
||||
// 1
|
||||
array(
|
||||
// single
|
||||
null
|
||||
),
|
||||
// 2
|
||||
array(
|
||||
// signle with allow other
|
||||
array('_other' => 'something', '_choices' => '')
|
||||
),
|
||||
// 3
|
||||
array(
|
||||
// multiple
|
||||
array()
|
||||
),
|
||||
// 4
|
||||
array(
|
||||
// multiple with allow other
|
||||
array('_other' => 'something', '_choices' => array())
|
||||
),
|
||||
// 5
|
||||
array(
|
||||
// multiple with allow other
|
||||
array('_other' => '', '_choices' => array())
|
||||
),
|
||||
// 6
|
||||
array(
|
||||
// empty
|
||||
array('_other' => null, '_choices' => null)
|
||||
),
|
||||
// 7
|
||||
array(
|
||||
// empty
|
||||
array(null)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,191 @@
|
||||
<?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\CustomFieldsBundle\Tests;
|
||||
|
||||
use Chill\CustomFieldsBundle\CustomFields\CustomFieldNumber;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
|
||||
use Chill\CustomFieldsBundle\Form\CustomFieldsGroupType;
|
||||
|
||||
/**
|
||||
* Test CustomFieldsNumber
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldsNumberTest extends \Symfony\Bundle\FrameworkBundle\Test\WebTestCase
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var CustomFieldNumber
|
||||
*/
|
||||
private $customFieldNumber;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var FormBuilderInterface
|
||||
*/
|
||||
private $formBuilder;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$this->customFieldNumber = self::$kernel->getContainer()
|
||||
->get('chill.custom_field.number');
|
||||
|
||||
$this->formBuilder = self::$kernel->getContainer()
|
||||
->get('form.factory')
|
||||
->createBuilder('form', null, array(
|
||||
'csrf_protection' => false,
|
||||
'csrf_field_name' => '_token'
|
||||
));
|
||||
|
||||
$request = new \Symfony\Component\HttpFoundation\Request();
|
||||
$request->setLocale('fr');
|
||||
|
||||
self::$kernel->getContainer()
|
||||
->get('request_stack')
|
||||
->push($request);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed[] $options
|
||||
* @return CustomField
|
||||
*/
|
||||
private function createCustomFieldNumber($options)
|
||||
{
|
||||
return (new CustomField())
|
||||
->setType('number')
|
||||
->setActive(true)
|
||||
->setOrdering(10)
|
||||
->setSlug('default')
|
||||
->setName(array('fr' => 'default'))
|
||||
->setOptions($options);
|
||||
}
|
||||
|
||||
public function testCreateValidForm()
|
||||
{
|
||||
$cf = $this->createCustomFieldNumber(array(
|
||||
'min' => null,
|
||||
'max' => null,
|
||||
'scale' => null,
|
||||
'post_text' => null
|
||||
));
|
||||
|
||||
$this->customFieldNumber->buildForm($this->formBuilder, $cf);
|
||||
|
||||
$form = $this->formBuilder->getForm();
|
||||
|
||||
$form->submit(array('default' => 10));
|
||||
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
$this->assertEquals(10, $form['default']->getData());
|
||||
}
|
||||
|
||||
public function testCreateInvalidFormValueGreaterThanMaximum()
|
||||
{
|
||||
$cf = $this->createCustomFieldNumber(array(
|
||||
'min' => null,
|
||||
'max' => 10,
|
||||
'scale' => null,
|
||||
'post_text' => null
|
||||
));
|
||||
|
||||
$this->customFieldNumber->buildForm($this->formBuilder, $cf);
|
||||
|
||||
$form = $this->formBuilder->getForm();
|
||||
|
||||
$form->submit(array('default' => 100));
|
||||
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
$this->assertFalse($form->isValid());
|
||||
$this->assertEquals(1, count($form['default']->getErrors()));
|
||||
}
|
||||
|
||||
public function testCreateInvalidFormValueLowerThanMinimum()
|
||||
{
|
||||
$cf = $this->createCustomFieldNumber(array(
|
||||
'min' => 1000,
|
||||
'max' => null,
|
||||
'scale' => null,
|
||||
'post_text' => null
|
||||
));
|
||||
|
||||
$this->customFieldNumber->buildForm($this->formBuilder, $cf);
|
||||
|
||||
$form = $this->formBuilder->getForm();
|
||||
|
||||
$form->submit(array('default' => 100));
|
||||
|
||||
$this->assertTrue($form->isSynchronized());
|
||||
$this->assertFalse($form->isValid());
|
||||
$this->assertEquals(1, count($form['default']->getErrors()));
|
||||
}
|
||||
|
||||
public function testRequiredFieldIsFalse()
|
||||
{
|
||||
$cf = $this->createCustomFieldNumber(array(
|
||||
'min' => 1000,
|
||||
'max' => null,
|
||||
'scale' => null,
|
||||
'post_text' => null
|
||||
));
|
||||
$cf->setRequired(false);
|
||||
|
||||
$cfGroup = (new \Chill\CustomFieldsBundle\Entity\CustomFieldsGroup())
|
||||
->addCustomField($cf);
|
||||
|
||||
$form = static::$kernel->getContainer()->get('form.factory')
|
||||
->createBuilder(\Chill\CustomFieldsBundle\Form\Type\CustomFieldType::class, array(), array(
|
||||
'group' => $cfGroup
|
||||
))
|
||||
->getForm();
|
||||
|
||||
$this->assertFalse($form['default']->isRequired(),
|
||||
"The field should not be required");
|
||||
}
|
||||
|
||||
public function testRequiredFieldIsTrue()
|
||||
{
|
||||
$cf = $this->createCustomFieldNumber(array(
|
||||
'min' => 1000,
|
||||
'max' => null,
|
||||
'scale' => null,
|
||||
'post_text' => null
|
||||
));
|
||||
$cf->setRequired(true);
|
||||
|
||||
$cfGroup = (new \Chill\CustomFieldsBundle\Entity\CustomFieldsGroup())
|
||||
->addCustomField($cf);
|
||||
|
||||
$form = static::$kernel->getContainer()->get('form.factory')
|
||||
->createBuilder(\Chill\CustomFieldsBundle\Form\Type\CustomFieldType::class, array(), array(
|
||||
'group' => $cfGroup
|
||||
))
|
||||
->getForm();
|
||||
|
||||
$this->assertTrue($form['default']->isRequired(),
|
||||
"The field should be required");
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Chill is a software for social workers
|
||||
* Copyright (C) 2014 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\CustomFieldsBundle\Tests;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Chill\CustomFieldsBundle\CustomFields\CustomFieldText;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
use Chill\CustomFieldsBundle\Tests\CustomFieldTestHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldsTextTest extends WebTestCase
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var \Chill\CustomFieldsBundle\Service\CustomFieldProvider
|
||||
*/
|
||||
private $customFieldProvider;
|
||||
|
||||
use CustomFieldTestHelper;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
static::bootKernel();
|
||||
$this->customFieldProvider = static::$kernel->getContainer()
|
||||
->get('chill.custom_field.provider');
|
||||
}
|
||||
|
||||
public function testCustomFieldsTextExists()
|
||||
{
|
||||
$customField = $this->customFieldProvider->getCustomFieldByType('text');
|
||||
|
||||
$this->assertInstanceOf('Chill\CustomFieldsBundle\CustomFields\CustomFieldInterface',
|
||||
$customField);
|
||||
$this->assertInstanceOf('Chill\CustomFieldsBundle\CustomFields\CustomFieldText',
|
||||
$customField);
|
||||
}
|
||||
|
||||
public function testPublicFormRenderingLengthLessThan256()
|
||||
{
|
||||
$customField = new CustomField();
|
||||
$customField->setType('text')
|
||||
->setOptions(array(CustomFieldText::MAX_LENGTH => 255))
|
||||
->setSlug('slug')
|
||||
->setOrdering(10)
|
||||
->setActive(true)
|
||||
->setName(array('en' => 'my label'));
|
||||
|
||||
$crawler = $this->getCrawlerForField($customField);
|
||||
|
||||
$this->assertCount(1, $crawler->filter("input[type=text]"));
|
||||
$this->assertCount(1, $crawler->filter("label:contains('my label')"));
|
||||
}
|
||||
|
||||
public function testPublicFormRenderingLengthMoreThan25()
|
||||
{
|
||||
$customField = new CustomField();
|
||||
$customField->setType('text')
|
||||
->setOptions(array(CustomFieldText::MAX_LENGTH => 256))
|
||||
->setSlug('slug')
|
||||
->setOrdering(10)
|
||||
->setActive(true)
|
||||
->setName(array('en' => 'my label'));
|
||||
|
||||
$crawler = $this->getCrawlerForField($customField);
|
||||
|
||||
$this->assertCount(1, $crawler->filter("textarea"));
|
||||
$this->assertCount(1, $crawler->filter("label:contains('my label')"));
|
||||
}
|
||||
|
||||
public function testFormTextNew()
|
||||
{
|
||||
$client = static::createClient();
|
||||
|
||||
$crawler = $client->request('GET', '/fr/admin/customfield/new?type=text');
|
||||
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$form = $crawler->selectButton('custom_field_choice_submit')->form();
|
||||
$this->assertTrue($form->has('custom_field_choice[options][maxLength]'));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
<?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\CustomFields\Tests\Form\Extension;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||
|
||||
/**
|
||||
* Test the post-text extension
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class PostTextIntegerExtensionTest extends KernelTestCase
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var \Symfony\Component\Form\FormBuilderInterface
|
||||
*/
|
||||
private $formBuilder;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$container = self::$kernel->getContainer();
|
||||
|
||||
$this->formBuilder = $container->get('form.factory')
|
||||
->createBuilder('form', null);
|
||||
}
|
||||
|
||||
public function testCreateView()
|
||||
{
|
||||
$form = $this->formBuilder->add('test', IntegerType::class, array(
|
||||
'post_text' => 'my text'
|
||||
))->getForm();
|
||||
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertEquals('my text', $view['test']->vars['post_text']);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
<?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\CustomFields\Tests\Form\Extension;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
|
||||
/**
|
||||
* Test the post-text extension
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class PostTextNumberExtensionTest extends KernelTestCase
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var \Symfony\Component\Form\FormBuilderInterface
|
||||
*/
|
||||
private $formBuilder;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$container = self::$kernel->getContainer();
|
||||
|
||||
$this->formBuilder = $container->get('form.factory')
|
||||
->createBuilder('form', null);
|
||||
}
|
||||
|
||||
public function testCreateView()
|
||||
{
|
||||
$form = $this->formBuilder->add('test', NumberType::class, array(
|
||||
'post_text' => 'my text'
|
||||
))->getForm();
|
||||
|
||||
$view = $form->createView();
|
||||
|
||||
$this->assertEquals('my text', $view['test']->vars['post_text']);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
*
|
||||
* 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\CustomFieldsBundle\Tests;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Test that routes are correctly loaded
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class RoutingLoaderTest extends WebTestCase
|
||||
{
|
||||
public function testRoutesAreLoaded()
|
||||
{
|
||||
$client = static::createClient();
|
||||
|
||||
$client->request('GET','/fr/admin/customfield/');
|
||||
|
||||
$this->assertEquals(
|
||||
Response::HTTP_OK,
|
||||
$client->getResponse()->getStatusCode()
|
||||
);
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
<?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\CustomFields\Tests\Service;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Chill\CustomFieldsBundle\Service\CustomFieldsHelper;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
|
||||
/**
|
||||
* Tests for custom fields helper
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
* @author Champs Libres <info@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldsHelperTest extends KernelTestCase
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var CustomFieldsHelper
|
||||
*/
|
||||
private $cfHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var CustomField
|
||||
*/
|
||||
private $randomCFText;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
self::bootKernel();
|
||||
|
||||
$container = self::$kernel->getContainer();
|
||||
|
||||
$this->cfHelper = $container->get('chill.custom_field.helper');
|
||||
|
||||
$this->randomCFText = (new CustomField())
|
||||
->setSlug('my-slug')
|
||||
->setActive(true)
|
||||
->setName(array('fr' => 'my cf'))
|
||||
->setOptions(array('maxLength' => 1000))
|
||||
->setType('text')
|
||||
;
|
||||
}
|
||||
|
||||
public function testRenderCustomField()
|
||||
{
|
||||
$data = array(
|
||||
$this->randomCFText->getSlug() => 'Sample text'
|
||||
);
|
||||
|
||||
$text = $this->cfHelper->renderCustomField($data, $this->randomCFText);
|
||||
|
||||
$this->assertContains('Sample text', $text);
|
||||
}
|
||||
|
||||
public function testIsEmptyValue()
|
||||
{
|
||||
// not empty value
|
||||
$data = array(
|
||||
$this->randomCFText->getSlug() => 'Sample text'
|
||||
);
|
||||
|
||||
$this->assertFalse($this->cfHelper->isEmptyValue($data, $this->randomCFText));
|
||||
|
||||
//empty value
|
||||
$data = array(
|
||||
$this->randomCFText->getSlug() => ''
|
||||
);
|
||||
|
||||
$this->assertTrue($this->cfHelper->isEmptyValue($data, $this->randomCFText));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
<?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\CustomFields\Tests\Templating\Twig;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Chill\CustomFieldsBundle\Templating\Twig\CustomFieldRenderingTwig;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
|
||||
|
||||
/**
|
||||
* Test the rendering of twig function which renders custom fields
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
* @author Champs Libres <info@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldRenderingTwigTest extends KernelTestCase
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var CustomFieldRenderingTwig
|
||||
*/
|
||||
private $cfRendering;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var CustomFieldProvider
|
||||
*/
|
||||
private $cfProvider;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
self::bootKernel();
|
||||
$this->cfRendering = self::$kernel->getContainer()
|
||||
->get('chill.custom_field.twig.custom_fields_rendering')
|
||||
;
|
||||
|
||||
$this->cfProvider = self::$kernel->getContainer()
|
||||
->get('chill.custom_field.provider');
|
||||
|
||||
// set locale to fr
|
||||
$prophet = new \Prophecy\Prophet;
|
||||
$request = $prophet->prophesize();
|
||||
$request->willExtend('Symfony\Component\HttpFoundation\Request');
|
||||
$request->getLocale()->willReturn('fr');
|
||||
self::$kernel->getContainer()->get('request_stack')
|
||||
->push($request->reveal());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return CustomField
|
||||
*/
|
||||
private function getSimpleCustomFieldText()
|
||||
{
|
||||
return (new CustomField())
|
||||
->setSlug('test')
|
||||
->setName(array('fr' => 'Test'))
|
||||
->setType('text')
|
||||
->setOrdering(10)
|
||||
->setOptions(array("maxLength" => 255))
|
||||
->setActive(true)
|
||||
;
|
||||
}
|
||||
|
||||
public function testLabelRendering()
|
||||
{
|
||||
$cf = $this->getSimpleCustomFieldText();
|
||||
|
||||
$text = $this->cfRendering->renderLabel($cf);
|
||||
|
||||
$this->assertContains('Test', $text,
|
||||
"The rendering text should contains the 'test' text");
|
||||
}
|
||||
|
||||
public function testWidgetRendering()
|
||||
{
|
||||
$cf = $this->getSimpleCustomFieldText();
|
||||
$fields = array(
|
||||
'test' => "My tailor is rich"
|
||||
);
|
||||
|
||||
$text = $this->cfRendering->renderWidget($fields, $cf);
|
||||
|
||||
$this->assertContains('My tailor is rich', $text,
|
||||
"The rendering text should contains the 'test' text");
|
||||
}
|
||||
|
||||
public function testIsEmpty()
|
||||
{
|
||||
$cf = $this->getSimpleCustomFieldText();
|
||||
|
||||
// value is not empty
|
||||
$fields = array(
|
||||
'test' => "My tailor is rich"
|
||||
);
|
||||
|
||||
$result = $this->cfRendering->isEmptyValue($fields, $cf);
|
||||
|
||||
$this->assertFalse($result);
|
||||
|
||||
// value is empty
|
||||
$fields = array(
|
||||
'text' => ''
|
||||
);
|
||||
|
||||
$result = $this->cfRendering->isEmptyValue($fields, $cf);
|
||||
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
<?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\CustomFields\Tests\Templating\Twig;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Chill\CustomFieldsBundle\Templating\Twig\CustomFieldsGroupRenderingTwig;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomField;
|
||||
use Chill\CustomFieldsBundle\Service\CustomFieldProvider;
|
||||
use Chill\CustomFieldsBundle\Entity\CustomFieldsGroup;
|
||||
|
||||
/**
|
||||
* Test the rendering of a custom fields group through
|
||||
* the `chill_custom_fields_group_widget`
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
* @author Champs Libres <info@champs-libres.coop>
|
||||
*/
|
||||
class CustomFieldsGroupRenderingTwigTest extends KernelTestCase
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var CustomFieldsGroupRenderingTwig
|
||||
*/
|
||||
private $cfRendering;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var CustomFieldProvider
|
||||
*/
|
||||
private $cfProvider;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
self::bootKernel();
|
||||
$this->cfRendering = self::$kernel->getContainer()
|
||||
->get('chill.custom_field.twig.custom_fields_group_rendering')
|
||||
;
|
||||
|
||||
$this->cfProvider = self::$kernel->getContainer()
|
||||
->get('chill.custom_field.provider');
|
||||
|
||||
// set locale to fr
|
||||
$prophet = new \Prophecy\Prophet;
|
||||
$request = $prophet->prophesize();
|
||||
$request->willExtend('Symfony\Component\HttpFoundation\Request');
|
||||
$request->getLocale()->willReturn('fr');
|
||||
self::$kernel->getContainer()->get('request_stack')
|
||||
->push($request->reveal());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return CustomField
|
||||
*/
|
||||
private function getSimpleCustomFieldText($slug, $name)
|
||||
{
|
||||
return (new CustomField())
|
||||
->setSlug($slug)
|
||||
->setName(array('fr' => $name))
|
||||
->setType('text')
|
||||
->setOrdering(10)
|
||||
->setOptions(array("maxLength" => 255))
|
||||
->setActive(true)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return CustomFieldsGroup
|
||||
*/
|
||||
private function getCustomFieldsGroup()
|
||||
{
|
||||
return (new CustomFieldsGroup())
|
||||
->setEntity('\Dummy')
|
||||
->setName(array("fr" => "A cf group"))
|
||||
->addCustomField($this->getSimpleCustomFieldText("horses", "Do you like horses ?."))
|
||||
->addCustomField($this->getSimpleCustomFieldText("sure", "Are you sure ?"))
|
||||
;
|
||||
}
|
||||
|
||||
public function testRenderingWidget()
|
||||
{
|
||||
$cfGroup = $this->getCustomFieldsGroup();
|
||||
|
||||
$text = $this->cfRendering->renderWidget(array(
|
||||
'horses' => 'I like horses',
|
||||
'sure' => 'Yes !'
|
||||
), $cfGroup);
|
||||
|
||||
$this->assertContains('Do you like horses', $text);
|
||||
$this->assertContains('I like horses', $text);
|
||||
$this->assertContains('Are you sure', $text);
|
||||
$this->assertContains('Yes', $text);
|
||||
}
|
||||
|
||||
public function testRenderingWidgetDoNotShowEmpty()
|
||||
{
|
||||
$cfGroup = $this->getCustomFieldsGroup();
|
||||
$cfGroup->addCustomField($this->getSimpleCustomFieldText('empty', 'Do not answer'));
|
||||
|
||||
$text = $this->cfRendering->renderWidget(array(
|
||||
'horses' => 'I like horses',
|
||||
'sure' => 'Yes !'
|
||||
), $cfGroup, 'html', array('show_empty' => false));
|
||||
|
||||
$this->assertContains('Do you like horses', $text);
|
||||
$this->assertContains('I like horses', $text);
|
||||
$this->assertContains('Are you sure', $text);
|
||||
$this->assertContains('Yes', $text);
|
||||
$this->assertNotContains('Do not answer', $text);
|
||||
}
|
||||
}
|
8
src/Bundle/ChillCustomFields/Tests/bootstrap.php
Normal file
8
src/Bundle/ChillCustomFields/Tests/bootstrap.php
Normal file
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
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;
|
||||
|
15
src/Bundle/ChillCustomFields/apigen.neon
Normal file
15
src/Bundle/ChillCustomFields/apigen.neon
Normal file
@ -0,0 +1,15 @@
|
||||
# configuration for apigen
|
||||
|
||||
|
||||
source:
|
||||
- .
|
||||
|
||||
accessLevels: ["public", "protected"]
|
||||
|
||||
exclude:
|
||||
- vendor/*
|
||||
- Resources/test/*
|
||||
- Tests/Fixtures/*
|
||||
|
||||
title: Chill CustomFields Bundle
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user