PageRenderTime 26ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/tippycracker/autokraitis
PHP | 222 lines | 99 code | 33 blank | 90 comment | 17 complexity | 691645833d248104df5de9837d4edd69 MD5 | raw file
Possible License(s): BSD-2-Clause, GPL-2.0, GPL-3.0, BSD-3-Clause, Apache-2.0
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\DomCrawler;
  11. /**
  12. * Link represents an HTML link (an HTML a, area or link tag).
  13. *
  14. * @author Fabien Potencier <fabien@symfony.com>
  15. */
  16. class Link
  17. {
  18. /**
  19. * @var \DOMElement
  20. */
  21. protected $node;
  22. /**
  23. * @var string The method to use for the link
  24. */
  25. protected $method;
  26. /**
  27. * @var string The URI of the page where the link is embedded (or the base href)
  28. */
  29. protected $currentUri;
  30. /**
  31. * @param \DOMElement $node A \DOMElement instance
  32. * @param string $currentUri The URI of the page where the link is embedded (or the base href)
  33. * @param string $method The method to use for the link (get by default)
  34. *
  35. * @throws \InvalidArgumentException if the node is not a link
  36. */
  37. public function __construct(\DOMElement $node, $currentUri, $method = 'GET')
  38. {
  39. if (!in_array(strtolower(substr($currentUri, 0, 4)), array('http', 'file'))) {
  40. throw new \InvalidArgumentException(sprintf('Current URI must be an absolute URL ("%s").', $currentUri));
  41. }
  42. $this->setNode($node);
  43. $this->method = $method ? strtoupper($method) : null;
  44. $this->currentUri = $currentUri;
  45. }
  46. /**
  47. * Gets the node associated with this link.
  48. *
  49. * @return \DOMElement A \DOMElement instance
  50. */
  51. public function getNode()
  52. {
  53. return $this->node;
  54. }
  55. /**
  56. * Gets the method associated with this link.
  57. *
  58. * @return string The method
  59. */
  60. public function getMethod()
  61. {
  62. return $this->method;
  63. }
  64. /**
  65. * Gets the URI associated with this link.
  66. *
  67. * @return string The URI
  68. */
  69. public function getUri()
  70. {
  71. $uri = trim($this->getRawUri());
  72. // absolute URL?
  73. if (null !== parse_url($uri, PHP_URL_SCHEME)) {
  74. return $uri;
  75. }
  76. // empty URI
  77. if (!$uri) {
  78. return $this->currentUri;
  79. }
  80. // an anchor
  81. if ('#' === $uri[0]) {
  82. return $this->cleanupAnchor($this->currentUri).$uri;
  83. }
  84. $baseUri = $this->cleanupUri($this->currentUri);
  85. if ('?' === $uri[0]) {
  86. return $baseUri.$uri;
  87. }
  88. // absolute URL with relative schema
  89. if (0 === strpos($uri, '//')) {
  90. return preg_replace('#^([^/]*)//.*$#', '$1', $baseUri).$uri;
  91. }
  92. $baseUri = preg_replace('#^(.*?//[^/]*)(?:\/.*)?$#', '$1', $baseUri);
  93. // absolute path
  94. if ('/' === $uri[0]) {
  95. return $baseUri.$uri;
  96. }
  97. // relative path
  98. $path = parse_url(substr($this->currentUri, strlen($baseUri)), PHP_URL_PATH);
  99. $path = $this->canonicalizePath(substr($path, 0, strrpos($path, '/')).'/'.$uri);
  100. return $baseUri.('' === $path || '/' !== $path[0] ? '/' : '').$path;
  101. }
  102. /**
  103. * Returns raw URI data.
  104. *
  105. * @return string
  106. */
  107. protected function getRawUri()
  108. {
  109. return $this->node->getAttribute('href');
  110. }
  111. /**
  112. * Returns the canonicalized URI path (see RFC 3986, section 5.2.4).
  113. *
  114. * @param string $path URI path
  115. *
  116. * @return string
  117. */
  118. protected function canonicalizePath($path)
  119. {
  120. if ('' === $path || '/' === $path) {
  121. return $path;
  122. }
  123. if ('.' === substr($path, -1)) {
  124. $path .= '/';
  125. }
  126. $output = array();
  127. foreach (explode('/', $path) as $segment) {
  128. if ('..' === $segment) {
  129. array_pop($output);
  130. } elseif ('.' !== $segment) {
  131. $output[] = $segment;
  132. }
  133. }
  134. return implode('/', $output);
  135. }
  136. /**
  137. * Sets current \DOMElement instance.
  138. *
  139. * @param \DOMElement $node A \DOMElement instance
  140. *
  141. * @throws \LogicException If given node is not an anchor
  142. */
  143. protected function setNode(\DOMElement $node)
  144. {
  145. if ('a' !== $node->nodeName && 'area' !== $node->nodeName && 'link' !== $node->nodeName) {
  146. throw new \LogicException(sprintf('Unable to navigate from a "%s" tag.', $node->nodeName));
  147. }
  148. $this->node = $node;
  149. }
  150. /**
  151. * Removes the query string and the anchor from the given uri.
  152. *
  153. * @param string $uri The uri to clean
  154. *
  155. * @return string
  156. */
  157. private function cleanupUri($uri)
  158. {
  159. return $this->cleanupQuery($this->cleanupAnchor($uri));
  160. }
  161. /**
  162. * Remove the query string from the uri.
  163. *
  164. * @param string $uri
  165. *
  166. * @return string
  167. */
  168. private function cleanupQuery($uri)
  169. {
  170. if (false !== $pos = strpos($uri, '?')) {
  171. return substr($uri, 0, $pos);
  172. }
  173. return $uri;
  174. }
  175. /**
  176. * Remove the anchor from the uri.
  177. *
  178. * @param string $uri
  179. *
  180. * @return string
  181. */
  182. private function cleanupAnchor($uri)
  183. {
  184. if (false !== $pos = strpos($uri, '#')) {
  185. return substr($uri, 0, $pos);
  186. }
  187. return $uri;
  188. }
  189. }