diff --git a/src/Symfony/Component/DomCrawler/AbstractUriElement.php b/src/Symfony/Component/DomCrawler/AbstractUriElement.php
index 39ae522fd178..e26be3fcf694 100644
--- a/src/Symfony/Component/DomCrawler/AbstractUriElement.php
+++ b/src/Symfony/Component/DomCrawler/AbstractUriElement.php
@@ -40,15 +40,17 @@ abstract class AbstractUriElement
*
* @throws \InvalidArgumentException if the node is not a link
*/
- public function __construct(\DOMElement $node, string $currentUri, ?string $method = 'GET')
+ public function __construct(\DOMElement $node, string $currentUri = null, ?string $method = 'GET')
{
- if (!\in_array(strtolower(substr($currentUri, 0, 4)), array('http', 'file'))) {
- throw new \InvalidArgumentException(sprintf('Current URI must be an absolute URL ("%s").', $currentUri));
- }
-
$this->setNode($node);
$this->method = $method ? strtoupper($method) : null;
$this->currentUri = $currentUri;
+
+ $elementUriIsRelative = null === parse_url(trim($this->getRawUri()), PHP_URL_SCHEME);
+ $baseUriIsAbsolute = \in_array(strtolower(substr($this->currentUri, 0, 4)), array('http', 'file'));
+ if ($elementUriIsRelative && !$baseUriIsAbsolute) {
+ throw new \InvalidArgumentException(sprintf('The URL of the element is relative, so you must define its base URI passing an absolute URL to the constructor of the %s class ("%s" was passed).', __CLASS__, $this->currentUri));
+ }
}
/**
diff --git a/src/Symfony/Component/DomCrawler/CHANGELOG.md b/src/Symfony/Component/DomCrawler/CHANGELOG.md
index e65176f5ac0b..c2065c591154 100644
--- a/src/Symfony/Component/DomCrawler/CHANGELOG.md
+++ b/src/Symfony/Component/DomCrawler/CHANGELOG.md
@@ -1,6 +1,12 @@
CHANGELOG
=========
+4.2.0
+-----
+
+* The `$currentUri` constructor argument of the `AbstractUriElement`, `Link` and
+ `Image` classes is now optional.
+
3.1.0
-----
diff --git a/src/Symfony/Component/DomCrawler/Image.php b/src/Symfony/Component/DomCrawler/Image.php
index fb83eaac1989..b1ac5ca2ccb4 100644
--- a/src/Symfony/Component/DomCrawler/Image.php
+++ b/src/Symfony/Component/DomCrawler/Image.php
@@ -16,7 +16,7 @@
*/
class Image extends AbstractUriElement
{
- public function __construct(\DOMElement $node, string $currentUri)
+ public function __construct(\DOMElement $node, string $currentUri = null)
{
parent::__construct($node, $currentUri, 'GET');
}
diff --git a/src/Symfony/Component/DomCrawler/Tests/ImageTest.php b/src/Symfony/Component/DomCrawler/Tests/ImageTest.php
index 309578a90233..5cac757cdfb3 100644
--- a/src/Symfony/Component/DomCrawler/Tests/ImageTest.php
+++ b/src/Symfony/Component/DomCrawler/Tests/ImageTest.php
@@ -27,6 +27,27 @@ public function testConstructorWithANonImgTag()
new Image($dom->getElementsByTagName('div')->item(0), 'http://www.example.com/');
}
+ public function testBaseUriIsOptionalWhenImageUrlIsAbsolute()
+ {
+ $dom = new \DOMDocument();
+ $dom->loadHTML('');
+
+ $image = new Image($dom->getElementsByTagName('img')->item(0));
+ $this->assertSame('https://example.com/foo', $image->getUri());
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testAbsoluteBaseUriIsMandatoryWhenImageUrlIsRelative()
+ {
+ $dom = new \DOMDocument();
+ $dom->loadHTML('');
+
+ $image = new Image($dom->getElementsByTagName('img')->item(0), 'example.com');
+ $image->getUri();
+ }
+
/**
* @dataProvider getGetUriTests
*/
diff --git a/src/Symfony/Component/DomCrawler/Tests/LinkTest.php b/src/Symfony/Component/DomCrawler/Tests/LinkTest.php
index 3f0364705f98..f485cc2ac1ee 100644
--- a/src/Symfony/Component/DomCrawler/Tests/LinkTest.php
+++ b/src/Symfony/Component/DomCrawler/Tests/LinkTest.php
@@ -27,15 +27,25 @@ public function testConstructorWithANonATag()
new Link($dom->getElementsByTagName('div')->item(0), 'http://www.example.com/');
}
+ public function testBaseUriIsOptionalWhenLinkUrlIsAbsolute()
+ {
+ $dom = new \DOMDocument();
+ $dom->loadHTML('foo');
+
+ $link = new Link($dom->getElementsByTagName('a')->item(0));
+ $this->assertSame('https://example.com/foo', $link->getUri());
+ }
+
/**
* @expectedException \InvalidArgumentException
*/
- public function testConstructorWithAnInvalidCurrentUri()
+ public function testAbsoluteBaseUriIsMandatoryWhenLinkUrlIsRelative()
{
$dom = new \DOMDocument();
$dom->loadHTML('foo');
- new Link($dom->getElementsByTagName('a')->item(0), 'example.com');
+ $link = new Link($dom->getElementsByTagName('a')->item(0), 'example.com');
+ $link->getUri();
}
public function testGetNode()