PageRenderTime 24ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/vendor/symfony/src/Symfony/Component/DomCrawler/Form.php

https://github.com/jakemhiller/SillyCMS
PHP | 362 lines | 182 code | 43 blank | 137 comment | 47 complexity | 252a941dc4b14e60dc7be1baf2bd1c53 MD5 | raw file
  1. <?php
  2. namespace Symfony\Component\DomCrawler;
  3. use Symfony\Component\DomCrawler\FormField;
  4. /*
  5. * This file is part of the Symfony package.
  6. *
  7. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  8. *
  9. * For the full copyright and license information, please view the LICENSE
  10. * file that was distributed with this source code.
  11. */
  12. /**
  13. * Form represents an HTML form.
  14. *
  15. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  16. */
  17. class Form implements \ArrayAccess
  18. {
  19. protected $document;
  20. protected $button;
  21. protected $node;
  22. protected $fields;
  23. protected $method;
  24. protected $host;
  25. protected $path;
  26. /**
  27. * Constructor.
  28. *
  29. * @param \DOMNode $node A \DOMNode instance
  30. * @param string $method The method to use for the link (if null, it defaults to the method defined by the form)
  31. * @param string $host The base URI to use for absolute links (like http://localhost)
  32. * @param string $path The base path for relative links (/ by default)
  33. *
  34. * @throws \LogicException if the node is not a button inside a form tag
  35. */
  36. public function __construct(\DOMNode $node, $method = null, $host = null, $path = '/')
  37. {
  38. $this->button = $node;
  39. if ('button' == $node->nodeName || ('input' == $node->nodeName && in_array($node->getAttribute('type'), array('submit', 'button', 'image')))) {
  40. do {
  41. // use the ancestor form element
  42. if (null === $node = $node->parentNode) {
  43. throw new \LogicException('The selected node does not have a form ancestor.');
  44. }
  45. } while ('form' != $node->nodeName);
  46. } else {
  47. throw new \LogicException(sprintf('Unable to submit on a "%s" tag.', $node->nodeName));
  48. }
  49. $this->node = $node;
  50. $this->method = $method;
  51. $this->host = $host;
  52. $this->path = empty($path) ? '/' : $path;
  53. $this->initialize();
  54. }
  55. /**
  56. * Gets the form node associated with this form.
  57. *
  58. * @return \DOMNode A \DOMNode instance
  59. */
  60. public function getFormNode()
  61. {
  62. return $this->node;
  63. }
  64. /**
  65. * Sets the value of the fields.
  66. *
  67. * @param array $values An array of field values
  68. */
  69. public function setValues(array $values)
  70. {
  71. foreach ($values as $name => $value) {
  72. $this[$name] = $value;
  73. }
  74. return $this;
  75. }
  76. /**
  77. * Gets the field values.
  78. *
  79. * The returned array does not include file fields (@see getFiles).
  80. *
  81. * @return array An array of field values.
  82. */
  83. public function getValues()
  84. {
  85. $values = array();
  86. foreach ($this->fields as $name => $field) {
  87. if (!$field instanceof Field\FileFormField && $field->hasValue()) {
  88. $values[$name] = $field->getValue();
  89. }
  90. }
  91. return $values;
  92. }
  93. /**
  94. * Gets the file field values.
  95. *
  96. * @return array An array of file field values.
  97. */
  98. public function getFiles()
  99. {
  100. if (!in_array($this->getMethod(), array('post', 'put', 'delete'))) {
  101. return array();
  102. }
  103. $files = array();
  104. foreach ($this->fields as $name => $field) {
  105. if ($field instanceof Field\FileFormField) {
  106. $files[$name] = $field->getValue();
  107. }
  108. }
  109. return $files;
  110. }
  111. /**
  112. * Gets the field values as PHP.
  113. *
  114. * This method converts fields with th array notation
  115. * (like foo[bar] to arrays) like PHP does.
  116. *
  117. * @return array An array of field values.
  118. */
  119. public function getPhpValues()
  120. {
  121. $qs = http_build_query($this->getValues());
  122. parse_str($qs, $values);
  123. return $values;
  124. }
  125. /**
  126. * Gets the file field values as PHP.
  127. *
  128. * This method converts fields with th array notation
  129. * (like foo[bar] to arrays) like PHP does.
  130. *
  131. * @return array An array of field values.
  132. */
  133. public function getPhpFiles()
  134. {
  135. $qs = http_build_query($this->getFiles());
  136. parse_str($qs, $values);
  137. return $values;
  138. }
  139. /**
  140. * Gets the URI of the form.
  141. *
  142. * The returned URI is not the same as the form "action" attribute.
  143. * This method merges the value if the method is GET to mimics
  144. * browser behavior.
  145. *
  146. * @param Boolean $absolute Whether to return an absolute URI or not (this only works if a base URI has been provided)
  147. *
  148. * @return string The URI
  149. */
  150. public function getUri($absolute = true)
  151. {
  152. $uri = $this->node->getAttribute('action');
  153. $urlHaveScheme = 'http' === substr($uri, 0, 4);
  154. if(!$uri) {
  155. $uri = $this->path;
  156. }
  157. if (!in_array($this->getMethod(), array('post', 'put', 'delete')) && $queryString = http_build_query($this->getValues(), null, '&')) {
  158. $sep = false === strpos($uri, '?') ? '?' : '&';
  159. $uri .= $sep.$queryString;
  160. }
  161. $path = $this->path;
  162. if ('?' !== substr($uri, 0, 1) && '/' !== substr($path, -1)) {
  163. $path = substr($path, 0, strrpos($path, '/') + 1);
  164. }
  165. if ($uri && '/' !== $uri[0] && !$urlHaveScheme) {
  166. $uri = $path.$uri;
  167. }
  168. if ($absolute && null !== $this->host && !$urlHaveScheme) {
  169. return $this->host.$uri;
  170. }
  171. return $uri;
  172. }
  173. /**
  174. * Gets the form method.
  175. *
  176. * If no method is defined in the form, GET is returned.
  177. *
  178. * @return string The method
  179. */
  180. public function getMethod()
  181. {
  182. if (null !== $this->method) {
  183. return $this->method;
  184. }
  185. return $this->node->getAttribute('method') ? strtolower($this->node->getAttribute('method')) : 'get';
  186. }
  187. /**
  188. * Returns true if the named field exists.
  189. *
  190. * @param string $name The field name
  191. *
  192. * @return Boolean true if the field exists, false otherwise
  193. */
  194. public function has($name)
  195. {
  196. return isset($this->fields[$name]);
  197. }
  198. /**
  199. * Gets a named field.
  200. *
  201. * @param string $name The field name
  202. *
  203. * @return FormField The field instance
  204. *
  205. * @throws \InvalidArgumentException When field is not present in this form
  206. */
  207. public function get($name)
  208. {
  209. if (!$this->has($name)) {
  210. throw new \InvalidArgumentException(sprintf('The form has no "%s" field', $name));
  211. }
  212. return $this->fields[$name];
  213. }
  214. /**
  215. * Sets a named field.
  216. *
  217. * @param string $name The field name
  218. *
  219. * @return FormField The field instance
  220. */
  221. public function set(Field\FormField $field)
  222. {
  223. $this->fields[$field->getName()] = $field;
  224. }
  225. /**
  226. * Gets all fields.
  227. *
  228. * @return array An array of fields
  229. */
  230. public function all()
  231. {
  232. return $this->fields;
  233. }
  234. protected function initialize()
  235. {
  236. $this->fields = array();
  237. $document = new \DOMDocument('1.0', 'UTF-8');
  238. $node = $document->importNode($this->node, true);
  239. $button = $document->importNode($this->button, true);
  240. $root = $document->appendChild($document->createElement('_root'));
  241. $root->appendChild($node);
  242. $root->appendChild($button);
  243. $xpath = new \DOMXPath($document);
  244. foreach ($xpath->query('descendant::input | descendant::textarea | descendant::select', $root) as $node) {
  245. if ($node->hasAttribute('disabled') || !$node->hasAttribute('name')) {
  246. continue;
  247. }
  248. $nodeName = $node->nodeName;
  249. if ($node === $button) {
  250. $this->set(new Field\InputFormField($node));
  251. } elseif ('select' == $nodeName || 'input' == $nodeName && 'checkbox' == $node->getAttribute('type')) {
  252. $this->set(new Field\ChoiceFormField($node));
  253. } elseif ('input' == $nodeName && 'radio' == $node->getAttribute('type')) {
  254. if ($this->has($node->getAttribute('name'))) {
  255. $this->get($node->getAttribute('name'))->addChoice($node);
  256. } else {
  257. $this->set(new Field\ChoiceFormField($node));
  258. }
  259. } elseif ('input' == $nodeName && 'file' == $node->getAttribute('type')) {
  260. $this->set(new Field\FileFormField($node));
  261. } elseif ('input' == $nodeName && !in_array($node->getAttribute('type'), array('submit', 'button', 'image'))) {
  262. $this->set(new Field\InputFormField($node));
  263. } elseif ('textarea' == $nodeName) {
  264. $this->set(new Field\TextareaFormField($node));
  265. }
  266. }
  267. }
  268. /**
  269. * Returns true if the named field exists.
  270. *
  271. * @param string $name The field name
  272. *
  273. * @return Boolean true if the field exists, false otherwise
  274. */
  275. public function offsetExists($name)
  276. {
  277. return $this->has($name);
  278. }
  279. /**
  280. * Gets the value of a field.
  281. *
  282. * @param string $name The field name
  283. *
  284. * @return FormField The associated Field instance
  285. *
  286. * @throws \InvalidArgumentException if the field does not exist
  287. */
  288. public function offsetGet($name)
  289. {
  290. if (!$this->has($name)) {
  291. throw new \InvalidArgumentException(sprintf('The form field "%s" does not exist', $name));
  292. }
  293. return $this->fields[$name];
  294. }
  295. /**
  296. * Sets the value of a field.
  297. *
  298. * @param string $name The field name
  299. * @param string|array $value The value of the field
  300. *
  301. * @throws \InvalidArgumentException if the field does not exist
  302. */
  303. public function offsetSet($name, $value)
  304. {
  305. if (!$this->has($name)) {
  306. throw new \InvalidArgumentException(sprintf('The form field "%s" does not exist', $name));
  307. }
  308. $this->fields[$name]->setValue($value);
  309. }
  310. /**
  311. * Unimplemented.
  312. *
  313. * @param string $name The field name
  314. */
  315. public function offsetUnset($name)
  316. {
  317. throw new \LogicException('The Form fields cannot be removed.');
  318. }
  319. }