Skip to content

Commit 75bca86

Browse files
authored
Merge pull request paquettg#90 from andreyshade/develop
Add additional features
2 parents 213b0ae + 32ae4a0 commit 75bca86

File tree

10 files changed

+324
-5
lines changed

10 files changed

+324
-5
lines changed

src/PHPHtmlParser/Dom.php

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ public function __get($name)
135135
*/
136136
public function load($str, $options = [])
137137
{
138+
AbstractNode::resetCount();
138139
// check if it's a file
139140
if (strpos($str, "\n") === false && is_file($str)) {
140141
return $this->loadFromFile($str, $options);
@@ -234,6 +235,20 @@ public function find($selector, $nth = null)
234235
return $this->root->find($selector, $nth);
235236
}
236237

238+
/**
239+
* Find element by Id on the root node
240+
*
241+
* @param int $id Element Id
242+
* @return mixed
243+
*
244+
*/
245+
public function findById($id)
246+
{
247+
$this->isLoaded();
248+
249+
return $this->root->findById($id);
250+
}
251+
237252
/**
238253
* Adds the tag (or tags in an array) to the list of tags that will always
239254
* be self closing.
@@ -353,6 +368,42 @@ public function lastChild()
353368
return $this->root->lastChild();
354369
}
355370

371+
/**
372+
* Simple wrapper function that returns count of child elements
373+
*
374+
* @return int
375+
*/
376+
public function countChildren()
377+
{
378+
$this->isLoaded();
379+
380+
return $this->root->countChildren();
381+
}
382+
383+
/**
384+
* Get array of children
385+
*
386+
* @return array
387+
*/
388+
public function getChildren()
389+
{
390+
$this->isLoaded();
391+
392+
return $this->root->getChildren();
393+
}
394+
395+
/**
396+
* Check if node have children nodes
397+
*
398+
* @return bool
399+
*/
400+
public function hasChildren()
401+
{
402+
$this->isLoaded();
403+
404+
return $this->root->hasChildren();
405+
}
406+
356407
/**
357408
* Simple wrapper function that returns an element by the
358409
* id.
@@ -453,7 +504,9 @@ protected function clean($str)
453504
}
454505

455506
// strip out server side scripts
456-
$str = mb_eregi_replace("(<\?)(.*?)(\?>)", '', $str);
507+
if ($this->options->get('serverSideScriptis') == true){
508+
$str = mb_eregi_replace("(<\?)(.*?)(\?>)", '', $str);
509+
}
457510

458511
// strip smarty scripts
459512
$str = mb_eregi_replace("(\{\w)(.*?)(\})", '', $str);

src/PHPHtmlParser/Dom/AbstractNode.php

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PHPHtmlParser\Exceptions\ParentNotFoundException;
66
use PHPHtmlParser\Selector;
77
use stringEncode\Encode;
8+
use PHPHtmlParser\Finder;
89

910
/**
1011
* Dom node object.
@@ -17,7 +18,7 @@
1718
*/
1819
abstract class AbstractNode
1920
{
20-
21+
private static $count = 0;
2122
/**
2223
* Contains the tag name/type
2324
*
@@ -54,11 +55,12 @@ abstract class AbstractNode
5455
protected $encode;
5556

5657
/**
57-
* Creates a unique spl hash for this node.
58+
* Creates a unique id for this node.
5859
*/
5960
public function __construct()
6061
{
61-
$this->id = spl_object_hash($this);
62+
$this->id = self::$count;
63+
self::$count++;
6264
}
6365

6466
/**
@@ -110,6 +112,14 @@ public function __toString()
110112
return $this->outerHtml();
111113
}
112114

115+
/**
116+
* Reset node counter
117+
*/
118+
public static function resetCount()
119+
{
120+
self::$count = 0;
121+
}
122+
113123
/**
114124
* Returns the id of this object.
115125
*/
@@ -220,6 +230,15 @@ public function getAncestor($id)
220230
return null;
221231
}
222232

233+
public function hasNextSibling()
234+
{
235+
if (is_null($this->parent) || (!$this->parent->hasChildren())) {
236+
return false;
237+
}
238+
239+
return $this->parent->hasNextChild($this->id());
240+
}
241+
223242
/**
224243
* Attempts to get the next sibling.
225244
*
@@ -398,6 +417,20 @@ public function find($selector, $nth = null)
398417
return $nodes;
399418
}
400419

420+
/**
421+
* Find node by id
422+
*
423+
* @param $id
424+
* @return bool|AbstractNode
425+
*/
426+
public function findById($id)
427+
{
428+
$finder= new Finder($id);
429+
430+
return $finder->find($this);
431+
}
432+
433+
401434
/**
402435
* Gets the inner html of this node.
403436
*
@@ -427,4 +460,14 @@ abstract public function text();
427460
* @return void
428461
*/
429462
abstract protected function clear();
463+
464+
/**
465+
* Check is node type textNode
466+
*
467+
* @return boolean
468+
*/
469+
public function isTextNode() {
470+
471+
return false;
472+
}
430473
}

src/PHPHtmlParser/Dom/InnerNode.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,18 @@ public function removeChild($id)
175175
return $this;
176176
}
177177

