From 1b4f4bba22f9e8cc47ab1425466dfa642a22f263 Mon Sep 17 00:00:00 2001 From: Kevin Papst Date: Wed, 12 Feb 2020 15:35:42 +0100 Subject: [PATCH] added option to use only pre-defined tags (#1463) --- ...tCommand.php => ImportCustomerCommand.php} | 2 +- src/Configuration/ThemeConfiguration.php | 7 ++++ .../SystemConfigurationController.php | 5 +++ src/DependencyInjection/Configuration.php | 5 ++- src/Form/API/TimesheetApiEditForm.php | 14 +++++++ src/Form/FormTrait.php | 10 ++--- src/Form/MultiUpdate/TimesheetMultiUpdate.php | 4 +- src/Form/Toolbar/AbstractToolbarForm.php | 14 +------ src/Form/Type/TagsInputType.php | 5 +++ src/Form/Type/TagsSelectType.php | 1 + src/Form/Type/TagsType.php | 38 +++++++++++++++++++ .../Configuration/ThemeConfigurationTest.php | 12 +++++- .../DependencyInjection/AppExtensionTest.php | 1 + .../DependencyInjection/ConfigurationTest.php | 1 + translations/system-configuration.de.xlf | 4 ++ translations/system-configuration.en.xlf | 4 ++ 16 files changed, 103 insertions(+), 24 deletions(-) rename src/Command/{ImportProjectCommand.php => ImportCustomerCommand.php} (99%) create mode 100644 src/Form/Type/TagsType.php diff --git a/src/Command/ImportProjectCommand.php b/src/Command/ImportCustomerCommand.php similarity index 99% rename from src/Command/ImportProjectCommand.php rename to src/Command/ImportCustomerCommand.php index 8ee7c960..349af4a0 100644 --- a/src/Command/ImportProjectCommand.php +++ b/src/Command/ImportCustomerCommand.php @@ -32,7 +32,7 @@ use Symfony\Component\Console\Style\SymfonyStyle; * @internal * @codeCoverageIgnore */ -class ImportProjectCommand extends Command +class ImportCustomerCommand extends Command { protected static $defaultName = 'kimai:import:customer'; diff --git a/src/Configuration/ThemeConfiguration.php b/src/Configuration/ThemeConfiguration.php index c7366993..2809b937 100644 --- a/src/Configuration/ThemeConfiguration.php +++ b/src/Configuration/ThemeConfiguration.php @@ -23,12 +23,19 @@ class ThemeConfiguration implements SystemBundleConfiguration, \ArrayAccess return (bool) $this->find('auto_reload_datatable'); } + public function isAllowTagCreation(): bool + { + return (bool) $this->find('tags_create'); + } + /** * Currently unused, as JS selects are always activated. * @deprecated since 1.7 will be removed with 2.0 */ public function getSelectPicker(): string { + @trigger_error('getSelectPicker() is deprecated and will be removed with 2.0', E_USER_DEPRECATED); + return (string) $this->find('select_type'); } diff --git a/src/Controller/SystemConfigurationController.php b/src/Controller/SystemConfigurationController.php index 6ccf55a5..6379aeec 100644 --- a/src/Controller/SystemConfigurationController.php +++ b/src/Controller/SystemConfigurationController.php @@ -301,6 +301,11 @@ class SystemConfigurationController extends AbstractController ->setLabel('theme.markdown_content') ->setType(CheckboxType::class) ->setTranslationDomain('system-configuration'), + (new Configuration()) + ->setName('theme.tags_create') + ->setLabel('theme.tags_create') + ->setType(CheckboxType::class) + ->setTranslationDomain('system-configuration'), // TODO should that be configurable per user? /* (new Configuration()) diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 5146e142..2aea99a2 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -329,9 +329,12 @@ class Configuration implements ConfigurationInterface ->defaultValue('selectpicker') ->setDeprecated() ->end() - ->scalarNode('auto_reload_datatable') + ->booleanNode('auto_reload_datatable') ->defaultFalse() ->end() + ->booleanNode('tags_create') + ->defaultTrue() + ->end() ->booleanNode('show_about') ->defaultTrue() ->end() diff --git a/src/Form/API/TimesheetApiEditForm.php b/src/Form/API/TimesheetApiEditForm.php index 9c90cce9..eff1e67b 100644 --- a/src/Form/API/TimesheetApiEditForm.php +++ b/src/Form/API/TimesheetApiEditForm.php @@ -10,6 +10,7 @@ namespace App\Form\API; use App\Form\TimesheetEditForm; +use App\Form\Type\TagsInputType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -29,6 +30,19 @@ class TimesheetApiEditForm extends TimesheetEditForm } } + /** + * Method added to prevent API BC breaks. + * + * @param FormBuilderInterface $builder + */ + protected function addTags(FormBuilderInterface $builder) + { + $builder + ->add('tags', TagsInputType::class, [ + 'required' => false, + ]); + } + public function configureOptions(OptionsResolver $resolver) { parent::configureOptions($resolver); diff --git a/src/Form/FormTrait.php b/src/Form/FormTrait.php index 876d21e5..fa423874 100644 --- a/src/Form/FormTrait.php +++ b/src/Form/FormTrait.php @@ -15,7 +15,7 @@ use App\Entity\Project; use App\Form\Type\ActivityType; use App\Form\Type\CustomerType; use App\Form\Type\ProjectType; -use App\Form\Type\TagsInputType; +use App\Form\Type\TagsType; use App\Repository\ActivityRepository; use App\Repository\CustomerRepository; use App\Repository\ProjectRepository; @@ -29,6 +29,7 @@ use Symfony\Component\Form\FormEvents; /** * Defines the form used to manipulate Timesheet entries. + * @internal */ trait FormTrait { @@ -148,12 +149,7 @@ trait FormTrait protected function addTags(FormBuilderInterface $builder) { $builder - ->add('tags', TagsInputType::class, [ - // documentation is for NelmioApiDocBundle - 'documentation' => [ - 'type' => 'string', - 'description' => 'Comma separated list of tags', - ], + ->add('tags', TagsType::class, [ 'required' => false, ]); } diff --git a/src/Form/MultiUpdate/TimesheetMultiUpdate.php b/src/Form/MultiUpdate/TimesheetMultiUpdate.php index 76698be9..d4ae4669 100644 --- a/src/Form/MultiUpdate/TimesheetMultiUpdate.php +++ b/src/Form/MultiUpdate/TimesheetMultiUpdate.php @@ -14,7 +14,7 @@ use App\Form\Type\CustomerType; use App\Form\Type\FixedRateType; use App\Form\Type\HourlyRateType; use App\Form\Type\ProjectType; -use App\Form\Type\TagsInputType; +use App\Form\Type\TagsType; use App\Form\Type\UserType; use App\Form\Type\YesNoType; use App\Repository\ActivityRepository; @@ -180,7 +180,7 @@ class TimesheetMultiUpdate extends AbstractType ] ]); - $builder->add('tags', TagsInputType::class, [ + $builder->add('tags', TagsType::class, [ 'required' => false, ]); diff --git a/src/Form/Toolbar/AbstractToolbarForm.php b/src/Form/Toolbar/AbstractToolbarForm.php index 57f7a114..30d90c17 100644 --- a/src/Form/Toolbar/AbstractToolbarForm.php +++ b/src/Form/Toolbar/AbstractToolbarForm.php @@ -15,8 +15,7 @@ use App\Form\Type\DateRangeType; use App\Form\Type\PageSizeType; use App\Form\Type\ProjectType; use App\Form\Type\SearchTermType; -use App\Form\Type\TagsInputType; -use App\Form\Type\TagsSelectType; +use App\Form\Type\TagsType; use App\Form\Type\UserRoleType; use App\Form\Type\UserType; use App\Form\Type\VisibilityType; @@ -225,20 +224,11 @@ abstract class AbstractToolbarForm extends AbstractType protected function addTagInputField(FormBuilderInterface $builder) { - $builder->add('tags', TagsInputType::class, [ + $builder->add('tags', TagsType::class, [ 'required' => false ]); } - // TODO add a system setting to control if tags can be created on the fly - protected function addTagSelectField(FormBuilderInterface $builder) - { - $builder->add('tags', TagsSelectType::class, [ - 'required' => false, - 'multiple' => true, - ]); - } - protected function addSearchTermInputField(FormBuilderInterface $builder) { $builder->add('searchTerm', SearchTermType::class); diff --git a/src/Form/Type/TagsInputType.php b/src/Form/Type/TagsInputType.php index 847f163a..c9bd431a 100644 --- a/src/Form/Type/TagsInputType.php +++ b/src/Form/Type/TagsInputType.php @@ -58,6 +58,11 @@ class TagsInputType extends AbstractType public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ + // documentation is for NelmioApiDocBundle + 'documentation' => [ + 'type' => 'string', + 'description' => 'Comma separated list of tags', + ], 'label' => 'label.tag', 'attr' => [ 'data-autocomplete-url' => $this->router->generate('get_tags'), diff --git a/src/Form/Type/TagsSelectType.php b/src/Form/Type/TagsSelectType.php index 8dc046b8..c5788e4f 100644 --- a/src/Form/Type/TagsSelectType.php +++ b/src/Form/Type/TagsSelectType.php @@ -28,6 +28,7 @@ class TagsSelectType extends AbstractType public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ + 'multiple' => true, 'class' => Tag::class, 'label' => 'label.tag', 'choice_label' => function (Tag $tag) { diff --git a/src/Form/Type/TagsType.php b/src/Form/Type/TagsType.php new file mode 100644 index 00000000..a738c472 --- /dev/null +++ b/src/Form/Type/TagsType.php @@ -0,0 +1,38 @@ +configuration = $configuration; + } + + /** + * {@inheritdoc} + */ + public function getParent() + { + if ($this->configuration->isAllowTagCreation()) { + return TagsInputType::class; + } + + return TagsSelectType::class; + } +} diff --git a/tests/Configuration/ThemeConfigurationTest.php b/tests/Configuration/ThemeConfigurationTest.php index 0b45203f..513b7ea7 100644 --- a/tests/Configuration/ThemeConfigurationTest.php +++ b/tests/Configuration/ThemeConfigurationTest.php @@ -48,6 +48,7 @@ class ThemeConfigurationTest extends TestCase 'title' => null, ], 'auto_reload_datatable' => false, + 'tags_create' => true, ]; } @@ -61,7 +62,16 @@ class ThemeConfigurationTest extends TestCase { $sut = $this->getSut($this->getDefaultSettings(), []); $this->assertFalse($sut->isAutoReloadDatatable()); - $this->assertEquals('', $sut->getSelectPicker()); + $this->assertTrue($sut->isAllowTagCreation()); $this->assertNull($sut->getTitle()); } + + /** + * @group legacy + */ + public function testDeprecations() + { + $sut = $this->getSut($this->getDefaultSettings(), []); + $this->assertEquals('', $sut->getSelectPicker()); + } } diff --git a/tests/DependencyInjection/AppExtensionTest.php b/tests/DependencyInjection/AppExtensionTest.php index 8cd6ab17..91cb0006 100644 --- a/tests/DependencyInjection/AppExtensionTest.php +++ b/tests/DependencyInjection/AppExtensionTest.php @@ -171,6 +171,7 @@ class AppExtensionTest extends TestCase ], 'auto_reload_datatable' => false, 'autocomplete_chars' => 3, + 'tags_create' => true, ], 'kimai.theme.select_type' => 'selectpicker', 'kimai.theme.show_about' => true, diff --git a/tests/DependencyInjection/ConfigurationTest.php b/tests/DependencyInjection/ConfigurationTest.php index e90e8b79..60215405 100644 --- a/tests/DependencyInjection/ConfigurationTest.php +++ b/tests/DependencyInjection/ConfigurationTest.php @@ -337,6 +337,7 @@ class ConfigurationTest extends TestCase 'translation' => null, ], 'autocomplete_chars' => 3, + 'tags_create' => true, ], 'industry' => [ 'translation' => null, diff --git a/translations/system-configuration.de.xlf b/translations/system-configuration.de.xlf index 5d632367..f7ac9b4b 100644 --- a/translations/system-configuration.de.xlf +++ b/translations/system-configuration.de.xlf @@ -34,6 +34,10 @@ label.theme.markdown_content Erlaube Markdown-Formatierungen in Beschreibungen und Kommentaren + + label.theme.tags_create + Schlagworte: Suche per Auto-Complete und Erstellung von Schlagworten erlauben + label.timesheet.mode Zeiterfassungs Modus diff --git a/translations/system-configuration.en.xlf b/translations/system-configuration.en.xlf index b4438e65..2d1d1532 100644 --- a/translations/system-configuration.en.xlf +++ b/translations/system-configuration.en.xlf @@ -34,6 +34,10 @@ label.theme.markdown_content Allow markdown-formattings in descriptions and comments + + label.theme.tags_create + Tags: use auto-complete search and allow tag creation + label.timesheet.mode Timetracking mode