Bläddra i källkod

refactory clientId form field

Guillermo Espinoza 8 år sedan
förälder
incheckning
d462ab1526

+ 3 - 1
app/config/config.yml

@@ -41,6 +41,8 @@ framework:
 twig:
     debug:            "%kernel.debug%"
     strict_variables: "%kernel.debug%"
+    form_themes:
+        - 'WebserviceBundle:Type:remote_client_widget.html.twig'
 
 # Doctrine Configuration
 doctrine:
@@ -107,4 +109,4 @@ nelmio_cors:
 sensio_framework_extra:
     request: { converters: true }
     view:    { annotations: false }
-    router:  { annotations: true }            
+    router:  { annotations: true }

+ 1 - 1
app/config/url_webservice.yml

@@ -1,2 +1,2 @@
 parameters:
-    client: 'http://200.50.175.17/base/app_dev.php/api/clients.json'
+    client: 'http://200.50.168.111/base/app_dev.php/api/clients.json'

+ 1 - 3
src/FTTHBundle/Admin/ONUAdmin.php

@@ -61,9 +61,7 @@ class ONUAdmin extends AbstractAdmin
             ->add('mac')
             ->add('serialNumber')
             ->add('ponSerialNumber')
-            ->add('clientId', 'choice', array(
-                'choices' => $this->configurationPool->getContainer()->get('webservice')->getChoices('client')
-            ))
+            ->add('clientId')
         ;
     }
 

+ 5 - 1
src/FTTHBundle/Entity/ONU.php

@@ -54,11 +54,15 @@ class ONU
     /**
      * @var int
      *
-     * @ORM\Column(type="integer")
+     * @ORM\Column(type="integer", nullable=false)
+     * @Assert\NotNull
      */
     private $clientId;
 
 
