|
@@ -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');
|
|
|
+ }
|
|
|
+
|
|
|
+}
|