4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\DomCrawler;
14 use Symfony\Component\DomCrawler\Field\FormField;
17 * This is an internal class that must not be used directly.
21 class FormFieldRegistry
23 private $fields = array();
28 * Adds a field to the registry.
30 public function add(FormField $field)
32 $segments = $this->getSegments($field->getName());
34 $target = &$this->fields;
36 if (!is_array($target)) {
39 $path = array_shift($segments);
43 $target = &$target[$path];
50 * Removes a field and its children from the registry.
52 * @param string $name The fully qualified name of the base field
54 public function remove($name)
56 $segments = $this->getSegments($name);
57 $target = &$this->fields;
58 while (count($segments) > 1) {
59 $path = array_shift($segments);
60 if (!array_key_exists($path, $target)) {
63 $target = &$target[$path];
65 unset($target[array_shift($segments)]);
69 * Returns the value of the field and its children.
71 * @param string $name The fully qualified name of the field
73 * @return mixed The value of the field
75 * @throws \InvalidArgumentException if the field does not exist
77 public function &get($name)
79 $segments = $this->getSegments($name);
80 $target = &$this->fields;
82 $path = array_shift($segments);
83 if (!array_key_exists($path, $target)) {
84 throw new \InvalidArgumentException(sprintf('Unreachable field "%s"', $path));
86 $target = &$target[$path];
93 * Tests whether the form has the given field.
95 * @param string $name The fully qualified name of the field
97 * @return bool Whether the form has the given field
99 public function has($name)
105 } catch (\InvalidArgumentException $e) {
111 * Set the value of a field and its children.
113 * @param string $name The fully qualified name of the field
114 * @param mixed $value The value
116 * @throws \InvalidArgumentException if the field does not exist
118 public function set($name, $value)
120 $target = &$this->get($name);
121 if ((!is_array($value) && $target instanceof Field\FormField) || $target instanceof Field\ChoiceFormField) {
122 $target->setValue($value);
123 } elseif (is_array($value)) {
124 $fields = self::create($name, $value);
125 foreach ($fields->all() as $k => $v) {
129 throw new \InvalidArgumentException(sprintf('Cannot set value on a compound field "%s".', $name));
134 * Returns the list of field with their value.
136 * @return FormField[] The list of fields as array((string) Fully qualified name => (mixed) value)
138 public function all()
140 return $this->walk($this->fields, $this->base);
144 * Creates an instance of the class.
146 * This function is made private because it allows overriding the $base and
147 * the $values properties without any type checking.
149 * @param string $base The fully qualified name of the base field
150 * @param array $values The values of the fields
154 private static function create($base, array $values)
156 $registry = new static();
157 $registry->base = $base;
158 $registry->fields = $values;
164 * Transforms a PHP array in a list of fully qualified name / value.
166 * @param array $array The PHP array
167 * @param string $base The name of the base field
168 * @param array $output The initial values
170 * @return array The list of fields as array((string) Fully qualified name => (mixed) value)
172 private function walk(array $array, $base = '', array &$output = array())
174 foreach ($array as $k => $v) {
175 $path = empty($base) ? $k : sprintf('%s[%s]', $base, $k);
177 $this->walk($v, $path, $output);
187 * Splits a field name into segments as a web browser would do.
190 * getSegments('base[foo][3][]') = array('base', 'foo, '3', '');
193 * @param string $name The name of the field
195 * @return string[] The list of segments
197 private function getSegments($name)
199 if (preg_match('/^(?P<base>[^[]+)(?P<extra>(\[.*)|$)/', $name, $m)) {
200 $segments = array($m['base']);
201 while (!empty($m['extra'])) {
202 $extra = $m['extra'];
203 if (preg_match('/^\[(?P<segment>.*?)\](?P<extra>.*)$/', $extra, $m)) {
204 $segments[] = $m['segment'];
206 $segments[] = $extra;