+    /**
+     * @return string
+     */
     public function __toString()
     {
         return $this->ponSerialNumber;

+ 0 - 1
src/FTTHBundle/Resources/config/routing.yml

@@ -1 +0,0 @@
-

+ 40 - 0
src/WebserviceBundle/Controller/WebserviceController.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace WebserviceBundle\Controller;
+
+use Symfony\Bundle\FrameworkBundle\Controller\Controller;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\JsonResponse;
+
+class WebserviceController extends Controller
+{
+
+    public function getClientListAction(Request $request)
+    {
+        $query = $request->query->get('q', '');
+
+        $choice_loader = $this->get('webservice.client.choiceloader');
+        $choice_list = $choice_loader->getChoicesList($query);
+        $list_values = [];
+
+        if (strlen($query) > 0) {
+            $list_values[] = [
+                'id' => 'create:' . $query,
+                'text' => $query . ' *'
+            ];
+        }
+
+        foreach ($choice_list as $label => $id) {
+            $list_values[] = [
+                'id' => $id,
+                'text' => $label
+            ];
+        }
+
+        $response = new JsonResponse();
+        $response->setData(['results' => $list_values]);
+
+        return $response;
+    }
+
+}

+ 200 - 0
src/WebserviceBundle/Form/ChoiceList/Loader/ClientChoiceLoader.php

@@ -0,0 +1,200 @@
+<?php
+
+namespace WebserviceBundle\Form\ChoiceList\Loader;
+
+use Symfony\Component\Form\ChoiceList\ArrayChoiceList;
+use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\Form\FormEvent;
+use Symfony\Component\Form\FormEvents;
+
+class ClientChoiceLoader implements ChoiceLoaderInterface
+{
+    
+    /**
+     * @var Webservice
+     */
+    protected $webservice;
+
+    // Currently selected choices
+    protected $selected = [];
+
+    
+    /**
+     * @param Webservice $webservice
+     */
+    public function __construct($webservice)
+    {
+        $this->webservice = $webservice;
+    }
+    
+    /**
+     * @param FormBuilderInterface $builder
+     */
+    public function setBuilder(FormBuilderInterface $builder)
+    {
+        if (is_object($builder) && ($builder instanceof FormBuilderInterface)) {
+            $builder->addEventListener(
+                FormEvents::POST_SET_DATA, [$this, 'onFormPostSetData']
+            );
+
+            $builder->addEventListener(
+                FormEvents::POST_SUBMIT, [$this, 'onFormPostSetData']
+            );
+        }
+    }
+
+    /**
+     * Form submit event callback
+     * Here we get notified about the submitted choices.
+     * Remember them so we can add them in loadChoiceList().
+     */
+    public function onFormPostSetData(FormEvent $event)
+    {
+        $this->selected = [];
+
+        $formdata = $event->getData();
+
+        if (!is_object($formdata)) {
+            return;
+        }
+
+        if ($formdata->getClientId()) {
+            $this->selected = array($formdata->getClientId());
+        }
+    }
+
+    /**
+     * Choices to be displayed in the SELECT element.
+     * It's okay to not return all available choices, but the
+     * selected/submitted choices (model values) must be
+     * included.
+     * Required by ChoiceLoaderInterface.
+     */
+    public function loadChoiceList($value = null)
+    {
+        $choices = $this->getChoicesList(false);
+
+        $missing_choices = array_flip($this->selected);
+
+        foreach ($choices as $label => $id) {
+            if (isset($missing_choices[$id])) {
+                unset($missing_choices[$id]);
+            }
+        }
+
+        // Now add selected choices if they're missing
+        foreach (array_keys($missing_choices) as $id) {
+            $label = $this->getChoiceLabel($id);
+
+            if (strlen($label) === 0) {
+                continue;
+            }
+
+            $choices[$label] = $id;
+        }
+        
+        return new ArrayChoiceList($choices);
+    }
+
+    /**
+     * Validate submitted choices, and turn them from strings
+     * (HTML option values) into other datatypes if needed
+     * (not needed here since our choices are strings).
+     * We're also using this place for creating new choices
+     * from new values typed into the autocomplete field.
+     * Required by ChoiceLoaderInterface.
+     */
+    public function loadChoicesForValues(array $values, $value = null)
+    {
+        $result = [];
+        foreach ($values as $id) {
+            if ($this->choiceExists($id)) {
+                $result[] = $id;
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * Turn choices from other datatypes into strings (HTML option
+     * values) if needed - we can simply return the choices as 
+     * they're strings already.
+     * Required by ChoiceLoaderInterface.
+     */
+    public function loadValuesForChoices(array $choices, $value = null)
+    {
+        $result = [];
+        foreach ($choices as $id) {
+            if ($this->choiceExists($id)) {
+                $result[] = $id;
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * Get first n choices
+     */
+    public function getChoicesList($filter)
+    {
+        $params = array();
+        if ($filter !== false) {
+            $params['name'] = $filter;
+        }
+        $choices = $this->webservice->getChoices('client', $params);
+
+        $result = [];
+        $cnt = 0;
+        $limit = 10;
+        $filter = mb_strtolower($filter);
+        $filter_len = mb_strlen($filter);
+
+        foreach ($choices as $label => $id) {
+            if ($filter_len > 0) {
+                if (mb_substr(mb_strtolower($label), 0, $filter_len) !== $filter) {
+                    continue;
+                }
+            }
+
+            $result[$label] = $id;
+
+            if (++$cnt >= $limit) {
+                break;
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * Validate whether a choice exists
+     */
+    protected function choiceExists($id)
+    {
+        $label = array_search($id, $this->initChoices());
+
+        return $label === false ? false : true;
+    }
+
+    /**
+     * Get choice label
+     */
+    protected function getChoiceLabel($id)
+    {
+        $label = array_search($id, $this->initChoices());
+
+        return $label === false ? false : $label;
+    }
+
+    /**
+     * @return array
+     */
+    protected function initChoices()
+    {
+        return $this->webservice->getChoices('client');
+    }
+
+}

+ 43 - 0
src/WebserviceBundle/Form/Type/RemoteClientType.php

@@ -0,0 +1,43 @@
+<?php
+
+namespace WebserviceBundle\Form\Type;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
+use WebserviceBundle\Form\ChoiceList\Loader\ClientChoiceLoader;
+
+class RemoteClientType extends AbstractType
+{
+
+    /**
+     * @var ClientChoiceLoader 
+     */
+    protected $choiceLoader;
+
+    
+    /**
+     * @param ClientChoiceLoader $choiceLoader
+     */
+    public function __construct(ClientChoiceLoader $choiceLoader)
+    {
+        $this->choiceLoader = $choiceLoader;
+    }
+
+    /**
+     * @param OptionsResolver $resolver
+     */
+    public function configureOptions(OptionsResolver $resolver)
+    {
+        $resolver->setDefaults(array(
+            'required' => false,
+            'choice_loader' => $this->choiceLoader
+        ));
+    }
+
+    public function getParent()
+    {
+        return ChoiceType::class;
+    }
+
+}

+ 3 - 0
src/WebserviceBundle/Resources/config/routing.yml

@@ -0,0 +1,3 @@
+ajax_client_list:
+    path:      /ajax_client_list
+    defaults:  { _controller: WebserviceBundle:Webservice:getClientList }

+ 16 - 4
src/WebserviceBundle/Resources/config/services.yml

@@ -1,8 +1,20 @@
 services:
+    
    webservice:
        class: WebserviceBundle\Services\Webservice
        arguments: ["@service_container"]
-#   webservice.admin:
-#        class: WebserviceBundle\Services\Admin
-#        tags:
-#            - { name: kernel.event_listener, event: sonata.admin.event.configure.list, method: addChoices } 
+       
+   webservice.client.choiceloader:
+       class: WebserviceBundle\Form\ChoiceList\Loader\ClientChoiceLoader
+       arguments: ["@webservice"]
+       
+   webservice.client.admin:
+        class: WebserviceBundle\Services\ClientAdmin
+        tags:
+            - { name: kernel.event_listener, event: sonata.admin.event.configure.form, method: addType }
+            
+   webservice.form.type.remoteclient:
+        class: WebserviceBundle\Form\Type\RemoteClientType
+        arguments: ["@webservice.client.choiceloader"]
+        tags:
+            - { name: form.type }            

+ 29 - 0
src/WebserviceBundle/Resources/views/Type/remote_client_widget.html.twig

@@ -0,0 +1,29 @@
+{% block remote_client_widget %}
+    {% spaceless %}
+        {% set locale = app.request.locale %}
+        <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
+        <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>
+        <script type="text/javascript">
+        $(function () {
+            var getAjaxListData = function (params) {
+                return {
+                    q: params.term,
+                    p: params.page
+                };
+            };
+
+            $('select[id$="clientId"]').select2({
+                ajax: {
+                    url: '{{ path('ajax_client_list') }}',
+                    dataType: 'json',
+                    delay: 250,
+                    data: getAjaxListData,
+                    cache: true,
+                    language: '{{ locale }}'
+            }});
+        });
+        </script>
+        {{ block('choice_widget') }}
+    {% endspaceless %}
+{% endblock %}

+ 21 - 0
src/WebserviceBundle/Services/ClientAdmin.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace WebserviceBundle\Services;
+
+use Sonata\AdminBundle\Event\ConfigureEvent;
+use WebserviceBundle\Form\Type\RemoteClientType;
+
+class ClientAdmin
+{
+
+    /**
+     * @param ConfigureEvent $event
+     */
+    public function addType(ConfigureEvent $event)
+    {
+        if ($event->getMapper()->has('clientId')) {
+            $event->getMapper()->add('clientId', RemoteClientType::class);
+        }
+    }
+
+}

+ 10 - 0
src/WebserviceBundle/Services/Webservice.php

@@ -5,9 +5,15 @@ namespace WebserviceBundle\Services;
 class Webservice
 {
 
+    /**
+     * @var ServiceContainer 
+     */
     protected $serviceContainer;
 
     
+    /**
+     * @param ServiceContainer $serviceContainer
+     */
     public function __construct($serviceContainer)
     {
         $this->serviceContainer = $serviceContainer;
@@ -23,6 +29,10 @@ class Webservice
         $choices = array();
         if ($this->serviceContainer->hasParameter($webservice)) {
             $url = $this->serviceContainer->getParameter($webservice);
+            $url .= '?filters[qb-criteria]';
+            foreach ($params as $param => $value) {
+                $url .= "&filters[{$param}]=$value";
+            }
             $objectsJson = json_decode(file_get_contents($url), true);
             foreach ($objectsJson as $object) {
                 $choices[$object['name']] = $object['id'];