/** * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { $choiceList = $this->createChoiceList($options); $builder->setAttribute('choice_list', $choiceList); if ($options['expanded']) { $builder->setDataMapper($options['multiple'] ? new CheckboxListMapper() : new RadioListMapper()); // Initialize all choices before doing the index check below. // This helps in cases where index checks are optimized for non // initialized choice lists. For example, when using an SQL driver, // the index check would read in one SQL query and the initialization // requires another SQL query. When the initialization is done first, // one SQL query is sufficient. $choiceListView = $this->createChoiceListView($choiceList, $options); $builder->setAttribute('choice_list_view', $choiceListView); // Check if the choices already contain the empty value // Only add the placeholder option if this is not the case if (null !== $options['placeholder'] && 0 === count($choiceList->getChoicesForValues(array('')))) { $placeholderView = new ChoiceView(null, '', $options['placeholder']); // "placeholder" is a reserved name $this->addSubForm($builder, 'placeholder', $placeholderView, $options); } $this->addSubForms($builder, $choiceListView->preferredChoices, $options); $this->addSubForms($builder, $choiceListView->choices, $options); // Make sure that scalar, submitted values are converted to arrays // which can be submitted to the checkboxes/radio buttons $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); if (null === $data) { $emptyData = $form->getConfig()->getEmptyData(); if (false === FormUtil::isEmpty($emptyData) && array() !== $emptyData) { $data = is_callable($emptyData) ? call_user_func($emptyData, $form, $data) : $emptyData; } } // Convert the submitted data to a string, if scalar, before // casting it to an array if (!is_array($data)) { $data = (array) (string) $data; } // A map from submitted values to integers $valueMap = array_flip($data); // Make a copy of the value map to determine whether any unknown // values were submitted $unknownValues = $valueMap; // Reconstruct the data as mapping from child names to values $data = array(); foreach ($form as $child) { $value = $child->getConfig()->getOption('value'); // Add the value to $data with the child's name as key if (isset($valueMap[$value])) { $data[$child->getName()] = $value; unset($unknownValues[$value]); continue; } } // The empty value is always known, independent of whether a // field exists for it or not unset($unknownValues['']); // Throw exception if unknown values were submitted if (count($unknownValues) > 0) { throw new TransformationFailedException(sprintf('The choices "%s" do not exist in the choice list.', implode('", "', array_keys($unknownValues)))); } $event->setData($data); }); } if ($options['multiple']) { // <select> tag with "multiple" option or list of checkbox inputs $builder->addViewTransformer(new ChoicesToValuesTransformer($choiceList)); } else { // <select> tag without "multiple" option or list of radio inputs $builder->addViewTransformer(new ChoiceToValueTransformer($choiceList)); } if ($options['multiple'] && $options['by_reference']) { // Make sure the collection created during the client->norm // transformation is merged back into the original collection $builder->addEventSubscriber(new MergeCollectionListener(true, true)); } }
public function isEmpty() { foreach ($this->children as $child) { if (!$child->isEmpty()) { return false; } } return FormUtil::isEmpty($this->modelData) || 0 === count($this->modelData) || $this->modelData instanceof \Traversable && 0 === iterator_count($this->modelData); }
/** * {@inheritdoc} */ public function isEmpty() { foreach ($this->children as $child) { if (!$child->isEmpty()) { return false; } } return FormUtil::isEmpty($this->modelData) || array() === $this->modelData; }