diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php
index 9ff232ca70430..1adc02ee097c2 100644
--- a/src/Symfony/Component/DomCrawler/Crawler.php
+++ b/src/Symfony/Component/DomCrawler/Crawler.php
@@ -23,19 +23,27 @@ class Crawler extends \SplObjectStorage
protected $uri;
protected $host;
protected $path;
+ protected $base;
/**
* Constructor.
*
* @param mixed $node A Node to use as the base for the crawling
* @param string $uri The base URI to use for absolute links or form actions
+ * @param string $base An optional base href for generating the uris for Form and Link.
+ * This will be autodetected if $node has a tag.
*/
- public function __construct($node = null, $uri = null)
+ public function __construct($node = null, $uri = null, $base = null)
{
$this->uri = $uri;
+
list($this->host, $this->path) = $this->parseUri($this->uri);
$this->add($node);
+
+ if ($base) {
+ $this->base = $base;
+ }
}
/**
@@ -103,6 +111,12 @@ public function addHtmlContent($content, $charset = 'UTF-8')
@$dom->loadHTML($content);
$this->addDocument($dom);
+
+ $base = $this->filter('base')->extract(array('href'));
+
+ if (count($base)) {
+ $this->base = current($base);
+ }
}
/**
@@ -430,7 +444,7 @@ public function filterXPath($xpath)
$domxpath = new \DOMXPath($document);
- return new static($domxpath->query($xpath), $this->uri);
+ return new static($domxpath->query($xpath), $this->uri, $this->base);
}
/**
@@ -503,7 +517,7 @@ public function link($method = 'get')
$node = $this->getNode(0);
- return new Link($node, $method, $this->host, $this->path);
+ return new Link($node, $method, $this->host, $this->path, $this->base);
}
/**
@@ -537,7 +551,7 @@ public function form(array $values = null, $method = null)
throw new \InvalidArgumentException('The current node list is empty.');
}
- $form = new Form($this->getNode(0), $method, $this->host, $this->path);
+ $form = new Form($this->getNode(0), $method, $this->host, $this->path, $this->base);
if (null !== $values) {
$form->setValues($values);
diff --git a/src/Symfony/Component/DomCrawler/Form.php b/src/Symfony/Component/DomCrawler/Form.php
index 7b401c8396ffb..250630bfa25ac 100644
--- a/src/Symfony/Component/DomCrawler/Form.php
+++ b/src/Symfony/Component/DomCrawler/Form.php
@@ -27,6 +27,7 @@ class Form implements \ArrayAccess
protected $method;
protected $host;
protected $path;
+ protected $base;
/**
* Constructor.
@@ -35,10 +36,11 @@ class Form implements \ArrayAccess
* @param string $method The method to use for the link (if null, it defaults to the method defined by the form)
* @param string $host The base URI to use for absolute links (like http://localhost)
* @param string $path The base path for relative links (/ by default)
+ * @param string $base An optional base href for generating the submit uri
*
* @throws \LogicException if the node is not a button inside a form tag
*/
- public function __construct(\DOMNode $node, $method = null, $host = null, $path = '/')
+ public function __construct(\DOMNode $node, $method = null, $host = null, $path = '/', $base = null)
{
$this->button = $node;
if ('button' == $node->nodeName || ('input' == $node->nodeName && in_array($node->getAttribute('type'), array('submit', 'button', 'image')))) {
@@ -55,6 +57,7 @@ public function __construct(\DOMNode $node, $method = null, $host = null, $path
$this->method = $method;
$this->host = $host;
$this->path = empty($path) ? '/' : $path;
+ $this->base = $base;
$this->initialize();
}
@@ -185,11 +188,13 @@ public function getUri($absolute = true)
$path = substr($path, 0, strrpos($path, '/') + 1);
}
- if ($uri && '/' !== $uri[0] && !$urlHaveScheme) {
+ if (!$this->base && $uri && '/' !== $uri[0] && !$urlHaveScheme) {
$uri = $path.$uri;
+ } elseif ($this->base) {
+ $uri = $this->base.$uri;
}
- if ($absolute && null !== $this->host && !$urlHaveScheme) {
+ if (!$this->base && $absolute && null !== $this->host && !$urlHaveScheme) {
return $this->host.$uri;
}
diff --git a/src/Symfony/Component/DomCrawler/Link.php b/src/Symfony/Component/DomCrawler/Link.php
index ae0500303cbc7..7c03d82495ca1 100644
--- a/src/Symfony/Component/DomCrawler/Link.php
+++ b/src/Symfony/Component/DomCrawler/Link.php
@@ -22,6 +22,7 @@ class Link
protected $method;
protected $host;
protected $path;
+ protected $base;
/**
* Constructor.
@@ -30,10 +31,11 @@ class Link
* @param string $method The method to use for the link (get by default)
* @param string $host The base URI to use for absolute links (like http://localhost)
* @param string $path The base path for relative links (/ by default)
+ * @param strin $base An optional base href for generating the uri
*
* @throws \LogicException if the node is not a link
*/
- public function __construct(\DOMNode $node, $method = 'get', $host = null, $path = '/')
+ public function __construct(\DOMNode $node, $method = 'get', $host = null, $path = '/', $base = null)
{
if ('a' != $node->nodeName) {
throw new \LogicException(sprintf('Unable to click on a "%s" tag.', $node->nodeName));
@@ -43,6 +45,7 @@ public function __construct(\DOMNode $node, $method = 'get', $host = null, $path
$this->method = $method;
$this->host = $host;
$this->path = empty($path) ? '/' : $path;
+ $this->base = $base;
}
/**
@@ -72,11 +75,14 @@ public function getUri($absolute = true)
$path = substr($path, 0, strrpos($path, '/') + 1);
}
- if ($uri && '/' !== $uri[0] && !$urlHaveScheme) {
+ if (!$this->base && $uri && '/' !== $uri[0] && !$urlHaveScheme) {
$uri = $path.$uri;
+ } elseif ($this->base) {
+ $uri = $this->base.$uri;
}
- if ($absolute && null !== $this->host && !$urlHaveScheme) {
+ if (!$this->base && $absolute && null !== $this->host && !$urlHaveScheme) {
+
return $this->host.$uri;
}
diff --git a/tests/Symfony/Tests/Component/DomCrawler/FormTest.php b/tests/Symfony/Tests/Component/DomCrawler/FormTest.php
index b95348d4100c9..b8c105232a198 100644
--- a/tests/Symfony/Tests/Component/DomCrawler/FormTest.php
+++ b/tests/Symfony/Tests/Component/DomCrawler/FormTest.php
@@ -384,4 +384,14 @@ protected function createForm($form, $method = null, $host = null, $path = '/')
return new Form($nodes->item($nodes->length - 1), $method, $host, $path);
}
+
+ public function testBase()
+ {
+ $dom = new \DOMDocument();
+ $dom->loadHTML('
');
+
+ $nodes = $dom->getElementsByTagName('input');
+ $form = new Form($nodes->item($nodes->length - 1), null, 'http://www.bar.com/foobar/', '/', 'http://www.foo.com/');
+ $this->assertEquals('http://www.foo.com/foo.php', $form->getUri());
+ }
}
diff --git a/tests/Symfony/Tests/Component/DomCrawler/LinkTest.php b/tests/Symfony/Tests/Component/DomCrawler/LinkTest.php
index bf3fda2c25ea7..a97e813c4d6ee 100644
--- a/tests/Symfony/Tests/Component/DomCrawler/LinkTest.php
+++ b/tests/Symfony/Tests/Component/DomCrawler/LinkTest.php
@@ -82,5 +82,11 @@ public function testGetters()
$link = new Link($node, 'get', 'http://www.foo.com', '/foo/bar');
$this->assertEquals('/foo/bar?get=param', $link->getUri(false), '->getUri() returns the relative URI of the link if false is the first argument');
+
+ $dom = new \DOMDocument();
+ $dom->loadHTML('foo');
+ $node = $dom->getElementsByTagName('a')->item(0);
+ $link = new Link($node, 'get', null, '/foo/bar', 'http://www.foo.com/');
+ $this->assertEquals('http://www.foo.com/test.html', $link->getUri());
}
}