6398cc60693ade7fdf1a4d96294f0d21ca1b50e9
[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     public function add(FormField $field)
31     {
32         $segments = $this->getSegments($field->getName());
33
34         $target = &$this->fields;
35         while ($segments) {
36             if (!\is_array($target)) {
37                 $target = array();
38             }
39             $path = array_shift($segments);
40             if ('' === $path) {
41                 $target = &$target[];
42             } else {
43                 $target = &$target[$path];
44             }
45         }
46         $target = $field;
47     }
48
49     /**
50      * Removes a field and its children from the registry.
51      *
52      * @param string $name The fully qualified name of the base field
53      */
54     public function remove($name)
55     {
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)) {
61                 return;
62             }
63             $target = &$target[$path];
64         }
65         unset($target[array_shift($segments)]);
66     }
67
68     /**
69      * Returns the value of the field and its children.
70      *
71      * @param string $name The fully qualified name of the field
72      *
73      * @return mixed The value of the field
74      *
75      * @throws \InvalidArgumentException if the field does not exist
76      */
77     public function &get($name)
78     {
79         $segments = $this->getSegments($name);
80         $target = &$this->fields;
81         while ($segments) {
82             $path = array_shift($segments);
83             if (!array_key_exists($path, $target)) {
84                 throw new \InvalidArgumentException(sprintf('Unreachable field "%s"', $path));
85             }
86             $target = &$target[$path];
87         }
88
89         return $target;
90     }
91
92     /**
93      * Tests whether the form has the given field.
94      *
95      * @param string $name The fully qualified name of the field
96      *
97      * @return bool Whether the form has the given field
98      */
99     public function has($name)
100     {
101         try {
102             $this->get($name);
103
104             return true;
105         } catch (\InvalidArgumentException $e) {
106             return false;
107         }
108     }
109
110     /**
111      * Set the value of a field and its children.
112      *
113      * @param string $name  The fully qualified name of the field
114      * @param mixed  $value The value
115      *
116      * @throws \InvalidArgumentException if the field does not exist
117      */
118     public function set($name, $value)
119     {
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) {
126                 $this->set($k, $v);
127             }
128         } else {
129             throw new \InvalidArgumentException(sprintf('Cannot set value on a compound field "%s".', $name));
130         }
131     }
132
133     /**
134      * Returns the list of field with their value.
135      *
136      * @return FormField[] The list of fields as array((string) Fully qualified name => (mixed) value)
137      */
138     public function all()
139     {
140         return $this->walk($this->fields, $this->base);
141     }
142
143     /**
144      * Creates an instance of the class.
145      *
146      * This function is made private because it allows overriding the $base and
147      * the $values properties without any type checking.
148      *
149      * @param string $base   The fully qualified name of the base field
150      * @param array  $values The values of the fields
151      *
152      * @return static
153      */
154     private static function create($base, array $values)
155     {
156         $registry = new static();
157         $registry->base = $base;
158         $registry->fields = $values;
159
160         return $registry;
161     }
162
163     /**
164      * Transforms a PHP array in a list of fully qualified name / value.
165      *
166      * @param array  $array  The PHP array
167      * @param string $base   The name of the base field
168      * @param array  $output The initial values
169      *
170      * @return array The list of fields as array((string) Fully qualified name => (mixed) value)
171      */
172     private function walk(array $array, $base = '', array &$output = array())
173     {
174         foreach ($array as $k => $v) {
175             $path = empty($base) ? $k : sprintf('%s[%s]', $base, $k);
176             if (\is_array($v)) {
177                 $this->walk($v, $path, $output);
178             } else {
179                 $output[$path] = $v;
180             }
181         }
182
183         return $output;
184     }
185
186     /**
187      * Splits a field name into segments as a web browser would do.
188      *
189      *     getSegments('base[foo][3][]') = array('base', 'foo, '3', '');
190      *
191      * @param string $name The name of the field
192      *
193      * @return string[] The list of segments
194      */
195     private function getSegments($name)
196     {
197         if (preg_match('/^(?P<base>[^[]+)(?P<extra>(\[.*)|$)/', $name, $m)) {
198             $segments = array($m['base']);
199             while (!empty($m['extra'])) {
200                 $extra = $m['extra'];
201                 if (preg_match('/^\[(?P<segment>.*?)\](?P<extra>.*)$/', $extra, $m)) {
202                     $segments[] = $m['segment'];
203                 } else {
204                     $segments[] = $extra;
205                 }
206             }
207
208             return $segments;
209         }
210
211         return array($name);
212     }
213 }