From 6f0da01ae7f188efe3ce7f00fce989c4b3ac8181 Mon Sep 17 00:00:00 2001 From: Jeremy Bush Date: Wed, 12 Jan 2011 19:05:26 -0600 Subject: [PATCH] Add support for base tag for Link and Form, Fixes #9422 --- src/Symfony/Component/DomCrawler/Crawler.php | 22 +++++++++++++++---- src/Symfony/Component/DomCrawler/Form.php | 11 +++++++--- src/Symfony/Component/DomCrawler/Link.php | 12 +++++++--- .../Tests/Component/DomCrawler/FormTest.php | 10 +++++++++ .../Tests/Component/DomCrawler/LinkTest.php | 6 +++++ 5 files changed, 51 insertions(+), 10 deletions(-) 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()); } }