From d1fd359366c7035fa9e3f8c29dbf9909b982d337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Tue, 27 Mar 2018 16:35:56 +0200 Subject: [PATCH 1/4] add a date field --- CustomFields/CustomFieldDate.php | 232 ++++++++++++++++++ Resources/config/services.yml | 8 + Resources/translations/messages.fr.yml | 5 + Resources/translations/validators.fr.yml | 4 +- .../CustomFieldsRendering/date.html.twig | 1 + 5 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 CustomFields/CustomFieldDate.php create mode 100644 Resources/views/CustomFieldsRendering/date.html.twig diff --git a/CustomFields/CustomFieldDate.php b/CustomFields/CustomFieldDate.php new file mode 100644 index 000000000..d5b109000 --- /dev/null +++ b/CustomFields/CustomFieldDate.php @@ -0,0 +1,232 @@ +, + * + * 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 . + */ + +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é + */ +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) + { + dump('desirialize'); + 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') + { + $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); + } + +} diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 08953ef82..500ad2ff7 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -87,6 +87,14 @@ services: - "@chill.main.helper.translatable_string" tags: - { name: 'chill.custom_field', type: 'title' } + + chill.custom_field.date: + class: Chill\CustomFieldsBundle\CustomFields\CustomFieldDate + arguments: + - "@templating" + - "@chill.main.helper.translatable_string" + tags: + - { name: 'chill.custom_field', type: 'date' } chill.custom_field.helper: class: Chill\CustomFieldsBundle\Service\CustomFieldsHelper diff --git a/Resources/translations/messages.fr.yml b/Resources/translations/messages.fr.yml index a80f4ea08..446176c51 100644 --- a/Resources/translations/messages.fr.yml +++ b/Resources/translations/messages.fr.yml @@ -57,6 +57,7 @@ choice: choix Title: Titre text: texte Text field: Champ texte +Date field: Champ date #custom field choice Multiplicity: Multiplicité @@ -94,3 +95,7 @@ Number field: Champ nombre Options key: Clé des options Choose a value: Choisissez une valeur Long choice field: Champ à choix pré-enregistrés + +#Custom field date +Greater or equal than (expression like 1 day ago, 2 years ago, +1 month, today, tomorrow, or date with format YYYY-mm-dd): Date après (indiquer une expression PHP comme '1 day ago', '2 years ago', '+1 month', 'today', 'tomorrow', ...) +Lesser or equal than (expression like 1 day ago, 2 years ago, +1 month, today, tomorrow, or date with format YYYY-mm-dd): Date avant (indiquer une expression PHP comme '1 day ago', '2 years ago', '+1 month', 'today', 'tomorrow', ...) \ No newline at end of file diff --git a/Resources/translations/validators.fr.yml b/Resources/translations/validators.fr.yml index afb6575ba..9747f4498 100644 --- a/Resources/translations/validators.fr.yml +++ b/Resources/translations/validators.fr.yml @@ -1 +1,3 @@ -Characters not allowed. Only lowercase letters, numbers and "-" are allowed.: Caractères non autorisés. Seules les lettres minuscules, les nombres et le tiret ("-") sont autorisés. \ No newline at end of file +Characters not allowed. Only lowercase letters, numbers and "-" are allowed.: Caractères non autorisés. Seules les lettres minuscules, les nombres et le tiret ("-") sont autorisés. +'This date must be after or equal to %date%': Cette date doit être égale ou postérieure au %date% +'This date must be before or equal to %date%': Cette date doit être antérieure ou égale au %date% \ No newline at end of file diff --git a/Resources/views/CustomFieldsRendering/date.html.twig b/Resources/views/CustomFieldsRendering/date.html.twig new file mode 100644 index 000000000..87d7f5567 --- /dev/null +++ b/Resources/views/CustomFieldsRendering/date.html.twig @@ -0,0 +1 @@ +{% if value is not empty %}{{ value|localizeddate(format, 'none')}}{% endif %} From 01fbf172e38a91a3b3bcf2f50635b2f7ee7b03fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Tue, 27 Mar 2018 17:47:04 +0200 Subject: [PATCH 2/4] remove dump --- CustomFields/CustomFieldDate.php | 1 - 1 file changed, 1 deletion(-) diff --git a/CustomFields/CustomFieldDate.php b/CustomFields/CustomFieldDate.php index d5b109000..89f76fae0 100644 --- a/CustomFields/CustomFieldDate.php +++ b/CustomFields/CustomFieldDate.php @@ -195,7 +195,6 @@ class CustomFieldDate extends AbstractCustomField public function deserialize($serialized, CustomField $customField) { - dump('desirialize'); if (empty($serialized)) { return null; } From e8b5bdf68eebbc7423daa739537e9b4fbd4d03c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 4 Apr 2018 13:01:05 +0200 Subject: [PATCH 3/4] set dependency to upgrade-sf3 for this branch --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 06fd2dd2d..378fb9a27 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,7 @@ "doctrine/doctrine-migrations-bundle": "~1.1", "doctrine/migrations": "~1.0", "symfony/monolog-bundle": "^2.7", - "chill-project/main": "dev-master@dev", + "chill-project/main": "dev-upgrade-sf3@dev", "phpoffice/phpspreadsheet": "dev-develop#9e835676a6a2df9f7e445a28d4d89f6bd296a7c5@dev" }, "require-dev": { From dd5416f88dcf26cbbbf63ddc1eb5cad331644d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 4 Apr 2018 13:02:31 +0200 Subject: [PATCH 4/4] Revert "set dependency to upgrade-sf3 for this branch" This reverts commit e8b5bdf68eebbc7423daa739537e9b4fbd4d03c6. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 378fb9a27..06fd2dd2d 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,7 @@ "doctrine/doctrine-migrations-bundle": "~1.1", "doctrine/migrations": "~1.0", "symfony/monolog-bundle": "^2.7", - "chill-project/main": "dev-upgrade-sf3@dev", + "chill-project/main": "dev-master@dev", "phpoffice/phpspreadsheet": "dev-develop#9e835676a6a2df9f7e445a28d4d89f6bd296a7c5@dev" }, "require-dev": {