Prevent adding non-DOMElement elements in DomCrawler

Many methods of the DomCrawler component are relying on the DOMElement
API, not only on the DOMNode API.
This commit is contained in:
Christophe Coevoet 2015-10-02 01:09:43 +02:00
parent 99745e12a7
commit 9f362a12f6
2 changed files with 35 additions and 8 deletions

View File

@ -308,10 +308,14 @@ class Crawler extends \SplObjectStorage
public function addNode(\DOMNode $node)
{
if ($node instanceof \DOMDocument) {
parent::attach($node->documentElement);
} else {
parent::attach($node);
$node = $node->documentElement;
}
if (!$node instanceof \DOMElement) {
throw new \InvalidArgumentException(sprintf('Nodes set in a Crawler must be DOMElement or DOMDocument instances, "%s" given.', get_class($node)));
}
parent::attach($node);
}
// Serializing and unserializing a crawler creates DOM objects in a corrupted state. DOM elements are not properly serializable.
@ -974,7 +978,12 @@ class Crawler extends \SplObjectStorage
foreach ($this as $node) {
$domxpath = $this->createDOMXPath($node->ownerDocument, $prefixes);
$crawler->add($domxpath->query($xpath, $node));
foreach ($domxpath->query($xpath, $node) as $subNode) {
if ($subNode->nodeType === 1) {
$crawler->add($subNode);
}
}
}
return $crawler;

View File

@ -20,7 +20,10 @@ class CrawlerTest extends \PHPUnit_Framework_TestCase
$crawler = new Crawler();
$this->assertCount(0, $crawler, '__construct() returns an empty crawler');
$crawler = new Crawler(new \DOMNode());
$doc = new \DOMDocument();
$node = $doc->createElement('test');
$crawler = new Crawler($node);
$this->assertCount(1, $crawler, '__construct() takes a node as a first argument');
}
@ -37,6 +40,7 @@ class CrawlerTest extends \PHPUnit_Framework_TestCase
$crawler->add($this->createNodeList());
$this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from a \DOMNodeList');
$list = array();
foreach ($this->createNodeList() as $node) {
$list[] = $node;
}
@ -56,12 +60,22 @@ class CrawlerTest extends \PHPUnit_Framework_TestCase
/**
* @expectedException \InvalidArgumentException
*/
public function testAddInvalidNode()
public function testAddInvalidType()
{
$crawler = new Crawler();
$crawler->add(1);
}
/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage Nodes set in a Crawler must be DOMElement or DOMDocument instances, "DOMNode" given.
*/
public function testAddInvalidNode()
{
$crawler = new Crawler();
$crawler->add(new \DOMNode());
}
/**
* @covers Symfony\Component\DomCrawler\Crawler::addHtmlContent
*/
@ -267,6 +281,7 @@ EOF
*/
public function testAddNodes()
{
$list = array();
foreach ($this->createNodeList() as $node) {
$list[] = $node;
}
@ -290,7 +305,10 @@ EOF
public function testClear()
{
$crawler = new Crawler(new \DOMNode());
$doc = new \DOMDocument();
$node = $doc->createElement('test');
$crawler = new Crawler($node);
$crawler->clear();
$this->assertCount(0, $crawler, '->clear() removes all the nodes from the crawler');
}
@ -526,7 +544,7 @@ EOF
public function testFilterXPathWithAttributeAxisAfterElementAxis()
{
$this->assertCount(3, $this->createTestCrawler()->filterXPath('//form/button/attribute::*'), '->filterXPath() handles attribute axes properly when they are preceded by an element filtering axis');
$this->assertCount(0, $this->createTestCrawler()->filterXPath('//form/button/attribute::*'), '->filterXPath() handles attribute axes properly when they are preceded by an element filtering axis');
}
public function testFilterXPathWithChildAxis()