9168dd365af9862aa262ca201362dca71f1760cc
[yaffs-website] / vendor / symfony / dom-crawler / FormFieldRegistry.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\DomCrawler;
13
14 use Symfony\Component\DomCrawler\Field\FormField;
15
16 /**
17  * This is an internal class that must not be used directly.
18  *
19  * @internal
20  */
21 class FormFieldRegistry
22 {
23     private $fields = array();
24
25     private $base;
26
27     /**
28      * Adds a field to the registry.
29      *
30      * @param FormField $field The field
31      */
32     public function add(FormField $field)
33     {
34         $segments = $this->getSegments($field->getName());
35
36         $target = &$this->fields;
37         while ($segments) {
38             if (!is_array($target)) {
39                 $target = array();
40             }
41             $path = array_shift($segments);
42             if ('' === $path) {
43                 $target = &$target[];
44             } else {
45                 $target = &$target[$path];
46             }
47         }
48         $target = $field;
49     }
50
51     /**
52      * Removes a field and its children from the registry.
53      *
54      * @param string $name The fully qualified name of the base field
55      */
56     public function remove($name)
57     {
58         $segments = $this->getSegments($name);
59         $target = &$this->fields;
60         while (count($segments) > 1) {
61             $path = array_shift($segments);
62             if (!array_key_exists($path, $target)) {
63                 return;
64             }
65             $target = &$target[$path];
66         }
67         unset($target[array_shift($segments)]);
68     }
69
70     /**
71      * Returns the value of the field and its children.
72      *
73      * @param string $name The fully qualified name of the field
74      *
75      * @return mixed The value of the field
76      *
77      * @throws \InvalidArgumentException if the field does not exist
78      */
79     public function &get($name)
80     {
81         $segments = $this->getSegments($name);
82         $target = &$this->fields;
83         while ($segments) {
84             $path = array_shift($segments);
85             if (!array_key_exists($path, $target)) {
86                 throw new \InvalidArgumentException(sprintf('Unreachable field "%s"', $path));
87             }
88             $target = &$target[$path];
89         }
90
91         return $target;
92     }
93
94     /**
95      * Tests whether the form has the given field.
96      *
97      * @param string $name The fully qualified name of the field
98      *
99      * @return bool Whether the form has the given field
100      */
101     public function has($name)
102     {
103         try {
104             $this->get($name);
105
106             return true;
107         } catch (\InvalidArgumentException $e) {
108             return false;
109         }
110     }
111
112     /**
113      * Set the value of a field and its children.
114      *
115      * @param string $name  The fully qualified name of the field
116      * @param mixed  $value The value
117      *
118      * @throws \InvalidArgumentException if the field does not exist
119      */
120     public function set($name, $value)
121     {
122         $target = &$this->get($name);
123         if ((!is_array($value) && $target instanceof Field\FormField) || $target instanceof Field\ChoiceFormField) {
124             $target->setValue($value);
125         } elseif (is_array($value)) {
126             $fields = self::create($name, $value);
127             foreach ($fields->all() as $k => $v) {
128                 $this->set($k, $v);
129             }
130         } else {
131             throw new \InvalidArgumentException(sprintf('Cannot set value on a compound field "%s".', $name));
132         }
133     }
134
135     /**
136      * Returns the list of field with their value.
137      *
138      * @return FormField[] The list of fields as array((string) Fully qualified name => (mixed) value)
139      */
140     public function all()
141     {
142         return $this->walk($this->fields, $this->base);
143     }
144
145     /**
146      * Creates an instance of the class.
147      *
148      * This function is made private because it allows overriding the $base and
149      * the $values properties without any type checking.
150      *
151      * @param string $base   The fully qualified name of the base field
152      * @param array  $values The values of the fields
153      *
154      * @return static
155      */
156     private static function create($base, array $values)
157     {
158         $registry = new static();
159         $registry->base = $base;
160         $registry->fields = $values;
161
162         return $registry;
163     }
164
165     /**
166      * Transforms a PHP array in a list of fully qualified name / value.
167      *
168      * @param array  $array  The PHP array
169      * @param string $base   The name of the base field
170      * @param array  $output The initial values
171      *
172      * @return array The list of fields as array((string) Fully qualified name => (mixed) value)
173      */
174     private function walk(array $array, $base = '', array &$output = array())
175     {
176         foreach ($array as $k => $v) {
177             $path = empty($base) ? $k : sprintf('%s[%s]', $base, $k);
178             if (is_array($v)) {
179                 $this->walk($v, $path, $output);
180             } else {
181                 $output[$path] = $v;
182             }
183         }
184
185         return $output;
186     }
187
188     /**
189      * Splits a field name into segments as a web browser would do.
190      *
191      * <code>
192      *     getSegments('base[foo][3][]') = array('base', 'foo, '3', '');
193      * </code>
194      *
195      * @param string $name The name of the field
196      *
197      * @return string[] The list of segments
198      */
199     private function getSegments($name)
200     {
201         if (preg_match('/^(?P<base>[^[]+)(?P<extra>(\[.*)|$)/', $name, $m)) {
202             $segments = array($m['base']);
203             while (!empty($m['extra'])) {
204                 $extra = $m['extra'];
205                 if (preg_match('/^\[(?P<segment>.*?)\](?P<extra>.*)$/', $extra, $m)) {
206                     $segments[] = $m['segment'];
207                 } else {
208                     $segments[] = $extra;
209                 }
210             }
211
212             return $segments;
213         }
214
215         return array($name);
216     }
217 }