From 6bcc3ebcc2dfbb6b2040738a9813dd6e49a88660 Mon Sep 17 00:00:00 2001 From: Ross Keatinge Date: Sun, 27 Jul 2014 17:29:42 -0400 Subject: [PATCH] First real commit --- DependencyInjection/Configuration.php | 36 +++++++++ .../TetranzSelect2EntityExtension.php | 34 ++++++++ .../EntitiesToPropertyTransformer.php | 64 +++++++++++++++ .../EntityToPropertyTransformer.php | 45 +++++++++++ Form/Type/Select2EntityType.php | 81 +++++++++++++++++++ Resources/config/services.yml | 8 ++ Resources/public/js/select2entity.js | 71 ++++++++++++++++ Resources/views/Form/fields.html.twig | 14 ++++ Tests/Controller/DefaultControllerTest.php | 17 ++++ TetranzSelect2EntityBundle.php | 9 +++ 10 files changed, 379 insertions(+) create mode 100644 DependencyInjection/Configuration.php create mode 100644 DependencyInjection/TetranzSelect2EntityExtension.php create mode 100644 Form/DataTransformer/EntitiesToPropertyTransformer.php create mode 100644 Form/DataTransformer/EntityToPropertyTransformer.php create mode 100644 Form/Type/Select2EntityType.php create mode 100644 Resources/config/services.yml create mode 100644 Resources/public/js/select2entity.js create mode 100644 Resources/views/Form/fields.html.twig create mode 100644 Tests/Controller/DefaultControllerTest.php create mode 100644 TetranzSelect2EntityBundle.php diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php new file mode 100644 index 0000000..115e075 --- /dev/null +++ b/DependencyInjection/Configuration.php @@ -0,0 +1,36 @@ +root('tetranz_select2_entity'); + + $rootNode + ->children() + ->scalarNode('minimum_input_length')->defaultValue(1)->end() + ->scalarNode('page_limit')->defaultValue(10)->end() + ->scalarNode('data_type')->defaultValue('json')->end() + ->end(); + + // Here you should define the parameters that are allowed to + // configure your bundle. See the documentation linked above for + // more information on that topic. + + return $treeBuilder; + } +} diff --git a/DependencyInjection/TetranzSelect2EntityExtension.php b/DependencyInjection/TetranzSelect2EntityExtension.php new file mode 100644 index 0000000..00c6dee --- /dev/null +++ b/DependencyInjection/TetranzSelect2EntityExtension.php @@ -0,0 +1,34 @@ +processConfiguration($configuration, $configs); + + $varNames = ['minimum_input_length', 'page_limit', 'data_type']; + + foreach($varNames as $varName) { + $container->setParameter("tetranz_select2_entity.$varName", $config[$varName]); + } + + $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader->load('services.yml'); + } +} diff --git a/Form/DataTransformer/EntitiesToPropertyTransformer.php b/Form/DataTransformer/EntitiesToPropertyTransformer.php new file mode 100644 index 0000000..a0ebcb3 --- /dev/null +++ b/Form/DataTransformer/EntitiesToPropertyTransformer.php @@ -0,0 +1,64 @@ +em = $em; + $this->className = $class; + $this->property = $property; + } + + public function transform($entities) + { + if (count($entities) == 0) { + return ''; + } + + $items = array(); + + foreach($entities as $entity) { + $items[] = $entity->getId() . '|' . $entity->getName(); + } + + return implode('|', $items); + } + + public function reverseTransform($values) + { + // $values has a leading comma + $values = ltrim($values, ','); + + if (null === $values || '' === $values) { + return array(); + } + + $ids = explode(',', $values); + + // get multiple entities with one query + $entities = $this->em->createQueryBuilder() + ->select('entity') + ->from($this->className, 'entity') + ->where('entity.id IN (:ids)') + ->setParameter('ids', $ids) + ->getQuery() + ->getResult(); + + return $entities; + } +} diff --git a/Form/DataTransformer/EntityToPropertyTransformer.php b/Form/DataTransformer/EntityToPropertyTransformer.php new file mode 100644 index 0000000..efdc074 --- /dev/null +++ b/Form/DataTransformer/EntityToPropertyTransformer.php @@ -0,0 +1,45 @@ +em = $em; + $this->className = $class; + $this->property = $property; + } + + public function transform($entity) + { + if (null === $entity || '' === $entity) { + return ''; + } + + return $entity->getId() . '|' . $entity->getName(); + } + + public function reverseTransform($value) + { + if (null === $value || '' === $value) { + return null; + } + + $repo = $this->em->getRepository($this->className); + return $repo->find($value); + } +} diff --git a/Form/Type/Select2EntityType.php b/Form/Type/Select2EntityType.php new file mode 100644 index 0000000..97c7cbd --- /dev/null +++ b/Form/Type/Select2EntityType.php @@ -0,0 +1,81 @@ +em = $em; + $this->router = $router; + $this->minimumInputLength = $minimumInputLength; + $this->pageLimit = $pageLimit; + $this->dataType = $dataType; + } + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $transformer = $options['multiple'] + ? new EntitiesToPropertyTransformer($this->em, $options['class']) + : new EntityToPropertyTransformer($this->em, $options['class']); + + $builder->addViewTransformer($transformer, true); + } + + public function finishView(FormView $view, FormInterface $form, array $options) + { + parent::finishView($view, $form, $options); + + $view->vars['remote_path'] = $options['remote_path'] + ?: $this->router->generate($options['remote_route'], $options['remote_params']); + + $varNames = array('multiple', 'minimum_input_length', 'page_limit', 'data_type'); + + foreach($varNames as $varName) { + $view->vars[$varName] = $options[$varName]; + } + } + + public function setDefaultOptions(OptionsResolverInterface $resolver) + { + $resolver->setDefaults(array( + 'class' => null, + 'remote_path' => null, + 'remote_route' => null, + 'remote_params' => array(), + 'multiple' => false, + 'compound' => false, + 'minimum_input_length' => $this->minimumInputLength, + 'page_limit' => $this->pageLimit, + 'data_type' => $this->dataType + )); + } + + public function getName() + { + return 'tetranz_select2entity'; + } +} diff --git a/Resources/config/services.yml b/Resources/config/services.yml new file mode 100644 index 0000000..f8c327f --- /dev/null +++ b/Resources/config/services.yml @@ -0,0 +1,8 @@ +parameters: + tetranz_select2entity.select2entity_type.class: Tetranz\Select2EntityBundle\Form\Type\Select2EntityType + +services: + tetranz_select2entity.select2entity_type: + class: %tetranz_select2entity.select2entity_type.class% + arguments: [@doctrine.orm.entity_manager, @router, %tetranz_select2_entity.minimum_input_length%, %tetranz_select2_entity.page_limit%, , %tetranz_select2_entity.data_type%] + tags: [{ name: form.type, alias: tetranz_select2entity }] diff --git a/Resources/public/js/select2entity.js b/Resources/public/js/select2entity.js new file mode 100644 index 0000000..d4221d9 --- /dev/null +++ b/Resources/public/js/select2entity.js @@ -0,0 +1,71 @@ +$(document).ready(function () { + + $('.select2entity').each(function(index) { + var initValue; + var multiple = $(this).data('multiple'); + + var options = { + placeholder: 'Search a country', + allowClear: true, + multiple: multiple, + minimumInputLength: $(this).data('min-length'), + ajax: { + url: $(this).data('rpath'), + dataType: $(this).data('data-type'), + data: function (term, page) { + return { + q: term, + page_limit: $(this).data('page-limit') + }; + }, + results: function (data, page) { + return {results: data}; + } + }, + + initSelection : function (element, callback) { + + var value = element.data('value'); + + if (multiple) { + + initValue = []; + + if (value !== '') { + + var parts = value.split('|'); + var length = parts.length; + + for(var i = 0; i < length; i += 2) { + initValue.push({id: parts[i], text: parts[i+1]}) + } + + } + } + + else { + + if (value === '') { + initValue = {id:'', text:''}; + } + else { + var parts = value.split('|'); + initValue = {id: parts[0], text: parts[1]}; + } + + } + + callback(initValue); + } + + }; + + $(this).select2(options); + + if (!multiple) { + $(this).select2('data', initValue); + } + + }); + +}); diff --git a/Resources/views/Form/fields.html.twig b/Resources/views/Form/fields.html.twig new file mode 100644 index 0000000..ef75422 --- /dev/null +++ b/Resources/views/Form/fields.html.twig @@ -0,0 +1,14 @@ +{% block tetranz_select2entity_widget %} + {% set attr = attr|merge({ + 'data-multiple':multiple ? 1:0, + 'data-rpath':remote_path, + 'data-value':value, + 'data-min-length':minimum_input_length, + 'data-page-limit':page_limit, + 'data-data-type':data_type + }) %} + + {% set value = ' ' %} + {% set type = type|default('hidden') %} + {{ block('form_widget_simple') }} +{% endblock %} diff --git a/Tests/Controller/DefaultControllerTest.php b/Tests/Controller/DefaultControllerTest.php new file mode 100644 index 0000000..74b00bd --- /dev/null +++ b/Tests/Controller/DefaultControllerTest.php @@ -0,0 +1,17 @@ +request('GET', '/hello/Fabien'); + + $this->assertTrue($crawler->filter('html:contains("Hello Fabien")')->count() > 0); + } +} diff --git a/TetranzSelect2EntityBundle.php b/TetranzSelect2EntityBundle.php new file mode 100644 index 0000000..a327226 --- /dev/null +++ b/TetranzSelect2EntityBundle.php @@ -0,0 +1,9 @@ +