178+
/**
179+
* Check if has next Child
180+
*
181+
* @param $id childId
182+
* @return mixed
183+
*/
184+
public function hasNextChild($id)
185+
{
186+
$child= $this->getChild($id);
187+
return $this->children[$child->id()]['next'];
188+
}
189+
178190
/**
179191
* Attempts to get the next child.
180192
*

src/PHPHtmlParser/Dom/Tag.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,51 @@ public function setAttribute($key, $value)
173173
return $this;
174174
}
175175

176+
/**
177+
* Set inline style attribute value.
178+
*
179+
* @param $attr_key
180+
* @param $attr_value
181+
*/
182+
public function setStyleAttributeValue($attr_key, $attr_value)
183+
{
184+
185+
$style_array = $this->getStyleAttributeArray();
186+
$style_array[$attr_key] = $attr_value;
187+
188+
$style_string = '';
189+
foreach ($style_array as $key => $value) {
190+
$style_string .= $key . ':' . $value . ';';
191+
}
192+
193+
$this->setAttribute('style', $style_string);
194+
}
195+
196+
/**
197+
* Get style attribute in array
198+
*
199+
* @return array|null
200+
*/
201+
public function getStyleAttributeArray()
202+
{
203+
$value = $this->getAttribute('style')['value'];
204+
205+
if ($value === null) {
206+
return null;
207+
}
208+
209+
$value = explode(';', substr(trim($value), 0, -1));
210+
$result = [];
211+
foreach ($value as $attr) {
212+
$attr = explode(':', $attr);
213+
$result[$attr[0]] = $attr[1];
214+
}
215+
216+
return $result;
217+
}
218+
219+
220+
176221
/**
177222
* Removes an attribute from this tag.
178223
*

src/PHPHtmlParser/Dom/TextNode.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,15 @@ protected function clear()
120120
{
121121
$this->convertedText = null;
122122
}
123+
124+
public function isTextNode()
125+
{
126+
return true;
127+
}
128+
129+
public function setText($text)
130+
{
131+
$this->text = $text;
132+
}
133+
123134
}

src/PHPHtmlParser/Finder.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
namespace PHPHtmlParser;
4+
5+
use PHPHtmlParser\Dom\AbstractNode;
6+
7+
class Finder
8+
{
9+
private $id;
10+
11+
/**
12+
* Finder constructor.
13+
* @param $id
14+
*/
15+
public function __construct($id)
16+
{
17+
$this->id = $id;
18+
}
19+
20+
/**
21+
*
22+
* Find node in tree by id
23+
*
24+
* @param AbstractNode $node
25+
* @return bool|AbstractNode
26+
*/
27+
public function find(AbstractNode $node)
28+
{
29+
if (!$node->id()) {
30+
return $this->find($node->firstChild());
31+
}
32+
33+
if ($node->id() == $this->id) {
34+
return $node;
35+
}
36+
37+
if ($node->hasNextSibling()) {
38+
$nextSibling = $node->nextSibling();
39+
if ($nextSibling->id() == $this->id) {
40+
return $nextSibling;
41+
}
42+
if ($nextSibling->id() > $this->id) {
43+
return $this->find($node->firstChild());
44+
}
45+
if ($nextSibling->id() < $this->id) {
46+
return $this->find($nextSibling);
47+
}
48+
} else if (!$node->isTextNode()) {
49+
return $this->find($node->firstChild());
50+
}
51+
52+
return false;
53+
}
54+
}

tests/DomTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,4 +329,52 @@ public function testDeleteNode()
329329
unset($a);
330330
$this->assertEquals('<div class="all"><p>Hey bro, <br /> :)</p></div>', (string) $dom);
331331
}
332+
333+
public function testCountChildren()
334+
{
335+
$dom = new Dom;
336+
$dom->load('<strong>hello</strong><code class="language-php">$foo = "bar";</code>');
337+
$this->assertEquals(2, $dom->countChildren());
338+
}
339+
340+
public function testGetChildrenArray()
341+
{
342+
$dom = new Dom;
343+
$dom->load('<strong>hello</strong><code class="language-php">$foo = "bar";</code>');
344+
$this->assertInternalType('array', $dom->getChildren());
345+
}
346+
347+
public function testHasChildren()
348+
{
349+
$dom = new Dom;
350+
$dom->load('<strong>hello</strong><code class="language-php">$foo = "bar";</code>');
351+
$this->assertTrue($dom->hasChildren());
352+
}
353+
354+
public function testFindByIdVar1()
355+
{
356+
$dom = new Dom;
357+
$dom->load('<div class="all"><p>Hey bro, <a href="google.com">click here</a><br /> :)</p></div>');
358+
/** @var Dom\AbstractNode $result */
359+
$result = $dom->findById(4);
360+
$this->assertEquals(4, $result->id());
361+
}
362+
363+
public function testFindByIdVar2()
364+
{
365+
$dom = new Dom;
366+
$dom->load('<div class="all"><p>Hey bro, <a href="google.com">click here</a><br /> :)</p></div>');
367+
/** @var Dom\AbstractNode $result */
368+
$result = $dom->findById(5);
369+
$this->assertEquals(5, $result->id());
370+
}
371+
372+
public function testFindByIdNotFountEleement()
373+
{
374+
$dom = new Dom;
375+
$dom->load('<div class="all"><p>Hey bro, <a href="google.com">click here</a><br /> :)</p></div>');
376+
/** @var Dom\AbstractNode $result */
377+
$result = $dom->findById(8);
378+
$this->assertFalse($result);
379+
}
332380
}

0 commit comments

Comments
 (0)