Skip to content

Commit

Permalink
First real commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Ross Keatinge committed Jul 27, 2014
1 parent a7ab580 commit 6bcc3eb
Show file tree
Hide file tree
Showing 10 changed files with 379 additions and 0 deletions.
36 changes: 36 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Tetranz\Select2EntityBundle\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();
$rootNode = $treeBuilder->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;
}
}
34 changes: 34 additions & 0 deletions DependencyInjection/TetranzSelect2EntityExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace Tetranz\Select2EntityBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;

/**
* 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 TetranzSelect2EntityExtension extends Extension
{
/**
* {@inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->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');
}
}
64 changes: 64 additions & 0 deletions Form/DataTransformer/EntitiesToPropertyTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php
/**
* Created by PhpStorm.
* User: ross
* Date: 7/19/14
* Time: 8:11 AM
*/

namespace Tetranz\Select2EntityBundle\Form\DataTransformer;

use Doctrine\ORM\EntityManager;
use Symfony\Component\Form\DataTransformerInterface;

class EntitiesToPropertyTransformer implements DataTransformerInterface
{
protected $em;
protected $className;
protected $property;

public function __construct(EntityManager $em, $class, $property = 'id')
{
$this->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;
}
}
45 changes: 45 additions & 0 deletions Form/DataTransformer/EntityToPropertyTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php
/**
* Created by PhpStorm.
* User: ross
* Date: 7/19/14
* Time: 8:11 AM
*/

namespace Tetranz\Select2EntityBundle\Form\DataTransformer;

use Doctrine\ORM\EntityManager;
use Symfony\Component\Form\DataTransformerInterface;

class EntityToPropertyTransformer implements DataTransformerInterface
{
protected $em;
protected $className;
protected $property;

public function __construct(EntityManager $em, $class, $property = 'id')
{
$this->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);
}
}
81 changes: 81 additions & 0 deletions Form/Type/Select2EntityType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php
/**
* Created by PhpStorm.
* User: ross
* Date: 7/17/14
* Time: 9:40 PM
*/

namespace Tetranz\Select2EntityBundle\Form\Type;

use Doctrine\ORM\EntityManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Routing\Router;
use Tetranz\Select2EntityBundle\Form\DataTransformer\EntitiesToPropertyTransformer;
use Tetranz\Select2EntityBundle\Form\DataTransformer\EntityToPropertyTransformer;

class Select2EntityType extends AbstractType
{
protected $em;
protected $router;
protected $pageLimit;
protected $minimumInputLength;
protected $dataType;

public function __construct(EntityManager $em, Router $router, $minimumInputLength, $pageLimit, $dataType)
{
$this->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';
}
}
8 changes: 8 additions & 0 deletions Resources/config/services.yml
Original file line number Diff line number Diff line change
@@ -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 }]
71 changes: 71 additions & 0 deletions Resources/public/js/select2entity.js
Original file line number Diff line number Diff line change
@@ -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);
}

});

});
14 changes: 14 additions & 0 deletions Resources/views/Form/fields.html.twig
Original file line number Diff line number Diff line change
@@ -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 %}
17 changes: 17 additions & 0 deletions Tests/Controller/DefaultControllerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Tetranz\Select2EntityBundle\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class DefaultControllerTest extends WebTestCase
{
public function testIndex()
{
$client = static::createClient();

$crawler = $client->request('GET', '/hello/Fabien');

$this->assertTrue($crawler->filter('html:contains("Hello Fabien")')->count() > 0);
}
}
9 changes: 9 additions & 0 deletions TetranzSelect2EntityBundle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Tetranz\Select2EntityBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class TetranzSelect2EntityBundle extends Bundle
{
}

0 comments on commit 6bcc3eb

Please sign in to comment.