herophuong

Untitled

Sep 16th, 2013
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 26.12 KB | None | 0 0
  1. <?php
  2. /**
  3.  * Zend Framework (http://framework.zend.com/)
  4.  *
  5.  * @link      http://github.com/zendframework/zf2 for the canonical source repository
  6.  * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
  7.  * @license   http://framework.zend.com/license/new-bsd New BSD License
  8.  */
  9.  
  10. namespace Zend\Form;
  11.  
  12. use Traversable;
  13. use Zend\Form\Element\Collection;
  14. use Zend\Form\Exception;
  15. use Zend\InputFilter\CollectionInputFilter;
  16. use Zend\InputFilter\InputFilter;
  17. use Zend\InputFilter\InputFilterAwareInterface;
  18. use Zend\InputFilter\InputFilterInterface;
  19. use Zend\InputFilter\InputFilterProviderInterface;
  20. use Zend\InputFilter\InputProviderInterface;
  21. use Zend\Stdlib\ArrayUtils;
  22. use Zend\Stdlib\Hydrator\HydratorInterface;
  23.  
  24. class Form extends Fieldset implements FormInterface
  25. {
  26.     /**
  27.      * Seed attributes
  28.      *
  29.      * @var array
  30.      */
  31.     protected $attributes = array(
  32.         'method' => 'POST',
  33.     );
  34.  
  35.     /**
  36.      * How to bind values to the attached object
  37.      *
  38.      * @var int
  39.      */
  40.     protected $bindAs = FormInterface::VALUES_NORMALIZED;
  41.  
  42.     /**
  43.      * Whether or not to bind values to the bound object on successful validation
  44.      *
  45.      * @var int
  46.      */
  47.     protected $bindOnValidate = FormInterface::BIND_ON_VALIDATE;
  48.  
  49.     /**
  50.      * Base fieldset to use for hydrating (if none specified, directly hydrate elements)
  51.      *
  52.      * @var FieldsetInterface
  53.      */
  54.     protected $baseFieldset;
  55.  
  56.     /**
  57.      * Data being validated
  58.      *
  59.      * @var null|array|Traversable
  60.      */
  61.     protected $data;
  62.  
  63.     /**
  64.      * @var null|InputFilterInterface
  65.      */
  66.     protected $filter;
  67.  
  68.     /**
  69.      * Whether or not to automatically scan for input filter defaults on
  70.      * attached fieldsets and elements
  71.      *
  72.      * @var bool
  73.      */
  74.     protected $useInputFilterDefaults = true;
  75.  
  76.     /**
  77.      * Has the input filter defaults been added already ?
  78.      *
  79.      * @var bool
  80.      */
  81.     protected $hasAddedInputFilterDefaults = false;
  82.  
  83.     /**
  84.      * Whether or not validation has occurred
  85.      *
  86.      * @var bool
  87.      */
  88.     protected $hasValidated = false;
  89.  
  90.     /**
  91.      * Result of last validation operation
  92.      *
  93.      * @var bool
  94.      */
  95.     protected $isValid = false;
  96.  
  97.     /**
  98.      * Is the form prepared ?
  99.      *
  100.      * @var bool
  101.      */
  102.     protected $isPrepared = false;
  103.  
  104.     /**
  105.      * Prefer form input filter over input filter defaults
  106.      *
  107.      * @var bool
  108.      */
  109.     protected $preferFormInputFilter = true;
  110.  
  111.     /**
  112.      * Are the form elements/fieldsets wrapped by the form name ?
  113.      *
  114.      * @var bool
  115.      */
  116.     protected $wrapElements = false;
  117.  
  118.     /**
  119.      * Validation group, if any
  120.      *
  121.      * @var null|array
  122.      */
  123.     protected $validationGroup;
  124.  
  125.  
  126.     /**
  127.      * Set options for a form. Accepted options are:
  128.      * - prefer_form_input_filter: is form input filter is preferred?
  129.      *
  130.      * @param  array|Traversable $options
  131.      * @return Element|ElementInterface
  132.      * @throws Exception\InvalidArgumentException
  133.      */
  134.     public function setOptions($options)
  135.     {
  136.         parent::setOptions($options);
  137.  
  138.         if (isset($options['prefer_form_input_filter'])) {
  139.             $this->setPreferFormInputFilter($options['prefer_form_input_filter']);
  140.         }
  141.  
  142.         return $this;
  143.     }
  144.  
  145.     /**
  146.      * Add an element or fieldset
  147.      *
  148.      * If $elementOrFieldset is an array or Traversable, passes the argument on
  149.      * to the composed factory to create the object before attaching it.
  150.      *
  151.      * $flags could contain metadata such as the alias under which to register
  152.      * the element or fieldset, order in which to prioritize it, etc.
  153.      *
  154.      * @param  array|Traversable|ElementInterface $elementOrFieldset
  155.      * @param  array                              $flags
  156.      * @return \Zend\Form\Fieldset|\Zend\Form\FieldsetInterface|\Zend\Form\FormInterface
  157.      */
  158.     public function add($elementOrFieldset, array $flags = array())
  159.     {
  160.         // TODO: find a better solution than duplicating the factory code, the problem being that if $elementOrFieldset is an array,
  161.         // it is passed by value, and we don't get back the concrete ElementInterface
  162.         if (is_array($elementOrFieldset)
  163.             || ($elementOrFieldset instanceof Traversable && !$elementOrFieldset instanceof ElementInterface)
  164.         ) {
  165.             $factory = $this->getFormFactory();
  166.             $elementOrFieldset = $factory->create($elementOrFieldset);
  167.         }
  168.  
  169.         parent::add($elementOrFieldset, $flags);
  170.  
  171.         if ($elementOrFieldset instanceof Fieldset && $elementOrFieldset->useAsBaseFieldset()) {
  172.             $this->baseFieldset = $elementOrFieldset;
  173.         }
  174.  
  175.         return $this;
  176.     }
  177.  
  178.     /**
  179.      * Ensures state is ready for use
  180.      *
  181.      * Marshalls the input filter, to ensure validation error messages are
  182.      * available, and prepares any elements and/or fieldsets that require
  183.      * preparation.
  184.      *
  185.      * @return Form
  186.      */
  187.     public function prepare()
  188.     {
  189.         if ($this->isPrepared) {
  190.             return $this;
  191.         }
  192.  
  193.         $this->getInputFilter();
  194.  
  195.         // If the user wants to, elements names can be wrapped by the form's name
  196.         if ($this->wrapElements()) {
  197.             $this->prepareElement($this);
  198.         } else {
  199.             foreach ($this->getIterator() as $elementOrFieldset) {
  200.                 if ($elementOrFieldset instanceof FormInterface) {
  201.                     $elementOrFieldset->prepare();
  202.                 } elseif ($elementOrFieldset instanceof ElementPrepareAwareInterface) {
  203.                     $elementOrFieldset->prepareElement($this);
  204.                 }
  205.             }
  206.         }
  207.  
  208.         $this->isPrepared = true;
  209.         return $this;
  210.     }
  211.  
  212.     /**
  213.      * Ensures state is ready for use. Here, we append the name of the fieldsets to every elements in order to avoid
  214.      * name clashes if the same fieldset is used multiple times
  215.      *
  216.      * @param  FormInterface $form
  217.      * @return mixed|void
  218.      */
  219.     public function prepareElement(FormInterface $form)
  220.     {
  221.         $name = $this->getName();
  222.  
  223.         foreach ($this->byName as $elementOrFieldset) {
  224.             if ($form->wrapElements()) {
  225.                 $elementOrFieldset->setName($name . '[' . $elementOrFieldset->getName() . ']');
  226.             }
  227.  
  228.             // Recursively prepare elements
  229.             if ($elementOrFieldset instanceof ElementPrepareAwareInterface) {
  230.                 $elementOrFieldset->prepareElement($form);
  231.             }
  232.         }
  233.     }
  234.  
  235.     /**
  236.      * Set data to validate and/or populate elements
  237.      *
  238.      * Typically, also passes data on to the composed input filter.
  239.      *
  240.      * @param  array|\ArrayAccess|Traversable $data
  241.      * @return Form|FormInterface
  242.      * @throws Exception\InvalidArgumentException
  243.      */
  244.     public function setData($data)
  245.     {
  246.         if ($data instanceof Traversable) {
  247.             $data = ArrayUtils::iteratorToArray($data);
  248.         }
  249.         if (!is_array($data)) {
  250.             throw new Exception\InvalidArgumentException(sprintf(
  251.                 '%s expects an array or Traversable argument; received "%s"',
  252.                 __METHOD__,
  253.                 (is_object($data) ? get_class($data) : gettype($data))
  254.             ));
  255.         }
  256.  
  257.         $this->hasValidated = false;
  258.         $this->data         = $data;
  259.         $this->populateValues($data);
  260.  
  261.         return $this;
  262.     }
  263.  
  264.     /**
  265.      * Bind an object to the form
  266.      *
  267.      * Ensures the object is populated with validated values.
  268.      *
  269.      * @param  object $object
  270.      * @param  int $flags
  271.      * @return mixed|void
  272.      * @throws Exception\InvalidArgumentException
  273.      */
  274.     public function bind($object, $flags = FormInterface::VALUES_NORMALIZED)
  275.     {
  276.         if (!in_array($flags, array(FormInterface::VALUES_NORMALIZED, FormInterface::VALUES_RAW))) {
  277.             throw new Exception\InvalidArgumentException(sprintf(
  278.                 '%s expects the $flags argument to be one of "%s" or "%s"; received "%s"',
  279.                 __METHOD__,
  280.                 'Zend\Form\FormInterface::VALUES_NORMALIZED',
  281.                 'Zend\Form\FormInterface::VALUES_RAW',
  282.                 $flags
  283.             ));
  284.         }
  285.  
  286.         if ($this->baseFieldset !== null) {
  287.             $this->baseFieldset->setObject($object);
  288.         }
  289.  
  290.         $this->bindAs = $flags;
  291.         $this->setObject($object);
  292.         $this->extract();
  293.  
  294.         return $this;
  295.     }
  296.  
  297.     /**
  298.      * Set the hydrator to use when binding an object to the element
  299.      *
  300.      * @param  HydratorInterface $hydrator
  301.      * @return FieldsetInterface
  302.      */
  303.     public function setHydrator(HydratorInterface $hydrator)
  304.     {
  305.         if ($this->baseFieldset !== null) {
  306.             $this->baseFieldset->setHydrator($hydrator);
  307.         }
  308.  
  309.         return parent::setHydrator($hydrator);
  310.     }
  311.  
  312.     /**
  313.      * Bind values to the bound object
  314.      *
  315.      * @param array $values
  316.      * @return mixed
  317.      */
  318.     public function bindValues(array $values = array())
  319.     {
  320.         if (!is_object($this->object)) {
  321.             if ($this->baseFieldset === null || $this->baseFieldset->allowValueBinding() == false) {
  322.                 return;
  323.             }
  324.         }
  325.         if (!$this->hasValidated() && !empty($values)) {
  326.             $this->setData($values);
  327.             if (!$this->isValid()) {
  328.                 return;
  329.             }
  330.         } elseif (!$this->isValid) {
  331.             return;
  332.         }
  333.  
  334.         $filter = $this->getInputFilter();
  335.  
  336.         switch ($this->bindAs) {
  337.             case FormInterface::VALUES_RAW:
  338.                 $data = $filter->getRawValues();
  339.                 break;
  340.             case FormInterface::VALUES_NORMALIZED:
  341.             default:
  342.                 $data = $filter->getValues();
  343.                 break;
  344.         }
  345.  
  346.         $data = $this->prepareBindData($data, $this->data);
  347.  
  348.         // If there is a base fieldset, only hydrate beginning from the base fieldset
  349.         if ($this->baseFieldset !== null) {
  350.             $data = $data[$this->baseFieldset->getName()];
  351.             $this->object = $this->baseFieldset->bindValues($data);
  352.         } else {
  353.             $this->object = parent::bindValues($data);
  354.         }
  355.     }
  356.  
  357.     /**
  358.      * Parse filtered values and return only posted fields for binding
  359.      *
  360.      * @param array $values
  361.      * @param array $match
  362.      * @return array
  363.      */
  364.     protected function prepareBindData(array $values, array $match)
  365.     {
  366.         $data = array();
  367.         foreach ($values as $name => $value) {
  368.             if (!array_key_exists($name, $match)) {
  369.                 continue;
  370.             }
  371.  
  372.             if (is_array($value) && is_array($match[$name])) {
  373.                 $data[$name] = $this->prepareBindData($value, $match[$name]);
  374.             } else {
  375.                 $data[$name] = $value;
  376.             }
  377.         }
  378.         return $data;
  379.     }
  380.  
  381.     /**
  382.      * Set flag indicating whether or not to bind values on successful validation
  383.      *
  384.      * @param  int $bindOnValidateFlag
  385.      * @return void|Form
  386.      * @throws Exception\InvalidArgumentException
  387.      */
  388.     public function setBindOnValidate($bindOnValidateFlag)
  389.     {
  390.         if (!in_array($bindOnValidateFlag, array(self::BIND_ON_VALIDATE, self::BIND_MANUAL))) {
  391.             throw new Exception\InvalidArgumentException(sprintf(
  392.                 '%s expects the flag to be one of %s::%s or %s::%s',
  393.                 __METHOD__,
  394.                 get_class($this),
  395.                 'BIND_ON_VALIDATE',
  396.                 get_class($this),
  397.                 'BIND_MANUAL'
  398.             ));
  399.         }
  400.         $this->bindOnValidate = $bindOnValidateFlag;
  401.         return $this;
  402.     }
  403.  
  404.     /**
  405.      * Will we bind values to the bound object on successful validation?
  406.      *
  407.      * @return bool
  408.      */
  409.     public function bindOnValidate()
  410.     {
  411.         return (static::BIND_ON_VALIDATE === $this->bindOnValidate);
  412.     }
  413.  
  414.     /**
  415.      * Set the base fieldset to use when hydrating
  416.      *
  417.      * @param  FieldsetInterface $baseFieldset
  418.      * @return Form
  419.      * @throws Exception\InvalidArgumentException
  420.      */
  421.     public function setBaseFieldset(FieldsetInterface $baseFieldset)
  422.     {
  423.         $this->baseFieldset = $baseFieldset;
  424.         return $this;
  425.     }
  426.  
  427.     /**
  428.      * Get the base fieldset to use when hydrating
  429.      *
  430.      * @return FieldsetInterface
  431.      */
  432.     public function getBaseFieldset()
  433.     {
  434.         return $this->baseFieldset;
  435.     }
  436.  
  437.     /**
  438.      * Check if the form has been validated
  439.      *
  440.      * @return bool
  441.      */
  442.     public function hasValidated()
  443.     {
  444.         return $this->hasValidated;
  445.     }
  446.  
  447.     /**
  448.      * Validate the form
  449.      *
  450.      * Typically, will proxy to the composed input filter.
  451.      *
  452.      * @return bool
  453.      * @throws Exception\DomainException
  454.      */
  455.     public function isValid()
  456.     {
  457.         if ($this->hasValidated) {
  458.             return $this->isValid;
  459.         }
  460.  
  461.         $this->isValid = false;
  462.  
  463.         if (!is_array($this->data) && !is_object($this->object)) {
  464.             throw new Exception\DomainException(sprintf(
  465.                 '%s is unable to validate as there is no data currently set',
  466.                 __METHOD__
  467.             ));
  468.         }
  469.  
  470.         if (!is_array($this->data)) {
  471.             $data = $this->extract();
  472.             if (!is_array($data)) {
  473.                 throw new Exception\DomainException(sprintf(
  474.                     '%s is unable to validate as there is no data currently set',
  475.                     __METHOD__
  476.                 ));
  477.             }
  478.             $this->data = $data;
  479.         }
  480.  
  481.         $filter = $this->getInputFilter();
  482.         if (!$filter instanceof InputFilterInterface) {
  483.             throw new Exception\DomainException(sprintf(
  484.                 '%s is unable to validate as there is no input filter present',
  485.                 __METHOD__
  486.             ));
  487.         }
  488.  
  489.         $filter->setData($this->data);
  490.         $filter->setValidationGroup(InputFilterInterface::VALIDATE_ALL);
  491.  
  492.         $validationGroup = $this->getValidationGroup();
  493.         if ($validationGroup !== null) {
  494.             $this->prepareValidationGroup($this, $this->data, $validationGroup);
  495.             $filter->setValidationGroup($validationGroup);
  496.         }
  497.  
  498.         $this->isValid = $result = $filter->isValid();
  499.         $this->hasValidated = true;
  500.  
  501.         if ($result && $this->bindOnValidate()) {
  502.             $this->bindValues();
  503.         }
  504.  
  505.         if (!$result) {
  506.             $this->setMessages($filter->getMessages());
  507.         }
  508.  
  509.         return $result;
  510.     }
  511.  
  512.     /**
  513.      * Retrieve the validated data
  514.      *
  515.      * By default, retrieves normalized values; pass one of the
  516.      * FormInterface::VALUES_* constants to shape the behavior.
  517.      *
  518.      * @param  int $flag
  519.      * @return array|object
  520.      * @throws Exception\DomainException
  521.      */
  522.     public function getData($flag = FormInterface::VALUES_NORMALIZED)
  523.     {
  524.         if (!$this->hasValidated) {
  525.             throw new Exception\DomainException(sprintf(
  526.                 '%s cannot return data as validation has not yet occurred',
  527.                 __METHOD__
  528.             ));
  529.         }
  530.  
  531.         if (($flag !== FormInterface::VALUES_AS_ARRAY) && is_object($this->object)) {
  532.             return $this->object;
  533.         }
  534.  
  535.         $filter = $this->getInputFilter();
  536.  
  537.         if ($flag === FormInterface::VALUES_RAW) {
  538.             return $filter->getRawValues();
  539.         }
  540.  
  541.         return $filter->getValues();
  542.     }
  543.  
  544.     /**
  545.      * Set the validation group (set of values to validate)
  546.      *
  547.      * Typically, proxies to the composed input filter
  548.      *
  549.      * @throws Exception\InvalidArgumentException
  550.      * @return Form|FormInterface
  551.      */
  552.     public function setValidationGroup()
  553.     {
  554.         $argc = func_num_args();
  555.         if (0 === $argc) {
  556.             throw new Exception\InvalidArgumentException(sprintf(
  557.                 '%s expects at least one argument; none provided',
  558.                 __METHOD__
  559.             ));
  560.         }
  561.  
  562.         $argv = func_get_args();
  563.         $this->hasValidated = false;
  564.  
  565.         if ($argc > 1) {
  566.             $this->validationGroup = $argv;
  567.             return $this;
  568.         }
  569.  
  570.         $arg = array_shift($argv);
  571.         if ($arg === FormInterface::VALIDATE_ALL) {
  572.             $this->validationGroup = null;
  573.             return $this;
  574.         }
  575.  
  576.         if (!is_array($arg)) {
  577.             $arg = (array) $arg;
  578.         }
  579.  
  580.         $this->validationGroup = $arg;
  581.         return $this;
  582.     }
  583.  
  584.     /**
  585.      * Retrieve the current validation group, if any
  586.      *
  587.      * @return null|array
  588.      */
  589.     public function getValidationGroup()
  590.     {
  591.         return $this->validationGroup;
  592.     }
  593.  
  594.     /**
  595.      * Prepare the validation group in case Collection elements were used (this function also handle the case where elements
  596.      * could have been dynamically added or removed from a collection using JavaScript)
  597.      *
  598.      * @param FieldsetInterface $formOrFieldset
  599.      * @param array             $data
  600.      * @param array             $validationGroup
  601.      */
  602.     protected function prepareValidationGroup(FieldsetInterface $formOrFieldset, array $data, array &$validationGroup)
  603.     {
  604.         foreach ($validationGroup as $key => &$value) {
  605.             if (!$formOrFieldset->has($key)) {
  606.                 continue;
  607.             }
  608.  
  609.             $fieldset = $formOrFieldset->byName[$key];
  610.  
  611.             if ($fieldset instanceof Collection) {
  612.                 if (!isset($data[$key]) && $fieldset->getCount() == 0) {
  613.                     unset ($validationGroup[$key]);
  614.                     continue;
  615.                 }
  616.  
  617.                 $values = array();
  618.  
  619.                 if (isset($data[$key])) {
  620.                     foreach (array_keys($data[$key]) as $cKey) {
  621.                         $values[$cKey] = $value;
  622.                     }
  623.                 }
  624.  
  625.                 $value = $values;
  626.             } else {
  627.                 if (!isset($data[$key])) {
  628.                     $data[$key] = array();
  629.                 }
  630.                 $this->prepareValidationGroup($fieldset, $data[$key], $validationGroup[$key]);
  631.             }
  632.         }
  633.     }
  634.  
  635.     /**
  636.      * Set the input filter used by this form
  637.      *
  638.      * @param  InputFilterInterface $inputFilter
  639.      * @return FormInterface
  640.      */
  641.     public function setInputFilter(InputFilterInterface $inputFilter)
  642.     {
  643.         $this->hasValidated                = false;
  644.         $this->hasAddedInputFilterDefaults = false;
  645.         $this->filter                      = $inputFilter;
  646.         return $this;
  647.     }
  648.  
  649.     /**
  650.      * Retrieve input filter used by this form
  651.      *
  652.      * @return null|InputFilterInterface
  653.      */
  654.     public function getInputFilter()
  655.     {
  656.         if ($this->object instanceof InputFilterAwareInterface) {
  657.             if (null == $this->baseFieldset) {
  658.                 $this->filter = $this->object->getInputFilter();
  659.             } else {
  660.                 $name = $this->baseFieldset->getName();
  661.                 if (!$this->filter instanceof InputFilterInterface || !$this->filter->has($name)) {
  662.                     $filter = new InputFilter();
  663.                     $filter->add($this->object->getInputFilter(), $name);
  664.                     $this->filter = $filter;
  665.                 }
  666.             }
  667.         }
  668.  
  669.         if (!isset($this->filter)) {
  670.             $this->filter = new InputFilter();
  671.         }
  672.  
  673.         if (!$this->hasAddedInputFilterDefaults
  674.             && $this->filter instanceof InputFilterInterface
  675.             && $this->useInputFilterDefaults()
  676.         ) {
  677.             $this->attachInputFilterDefaults($this->filter, $this);
  678.             $this->hasAddedInputFilterDefaults = true;
  679.         }
  680.  
  681.         return $this->filter;
  682.     }
  683.  
  684.     /**
  685.      * Set flag indicating whether or not to scan elements and fieldsets for defaults
  686.      *
  687.      * @param  bool $useInputFilterDefaults
  688.      * @return Form
  689.      */
  690.     public function setUseInputFilterDefaults($useInputFilterDefaults)
  691.     {
  692.         $this->useInputFilterDefaults = (bool) $useInputFilterDefaults;
  693.         return $this;
  694.     }
  695.  
  696.     /**
  697.      * Should we use input filter defaults from elements and fieldsets?
  698.      *
  699.      * @return bool
  700.      */
  701.     public function useInputFilterDefaults()
  702.     {
  703.         return $this->useInputFilterDefaults;
  704.     }
  705.  
  706.     /**
  707.      * Set flag indicating whether or not to prefer the form input filter over element and fieldset defaults
  708.      *
  709.      * @param  bool $preferFormInputFilter
  710.      * @return Form
  711.      */
  712.     public function setPreferFormInputFilter($preferFormInputFilter)
  713.     {
  714.         $this->preferFormInputFilter = (bool) $preferFormInputFilter;
  715.         return $this;
  716.     }
  717.  
  718.     /**
  719.      * Should we use form input filter over element input filter defaults from elements and fieldsets?
  720.      *
  721.      * @return bool
  722.      */
  723.     public function getPreferFormInputFilter()
  724.     {
  725.         return $this->preferFormInputFilter;
  726.     }
  727.  
  728.     /**
  729.      * Attach defaults provided by the elements to the input filter
  730.      *
  731.      * @param  InputFilterInterface $inputFilter
  732.      * @param  FieldsetInterface $fieldset Fieldset to traverse when looking for default inputs
  733.      * @return void
  734.      */
  735.     public function attachInputFilterDefaults(InputFilterInterface $inputFilter, FieldsetInterface $fieldset)
  736.     {
  737.         $formFactory  = $this->getFormFactory();
  738.         $inputFactory = $formFactory->getInputFilterFactory();
  739.  
  740.         if ($fieldset instanceof Collection && $fieldset->getTargetElement() instanceof FieldsetInterface) {
  741.             $elements = $fieldset->getTargetElement()->getElements();
  742.         } else {
  743.             $elements = $fieldset->getElements();
  744.         }
  745.  
  746.         if (!$fieldset instanceof Collection || $inputFilter instanceof CollectionInputFilter) {
  747.             foreach ($elements as $element) {
  748.                 $name = $element->getName();
  749.  
  750.                 if ($this->preferFormInputFilter && $inputFilter->has($name)) {
  751.                     continue;
  752.                 }
  753.  
  754.                 if (!$element instanceof InputProviderInterface) {
  755.                     if ($inputFilter->has($name)) {
  756.                         continue;
  757.                     }
  758.                     // Create a new empty default input for this element
  759.                     $spec = array('name' => $name, 'required' => false);
  760.                 } else {
  761.                     // Create an input based on the specification returned from the element
  762.                     $spec  = $element->getInputSpecification();
  763.                 }
  764.  
  765.                 $input = $inputFactory->createInput($spec);
  766.                 $inputFilter->add($input, $name);
  767.             }
  768.  
  769.             if ($fieldset instanceof InputFilterProviderInterface) {
  770.                 foreach ($fieldset->getInputFilterSpecification() as $name => $spec) {
  771.                     $input = $inputFactory->createInput($spec);
  772.                     $inputFilter->add($input, $name);
  773.                 }
  774.             }
  775.         }
  776.  
  777.         foreach ($fieldset->getFieldsets() as $childFieldset) {
  778.             $name = $childFieldset->getName();
  779.  
  780.             if (!$childFieldset instanceof InputFilterProviderInterface) {
  781.                 if (!$inputFilter->has($name)) {
  782.                     // Add a new empty input filter if it does not exist (or the fieldset's object input filter),
  783.                     // so that elements of nested fieldsets can be recursively added
  784.                     if ($childFieldset->getObject() instanceof InputFilterAwareInterface) {
  785.                         $inputFilter->add($childFieldset->getObject()->getInputFilter(), $name);
  786.                     } else {
  787.                         if ($fieldset instanceof Collection && $inputFilter instanceof CollectionInputFilter) {
  788.                             continue;
  789.                         } else {
  790.                             $inputFilter->add(new InputFilter(), $name);
  791.                         }
  792.                     }
  793.                 }
  794.  
  795.                 $fieldsetFilter = $inputFilter->get($name);
  796.  
  797.                 if (!$fieldsetFilter instanceof InputFilterInterface) {
  798.                     // Input attached for fieldset, not input filter; nothing more to do.
  799.                     continue;
  800.                 }
  801.  
  802.                 // Traverse the elements of the fieldset, and attach any
  803.                 // defaults to the fieldset's input filter
  804.                 $this->attachInputFilterDefaults($fieldsetFilter, $childFieldset);
  805.                 continue;
  806.             }
  807.  
  808.             if ($inputFilter->has($name)) {
  809.                 // if we already have an input/filter by this name, use it
  810.                 continue;
  811.             }
  812.  
  813.             // Create an input filter based on the specification returned from the fieldset
  814.             $spec   = $childFieldset->getInputFilterSpecification();
  815.             $filter = $inputFactory->createInputFilter($spec);
  816.             $inputFilter->add($filter, $name);
  817.  
  818.             // Recursively attach sub filters
  819.             $this->attachInputFilterDefaults($filter, $childFieldset);
  820.         }
  821.     }
  822.  
  823.     /**
  824.      * Are the form elements/fieldsets names wrapped by the form name ?
  825.      *
  826.      * @param  bool $wrapElements
  827.      * @return Form
  828.      */
  829.     public function setWrapElements($wrapElements)
  830.     {
  831.         $this->wrapElements = (bool) $wrapElements;
  832.         return $this;
  833.     }
  834.  
  835.     /**
  836.      * If true, form elements/fieldsets name's are wrapped around the form name itself
  837.      *
  838.      * @return bool
  839.      */
  840.     public function wrapElements()
  841.     {
  842.         return $this->wrapElements;
  843.     }
  844.  
  845.     /**
  846.      * Recursively extract values for elements and sub-fieldsets, and populate form values
  847.      *
  848.      * @return array
  849.      */
  850.     protected function extract()
  851.     {
  852.         if (null !== $this->baseFieldset) {
  853.             $name = $this->baseFieldset->getName();
  854.             $values[$name] = $this->baseFieldset->extract();
  855.             $this->baseFieldset->populateValues($values[$name]);
  856.         } else {
  857.             $values = parent::extract();
  858.             $this->populateValues($values);
  859.         }
  860.  
  861.         return $values;
  862.     }
  863. }
Advertisement
Add Comment
Please, Sign In to add comment