Exemplo n.º 1
0
    /**
     * Binds data to the field, transforms and validates it.
     *
     * @param string|array $clientData The data
     *
     * @return Form The current form
     *
     * @throws UnexpectedTypeException
     */
    public function bind($clientData)
    {
        if ($this->readOnly) {
            $this->bound = true;

            return $this;
        }

        if (is_scalar($clientData) || null === $clientData) {
            $clientData = (string) $clientData;
        }

        // Initialize errors in the very beginning so that we don't lose any
        // errors added during listeners
        $this->errors = array();

        $event = new DataEvent($this, $clientData);
        $this->dispatcher->dispatch(FormEvents::PRE_BIND, $event);

        $appData = null;
        $normData = null;
        $extraData = array();
        $synchronized = false;

        // Hook to change content of the data bound by the browser
        $event = new FilterDataEvent($this, $clientData);
        $this->dispatcher->dispatch(FormEvents::BIND_CLIENT_DATA, $event);
        $clientData = $event->getData();

        if (count($this->children) > 0) {
            if (null === $clientData || '' === $clientData) {
                $clientData = array();
            }

            if (!is_array($clientData)) {
                throw new UnexpectedTypeException($clientData, 'array');
            }

            foreach ($this->children as $name => $child) {
                if (!isset($clientData[$name])) {
                    $clientData[$name] = null;
                }
            }

            foreach ($clientData as $name => $value) {
                if ($this->has($name)) {
                    $this->children[$name]->bind($value);
                } else {
                    $extraData[$name] = $value;
                }
            }

            // If we have a data mapper, use old client data and merge
            // data from the children into it later
            if ($this->dataMapper) {
                $clientData = $this->getClientData();
            }
        }

        if (null === $clientData || '' === $clientData) {
            $clientData = $this->emptyData;

            if ($clientData instanceof \Closure) {
                $clientData = $clientData($this);
            }
        }

        // Merge form data from children into existing client data
        if (count($this->children) > 0 && $this->dataMapper) {
            $this->dataMapper->mapFormsToData($this->children, $clientData);
        }

        try {
            // Normalize data to unified representation
            $normData = $this->clientToNorm($clientData);
            $synchronized = true;
        } catch (TransformationFailedException $e) {
        }

        if ($synchronized) {
            // Hook to change content of the data in the normalized
            // representation
            $event = new FilterDataEvent($this, $normData);
            $this->dispatcher->dispatch(FormEvents::BIND_NORM_DATA, $event);
            $normData = $event->getData();

            // Synchronize representations - must not change the content!
            $appData = $this->normToApp($normData);
            $clientData = $this->normToClient($normData);
        }

        $this->bound = true;
        $this->appData = $appData;
        $this->normData = $normData;
        $this->clientData = $clientData;
        $this->extraData = $extraData;
        $this->synchronized = $synchronized;

        $event = new DataEvent($this, $clientData);
        $this->dispatcher->dispatch(FormEvents::POST_BIND, $event);

        foreach ($this->validators as $validator) {
            $validator->validate($this);
        }

        return $this;
    }
Exemplo n.º 2
0
 /**
  * Binds data to the field, transforms and validates it.
  *
  * @param string|array $clientData The data
  *
  * @return Form The current form
  *
  * @throws UnexpectedTypeException
  */
 public function bind($clientData)
 {
     if ($this->bound) {
         throw new AlreadyBoundException('A form can only be bound once');
     }
     if ($this->isDisabled()) {
         $this->bound = true;
         return $this;
     }
     // Don't convert NULL to a string here in order to determine later
     // whether an empty value has been submitted or whether no value has
     // been submitted at all. This is important for processing checkboxes
     // and radio buttons with empty values.
     if (is_scalar($clientData)) {
         $clientData = (string) $clientData;
     }
     // Initialize errors in the very beginning so that we don't lose any
     // errors added during listeners
     $this->errors = array();
     $event = new DataEvent($this, $clientData);
     $this->dispatcher->dispatch(FormEvents::PRE_BIND, $event);
     $appData = null;
     $normData = null;
     $extraData = array();
     $synchronized = false;
     // Hook to change content of the data bound by the browser
     $event = new FilterDataEvent($this, $clientData);
     $this->dispatcher->dispatch(FormEvents::BIND_CLIENT_DATA, $event);
     $clientData = $event->getData();
     if (count($this->children) > 0) {
         if (null === $clientData || '' === $clientData) {
             $clientData = array();
         }
         if (!is_array($clientData)) {
             throw new UnexpectedTypeException($clientData, 'array');
         }
         foreach ($this->children as $name => $child) {
             if (!isset($clientData[$name])) {
                 $clientData[$name] = null;
             }
         }
         foreach ($clientData as $name => $value) {
             if ($this->has($name)) {
                 $this->children[$name]->bind($value);
             } else {
                 $extraData[$name] = $value;
             }
         }
         // If we have a data mapper, use old client data and merge
         // data from the children into it later
         if ($this->dataMapper) {
             $clientData = $this->getClientData();
         }
     }
     if (null === $clientData || '' === $clientData) {
         $emptyData = $this->emptyData;
         if ($emptyData instanceof \Closure) {
             $emptyData = $emptyData($this, $clientData);
         }
         $clientData = $emptyData;
     }
     // Merge form data from children into existing client data
     if (count($this->children) > 0 && $this->dataMapper && null !== $clientData) {
         $this->dataMapper->mapFormsToData($this->children, $clientData);
     }
     try {
         // Normalize data to unified representation
         $normData = $this->clientToNorm($clientData);
         $synchronized = true;
     } catch (TransformationFailedException $e) {
     }
     if ($synchronized) {
         // Hook to change content of the data into the normalized
         // representation
         $event = new FilterDataEvent($this, $normData);
         $this->dispatcher->dispatch(FormEvents::BIND_NORM_DATA, $event);
         $normData = $event->getData();
         // Synchronize representations - must not change the content!
         $appData = $this->normToApp($normData);
         $clientData = $this->normToClient($normData);
     }
     $this->bound = true;
     $this->appData = $appData;
     $this->normData = $normData;
     $this->clientData = $clientData;
     $this->extraData = $extraData;
     $this->synchronized = $synchronized;
     $event = new DataEvent($this, $clientData);
     $this->dispatcher->dispatch(FormEvents::POST_BIND, $event);
     foreach ($this->validators as $validator) {
         $validator->validate($this);
     }
     $event = new DataEvent($this, $clientData);
     $this->dispatcher->dispatch(FormEvents::POST_VALIDATE, $event);
     return $this;
 }