diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php index 5ab8d8e243..1fe5df87cf 100644 --- a/src/Symfony/Component/DomCrawler/Crawler.php +++ b/src/Symfony/Component/DomCrawler/Crawler.php @@ -23,21 +23,27 @@ use Symfony\Component\CssSelector\CssSelector; class Crawler extends \SplObjectStorage { /** - * @var string The current URI or the base href value + * @var string The current URI */ protected $uri; + /** + * @var string The base href value + */ + private $baseHref; + /** * Constructor. * * @param mixed $node A Node to use as the base for the crawling - * @param string $uri The current URI or the base href value - * + * @param string $currentUri The current URI + * @param string $baseHref The base href value * @api */ - public function __construct($node = null, $uri = null) + public function __construct($node = null, $currentUri = null, $baseHref = null) { - $this->uri = $uri; + $this->uri = $currentUri; + $this->baseHref = $baseHref ?: $currentUri; $this->add($node); } @@ -176,13 +182,13 @@ class Crawler extends \SplObjectStorage $baseHref = current($base); if (count($base) && !empty($baseHref)) { - if ($this->uri) { + if ($this->baseHref) { $linkNode = $dom->createElement('a'); $linkNode->setAttribute('href', $baseHref); - $link = new Link($linkNode, $this->uri); - $this->uri = $link->getUri(); + $link = new Link($linkNode, $this->baseHref); + $this->baseHref = $link->getUri(); } else { - $this->uri = $baseHref; + $this->baseHref = $baseHref; } } } @@ -294,11 +300,11 @@ class Crawler extends \SplObjectStorage { foreach ($this as $i => $node) { if ($i == $position) { - return new static($node, $this->uri); + return new static($node, $this->uri, $this->baseHref); } } - return new static(null, $this->uri); + return new static(null, $this->uri, $this->baseHref); } /** @@ -323,7 +329,7 @@ class Crawler extends \SplObjectStorage { $data = array(); foreach ($this as $i => $node) { - $data[] = $closure(new static($node, $this->uri), $i); + $data[] = $closure(new static($node, $this->uri, $this->baseHref), $i); } return $data; @@ -344,12 +350,12 @@ class Crawler extends \SplObjectStorage { $nodes = array(); foreach ($this as $i => $node) { - if (false !== $closure(new static($node, $this->uri), $i)) { + if (false !== $closure(new static($node, $this->uri, $this->baseHref), $i)) { $nodes[] = $node; } } - return new static($nodes, $this->uri); + return new static($nodes, $this->uri, $this->baseHref); } /** @@ -391,7 +397,7 @@ class Crawler extends \SplObjectStorage throw new \InvalidArgumentException('The current node list is empty.'); } - return new static($this->sibling($this->getNode(0)->parentNode->firstChild), $this->uri); + return new static($this->sibling($this->getNode(0)->parentNode->firstChild), $this->uri, $this->baseHref); } /** @@ -409,7 +415,7 @@ class Crawler extends \SplObjectStorage throw new \InvalidArgumentException('The current node list is empty.'); } - return new static($this->sibling($this->getNode(0)), $this->uri); + return new static($this->sibling($this->getNode(0)), $this->uri, $this->baseHref); } /** @@ -427,7 +433,7 @@ class Crawler extends \SplObjectStorage throw new \InvalidArgumentException('The current node list is empty.'); } - return new static($this->sibling($this->getNode(0), 'previousSibling'), $this->uri); + return new static($this->sibling($this->getNode(0), 'previousSibling'), $this->uri, $this->baseHref); } /** @@ -454,7 +460,7 @@ class Crawler extends \SplObjectStorage } } - return new static($nodes, $this->uri); + return new static($nodes, $this->uri, $this->baseHref); } /** @@ -474,7 +480,7 @@ class Crawler extends \SplObjectStorage $node = $this->getNode(0)->firstChild; - return new static($node ? $this->sibling($node) : array(), $this->uri); + return new static($node ? $this->sibling($node) : array(), $this->uri, $this->baseHref); } /** @@ -601,7 +607,7 @@ class Crawler extends \SplObjectStorage // If we dropped all expressions in the XPath while preparing it, there would be no match if ('' === $xpath) { - return new static(null, $this->uri); + return new static(null, $this->uri, $this->baseHref); } return $this->filterRelativeXPath($xpath); @@ -687,7 +693,7 @@ class Crawler extends \SplObjectStorage $node = $this->getNode(0); - return new Link($node, $this->uri, $method); + return new Link($node, $this->baseHref, $method); } /** @@ -701,7 +707,7 @@ class Crawler extends \SplObjectStorage { $links = array(); foreach ($this as $node) { - $links[] = new Link($node, $this->uri, 'get'); + $links[] = new Link($node, $this->baseHref, 'get'); } return $links; @@ -792,7 +798,7 @@ class Crawler extends \SplObjectStorage */ private function filterRelativeXPath($xpath) { - $crawler = new static(null, $this->uri); + $crawler = new static(null, $this->uri, $this->baseHref); foreach ($this as $node) { $domxpath = new \DOMXPath($node->ownerDocument); diff --git a/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php b/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php index d424deaaad..ce3bcae11c 100644 --- a/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php @@ -823,16 +823,42 @@ HTML; } } - public function testBaseTag() + /** + * @dataProvider getBaseTagData + */ + public function testBaseTag($baseValue, $linkValue, $expectedUri, $currentUri = null, $description = null) { - $crawler = new Crawler(''); - $this->assertEquals('http://base.com/link', $crawler->filterXPath('//a')->link()->getUri()); + $crawler = new Crawler('', $currentUri); + $this->assertEquals($expectedUri, $crawler->filterXPath('//a')->link()->getUri(), $description); + } - $crawler = new Crawler('', 'https://domain.com'); - $this->assertEquals('https://base.com/link', $crawler->filterXPath('//a')->link()->getUri(), ' tag can use a schema-less URL'); + public function getBaseTagData() + { + return array( + array('http://base.com', 'link', 'http://base.com/link'), + array('//base.com', 'link', 'https://base.com/link', 'https://domain.com', ' tag can use a schema-less URL'), + array('path/', 'link', 'https://domain.com/path/link', 'https://domain.com', ' tag can set a path'), + array('http://base.com', '#', 'http://base.com#', 'http://domain.com/path/link', ' tag does work with links to an anchor'), + array('http://base.com', '', 'http://base.com', 'http://domain.com/path/link', ' tag does work with empty links'), + ); + } - $crawler = new Crawler('', 'https://domain.com'); - $this->assertEquals('https://domain.com/path/link', $crawler->filterXPath('//a')->link()->getUri(), ' tag can set a path'); + /** + * @dataProvider getBaseTagWithFormData + */ + public function testBaseTagWithForm($baseValue, $actionValue, $expectedUri, $currentUri = null, $description = null) + { + $crawler = new Crawler('