Version Description
- Add: Remove warnings for PHP 7.4.
- Update: New versions of DiDom and the Simple HTML DOM Parser.
- Info: If you like the plugin, your reviews are welcome here :) Thank you!
Download this release
Release Info
Developer | TigrouMeow |
Plugin | Gallery Custom Links |
Version | 1.2.7 |
Comparing to | |
See all releases |
Code changes from version 1.2.6 to 1.2.7
- common/img/kinsta.png +0 -0
- common/img/stackpath.png +0 -0
- composer.lock +10 -11
- gallery-custom-links.php +2 -2
- mgcl_admin.php +1 -1
- mgcl_core.php +2 -3
- mgcl_linker.php +3 -2
- readme.txt +7 -3
- vendor/composer/ClassLoader.php +1 -1
- vendor/composer/installed.json +12 -13
- vendor/imangazaliev/didom/.gitignore +0 -1
- vendor/imangazaliev/didom/.travis.yml +7 -6
- vendor/imangazaliev/didom/README-RU.md +1 -1
- vendor/imangazaliev/didom/README.md +1 -1
- vendor/imangazaliev/didom/composer.json +7 -3
- vendor/imangazaliev/didom/composer.lock +1049 -0
- vendor/imangazaliev/didom/phpunit.xml +12 -11
- vendor/imangazaliev/didom/src/DiDom/ClassAttribute.php +22 -24
- vendor/imangazaliev/didom/src/DiDom/Document.php +116 -101
- vendor/imangazaliev/didom/src/DiDom/DocumentFragment.php +34 -0
- vendor/imangazaliev/didom/src/DiDom/Element.php +63 -1139
- vendor/imangazaliev/didom/src/DiDom/Node.php +1193 -0
- vendor/imangazaliev/didom/src/DiDom/Query.php +25 -22
- vendor/imangazaliev/didom/src/DiDom/StyleAttribute.php +30 -32
- vendor/imangazaliev/didom/tests/DiDom/ClassAttributeTest.php +0 -383
- vendor/imangazaliev/didom/tests/DiDom/DocumentTest.php +0 -772
- vendor/imangazaliev/didom/tests/DiDom/ElementTest.php +0 -2094
- vendor/imangazaliev/didom/tests/DiDom/QueryTest.php +0 -425
- vendor/imangazaliev/didom/tests/DiDom/SelectorTest.php +0 -327
- vendor/imangazaliev/didom/tests/DiDom/StyleAttributeTest.php +0 -515
- vendor/imangazaliev/didom/tests/TestCase.php +0 -40
- vendor/imangazaliev/didom/tests/bootstrap.php +0 -7
- vendor/imangazaliev/didom/tests/fixtures/books.xml +0 -120
- vendor/imangazaliev/didom/tests/fixtures/menu.html +0 -15
- vendor/imangazaliev/didom/tests/fixtures/posts.html +0 -25
- vendor/kub-at/php-simple-html-dom-parser/README.md +2 -2
- vendor/kub-at/php-simple-html-dom-parser/src/KubAT/PhpSimple/lib/simple_html_dom.php +282 -737
common/img/kinsta.png
CHANGED
Binary file
|
common/img/stackpath.png
CHANGED
Binary file
|
composer.lock
CHANGED
@@ -8,16 +8,16 @@
|
|
8 |
"packages": [
|
9 |
{
|
10 |
"name": "imangazaliev/didom",
|
11 |
-
"version": "1.
|
12 |
"source": {
|
13 |
"type": "git",
|
14 |
"url": "https://github.com/Imangazaliev/DiDOM.git",
|
15 |
-
"reference": "
|
16 |
},
|
17 |
"dist": {
|
18 |
"type": "zip",
|
19 |
-
"url": "https://api.github.com/repos/Imangazaliev/DiDOM/zipball/
|
20 |
-
"reference": "
|
21 |
"shasum": ""
|
22 |
},
|
23 |
"require": {
|
@@ -26,7 +26,6 @@
|
|
26 |
"php": ">=5.4"
|
27 |
},
|
28 |
"require-dev": {
|
29 |
-
"friendsofphp/php-cs-fixer": "2.9",
|
30 |
"phpunit/phpunit": "^4.8"
|
31 |
},
|
32 |
"type": "library",
|
@@ -53,20 +52,20 @@
|
|
53 |
"parser",
|
54 |
"xml"
|
55 |
],
|
56 |
-
"time": "
|
57 |
},
|
58 |
{
|
59 |
"name": "kub-at/php-simple-html-dom-parser",
|
60 |
-
"version": "1.
|
61 |
"source": {
|
62 |
"type": "git",
|
63 |
"url": "https://github.com/Kub-AT/php-simple-html-dom-parser.git",
|
64 |
-
"reference": "
|
65 |
},
|
66 |
"dist": {
|
67 |
"type": "zip",
|
68 |
-
"url": "https://api.github.com/repos/Kub-AT/php-simple-html-dom-parser/zipball/
|
69 |
-
"reference": "
|
70 |
"shasum": ""
|
71 |
},
|
72 |
"require": {
|
@@ -99,7 +98,7 @@
|
|
99 |
"dom",
|
100 |
"html"
|
101 |
],
|
102 |
-
"time": "2019-
|
103 |
}
|
104 |
],
|
105 |
"packages-dev": [],
|
8 |
"packages": [
|
9 |
{
|
10 |
"name": "imangazaliev/didom",
|
11 |
+
"version": "1.16",
|
12 |
"source": {
|
13 |
"type": "git",
|
14 |
"url": "https://github.com/Imangazaliev/DiDOM.git",
|
15 |
+
"reference": "c2a8bd08679d2eec856782277267a48553322c7e"
|
16 |
},
|
17 |
"dist": {
|
18 |
"type": "zip",
|
19 |
+
"url": "https://api.github.com/repos/Imangazaliev/DiDOM/zipball/c2a8bd08679d2eec856782277267a48553322c7e",
|
20 |
+
"reference": "c2a8bd08679d2eec856782277267a48553322c7e",
|
21 |
"shasum": ""
|
22 |
},
|
23 |
"require": {
|
26 |
"php": ">=5.4"
|
27 |
},
|
28 |
"require-dev": {
|
|
|
29 |
"phpunit/phpunit": "^4.8"
|
30 |
},
|
31 |
"type": "library",
|
52 |
"parser",
|
53 |
"xml"
|
54 |
],
|
55 |
+
"time": "2020-05-12T21:04:30+00:00"
|
56 |
},
|
57 |
{
|
58 |
"name": "kub-at/php-simple-html-dom-parser",
|
59 |
+
"version": "1.9.1",
|
60 |
"source": {
|
61 |
"type": "git",
|
62 |
"url": "https://github.com/Kub-AT/php-simple-html-dom-parser.git",
|
63 |
+
"reference": "ff22f98bfd9235115c128059076f3eb740d66913"
|
64 |
},
|
65 |
"dist": {
|
66 |
"type": "zip",
|
67 |
+
"url": "https://api.github.com/repos/Kub-AT/php-simple-html-dom-parser/zipball/ff22f98bfd9235115c128059076f3eb740d66913",
|
68 |
+
"reference": "ff22f98bfd9235115c128059076f3eb740d66913",
|
69 |
"shasum": ""
|
70 |
},
|
71 |
"require": {
|
98 |
"dom",
|
99 |
"html"
|
100 |
],
|
101 |
+
"time": "2019-10-25T12:34:43+00:00"
|
102 |
}
|
103 |
],
|
104 |
"packages-dev": [],
|
gallery-custom-links.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: Gallery Custom Links
|
4 |
Plugin URI: https://meowapps.com
|
5 |
Description: Gallery Custom Links allows you to link images from galleries to a specified URL. Tested with WordPress Gallery, Gutenberg, the Meow Gallery and others.
|
6 |
-
Version: 1.2.
|
7 |
Author: Jordy Meow
|
8 |
Author URI: https://meowapps.com
|
9 |
Text Domain: gallery-custom-links
|
@@ -23,7 +23,7 @@ if ( class_exists( 'Meow_Gallery_Custom_Links' ) ) {
|
|
23 |
}
|
24 |
|
25 |
global $mgcl_version;
|
26 |
-
$mgcl_version = '1.2.
|
27 |
|
28 |
include "mgcl_admin.php";
|
29 |
$mgcl_admin = new Meow_Gallery_Custom_Links_Admin( 'mgcl', __FILE__, 'gallery-custom-links' );
|
3 |
Plugin Name: Gallery Custom Links
|
4 |
Plugin URI: https://meowapps.com
|
5 |
Description: Gallery Custom Links allows you to link images from galleries to a specified URL. Tested with WordPress Gallery, Gutenberg, the Meow Gallery and others.
|
6 |
+
Version: 1.2.7
|
7 |
Author: Jordy Meow
|
8 |
Author URI: https://meowapps.com
|
9 |
Text Domain: gallery-custom-links
|
23 |
}
|
24 |
|
25 |
global $mgcl_version;
|
26 |
+
$mgcl_version = '1.2.7';
|
27 |
|
28 |
include "mgcl_admin.php";
|
29 |
$mgcl_admin = new Meow_Gallery_Custom_Links_Admin( 'mgcl', __FILE__, 'gallery-custom-links' );
|
mgcl_admin.php
CHANGED
@@ -174,7 +174,7 @@ class Meow_Gallery_Custom_Links_Admin extends MeowApps_Admin { // extends MeowAp
|
|
174 |
|
175 |
function admin_parsing_engine_callback( $args ) {
|
176 |
$layouts = array(
|
177 |
-
|
178 |
'HtmlDomParser' => array( 'name' => __( 'HtmlDomParser', 'gallery-custom-links' ), 'desc' => "" ),
|
179 |
'DiDom' => array( 'name' => __( 'DiDom', 'gallery-custom-links' ), 'desc' => "" )
|
180 |
);
|
174 |
|
175 |
function admin_parsing_engine_callback( $args ) {
|
176 |
$layouts = array(
|
177 |
+
'None' => array( 'name' => __( 'None (Not Supported Yet)', 'gallery-custom-links' ), 'desc' => "" ),
|
178 |
'HtmlDomParser' => array( 'name' => __( 'HtmlDomParser', 'gallery-custom-links' ), 'desc' => "" ),
|
179 |
'DiDom' => array( 'name' => __( 'DiDom', 'gallery-custom-links' ), 'desc' => "" )
|
180 |
);
|
mgcl_core.php
CHANGED
@@ -152,7 +152,6 @@ class Meow_Gallery_Custom_Links
|
|
152 |
$this->isEnabled = apply_filters( 'gallery_custom_links_enabled', true );
|
153 |
if ( !$this->isEnabled || !isset( $buffer ) || trim( $buffer ) === '' )
|
154 |
return $buffer;
|
155 |
-
|
156 |
if ( $this->parsingEngine === 'HtmlDomParser' ) {
|
157 |
$html = new KubAT\PhpSimple\HtmlDomParser();
|
158 |
$html = $html->str_get_html( $buffer, true, true, DEFAULT_TARGET_CHARSET, false );
|
@@ -161,9 +160,9 @@ class Meow_Gallery_Custom_Links
|
|
161 |
$html = new DiDom\Document();
|
162 |
$html->preserveWhiteSpace();
|
163 |
if ( defined( 'LIBXML_HTML_NOIMPLIED' ) && defined( 'LIBXML_HTML_NODEFDTD' ) )
|
164 |
-
$html->loadHtml( $buffer, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
|
165 |
else
|
166 |
-
$html->loadHtml( $buffer, 0 );
|
167 |
}
|
168 |
|
169 |
if ( empty( $html ) || is_bool( $html ) ) {
|
152 |
$this->isEnabled = apply_filters( 'gallery_custom_links_enabled', true );
|
153 |
if ( !$this->isEnabled || !isset( $buffer ) || trim( $buffer ) === '' )
|
154 |
return $buffer;
|
|
|
155 |
if ( $this->parsingEngine === 'HtmlDomParser' ) {
|
156 |
$html = new KubAT\PhpSimple\HtmlDomParser();
|
157 |
$html = $html->str_get_html( $buffer, true, true, DEFAULT_TARGET_CHARSET, false );
|
160 |
$html = new DiDom\Document();
|
161 |
$html->preserveWhiteSpace();
|
162 |
if ( defined( 'LIBXML_HTML_NOIMPLIED' ) && defined( 'LIBXML_HTML_NODEFDTD' ) )
|
163 |
+
$html->loadHtml( (string)$buffer, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
|
164 |
else
|
165 |
+
$html->loadHtml( (string)$buffer, 0 );
|
166 |
}
|
167 |
|
168 |
if ( empty( $html ) || is_bool( $html ) ) {
|
mgcl_linker.php
CHANGED
@@ -10,7 +10,8 @@ class Meow_Gallery_Custom_Links_Linker {
|
|
10 |
// XXXX: Custom code with $aria, Christoph Letmaier, 14.01.2020
|
11 |
function linker( $element, $parent, $mediaId, $url, $rel, $aria, $target ) {
|
12 |
// Let's look for the closest link tag enclosing the image
|
13 |
-
$
|
|
|
14 |
$potentialLinkNode = $parent;
|
15 |
$maxDepth = 5;
|
16 |
do {
|
@@ -46,7 +47,7 @@ class Meow_Gallery_Custom_Links_Linker {
|
|
46 |
if ( !empty( $rel ) )
|
47 |
$potentialLinkNode->attr( 'rel', $rel );
|
48 |
if ( !empty( $aria ) )
|
49 |
-
$potentialLinkNode->attr
|
50 |
}
|
51 |
return true;
|
52 |
}
|
10 |
// XXXX: Custom code with $aria, Christoph Letmaier, 14.01.2020
|
11 |
function linker( $element, $parent, $mediaId, $url, $rel, $aria, $target ) {
|
12 |
// Let's look for the closest link tag enclosing the image
|
13 |
+
$media = get_post( $mediaId );
|
14 |
+
$title = the_title_attribute( array( 'echo' => false, 'post' => $media ) );
|
15 |
$potentialLinkNode = $parent;
|
16 |
$maxDepth = 5;
|
17 |
do {
|
47 |
if ( !empty( $rel ) )
|
48 |
$potentialLinkNode->attr( 'rel', $rel );
|
49 |
if ( !empty( $aria ) )
|
50 |
+
$potentialLinkNode->attr['aria-label'] = $aria;
|
51 |
}
|
52 |
return true;
|
53 |
}
|
readme.txt
CHANGED
@@ -3,9 +3,9 @@ Contributors: TigrouMeow
|
|
3 |
Tags: custom, links, gallery, gutenberg
|
4 |
Donate link: https://commerce.coinbase.com/checkout/d047546a-77a8-41c8-9ea9-4a950f61832f
|
5 |
Requires at least: 5.0
|
6 |
-
Tested up to: 5.
|
7 |
Requires PHP: 7.0
|
8 |
-
Stable tag: 1.2.
|
9 |
|
10 |
Gallery Custom Links allows you to link images from galleries to a specified URL. Tested with WordPress Gallery, Gutenberg, the Meow Gallery and others.
|
11 |
|
@@ -42,9 +42,13 @@ Replace all the files. Nothing else to do.
|
|
42 |
|
43 |
== Changelog ==
|
44 |
|
|
|
|
|
|
|
|
|
|
|
45 |
= 1.2.6 =
|
46 |
* Add: Because we love the W3C, the title has been added to the link.
|
47 |
-
* Info: If you like the plugin, your reviews are welcome [here](https://wordpress.org/support/plugin/gallery-custom-links/reviews/?rate=5#new-post) :) Thank you!
|
48 |
|
49 |
= 1.2.5 =
|
50 |
* Fix: Avoid errors in the admin.
|
3 |
Tags: custom, links, gallery, gutenberg
|
4 |
Donate link: https://commerce.coinbase.com/checkout/d047546a-77a8-41c8-9ea9-4a950f61832f
|
5 |
Requires at least: 5.0
|
6 |
+
Tested up to: 5.4
|
7 |
Requires PHP: 7.0
|
8 |
+
Stable tag: 1.2.7
|
9 |
|
10 |
Gallery Custom Links allows you to link images from galleries to a specified URL. Tested with WordPress Gallery, Gutenberg, the Meow Gallery and others.
|
11 |
|
42 |
|
43 |
== Changelog ==
|
44 |
|
45 |
+
= 1.2.7 =
|
46 |
+
* Add: Remove warnings for PHP 7.4.
|
47 |
+
* Update: New versions of DiDom and the Simple HTML DOM Parser.
|
48 |
+
* Info: If you like the plugin, your reviews are welcome [here](https://wordpress.org/support/plugin/gallery-custom-links/reviews/?rate=5#new-post) :) Thank you!
|
49 |
+
|
50 |
= 1.2.6 =
|
51 |
* Add: Because we love the W3C, the title has been added to the link.
|
|
|
52 |
|
53 |
= 1.2.5 =
|
54 |
* Fix: Avoid errors in the admin.
|
vendor/composer/ClassLoader.php
CHANGED
@@ -279,7 +279,7 @@ class ClassLoader
|
|
279 |
*/
|
280 |
public function setApcuPrefix($apcuPrefix)
|
281 |
{
|
282 |
-
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
|
283 |
}
|
284 |
|
285 |
/**
|
279 |
*/
|
280 |
public function setApcuPrefix($apcuPrefix)
|
281 |
{
|
282 |
+
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
283 |
}
|
284 |
|
285 |
/**
|
vendor/composer/installed.json
CHANGED
@@ -1,17 +1,17 @@
|
|
1 |
[
|
2 |
{
|
3 |
"name": "imangazaliev/didom",
|
4 |
-
"version": "1.
|
5 |
-
"version_normalized": "1.
|
6 |
"source": {
|
7 |
"type": "git",
|
8 |
"url": "https://github.com/Imangazaliev/DiDOM.git",
|
9 |
-
"reference": "
|
10 |
},
|
11 |
"dist": {
|
12 |
"type": "zip",
|
13 |
-
"url": "https://api.github.com/repos/Imangazaliev/DiDOM/zipball/
|
14 |
-
"reference": "
|
15 |
"shasum": ""
|
16 |
},
|
17 |
"require": {
|
@@ -20,10 +20,9 @@
|
|
20 |
"php": ">=5.4"
|
21 |
},
|
22 |
"require-dev": {
|
23 |
-
"friendsofphp/php-cs-fixer": "2.9",
|
24 |
"phpunit/phpunit": "^4.8"
|
25 |
},
|
26 |
-
"time": "
|
27 |
"type": "library",
|
28 |
"installation-source": "dist",
|
29 |
"autoload": {
|
@@ -52,23 +51,23 @@
|
|
52 |
},
|
53 |
{
|
54 |
"name": "kub-at/php-simple-html-dom-parser",
|
55 |
-
"version": "1.
|
56 |
-
"version_normalized": "1.
|
57 |
"source": {
|
58 |
"type": "git",
|
59 |
"url": "https://github.com/Kub-AT/php-simple-html-dom-parser.git",
|
60 |
-
"reference": "
|
61 |
},
|
62 |
"dist": {
|
63 |
"type": "zip",
|
64 |
-
"url": "https://api.github.com/repos/Kub-AT/php-simple-html-dom-parser/zipball/
|
65 |
-
"reference": "
|
66 |
"shasum": ""
|
67 |
},
|
68 |
"require": {
|
69 |
"php": ">=5.3.2"
|
70 |
},
|
71 |
-
"time": "2019-
|
72 |
"type": "library",
|
73 |
"installation-source": "dist",
|
74 |
"autoload": {
|
1 |
[
|
2 |
{
|
3 |
"name": "imangazaliev/didom",
|
4 |
+
"version": "1.16",
|
5 |
+
"version_normalized": "1.16.0.0",
|
6 |
"source": {
|
7 |
"type": "git",
|
8 |
"url": "https://github.com/Imangazaliev/DiDOM.git",
|
9 |
+
"reference": "c2a8bd08679d2eec856782277267a48553322c7e"
|
10 |
},
|
11 |
"dist": {
|
12 |
"type": "zip",
|
13 |
+
"url": "https://api.github.com/repos/Imangazaliev/DiDOM/zipball/c2a8bd08679d2eec856782277267a48553322c7e",
|
14 |
+
"reference": "c2a8bd08679d2eec856782277267a48553322c7e",
|
15 |
"shasum": ""
|
16 |
},
|
17 |
"require": {
|
20 |
"php": ">=5.4"
|
21 |
},
|
22 |
"require-dev": {
|
|
|
23 |
"phpunit/phpunit": "^4.8"
|
24 |
},
|
25 |
+
"time": "2020-05-12T21:04:30+00:00",
|
26 |
"type": "library",
|
27 |
"installation-source": "dist",
|
28 |
"autoload": {
|
51 |
},
|
52 |
{
|
53 |
"name": "kub-at/php-simple-html-dom-parser",
|
54 |
+
"version": "1.9.1",
|
55 |
+
"version_normalized": "1.9.1.0",
|
56 |
"source": {
|
57 |
"type": "git",
|
58 |
"url": "https://github.com/Kub-AT/php-simple-html-dom-parser.git",
|
59 |
+
"reference": "ff22f98bfd9235115c128059076f3eb740d66913"
|
60 |
},
|
61 |
"dist": {
|
62 |
"type": "zip",
|
63 |
+
"url": "https://api.github.com/repos/Kub-AT/php-simple-html-dom-parser/zipball/ff22f98bfd9235115c128059076f3eb740d66913",
|
64 |
+
"reference": "ff22f98bfd9235115c128059076f3eb740d66913",
|
65 |
"shasum": ""
|
66 |
},
|
67 |
"require": {
|
68 |
"php": ">=5.3.2"
|
69 |
},
|
70 |
+
"time": "2019-10-25T12:34:43+00:00",
|
71 |
"type": "library",
|
72 |
"installation-source": "dist",
|
73 |
"autoload": {
|
vendor/imangazaliev/didom/.gitignore
CHANGED
@@ -1,7 +1,6 @@
|
|
1 |
/vendor
|
2 |
/.idea
|
3 |
composer.phar
|
4 |
-
composer.lock
|
5 |
.php_cs.cache
|
6 |
.DS_Store
|
7 |
Thumbs.db
|
1 |
/vendor
|
2 |
/.idea
|
3 |
composer.phar
|
|
|
4 |
.php_cs.cache
|
5 |
.DS_Store
|
6 |
Thumbs.db
|
vendor/imangazaliev/didom/.travis.yml
CHANGED
@@ -1,20 +1,21 @@
|
|
1 |
language: php
|
2 |
|
|
|
|
|
3 |
php:
|
4 |
- 5.4
|
5 |
-
- 5.5.9
|
6 |
- 5.5
|
|
|
7 |
- 5.6
|
8 |
- 7.0
|
|
|
|
|
|
|
9 |
|
10 |
before_script:
|
11 |
- composer self-update
|
12 |
- composer install
|
13 |
|
14 |
script:
|
15 |
-
- phpunit
|
16 |
|
17 |
-
matrix:
|
18 |
-
allow_failures:
|
19 |
-
- php: 5.4
|
20 |
-
- php: 7.0
|
1 |
language: php
|
2 |
|
3 |
+
dist: trusty
|
4 |
+
|
5 |
php:
|
6 |
- 5.4
|
|
|
7 |
- 5.5
|
8 |
+
- 5.5.9
|
9 |
- 5.6
|
10 |
- 7.0
|
11 |
+
- 7.1
|
12 |
+
- 7.2
|
13 |
+
- 7.3
|
14 |
|
15 |
before_script:
|
16 |
- composer self-update
|
17 |
- composer install
|
18 |
|
19 |
script:
|
20 |
+
- ./vendor/bin/phpunit
|
21 |
|
|
|
|
|
|
|
|
vendor/imangazaliev/didom/README-RU.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
# DiDOM
|
2 |
|
3 |
-
[![Build Status](https://
|
4 |
[![Total Downloads](https://poser.pugx.org/imangazaliev/didom/downloads)](https://packagist.org/packages/imangazaliev/didom)
|
5 |
[![Latest Stable Version](https://poser.pugx.org/imangazaliev/didom/v/stable)](https://packagist.org/packages/imangazaliev/didom)
|
6 |
[![License](https://poser.pugx.org/imangazaliev/didom/license)](https://packagist.org/packages/imangazaliev/didom)
|
1 |
# DiDOM
|
2 |
|
3 |
+
[![Build Status](https://travis-ci.org/Imangazaliev/DiDOM.svg?branch=master)](https://travis-ci.org/Imangazaliev/DiDOM)
|
4 |
[![Total Downloads](https://poser.pugx.org/imangazaliev/didom/downloads)](https://packagist.org/packages/imangazaliev/didom)
|
5 |
[![Latest Stable Version](https://poser.pugx.org/imangazaliev/didom/v/stable)](https://packagist.org/packages/imangazaliev/didom)
|
6 |
[![License](https://poser.pugx.org/imangazaliev/didom/license)](https://packagist.org/packages/imangazaliev/didom)
|
vendor/imangazaliev/didom/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
# DiDOM
|
2 |
|
3 |
-
[![Build Status](https://
|
4 |
[![Total Downloads](https://poser.pugx.org/imangazaliev/didom/downloads)](https://packagist.org/packages/imangazaliev/didom)
|
5 |
[![Latest Stable Version](https://poser.pugx.org/imangazaliev/didom/v/stable)](https://packagist.org/packages/imangazaliev/didom)
|
6 |
[![License](https://poser.pugx.org/imangazaliev/didom/license)](https://packagist.org/packages/imangazaliev/didom)
|
1 |
# DiDOM
|
2 |
|
3 |
+
[![Build Status](https://travis-ci.org/Imangazaliev/DiDOM.svg?branch=master)](https://travis-ci.org/Imangazaliev/DiDOM)
|
4 |
[![Total Downloads](https://poser.pugx.org/imangazaliev/didom/downloads)](https://packagist.org/packages/imangazaliev/didom)
|
5 |
[![Latest Stable Version](https://poser.pugx.org/imangazaliev/didom/v/stable)](https://packagist.org/packages/imangazaliev/didom)
|
6 |
[![License](https://poser.pugx.org/imangazaliev/didom/license)](https://packagist.org/packages/imangazaliev/didom)
|
vendor/imangazaliev/didom/composer.json
CHANGED
@@ -17,8 +17,7 @@
|
|
17 |
"ext-iconv": "*"
|
18 |
},
|
19 |
"require-dev": {
|
20 |
-
"phpunit/phpunit": "^4.8"
|
21 |
-
"friendsofphp/php-cs-fixer": "2.9"
|
22 |
},
|
23 |
"autoload": {
|
24 |
"psr-4": {
|
@@ -27,7 +26,12 @@
|
|
27 |
},
|
28 |
"autoload-dev": {
|
29 |
"psr-4": {
|
30 |
-
"Tests\\": "tests/"
|
|
|
|
|
|
|
|
|
|
|
31 |
}
|
32 |
}
|
33 |
}
|
17 |
"ext-iconv": "*"
|
18 |
},
|
19 |
"require-dev": {
|
20 |
+
"phpunit/phpunit": "^4.8"
|
|
|
21 |
},
|
22 |
"autoload": {
|
23 |
"psr-4": {
|
26 |
},
|
27 |
"autoload-dev": {
|
28 |
"psr-4": {
|
29 |
+
"DiDom\\Tests\\": "tests/"
|
30 |
+
}
|
31 |
+
},
|
32 |
+
"config": {
|
33 |
+
"platform": {
|
34 |
+
"php": "5.4"
|
35 |
}
|
36 |
}
|
37 |
}
|
vendor/imangazaliev/didom/composer.lock
ADDED
@@ -0,0 +1,1049 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"_readme": [
|
3 |
+
"This file locks the dependencies of your project to a known state",
|
4 |
+
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
5 |
+
"This file is @generated automatically"
|
6 |
+
],
|
7 |
+
"hash": "7d413af5e53b1204b6c430dbd32ca728",
|
8 |
+
"content-hash": "fa5a5b325a0458a9fe05c67fb6b0e719",
|
9 |
+
"packages": [],
|
10 |
+
"packages-dev": [
|
11 |
+
{
|
12 |
+
"name": "doctrine/instantiator",
|
13 |
+
"version": "1.0.5",
|
14 |
+
"source": {
|
15 |
+
"type": "git",
|
16 |
+
"url": "https://github.com/doctrine/instantiator.git",
|
17 |
+
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
|
18 |
+
},
|
19 |
+
"dist": {
|
20 |
+
"type": "zip",
|
21 |
+
"url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
|
22 |
+
"reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
|
23 |
+
"shasum": ""
|
24 |
+
},
|
25 |
+
"require": {
|
26 |
+
"php": ">=5.3,<8.0-DEV"
|
27 |
+
},
|
28 |
+
"require-dev": {
|
29 |
+
"athletic/athletic": "~0.1.8",
|
30 |
+
"ext-pdo": "*",
|
31 |
+
"ext-phar": "*",
|
32 |
+
"phpunit/phpunit": "~4.0",
|
33 |
+
"squizlabs/php_codesniffer": "~2.0"
|
34 |
+
},
|
35 |
+
"type": "library",
|
36 |
+
"extra": {
|
37 |
+
"branch-alias": {
|
38 |
+
"dev-master": "1.0.x-dev"
|
39 |
+
}
|
40 |
+
},
|
41 |
+
"autoload": {
|
42 |
+
"psr-4": {
|
43 |
+
"Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
|
44 |
+
}
|
45 |
+
},
|
46 |
+
"notification-url": "https://packagist.org/downloads/",
|
47 |
+
"license": [
|
48 |
+
"MIT"
|
49 |
+
],
|
50 |
+
"authors": [
|
51 |
+
{
|
52 |
+
"name": "Marco Pivetta",
|
53 |
+
"email": "ocramius@gmail.com",
|
54 |
+
"homepage": "http://ocramius.github.com/"
|
55 |
+
}
|
56 |
+
],
|
57 |
+
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
|
58 |
+
"homepage": "https://github.com/doctrine/instantiator",
|
59 |
+
"keywords": [
|
60 |
+
"constructor",
|
61 |
+
"instantiate"
|
62 |
+
],
|
63 |
+
"time": "2015-06-14 21:17:01"
|
64 |
+
},
|
65 |
+
{
|
66 |
+
"name": "phpdocumentor/reflection-docblock",
|
67 |
+
"version": "2.0.5",
|
68 |
+
"source": {
|
69 |
+
"type": "git",
|
70 |
+
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
|
71 |
+
"reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b"
|
72 |
+
},
|
73 |
+
"dist": {
|
74 |
+
"type": "zip",
|
75 |
+
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/e6a969a640b00d8daa3c66518b0405fb41ae0c4b",
|
76 |
+
"reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b",
|
77 |
+
"shasum": ""
|
78 |
+
},
|
79 |
+
"require": {
|
80 |
+
"php": ">=5.3.3"
|
81 |
+
},
|
82 |
+
"require-dev": {
|
83 |
+
"phpunit/phpunit": "~4.0"
|
84 |
+
},
|
85 |
+
"suggest": {
|
86 |
+
"dflydev/markdown": "~1.0",
|
87 |
+
"erusev/parsedown": "~1.0"
|
88 |
+
},
|
89 |
+
"type": "library",
|
90 |
+
"extra": {
|
91 |
+
"branch-alias": {
|
92 |
+
"dev-master": "2.0.x-dev"
|
93 |
+
}
|
94 |
+
},
|
95 |
+
"autoload": {
|
96 |
+
"psr-0": {
|
97 |
+
"phpDocumentor": [
|
98 |
+
"src/"
|
99 |
+
]
|
100 |
+
}
|
101 |
+
},
|
102 |
+
"notification-url": "https://packagist.org/downloads/",
|
103 |
+
"license": [
|
104 |
+
"MIT"
|
105 |
+
],
|
106 |
+
"authors": [
|
107 |
+
{
|
108 |
+
"name": "Mike van Riel",
|
109 |
+
"email": "mike.vanriel@naenius.com"
|
110 |
+
}
|
111 |
+
],
|
112 |
+
"time": "2016-01-25 08:17:30"
|
113 |
+
},
|
114 |
+
{
|
115 |
+
"name": "phpspec/prophecy",
|
116 |
+
"version": "1.8.1",
|
117 |
+
"source": {
|
118 |
+
"type": "git",
|
119 |
+
"url": "https://github.com/phpspec/prophecy.git",
|
120 |
+
"reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76"
|
121 |
+
},
|
122 |
+
"dist": {
|
123 |
+
"type": "zip",
|
124 |
+
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76",
|
125 |
+
"reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76",
|
126 |
+
"shasum": ""
|
127 |
+
},
|
128 |
+
"require": {
|
129 |
+
"doctrine/instantiator": "^1.0.2",
|
130 |
+
"php": "^5.3|^7.0",
|
131 |
+
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0",
|
132 |
+
"sebastian/comparator": "^1.1|^2.0|^3.0",
|
133 |
+
"sebastian/recursion-context": "^1.0|^2.0|^3.0"
|
134 |
+
},
|
135 |
+
"require-dev": {
|
136 |
+
"phpspec/phpspec": "^2.5|^3.2",
|
137 |
+
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1"
|
138 |
+
},
|
139 |
+
"type": "library",
|
140 |
+
"extra": {
|
141 |
+
"branch-alias": {
|
142 |
+
"dev-master": "1.8.x-dev"
|
143 |
+
}
|
144 |
+
},
|
145 |
+
"autoload": {
|
146 |
+
"psr-4": {
|
147 |
+
"Prophecy\\": "src/Prophecy"
|
148 |
+
}
|
149 |
+
},
|
150 |
+
"notification-url": "https://packagist.org/downloads/",
|
151 |
+
"license": [
|
152 |
+
"MIT"
|
153 |
+
],
|
154 |
+
"authors": [
|
155 |
+
{
|
156 |
+
"name": "Konstantin Kudryashov",
|
157 |
+
"email": "ever.zet@gmail.com",
|
158 |
+
"homepage": "http://everzet.com"
|
159 |
+
},
|
160 |
+
{
|
161 |
+
"name": "Marcello Duarte",
|
162 |
+
"email": "marcello.duarte@gmail.com"
|
163 |
+
}
|
164 |
+
],
|
165 |
+
"description": "Highly opinionated mocking framework for PHP 5.3+",
|
166 |
+
"homepage": "https://github.com/phpspec/prophecy",
|
167 |
+
"keywords": [
|
168 |
+
"Double",
|
169 |
+
"Dummy",
|
170 |
+
"fake",
|
171 |
+
"mock",
|
172 |
+
"spy",
|
173 |
+
"stub"
|
174 |
+
],
|
175 |
+
"time": "2019-06-13 12:50:23"
|
176 |
+
},
|
177 |
+
{
|
178 |
+
"name": "phpunit/php-code-coverage",
|
179 |
+
"version": "2.2.4",
|
180 |
+
"source": {
|
181 |
+
"type": "git",
|
182 |
+
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
|
183 |
+
"reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
|
184 |
+
},
|
185 |
+
"dist": {
|
186 |
+
"type": "zip",
|
187 |
+
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
|
188 |
+
"reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
|
189 |
+
"shasum": ""
|
190 |
+
},
|
191 |
+
"require": {
|
192 |
+
"php": ">=5.3.3",
|
193 |
+
"phpunit/php-file-iterator": "~1.3",
|
194 |
+
"phpunit/php-text-template": "~1.2",
|
195 |
+
"phpunit/php-token-stream": "~1.3",
|
196 |
+
"sebastian/environment": "^1.3.2",
|
197 |
+
"sebastian/version": "~1.0"
|
198 |
+
},
|
199 |
+
"require-dev": {
|
200 |
+
"ext-xdebug": ">=2.1.4",
|
201 |
+
"phpunit/phpunit": "~4"
|
202 |
+
},
|
203 |
+
"suggest": {
|
204 |
+
"ext-dom": "*",
|
205 |
+
"ext-xdebug": ">=2.2.1",
|
206 |
+
"ext-xmlwriter": "*"
|
207 |
+
},
|
208 |
+
"type": "library",
|
209 |
+
"extra": {
|
210 |
+
"branch-alias": {
|
211 |
+
"dev-master": "2.2.x-dev"
|
212 |
+
}
|
213 |
+
},
|
214 |
+
"autoload": {
|
215 |
+
"classmap": [
|
216 |
+
"src/"
|
217 |
+
]
|
218 |
+
},
|
219 |
+
"notification-url": "https://packagist.org/downloads/",
|
220 |
+
"license": [
|
221 |
+
"BSD-3-Clause"
|
222 |
+
],
|
223 |
+
"authors": [
|
224 |
+
{
|
225 |
+
"name": "Sebastian Bergmann",
|
226 |
+
"email": "sb@sebastian-bergmann.de",
|
227 |
+
"role": "lead"
|
228 |
+
}
|
229 |
+
],
|
230 |
+
"description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
|
231 |
+
"homepage": "https://github.com/sebastianbergmann/php-code-coverage",
|
232 |
+
"keywords": [
|
233 |
+
"coverage",
|
234 |
+
"testing",
|
235 |
+
"xunit"
|
236 |
+
],
|
237 |
+
"time": "2015-10-06 15:47:00"
|
238 |
+
},
|
239 |
+
{
|
240 |
+
"name": "phpunit/php-file-iterator",
|
241 |
+
"version": "1.4.5",
|
242 |
+
"source": {
|
243 |
+
"type": "git",
|
244 |
+
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
|
245 |
+
"reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4"
|
246 |
+
},
|
247 |
+
"dist": {
|
248 |
+
"type": "zip",
|
249 |
+
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4",
|
250 |
+
"reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4",
|
251 |
+
"shasum": ""
|
252 |
+
},
|
253 |
+
"require": {
|
254 |
+
"php": ">=5.3.3"
|
255 |
+
},
|
256 |
+
"type": "library",
|
257 |
+
"extra": {
|
258 |
+
"branch-alias": {
|
259 |
+
"dev-master": "1.4.x-dev"
|
260 |
+
}
|
261 |
+
},
|
262 |
+
"autoload": {
|
263 |
+
"classmap": [
|
264 |
+
"src/"
|
265 |
+
]
|
266 |
+
},
|
267 |
+
"notification-url": "https://packagist.org/downloads/",
|
268 |
+
"license": [
|
269 |
+
"BSD-3-Clause"
|
270 |
+
],
|
271 |
+
"authors": [
|
272 |
+
{
|
273 |
+
"name": "Sebastian Bergmann",
|
274 |
+
"email": "sb@sebastian-bergmann.de",
|
275 |
+
"role": "lead"
|
276 |
+
}
|
277 |
+
],
|
278 |
+
"description": "FilterIterator implementation that filters files based on a list of suffixes.",
|
279 |
+
"homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
|
280 |
+
"keywords": [
|
281 |
+
"filesystem",
|
282 |
+
"iterator"
|
283 |
+
],
|
284 |
+
"time": "2017-11-27 13:52:08"
|
285 |
+
},
|
286 |
+
{
|
287 |
+
"name": "phpunit/php-text-template",
|
288 |
+
"version": "1.2.1",
|
289 |
+
"source": {
|
290 |
+
"type": "git",
|
291 |
+
"url": "https://github.com/sebastianbergmann/php-text-template.git",
|
292 |
+
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
|
293 |
+
},
|
294 |
+
"dist": {
|
295 |
+
"type": "zip",
|
296 |
+
"url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
|
297 |
+
"reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
|
298 |
+
"shasum": ""
|
299 |
+
},
|
300 |
+
"require": {
|
301 |
+
"php": ">=5.3.3"
|
302 |
+
},
|
303 |
+
"type": "library",
|
304 |
+
"autoload": {
|
305 |
+
"classmap": [
|
306 |
+
"src/"
|
307 |
+
]
|
308 |
+
},
|
309 |
+
"notification-url": "https://packagist.org/downloads/",
|
310 |
+
"license": [
|
311 |
+
"BSD-3-Clause"
|
312 |
+
],
|
313 |
+
"authors": [
|
314 |
+
{
|
315 |
+
"name": "Sebastian Bergmann",
|
316 |
+
"email": "sebastian@phpunit.de",
|
317 |
+
"role": "lead"
|
318 |
+
}
|
319 |
+
],
|
320 |
+
"description": "Simple template engine.",
|
321 |
+
"homepage": "https://github.com/sebastianbergmann/php-text-template/",
|
322 |
+
"keywords": [
|
323 |
+
"template"
|
324 |
+
],
|
325 |
+
"time": "2015-06-21 13:50:34"
|
326 |
+
},
|
327 |
+
{
|
328 |
+
"name": "phpunit/php-timer",
|
329 |
+
"version": "1.0.9",
|
330 |
+
"source": {
|
331 |
+
"type": "git",
|
332 |
+
"url": "https://github.com/sebastianbergmann/php-timer.git",
|
333 |
+
"reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f"
|
334 |
+
},
|
335 |
+
"dist": {
|
336 |
+
"type": "zip",
|
337 |
+
"url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
|
338 |
+
"reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
|
339 |
+
"shasum": ""
|
340 |
+
},
|
341 |
+
"require": {
|
342 |
+
"php": "^5.3.3 || ^7.0"
|
343 |
+
},
|
344 |
+
"require-dev": {
|
345 |
+
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
|
346 |
+
},
|
347 |
+
"type": "library",
|
348 |
+
"extra": {
|
349 |
+
"branch-alias": {
|
350 |
+
"dev-master": "1.0-dev"
|
351 |
+
}
|
352 |
+
},
|
353 |
+
"autoload": {
|
354 |
+
"classmap": [
|
355 |
+
"src/"
|
356 |
+
]
|
357 |
+
},
|
358 |
+
"notification-url": "https://packagist.org/downloads/",
|
359 |
+
"license": [
|
360 |
+
"BSD-3-Clause"
|
361 |
+
],
|
362 |
+
"authors": [
|
363 |
+
{
|
364 |
+
"name": "Sebastian Bergmann",
|
365 |
+
"email": "sb@sebastian-bergmann.de",
|
366 |
+
"role": "lead"
|
367 |
+
}
|
368 |
+
],
|
369 |
+
"description": "Utility class for timing",
|
370 |
+
"homepage": "https://github.com/sebastianbergmann/php-timer/",
|
371 |
+
"keywords": [
|
372 |
+
"timer"
|
373 |
+
],
|
374 |
+
"time": "2017-02-26 11:10:40"
|
375 |
+
},
|
376 |
+
{
|
377 |
+
"name": "phpunit/php-token-stream",
|
378 |
+
"version": "1.4.12",
|
379 |
+
"source": {
|
380 |
+
"type": "git",
|
381 |
+
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
|
382 |
+
"reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16"
|
383 |
+
},
|
384 |
+
"dist": {
|
385 |
+
"type": "zip",
|
386 |
+
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16",
|
387 |
+
"reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16",
|
388 |
+
"shasum": ""
|
389 |
+
},
|
390 |
+
"require": {
|
391 |
+
"ext-tokenizer": "*",
|
392 |
+
"php": ">=5.3.3"
|
393 |
+
},
|
394 |
+
"require-dev": {
|
395 |
+
"phpunit/phpunit": "~4.2"
|
396 |
+
},
|
397 |
+
"type": "library",
|
398 |
+
"extra": {
|
399 |
+
"branch-alias": {
|
400 |
+
"dev-master": "1.4-dev"
|
401 |
+
}
|
402 |
+
},
|
403 |
+
"autoload": {
|
404 |
+
"classmap": [
|
405 |
+
"src/"
|
406 |
+
]
|
407 |
+
},
|
408 |
+
"notification-url": "https://packagist.org/downloads/",
|
409 |
+
"license": [
|
410 |
+
"BSD-3-Clause"
|
411 |
+
],
|
412 |
+
"authors": [
|
413 |
+
{
|
414 |
+
"name": "Sebastian Bergmann",
|
415 |
+
"email": "sebastian@phpunit.de"
|
416 |
+
}
|
417 |
+
],
|
418 |
+
"description": "Wrapper around PHP's tokenizer extension.",
|
419 |
+
"homepage": "https://github.com/sebastianbergmann/php-token-stream/",
|
420 |
+
"keywords": [
|
421 |
+
"tokenizer"
|
422 |
+
],
|
423 |
+
"time": "2017-12-04 08:55:13"
|
424 |
+
},
|
425 |
+
{
|
426 |
+
"name": "phpunit/phpunit",
|
427 |
+
"version": "4.8.36",
|
428 |
+
"source": {
|
429 |
+
"type": "git",
|
430 |
+
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
431 |
+
"reference": "46023de9a91eec7dfb06cc56cb4e260017298517"
|
432 |
+
},
|
433 |
+
"dist": {
|
434 |
+
"type": "zip",
|
435 |
+
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517",
|
436 |
+
"reference": "46023de9a91eec7dfb06cc56cb4e260017298517",
|
437 |
+
"shasum": ""
|
438 |
+
},
|
439 |
+
"require": {
|
440 |
+
"ext-dom": "*",
|
441 |
+
"ext-json": "*",
|
442 |
+
"ext-pcre": "*",
|
443 |
+
"ext-reflection": "*",
|
444 |
+
"ext-spl": "*",
|
445 |
+
"php": ">=5.3.3",
|
446 |
+
"phpspec/prophecy": "^1.3.1",
|
447 |
+
"phpunit/php-code-coverage": "~2.1",
|
448 |
+
"phpunit/php-file-iterator": "~1.4",
|
449 |
+
"phpunit/php-text-template": "~1.2",
|
450 |
+
"phpunit/php-timer": "^1.0.6",
|
451 |
+
"phpunit/phpunit-mock-objects": "~2.3",
|
452 |
+
"sebastian/comparator": "~1.2.2",
|
453 |
+
"sebastian/diff": "~1.2",
|
454 |
+
"sebastian/environment": "~1.3",
|
455 |
+
"sebastian/exporter": "~1.2",
|
456 |
+
"sebastian/global-state": "~1.0",
|
457 |
+
"sebastian/version": "~1.0",
|
458 |
+
"symfony/yaml": "~2.1|~3.0"
|
459 |
+
},
|
460 |
+
"suggest": {
|
461 |
+
"phpunit/php-invoker": "~1.1"
|
462 |
+
},
|
463 |
+
"bin": [
|
464 |
+
"phpunit"
|
465 |
+
],
|
466 |
+
"type": "library",
|
467 |
+
"extra": {
|
468 |
+
"branch-alias": {
|
469 |
+
"dev-master": "4.8.x-dev"
|
470 |
+
}
|
471 |
+
},
|
472 |
+
"autoload": {
|
473 |
+
"classmap": [
|
474 |
+
"src/"
|
475 |
+
]
|
476 |
+
},
|
477 |
+
"notification-url": "https://packagist.org/downloads/",
|
478 |
+
"license": [
|
479 |
+
"BSD-3-Clause"
|
480 |
+
],
|
481 |
+
"authors": [
|
482 |
+
{
|
483 |
+
"name": "Sebastian Bergmann",
|
484 |
+
"email": "sebastian@phpunit.de",
|
485 |
+
"role": "lead"
|
486 |
+
}
|
487 |
+
],
|
488 |
+
"description": "The PHP Unit Testing framework.",
|
489 |
+
"homepage": "https://phpunit.de/",
|
490 |
+
"keywords": [
|
491 |
+
"phpunit",
|
492 |
+
"testing",
|
493 |
+
"xunit"
|
494 |
+
],
|
495 |
+
"time": "2017-06-21 08:07:12"
|
496 |
+
},
|
497 |
+
{
|
498 |
+
"name": "phpunit/phpunit-mock-objects",
|
499 |
+
"version": "2.3.8",
|
500 |
+
"source": {
|
501 |
+
"type": "git",
|
502 |
+
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
|
503 |
+
"reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
|
504 |
+
},
|
505 |
+
"dist": {
|
506 |
+
"type": "zip",
|
507 |
+
"url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
|
508 |
+
"reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
|
509 |
+
"shasum": ""
|
510 |
+
},
|
511 |
+
"require": {
|
512 |
+
"doctrine/instantiator": "^1.0.2",
|
513 |
+
"php": ">=5.3.3",
|
514 |
+
"phpunit/php-text-template": "~1.2",
|
515 |
+
"sebastian/exporter": "~1.2"
|
516 |
+
},
|
517 |
+
"require-dev": {
|
518 |
+
"phpunit/phpunit": "~4.4"
|
519 |
+
},
|
520 |
+
"suggest": {
|
521 |
+
"ext-soap": "*"
|
522 |
+
},
|
523 |
+
"type": "library",
|
524 |
+
"extra": {
|
525 |
+
"branch-alias": {
|
526 |
+
"dev-master": "2.3.x-dev"
|
527 |
+
}
|
528 |
+
},
|
529 |
+
"autoload": {
|
530 |
+
"classmap": [
|
531 |
+
"src/"
|
532 |
+
]
|
533 |
+
},
|
534 |
+
"notification-url": "https://packagist.org/downloads/",
|
535 |
+
"license": [
|
536 |
+
"BSD-3-Clause"
|
537 |
+
],
|
538 |
+
"authors": [
|
539 |
+
{
|
540 |
+
"name": "Sebastian Bergmann",
|
541 |
+
"email": "sb@sebastian-bergmann.de",
|
542 |
+
"role": "lead"
|
543 |
+
}
|
544 |
+
],
|
545 |
+
"description": "Mock Object library for PHPUnit",
|
546 |
+
"homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
|
547 |
+
"keywords": [
|
548 |
+
"mock",
|
549 |
+
"xunit"
|
550 |
+
],
|
551 |
+
"abandoned": true,
|
552 |
+
"time": "2015-10-02 06:51:40"
|
553 |
+
},
|
554 |
+
{
|
555 |
+
"name": "sebastian/comparator",
|
556 |
+
"version": "1.2.4",
|
557 |
+
"source": {
|
558 |
+
"type": "git",
|
559 |
+
"url": "https://github.com/sebastianbergmann/comparator.git",
|
560 |
+
"reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be"
|
561 |
+
},
|
562 |
+
"dist": {
|
563 |
+
"type": "zip",
|
564 |
+
"url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
|
565 |
+
"reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
|
566 |
+
"shasum": ""
|
567 |
+
},
|
568 |
+
"require": {
|
569 |
+
"php": ">=5.3.3",
|
570 |
+
"sebastian/diff": "~1.2",
|
571 |
+
"sebastian/exporter": "~1.2 || ~2.0"
|
572 |
+
},
|
573 |
+
"require-dev": {
|
574 |
+
"phpunit/phpunit": "~4.4"
|
575 |
+
},
|
576 |
+
"type": "library",
|
577 |
+
"extra": {
|
578 |
+
"branch-alias": {
|
579 |
+
"dev-master": "1.2.x-dev"
|
580 |
+
}
|
581 |
+
},
|
582 |
+
"autoload": {
|
583 |
+
"classmap": [
|
584 |
+
"src/"
|
585 |
+
]
|
586 |
+
},
|
587 |
+
"notification-url": "https://packagist.org/downloads/",
|
588 |
+
"license": [
|
589 |
+
"BSD-3-Clause"
|
590 |
+
],
|
591 |
+
"authors": [
|
592 |
+
{
|
593 |
+
"name": "Jeff Welch",
|
594 |
+
"email": "whatthejeff@gmail.com"
|
595 |
+
},
|
596 |
+
{
|
597 |
+
"name": "Volker Dusch",
|
598 |
+
"email": "github@wallbash.com"
|
599 |
+
},
|
600 |
+
{
|
601 |
+
"name": "Bernhard Schussek",
|
602 |
+
"email": "bschussek@2bepublished.at"
|
603 |
+
},
|
604 |
+
{
|
605 |
+
"name": "Sebastian Bergmann",
|
606 |
+
"email": "sebastian@phpunit.de"
|
607 |
+
}
|
608 |
+
],
|
609 |
+
"description": "Provides the functionality to compare PHP values for equality",
|
610 |
+
"homepage": "http://www.github.com/sebastianbergmann/comparator",
|
611 |
+
"keywords": [
|
612 |
+
"comparator",
|
613 |
+
"compare",
|
614 |
+
"equality"
|
615 |
+
],
|
616 |
+
"time": "2017-01-29 09:50:25"
|
617 |
+
},
|
618 |
+
{
|
619 |
+
"name": "sebastian/diff",
|
620 |
+
"version": "1.4.3",
|
621 |
+
"source": {
|
622 |
+
"type": "git",
|
623 |
+
"url": "https://github.com/sebastianbergmann/diff.git",
|
624 |
+
"reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4"
|
625 |
+
},
|
626 |
+
"dist": {
|
627 |
+
"type": "zip",
|
628 |
+
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4",
|
629 |
+
"reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4",
|
630 |
+
"shasum": ""
|
631 |
+
},
|
632 |
+
"require": {
|
633 |
+
"php": "^5.3.3 || ^7.0"
|
634 |
+
},
|
635 |
+
"require-dev": {
|
636 |
+
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
|
637 |
+
},
|
638 |
+
"type": "library",
|
639 |
+
"extra": {
|
640 |
+
"branch-alias": {
|
641 |
+
"dev-master": "1.4-dev"
|
642 |
+
}
|
643 |
+
},
|
644 |
+
"autoload": {
|
645 |
+
"classmap": [
|
646 |
+
"src/"
|
647 |
+
]
|
648 |
+
},
|
649 |
+
"notification-url": "https://packagist.org/downloads/",
|
650 |
+
"license": [
|
651 |
+
"BSD-3-Clause"
|
652 |
+
],
|
653 |
+
"authors": [
|
654 |
+
{
|
655 |
+
"name": "Kore Nordmann",
|
656 |
+
"email": "mail@kore-nordmann.de"
|
657 |
+
},
|
658 |
+
{
|
659 |
+
"name": "Sebastian Bergmann",
|
660 |
+
"email": "sebastian@phpunit.de"
|
661 |
+
}
|
662 |
+
],
|
663 |
+
"description": "Diff implementation",
|
664 |
+
"homepage": "https://github.com/sebastianbergmann/diff",
|
665 |
+
"keywords": [
|
666 |
+
"diff"
|
667 |
+
],
|
668 |
+
"time": "2017-05-22 07:24:03"
|
669 |
+
},
|
670 |
+
{
|
671 |
+
"name": "sebastian/environment",
|
672 |
+
"version": "1.3.8",
|
673 |
+
"source": {
|
674 |
+
"type": "git",
|
675 |
+
"url": "https://github.com/sebastianbergmann/environment.git",
|
676 |
+
"reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea"
|
677 |
+
},
|
678 |
+
"dist": {
|
679 |
+
"type": "zip",
|
680 |
+
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea",
|
681 |
+
"reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea",
|
682 |
+
"shasum": ""
|
683 |
+
},
|
684 |
+
"require": {
|
685 |
+
"php": "^5.3.3 || ^7.0"
|
686 |
+
},
|
687 |
+
"require-dev": {
|
688 |
+
"phpunit/phpunit": "^4.8 || ^5.0"
|
689 |
+
},
|
690 |
+
"type": "library",
|
691 |
+
"extra": {
|
692 |
+
"branch-alias": {
|
693 |
+
"dev-master": "1.3.x-dev"
|
694 |
+
}
|
695 |
+
},
|
696 |
+
"autoload": {
|
697 |
+
"classmap": [
|
698 |
+
"src/"
|
699 |
+
]
|
700 |
+
},
|
701 |
+
"notification-url": "https://packagist.org/downloads/",
|
702 |
+
"license": [
|
703 |
+
"BSD-3-Clause"
|
704 |
+
],
|
705 |
+
"authors": [
|
706 |
+
{
|
707 |
+
"name": "Sebastian Bergmann",
|
708 |
+
"email": "sebastian@phpunit.de"
|
709 |
+
}
|
710 |
+
],
|
711 |
+
"description": "Provides functionality to handle HHVM/PHP environments",
|
712 |
+
"homepage": "http://www.github.com/sebastianbergmann/environment",
|
713 |
+
"keywords": [
|
714 |
+
"Xdebug",
|
715 |
+
"environment",
|
716 |
+
"hhvm"
|
717 |
+
],
|
718 |
+
"time": "2016-08-18 05:49:44"
|
719 |
+
},
|
720 |
+
{
|
721 |
+
"name": "sebastian/exporter",
|
722 |
+
"version": "1.2.2",
|
723 |
+
"source": {
|
724 |
+
"type": "git",
|
725 |
+
"url": "https://github.com/sebastianbergmann/exporter.git",
|
726 |
+
"reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
|
727 |
+
},
|
728 |
+
"dist": {
|
729 |
+
"type": "zip",
|
730 |
+
"url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
|
731 |
+
"reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
|
732 |
+
"shasum": ""
|
733 |
+
},
|
734 |
+
"require": {
|
735 |
+
"php": ">=5.3.3",
|
736 |
+
"sebastian/recursion-context": "~1.0"
|
737 |
+
},
|
738 |
+
"require-dev": {
|
739 |
+
"ext-mbstring": "*",
|
740 |
+
"phpunit/phpunit": "~4.4"
|
741 |
+
},
|
742 |
+
"type": "library",
|
743 |
+
"extra": {
|
744 |
+
"branch-alias": {
|
745 |
+
"dev-master": "1.3.x-dev"
|
746 |
+
}
|
747 |
+
},
|
748 |
+
"autoload": {
|
749 |
+
"classmap": [
|
750 |
+
"src/"
|
751 |
+
]
|
752 |
+
},
|
753 |
+
"notification-url": "https://packagist.org/downloads/",
|
754 |
+
"license": [
|
755 |
+
"BSD-3-Clause"
|
756 |
+
],
|
757 |
+
"authors": [
|
758 |
+
{
|
759 |
+
"name": "Jeff Welch",
|
760 |
+
"email": "whatthejeff@gmail.com"
|
761 |
+
},
|
762 |
+
{
|
763 |
+
"name": "Volker Dusch",
|
764 |
+
"email": "github@wallbash.com"
|
765 |
+
},
|
766 |
+
{
|
767 |
+
"name": "Bernhard Schussek",
|
768 |
+
"email": "bschussek@2bepublished.at"
|
769 |
+
},
|
770 |
+
{
|
771 |
+
"name": "Sebastian Bergmann",
|
772 |
+
"email": "sebastian@phpunit.de"
|
773 |
+
},
|
774 |
+
{
|
775 |
+
"name": "Adam Harvey",
|
776 |
+
"email": "aharvey@php.net"
|
777 |
+
}
|
778 |
+
],
|
779 |
+
"description": "Provides the functionality to export PHP variables for visualization",
|
780 |
+
"homepage": "http://www.github.com/sebastianbergmann/exporter",
|
781 |
+
"keywords": [
|
782 |
+
"export",
|
783 |
+
"exporter"
|
784 |
+
],
|
785 |
+
"time": "2016-06-17 09:04:28"
|
786 |
+
},
|
787 |
+
{
|
788 |
+
"name": "sebastian/global-state",
|
789 |
+
"version": "1.1.1",
|
790 |
+
"source": {
|
791 |
+
"type": "git",
|
792 |
+
"url": "https://github.com/sebastianbergmann/global-state.git",
|
793 |
+
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
|
794 |
+
},
|
795 |
+
"dist": {
|
796 |
+
"type": "zip",
|
797 |
+
"url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
|
798 |
+
"reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
|
799 |
+
"shasum": ""
|
800 |
+
},
|
801 |
+
"require": {
|
802 |
+
"php": ">=5.3.3"
|
803 |
+
},
|
804 |
+
"require-dev": {
|
805 |
+
"phpunit/phpunit": "~4.2"
|
806 |
+
},
|
807 |
+
"suggest": {
|
808 |
+
"ext-uopz": "*"
|
809 |
+
},
|
810 |
+
"type": "library",
|
811 |
+
"extra": {
|
812 |
+
"branch-alias": {
|
813 |
+
"dev-master": "1.0-dev"
|
814 |
+
}
|
815 |
+
},
|
816 |
+
"autoload": {
|
817 |
+
"classmap": [
|
818 |
+
"src/"
|
819 |
+
]
|
820 |
+
},
|
821 |
+
"notification-url": "https://packagist.org/downloads/",
|
822 |
+
"license": [
|
823 |
+
"BSD-3-Clause"
|
824 |
+
],
|
825 |
+
"authors": [
|
826 |
+
{
|
827 |
+
"name": "Sebastian Bergmann",
|
828 |
+
"email": "sebastian@phpunit.de"
|
829 |
+
}
|
830 |
+
],
|
831 |
+
"description": "Snapshotting of global state",
|
832 |
+
"homepage": "http://www.github.com/sebastianbergmann/global-state",
|
833 |
+
"keywords": [
|
834 |
+
"global state"
|
835 |
+
],
|
836 |
+
"time": "2015-10-12 03:26:01"
|
837 |
+
},
|
838 |
+
{
|
839 |
+
"name": "sebastian/recursion-context",
|
840 |
+
"version": "1.0.5",
|
841 |
+
"source": {
|
842 |
+
"type": "git",
|
843 |
+
"url": "https://github.com/sebastianbergmann/recursion-context.git",
|
844 |
+
"reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7"
|
845 |
+
},
|
846 |
+
"dist": {
|
847 |
+
"type": "zip",
|
848 |
+
"url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7",
|
849 |
+
"reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7",
|
850 |
+
"shasum": ""
|
851 |
+
},
|
852 |
+
"require": {
|
853 |
+
"php": ">=5.3.3"
|
854 |
+
},
|
855 |
+
"require-dev": {
|
856 |
+
"phpunit/phpunit": "~4.4"
|
857 |
+
},
|
858 |
+
"type": "library",
|
859 |
+
"extra": {
|
860 |
+
"branch-alias": {
|
861 |
+
"dev-master": "1.0.x-dev"
|
862 |
+
}
|
863 |
+
},
|
864 |
+
"autoload": {
|
865 |
+
"classmap": [
|
866 |
+
"src/"
|
867 |
+
]
|
868 |
+
},
|
869 |
+
"notification-url": "https://packagist.org/downloads/",
|
870 |
+
"license": [
|
871 |
+
"BSD-3-Clause"
|
872 |
+
],
|
873 |
+
"authors": [
|
874 |
+
{
|
875 |
+
"name": "Jeff Welch",
|
876 |
+
"email": "whatthejeff@gmail.com"
|
877 |
+
},
|
878 |
+
{
|
879 |
+
"name": "Sebastian Bergmann",
|
880 |
+
"email": "sebastian@phpunit.de"
|
881 |
+
},
|
882 |
+
{
|
883 |
+
"name": "Adam Harvey",
|
884 |
+
"email": "aharvey@php.net"
|
885 |
+
}
|
886 |
+
],
|
887 |
+
"description": "Provides functionality to recursively process PHP variables",
|
888 |
+
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
|
889 |
+
"time": "2016-10-03 07:41:43"
|
890 |
+
},
|
891 |
+
{
|
892 |
+
"name": "sebastian/version",
|
893 |
+
"version": "1.0.6",
|
894 |
+
"source": {
|
895 |
+
"type": "git",
|
896 |
+
"url": "https://github.com/sebastianbergmann/version.git",
|
897 |
+
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
|
898 |
+
},
|
899 |
+
"dist": {
|
900 |
+
"type": "zip",
|
901 |
+
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
|
902 |
+
"reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
|
903 |
+
"shasum": ""
|
904 |
+
},
|
905 |
+
"type": "library",
|
906 |
+
"autoload": {
|
907 |
+
"classmap": [
|
908 |
+
"src/"
|
909 |
+
]
|
910 |
+
},
|
911 |
+
"notification-url": "https://packagist.org/downloads/",
|
912 |
+
"license": [
|
913 |
+
"BSD-3-Clause"
|
914 |
+
],
|
915 |
+
"authors": [
|
916 |
+
{
|
917 |
+
"name": "Sebastian Bergmann",
|
918 |
+
"email": "sebastian@phpunit.de",
|
919 |
+
"role": "lead"
|
920 |
+
}
|
921 |
+
],
|
922 |
+
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
|
923 |
+
"homepage": "https://github.com/sebastianbergmann/version",
|
924 |
+
"time": "2015-06-21 13:59:46"
|
925 |
+
},
|
926 |
+
{
|
927 |
+
"name": "symfony/polyfill-ctype",
|
928 |
+
"version": "v1.12.0",
|
929 |
+
"source": {
|
930 |
+
"type": "git",
|
931 |
+
"url": "https://github.com/symfony/polyfill-ctype.git",
|
932 |
+
"reference": "550ebaac289296ce228a706d0867afc34687e3f4"
|
933 |
+
},
|
934 |
+
"dist": {
|
935 |
+
"type": "zip",
|
936 |
+
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4",
|
937 |
+
"reference": "550ebaac289296ce228a706d0867afc34687e3f4",
|
938 |
+
"shasum": ""
|
939 |
+
},
|
940 |
+
"require": {
|
941 |
+
"php": ">=5.3.3"
|
942 |
+
},
|
943 |
+
"suggest": {
|
944 |
+
"ext-ctype": "For best performance"
|
945 |
+
},
|
946 |
+
"type": "library",
|
947 |
+
"extra": {
|
948 |
+
"branch-alias": {
|
949 |
+
"dev-master": "1.12-dev"
|
950 |
+
}
|
951 |
+
},
|
952 |
+
"autoload": {
|
953 |
+
"psr-4": {
|
954 |
+
"Symfony\\Polyfill\\Ctype\\": ""
|
955 |
+
},
|
956 |
+
"files": [
|
957 |
+
"bootstrap.php"
|
958 |
+
]
|
959 |
+
},
|
960 |
+
"notification-url": "https://packagist.org/downloads/",
|
961 |
+
"license": [
|
962 |
+
"MIT"
|
963 |
+
],
|
964 |
+
"authors": [
|
965 |
+
{
|
966 |
+
"name": "Gert de Pagter",
|
967 |
+
"email": "BackEndTea@gmail.com"
|
968 |
+
},
|
969 |
+
{
|
970 |
+
"name": "Symfony Community",
|
971 |
+
"homepage": "https://symfony.com/contributors"
|
972 |
+
}
|
973 |
+
],
|
974 |
+
"description": "Symfony polyfill for ctype functions",
|
975 |
+
"homepage": "https://symfony.com",
|
976 |
+
"keywords": [
|
977 |
+
"compatibility",
|
978 |
+
"ctype",
|
979 |
+
"polyfill",
|
980 |
+
"portable"
|
981 |
+
],
|
982 |
+
"time": "2019-08-06 08:03:45"
|
983 |
+
},
|
984 |
+
{
|
985 |
+
"name": "symfony/yaml",
|
986 |
+
"version": "v2.8.50",
|
987 |
+
"source": {
|
988 |
+
"type": "git",
|
989 |
+
"url": "https://github.com/symfony/yaml.git",
|
990 |
+
"reference": "02c1859112aa779d9ab394ae4f3381911d84052b"
|
991 |
+
},
|
992 |
+
"dist": {
|
993 |
+
"type": "zip",
|
994 |
+
"url": "https://api.github.com/repos/symfony/yaml/zipball/02c1859112aa779d9ab394ae4f3381911d84052b",
|
995 |
+
"reference": "02c1859112aa779d9ab394ae4f3381911d84052b",
|
996 |
+
"shasum": ""
|
997 |
+
},
|
998 |
+
"require": {
|
999 |
+
"php": ">=5.3.9",
|
1000 |
+
"symfony/polyfill-ctype": "~1.8"
|
1001 |
+
},
|
1002 |
+
"type": "library",
|
1003 |
+
"extra": {
|
1004 |
+
"branch-alias": {
|
1005 |
+
"dev-master": "2.8-dev"
|
1006 |
+
}
|
1007 |
+
},
|
1008 |
+
"autoload": {
|
1009 |
+
"psr-4": {
|
1010 |
+
"Symfony\\Component\\Yaml\\": ""
|
1011 |
+
},
|
1012 |
+
"exclude-from-classmap": [
|
1013 |
+
"/Tests/"
|
1014 |
+
]
|
1015 |
+
},
|
1016 |
+
"notification-url": "https://packagist.org/downloads/",
|
1017 |
+
"license": [
|
1018 |
+
"MIT"
|
1019 |
+
],
|
1020 |
+
"authors": [
|
1021 |
+
{
|
1022 |
+
"name": "Fabien Potencier",
|
1023 |
+
"email": "fabien@symfony.com"
|
1024 |
+
},
|
1025 |
+
{
|
1026 |
+
"name": "Symfony Community",
|
1027 |
+
"homepage": "https://symfony.com/contributors"
|
1028 |
+
}
|
1029 |
+
],
|
1030 |
+
"description": "Symfony Yaml Component",
|
1031 |
+
"homepage": "https://symfony.com",
|
1032 |
+
"time": "2018-11-11 11:18:13"
|
1033 |
+
}
|
1034 |
+
],
|
1035 |
+
"aliases": [],
|
1036 |
+
"minimum-stability": "stable",
|
1037 |
+
"stability-flags": [],
|
1038 |
+
"prefer-stable": false,
|
1039 |
+
"prefer-lowest": false,
|
1040 |
+
"platform": {
|
1041 |
+
"php": ">=5.4",
|
1042 |
+
"ext-dom": "*",
|
1043 |
+
"ext-iconv": "*"
|
1044 |
+
},
|
1045 |
+
"platform-dev": [],
|
1046 |
+
"platform-overrides": {
|
1047 |
+
"php": "5.4"
|
1048 |
+
}
|
1049 |
+
}
|
vendor/imangazaliev/didom/phpunit.xml
CHANGED
@@ -1,17 +1,18 @@
|
|
1 |
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
-
<phpunit
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
|
|
12 |
<testsuites>
|
13 |
<testsuite name="DiDom Test Suite">
|
14 |
<directory>./tests/</directory>
|
15 |
</testsuite>
|
16 |
</testsuites>
|
17 |
-
</phpunit>
|
1 |
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<phpunit
|
3 |
+
backupGlobals="false"
|
4 |
+
backupStaticAttributes="false"
|
5 |
+
bootstrap="tests/bootstrap.php"
|
6 |
+
colors="true"
|
7 |
+
convertErrorsToExceptions="true"
|
8 |
+
convertNoticesToExceptions="true"
|
9 |
+
convertWarningsToExceptions="true"
|
10 |
+
processIsolation="false"
|
11 |
+
stopOnFailure="false"
|
12 |
+
>
|
13 |
<testsuites>
|
14 |
<testsuite name="DiDom Test Suite">
|
15 |
<directory>./tests/</directory>
|
16 |
</testsuite>
|
17 |
</testsuites>
|
18 |
+
</phpunit>
|
vendor/imangazaliev/didom/src/DiDom/ClassAttribute.php
CHANGED
@@ -9,7 +9,7 @@ class ClassAttribute
|
|
9 |
/**
|
10 |
* The DOM element instance.
|
11 |
*
|
12 |
-
* @var
|
13 |
*/
|
14 |
protected $element;
|
15 |
|
@@ -24,15 +24,13 @@ class ClassAttribute
|
|
24 |
protected $classes = [];
|
25 |
|
26 |
/**
|
27 |
-
*
|
28 |
*
|
29 |
-
* @
|
30 |
-
*
|
31 |
-
* @throws \InvalidArgumentException if passed argument is not an element node
|
32 |
*/
|
33 |
public function __construct(Element $element)
|
34 |
{
|
35 |
-
if (
|
36 |
throw new InvalidArgumentException(sprintf('The element must contain DOMElement node'));
|
37 |
}
|
38 |
|
@@ -46,7 +44,7 @@ class ClassAttribute
|
|
46 |
*/
|
47 |
protected function parseClassAttribute()
|
48 |
{
|
49 |
-
if (
|
50 |
// possible if class attribute has been removed
|
51 |
if ($this->classesString !== '') {
|
52 |
$this->classesString = '';
|
@@ -94,13 +92,13 @@ class ClassAttribute
|
|
94 |
/**
|
95 |
* @param string $className
|
96 |
*
|
97 |
-
* @return
|
98 |
*
|
99 |
-
* @throws
|
100 |
*/
|
101 |
public function add($className)
|
102 |
{
|
103 |
-
if (!is_string($className)) {
|
104 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($className) ? get_class($className) : gettype($className))));
|
105 |
}
|
106 |
|
@@ -120,16 +118,16 @@ class ClassAttribute
|
|
120 |
/**
|
121 |
* @param array $classNames
|
122 |
*
|
123 |
-
* @return
|
124 |
*
|
125 |
-
* @throws
|
126 |
*/
|
127 |
public function addMultiple(array $classNames)
|
128 |
{
|
129 |
$this->parseClassAttribute();
|
130 |
|
131 |
foreach ($classNames as $className) {
|
132 |
-
if (!is_string($className)) {
|
133 |
throw new InvalidArgumentException(sprintf('Class name must be a string, %s given', (is_object($className) ? get_class($className) : gettype($className))));
|
134 |
}
|
135 |
|
@@ -162,7 +160,7 @@ class ClassAttribute
|
|
162 |
*/
|
163 |
public function contains($className)
|
164 |
{
|
165 |
-
if (!is_string($className)) {
|
166 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($className) ? get_class($className) : gettype($className))));
|
167 |
}
|
168 |
|
@@ -174,13 +172,13 @@ class ClassAttribute
|
|
174 |
/**
|
175 |
* @param string $className
|
176 |
*
|
177 |
-
* @return
|
178 |
*
|
179 |
-
* @throws
|
180 |
*/
|
181 |
public function remove($className)
|
182 |
{
|
183 |
-
if (!is_string($className)) {
|
184 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($className) ? get_class($className) : gettype($className))));
|
185 |
}
|
186 |
|
@@ -202,16 +200,16 @@ class ClassAttribute
|
|
202 |
/**
|
203 |
* @param array $classNames
|
204 |
*
|
205 |
-
* @return
|
206 |
*
|
207 |
-
* @throws
|
208 |
*/
|
209 |
public function removeMultiple(array $classNames)
|
210 |
{
|
211 |
$this->parseClassAttribute();
|
212 |
|
213 |
foreach ($classNames as $className) {
|
214 |
-
if (!is_string($className)) {
|
215 |
throw new InvalidArgumentException(sprintf('Class name must be a string, %s given', (is_object($className) ? get_class($className) : gettype($className))));
|
216 |
}
|
217 |
|
@@ -232,7 +230,7 @@ class ClassAttribute
|
|
232 |
/**
|
233 |
* @param string[] $exclusions
|
234 |
*
|
235 |
-
* @return
|
236 |
*/
|
237 |
public function removeAll(array $exclusions = [])
|
238 |
{
|
@@ -241,11 +239,11 @@ class ClassAttribute
|
|
241 |
$preservedClasses = [];
|
242 |
|
243 |
foreach ($exclusions as $className) {
|
244 |
-
if (!is_string($className)) {
|
245 |
throw new InvalidArgumentException(sprintf('Class name must be a string, %s given', (is_object($className) ? get_class($className) : gettype($className))));
|
246 |
}
|
247 |
|
248 |
-
if (!in_array($className, $this->classes, true)) {
|
249 |
continue;
|
250 |
}
|
251 |
|
@@ -260,7 +258,7 @@ class ClassAttribute
|
|
260 |
}
|
261 |
|
262 |
/**
|
263 |
-
* @return
|
264 |
*/
|
265 |
public function getElement()
|
266 |
{
|
9 |
/**
|
10 |
* The DOM element instance.
|
11 |
*
|
12 |
+
* @var Element
|
13 |
*/
|
14 |
protected $element;
|
15 |
|
24 |
protected $classes = [];
|
25 |
|
26 |
/**
|
27 |
+
* @param Element $element
|
28 |
*
|
29 |
+
* @throws InvalidArgumentException if parameter 1 is not an element node
|
|
|
|
|
30 |
*/
|
31 |
public function __construct(Element $element)
|
32 |
{
|
33 |
+
if ( ! $element->isElementNode()) {
|
34 |
throw new InvalidArgumentException(sprintf('The element must contain DOMElement node'));
|
35 |
}
|
36 |
|
44 |
*/
|
45 |
protected function parseClassAttribute()
|
46 |
{
|
47 |
+
if ( ! $this->element->hasAttribute('class')) {
|
48 |
// possible if class attribute has been removed
|
49 |
if ($this->classesString !== '') {
|
50 |
$this->classesString = '';
|
92 |
/**
|
93 |
* @param string $className
|
94 |
*
|
95 |
+
* @return ClassAttribute
|
96 |
*
|
97 |
+
* @throws InvalidArgumentException if class name is not a string
|
98 |
*/
|
99 |
public function add($className)
|
100 |
{
|
101 |
+
if ( ! is_string($className)) {
|
102 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($className) ? get_class($className) : gettype($className))));
|
103 |
}
|
104 |
|
118 |
/**
|
119 |
* @param array $classNames
|
120 |
*
|
121 |
+
* @return ClassAttribute
|
122 |
*
|
123 |
+
* @throws InvalidArgumentException if class name is not a string
|
124 |
*/
|
125 |
public function addMultiple(array $classNames)
|
126 |
{
|
127 |
$this->parseClassAttribute();
|
128 |
|
129 |
foreach ($classNames as $className) {
|
130 |
+
if ( ! is_string($className)) {
|
131 |
throw new InvalidArgumentException(sprintf('Class name must be a string, %s given', (is_object($className) ? get_class($className) : gettype($className))));
|
132 |
}
|
133 |
|
160 |
*/
|
161 |
public function contains($className)
|
162 |
{
|
163 |
+
if ( ! is_string($className)) {
|
164 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($className) ? get_class($className) : gettype($className))));
|
165 |
}
|
166 |
|
172 |
/**
|
173 |
* @param string $className
|
174 |
*
|
175 |
+
* @return ClassAttribute
|
176 |
*
|
177 |
+
* @throws InvalidArgumentException if class name is not a string
|
178 |
*/
|
179 |
public function remove($className)
|
180 |
{
|
181 |
+
if ( ! is_string($className)) {
|
182 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($className) ? get_class($className) : gettype($className))));
|
183 |
}
|
184 |
|
200 |
/**
|
201 |
* @param array $classNames
|
202 |
*
|
203 |
+
* @return ClassAttribute
|
204 |
*
|
205 |
+
* @throws InvalidArgumentException if class name is not a string
|
206 |
*/
|
207 |
public function removeMultiple(array $classNames)
|
208 |
{
|
209 |
$this->parseClassAttribute();
|
210 |
|
211 |
foreach ($classNames as $className) {
|
212 |
+
if ( ! is_string($className)) {
|
213 |
throw new InvalidArgumentException(sprintf('Class name must be a string, %s given', (is_object($className) ? get_class($className) : gettype($className))));
|
214 |
}
|
215 |
|
230 |
/**
|
231 |
* @param string[] $exclusions
|
232 |
*
|
233 |
+
* @return ClassAttribute
|
234 |
*/
|
235 |
public function removeAll(array $exclusions = [])
|
236 |
{
|
239 |
$preservedClasses = [];
|
240 |
|
241 |
foreach ($exclusions as $className) {
|
242 |
+
if ( ! is_string($className)) {
|
243 |
throw new InvalidArgumentException(sprintf('Class name must be a string, %s given', (is_object($className) ? get_class($className) : gettype($className))));
|
244 |
}
|
245 |
|
246 |
+
if ( ! in_array($className, $this->classes, true)) {
|
247 |
continue;
|
248 |
}
|
249 |
|
258 |
}
|
259 |
|
260 |
/**
|
261 |
+
* @return Element
|
262 |
*/
|
263 |
public function getElement()
|
264 |
{
|
vendor/imangazaliev/didom/src/DiDom/Document.php
CHANGED
@@ -2,6 +2,8 @@
|
|
2 |
|
3 |
namespace DiDom;
|
4 |
|
|
|
|
|
5 |
use DOMCdataSection;
|
6 |
use DOMComment;
|
7 |
use DOMDocument;
|
@@ -9,6 +11,7 @@ use DOMElement;
|
|
9 |
use DOMNode;
|
10 |
use DOMText;
|
11 |
use DOMXPath;
|
|
|
12 |
use InvalidArgumentException;
|
13 |
use RuntimeException;
|
14 |
|
@@ -20,10 +23,10 @@ class Document
|
|
20 |
* @const string
|
21 |
*/
|
22 |
const TYPE_HTML = 'html';
|
23 |
-
const TYPE_XML
|
24 |
|
25 |
/**
|
26 |
-
* @var
|
27 |
*/
|
28 |
protected $document;
|
29 |
|
@@ -38,14 +41,12 @@ class Document
|
|
38 |
protected $encoding;
|
39 |
|
40 |
/**
|
41 |
-
*
|
|
|
|
|
|
|
42 |
*
|
43 |
-
* @
|
44 |
-
* @param bool $isFile Indicates that the first parameter is a path to a file
|
45 |
-
* @param string $encoding The document encoding
|
46 |
-
* @param string $type The document type
|
47 |
-
*
|
48 |
-
* @throws \InvalidArgumentException if the passed encoding is not a string
|
49 |
*/
|
50 |
public function __construct($string = null, $isFile = false, $encoding = 'UTF-8', $type = Document::TYPE_HTML)
|
51 |
{
|
@@ -55,7 +56,7 @@ class Document
|
|
55 |
return;
|
56 |
}
|
57 |
|
58 |
-
if (!is_string($encoding)) {
|
59 |
throw new InvalidArgumentException(sprintf('%s expects parameter 3 to be string, %s given', __METHOD__, gettype($encoding)));
|
60 |
}
|
61 |
|
@@ -73,12 +74,12 @@ class Document
|
|
73 |
/**
|
74 |
* Creates a new document.
|
75 |
*
|
76 |
-
* @param string|null $string
|
77 |
-
* @param bool
|
78 |
-
* @param string
|
79 |
-
* @param string
|
80 |
*
|
81 |
-
* @return
|
82 |
*/
|
83 |
public static function create($string = null, $isFile = false, $encoding = 'UTF-8', $type = Document::TYPE_HTML)
|
84 |
{
|
@@ -88,11 +89,11 @@ class Document
|
|
88 |
/**
|
89 |
* Creates a new element node.
|
90 |
*
|
91 |
-
* @param string
|
92 |
-
* @param string|null $value
|
93 |
-
* @param array
|
94 |
*
|
95 |
-
* @return
|
96 |
*/
|
97 |
public function createElement($name, $value = null, array $attributes = [])
|
98 |
{
|
@@ -104,11 +105,13 @@ class Document
|
|
104 |
/**
|
105 |
* Creates a new element node by CSS selector.
|
106 |
*
|
107 |
-
* @param string
|
108 |
* @param string|null $value
|
109 |
-
* @param array
|
|
|
|
|
110 |
*
|
111 |
-
* @
|
112 |
*/
|
113 |
public function createElementBySelector($selector, $value = null, array $attributes = [])
|
114 |
{
|
@@ -161,20 +164,28 @@ class Document
|
|
161 |
return new Element(new DOMCdataSection($data));
|
162 |
}
|
163 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
/**
|
165 |
* Adds a new child at the end of the children.
|
166 |
*
|
167 |
-
* @param
|
168 |
*
|
169 |
-
* @return
|
170 |
*
|
171 |
-
* @throws
|
172 |
*/
|
173 |
public function appendChild($nodes)
|
174 |
{
|
175 |
$returnArray = true;
|
176 |
|
177 |
-
if (!is_array($nodes)) {
|
178 |
$nodes = [$nodes];
|
179 |
|
180 |
$returnArray = false;
|
@@ -187,7 +198,7 @@ class Document
|
|
187 |
$node = $node->getNode();
|
188 |
}
|
189 |
|
190 |
-
if (
|
191 |
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of %s\Element or DOMNode, %s given', __METHOD__, __NAMESPACE__, (is_object($node) ? get_class($node) : gettype($node))));
|
192 |
}
|
193 |
|
@@ -213,11 +224,11 @@ class Document
|
|
213 |
*
|
214 |
* @param bool $value
|
215 |
*
|
216 |
-
* @return
|
217 |
*/
|
218 |
public function preserveWhiteSpace($value = true)
|
219 |
{
|
220 |
-
if (!is_bool($value)) {
|
221 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be boolean, %s given', __METHOD__, gettype($value)));
|
222 |
}
|
223 |
|
@@ -229,28 +240,29 @@ class Document
|
|
229 |
/**
|
230 |
* Load HTML or XML.
|
231 |
*
|
232 |
-
* @param string
|
233 |
-
* @param bool
|
234 |
-
* @param string
|
235 |
-
* @param int|null $options
|
236 |
*
|
237 |
-
* @return
|
238 |
*
|
239 |
-
* @throws
|
240 |
-
* @throws
|
241 |
-
* @throws
|
|
|
242 |
*/
|
243 |
public function load($string, $isFile = false, $type = Document::TYPE_HTML, $options = null)
|
244 |
{
|
245 |
-
if (!is_string($string)) {
|
246 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($string) ? get_class($string) : gettype($string))));
|
247 |
}
|
248 |
|
249 |
-
if (!is_string($type)) {
|
250 |
throw new InvalidArgumentException(sprintf('%s expects parameter 3 to be string, %s given', __METHOD__, (is_object($type) ? get_class($type) : gettype($type))));
|
251 |
}
|
252 |
|
253 |
-
if (!in_array(strtolower($type), [Document::TYPE_HTML, Document::TYPE_XML], true)) {
|
254 |
throw new RuntimeException(sprintf('Document type must be "xml" or "html", %s given', $type));
|
255 |
}
|
256 |
|
@@ -259,7 +271,7 @@ class Document
|
|
259 |
$options = LIBXML_HTML_NODEFDTD;
|
260 |
}
|
261 |
|
262 |
-
if (!is_int($options)) {
|
263 |
throw new InvalidArgumentException(sprintf('%s expects parameter 4 to be integer, %s given', __METHOD__, (is_object($options) ? get_class($options) : gettype($options))));
|
264 |
}
|
265 |
|
@@ -291,12 +303,12 @@ class Document
|
|
291 |
/**
|
292 |
* Load HTML from a string.
|
293 |
*
|
294 |
-
* @param string
|
295 |
* @param int|null $options Additional parameters
|
296 |
*
|
297 |
-
* @return
|
298 |
*
|
299 |
-
* @throws
|
300 |
*/
|
301 |
public function loadHtml($html, $options = null)
|
302 |
{
|
@@ -306,14 +318,14 @@ class Document
|
|
306 |
/**
|
307 |
* Load HTML from a file.
|
308 |
*
|
309 |
-
* @param string
|
310 |
-
* @param int|null $options
|
311 |
*
|
312 |
-
* @return
|
313 |
*
|
314 |
-
* @throws
|
315 |
-
* @throws
|
316 |
-
* @throws
|
317 |
*/
|
318 |
public function loadHtmlFile($filename, $options = null)
|
319 |
{
|
@@ -323,12 +335,12 @@ class Document
|
|
323 |
/**
|
324 |
* Load XML from a string.
|
325 |
*
|
326 |
-
* @param string
|
327 |
* @param int|null $options Additional parameters
|
328 |
*
|
329 |
-
* @return
|
330 |
*
|
331 |
-
* @throws
|
332 |
*/
|
333 |
public function loadXml($xml, $options = null)
|
334 |
{
|
@@ -338,14 +350,14 @@ class Document
|
|
338 |
/**
|
339 |
* Load XML from a file.
|
340 |
*
|
341 |
-
* @param string
|
342 |
-
* @param int|null $options
|
343 |
*
|
344 |
-
* @return
|
345 |
*
|
346 |
-
* @throws
|
347 |
-
* @throws
|
348 |
-
* @throws
|
349 |
*/
|
350 |
public function loadXmlFile($filename, $options = null)
|
351 |
{
|
@@ -359,18 +371,18 @@ class Document
|
|
359 |
*
|
360 |
* @return string
|
361 |
*
|
362 |
-
* @throws
|
363 |
-
* @throws
|
364 |
*/
|
365 |
protected function loadFile($filename)
|
366 |
{
|
367 |
-
if (!is_string($filename)) {
|
368 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, gettype($filename)));
|
369 |
}
|
370 |
|
371 |
try {
|
372 |
$content = file_get_contents($filename);
|
373 |
-
} catch (
|
374 |
throw new RuntimeException(sprintf('Could not load file %s', $filename));
|
375 |
}
|
376 |
|
@@ -400,14 +412,15 @@ class Document
|
|
400 |
/**
|
401 |
* Searches for an node in the DOM tree for a given XPath expression or a CSS selector.
|
402 |
*
|
403 |
-
* @param string
|
404 |
-
* @param string
|
405 |
-
* @param bool
|
406 |
-
* @param
|
407 |
*
|
408 |
-
* @return
|
409 |
*
|
410 |
-
* @throws
|
|
|
411 |
*/
|
412 |
public function find($expression, $type = Query::TYPE_CSS, $wrapNode = true, $contextNode = null)
|
413 |
{
|
@@ -418,7 +431,7 @@ class Document
|
|
418 |
$contextNode = $contextNode->getNode();
|
419 |
}
|
420 |
|
421 |
-
if (
|
422 |
throw new InvalidArgumentException(sprintf('Argument 4 passed to %s must be an instance of %s\Element or DOMElement, %s given', __METHOD__, __NAMESPACE__, (is_object($contextNode) ? get_class($contextNode) : gettype($contextNode))));
|
423 |
}
|
424 |
|
@@ -447,12 +460,14 @@ class Document
|
|
447 |
/**
|
448 |
* Searches for an node in the DOM tree and returns first element or null.
|
449 |
*
|
450 |
-
* @param string
|
451 |
-
* @param string
|
452 |
-
* @param bool
|
453 |
-
* @param
|
|
|
|
|
454 |
*
|
455 |
-
* @
|
456 |
*/
|
457 |
public function first($expression, $type = Query::TYPE_CSS, $wrapNode = true, $contextNode = null)
|
458 |
{
|
@@ -474,27 +489,23 @@ class Document
|
|
474 |
}
|
475 |
|
476 |
/**
|
477 |
-
* @param
|
478 |
*
|
479 |
-
* @return
|
480 |
*
|
481 |
-
* @throws InvalidArgumentException if
|
482 |
*/
|
483 |
protected function wrapNode($node)
|
484 |
{
|
485 |
switch (get_class($node)) {
|
486 |
case 'DOMElement':
|
|
|
|
|
487 |
return new Element($node);
|
488 |
|
489 |
case 'DOMText':
|
490 |
return $node->data;
|
491 |
|
492 |
-
case 'DOMComment':
|
493 |
-
return new Element($node);
|
494 |
-
|
495 |
-
case 'DOMCdataSection':
|
496 |
-
return new Element($node);
|
497 |
-
|
498 |
case 'DOMAttr':
|
499 |
return $node->value;
|
500 |
}
|
@@ -505,11 +516,11 @@ class Document
|
|
505 |
/**
|
506 |
* Searches for a node in the DOM tree for a given XPath expression.
|
507 |
*
|
508 |
-
* @param string
|
509 |
-
* @param bool
|
510 |
-
* @param
|
511 |
*
|
512 |
-
* @return
|
513 |
*/
|
514 |
public function xpath($expression, $wrapNode = true, $contextNode = null)
|
515 |
{
|
@@ -523,6 +534,8 @@ class Document
|
|
523 |
* @param string $type The type of the expression
|
524 |
*
|
525 |
* @return int
|
|
|
|
|
526 |
*/
|
527 |
public function count($expression, $type = Query::TYPE_CSS)
|
528 |
{
|
@@ -572,11 +585,11 @@ class Document
|
|
572 |
*
|
573 |
* @param bool $format Formats output if true
|
574 |
*
|
575 |
-
* @return
|
576 |
*/
|
577 |
public function format($format = true)
|
578 |
{
|
579 |
-
if (!is_bool($format)) {
|
580 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be boolean, %s given', __METHOD__, gettype($format)));
|
581 |
}
|
582 |
|
@@ -598,18 +611,18 @@ class Document
|
|
598 |
/**
|
599 |
* Indicates if two documents are the same document.
|
600 |
*
|
601 |
-
* @param
|
602 |
*
|
603 |
* @return bool
|
604 |
*
|
605 |
-
* @throws
|
606 |
*/
|
607 |
public function is($document)
|
608 |
{
|
609 |
if ($document instanceof Document) {
|
610 |
$element = $document->getElement();
|
611 |
} else {
|
612 |
-
if (
|
613 |
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of %s or DOMDocument, %s given', __METHOD__, __CLASS__, (is_object($document) ? get_class($document) : gettype($document))));
|
614 |
}
|
615 |
|
@@ -644,7 +657,7 @@ class Document
|
|
644 |
}
|
645 |
|
646 |
/**
|
647 |
-
* @return
|
648 |
*/
|
649 |
public function getDocument()
|
650 |
{
|
@@ -652,7 +665,7 @@ class Document
|
|
652 |
}
|
653 |
|
654 |
/**
|
655 |
-
* @return
|
656 |
*/
|
657 |
public function getElement()
|
658 |
{
|
@@ -660,7 +673,7 @@ class Document
|
|
660 |
}
|
661 |
|
662 |
/**
|
663 |
-
* @return
|
664 |
*/
|
665 |
public function toElement()
|
666 |
{
|
@@ -684,12 +697,14 @@ class Document
|
|
684 |
/**
|
685 |
* Searches for an node in the DOM tree for a given XPath expression or a CSS selector.
|
686 |
*
|
687 |
-
* @param string
|
688 |
-
* @param string
|
689 |
-
* @param bool
|
690 |
-
* @param
|
|
|
|
|
691 |
*
|
692 |
-
* @
|
693 |
*
|
694 |
* @deprecated Not longer recommended, use Document::find() instead.
|
695 |
*/
|
2 |
|
3 |
namespace DiDom;
|
4 |
|
5 |
+
use DiDom\Exceptions\InvalidSelectorException;
|
6 |
+
use DOMAttr;
|
7 |
use DOMCdataSection;
|
8 |
use DOMComment;
|
9 |
use DOMDocument;
|
11 |
use DOMNode;
|
12 |
use DOMText;
|
13 |
use DOMXPath;
|
14 |
+
use Exception;
|
15 |
use InvalidArgumentException;
|
16 |
use RuntimeException;
|
17 |
|
23 |
* @const string
|
24 |
*/
|
25 |
const TYPE_HTML = 'html';
|
26 |
+
const TYPE_XML = 'xml';
|
27 |
|
28 |
/**
|
29 |
+
* @var DOMDocument
|
30 |
*/
|
31 |
protected $document;
|
32 |
|
41 |
protected $encoding;
|
42 |
|
43 |
/**
|
44 |
+
* @param string|null $string An HTML or XML string or a file path
|
45 |
+
* @param bool $isFile Indicates that the first parameter is a path to a file
|
46 |
+
* @param string $encoding The document encoding
|
47 |
+
* @param string $type The document type
|
48 |
*
|
49 |
+
* @throws InvalidArgumentException if parameter 3 is not a string
|
|
|
|
|
|
|
|
|
|
|
50 |
*/
|
51 |
public function __construct($string = null, $isFile = false, $encoding = 'UTF-8', $type = Document::TYPE_HTML)
|
52 |
{
|
56 |
return;
|
57 |
}
|
58 |
|
59 |
+
if ( ! is_string($encoding)) {
|
60 |
throw new InvalidArgumentException(sprintf('%s expects parameter 3 to be string, %s given', __METHOD__, gettype($encoding)));
|
61 |
}
|
62 |
|
74 |
/**
|
75 |
* Creates a new document.
|
76 |
*
|
77 |
+
* @param string|null $string An HTML or XML string or a file path
|
78 |
+
* @param bool $isFile Indicates that the first parameter is a path to a file
|
79 |
+
* @param string $encoding The document encoding
|
80 |
+
* @param string $type The document type
|
81 |
*
|
82 |
+
* @return Document
|
83 |
*/
|
84 |
public static function create($string = null, $isFile = false, $encoding = 'UTF-8', $type = Document::TYPE_HTML)
|
85 |
{
|
89 |
/**
|
90 |
* Creates a new element node.
|
91 |
*
|
92 |
+
* @param string $name The tag name of the element
|
93 |
+
* @param string|null $value The value of the element
|
94 |
+
* @param array $attributes The attributes of the element
|
95 |
*
|
96 |
+
* @return Element created element
|
97 |
*/
|
98 |
public function createElement($name, $value = null, array $attributes = [])
|
99 |
{
|
105 |
/**
|
106 |
* Creates a new element node by CSS selector.
|
107 |
*
|
108 |
+
* @param string $selector
|
109 |
* @param string|null $value
|
110 |
+
* @param array $attributes
|
111 |
+
*
|
112 |
+
* @return Element
|
113 |
*
|
114 |
+
* @throws InvalidSelectorException
|
115 |
*/
|
116 |
public function createElementBySelector($selector, $value = null, array $attributes = [])
|
117 |
{
|
164 |
return new Element(new DOMCdataSection($data));
|
165 |
}
|
166 |
|
167 |
+
/**
|
168 |
+
* @return DocumentFragment
|
169 |
+
*/
|
170 |
+
public function createDocumentFragment()
|
171 |
+
{
|
172 |
+
return new DocumentFragment($this->document->createDocumentFragment());
|
173 |
+
}
|
174 |
+
|
175 |
/**
|
176 |
* Adds a new child at the end of the children.
|
177 |
*
|
178 |
+
* @param Element|DOMNode|array $nodes The appended child
|
179 |
*
|
180 |
+
* @return Element|Element[]
|
181 |
*
|
182 |
+
* @throws InvalidArgumentException if one of elements of parameter 1 is not an instance of DOMNode or Element
|
183 |
*/
|
184 |
public function appendChild($nodes)
|
185 |
{
|
186 |
$returnArray = true;
|
187 |
|
188 |
+
if ( ! is_array($nodes)) {
|
189 |
$nodes = [$nodes];
|
190 |
|
191 |
$returnArray = false;
|
198 |
$node = $node->getNode();
|
199 |
}
|
200 |
|
201 |
+
if ( ! $node instanceof DOMNode) {
|
202 |
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of %s\Element or DOMNode, %s given', __METHOD__, __NAMESPACE__, (is_object($node) ? get_class($node) : gettype($node))));
|
203 |
}
|
204 |
|
224 |
*
|
225 |
* @param bool $value
|
226 |
*
|
227 |
+
* @return Document
|
228 |
*/
|
229 |
public function preserveWhiteSpace($value = true)
|
230 |
{
|
231 |
+
if ( ! is_bool($value)) {
|
232 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be boolean, %s given', __METHOD__, gettype($value)));
|
233 |
}
|
234 |
|
240 |
/**
|
241 |
* Load HTML or XML.
|
242 |
*
|
243 |
+
* @param string $string An HTML or XML string or a file path
|
244 |
+
* @param bool $isFile Indicates that the first parameter is a file path
|
245 |
+
* @param string $type The type of a document
|
246 |
+
* @param int|null $options libxml option constants
|
247 |
*
|
248 |
+
* @return Document
|
249 |
*
|
250 |
+
* @throws InvalidArgumentException if parameter 1 is not a string
|
251 |
+
* @throws InvalidArgumentException if parameter 3 is not a string
|
252 |
+
* @throws InvalidArgumentException if parameter 4 is not an integer or null
|
253 |
+
* @throws RuntimeException if the document type is invalid (not Document::TYPE_HTML or Document::TYPE_XML)
|
254 |
*/
|
255 |
public function load($string, $isFile = false, $type = Document::TYPE_HTML, $options = null)
|
256 |
{
|
257 |
+
if ( ! is_string($string)) {
|
258 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($string) ? get_class($string) : gettype($string))));
|
259 |
}
|
260 |
|
261 |
+
if ( ! is_string($type)) {
|
262 |
throw new InvalidArgumentException(sprintf('%s expects parameter 3 to be string, %s given', __METHOD__, (is_object($type) ? get_class($type) : gettype($type))));
|
263 |
}
|
264 |
|
265 |
+
if ( ! in_array(strtolower($type), [Document::TYPE_HTML, Document::TYPE_XML], true)) {
|
266 |
throw new RuntimeException(sprintf('Document type must be "xml" or "html", %s given', $type));
|
267 |
}
|
268 |
|
271 |
$options = LIBXML_HTML_NODEFDTD;
|
272 |
}
|
273 |
|
274 |
+
if ( ! is_int($options)) {
|
275 |
throw new InvalidArgumentException(sprintf('%s expects parameter 4 to be integer, %s given', __METHOD__, (is_object($options) ? get_class($options) : gettype($options))));
|
276 |
}
|
277 |
|
303 |
/**
|
304 |
* Load HTML from a string.
|
305 |
*
|
306 |
+
* @param string $html The HTML string
|
307 |
* @param int|null $options Additional parameters
|
308 |
*
|
309 |
+
* @return Document
|
310 |
*
|
311 |
+
* @throws InvalidArgumentException if parameter 1 is not a string
|
312 |
*/
|
313 |
public function loadHtml($html, $options = null)
|
314 |
{
|
318 |
/**
|
319 |
* Load HTML from a file.
|
320 |
*
|
321 |
+
* @param string $filename The path to the HTML file
|
322 |
+
* @param int|null $options Additional parameters
|
323 |
*
|
324 |
+
* @return Document
|
325 |
*
|
326 |
+
* @throws InvalidArgumentException if parameter 1 not a string
|
327 |
+
* @throws RuntimeException if the file doesn't exist
|
328 |
+
* @throws RuntimeException if you are unable to load the file
|
329 |
*/
|
330 |
public function loadHtmlFile($filename, $options = null)
|
331 |
{
|
335 |
/**
|
336 |
* Load XML from a string.
|
337 |
*
|
338 |
+
* @param string $xml The XML string
|
339 |
* @param int|null $options Additional parameters
|
340 |
*
|
341 |
+
* @return Document
|
342 |
*
|
343 |
+
* @throws InvalidArgumentException if parameter 1 is not a string
|
344 |
*/
|
345 |
public function loadXml($xml, $options = null)
|
346 |
{
|
350 |
/**
|
351 |
* Load XML from a file.
|
352 |
*
|
353 |
+
* @param string $filename The path to the XML file
|
354 |
+
* @param int|null $options Additional parameters
|
355 |
*
|
356 |
+
* @return Document
|
357 |
*
|
358 |
+
* @throws InvalidArgumentException if the file path is not a string
|
359 |
+
* @throws RuntimeException if the file doesn't exist
|
360 |
+
* @throws RuntimeException if you are unable to load the file
|
361 |
*/
|
362 |
public function loadXmlFile($filename, $options = null)
|
363 |
{
|
371 |
*
|
372 |
* @return string
|
373 |
*
|
374 |
+
* @throws InvalidArgumentException if parameter 1 is not a string
|
375 |
+
* @throws RuntimeException if an error occurred
|
376 |
*/
|
377 |
protected function loadFile($filename)
|
378 |
{
|
379 |
+
if ( ! is_string($filename)) {
|
380 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, gettype($filename)));
|
381 |
}
|
382 |
|
383 |
try {
|
384 |
$content = file_get_contents($filename);
|
385 |
+
} catch (Exception $exception) {
|
386 |
throw new RuntimeException(sprintf('Could not load file %s', $filename));
|
387 |
}
|
388 |
|
412 |
/**
|
413 |
* Searches for an node in the DOM tree for a given XPath expression or a CSS selector.
|
414 |
*
|
415 |
+
* @param string $expression XPath expression or a CSS selector
|
416 |
+
* @param string $type The type of the expression
|
417 |
+
* @param bool $wrapNode Returns array of Element if true, otherwise array of DOMElement
|
418 |
+
* @param DOMElement|null $contextNode The node in which the search will be performed
|
419 |
*
|
420 |
+
* @return Element[]|DOMElement[]
|
421 |
*
|
422 |
+
* @throws InvalidSelectorException if the selector is invalid
|
423 |
+
* @throws InvalidArgumentException if context node is not DOMElement
|
424 |
*/
|
425 |
public function find($expression, $type = Query::TYPE_CSS, $wrapNode = true, $contextNode = null)
|
426 |
{
|
431 |
$contextNode = $contextNode->getNode();
|
432 |
}
|
433 |
|
434 |
+
if ( ! $contextNode instanceof DOMElement) {
|
435 |
throw new InvalidArgumentException(sprintf('Argument 4 passed to %s must be an instance of %s\Element or DOMElement, %s given', __METHOD__, __NAMESPACE__, (is_object($contextNode) ? get_class($contextNode) : gettype($contextNode))));
|
436 |
}
|
437 |
|
460 |
/**
|
461 |
* Searches for an node in the DOM tree and returns first element or null.
|
462 |
*
|
463 |
+
* @param string $expression XPath expression or a CSS selector
|
464 |
+
* @param string $type The type of the expression
|
465 |
+
* @param bool $wrapNode Returns array of Element if true, otherwise array of DOMElement
|
466 |
+
* @param DOMElement|null $contextNode The node in which the search will be performed
|
467 |
+
*
|
468 |
+
* @return Element|DOMElement|null
|
469 |
*
|
470 |
+
* @throws InvalidSelectorException if the selector is invalid
|
471 |
*/
|
472 |
public function first($expression, $type = Query::TYPE_CSS, $wrapNode = true, $contextNode = null)
|
473 |
{
|
489 |
}
|
490 |
|
491 |
/**
|
492 |
+
* @param DOMElement|DOMText|DOMAttr $node
|
493 |
*
|
494 |
+
* @return Element|string
|
495 |
*
|
496 |
+
* @throws InvalidArgumentException if parameter 1 is not an instance of DOMElement, DOMText, DOMComment, DOMCdataSection or DOMAttr
|
497 |
*/
|
498 |
protected function wrapNode($node)
|
499 |
{
|
500 |
switch (get_class($node)) {
|
501 |
case 'DOMElement':
|
502 |
+
case 'DOMComment':
|
503 |
+
case 'DOMCdataSection':
|
504 |
return new Element($node);
|
505 |
|
506 |
case 'DOMText':
|
507 |
return $node->data;
|
508 |
|
|
|
|
|
|
|
|
|
|
|
|
|
509 |
case 'DOMAttr':
|
510 |
return $node->value;
|
511 |
}
|
516 |
/**
|
517 |
* Searches for a node in the DOM tree for a given XPath expression.
|
518 |
*
|
519 |
+
* @param string $expression XPath expression
|
520 |
+
* @param bool $wrapNode Returns array of Element if true, otherwise array of DOMElement
|
521 |
+
* @param DOMElement $contextNode The node in which the search will be performed
|
522 |
*
|
523 |
+
* @return Element[]|DOMElement[]
|
524 |
*/
|
525 |
public function xpath($expression, $wrapNode = true, $contextNode = null)
|
526 |
{
|
534 |
* @param string $type The type of the expression
|
535 |
*
|
536 |
* @return int
|
537 |
+
*
|
538 |
+
* @throws InvalidSelectorException
|
539 |
*/
|
540 |
public function count($expression, $type = Query::TYPE_CSS)
|
541 |
{
|
585 |
*
|
586 |
* @param bool $format Formats output if true
|
587 |
*
|
588 |
+
* @return Document
|
589 |
*/
|
590 |
public function format($format = true)
|
591 |
{
|
592 |
+
if ( ! is_bool($format)) {
|
593 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be boolean, %s given', __METHOD__, gettype($format)));
|
594 |
}
|
595 |
|
611 |
/**
|
612 |
* Indicates if two documents are the same document.
|
613 |
*
|
614 |
+
* @param Document|DOMDocument $document The compared document
|
615 |
*
|
616 |
* @return bool
|
617 |
*
|
618 |
+
* @throws InvalidArgumentException if parameter 1 is not an instance of DOMDocument or Document
|
619 |
*/
|
620 |
public function is($document)
|
621 |
{
|
622 |
if ($document instanceof Document) {
|
623 |
$element = $document->getElement();
|
624 |
} else {
|
625 |
+
if ( ! $document instanceof DOMDocument) {
|
626 |
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of %s or DOMDocument, %s given', __METHOD__, __CLASS__, (is_object($document) ? get_class($document) : gettype($document))));
|
627 |
}
|
628 |
|
657 |
}
|
658 |
|
659 |
/**
|
660 |
+
* @return DOMDocument
|
661 |
*/
|
662 |
public function getDocument()
|
663 |
{
|
665 |
}
|
666 |
|
667 |
/**
|
668 |
+
* @return DOMElement
|
669 |
*/
|
670 |
public function getElement()
|
671 |
{
|
673 |
}
|
674 |
|
675 |
/**
|
676 |
+
* @return Element
|
677 |
*/
|
678 |
public function toElement()
|
679 |
{
|
697 |
/**
|
698 |
* Searches for an node in the DOM tree for a given XPath expression or a CSS selector.
|
699 |
*
|
700 |
+
* @param string $expression XPath expression or a CSS selector
|
701 |
+
* @param string $type The type of the expression
|
702 |
+
* @param bool $wrapNode Returns array of Element if true, otherwise array of DOMElement
|
703 |
+
* @param DOMElement|null $contextNode The node in which the search will be performed
|
704 |
+
*
|
705 |
+
* @return Element[]|DOMElement[]
|
706 |
*
|
707 |
+
* @throws InvalidSelectorException
|
708 |
*
|
709 |
* @deprecated Not longer recommended, use Document::find() instead.
|
710 |
*/
|
vendor/imangazaliev/didom/src/DiDom/DocumentFragment.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DiDom;
|
4 |
+
|
5 |
+
use DOMDocumentFragment;
|
6 |
+
use InvalidArgumentException;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* @property string $tag
|
10 |
+
*/
|
11 |
+
class DocumentFragment extends Node
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* @param DOMDocumentFragment $documentFragment
|
15 |
+
*/
|
16 |
+
public function __construct($documentFragment)
|
17 |
+
{
|
18 |
+
if ( ! $documentFragment instanceof DOMDocumentFragment) {
|
19 |
+
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of DOMDocumentFragment, %s given', __METHOD__, (is_object($documentFragment) ? get_class($documentFragment) : gettype($documentFragment))));
|
20 |
+
}
|
21 |
+
|
22 |
+
$this->setNode($documentFragment);
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Append raw XML data.
|
27 |
+
*
|
28 |
+
* @param string $data
|
29 |
+
*/
|
30 |
+
public function appendXml($data)
|
31 |
+
{
|
32 |
+
$this->node->appendXML($data);
|
33 |
+
}
|
34 |
+
}
|
vendor/imangazaliev/didom/src/DiDom/Element.php
CHANGED
@@ -2,6 +2,7 @@
|
|
2 |
|
3 |
namespace DiDom;
|
4 |
|
|
|
5 |
use DOMCdataSection;
|
6 |
use DOMComment;
|
7 |
use DOMDocument;
|
@@ -15,31 +16,22 @@ use RuntimeException;
|
|
15 |
/**
|
16 |
* @property string $tag
|
17 |
*/
|
18 |
-
class Element
|
19 |
{
|
20 |
/**
|
21 |
-
*
|
22 |
-
*
|
23 |
-
* @var \DOMElement|\DOMText|\DOMComment|\DOMCdataSection
|
24 |
-
*/
|
25 |
-
protected $node;
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @var \DiDom\ClassAttribute
|
29 |
*/
|
30 |
protected $classAttribute;
|
31 |
|
32 |
/**
|
33 |
-
* @var
|
34 |
*/
|
35 |
protected $styleAttribute;
|
36 |
|
37 |
/**
|
38 |
-
*
|
39 |
-
*
|
40 |
-
* @param
|
41 |
-
* @param string|null $value The value of the element
|
42 |
-
* @param array $attributes The attributes of the element
|
43 |
*/
|
44 |
public function __construct($tagName, $value = null, array $attributes = [])
|
45 |
{
|
@@ -65,11 +57,11 @@ class Element
|
|
65 |
/**
|
66 |
* Creates a new element.
|
67 |
*
|
68 |
-
* @param
|
69 |
-
* @param string|null $value The value of
|
70 |
-
* @param array
|
71 |
*
|
72 |
-
* @return
|
73 |
*/
|
74 |
public static function create($name, $value = null, array $attributes = [])
|
75 |
{
|
@@ -83,290 +75,15 @@ class Element
|
|
83 |
* @param string|null $value
|
84 |
* @param array $attributes
|
85 |
*
|
86 |
-
* @return
|
|
|
|
|
87 |
*/
|
88 |
public static function createBySelector($selector, $value = null, array $attributes = [])
|
89 |
{
|
90 |
return Document::create()->createElementBySelector($selector, $value, $attributes);
|
91 |
}
|
92 |
|
93 |
-
/**
|
94 |
-
* Adds a new child at the start of the children.
|
95 |
-
*
|
96 |
-
* @param \DiDom\Element|\DOMNode|array $nodes The prepended child
|
97 |
-
*
|
98 |
-
* @return \DiDom\Element|\DiDom\Element[]
|
99 |
-
*
|
100 |
-
* @throws \LogicException if current node has no owner document
|
101 |
-
* @throws \InvalidArgumentException if the provided argument is not an instance of \DOMNode or \DiDom\Element
|
102 |
-
*/
|
103 |
-
public function prependChild($nodes)
|
104 |
-
{
|
105 |
-
if ($this->node->ownerDocument === null) {
|
106 |
-
throw new LogicException('Can not prepend child to element without owner document');
|
107 |
-
}
|
108 |
-
|
109 |
-
$returnArray = true;
|
110 |
-
|
111 |
-
if (!is_array($nodes)) {
|
112 |
-
$nodes = [$nodes];
|
113 |
-
|
114 |
-
$returnArray = false;
|
115 |
-
}
|
116 |
-
|
117 |
-
$nodes = array_reverse($nodes);
|
118 |
-
|
119 |
-
$result = [];
|
120 |
-
|
121 |
-
$referenceNode = $this->node->firstChild;
|
122 |
-
|
123 |
-
foreach ($nodes as $node) {
|
124 |
-
$result[] = $this->insertBefore($node, $referenceNode);
|
125 |
-
|
126 |
-
$referenceNode = $this->node->firstChild;
|
127 |
-
}
|
128 |
-
|
129 |
-
return $returnArray ? $result : $result[0];
|
130 |
-
}
|
131 |
-
|
132 |
-
/**
|
133 |
-
* Adds a new child at the end of the children.
|
134 |
-
*
|
135 |
-
* @param \DiDom\Element|\DOMNode|array $nodes The appended child
|
136 |
-
*
|
137 |
-
* @return \DiDom\Element|\DiDom\Element[]
|
138 |
-
*
|
139 |
-
* @throws \LogicException if current node has no owner document
|
140 |
-
* @throws \InvalidArgumentException if the provided argument is not an instance of \DOMNode or \DiDom\Element
|
141 |
-
*/
|
142 |
-
public function appendChild($nodes)
|
143 |
-
{
|
144 |
-
if ($this->node->ownerDocument === null) {
|
145 |
-
throw new LogicException('Can not append child to element without owner document');
|
146 |
-
}
|
147 |
-
|
148 |
-
$returnArray = true;
|
149 |
-
|
150 |
-
if (!is_array($nodes)) {
|
151 |
-
$nodes = [$nodes];
|
152 |
-
|
153 |
-
$returnArray = false;
|
154 |
-
}
|
155 |
-
|
156 |
-
$result = [];
|
157 |
-
|
158 |
-
Errors::disable();
|
159 |
-
|
160 |
-
foreach ($nodes as $node) {
|
161 |
-
if ($node instanceof Element) {
|
162 |
-
$node = $node->getNode();
|
163 |
-
}
|
164 |
-
|
165 |
-
if (!$node instanceof DOMNode) {
|
166 |
-
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of %s\Element or DOMNode, %s given', __METHOD__, __NAMESPACE__, (is_object($node) ? get_class($node) : gettype($node))));
|
167 |
-
}
|
168 |
-
|
169 |
-
$clonedNode = $node->cloneNode(true);
|
170 |
-
$newNode = $this->node->ownerDocument->importNode($clonedNode, true);
|
171 |
-
|
172 |
-
$result[] = $this->node->appendChild($newNode);
|
173 |
-
}
|
174 |
-
|
175 |
-
Errors::restore();
|
176 |
-
|
177 |
-
$result = array_map(function (DOMNode $node) {
|
178 |
-
return new Element($node);
|
179 |
-
}, $result);
|
180 |
-
|
181 |
-
return $returnArray ? $result : $result[0];
|
182 |
-
}
|
183 |
-
|
184 |
-
/**
|
185 |
-
* Adds a new child before a reference node.
|
186 |
-
*
|
187 |
-
* @param \DiDom\Element|\DOMNode $node The new node
|
188 |
-
* @param \DiDom\Element|\DOMNode|null $referenceNode The reference node
|
189 |
-
*
|
190 |
-
* @return \DiDom\Element
|
191 |
-
*
|
192 |
-
* @throws \LogicException if current node has no owner document
|
193 |
-
* @throws \InvalidArgumentException if $node is not an instance of \DOMNode or \DiDom\Element
|
194 |
-
* @throws \InvalidArgumentException if $referenceNode is not an instance of \DOMNode or \DiDom\Element
|
195 |
-
*/
|
196 |
-
public function insertBefore($node, $referenceNode = null)
|
197 |
-
{
|
198 |
-
if ($this->node->ownerDocument === null) {
|
199 |
-
throw new LogicException('Can not insert child to element without owner document');
|
200 |
-
}
|
201 |
-
|
202 |
-
if ($node instanceof Element) {
|
203 |
-
$node = $node->getNode();
|
204 |
-
}
|
205 |
-
|
206 |
-
if (!$node instanceof DOMNode) {
|
207 |
-
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of %s\Element or DOMNode, %s given', __METHOD__, __NAMESPACE__, (is_object($node) ? get_class($node) : gettype($node))));
|
208 |
-
}
|
209 |
-
|
210 |
-
if ($referenceNode !== null) {
|
211 |
-
if ($referenceNode instanceof Element) {
|
212 |
-
$referenceNode = $referenceNode->getNode();
|
213 |
-
}
|
214 |
-
|
215 |
-
if (!$referenceNode instanceof DOMNode) {
|
216 |
-
throw new InvalidArgumentException(sprintf('Argument 2 passed to %s must be an instance of %s\Element or DOMNode, %s given', __METHOD__, __NAMESPACE__, (is_object($referenceNode) ? get_class($referenceNode) : gettype($referenceNode))));
|
217 |
-
}
|
218 |
-
}
|
219 |
-
|
220 |
-
Errors::disable();
|
221 |
-
|
222 |
-
$clonedNode = $node->cloneNode(true);
|
223 |
-
$newNode = $this->node->ownerDocument->importNode($clonedNode, true);
|
224 |
-
|
225 |
-
$insertedNode = $this->node->insertBefore($newNode, $referenceNode);
|
226 |
-
|
227 |
-
Errors::restore();
|
228 |
-
|
229 |
-
return new Element($insertedNode);
|
230 |
-
}
|
231 |
-
|
232 |
-
/**
|
233 |
-
* Adds a new child after a reference node.
|
234 |
-
*
|
235 |
-
* @param \DiDom\Element|\DOMNode $node The new node
|
236 |
-
* @param \DiDom\Element|\DOMNode|null $referenceNode The reference node
|
237 |
-
*
|
238 |
-
* @return \DiDom\Element
|
239 |
-
*
|
240 |
-
* @throws \LogicException if current node has no owner document
|
241 |
-
* @throws \InvalidArgumentException if $node is not an instance of \DOMNode or \DiDom\Element
|
242 |
-
* @throws \InvalidArgumentException if $referenceNode is not an instance of \DOMNode or \DiDom\Element
|
243 |
-
*/
|
244 |
-
public function insertAfter($node, $referenceNode = null)
|
245 |
-
{
|
246 |
-
if ($referenceNode === null) {
|
247 |
-
return $this->insertBefore($node);
|
248 |
-
}
|
249 |
-
|
250 |
-
if ($referenceNode instanceof Element) {
|
251 |
-
$referenceNode = $referenceNode->getNode();
|
252 |
-
}
|
253 |
-
|
254 |
-
if (!$referenceNode instanceof DOMNode) {
|
255 |
-
throw new InvalidArgumentException(sprintf('Argument 2 passed to %s must be an instance of %s\Element or DOMNode, %s given', __METHOD__, __NAMESPACE__, (is_object($referenceNode) ? get_class($referenceNode) : gettype($referenceNode))));
|
256 |
-
}
|
257 |
-
|
258 |
-
return $this->insertBefore($node, $referenceNode->nextSibling);
|
259 |
-
}
|
260 |
-
|
261 |
-
/**
|
262 |
-
* Checks the existence of the node.
|
263 |
-
*
|
264 |
-
* @param string $expression XPath expression or CSS selector
|
265 |
-
* @param string $type The type of the expression
|
266 |
-
*
|
267 |
-
* @return bool
|
268 |
-
*/
|
269 |
-
public function has($expression, $type = Query::TYPE_CSS)
|
270 |
-
{
|
271 |
-
return $this->toDocument()->has($expression, $type);
|
272 |
-
}
|
273 |
-
|
274 |
-
/**
|
275 |
-
* Searches for an node in the DOM tree for a given XPath expression or a CSS selector.
|
276 |
-
*
|
277 |
-
* @param string $expression XPath expression or a CSS selector
|
278 |
-
* @param string $type The type of the expression
|
279 |
-
* @param bool $wrapElement Returns array of \DiDom\Element if true, otherwise array of \DOMElement
|
280 |
-
*
|
281 |
-
* @return \DiDom\Element[]|\DOMElement[]
|
282 |
-
*/
|
283 |
-
public function find($expression, $type = Query::TYPE_CSS, $wrapElement = true)
|
284 |
-
{
|
285 |
-
return $this->toDocument()->find($expression, $type, $wrapElement);
|
286 |
-
}
|
287 |
-
|
288 |
-
/**
|
289 |
-
* Searches for an node in the owner document using current node as context.
|
290 |
-
*
|
291 |
-
* @param string $expression XPath expression or a CSS selector
|
292 |
-
* @param string $type The type of the expression
|
293 |
-
* @param bool $wrapNode Returns array of \DiDom\Element if true, otherwise array of \DOMElement
|
294 |
-
*
|
295 |
-
* @return \DiDom\Element[]|\DOMElement[]
|
296 |
-
*
|
297 |
-
* @throws \LogicException if current node has no owner document
|
298 |
-
*/
|
299 |
-
public function findInDocument($expression, $type = Query::TYPE_CSS, $wrapNode = true)
|
300 |
-
{
|
301 |
-
$ownerDocument = $this->getDocument();
|
302 |
-
|
303 |
-
if ($ownerDocument === null) {
|
304 |
-
throw new LogicException('Can not search in context without owner document');
|
305 |
-
}
|
306 |
-
|
307 |
-
return $ownerDocument->find($expression, $type, $wrapNode, $this->node);
|
308 |
-
}
|
309 |
-
|
310 |
-
/**
|
311 |
-
* Searches for an node in the DOM tree and returns first element or null.
|
312 |
-
*
|
313 |
-
* @param string $expression XPath expression or a CSS selector
|
314 |
-
* @param string $type The type of the expression
|
315 |
-
* @param bool $wrapNode Returns \DiDom\Element if true, otherwise \DOMElement
|
316 |
-
*
|
317 |
-
* @return \DiDom\Element|\DOMElement|null
|
318 |
-
*/
|
319 |
-
public function first($expression, $type = Query::TYPE_CSS, $wrapNode = true)
|
320 |
-
{
|
321 |
-
return $this->toDocument()->first($expression, $type, $wrapNode);
|
322 |
-
}
|
323 |
-
|
324 |
-
/**
|
325 |
-
* Searches for an node in the owner document using current node as context and returns first element or null.
|
326 |
-
*
|
327 |
-
* @param string $expression XPath expression or a CSS selector
|
328 |
-
* @param string $type The type of the expression
|
329 |
-
* @param bool $wrapNode Returns \DiDom\Element if true, otherwise \DOMElement
|
330 |
-
*
|
331 |
-
* @return \DiDom\Element|\DOMElement|null
|
332 |
-
*/
|
333 |
-
public function firstInDocument($expression, $type = Query::TYPE_CSS, $wrapNode = true)
|
334 |
-
{
|
335 |
-
$ownerDocument = $this->getDocument();
|
336 |
-
|
337 |
-
if ($ownerDocument === null) {
|
338 |
-
throw new LogicException('Can not search in context without owner document');
|
339 |
-
}
|
340 |
-
|
341 |
-
return $ownerDocument->first($expression, $type, $wrapNode, $this->node);
|
342 |
-
}
|
343 |
-
|
344 |
-
/**
|
345 |
-
* Searches for an node in the DOM tree for a given XPath expression.
|
346 |
-
*
|
347 |
-
* @param string $expression XPath expression
|
348 |
-
* @param bool $wrapNode Returns array of \DiDom\Element if true, otherwise array of \DOMElement
|
349 |
-
*
|
350 |
-
* @return \DiDom\Element[]|\DOMElement[]
|
351 |
-
*/
|
352 |
-
public function xpath($expression, $wrapNode = true)
|
353 |
-
{
|
354 |
-
return $this->find($expression, Query::TYPE_XPATH, $wrapNode);
|
355 |
-
}
|
356 |
-
|
357 |
-
/**
|
358 |
-
* Counts nodes for a given XPath expression or a CSS selector.
|
359 |
-
*
|
360 |
-
* @param string $expression XPath expression or CSS selector
|
361 |
-
* @param string $type The type of the expression
|
362 |
-
*
|
363 |
-
* @return int
|
364 |
-
*/
|
365 |
-
public function count($expression, $type = Query::TYPE_CSS)
|
366 |
-
{
|
367 |
-
return $this->toDocument()->count($expression, $type);
|
368 |
-
}
|
369 |
-
|
370 |
/**
|
371 |
* Checks that the node matches selector.
|
372 |
*
|
@@ -375,16 +92,17 @@ class Element
|
|
375 |
*
|
376 |
* @return bool
|
377 |
*
|
378 |
-
* @throws
|
379 |
-
* @throws
|
|
|
380 |
*/
|
381 |
public function matches($selector, $strict = false)
|
382 |
{
|
383 |
-
if (!is_string($selector)) {
|
384 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, gettype($selector)));
|
385 |
}
|
386 |
|
387 |
-
if (
|
388 |
return false;
|
389 |
}
|
390 |
|
@@ -392,7 +110,7 @@ class Element
|
|
392 |
return true;
|
393 |
}
|
394 |
|
395 |
-
if (
|
396 |
$innerHtml = $this->html();
|
397 |
$html = "<root>$innerHtml</root>";
|
398 |
|
@@ -407,7 +125,7 @@ class Element
|
|
407 |
|
408 |
$segments = Query::getSegments($selector);
|
409 |
|
410 |
-
if (!array_key_exists('tag', $segments)) {
|
411 |
throw new RuntimeException(sprintf('Tag name must be specified in %s', $selector));
|
412 |
}
|
413 |
|
@@ -452,7 +170,7 @@ class Element
|
|
452 |
/**
|
453 |
* Determine if an attribute exists on the element.
|
454 |
*
|
455 |
-
* @param string $name The attribute
|
456 |
*
|
457 |
* @return bool
|
458 |
*/
|
@@ -464,10 +182,10 @@ class Element
|
|
464 |
/**
|
465 |
* Set an attribute on the element.
|
466 |
*
|
467 |
-
* @param string $name The attribute
|
468 |
-
* @param string $value The attribute
|
469 |
*
|
470 |
-
* @return
|
471 |
*/
|
472 |
public function setAttribute($name, $value)
|
473 |
{
|
@@ -475,7 +193,7 @@ class Element
|
|
475 |
$value = (string) $value;
|
476 |
}
|
477 |
|
478 |
-
if (!is_string($value) && $value !== null) {
|
479 |
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string or null, %s given', __METHOD__, (is_object($value) ? get_class($value) : gettype($value))));
|
480 |
}
|
481 |
|
@@ -487,10 +205,10 @@ class Element
|
|
487 |
/**
|
488 |
* Access to the element's attributes.
|
489 |
*
|
490 |
-
* @param string $name The attribute
|
491 |
-
* @param string|null $default The value returned if the attribute
|
492 |
*
|
493 |
-
* @return string|null The value of
|
494 |
*/
|
495 |
public function getAttribute($name, $default = null)
|
496 |
{
|
@@ -504,9 +222,9 @@ class Element
|
|
504 |
/**
|
505 |
* Unset an attribute on the element.
|
506 |
*
|
507 |
-
* @param string $name The attribute
|
508 |
*
|
509 |
-
* @return
|
510 |
*/
|
511 |
public function removeAttribute($name)
|
512 |
{
|
@@ -520,11 +238,11 @@ class Element
|
|
520 |
*
|
521 |
* @param string[] $exclusions
|
522 |
*
|
523 |
-
* @return
|
524 |
*/
|
525 |
public function removeAllAttributes(array $exclusions = [])
|
526 |
{
|
527 |
-
if (
|
528 |
return $this;
|
529 |
}
|
530 |
|
@@ -542,10 +260,10 @@ class Element
|
|
542 |
/**
|
543 |
* Alias for getAttribute and setAttribute methods.
|
544 |
*
|
545 |
-
* @param string $name The attribute
|
546 |
-
* @param string|null $value The
|
547 |
*
|
548 |
-
* @return string|null
|
549 |
*/
|
550 |
public function attr($name, $value = null)
|
551 |
{
|
@@ -565,7 +283,7 @@ class Element
|
|
565 |
*/
|
566 |
public function attributes(array $names = null)
|
567 |
{
|
568 |
-
if (
|
569 |
return null;
|
570 |
}
|
571 |
|
@@ -591,9 +309,9 @@ class Element
|
|
591 |
}
|
592 |
|
593 |
/**
|
594 |
-
* @return
|
595 |
*
|
596 |
-
* @throws
|
597 |
*/
|
598 |
public function classes()
|
599 |
{
|
@@ -601,7 +319,7 @@ class Element
|
|
601 |
return $this->classAttribute;
|
602 |
}
|
603 |
|
604 |
-
if (
|
605 |
throw new LogicException('Class attribute is available only for element nodes');
|
606 |
}
|
607 |
|
@@ -611,9 +329,9 @@ class Element
|
|
611 |
}
|
612 |
|
613 |
/**
|
614 |
-
* @return
|
615 |
*
|
616 |
-
* @throws
|
617 |
*/
|
618 |
public function style()
|
619 |
{
|
@@ -621,7 +339,7 @@ class Element
|
|
621 |
return $this->styleAttribute;
|
622 |
}
|
623 |
|
624 |
-
if (
|
625 |
throw new LogicException('Style attribute is available only for element nodes');
|
626 |
}
|
627 |
|
@@ -631,847 +349,53 @@ class Element
|
|
631 |
}
|
632 |
|
633 |
/**
|
634 |
-
*
|
635 |
-
*
|
636 |
-
* @return string
|
637 |
-
*/
|
638 |
-
public function html()
|
639 |
-
{
|
640 |
-
return $this->toDocument()->html();
|
641 |
-
}
|
642 |
-
|
643 |
-
/**
|
644 |
-
* Dumps the node into a string using HTML formatting (without child nodes).
|
645 |
-
*
|
646 |
-
* @return string
|
647 |
-
*/
|
648 |
-
public function outerHtml()
|
649 |
-
{
|
650 |
-
$document = new DOMDocument();
|
651 |
-
|
652 |
-
$importedNode = $document->importNode($this->node);
|
653 |
-
|
654 |
-
return $document->saveHTML($importedNode);
|
655 |
-
}
|
656 |
-
|
657 |
-
/**
|
658 |
-
* Dumps the node descendants into a string using HTML formatting.
|
659 |
-
*
|
660 |
-
* @param string $delimiter
|
661 |
-
*
|
662 |
-
* @return string
|
663 |
-
*/
|
664 |
-
public function innerHtml($delimiter = '')
|
665 |
-
{
|
666 |
-
$innerHtml = [];
|
667 |
-
|
668 |
-
foreach ($this->node->childNodes as $childNode) {
|
669 |
-
$innerHtml[] = $childNode->ownerDocument->saveHTML($childNode);
|
670 |
-
}
|
671 |
-
|
672 |
-
return implode($delimiter, $innerHtml);
|
673 |
-
}
|
674 |
-
|
675 |
-
/**
|
676 |
-
* Dumps the node descendants into a string using XML formatting.
|
677 |
-
*
|
678 |
-
* @param string $delimiter
|
679 |
-
*
|
680 |
-
* @return string
|
681 |
-
*/
|
682 |
-
public function innerXml($delimiter = '')
|
683 |
-
{
|
684 |
-
$innerXml = [];
|
685 |
-
|
686 |
-
foreach ($this->node->childNodes as $childNode) {
|
687 |
-
$innerXml[] = $childNode->ownerDocument->saveXML($childNode);
|
688 |
-
}
|
689 |
-
|
690 |
-
return implode($delimiter, $innerXml);
|
691 |
-
}
|
692 |
-
|
693 |
-
/**
|
694 |
-
* Sets inner HTML.
|
695 |
-
*
|
696 |
-
* @param string $html
|
697 |
-
*
|
698 |
-
* @return \DiDom\Element
|
699 |
-
*
|
700 |
-
* @throws InvalidArgumentException if passed argument is not a string
|
701 |
-
*/
|
702 |
-
public function setInnerHtml($html)
|
703 |
-
{
|
704 |
-
if (!is_string($html)) {
|
705 |
-
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($html) ? get_class($html) : gettype($html))));
|
706 |
-
}
|
707 |
-
|
708 |
-
$this->removeChildren();
|
709 |
-
|
710 |
-
if ($html !== '') {
|
711 |
-
Errors::disable();
|
712 |
-
|
713 |
-
$html = "<htmlfragment>$html</htmlfragment>";
|
714 |
-
|
715 |
-
$document = new Document($html);
|
716 |
-
|
717 |
-
$fragment = $document->first('htmlfragment')->getNode();
|
718 |
-
|
719 |
-
foreach ($fragment->childNodes as $node) {
|
720 |
-
$newNode = $this->node->ownerDocument->importNode($node, true);
|
721 |
-
|
722 |
-
$this->node->appendChild($newNode);
|
723 |
-
}
|
724 |
-
|
725 |
-
Errors::restore();
|
726 |
-
}
|
727 |
-
|
728 |
-
return $this;
|
729 |
-
}
|
730 |
-
|
731 |
-
/**
|
732 |
-
* Dumps the node into a string using XML formatting.
|
733 |
-
*
|
734 |
-
* @param int $options Additional options
|
735 |
*
|
736 |
-
* @
|
737 |
-
|
738 |
-
public function xml($options = 0)
|
739 |
-
{
|
740 |
-
return $this->toDocument()->xml($options);
|
741 |
-
}
|
742 |
-
|
743 |
-
/**
|
744 |
-
* Get the text content of this node and its descendants.
|
745 |
*
|
746 |
-
* @return
|
747 |
*/
|
748 |
-
public function
|
749 |
{
|
750 |
-
return $this->
|
751 |
}
|
752 |
|
753 |
/**
|
754 |
-
*
|
755 |
-
*
|
756 |
-
* @param string $value The new value of the node
|
757 |
*
|
758 |
-
* @
|
759 |
*
|
760 |
-
* @
|
761 |
*/
|
762 |
-
public function
|
763 |
{
|
764 |
-
if (
|
765 |
-
|
766 |
-
}
|
767 |
-
|
768 |
-
if (!is_string($value) && $value !== null) {
|
769 |
-
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($value) ? get_class($value) : gettype($value))));
|
770 |
}
|
771 |
|
772 |
-
$this->
|
773 |
-
|
774 |
-
return $this;
|
775 |
-
}
|
776 |
-
|
777 |
-
/**
|
778 |
-
* Returns true if current node is a DOMElement instance.
|
779 |
-
*
|
780 |
-
* @return bool
|
781 |
-
*/
|
782 |
-
public function isElementNode()
|
783 |
-
{
|
784 |
-
return $this->node instanceof DOMElement;
|
785 |
}
|
786 |
|
787 |
/**
|
788 |
-
*
|
789 |
*
|
790 |
-
* @
|
791 |
-
*/
|
792 |
-
public function isTextNode()
|
793 |
-
{
|
794 |
-
return $this->node instanceof DOMText;
|
795 |
-
}
|
796 |
-
|
797 |
-
/**
|
798 |
-
* Returns true if current node is a DOMComment instance.
|
799 |
*
|
800 |
* @return bool
|
801 |
*/
|
802 |
-
public function
|
803 |
{
|
804 |
-
return $this->
|
805 |
}
|
806 |
|
807 |
/**
|
808 |
-
*
|
809 |
*
|
810 |
-
* @
|
811 |
*/
|
812 |
-
public function
|
813 |
-
{
|
814 |
-
return $this->node instanceof DOMCdataSection;
|
815 |
-
}
|
816 |
-
|
817 |
-
/**
|
818 |
-
* Indicates if two nodes are the same node.
|
819 |
-
*
|
820 |
-
* @param \DiDom\Element|\DOMNode $node
|
821 |
-
*
|
822 |
-
* @return bool
|
823 |
-
*
|
824 |
-
* @throws \InvalidArgumentException if the provided argument is not an instance of \DOMNode
|
825 |
-
*/
|
826 |
-
public function is($node)
|
827 |
-
{
|
828 |
-
if ($node instanceof Element) {
|
829 |
-
$node = $node->getNode();
|
830 |
-
}
|
831 |
-
|
832 |
-
if (!$node instanceof DOMNode) {
|
833 |
-
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of %s or DOMNode, %s given', __METHOD__, __CLASS__, (is_object($node) ? get_class($node) : gettype($node))));
|
834 |
-
}
|
835 |
-
|
836 |
-
return $this->node->isSameNode($node);
|
837 |
-
}
|
838 |
-
|
839 |
-
/**
|
840 |
-
* @return \DiDom\Element|\DiDom\Document|null
|
841 |
-
*/
|
842 |
-
public function parent()
|
843 |
-
{
|
844 |
-
if ($this->node->parentNode === null) {
|
845 |
-
return null;
|
846 |
-
}
|
847 |
-
|
848 |
-
if ($this->node->parentNode instanceof DOMDocument) {
|
849 |
-
return new Document($this->node->parentNode);
|
850 |
-
}
|
851 |
-
|
852 |
-
return new Element($this->node->parentNode);
|
853 |
-
}
|
854 |
-
|
855 |
-
/**
|
856 |
-
* Returns first parent node matches passed selector.
|
857 |
-
*
|
858 |
-
* @param string $selector
|
859 |
-
* @param bool $strict
|
860 |
-
*
|
861 |
-
* @return \DiDom\Element|null
|
862 |
-
*/
|
863 |
-
public function closest($selector, $strict = false)
|
864 |
-
{
|
865 |
-
$node = $this;
|
866 |
-
|
867 |
-
while (true) {
|
868 |
-
$parent = $node->parent();
|
869 |
-
|
870 |
-
if ($parent === null || $parent instanceof Document) {
|
871 |
-
return null;
|
872 |
-
}
|
873 |
-
|
874 |
-
if ($parent->matches($selector, $strict)) {
|
875 |
-
return $parent;
|
876 |
-
}
|
877 |
-
|
878 |
-
$node = $parent;
|
879 |
-
}
|
880 |
-
}
|
881 |
-
|
882 |
-
/**
|
883 |
-
* @param string|null $selector
|
884 |
-
* @param string|null $nodeType
|
885 |
-
*
|
886 |
-
* @return \DiDom\Element|null
|
887 |
-
*
|
888 |
-
* @throws \InvalidArgumentException if node type is not string
|
889 |
-
* @throws \RuntimeException if node type is invalid
|
890 |
-
* @throws \LogicException if selector used with non DOMElement node type
|
891 |
-
*/
|
892 |
-
public function previousSibling($selector = null, $nodeType = null)
|
893 |
-
{
|
894 |
-
if ($this->node->previousSibling === null) {
|
895 |
-
return null;
|
896 |
-
}
|
897 |
-
|
898 |
-
if ($selector === null && $nodeType === null) {
|
899 |
-
return new Element($this->node->previousSibling);
|
900 |
-
}
|
901 |
-
|
902 |
-
if ($selector !== null && $nodeType === null) {
|
903 |
-
$nodeType = 'DOMElement';
|
904 |
-
}
|
905 |
-
|
906 |
-
if (!is_string($nodeType)) {
|
907 |
-
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($nodeType)));
|
908 |
-
}
|
909 |
-
|
910 |
-
$allowedTypes = ['DOMElement', 'DOMText', 'DOMComment', 'DOMCdataSection'];
|
911 |
-
|
912 |
-
if (!in_array($nodeType, $allowedTypes, true)) {
|
913 |
-
throw new RuntimeException(sprintf('Unknown node type "%s". Allowed types: %s', $nodeType, implode(', ', $allowedTypes)));
|
914 |
-
}
|
915 |
-
|
916 |
-
if ($selector !== null && $nodeType !== 'DOMElement') {
|
917 |
-
throw new LogicException(sprintf('Selector can be used only with DOMElement node type, %s given', $nodeType));
|
918 |
-
}
|
919 |
-
|
920 |
-
$node = $this->node->previousSibling;
|
921 |
-
|
922 |
-
while ($node !== null) {
|
923 |
-
if (get_class($node) !== $nodeType) {
|
924 |
-
$node = $node->previousSibling;
|
925 |
-
|
926 |
-
continue;
|
927 |
-
}
|
928 |
-
|
929 |
-
$element = new Element($node);
|
930 |
-
|
931 |
-
if ($selector === null) {
|
932 |
-
return $element;
|
933 |
-
}
|
934 |
-
|
935 |
-
if ($element->matches($selector)) {
|
936 |
-
return $element;
|
937 |
-
}
|
938 |
-
|
939 |
-
$node = $node->previousSibling;
|
940 |
-
}
|
941 |
-
|
942 |
-
return new Element($this->node->previousSibling);
|
943 |
-
}
|
944 |
-
|
945 |
-
/**
|
946 |
-
* @param string|null $selector
|
947 |
-
* @param string|null $nodeType
|
948 |
-
*
|
949 |
-
* @return \DiDom\Element[]
|
950 |
-
*
|
951 |
-
* @throws \InvalidArgumentException if node type is not string
|
952 |
-
* @throws \RuntimeException if node type is invalid
|
953 |
-
* @throws \LogicException if selector used with non DOMElement node type
|
954 |
-
*/
|
955 |
-
public function previousSiblings($selector = null, $nodeType = null)
|
956 |
-
{
|
957 |
-
if ($this->node->previousSibling === null) {
|
958 |
-
return [];
|
959 |
-
}
|
960 |
-
|
961 |
-
if ($selector !== null && $nodeType === null) {
|
962 |
-
$nodeType = 'DOMElement';
|
963 |
-
}
|
964 |
-
|
965 |
-
if ($nodeType !== null) {
|
966 |
-
if (!is_string($nodeType)) {
|
967 |
-
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($nodeType)));
|
968 |
-
}
|
969 |
-
|
970 |
-
$allowedTypes = ['DOMElement', 'DOMText', 'DOMComment', 'DOMCdataSection'];
|
971 |
-
|
972 |
-
if (!in_array($nodeType, $allowedTypes, true)) {
|
973 |
-
throw new RuntimeException(sprintf('Unknown node type "%s". Allowed types: %s', $nodeType, implode(', ', $allowedTypes)));
|
974 |
-
}
|
975 |
-
}
|
976 |
-
|
977 |
-
if ($selector !== null && $nodeType !== 'DOMElement') {
|
978 |
-
throw new LogicException(sprintf('Selector can be used only with DOMElement node type, %s given', $nodeType));
|
979 |
-
}
|
980 |
-
|
981 |
-
$result = [];
|
982 |
-
|
983 |
-
$node = $this->node->previousSibling;
|
984 |
-
|
985 |
-
while ($node !== null) {
|
986 |
-
$element = new Element($node);
|
987 |
-
|
988 |
-
if ($nodeType === null) {
|
989 |
-
$result[] = $element;
|
990 |
-
|
991 |
-
$node = $node->previousSibling;
|
992 |
-
|
993 |
-
continue;
|
994 |
-
}
|
995 |
-
|
996 |
-
if (get_class($node) !== $nodeType) {
|
997 |
-
$node = $node->previousSibling;
|
998 |
-
|
999 |
-
continue;
|
1000 |
-
}
|
1001 |
-
|
1002 |
-
if ($selector === null) {
|
1003 |
-
$result[] = $element;
|
1004 |
-
|
1005 |
-
$node = $node->previousSibling;
|
1006 |
-
|
1007 |
-
continue;
|
1008 |
-
}
|
1009 |
-
|
1010 |
-
if ($element->matches($selector)) {
|
1011 |
-
$result[] = $element;
|
1012 |
-
}
|
1013 |
-
|
1014 |
-
$node = $node->previousSibling;
|
1015 |
-
}
|
1016 |
-
|
1017 |
-
return array_reverse($result);
|
1018 |
-
}
|
1019 |
-
|
1020 |
-
/**
|
1021 |
-
* @param string|null $selector
|
1022 |
-
* @param string|null $nodeType
|
1023 |
-
*
|
1024 |
-
* @return \DiDom\Element|null
|
1025 |
-
*
|
1026 |
-
* @throws \InvalidArgumentException if node type is not string
|
1027 |
-
* @throws \RuntimeException if node type is invalid
|
1028 |
-
* @throws \LogicException if selector used with non DOMElement node type
|
1029 |
-
*/
|
1030 |
-
public function nextSibling($selector = null, $nodeType = null)
|
1031 |
-
{
|
1032 |
-
if ($this->node->nextSibling === null) {
|
1033 |
-
return null;
|
1034 |
-
}
|
1035 |
-
|
1036 |
-
if ($selector === null && $nodeType === null) {
|
1037 |
-
return new Element($this->node->nextSibling);
|
1038 |
-
}
|
1039 |
-
|
1040 |
-
if ($selector !== null && $nodeType === null) {
|
1041 |
-
$nodeType = 'DOMElement';
|
1042 |
-
}
|
1043 |
-
|
1044 |
-
if (!is_string($nodeType)) {
|
1045 |
-
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($nodeType)));
|
1046 |
-
}
|
1047 |
-
|
1048 |
-
$allowedTypes = ['DOMElement', 'DOMText', 'DOMComment', 'DOMCdataSection'];
|
1049 |
-
|
1050 |
-
if (!in_array($nodeType, $allowedTypes, true)) {
|
1051 |
-
throw new RuntimeException(sprintf('Unknown node type "%s". Allowed types: %s', $nodeType, implode(', ', $allowedTypes)));
|
1052 |
-
}
|
1053 |
-
|
1054 |
-
if ($selector !== null && $nodeType !== 'DOMElement') {
|
1055 |
-
throw new LogicException(sprintf('Selector can be used only with DOMElement node type, %s given', $nodeType));
|
1056 |
-
}
|
1057 |
-
|
1058 |
-
$node = $this->node->nextSibling;
|
1059 |
-
|
1060 |
-
while ($node !== null) {
|
1061 |
-
if (get_class($node) !== $nodeType) {
|
1062 |
-
$node = $node->nextSibling;
|
1063 |
-
|
1064 |
-
continue;
|
1065 |
-
}
|
1066 |
-
|
1067 |
-
$element = new Element($node);
|
1068 |
-
|
1069 |
-
if ($selector === null) {
|
1070 |
-
return $element;
|
1071 |
-
}
|
1072 |
-
|
1073 |
-
if ($element->matches($selector)) {
|
1074 |
-
return $element;
|
1075 |
-
}
|
1076 |
-
|
1077 |
-
$node = $node->nextSibling;
|
1078 |
-
}
|
1079 |
-
|
1080 |
-
return null;
|
1081 |
-
}
|
1082 |
-
|
1083 |
-
/**
|
1084 |
-
* @param string|null $selector
|
1085 |
-
* @param string $nodeType
|
1086 |
-
*
|
1087 |
-
* @return \DiDom\Element[]
|
1088 |
-
*
|
1089 |
-
* @throws \InvalidArgumentException if node type is not string
|
1090 |
-
* @throws \RuntimeException if node type is invalid
|
1091 |
-
* @throws \LogicException if selector used with non DOMElement node type
|
1092 |
-
*/
|
1093 |
-
public function nextSiblings($selector = null, $nodeType = null)
|
1094 |
-
{
|
1095 |
-
if ($this->node->nextSibling === null) {
|
1096 |
-
return [];
|
1097 |
-
}
|
1098 |
-
|
1099 |
-
if ($selector !== null && $nodeType === null) {
|
1100 |
-
$nodeType = 'DOMElement';
|
1101 |
-
}
|
1102 |
-
|
1103 |
-
if ($nodeType !== null) {
|
1104 |
-
if (!is_string($nodeType)) {
|
1105 |
-
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($nodeType)));
|
1106 |
-
}
|
1107 |
-
|
1108 |
-
$allowedTypes = ['DOMElement', 'DOMText', 'DOMComment', 'DOMCdataSection'];
|
1109 |
-
|
1110 |
-
if (!in_array($nodeType, $allowedTypes, true)) {
|
1111 |
-
throw new RuntimeException(sprintf('Unknown node type "%s". Allowed types: %s', $nodeType, implode(', ', $allowedTypes)));
|
1112 |
-
}
|
1113 |
-
}
|
1114 |
-
|
1115 |
-
if ($selector !== null && $nodeType !== 'DOMElement') {
|
1116 |
-
throw new LogicException(sprintf('Selector can be used only with DOMElement node type, %s given', $nodeType));
|
1117 |
-
}
|
1118 |
-
|
1119 |
-
$result = [];
|
1120 |
-
|
1121 |
-
$node = $this->node->nextSibling;
|
1122 |
-
|
1123 |
-
while ($node !== null) {
|
1124 |
-
$element = new Element($node);
|
1125 |
-
|
1126 |
-
if ($nodeType === null) {
|
1127 |
-
$result[] = $element;
|
1128 |
-
|
1129 |
-
$node = $node->nextSibling;
|
1130 |
-
|
1131 |
-
continue;
|
1132 |
-
}
|
1133 |
-
|
1134 |
-
if (get_class($node) !== $nodeType) {
|
1135 |
-
$node = $node->nextSibling;
|
1136 |
-
|
1137 |
-
continue;
|
1138 |
-
}
|
1139 |
-
|
1140 |
-
if ($selector === null) {
|
1141 |
-
$result[] = $element;
|
1142 |
-
|
1143 |
-
$node = $node->nextSibling;
|
1144 |
-
|
1145 |
-
continue;
|
1146 |
-
}
|
1147 |
-
|
1148 |
-
if ($element->matches($selector)) {
|
1149 |
-
$result[] = $element;
|
1150 |
-
}
|
1151 |
-
|
1152 |
-
$node = $node->nextSibling;
|
1153 |
-
}
|
1154 |
-
|
1155 |
-
return $result;
|
1156 |
-
}
|
1157 |
-
|
1158 |
-
/**
|
1159 |
-
* @param int $index
|
1160 |
-
*
|
1161 |
-
* @return \DiDom\Element|null
|
1162 |
-
*/
|
1163 |
-
public function child($index)
|
1164 |
-
{
|
1165 |
-
$child = $this->node->childNodes->item($index);
|
1166 |
-
|
1167 |
-
return $child === null ? null : new Element($child);
|
1168 |
-
}
|
1169 |
-
|
1170 |
-
/**
|
1171 |
-
* @return \DiDom\Element|null
|
1172 |
-
*/
|
1173 |
-
public function firstChild()
|
1174 |
-
{
|
1175 |
-
if ($this->node->firstChild === null) {
|
1176 |
-
return null;
|
1177 |
-
}
|
1178 |
-
|
1179 |
-
return new Element($this->node->firstChild);
|
1180 |
-
}
|
1181 |
-
|
1182 |
-
/**
|
1183 |
-
* @return \DiDom\Element|null
|
1184 |
-
*/
|
1185 |
-
public function lastChild()
|
1186 |
-
{
|
1187 |
-
if ($this->node->lastChild === null) {
|
1188 |
-
return null;
|
1189 |
-
}
|
1190 |
-
|
1191 |
-
return new Element($this->node->lastChild);
|
1192 |
-
}
|
1193 |
-
|
1194 |
-
/**
|
1195 |
-
* @return bool
|
1196 |
-
*/
|
1197 |
-
public function hasChildren()
|
1198 |
-
{
|
1199 |
-
return $this->node->hasChildNodes();
|
1200 |
-
}
|
1201 |
-
|
1202 |
-
/**
|
1203 |
-
* @return \DiDom\Element[]
|
1204 |
-
*/
|
1205 |
-
public function children()
|
1206 |
-
{
|
1207 |
-
$children = [];
|
1208 |
-
|
1209 |
-
foreach ($this->node->childNodes as $node) {
|
1210 |
-
$children[] = new Element($node);
|
1211 |
-
}
|
1212 |
-
|
1213 |
-
return $children;
|
1214 |
-
}
|
1215 |
-
|
1216 |
-
/**
|
1217 |
-
* Removes child from list of children.
|
1218 |
-
*
|
1219 |
-
* @param \DOMNode|\DiDom\Element $childNode
|
1220 |
-
*
|
1221 |
-
* @return \DiDom\Element the node that has been removed
|
1222 |
-
*/
|
1223 |
-
public function removeChild($childNode)
|
1224 |
-
{
|
1225 |
-
if ($childNode instanceof Element) {
|
1226 |
-
$childNode = $childNode->getNode();
|
1227 |
-
}
|
1228 |
-
|
1229 |
-
if (!$childNode instanceof DOMNode) {
|
1230 |
-
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of %s or DOMNode, %s given', __METHOD__, __CLASS__, (is_object($childNode) ? get_class($childNode) : gettype($childNode))));
|
1231 |
-
}
|
1232 |
-
|
1233 |
-
$removedNode = $this->node->removeChild($childNode);
|
1234 |
-
|
1235 |
-
return new Element($removedNode);
|
1236 |
-
}
|
1237 |
-
|
1238 |
-
/**
|
1239 |
-
* Removes all child nodes.
|
1240 |
-
*
|
1241 |
-
* @return \DiDom\Element[] the nodes that has been removed
|
1242 |
-
*/
|
1243 |
-
public function removeChildren()
|
1244 |
-
{
|
1245 |
-
// we need to collect child nodes to array
|
1246 |
-
// because removing nodes from the DOMNodeList on iterating is not working
|
1247 |
-
$childNodes = [];
|
1248 |
-
|
1249 |
-
foreach ($this->node->childNodes as $childNode) {
|
1250 |
-
$childNodes[] = $childNode;
|
1251 |
-
}
|
1252 |
-
|
1253 |
-
$removedNodes = [];
|
1254 |
-
|
1255 |
-
foreach ($childNodes as $childNode) {
|
1256 |
-
$removedNode = $this->node->removeChild($childNode);
|
1257 |
-
|
1258 |
-
$removedNodes[] = new Element($removedNode);
|
1259 |
-
}
|
1260 |
-
|
1261 |
-
return $removedNodes;
|
1262 |
-
}
|
1263 |
-
|
1264 |
-
/**
|
1265 |
-
* Removes current node from the parent.
|
1266 |
-
*
|
1267 |
-
* @return \DiDom\Element the node that has been removed
|
1268 |
-
*
|
1269 |
-
* @throws \LogicException if current node has no parent node
|
1270 |
-
*/
|
1271 |
-
public function remove()
|
1272 |
-
{
|
1273 |
-
if ($this->node->parentNode === null) {
|
1274 |
-
throw new LogicException('Can not remove element without parent node');
|
1275 |
-
}
|
1276 |
-
|
1277 |
-
$removedNode = $this->node->parentNode->removeChild($this->node);
|
1278 |
-
|
1279 |
-
return new Element($removedNode);
|
1280 |
-
}
|
1281 |
-
|
1282 |
-
/**
|
1283 |
-
* Replaces a child.
|
1284 |
-
*
|
1285 |
-
* @param \DOMNode|\DiDom\Element $newNode The new node
|
1286 |
-
* @param bool $clone Clone the node if true, otherwise move it
|
1287 |
-
*
|
1288 |
-
* @return \DiDom\Element The node that has been replaced
|
1289 |
-
*
|
1290 |
-
* @throws \LogicException if current node has no parent node
|
1291 |
-
*/
|
1292 |
-
public function replace($newNode, $clone = true)
|
1293 |
-
{
|
1294 |
-
if ($this->node->parentNode === null) {
|
1295 |
-
throw new LogicException('Can not replace element without parent node');
|
1296 |
-
}
|
1297 |
-
|
1298 |
-
if ($newNode instanceof Element) {
|
1299 |
-
$newNode = $newNode->getNode();
|
1300 |
-
}
|
1301 |
-
|
1302 |
-
if (!$newNode instanceof DOMNode) {
|
1303 |
-
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of %s or DOMNode, %s given', __METHOD__, __CLASS__, (is_object($newNode) ? get_class($newNode) : gettype($newNode))));
|
1304 |
-
}
|
1305 |
-
|
1306 |
-
if ($clone) {
|
1307 |
-
$newNode = $newNode->cloneNode(true);
|
1308 |
-
}
|
1309 |
-
|
1310 |
-
if ($newNode->ownerDocument === null || !$this->getDocument()->is($newNode->ownerDocument)) {
|
1311 |
-
$newNode = $this->node->ownerDocument->importNode($newNode, true);
|
1312 |
-
}
|
1313 |
-
|
1314 |
-
$node = $this->node->parentNode->replaceChild($newNode, $this->node);
|
1315 |
-
|
1316 |
-
return new Element($node);
|
1317 |
-
}
|
1318 |
-
|
1319 |
-
/**
|
1320 |
-
* Get line number for a node.
|
1321 |
-
*
|
1322 |
-
* @return int
|
1323 |
-
*/
|
1324 |
-
public function getLineNo()
|
1325 |
-
{
|
1326 |
-
return $this->node->getLineNo();
|
1327 |
-
}
|
1328 |
-
|
1329 |
-
/**
|
1330 |
-
* Clones a node.
|
1331 |
-
*
|
1332 |
-
* @param bool $deep Indicates whether to copy all descendant nodes
|
1333 |
-
*
|
1334 |
-
* @return \DiDom\Element The cloned node
|
1335 |
-
*/
|
1336 |
-
public function cloneNode($deep = true)
|
1337 |
-
{
|
1338 |
-
return new Element($this->node->cloneNode($deep));
|
1339 |
-
}
|
1340 |
-
|
1341 |
-
/**
|
1342 |
-
* Sets current node instance.
|
1343 |
-
*
|
1344 |
-
* @param \DOMElement|\DOMText|\DOMComment|\DOMCdataSection $node
|
1345 |
-
*
|
1346 |
-
* @return \DiDom\Element
|
1347 |
-
*/
|
1348 |
-
protected function setNode($node)
|
1349 |
-
{
|
1350 |
-
$allowedClasses = ['DOMElement', 'DOMText', 'DOMComment', 'DOMCdataSection'];
|
1351 |
-
|
1352 |
-
if (!is_object($node) || !in_array(get_class($node), $allowedClasses, true)) {
|
1353 |
-
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of DOMElement, DOMText, DOMComment or DOMCdataSection, %s given', __METHOD__, (is_object($node) ? get_class($node) : gettype($node))));
|
1354 |
-
}
|
1355 |
-
|
1356 |
-
$this->node = $node;
|
1357 |
-
|
1358 |
-
return $this;
|
1359 |
-
}
|
1360 |
-
|
1361 |
-
/**
|
1362 |
-
* Returns current node instance.
|
1363 |
-
*
|
1364 |
-
* @return \DOMElement|\DOMText|\DOMComment|\DOMCdataSection
|
1365 |
-
*/
|
1366 |
-
public function getNode()
|
1367 |
-
{
|
1368 |
-
return $this->node;
|
1369 |
-
}
|
1370 |
-
|
1371 |
-
/**
|
1372 |
-
* Returns the document associated with this node.
|
1373 |
-
*
|
1374 |
-
* @return \DiDom\Document|null
|
1375 |
-
*/
|
1376 |
-
public function getDocument()
|
1377 |
-
{
|
1378 |
-
if ($this->node->ownerDocument === null) {
|
1379 |
-
return null;
|
1380 |
-
}
|
1381 |
-
|
1382 |
-
return new Document($this->node->ownerDocument);
|
1383 |
-
}
|
1384 |
-
|
1385 |
-
/**
|
1386 |
-
* Get the DOM document with the current element.
|
1387 |
-
*
|
1388 |
-
* @param string $encoding The document encoding
|
1389 |
-
*
|
1390 |
-
* @return \DiDom\Document
|
1391 |
-
*/
|
1392 |
-
public function toDocument($encoding = 'UTF-8')
|
1393 |
-
{
|
1394 |
-
$document = new Document(null, false, $encoding);
|
1395 |
-
|
1396 |
-
$document->appendChild($this->node);
|
1397 |
-
|
1398 |
-
return $document;
|
1399 |
-
}
|
1400 |
-
|
1401 |
-
/**
|
1402 |
-
* Dynamically set an attribute on the element.
|
1403 |
-
*
|
1404 |
-
* @param string $name The attribute name
|
1405 |
-
* @param mixed $value The attribute value
|
1406 |
-
*
|
1407 |
-
* @return \DiDom\Element
|
1408 |
-
*/
|
1409 |
-
public function __set($name, $value)
|
1410 |
-
{
|
1411 |
-
return $this->setAttribute($name, $value);
|
1412 |
-
}
|
1413 |
-
|
1414 |
-
/**
|
1415 |
-
* Dynamically access the element's attributes.
|
1416 |
-
*
|
1417 |
-
* @param string $name The attribute name
|
1418 |
-
*
|
1419 |
-
* @return string|null
|
1420 |
-
*/
|
1421 |
-
public function __get($name)
|
1422 |
-
{
|
1423 |
-
if ($name === 'tag') {
|
1424 |
-
return $this->node->tagName;
|
1425 |
-
}
|
1426 |
-
|
1427 |
-
return $this->getAttribute($name);
|
1428 |
-
}
|
1429 |
-
|
1430 |
-
/**
|
1431 |
-
* Determine if an attribute exists on the element.
|
1432 |
-
*
|
1433 |
-
* @param string $name The attribute name
|
1434 |
-
*
|
1435 |
-
* @return bool
|
1436 |
-
*/
|
1437 |
-
public function __isset($name)
|
1438 |
-
{
|
1439 |
-
return $this->hasAttribute($name);
|
1440 |
-
}
|
1441 |
-
|
1442 |
-
/**
|
1443 |
-
* Unset an attribute on the model.
|
1444 |
-
*
|
1445 |
-
* @param string $name The attribute name
|
1446 |
-
*/
|
1447 |
-
public function __unset($name)
|
1448 |
{
|
1449 |
$this->removeAttribute($name);
|
1450 |
}
|
1451 |
-
|
1452 |
-
/**
|
1453 |
-
* Convert the element to its string representation.
|
1454 |
-
*
|
1455 |
-
* @return string
|
1456 |
-
*/
|
1457 |
-
public function __toString()
|
1458 |
-
{
|
1459 |
-
return $this->html();
|
1460 |
-
}
|
1461 |
-
|
1462 |
-
/**
|
1463 |
-
* Searches for an node in the DOM tree for a given XPath expression or a CSS selector.
|
1464 |
-
*
|
1465 |
-
* @param string $expression XPath expression or a CSS selector
|
1466 |
-
* @param string $type The type of the expression
|
1467 |
-
* @param bool $wrapNode Returns array of \DiDom\Element if true, otherwise array of \DOMElement
|
1468 |
-
*
|
1469 |
-
* @return \DiDom\Element[]|\DOMElement[]
|
1470 |
-
*
|
1471 |
-
* @deprecated Not longer recommended, use Element::find() instead.
|
1472 |
-
*/
|
1473 |
-
public function __invoke($expression, $type = Query::TYPE_CSS, $wrapNode = true)
|
1474 |
-
{
|
1475 |
-
return $this->find($expression, $type, $wrapNode);
|
1476 |
-
}
|
1477 |
}
|
2 |
|
3 |
namespace DiDom;
|
4 |
|
5 |
+
use DiDom\Exceptions\InvalidSelectorException;
|
6 |
use DOMCdataSection;
|
7 |
use DOMComment;
|
8 |
use DOMDocument;
|
16 |
/**
|
17 |
* @property string $tag
|
18 |
*/
|
19 |
+
class Element extends Node
|
20 |
{
|
21 |
/**
|
22 |
+
* @var ClassAttribute
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
*/
|
24 |
protected $classAttribute;
|
25 |
|
26 |
/**
|
27 |
+
* @var StyleAttribute
|
28 |
*/
|
29 |
protected $styleAttribute;
|
30 |
|
31 |
/**
|
32 |
+
* @param DOMElement|DOMText|DOMComment|DOMCdataSection|string $tagName The tag name of an element
|
33 |
+
* @param string|null $value The value of an element
|
34 |
+
* @param array $attributes The attributes of an element
|
|
|
|
|
35 |
*/
|
36 |
public function __construct($tagName, $value = null, array $attributes = [])
|
37 |
{
|
57 |
/**
|
58 |
* Creates a new element.
|
59 |
*
|
60 |
+
* @param DOMNode|string $name The tag name of an element
|
61 |
+
* @param string|null $value The value of an element
|
62 |
+
* @param array $attributes The attributes of an element
|
63 |
*
|
64 |
+
* @return Element
|
65 |
*/
|
66 |
public static function create($name, $value = null, array $attributes = [])
|
67 |
{
|
75 |
* @param string|null $value
|
76 |
* @param array $attributes
|
77 |
*
|
78 |
+
* @return Element
|
79 |
+
*
|
80 |
+
* @throws InvalidSelectorException
|
81 |
*/
|
82 |
public static function createBySelector($selector, $value = null, array $attributes = [])
|
83 |
{
|
84 |
return Document::create()->createElementBySelector($selector, $value, $attributes);
|
85 |
}
|
86 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
/**
|
88 |
* Checks that the node matches selector.
|
89 |
*
|
92 |
*
|
93 |
* @return bool
|
94 |
*
|
95 |
+
* @throws InvalidSelectorException if the selector is invalid
|
96 |
+
* @throws InvalidArgumentException if the tag name is not a string
|
97 |
+
* @throws RuntimeException if the tag name is not specified in strict mode
|
98 |
*/
|
99 |
public function matches($selector, $strict = false)
|
100 |
{
|
101 |
+
if ( ! is_string($selector)) {
|
102 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, gettype($selector)));
|
103 |
}
|
104 |
|
105 |
+
if ( ! $this->node instanceof DOMElement) {
|
106 |
return false;
|
107 |
}
|
108 |
|
110 |
return true;
|
111 |
}
|
112 |
|
113 |
+
if ( ! $strict) {
|
114 |
$innerHtml = $this->html();
|
115 |
$html = "<root>$innerHtml</root>";
|
116 |
|
125 |
|
126 |
$segments = Query::getSegments($selector);
|
127 |
|
128 |
+
if ( ! array_key_exists('tag', $segments)) {
|
129 |
throw new RuntimeException(sprintf('Tag name must be specified in %s', $selector));
|
130 |
}
|
131 |
|
170 |
/**
|
171 |
* Determine if an attribute exists on the element.
|
172 |
*
|
173 |
+
* @param string $name The name of an attribute
|
174 |
*
|
175 |
* @return bool
|
176 |
*/
|
182 |
/**
|
183 |
* Set an attribute on the element.
|
184 |
*
|
185 |
+
* @param string $name The name of an attribute
|
186 |
+
* @param string $value The value of an attribute
|
187 |
*
|
188 |
+
* @return Element
|
189 |
*/
|
190 |
public function setAttribute($name, $value)
|
191 |
{
|
193 |
$value = (string) $value;
|
194 |
}
|
195 |
|
196 |
+
if ( ! is_string($value) && $value !== null) {
|
197 |
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string or null, %s given', __METHOD__, (is_object($value) ? get_class($value) : gettype($value))));
|
198 |
}
|
199 |
|
205 |
/**
|
206 |
* Access to the element's attributes.
|
207 |
*
|
208 |
+
* @param string $name The name of an attribute
|
209 |
+
* @param string|null $default The value returned if the attribute doesn't exist
|
210 |
*
|
211 |
+
* @return string|null The value of an attribute or null if attribute doesn't exist
|
212 |
*/
|
213 |
public function getAttribute($name, $default = null)
|
214 |
{
|
222 |
/**
|
223 |
* Unset an attribute on the element.
|
224 |
*
|
225 |
+
* @param string $name The name of an attribute
|
226 |
*
|
227 |
+
* @return Element
|
228 |
*/
|
229 |
public function removeAttribute($name)
|
230 |
{
|
238 |
*
|
239 |
* @param string[] $exclusions
|
240 |
*
|
241 |
+
* @return Element
|
242 |
*/
|
243 |
public function removeAllAttributes(array $exclusions = [])
|
244 |
{
|
245 |
+
if ( ! $this->node instanceof DOMElement) {
|
246 |
return $this;
|
247 |
}
|
248 |
|
260 |
/**
|
261 |
* Alias for getAttribute and setAttribute methods.
|
262 |
*
|
263 |
+
* @param string $name The name of an attribute
|
264 |
+
* @param string|null $value The value that will be returned an attribute doesn't exist
|
265 |
*
|
266 |
+
* @return string|null|Element
|
267 |
*/
|
268 |
public function attr($name, $value = null)
|
269 |
{
|
283 |
*/
|
284 |
public function attributes(array $names = null)
|
285 |
{
|
286 |
+
if ( ! $this->node instanceof DOMElement) {
|
287 |
return null;
|
288 |
}
|
289 |
|
309 |
}
|
310 |
|
311 |
/**
|
312 |
+
* @return ClassAttribute
|
313 |
*
|
314 |
+
* @throws LogicException if the node is not an instance of DOMElement
|
315 |
*/
|
316 |
public function classes()
|
317 |
{
|
319 |
return $this->classAttribute;
|
320 |
}
|
321 |
|
322 |
+
if ( ! $this->isElementNode()) {
|
323 |
throw new LogicException('Class attribute is available only for element nodes');
|
324 |
}
|
325 |
|
329 |
}
|
330 |
|
331 |
/**
|
332 |
+
* @return StyleAttribute
|
333 |
*
|
334 |
+
* @throws LogicException if the node is not an instance of DOMElement
|
335 |
*/
|
336 |
public function style()
|
337 |
{
|
339 |
return $this->styleAttribute;
|
340 |
}
|
341 |
|
342 |
+
if ( ! $this->isElementNode()) {
|
343 |
throw new LogicException('Style attribute is available only for element nodes');
|
344 |
}
|
345 |
|
349 |
}
|
350 |
|
351 |
/**
|
352 |
+
* Dynamically set an attribute on the element.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
353 |
*
|
354 |
+
* @param string $name The name of an attribute
|
355 |
+
* @param string $value The value of an attribute
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
356 |
*
|
357 |
+
* @return Element
|
358 |
*/
|
359 |
+
public function __set($name, $value)
|
360 |
{
|
361 |
+
return $this->setAttribute($name, $value);
|
362 |
}
|
363 |
|
364 |
/**
|
365 |
+
* Dynamically access the element's attributes.
|
|
|
|
|
366 |
*
|
367 |
+
* @param string $name The name of an attribute
|
368 |
*
|
369 |
+
* @return string|null
|
370 |
*/
|
371 |
+
public function __get($name)
|
372 |
{
|
373 |
+
if ($name === 'tag') {
|
374 |
+
return $this->node->tagName;
|
|
|
|
|
|
|
|
|
375 |
}
|
376 |
|
377 |
+
return $this->getAttribute($name);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
378 |
}
|
379 |
|
380 |
/**
|
381 |
+
* Determine if an attribute exists on the element.
|
382 |
*
|
383 |
+
* @param string $name The attribute name
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
384 |
*
|
385 |
* @return bool
|
386 |
*/
|
387 |
+
public function __isset($name)
|
388 |
{
|
389 |
+
return $this->hasAttribute($name);
|
390 |
}
|
391 |
|
392 |
/**
|
393 |
+
* Unset an attribute on the model.
|
394 |
*
|
395 |
+
* @param string $name The name of an attribute
|
396 |
*/
|
397 |
+
public function __unset($name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
398 |
{
|
399 |
$this->removeAttribute($name);
|
400 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
401 |
}
|
vendor/imangazaliev/didom/src/DiDom/Node.php
ADDED
@@ -0,0 +1,1193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace DiDom;
|
4 |
+
|
5 |
+
use DiDom\Exceptions\InvalidSelectorException;
|
6 |
+
use DOMCdataSection;
|
7 |
+
use DOMComment;
|
8 |
+
use DOMDocument;
|
9 |
+
use DOMDocumentFragment;
|
10 |
+
use DOMElement;
|
11 |
+
use DOMNode;
|
12 |
+
use DOMText;
|
13 |
+
use InvalidArgumentException;
|
14 |
+
use LogicException;
|
15 |
+
use RuntimeException;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @property string $tag
|
19 |
+
*/
|
20 |
+
abstract class Node
|
21 |
+
{
|
22 |
+
/**
|
23 |
+
* The DOM element instance.
|
24 |
+
*
|
25 |
+
* @var DOMElement|DOMText|DOMComment|DOMCdataSection|DOMDocumentFragment
|
26 |
+
*/
|
27 |
+
protected $node;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Adds a new child at the start of the children.
|
31 |
+
*
|
32 |
+
* @param Node|DOMNode|array $nodes The prepended child
|
33 |
+
*
|
34 |
+
* @return Element|Element[]
|
35 |
+
*
|
36 |
+
* @throws LogicException if the current node has no owner document
|
37 |
+
* @throws InvalidArgumentException if one of elements of parameter 1 is not an instance of DOMNode or Element
|
38 |
+
*/
|
39 |
+
public function prependChild($nodes)
|
40 |
+
{
|
41 |
+
if ($this->node->ownerDocument === null) {
|
42 |
+
throw new LogicException('Can not prepend a child to element without the owner document');
|
43 |
+
}
|
44 |
+
|
45 |
+
$returnArray = true;
|
46 |
+
|
47 |
+
if ( ! is_array($nodes)) {
|
48 |
+
$nodes = [$nodes];
|
49 |
+
|
50 |
+
$returnArray = false;
|
51 |
+
}
|
52 |
+
|
53 |
+
$nodes = array_reverse($nodes);
|
54 |
+
|
55 |
+
$result = [];
|
56 |
+
|
57 |
+
$referenceNode = $this->node->firstChild;
|
58 |
+
|
59 |
+
foreach ($nodes as $node) {
|
60 |
+
$result[] = $this->insertBefore($node, $referenceNode);
|
61 |
+
|
62 |
+
$referenceNode = $this->node->firstChild;
|
63 |
+
}
|
64 |
+
|
65 |
+
return $returnArray ? $result : $result[0];
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Adds a new child at the end of the children.
|
70 |
+
*
|
71 |
+
* @param Node|DOMNode|array $nodes The appended child
|
72 |
+
*
|
73 |
+
* @return Element|Element[]
|
74 |
+
*
|
75 |
+
* @throws LogicException if the current node has no owner document
|
76 |
+
* @throws InvalidArgumentException if the provided argument is not an instance of DOMNode or Element
|
77 |
+
*/
|
78 |
+
public function appendChild($nodes)
|
79 |
+
{
|
80 |
+
if ($this->node->ownerDocument === null) {
|
81 |
+
throw new LogicException('Can not append a child to element without the owner document');
|
82 |
+
}
|
83 |
+
|
84 |
+
$returnArray = true;
|
85 |
+
|
86 |
+
if ( ! is_array($nodes)) {
|
87 |
+
$nodes = [$nodes];
|
88 |
+
|
89 |
+
$returnArray = false;
|
90 |
+
}
|
91 |
+
|
92 |
+
$result = [];
|
93 |
+
|
94 |
+
Errors::disable();
|
95 |
+
|
96 |
+
foreach ($nodes as $node) {
|
97 |
+
if ($node instanceof Node) {
|
98 |
+
$node = $node->getNode();
|
99 |
+
}
|
100 |
+
|
101 |
+
if ( ! $node instanceof DOMNode) {
|
102 |
+
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of %s or DOMNode, %s given', __METHOD__, __CLASS__, (is_object($node) ? get_class($node) : gettype($node))));
|
103 |
+
}
|
104 |
+
|
105 |
+
$clonedNode = $node->cloneNode(true);
|
106 |
+
$newNode = $this->node->ownerDocument->importNode($clonedNode, true);
|
107 |
+
|
108 |
+
$result[] = $this->node->appendChild($newNode);
|
109 |
+
}
|
110 |
+
|
111 |
+
Errors::restore();
|
112 |
+
|
113 |
+
$result = array_map(function (DOMNode $node) {
|
114 |
+
return new Element($node);
|
115 |
+
}, $result);
|
116 |
+
|
117 |
+
return $returnArray ? $result : $result[0];
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Adds a new child before a reference node.
|
122 |
+
*
|
123 |
+
* @param Node|DOMNode $node The new node
|
124 |
+
* @param Element|DOMNode|null $referenceNode The reference node
|
125 |
+
*
|
126 |
+
* @return Element
|
127 |
+
*
|
128 |
+
* @throws LogicException if the current node has no owner document
|
129 |
+
* @throws InvalidArgumentException if $node is not an instance of DOMNode or Element
|
130 |
+
* @throws InvalidArgumentException if $referenceNode is not an instance of DOMNode or Element
|
131 |
+
*/
|
132 |
+
public function insertBefore($node, $referenceNode = null)
|
133 |
+
{
|
134 |
+
if ($this->node->ownerDocument === null) {
|
135 |
+
throw new LogicException('Can not insert a child to an element without the owner document');
|
136 |
+
}
|
137 |
+
|
138 |
+
if ($node instanceof Node) {
|
139 |
+
$node = $node->getNode();
|
140 |
+
}
|
141 |
+
|
142 |
+
if ( ! $node instanceof DOMNode) {
|
143 |
+
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of %s or DOMNode, %s given', __METHOD__, __CLASS__, (is_object($node) ? get_class($node) : gettype($node))));
|
144 |
+
}
|
145 |
+
|
146 |
+
if ($referenceNode !== null) {
|
147 |
+
if ($referenceNode instanceof Element) {
|
148 |
+
$referenceNode = $referenceNode->getNode();
|
149 |
+
}
|
150 |
+
|
151 |
+
if ( ! $referenceNode instanceof DOMNode) {
|
152 |
+
throw new InvalidArgumentException(sprintf('Argument 2 passed to %s must be an instance of %s or DOMNode, %s given', __METHOD__, __CLASS__, (is_object($referenceNode) ? get_class($referenceNode) : gettype($referenceNode))));
|
153 |
+
}
|
154 |
+
}
|
155 |
+
|
156 |
+
Errors::disable();
|
157 |
+
|
158 |
+
$clonedNode = $node->cloneNode(true);
|
159 |
+
$newNode = $this->node->ownerDocument->importNode($clonedNode, true);
|
160 |
+
|
161 |
+
$insertedNode = $this->node->insertBefore($newNode, $referenceNode);
|
162 |
+
|
163 |
+
Errors::restore();
|
164 |
+
|
165 |
+
return new Element($insertedNode);
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Adds a new child after a reference node.
|
170 |
+
*
|
171 |
+
* @param Node|DOMNode $node The new node
|
172 |
+
* @param Element|DOMNode|null $referenceNode The reference node
|
173 |
+
*
|
174 |
+
* @return Element
|
175 |
+
*
|
176 |
+
* @throws LogicException if the current node has no owner document
|
177 |
+
* @throws InvalidArgumentException if $node is not an instance of DOMNode or Element
|
178 |
+
* @throws InvalidArgumentException if $referenceNode is not an instance of DOMNode or Element
|
179 |
+
*/
|
180 |
+
public function insertAfter($node, $referenceNode = null)
|
181 |
+
{
|
182 |
+
if ($referenceNode === null) {
|
183 |
+
return $this->insertBefore($node);
|
184 |
+
}
|
185 |
+
|
186 |
+
if ($referenceNode instanceof Node) {
|
187 |
+
$referenceNode = $referenceNode->getNode();
|
188 |
+
}
|
189 |
+
|
190 |
+
if ( ! $referenceNode instanceof DOMNode) {
|
191 |
+
throw new InvalidArgumentException(sprintf('Argument 2 passed to %s must be an instance of %s or DOMNode, %s given', __METHOD__, __CLASS__, (is_object($referenceNode) ? get_class($referenceNode) : gettype($referenceNode))));
|
192 |
+
}
|
193 |
+
|
194 |
+
return $this->insertBefore($node, $referenceNode->nextSibling);
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Adds a new sibling before a reference node.
|
199 |
+
*
|
200 |
+
* @param Node|DOMNode $node The new node
|
201 |
+
*
|
202 |
+
* @return Element
|
203 |
+
*
|
204 |
+
* @throws LogicException if the current node has no owner document
|
205 |
+
* @throws InvalidArgumentException if $node is not an instance of DOMNode or Element
|
206 |
+
* @throws InvalidArgumentException if $referenceNode is not an instance of DOMNode or Element
|
207 |
+
*/
|
208 |
+
public function insertSiblingBefore($node)
|
209 |
+
{
|
210 |
+
if ($this->node->ownerDocument === null) {
|
211 |
+
throw new LogicException('Can not insert a child to an element without the owner document');
|
212 |
+
}
|
213 |
+
|
214 |
+
if ($this->parent() === null) {
|
215 |
+
throw new LogicException('Can not insert a child to an element without the parent element');
|
216 |
+
}
|
217 |
+
|
218 |
+
if ($node instanceof Node) {
|
219 |
+
$node = $node->getNode();
|
220 |
+
}
|
221 |
+
|
222 |
+
if ( ! $node instanceof DOMNode) {
|
223 |
+
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of %s or DOMNode, %s given', __METHOD__, __CLASS__, (is_object($node) ? get_class($node) : gettype($node))));
|
224 |
+
}
|
225 |
+
|
226 |
+
Errors::disable();
|
227 |
+
|
228 |
+
$clonedNode = $node->cloneNode(true);
|
229 |
+
$newNode = $this->node->ownerDocument->importNode($clonedNode, true);
|
230 |
+
|
231 |
+
$insertedNode = $this->parent()->getNode()->insertBefore($newNode, $this->node);
|
232 |
+
|
233 |
+
Errors::restore();
|
234 |
+
|
235 |
+
return new Element($insertedNode);
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Adds a new sibling after a reference node.
|
240 |
+
*
|
241 |
+
* @param Node|DOMNode $node The new node
|
242 |
+
*
|
243 |
+
* @return Element
|
244 |
+
*
|
245 |
+
* @throws LogicException if the current node has no owner document
|
246 |
+
* @throws InvalidArgumentException if $node is not an instance of DOMNode or Element
|
247 |
+
* @throws InvalidArgumentException if $referenceNode is not an instance of DOMNode or Element
|
248 |
+
*/
|
249 |
+
public function insertSiblingAfter($node)
|
250 |
+
{
|
251 |
+
if ($this->node->ownerDocument === null) {
|
252 |
+
throw new LogicException('Can not insert a child to an element without the owner document');
|
253 |
+
}
|
254 |
+
|
255 |
+
if ($this->parent() === null) {
|
256 |
+
throw new LogicException('Can not insert a child to an element without the parent element');
|
257 |
+
}
|
258 |
+
|
259 |
+
$nextSibling = $this->nextSibling();
|
260 |
+
|
261 |
+
// if the current node is the last child
|
262 |
+
if ($nextSibling === null) {
|
263 |
+
return $this->parent()->appendChild($node);
|
264 |
+
}
|
265 |
+
|
266 |
+
return $nextSibling->insertSiblingBefore($node);
|
267 |
+
}
|
268 |
+
|
269 |
+
/**
|
270 |
+
* Checks the existence of the node.
|
271 |
+
*
|
272 |
+
* @param string $expression XPath expression or CSS selector
|
273 |
+
* @param string $type The type of the expression
|
274 |
+
*
|
275 |
+
* @return bool
|
276 |
+
*/
|
277 |
+
public function has($expression, $type = Query::TYPE_CSS)
|
278 |
+
{
|
279 |
+
return $this->toDocument()->has($expression, $type);
|
280 |
+
}
|
281 |
+
|
282 |
+
/**
|
283 |
+
* Searches for an node in the DOM tree for a given XPath expression or a CSS selector.
|
284 |
+
*
|
285 |
+
* @param string $expression XPath expression or a CSS selector
|
286 |
+
* @param string $type The type of the expression
|
287 |
+
* @param bool $wrapElement Returns array of Element if true, otherwise array of DOMElement
|
288 |
+
*
|
289 |
+
* @return Element[]|DOMElement[]
|
290 |
+
*
|
291 |
+
* @throws InvalidSelectorException
|
292 |
+
*/
|
293 |
+
public function find($expression, $type = Query::TYPE_CSS, $wrapElement = true)
|
294 |
+
{
|
295 |
+
return $this->toDocument()->find($expression, $type, $wrapElement);
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Searches for an node in the owner document using current node as context.
|
300 |
+
*
|
301 |
+
* @param string $expression XPath expression or a CSS selector
|
302 |
+
* @param string $type The type of the expression
|
303 |
+
* @param bool $wrapNode Returns array of Element if true, otherwise array of DOMElement
|
304 |
+
*
|
305 |
+
* @return Element[]|DOMElement[]
|
306 |
+
*
|
307 |
+
* @throws LogicException if the current node has no owner document
|
308 |
+
* @throws InvalidSelectorException
|
309 |
+
*/
|
310 |
+
public function findInDocument($expression, $type = Query::TYPE_CSS, $wrapNode = true)
|
311 |
+
{
|
312 |
+
$ownerDocument = $this->getDocument();
|
313 |
+
|
314 |
+
if ($ownerDocument === null) {
|
315 |
+
throw new LogicException('Can not search in context without the owner document');
|
316 |
+
}
|
317 |
+
|
318 |
+
return $ownerDocument->find($expression, $type, $wrapNode, $this->node);
|
319 |
+
}
|
320 |
+
|
321 |
+
/**
|
322 |
+
* Searches for an node in the DOM tree and returns first element or null.
|
323 |
+
*
|
324 |
+
* @param string $expression XPath expression or a CSS selector
|
325 |
+
* @param string $type The type of the expression
|
326 |
+
* @param bool $wrapNode Returns Element if true, otherwise DOMElement
|
327 |
+
*
|
328 |
+
* @return Element|DOMElement|null
|
329 |
+
*
|
330 |
+
* @throws InvalidSelectorException
|
331 |
+
*/
|
332 |
+
public function first($expression, $type = Query::TYPE_CSS, $wrapNode = true)
|
333 |
+
{
|
334 |
+
return $this->toDocument()->first($expression, $type, $wrapNode);
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
* Searches for an node in the owner document using current node as context and returns first element or null.
|
339 |
+
*
|
340 |
+
* @param string $expression XPath expression or a CSS selector
|
341 |
+
* @param string $type The type of the expression
|
342 |
+
* @param bool $wrapNode Returns Element if true, otherwise DOMElement
|
343 |
+
*
|
344 |
+
* @return Element|DOMElement|null
|
345 |
+
*
|
346 |
+
* @throws InvalidSelectorException
|
347 |
+
*/
|
348 |
+
public function firstInDocument($expression, $type = Query::TYPE_CSS, $wrapNode = true)
|
349 |
+
{
|
350 |
+
$ownerDocument = $this->getDocument();
|
351 |
+
|
352 |
+
if ($ownerDocument === null) {
|
353 |
+
throw new LogicException('Can not search in context without the owner document');
|
354 |
+
}
|
355 |
+
|
356 |
+
return $ownerDocument->first($expression, $type, $wrapNode, $this->node);
|
357 |
+
}
|
358 |
+
|
359 |
+
/**
|
360 |
+
* Searches for an node in the DOM tree for a given XPath expression.
|
361 |
+
*
|
362 |
+
* @param string $expression XPath expression
|
363 |
+
* @param bool $wrapNode Returns array of Element if true, otherwise array of DOMElement
|
364 |
+
*
|
365 |
+
* @return Element[]|DOMElement[]
|
366 |
+
*
|
367 |
+
* @throws InvalidSelectorException
|
368 |
+
*/
|
369 |
+
public function xpath($expression, $wrapNode = true)
|
370 |
+
{
|
371 |
+
return $this->find($expression, Query::TYPE_XPATH, $wrapNode);
|
372 |
+
}
|
373 |
+
|
374 |
+
/**
|
375 |
+
* Counts nodes for a given XPath expression or a CSS selector.
|
376 |
+
*
|
377 |
+
* @param string $expression XPath expression or CSS selector
|
378 |
+
* @param string $type The type of the expression
|
379 |
+
*
|
380 |
+
* @return int
|
381 |
+
*
|
382 |
+
* @throws InvalidSelectorException
|
383 |
+
*/
|
384 |
+
public function count($expression, $type = Query::TYPE_CSS)
|
385 |
+
{
|
386 |
+
return $this->toDocument()->count($expression, $type);
|
387 |
+
}
|
388 |
+
|
389 |
+
/**
|
390 |
+
* Dumps the node into a string using HTML formatting (including child nodes).
|
391 |
+
*
|
392 |
+
* @return string
|
393 |
+
*/
|
394 |
+
public function html()
|
395 |
+
{
|
396 |
+
return $this->toDocument()->html();
|
397 |
+
}
|
398 |
+
|
399 |
+
/**
|
400 |
+
* Dumps the node into a string using HTML formatting (without child nodes).
|
401 |
+
*
|
402 |
+
* @return string
|
403 |
+
*/
|
404 |
+
public function outerHtml()
|
405 |
+
{
|
406 |
+
$document = new DOMDocument();
|
407 |
+
|
408 |
+
$importedNode = $document->importNode($this->node);
|
409 |
+
|
410 |
+
return $document->saveHTML($importedNode);
|
411 |
+
}
|
412 |
+
|
413 |
+
/**
|
414 |
+
* Dumps the node descendants into a string using HTML formatting.
|
415 |
+
*
|
416 |
+
* @param string $delimiter
|
417 |
+
*
|
418 |
+
* @return string
|
419 |
+
*/
|
420 |
+
public function innerHtml($delimiter = '')
|
421 |
+
{
|
422 |
+
$innerHtml = [];
|
423 |
+
|
424 |
+
foreach ($this->node->childNodes as $childNode) {
|
425 |
+
$innerHtml[] = $childNode->ownerDocument->saveHTML($childNode);
|
426 |
+
}
|
427 |
+
|
428 |
+
return implode($delimiter, $innerHtml);
|
429 |
+
}
|
430 |
+
|
431 |
+
/**
|
432 |
+
* Dumps the node descendants into a string using XML formatting.
|
433 |
+
*
|
434 |
+
* @param string $delimiter
|
435 |
+
*
|
436 |
+
* @return string
|
437 |
+
*/
|
438 |
+
public function innerXml($delimiter = '')
|
439 |
+
{
|
440 |
+
$innerXml = [];
|
441 |
+
|
442 |
+
foreach ($this->node->childNodes as $childNode) {
|
443 |
+
$innerXml[] = $childNode->ownerDocument->saveXML($childNode);
|
444 |
+
}
|
445 |
+
|
446 |
+
return implode($delimiter, $innerXml);
|
447 |
+
}
|
448 |
+
|
449 |
+
/**
|
450 |
+
* Sets inner HTML.
|
451 |
+
*
|
452 |
+
* @param string $html
|
453 |
+
*
|
454 |
+
* @return static
|
455 |
+
*
|
456 |
+
* @throws InvalidArgumentException if passed argument is not a string
|
457 |
+
* @throws InvalidSelectorException
|
458 |
+
*/
|
459 |
+
public function setInnerHtml($html)
|
460 |
+
{
|
461 |
+
if ( ! is_string($html)) {
|
462 |
+
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($html) ? get_class($html) : gettype($html))));
|
463 |
+
}
|
464 |
+
|
465 |
+
$this->removeChildren();
|
466 |
+
|
467 |
+
if ($html !== '') {
|
468 |
+
Errors::disable();
|
469 |
+
|
470 |
+
$html = "<htmlfragment>$html</htmlfragment>";
|
471 |
+
|
472 |
+
$document = new Document($html);
|
473 |
+
|
474 |
+
$fragment = $document->first('htmlfragment')->getNode();
|
475 |
+
|
476 |
+
foreach ($fragment->childNodes as $node) {
|
477 |
+
$newNode = $this->node->ownerDocument->importNode($node, true);
|
478 |
+
|
479 |
+
$this->node->appendChild($newNode);
|
480 |
+
}
|
481 |
+
|
482 |
+
Errors::restore();
|
483 |
+
}
|
484 |
+
|
485 |
+
return $this;
|
486 |
+
}
|
487 |
+
|
488 |
+
/**
|
489 |
+
* Dumps the node into a string using XML formatting.
|
490 |
+
*
|
491 |
+
* @param int $options Additional options
|
492 |
+
*
|
493 |
+
* @return string The node XML
|
494 |
+
*/
|
495 |
+
public function xml($options = 0)
|
496 |
+
{
|
497 |
+
return $this->toDocument()->xml($options);
|
498 |
+
}
|
499 |
+
|
500 |
+
/**
|
501 |
+
* Get the text content of this node and its descendants.
|
502 |
+
*
|
503 |
+
* @return string The node value
|
504 |
+
*/
|
505 |
+
public function text()
|
506 |
+
{
|
507 |
+
return $this->node->textContent;
|
508 |
+
}
|
509 |
+
|
510 |
+
/**
|
511 |
+
* Set the value of this node.
|
512 |
+
*
|
513 |
+
* @param string $value The new value of the node
|
514 |
+
*
|
515 |
+
* @return static
|
516 |
+
*
|
517 |
+
* @throws InvalidArgumentException if parameter 1 is not a string
|
518 |
+
*/
|
519 |
+
public function setValue($value)
|
520 |
+
{
|
521 |
+
if (is_numeric($value)) {
|
522 |
+
$value = (string) $value;
|
523 |
+
}
|
524 |
+
|
525 |
+
if ( ! is_string($value) && $value !== null) {
|
526 |
+
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($value) ? get_class($value) : gettype($value))));
|
527 |
+
}
|
528 |
+
|
529 |
+
$this->node->nodeValue = $value;
|
530 |
+
|
531 |
+
return $this;
|
532 |
+
}
|
533 |
+
|
534 |
+
/**
|
535 |
+
* Returns true if the current node is a DOMElement instance.
|
536 |
+
*
|
537 |
+
* @return bool
|
538 |
+
*/
|
539 |
+
public function isElementNode()
|
540 |
+
{
|
541 |
+
return $this->node instanceof DOMElement;
|
542 |
+
}
|
543 |
+
|
544 |
+
/**
|
545 |
+
* Returns true if the current node is a a DOMText instance.
|
546 |
+
*
|
547 |
+
* @return bool
|
548 |
+
*/
|
549 |
+
public function isTextNode()
|
550 |
+
{
|
551 |
+
return $this->node instanceof DOMText;
|
552 |
+
}
|
553 |
+
|
554 |
+
/**
|
555 |
+
* Returns true if the current node is a DOMComment instance.
|
556 |
+
*
|
557 |
+
* @return bool
|
558 |
+
*/
|
559 |
+
public function isCommentNode()
|
560 |
+
{
|
561 |
+
return $this->node instanceof DOMComment;
|
562 |
+
}
|
563 |
+
|
564 |
+
/**
|
565 |
+
* Returns true if the current node is a DOMCdataSection instance.
|
566 |
+
*
|
567 |
+
* @return bool
|
568 |
+
*/
|
569 |
+
public function isCdataSectionNode()
|
570 |
+
{
|
571 |
+
return $this->node instanceof DOMCdataSection;
|
572 |
+
}
|
573 |
+
|
574 |
+
/**
|
575 |
+
* Indicates if two nodes are the same node.
|
576 |
+
*
|
577 |
+
* @param Element|DOMNode $node
|
578 |
+
*
|
579 |
+
* @return bool
|
580 |
+
*
|
581 |
+
* @throws InvalidArgumentException if parameter 1 is not an instance of DOMNode
|
582 |
+
*/
|
583 |
+
public function is($node)
|
584 |
+
{
|
585 |
+
if ($node instanceof Node) {
|
586 |
+
$node = $node->getNode();
|
587 |
+
}
|
588 |
+
|
589 |
+
if ( ! $node instanceof DOMNode) {
|
590 |
+
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of %s or DOMNode, %s given', __METHOD__, __CLASS__, (is_object($node) ? get_class($node) : gettype($node))));
|
591 |
+
}
|
592 |
+
|
593 |
+
return $this->node->isSameNode($node);
|
594 |
+
}
|
595 |
+
|
596 |
+
/**
|
597 |
+
* @return Element|Document|null
|
598 |
+
*/
|
599 |
+
public function parent()
|
600 |
+
{
|
601 |
+
if ($this->node->parentNode === null) {
|
602 |
+
return null;
|
603 |
+
}
|
604 |
+
|
605 |
+
if ($this->node->parentNode instanceof DOMDocument) {
|
606 |
+
return new Document($this->node->parentNode);
|
607 |
+
}
|
608 |
+
|
609 |
+
return new Element($this->node->parentNode);
|
610 |
+
}
|
611 |
+
|
612 |
+
/**
|
613 |
+
* Returns first parent node matches passed selector.
|
614 |
+
*
|
615 |
+
* @param string $selector
|
616 |
+
* @param bool $strict
|
617 |
+
*
|
618 |
+
* @return Element|null
|
619 |
+
*
|
620 |
+
* @throws InvalidSelectorException if the selector is invalid
|
621 |
+
*/
|
622 |
+
public function closest($selector, $strict = false)
|
623 |
+
{
|
624 |
+
$node = $this;
|
625 |
+
|
626 |
+
while (true) {
|
627 |
+
$parent = $node->parent();
|
628 |
+
|
629 |
+
if ($parent === null || $parent instanceof Document) {
|
630 |
+
return null;
|
631 |
+
}
|
632 |
+
|
633 |
+
if ($parent->matches($selector, $strict)) {
|
634 |
+
return $parent;
|
635 |
+
}
|
636 |
+
|
637 |
+
$node = $parent;
|
638 |
+
}
|
639 |
+
|
640 |
+
return null;
|
641 |
+
}
|
642 |
+
|
643 |
+
/**
|
644 |
+
* @param string|null $selector
|
645 |
+
* @param string|null $nodeType
|
646 |
+
*
|
647 |
+
* @return Element|null
|
648 |
+
*
|
649 |
+
* @throws InvalidArgumentException if parameter 2 is not a string
|
650 |
+
* @throws RuntimeException if the node type is invalid
|
651 |
+
* @throws LogicException if the selector used with non DOMElement node type
|
652 |
+
* @throws InvalidSelectorException if the selector is invalid
|
653 |
+
*/
|
654 |
+
public function previousSibling($selector = null, $nodeType = null)
|
655 |
+
{
|
656 |
+
if ($this->node->previousSibling === null) {
|
657 |
+
return null;
|
658 |
+
}
|
659 |
+
|
660 |
+
if ($selector === null && $nodeType === null) {
|
661 |
+
return new Element($this->node->previousSibling);
|
662 |
+
}
|
663 |
+
|
664 |
+
if ($selector !== null && $nodeType === null) {
|
665 |
+
$nodeType = 'DOMElement';
|
666 |
+
}
|
667 |
+
|
668 |
+
if ( ! is_string($nodeType)) {
|
669 |
+
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($nodeType)));
|
670 |
+
}
|
671 |
+
|
672 |
+
$allowedTypes = ['DOMElement', 'DOMText', 'DOMComment', 'DOMCdataSection'];
|
673 |
+
|
674 |
+
if ( ! in_array($nodeType, $allowedTypes, true)) {
|
675 |
+
throw new RuntimeException(sprintf('Unknown node type "%s". Allowed types: %s', $nodeType, implode(', ', $allowedTypes)));
|
676 |
+
}
|
677 |
+
|
678 |
+
if ($selector !== null && $nodeType !== 'DOMElement') {
|
679 |
+
throw new LogicException(sprintf('Selector can be used only with DOMElement node type, %s given', $nodeType));
|
680 |
+
}
|
681 |
+
|
682 |
+
$node = $this->node->previousSibling;
|
683 |
+
|
684 |
+
while ($node !== null) {
|
685 |
+
if (get_class($node) !== $nodeType) {
|
686 |
+
$node = $node->previousSibling;
|
687 |
+
|
688 |
+
continue;
|
689 |
+
}
|
690 |
+
|
691 |
+
$element = new Element($node);
|
692 |
+
|
693 |
+
if ($selector === null) {
|
694 |
+
return $element;
|
695 |
+
}
|
696 |
+
|
697 |
+
if ($element->matches($selector)) {
|
698 |
+
return $element;
|
699 |
+
}
|
700 |
+
|
701 |
+
$node = $node->previousSibling;
|
702 |
+
}
|
703 |
+
|
704 |
+
return new Element($this->node->previousSibling);
|
705 |
+
}
|
706 |
+
|
707 |
+
/**
|
708 |
+
* @param string|null $selector
|
709 |
+
* @param string|null $nodeType
|
710 |
+
*
|
711 |
+
* @return Element[]
|
712 |
+
*
|
713 |
+
* @throws InvalidArgumentException if parameter 2 is not a string
|
714 |
+
* @throws RuntimeException if the node type is invalid
|
715 |
+
* @throws LogicException if the selector used with non DOMElement node type
|
716 |
+
* @throws InvalidSelectorException if the selector is invalid
|
717 |
+
*/
|
718 |
+
public function previousSiblings($selector = null, $nodeType = null)
|
719 |
+
{
|
720 |
+
if ($this->node->previousSibling === null) {
|
721 |
+
return [];
|
722 |
+
}
|
723 |
+
|
724 |
+
if ($selector !== null && $nodeType === null) {
|
725 |
+
$nodeType = 'DOMElement';
|
726 |
+
}
|
727 |
+
|
728 |
+
if ($nodeType !== null) {
|
729 |
+
if ( ! is_string($nodeType)) {
|
730 |
+
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($nodeType)));
|
731 |
+
}
|
732 |
+
|
733 |
+
$allowedTypes = ['DOMElement', 'DOMText', 'DOMComment', 'DOMCdataSection'];
|
734 |
+
|
735 |
+
if ( ! in_array($nodeType, $allowedTypes, true)) {
|
736 |
+
throw new RuntimeException(sprintf('Unknown node type "%s". Allowed types: %s', $nodeType, implode(', ', $allowedTypes)));
|
737 |
+
}
|
738 |
+
}
|
739 |
+
|
740 |
+
if ($selector !== null && $nodeType !== 'DOMElement') {
|
741 |
+
throw new LogicException(sprintf('Selector can be used only with DOMElement node type, %s given', $nodeType));
|
742 |
+
}
|
743 |
+
|
744 |
+
$result = [];
|
745 |
+
|
746 |
+
$node = $this->node->previousSibling;
|
747 |
+
|
748 |
+
while ($node !== null) {
|
749 |
+
$element = new Element($node);
|
750 |
+
|
751 |
+
if ($nodeType === null) {
|
752 |
+
$result[] = $element;
|
753 |
+
|
754 |
+
$node = $node->previousSibling;
|
755 |
+
|
756 |
+
continue;
|
757 |
+
}
|
758 |
+
|
759 |
+
if (get_class($node) !== $nodeType) {
|
760 |
+
$node = $node->previousSibling;
|
761 |
+
|
762 |
+
continue;
|
763 |
+
}
|
764 |
+
|
765 |
+
if ($selector === null) {
|
766 |
+
$result[] = $element;
|
767 |
+
|
768 |
+
$node = $node->previousSibling;
|
769 |
+
|
770 |
+
continue;
|
771 |
+
}
|
772 |
+
|
773 |
+
if ($element->matches($selector)) {
|
774 |
+
$result[] = $element;
|
775 |
+
}
|
776 |
+
|
777 |
+
$node = $node->previousSibling;
|
778 |
+
}
|
779 |
+
|
780 |
+
return array_reverse($result);
|
781 |
+
}
|
782 |
+
|
783 |
+
/**
|
784 |
+
* @param string|null $selector
|
785 |
+
* @param string|null $nodeType
|
786 |
+
*
|
787 |
+
* @return Element|null
|
788 |
+
*
|
789 |
+
* @throws InvalidArgumentException if parameter 2 is not a string
|
790 |
+
* @throws RuntimeException if the node type is invalid
|
791 |
+
* @throws LogicException if the selector used with non DOMElement node type
|
792 |
+
* @throws InvalidSelectorException if the selector is invalid
|
793 |
+
*/
|
794 |
+
public function nextSibling($selector = null, $nodeType = null)
|
795 |
+
{
|
796 |
+
if ($this->node->nextSibling === null) {
|
797 |
+
return null;
|
798 |
+
}
|
799 |
+
|
800 |
+
if ($selector === null && $nodeType === null) {
|
801 |
+
return new Element($this->node->nextSibling);
|
802 |
+
}
|
803 |
+
|
804 |
+
if ($selector !== null && $nodeType === null) {
|
805 |
+
$nodeType = 'DOMElement';
|
806 |
+
}
|
807 |
+
|
808 |
+
if ( ! is_string($nodeType)) {
|
809 |
+
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($nodeType)));
|
810 |
+
}
|
811 |
+
|
812 |
+
$allowedTypes = ['DOMElement', 'DOMText', 'DOMComment', 'DOMCdataSection'];
|
813 |
+
|
814 |
+
if ( ! in_array($nodeType, $allowedTypes, true)) {
|
815 |
+
throw new RuntimeException(sprintf('Unknown node type "%s". Allowed types: %s', $nodeType, implode(', ', $allowedTypes)));
|
816 |
+
}
|
817 |
+
|
818 |
+
if ($selector !== null && $nodeType !== 'DOMElement') {
|
819 |
+
throw new LogicException(sprintf('Selector can be used only with DOMElement node type, %s given', $nodeType));
|
820 |
+
}
|
821 |
+
|
822 |
+
$node = $this->node->nextSibling;
|
823 |
+
|
824 |
+
while ($node !== null) {
|
825 |
+
if (get_class($node) !== $nodeType) {
|
826 |
+
$node = $node->nextSibling;
|
827 |
+
|
828 |
+
continue;
|
829 |
+
}
|
830 |
+
|
831 |
+
$element = new Element($node);
|
832 |
+
|
833 |
+
if ($selector === null) {
|
834 |
+
return $element;
|
835 |
+
}
|
836 |
+
|
837 |
+
if ($element->matches($selector)) {
|
838 |
+
return $element;
|
839 |
+
}
|
840 |
+
|
841 |
+
$node = $node->nextSibling;
|
842 |
+
}
|
843 |
+
|
844 |
+
return null;
|
845 |
+
}
|
846 |
+
|
847 |
+
/**
|
848 |
+
* @param string|null $selector
|
849 |
+
* @param string $nodeType
|
850 |
+
*
|
851 |
+
* @return Element[]
|
852 |
+
*
|
853 |
+
* @throws InvalidArgumentException if parameter 2 is not a string
|
854 |
+
* @throws RuntimeException if the node type is invalid
|
855 |
+
* @throws LogicException if the selector used with non DOMElement node type
|
856 |
+
* @throws InvalidSelectorException if the selector is invalid
|
857 |
+
*/
|
858 |
+
public function nextSiblings($selector = null, $nodeType = null)
|
859 |
+
{
|
860 |
+
if ($this->node->nextSibling === null) {
|
861 |
+
return [];
|
862 |
+
}
|
863 |
+
|
864 |
+
if ($selector !== null && $nodeType === null) {
|
865 |
+
$nodeType = 'DOMElement';
|
866 |
+
}
|
867 |
+
|
868 |
+
if ($nodeType !== null) {
|
869 |
+
if ( ! is_string($nodeType)) {
|
870 |
+
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($nodeType)));
|
871 |
+
}
|
872 |
+
|
873 |
+
$allowedTypes = ['DOMElement', 'DOMText', 'DOMComment', 'DOMCdataSection'];
|
874 |
+
|
875 |
+
if ( ! in_array($nodeType, $allowedTypes, true)) {
|
876 |
+
throw new RuntimeException(sprintf('Unknown node type "%s". Allowed types: %s', $nodeType, implode(', ', $allowedTypes)));
|
877 |
+
}
|
878 |
+
}
|
879 |
+
|
880 |
+
if ($selector !== null && $nodeType !== 'DOMElement') {
|
881 |
+
throw new LogicException(sprintf('Selector can be used only with DOMElement node type, %s given', $nodeType));
|
882 |
+
}
|
883 |
+
|
884 |
+
$result = [];
|
885 |
+
|
886 |
+
$node = $this->node->nextSibling;
|
887 |
+
|
888 |
+
while ($node !== null) {
|
889 |
+
$element = new Element($node);
|
890 |
+
|
891 |
+
if ($nodeType === null) {
|
892 |
+
$result[] = $element;
|
893 |
+
|
894 |
+
$node = $node->nextSibling;
|
895 |
+
|
896 |
+
continue;
|
897 |
+
}
|
898 |
+
|
899 |
+
if (get_class($node) !== $nodeType) {
|
900 |
+
$node = $node->nextSibling;
|
901 |
+
|
902 |
+
continue;
|
903 |
+
}
|
904 |
+
|
905 |
+
if ($selector === null) {
|
906 |
+
$result[] = $element;
|
907 |
+
|
908 |
+
$node = $node->nextSibling;
|
909 |
+
|
910 |
+
continue;
|
911 |
+
}
|
912 |
+
|
913 |
+
if ($element->matches($selector)) {
|
914 |
+
$result[] = $element;
|
915 |
+
}
|
916 |
+
|
917 |
+
$node = $node->nextSibling;
|
918 |
+
}
|
919 |
+
|
920 |
+
return $result;
|
921 |
+
}
|
922 |
+
|
923 |
+
/**
|
924 |
+
* @param int $index
|
925 |
+
*
|
926 |
+
* @return Element|null
|
927 |
+
*/
|
928 |
+
public function child($index)
|
929 |
+
{
|
930 |
+
$child = $this->node->childNodes->item($index);
|
931 |
+
|
932 |
+
return $child === null ? null : new Element($child);
|
933 |
+
}
|
934 |
+
|
935 |
+
/**
|
936 |
+
* @return Element|null
|
937 |
+
*/
|
938 |
+
public function firstChild()
|
939 |
+
{
|
940 |
+
if ($this->node->firstChild === null) {
|
941 |
+
return null;
|
942 |
+
}
|
943 |
+
|
944 |
+
return new Element($this->node->firstChild);
|
945 |
+
}
|
946 |
+
|
947 |
+
/**
|
948 |
+
* @return Element|null
|
949 |
+
*/
|
950 |
+
public function lastChild()
|
951 |
+
{
|
952 |
+
if ($this->node->lastChild === null) {
|
953 |
+
return null;
|
954 |
+
}
|
955 |
+
|
956 |
+
return new Element($this->node->lastChild);
|
957 |
+
}
|
958 |
+
|
959 |
+
/**
|
960 |
+
* @return bool
|
961 |
+
*/
|
962 |
+
public function hasChildren()
|
963 |
+
{
|
964 |
+
return $this->node->hasChildNodes();
|
965 |
+
}
|
966 |
+
|
967 |
+
/**
|
968 |
+
* @return Element[]
|
969 |
+
*/
|
970 |
+
public function children()
|
971 |
+
{
|
972 |
+
$children = [];
|
973 |
+
|
974 |
+
foreach ($this->node->childNodes as $node) {
|
975 |
+
$children[] = new Element($node);
|
976 |
+
}
|
977 |
+
|
978 |
+
return $children;
|
979 |
+
}
|
980 |
+
|
981 |
+
/**
|
982 |
+
* Removes child from list of children.
|
983 |
+
*
|
984 |
+
* @param Node|DOMNode $childNode
|
985 |
+
*
|
986 |
+
* @return Element the node that has been removed
|
987 |
+
*/
|
988 |
+
public function removeChild($childNode)
|
989 |
+
{
|
990 |
+
if ($childNode instanceof Node) {
|
991 |
+
$childNode = $childNode->getNode();
|
992 |
+
}
|
993 |
+
|
994 |
+
if ( ! $childNode instanceof DOMNode) {
|
995 |
+
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of %s or DOMNode, %s given', __METHOD__, __CLASS__, (is_object($childNode) ? get_class($childNode) : gettype($childNode))));
|
996 |
+
}
|
997 |
+
|
998 |
+
$removedNode = $this->node->removeChild($childNode);
|
999 |
+
|
1000 |
+
return new Element($removedNode);
|
1001 |
+
}
|
1002 |
+
|
1003 |
+
/**
|
1004 |
+
* Removes all child nodes.
|
1005 |
+
*
|
1006 |
+
* @return Element[] the nodes that has been removed
|
1007 |
+
*/
|
1008 |
+
public function removeChildren()
|
1009 |
+
{
|
1010 |
+
// we need to collect child nodes to array
|
1011 |
+
// because removing nodes from the DOMNodeList on iterating is not working
|
1012 |
+
$childNodes = [];
|
1013 |
+
|
1014 |
+
foreach ($this->node->childNodes as $childNode) {
|
1015 |
+
$childNodes[] = $childNode;
|
1016 |
+
}
|
1017 |
+
|
1018 |
+
$removedNodes = [];
|
1019 |
+
|
1020 |
+
foreach ($childNodes as $childNode) {
|
1021 |
+
$removedNode = $this->node->removeChild($childNode);
|
1022 |
+
|
1023 |
+
$removedNodes[] = new Element($removedNode);
|
1024 |
+
}
|
1025 |
+
|
1026 |
+
return $removedNodes;
|
1027 |
+
}
|
1028 |
+
|
1029 |
+
/**
|
1030 |
+
* Removes current node from the parent.
|
1031 |
+
*
|
1032 |
+
* @return Element the node that has been removed
|
1033 |
+
*
|
1034 |
+
* @throws LogicException if the current node has no parent node
|
1035 |
+
*/
|
1036 |
+
public function remove()
|
1037 |
+
{
|
1038 |
+
if ($this->node->parentNode === null) {
|
1039 |
+
throw new LogicException('Can not remove an element without the parent node');
|
1040 |
+
}
|
1041 |
+
|
1042 |
+
$removedNode = $this->node->parentNode->removeChild($this->node);
|
1043 |
+
|
1044 |
+
return new Element($removedNode);
|
1045 |
+
}
|
1046 |
+
|
1047 |
+
/**
|
1048 |
+
* Replaces a child.
|
1049 |
+
*
|
1050 |
+
* @param Node|DOMNode $newNode The new node
|
1051 |
+
* @param bool $clone Clone the node if true, otherwise move it
|
1052 |
+
*
|
1053 |
+
* @return Element The node that has been replaced
|
1054 |
+
*
|
1055 |
+
* @throws LogicException if the current node has no parent node
|
1056 |
+
*/
|
1057 |
+
public function replace($newNode, $clone = true)
|
1058 |
+
{
|
1059 |
+
if ($this->node->parentNode === null) {
|
1060 |
+
throw new LogicException('Can not replace an element without the parent node');
|
1061 |
+
}
|
1062 |
+
|
1063 |
+
if ($newNode instanceof Node) {
|
1064 |
+
$newNode = $newNode->getNode();
|
1065 |
+
}
|
1066 |
+
|
1067 |
+
if ( ! $newNode instanceof DOMNode) {
|
1068 |
+
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of %s or DOMNode, %s given', __METHOD__, __CLASS__, (is_object($newNode) ? get_class($newNode) : gettype($newNode))));
|
1069 |
+
}
|
1070 |
+
|
1071 |
+
if ($clone) {
|
1072 |
+
$newNode = $newNode->cloneNode(true);
|
1073 |
+
}
|
1074 |
+
|
1075 |
+
if ($newNode->ownerDocument === null || ! $this->getDocument()->is($newNode->ownerDocument)) {
|
1076 |
+
$newNode = $this->node->ownerDocument->importNode($newNode, true);
|
1077 |
+
}
|
1078 |
+
|
1079 |
+
$node = $this->node->parentNode->replaceChild($newNode, $this->node);
|
1080 |
+
|
1081 |
+
return new Element($node);
|
1082 |
+
}
|
1083 |
+
|
1084 |
+
/**
|
1085 |
+
* Get line number for a node.
|
1086 |
+
*
|
1087 |
+
* @return int
|
1088 |
+
*/
|
1089 |
+
public function getLineNo()
|
1090 |
+
{
|
1091 |
+
return $this->node->getLineNo();
|
1092 |
+
}
|
1093 |
+
|
1094 |
+
/**
|
1095 |
+
* Clones a node.
|
1096 |
+
*
|
1097 |
+
* @param bool $deep Indicates whether to copy all descendant nodes
|
1098 |
+
*
|
1099 |
+
* @return Element The cloned node
|
1100 |
+
*/
|
1101 |
+
public function cloneNode($deep = true)
|
1102 |
+
{
|
1103 |
+
return new Element($this->node->cloneNode($deep));
|
1104 |
+
}
|
1105 |
+
|
1106 |
+
/**
|
1107 |
+
* Sets current node instance.
|
1108 |
+
*
|
1109 |
+
* @param DOMElement|DOMText|DOMComment|DOMCdataSection|DOMDocumentFragment $node
|
1110 |
+
*
|
1111 |
+
* @return static
|
1112 |
+
*/
|
1113 |
+
protected function setNode($node)
|
1114 |
+
{
|
1115 |
+
$allowedClasses = ['DOMElement', 'DOMText', 'DOMComment', 'DOMCdataSection', 'DOMDocumentFragment'];
|
1116 |
+
|
1117 |
+
if ( ! is_object($node) || ! in_array(get_class($node), $allowedClasses, true)) {
|
1118 |
+
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of DOMElement, DOMText, DOMComment, DOMCdataSection or DOMDocumentFragment, %s given', __METHOD__, (is_object($node) ? get_class($node) : gettype($node))));
|
1119 |
+
}
|
1120 |
+
|
1121 |
+
$this->node = $node;
|
1122 |
+
|
1123 |
+
return $this;
|
1124 |
+
}
|
1125 |
+
|
1126 |
+
/**
|
1127 |
+
* Returns current node instance.
|
1128 |
+
*
|
1129 |
+
* @return DOMElement|DOMText|DOMComment|DOMCdataSection|DOMDocumentFragment
|
1130 |
+
*/
|
1131 |
+
public function getNode()
|
1132 |
+
{
|
1133 |
+
return $this->node;
|
1134 |
+
}
|
1135 |
+
|
1136 |
+
/**
|
1137 |
+
* Returns the document associated with this node.
|
1138 |
+
*
|
1139 |
+
* @return Document|null
|
1140 |
+
*/
|
1141 |
+
public function getDocument()
|
1142 |
+
{
|
1143 |
+
if ($this->node->ownerDocument === null) {
|
1144 |
+
return null;
|
1145 |
+
}
|
1146 |
+
|
1147 |
+
return new Document($this->node->ownerDocument);
|
1148 |
+
}
|
1149 |
+
|
1150 |
+
/**
|
1151 |
+
* Get the DOM document with the current element.
|
1152 |
+
*
|
1153 |
+
* @param string $encoding The document encoding
|
1154 |
+
*
|
1155 |
+
* @return Document
|
1156 |
+
*/
|
1157 |
+
public function toDocument($encoding = 'UTF-8')
|
1158 |
+
{
|
1159 |
+
$document = new Document(null, false, $encoding);
|
1160 |
+
|
1161 |
+
$document->appendChild($this->node);
|
1162 |
+
|
1163 |
+
return $document;
|
1164 |
+
}
|
1165 |
+
|
1166 |
+
/**
|
1167 |
+
* Convert the element to its string representation.
|
1168 |
+
*
|
1169 |
+
* @return string
|
1170 |
+
*/
|
1171 |
+
public function __toString()
|
1172 |
+
{
|
1173 |
+
return $this->html();
|
1174 |
+
}
|
1175 |
+
|
1176 |
+
/**
|
1177 |
+
* Searches for an node in the DOM tree for a given XPath expression or a CSS selector.
|
1178 |
+
*
|
1179 |
+
* @param string $expression XPath expression or a CSS selector
|
1180 |
+
* @param string $type The type of the expression
|
1181 |
+
* @param bool $wrapNode Returns array of Element if true, otherwise array of DOMElement
|
1182 |
+
*
|
1183 |
+
* @return Element[]|DOMElement[]
|
1184 |
+
*
|
1185 |
+
* @throws InvalidSelectorException
|
1186 |
+
*
|
1187 |
+
* @deprecated Not longer recommended, use Element::find() instead.
|
1188 |
+
*/
|
1189 |
+
public function __invoke($expression, $type = Query::TYPE_CSS, $wrapNode = true)
|
1190 |
+
{
|
1191 |
+
return $this->find($expression, $type, $wrapNode);
|
1192 |
+
}
|
1193 |
+
}
|
vendor/imangazaliev/didom/src/DiDom/Query.php
CHANGED
@@ -33,11 +33,11 @@ class Query
|
|
33 |
*/
|
34 |
public static function compile($expression, $type = self::TYPE_CSS)
|
35 |
{
|
36 |
-
if (!is_string($expression)) {
|
37 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, gettype($expression)));
|
38 |
}
|
39 |
|
40 |
-
if (!is_string($type)) {
|
41 |
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($type)));
|
42 |
}
|
43 |
|
@@ -55,7 +55,7 @@ class Query
|
|
55 |
return $expression;
|
56 |
}
|
57 |
|
58 |
-
if (!array_key_exists($expression, static::$compiled)) {
|
59 |
static::$compiled[$expression] = static::cssToXpath($expression);
|
60 |
}
|
61 |
|
@@ -69,6 +69,8 @@ class Query
|
|
69 |
* @param string $prefix Specifies the nesting of nodes
|
70 |
*
|
71 |
* @return string XPath expression
|
|
|
|
|
72 |
*/
|
73 |
public static function cssToXpath($selector, $prefix = '//')
|
74 |
{
|
@@ -92,6 +94,8 @@ class Query
|
|
92 |
* @param string $prefix
|
93 |
*
|
94 |
* @return array
|
|
|
|
|
95 |
*/
|
96 |
protected static function parseAndConvertSelector($selector, $prefix = '//')
|
97 |
{
|
@@ -162,26 +166,26 @@ class Query
|
|
162 |
|
163 |
/**
|
164 |
* @param string $name
|
165 |
-
* @param array
|
166 |
*
|
167 |
* @return string
|
168 |
*
|
169 |
-
* @throws InvalidSelectorException if the
|
170 |
*/
|
171 |
-
protected static function convertProperty($name, array $
|
172 |
{
|
173 |
if ($name === 'text') {
|
174 |
return 'text()';
|
175 |
}
|
176 |
|
177 |
if ($name === 'attr') {
|
178 |
-
if (count($
|
179 |
return '@*';
|
180 |
}
|
181 |
|
182 |
$attributes = [];
|
183 |
|
184 |
-
foreach ($
|
185 |
$attributes[] = sprintf('name() = "%s"', $attribute);
|
186 |
}
|
187 |
|
@@ -200,7 +204,7 @@ class Query
|
|
200 |
*
|
201 |
* @return string
|
202 |
*
|
203 |
-
* @throws InvalidSelectorException if
|
204 |
*/
|
205 |
protected static function convertPseudo($pseudo, &$tagName, array $parameters = [])
|
206 |
{
|
@@ -305,7 +309,7 @@ class Query
|
|
305 |
$attributes[] = self::convertPseudo($segments['pseudo'], $tagName, $parameters);
|
306 |
}
|
307 |
|
308 |
-
if (count($attributes) === 0 && !isset($segments['tag'])) {
|
309 |
throw new InvalidArgumentException('The array of segments must contain the name of the tag or at least one attribute');
|
310 |
}
|
311 |
|
@@ -319,15 +323,15 @@ class Query
|
|
319 |
}
|
320 |
|
321 |
/**
|
322 |
-
* @param string $name
|
323 |
-
* @param string $value The attribute
|
324 |
*
|
325 |
* @return string
|
326 |
*/
|
327 |
protected static function convertAttribute($name, $value)
|
328 |
{
|
329 |
-
$isSimpleSelector = !in_array(substr($name, 0, 1), ['^', '!'], true);
|
330 |
-
$isSimpleSelector = $isSimpleSelector && (!in_array(substr($name, -1), ['^', '$', '*', '!', '~'], true));
|
331 |
|
332 |
if ($isSimpleSelector) {
|
333 |
// if specified only the attribute name
|
@@ -383,8 +387,7 @@ class Query
|
|
383 |
*
|
384 |
* @return string
|
385 |
*
|
386 |
-
* @throws InvalidSelectorException if
|
387 |
-
* @throws InvalidSelectorException if passed an unknown nth-child expression
|
388 |
*/
|
389 |
protected static function convertNthExpression($expression)
|
390 |
{
|
@@ -419,8 +422,8 @@ class Query
|
|
419 |
|
420 |
/**
|
421 |
* @param string $string
|
422 |
-
* @param bool
|
423 |
-
* @param bool
|
424 |
*
|
425 |
* @return string
|
426 |
*/
|
@@ -430,17 +433,17 @@ class Query
|
|
430 |
return sprintf('text() = "%s"', $string);
|
431 |
}
|
432 |
|
433 |
-
if ($caseSensitive &&
|
434 |
return sprintf('contains(text(), "%s")', $string);
|
435 |
}
|
436 |
|
437 |
$strToLowerFunction = function_exists('mb_strtolower') ? 'mb_strtolower' : 'strtolower';
|
438 |
|
439 |
-
if (
|
440 |
return sprintf("php:functionString(\"{$strToLowerFunction}\", .) = php:functionString(\"{$strToLowerFunction}\", \"%s\")", $string);
|
441 |
}
|
442 |
|
443 |
-
// if
|
444 |
return sprintf("contains(php:functionString(\"{$strToLowerFunction}\", .), php:functionString(\"{$strToLowerFunction}\", \"%s\"))", $string);
|
445 |
}
|
446 |
|
@@ -550,7 +553,7 @@ class Query
|
|
550 |
/**
|
551 |
* @param array $compiled
|
552 |
*
|
553 |
-
* @throws
|
554 |
*/
|
555 |
public static function setCompiled(array $compiled)
|
556 |
{
|
33 |
*/
|
34 |
public static function compile($expression, $type = self::TYPE_CSS)
|
35 |
{
|
36 |
+
if ( ! is_string($expression)) {
|
37 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, gettype($expression)));
|
38 |
}
|
39 |
|
40 |
+
if ( ! is_string($type)) {
|
41 |
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($type)));
|
42 |
}
|
43 |
|
55 |
return $expression;
|
56 |
}
|
57 |
|
58 |
+
if ( ! array_key_exists($expression, static::$compiled)) {
|
59 |
static::$compiled[$expression] = static::cssToXpath($expression);
|
60 |
}
|
61 |
|
69 |
* @param string $prefix Specifies the nesting of nodes
|
70 |
*
|
71 |
* @return string XPath expression
|
72 |
+
*
|
73 |
+
* @throws InvalidSelectorException
|
74 |
*/
|
75 |
public static function cssToXpath($selector, $prefix = '//')
|
76 |
{
|
94 |
* @param string $prefix
|
95 |
*
|
96 |
* @return array
|
97 |
+
*
|
98 |
+
* @throws InvalidSelectorException
|
99 |
*/
|
100 |
protected static function parseAndConvertSelector($selector, $prefix = '//')
|
101 |
{
|
166 |
|
167 |
/**
|
168 |
* @param string $name
|
169 |
+
* @param array $parameters
|
170 |
*
|
171 |
* @return string
|
172 |
*
|
173 |
+
* @throws InvalidSelectorException if the specified property is unknown
|
174 |
*/
|
175 |
+
protected static function convertProperty($name, array $parameters = [])
|
176 |
{
|
177 |
if ($name === 'text') {
|
178 |
return 'text()';
|
179 |
}
|
180 |
|
181 |
if ($name === 'attr') {
|
182 |
+
if (count($parameters) === 0) {
|
183 |
return '@*';
|
184 |
}
|
185 |
|
186 |
$attributes = [];
|
187 |
|
188 |
+
foreach ($parameters as $attribute) {
|
189 |
$attributes[] = sprintf('name() = "%s"', $attribute);
|
190 |
}
|
191 |
|
204 |
*
|
205 |
* @return string
|
206 |
*
|
207 |
+
* @throws InvalidSelectorException if the specified pseudo-class is unknown
|
208 |
*/
|
209 |
protected static function convertPseudo($pseudo, &$tagName, array $parameters = [])
|
210 |
{
|
309 |
$attributes[] = self::convertPseudo($segments['pseudo'], $tagName, $parameters);
|
310 |
}
|
311 |
|
312 |
+
if (count($attributes) === 0 && ! isset($segments['tag'])) {
|
313 |
throw new InvalidArgumentException('The array of segments must contain the name of the tag or at least one attribute');
|
314 |
}
|
315 |
|
323 |
}
|
324 |
|
325 |
/**
|
326 |
+
* @param string $name The name of an attribute
|
327 |
+
* @param string $value The value of an attribute
|
328 |
*
|
329 |
* @return string
|
330 |
*/
|
331 |
protected static function convertAttribute($name, $value)
|
332 |
{
|
333 |
+
$isSimpleSelector = ! in_array(substr($name, 0, 1), ['^', '!'], true);
|
334 |
+
$isSimpleSelector = $isSimpleSelector && ( ! in_array(substr($name, -1), ['^', '$', '*', '!', '~'], true));
|
335 |
|
336 |
if ($isSimpleSelector) {
|
337 |
// if specified only the attribute name
|
387 |
*
|
388 |
* @return string
|
389 |
*
|
390 |
+
* @throws InvalidSelectorException if the given nth-child expression is empty or invalid
|
|
|
391 |
*/
|
392 |
protected static function convertNthExpression($expression)
|
393 |
{
|
422 |
|
423 |
/**
|
424 |
* @param string $string
|
425 |
+
* @param bool $caseSensitive
|
426 |
+
* @param bool $fullMatch
|
427 |
*
|
428 |
* @return string
|
429 |
*/
|
433 |
return sprintf('text() = "%s"', $string);
|
434 |
}
|
435 |
|
436 |
+
if ($caseSensitive && ! $fullMatch) {
|
437 |
return sprintf('contains(text(), "%s")', $string);
|
438 |
}
|
439 |
|
440 |
$strToLowerFunction = function_exists('mb_strtolower') ? 'mb_strtolower' : 'strtolower';
|
441 |
|
442 |
+
if ( ! $caseSensitive && $fullMatch) {
|
443 |
return sprintf("php:functionString(\"{$strToLowerFunction}\", .) = php:functionString(\"{$strToLowerFunction}\", \"%s\")", $string);
|
444 |
}
|
445 |
|
446 |
+
// if ! $caseSensitive and ! $fullMatch
|
447 |
return sprintf("contains(php:functionString(\"{$strToLowerFunction}\", .), php:functionString(\"{$strToLowerFunction}\", \"%s\"))", $string);
|
448 |
}
|
449 |
|
553 |
/**
|
554 |
* @param array $compiled
|
555 |
*
|
556 |
+
* @throws InvalidArgumentException if the attributes is not an array
|
557 |
*/
|
558 |
public static function setCompiled(array $compiled)
|
559 |
{
|
vendor/imangazaliev/didom/src/DiDom/StyleAttribute.php
CHANGED
@@ -9,7 +9,7 @@ class StyleAttribute
|
|
9 |
/**
|
10 |
* The DOM element instance.
|
11 |
*
|
12 |
-
* @var
|
13 |
*/
|
14 |
protected $element;
|
15 |
|
@@ -24,15 +24,13 @@ class StyleAttribute
|
|
24 |
protected $properties = [];
|
25 |
|
26 |
/**
|
27 |
-
*
|
28 |
*
|
29 |
-
* @
|
30 |
-
*
|
31 |
-
* @throws \InvalidArgumentException if passed argument is not an element node
|
32 |
*/
|
33 |
public function __construct(Element $element)
|
34 |
{
|
35 |
-
if (
|
36 |
throw new InvalidArgumentException(sprintf('The element must contain DOMElement node'));
|
37 |
}
|
38 |
|
@@ -46,7 +44,7 @@ class StyleAttribute
|
|
46 |
*/
|
47 |
protected function parseStyleAttribute()
|
48 |
{
|
49 |
-
if (
|
50 |
// possible if style attribute has been removed
|
51 |
if ($this->styleString !== '') {
|
52 |
$this->styleString = '';
|
@@ -112,18 +110,18 @@ class StyleAttribute
|
|
112 |
* @param string $name
|
113 |
* @param string $value
|
114 |
*
|
115 |
-
* @return
|
116 |
*
|
117 |
-
* @throws
|
118 |
-
* @throws
|
119 |
*/
|
120 |
public function setProperty($name, $value)
|
121 |
{
|
122 |
-
if (!is_string($name)) {
|
123 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($name) ? get_class($name) : gettype($name))));
|
124 |
}
|
125 |
|
126 |
-
if (!is_string($value)) {
|
127 |
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, (is_object($value) ? get_class($value) : gettype($value))));
|
128 |
}
|
129 |
|
@@ -139,21 +137,21 @@ class StyleAttribute
|
|
139 |
/**
|
140 |
* @param array $properties
|
141 |
*
|
142 |
-
* @return
|
143 |
*
|
144 |
-
* @throws
|
145 |
-
* @throws
|
146 |
*/
|
147 |
public function setMultipleProperties(array $properties)
|
148 |
{
|
149 |
$this->parseStyleAttribute();
|
150 |
|
151 |
foreach ($properties as $propertyName => $value) {
|
152 |
-
if (!is_string($propertyName)) {
|
153 |
throw new InvalidArgumentException(sprintf('Property name must be a string, %s given', (is_object($propertyName) ? get_class($propertyName) : gettype($propertyName))));
|
154 |
}
|
155 |
|
156 |
-
if (!is_string($value)) {
|
157 |
throw new InvalidArgumentException(sprintf('Property value must be a string, %s given', (is_object($value) ? get_class($value) : gettype($value))));
|
158 |
}
|
159 |
|
@@ -173,13 +171,13 @@ class StyleAttribute
|
|
173 |
*/
|
174 |
public function getProperty($name, $default = null)
|
175 |
{
|
176 |
-
if (!is_string($name)) {
|
177 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($name) ? get_class($name) : gettype($name))));
|
178 |
}
|
179 |
|
180 |
$this->parseStyleAttribute();
|
181 |
|
182 |
-
if (!array_key_exists($name, $this->properties)) {
|
183 |
return $default;
|
184 |
}
|
185 |
|
@@ -191,7 +189,7 @@ class StyleAttribute
|
|
191 |
*
|
192 |
* @return mixed
|
193 |
*
|
194 |
-
* @throws
|
195 |
*/
|
196 |
public function getMultipleProperties(array $propertyNames)
|
197 |
{
|
@@ -200,7 +198,7 @@ class StyleAttribute
|
|
200 |
$result = [];
|
201 |
|
202 |
foreach ($propertyNames as $propertyName) {
|
203 |
-
if (!is_string($propertyName)) {
|
204 |
throw new InvalidArgumentException(sprintf('Property name must be a string, %s given', (is_object($propertyName) ? get_class($propertyName) : gettype($propertyName))));
|
205 |
}
|
206 |
|
@@ -229,7 +227,7 @@ class StyleAttribute
|
|
229 |
*/
|
230 |
public function hasProperty($name)
|
231 |
{
|
232 |
-
if (!is_string($name)) {
|
233 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($name) ? get_class($name) : gettype($name))));
|
234 |
}
|
235 |
|
@@ -241,13 +239,13 @@ class StyleAttribute
|
|
241 |
/**
|
242 |
* @param string $name
|
243 |
*
|
244 |
-
* @return
|
245 |
*
|
246 |
-
* @throws
|
247 |
*/
|
248 |
public function removeProperty($name)
|
249 |
{
|
250 |
-
if (!is_string($name)) {
|
251 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($name) ? get_class($name) : gettype($name))));
|
252 |
}
|
253 |
|
@@ -263,16 +261,16 @@ class StyleAttribute
|
|
263 |
/**
|
264 |
* @param array $propertyNames
|
265 |
*
|
266 |
-
* @return
|
267 |
*
|
268 |
-
* @throws
|
269 |
*/
|
270 |
public function removeMultipleProperties(array $propertyNames)
|
271 |
{
|
272 |
$this->parseStyleAttribute();
|
273 |
|
274 |
foreach ($propertyNames as $propertyName) {
|
275 |
-
if (!is_string($propertyName)) {
|
276 |
throw new InvalidArgumentException(sprintf('Property name must be a string, %s given', (is_object($propertyName) ? get_class($propertyName) : gettype($propertyName))));
|
277 |
}
|
278 |
|
@@ -287,7 +285,7 @@ class StyleAttribute
|
|
287 |
/**
|
288 |
* @param string[] $exclusions
|
289 |
*
|
290 |
-
* @return
|
291 |
*/
|
292 |
public function removeAllProperties(array $exclusions = [])
|
293 |
{
|
@@ -296,11 +294,11 @@ class StyleAttribute
|
|
296 |
$preservedProperties = [];
|
297 |
|
298 |
foreach ($exclusions as $propertyName) {
|
299 |
-
if (!is_string($propertyName)) {
|
300 |
throw new InvalidArgumentException(sprintf('Property name must be a string, %s given', (is_object($propertyName) ? get_class($propertyName) : gettype($propertyName))));
|
301 |
}
|
302 |
|
303 |
-
if (!array_key_exists($propertyName, $this->properties)) {
|
304 |
continue;
|
305 |
}
|
306 |
|
@@ -315,7 +313,7 @@ class StyleAttribute
|
|
315 |
}
|
316 |
|
317 |
/**
|
318 |
-
* @return
|
319 |
*/
|
320 |
public function getElement()
|
321 |
{
|
9 |
/**
|
10 |
* The DOM element instance.
|
11 |
*
|
12 |
+
* @var Element
|
13 |
*/
|
14 |
protected $element;
|
15 |
|
24 |
protected $properties = [];
|
25 |
|
26 |
/**
|
27 |
+
* @param Element $element
|
28 |
*
|
29 |
+
* @throws InvalidArgumentException if parameter 1 is not an element node
|
|
|
|
|
30 |
*/
|
31 |
public function __construct(Element $element)
|
32 |
{
|
33 |
+
if ( ! $element->isElementNode()) {
|
34 |
throw new InvalidArgumentException(sprintf('The element must contain DOMElement node'));
|
35 |
}
|
36 |
|
44 |
*/
|
45 |
protected function parseStyleAttribute()
|
46 |
{
|
47 |
+
if ( ! $this->element->hasAttribute('style')) {
|
48 |
// possible if style attribute has been removed
|
49 |
if ($this->styleString !== '') {
|
50 |
$this->styleString = '';
|
110 |
* @param string $name
|
111 |
* @param string $value
|
112 |
*
|
113 |
+
* @return StyleAttribute
|
114 |
*
|
115 |
+
* @throws InvalidArgumentException if property name is not a string
|
116 |
+
* @throws InvalidArgumentException if property value is not a string
|
117 |
*/
|
118 |
public function setProperty($name, $value)
|
119 |
{
|
120 |
+
if ( ! is_string($name)) {
|
121 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($name) ? get_class($name) : gettype($name))));
|
122 |
}
|
123 |
|
124 |
+
if ( ! is_string($value)) {
|
125 |
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, (is_object($value) ? get_class($value) : gettype($value))));
|
126 |
}
|
127 |
|
137 |
/**
|
138 |
* @param array $properties
|
139 |
*
|
140 |
+
* @return StyleAttribute
|
141 |
*
|
142 |
+
* @throws InvalidArgumentException if property name is not a string
|
143 |
+
* @throws InvalidArgumentException if property value is not a string
|
144 |
*/
|
145 |
public function setMultipleProperties(array $properties)
|
146 |
{
|
147 |
$this->parseStyleAttribute();
|
148 |
|
149 |
foreach ($properties as $propertyName => $value) {
|
150 |
+
if ( ! is_string($propertyName)) {
|
151 |
throw new InvalidArgumentException(sprintf('Property name must be a string, %s given', (is_object($propertyName) ? get_class($propertyName) : gettype($propertyName))));
|
152 |
}
|
153 |
|
154 |
+
if ( ! is_string($value)) {
|
155 |
throw new InvalidArgumentException(sprintf('Property value must be a string, %s given', (is_object($value) ? get_class($value) : gettype($value))));
|
156 |
}
|
157 |
|
171 |
*/
|
172 |
public function getProperty($name, $default = null)
|
173 |
{
|
174 |
+
if ( ! is_string($name)) {
|
175 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($name) ? get_class($name) : gettype($name))));
|
176 |
}
|
177 |
|
178 |
$this->parseStyleAttribute();
|
179 |
|
180 |
+
if ( ! array_key_exists($name, $this->properties)) {
|
181 |
return $default;
|
182 |
}
|
183 |
|
189 |
*
|
190 |
* @return mixed
|
191 |
*
|
192 |
+
* @throws InvalidArgumentException if property name is not a string
|
193 |
*/
|
194 |
public function getMultipleProperties(array $propertyNames)
|
195 |
{
|
198 |
$result = [];
|
199 |
|
200 |
foreach ($propertyNames as $propertyName) {
|
201 |
+
if ( ! is_string($propertyName)) {
|
202 |
throw new InvalidArgumentException(sprintf('Property name must be a string, %s given', (is_object($propertyName) ? get_class($propertyName) : gettype($propertyName))));
|
203 |
}
|
204 |
|
227 |
*/
|
228 |
public function hasProperty($name)
|
229 |
{
|
230 |
+
if ( ! is_string($name)) {
|
231 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($name) ? get_class($name) : gettype($name))));
|
232 |
}
|
233 |
|
239 |
/**
|
240 |
* @param string $name
|
241 |
*
|
242 |
+
* @return StyleAttribute
|
243 |
*
|
244 |
+
* @throws InvalidArgumentException if property name is not a string
|
245 |
*/
|
246 |
public function removeProperty($name)
|
247 |
{
|
248 |
+
if ( ! is_string($name)) {
|
249 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($name) ? get_class($name) : gettype($name))));
|
250 |
}
|
251 |
|
261 |
/**
|
262 |
* @param array $propertyNames
|
263 |
*
|
264 |
+
* @return StyleAttribute
|
265 |
*
|
266 |
+
* @throws InvalidArgumentException if property name is not a string
|
267 |
*/
|
268 |
public function removeMultipleProperties(array $propertyNames)
|
269 |
{
|
270 |
$this->parseStyleAttribute();
|
271 |
|
272 |
foreach ($propertyNames as $propertyName) {
|
273 |
+
if ( ! is_string($propertyName)) {
|
274 |
throw new InvalidArgumentException(sprintf('Property name must be a string, %s given', (is_object($propertyName) ? get_class($propertyName) : gettype($propertyName))));
|
275 |
}
|
276 |
|
285 |
/**
|
286 |
* @param string[] $exclusions
|
287 |
*
|
288 |
+
* @return StyleAttribute
|
289 |
*/
|
290 |
public function removeAllProperties(array $exclusions = [])
|
291 |
{
|
294 |
$preservedProperties = [];
|
295 |
|
296 |
foreach ($exclusions as $propertyName) {
|
297 |
+
if ( ! is_string($propertyName)) {
|
298 |
throw new InvalidArgumentException(sprintf('Property name must be a string, %s given', (is_object($propertyName) ? get_class($propertyName) : gettype($propertyName))));
|
299 |
}
|
300 |
|
301 |
+
if ( ! array_key_exists($propertyName, $this->properties)) {
|
302 |
continue;
|
303 |
}
|
304 |
|
313 |
}
|
314 |
|
315 |
/**
|
316 |
+
* @return Element
|
317 |
*/
|
318 |
public function getElement()
|
319 |
{
|
vendor/imangazaliev/didom/tests/DiDom/ClassAttributeTest.php
DELETED
@@ -1,383 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Tests\DiDom;
|
4 |
-
|
5 |
-
use DiDom\Element;
|
6 |
-
use DiDom\ClassAttribute;
|
7 |
-
use Tests\TestCase;
|
8 |
-
|
9 |
-
class ClassAttributeTest extends TestCase
|
10 |
-
{
|
11 |
-
/**
|
12 |
-
* @expectedException \InvalidArgumentException
|
13 |
-
* @expectedExceptionMessage The element must contain DOMElement node
|
14 |
-
*/
|
15 |
-
public function testConstructorWithTextNode()
|
16 |
-
{
|
17 |
-
$element = new Element(new \DOMText('foo'));
|
18 |
-
|
19 |
-
new ClassAttribute($element);
|
20 |
-
}
|
21 |
-
|
22 |
-
/**
|
23 |
-
* @expectedException \InvalidArgumentException
|
24 |
-
* @expectedExceptionMessage The element must contain DOMElement node
|
25 |
-
*/
|
26 |
-
public function testConstructorWithCommentNode()
|
27 |
-
{
|
28 |
-
$element = new Element(new \DOMComment('foo'));
|
29 |
-
|
30 |
-
new ClassAttribute($element);
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* @expectedException \InvalidArgumentException
|
35 |
-
* @expectedExceptionMessage DiDom\ClassAttribute::add expects parameter 1 to be string, NULL given
|
36 |
-
*/
|
37 |
-
public function testAddWithInvalidClassName()
|
38 |
-
{
|
39 |
-
$element = new Element('div', null, [
|
40 |
-
'class' => 'foo',
|
41 |
-
]);
|
42 |
-
|
43 |
-
$classAttribute = new ClassAttribute($element);
|
44 |
-
|
45 |
-
$classAttribute->add(null);
|
46 |
-
}
|
47 |
-
|
48 |
-
public function testAdd()
|
49 |
-
{
|
50 |
-
// without class attribute
|
51 |
-
$element = new Element('div', null);
|
52 |
-
|
53 |
-
$classAttribute = new ClassAttribute($element);
|
54 |
-
|
55 |
-
$this->assertEquals(null, $element->getAttribute('class'));
|
56 |
-
|
57 |
-
$classAttribute->add('foo');
|
58 |
-
|
59 |
-
$this->assertEquals('foo', $element->getAttribute('class'));
|
60 |
-
|
61 |
-
// with empty class attribute
|
62 |
-
$element = new Element('div', null, [
|
63 |
-
'class' => '',
|
64 |
-
]);
|
65 |
-
|
66 |
-
$classAttribute = new ClassAttribute($element);
|
67 |
-
|
68 |
-
$this->assertEquals('', $element->getAttribute('class'));
|
69 |
-
|
70 |
-
$classAttribute->add('foo');
|
71 |
-
|
72 |
-
$this->assertEquals('foo', $element->getAttribute('class'));
|
73 |
-
|
74 |
-
// class attribute with spaces
|
75 |
-
$element = new Element('div', null, [
|
76 |
-
'class' => ' ',
|
77 |
-
]);
|
78 |
-
|
79 |
-
$classAttribute = new ClassAttribute($element);
|
80 |
-
|
81 |
-
$this->assertEquals(' ', $element->getAttribute('class'));
|
82 |
-
|
83 |
-
$classAttribute->add('foo');
|
84 |
-
|
85 |
-
$this->assertEquals('foo', $element->getAttribute('class'));
|
86 |
-
|
87 |
-
// with not empty class attribute
|
88 |
-
$element = new Element('div', null, [
|
89 |
-
'class' => 'foo bar',
|
90 |
-
]);
|
91 |
-
|
92 |
-
$classAttribute = new ClassAttribute($element);
|
93 |
-
|
94 |
-
$this->assertEquals('foo bar', $element->getAttribute('class'));
|
95 |
-
|
96 |
-
$classAttribute->add('baz');
|
97 |
-
|
98 |
-
$this->assertEquals('foo bar baz', $element->getAttribute('class'));
|
99 |
-
|
100 |
-
// with existing class name
|
101 |
-
$element = new Element('div', null, [
|
102 |
-
'class' => 'foo bar baz',
|
103 |
-
]);
|
104 |
-
|
105 |
-
$classAttribute = new ClassAttribute($element);
|
106 |
-
|
107 |
-
$this->assertEquals('foo bar baz', $element->getAttribute('class'));
|
108 |
-
|
109 |
-
$classAttribute->add('bar');
|
110 |
-
|
111 |
-
$this->assertEquals('foo bar baz', $element->getAttribute('class'));
|
112 |
-
}
|
113 |
-
|
114 |
-
/**
|
115 |
-
* @expectedException \InvalidArgumentException
|
116 |
-
* @expectedExceptionMessage Class name must be a string, NULL given
|
117 |
-
*/
|
118 |
-
public function testAddMultipleWithInvalidClassName()
|
119 |
-
{
|
120 |
-
$element = new Element('div', null, [
|
121 |
-
'class' => 'foo',
|
122 |
-
]);
|
123 |
-
|
124 |
-
$classAttribute = new ClassAttribute($element);
|
125 |
-
|
126 |
-
$classAttribute->addMultiple(['bar', null]);
|
127 |
-
}
|
128 |
-
|
129 |
-
public function testAddMultiple()
|
130 |
-
{
|
131 |
-
$element = new Element('div', null, [
|
132 |
-
'class' => 'foo',
|
133 |
-
]);
|
134 |
-
|
135 |
-
$classAttribute = new ClassAttribute($element);
|
136 |
-
|
137 |
-
$this->assertEquals('foo', $element->getAttribute('class'));
|
138 |
-
|
139 |
-
$classAttribute->addMultiple([
|
140 |
-
'bar', 'baz',
|
141 |
-
]);
|
142 |
-
|
143 |
-
$this->assertEquals('foo bar baz', $element->getAttribute('class'));
|
144 |
-
}
|
145 |
-
|
146 |
-
public function testGetAll()
|
147 |
-
{
|
148 |
-
// without class attribute
|
149 |
-
$element = new Element('div', null);
|
150 |
-
|
151 |
-
$classAttribute = new ClassAttribute($element);
|
152 |
-
|
153 |
-
$this->assertEquals([], $classAttribute->getAll());
|
154 |
-
|
155 |
-
// with empty class attribute
|
156 |
-
$element = new Element('div', null, [
|
157 |
-
'class' => '',
|
158 |
-
]);
|
159 |
-
|
160 |
-
$classAttribute = new ClassAttribute($element);
|
161 |
-
|
162 |
-
$this->assertEquals([], $classAttribute->getAll());
|
163 |
-
|
164 |
-
// class attribute with spaces
|
165 |
-
$element = new Element('div', null, [
|
166 |
-
'class' => ' ',
|
167 |
-
]);
|
168 |
-
|
169 |
-
$classAttribute = new ClassAttribute($element);
|
170 |
-
|
171 |
-
$this->assertEquals([], $classAttribute->getAll());
|
172 |
-
|
173 |
-
// one class
|
174 |
-
$element = new Element('div', null, [
|
175 |
-
'class' => 'foo',
|
176 |
-
]);
|
177 |
-
|
178 |
-
$classAttribute = new ClassAttribute($element);
|
179 |
-
|
180 |
-
$this->assertEquals(['foo'], $classAttribute->getAll());
|
181 |
-
|
182 |
-
// several classes
|
183 |
-
$element = new Element('div', null, [
|
184 |
-
'class' => 'foo bar baz',
|
185 |
-
]);
|
186 |
-
|
187 |
-
$classAttribute = new ClassAttribute($element);
|
188 |
-
|
189 |
-
$this->assertEquals(['foo', 'bar', 'baz'], $classAttribute->getAll());
|
190 |
-
|
191 |
-
// with multiple spaces between class names
|
192 |
-
$element = new Element('div', null, [
|
193 |
-
'class' => 'foo bar baz',
|
194 |
-
]);
|
195 |
-
|
196 |
-
$classAttribute = new ClassAttribute($element);
|
197 |
-
|
198 |
-
$this->assertEquals(['foo', 'bar', 'baz'], $classAttribute->getAll());
|
199 |
-
}
|
200 |
-
|
201 |
-
public function testGetAllPropertiesAfterEmptyClassAttribute()
|
202 |
-
{
|
203 |
-
$element = new Element('div', null, [
|
204 |
-
'class' => 'foo bar baz',
|
205 |
-
]);
|
206 |
-
|
207 |
-
$classAttribute = new ClassAttribute($element);
|
208 |
-
|
209 |
-
$this->assertEquals(['foo', 'bar', 'baz'], $classAttribute->getAll());
|
210 |
-
|
211 |
-
$element->setAttribute('class', '');
|
212 |
-
|
213 |
-
$this->assertEquals([], $classAttribute->getAll());
|
214 |
-
}
|
215 |
-
|
216 |
-
public function testContains()
|
217 |
-
{
|
218 |
-
$element = new Element('div', null, [
|
219 |
-
'class' => 'foo bar',
|
220 |
-
]);
|
221 |
-
|
222 |
-
$classAttribute = new ClassAttribute($element);
|
223 |
-
|
224 |
-
$this->assertTrue($classAttribute->contains('foo'));
|
225 |
-
$this->assertTrue($classAttribute->contains('bar'));
|
226 |
-
$this->assertFalse($classAttribute->contains('baz'));
|
227 |
-
}
|
228 |
-
|
229 |
-
/**
|
230 |
-
* @expectedException \InvalidArgumentException
|
231 |
-
* @expectedExceptionMessage DiDom\ClassAttribute::remove expects parameter 1 to be string, NULL given
|
232 |
-
*/
|
233 |
-
public function testRemoveWithInvalidClassName()
|
234 |
-
{
|
235 |
-
$element = new Element('div', null, [
|
236 |
-
'class' => 'foo bar baz',
|
237 |
-
]);
|
238 |
-
|
239 |
-
$classAttribute = new ClassAttribute($element);
|
240 |
-
|
241 |
-
$classAttribute->remove(null);
|
242 |
-
}
|
243 |
-
|
244 |
-
public function testRemove()
|
245 |
-
{
|
246 |
-
$element = new Element('div', null, [
|
247 |
-
'class' => 'foo bar baz',
|
248 |
-
]);
|
249 |
-
|
250 |
-
$classAttribute = new ClassAttribute($element);
|
251 |
-
|
252 |
-
$this->assertEquals('foo bar baz', $element->getAttribute('class'));
|
253 |
-
|
254 |
-
$classAttribute->remove('bar');
|
255 |
-
|
256 |
-
$this->assertEquals('foo baz', $element->getAttribute('class'));
|
257 |
-
|
258 |
-
// with nonexistent class name
|
259 |
-
$element = new Element('div', null, [
|
260 |
-
'class' => 'foo bar',
|
261 |
-
]);
|
262 |
-
|
263 |
-
$classAttribute = new ClassAttribute($element);
|
264 |
-
|
265 |
-
$this->assertEquals('foo bar', $element->getAttribute('class'));
|
266 |
-
|
267 |
-
$classAttribute->remove('baz');
|
268 |
-
|
269 |
-
$this->assertEquals('foo bar', $element->getAttribute('class'));
|
270 |
-
}
|
271 |
-
|
272 |
-
/**
|
273 |
-
* @expectedException \InvalidArgumentException
|
274 |
-
* @expectedExceptionMessage Class name must be a string, NULL given
|
275 |
-
*/
|
276 |
-
public function testRemoveMultipleWithInvalidClassName()
|
277 |
-
{
|
278 |
-
$element = new Element('div', null, [
|
279 |
-
'class' => 'foo bar baz',
|
280 |
-
]);
|
281 |
-
|
282 |
-
$classAttribute = new ClassAttribute($element);
|
283 |
-
|
284 |
-
$classAttribute->removeMultiple(['foo', null]);
|
285 |
-
}
|
286 |
-
|
287 |
-
public function testRemoveMultiple()
|
288 |
-
{
|
289 |
-
$element = new Element('div', null, [
|
290 |
-
'class' => 'foo bar baz',
|
291 |
-
]);
|
292 |
-
|
293 |
-
$classAttribute = new ClassAttribute($element);
|
294 |
-
|
295 |
-
$this->assertEquals('foo bar baz', $element->getAttribute('class'));
|
296 |
-
|
297 |
-
$classAttribute->removeMultiple(['foo', 'bar']);
|
298 |
-
|
299 |
-
$this->assertEquals('baz', $element->getAttribute('class'));
|
300 |
-
|
301 |
-
// with nonexistent class name
|
302 |
-
$element = new Element('div', null, [
|
303 |
-
'class' => 'foo bar baz',
|
304 |
-
]);
|
305 |
-
|
306 |
-
$classAttribute = new ClassAttribute($element);
|
307 |
-
|
308 |
-
$this->assertEquals('foo bar baz', $element->getAttribute('class'));
|
309 |
-
|
310 |
-
$classAttribute->removeMultiple(['bar', 'qux']);
|
311 |
-
|
312 |
-
$this->assertEquals('foo baz', $element->getAttribute('class'));
|
313 |
-
}
|
314 |
-
|
315 |
-
/**
|
316 |
-
* @expectedException \InvalidArgumentException
|
317 |
-
* @expectedExceptionMessage Class name must be a string, NULL given
|
318 |
-
*/
|
319 |
-
public function testRemoveAllWithInvalidClassName()
|
320 |
-
{
|
321 |
-
$element = new Element('div', null, [
|
322 |
-
'class' => 'foo bar baz',
|
323 |
-
]);
|
324 |
-
|
325 |
-
$classAttribute = new ClassAttribute($element);
|
326 |
-
|
327 |
-
$classAttribute->removeAll(['foo', null]);
|
328 |
-
}
|
329 |
-
|
330 |
-
public function testRemoveAll()
|
331 |
-
{
|
332 |
-
$element = new Element('div', null, [
|
333 |
-
'class' => 'foo bar baz',
|
334 |
-
]);
|
335 |
-
|
336 |
-
$classAttribute = new ClassAttribute($element);
|
337 |
-
|
338 |
-
$this->assertEquals('foo bar baz', $element->getAttribute('class'));
|
339 |
-
|
340 |
-
$classAttribute->removeAll();
|
341 |
-
|
342 |
-
$this->assertEquals('', $element->getAttribute('class'));
|
343 |
-
}
|
344 |
-
|
345 |
-
public function testRemoveAllWithExclusions()
|
346 |
-
{
|
347 |
-
$element = new Element('div', null, [
|
348 |
-
'class' => 'foo bar baz',
|
349 |
-
]);
|
350 |
-
|
351 |
-
$classAttribute = new ClassAttribute($element);
|
352 |
-
|
353 |
-
$this->assertEquals('foo bar baz', $element->getAttribute('class'));
|
354 |
-
|
355 |
-
$classAttribute->removeAll(['bar']);
|
356 |
-
|
357 |
-
$this->assertEquals('bar', $element->getAttribute('class'));
|
358 |
-
|
359 |
-
// with nonexistent class name
|
360 |
-
$element = new Element('div', null, [
|
361 |
-
'class' => 'foo bar baz',
|
362 |
-
]);
|
363 |
-
|
364 |
-
$classAttribute = new ClassAttribute($element);
|
365 |
-
|
366 |
-
$this->assertEquals('foo bar baz', $element->getAttribute('class'));
|
367 |
-
|
368 |
-
$classAttribute->removeAll(['bar', 'qux']);
|
369 |
-
|
370 |
-
$this->assertEquals('bar', $element->getAttribute('class'));
|
371 |
-
}
|
372 |
-
|
373 |
-
public function testGetElement()
|
374 |
-
{
|
375 |
-
$element = new Element('div', null, [
|
376 |
-
'class' => 'foo bar baz',
|
377 |
-
]);
|
378 |
-
|
379 |
-
$classAttribute = new ClassAttribute($element);
|
380 |
-
|
381 |
-
$this->assertSame($element, $classAttribute->getElement());
|
382 |
-
}
|
383 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/imangazaliev/didom/tests/DiDom/DocumentTest.php
DELETED
@@ -1,772 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Tests\DiDom;
|
4 |
-
|
5 |
-
use DiDom\Document;
|
6 |
-
use DiDom\Query;
|
7 |
-
use Tests\TestCase;
|
8 |
-
|
9 |
-
class DocumentTest extends TestCase
|
10 |
-
{
|
11 |
-
/**
|
12 |
-
* @expectedException \InvalidArgumentException
|
13 |
-
* @expectedExceptionMessage DiDom\Document::load expects parameter 1 to be string, array given
|
14 |
-
*/
|
15 |
-
public function testConstructWithInvalidArgument()
|
16 |
-
{
|
17 |
-
new Document(array('foo'));
|
18 |
-
}
|
19 |
-
|
20 |
-
/**
|
21 |
-
* @expectedException \InvalidArgumentException
|
22 |
-
* @expectedExceptionMessage DiDom\Document::__construct expects parameter 3 to be string, NULL given
|
23 |
-
*/
|
24 |
-
public function testConstructWithInvalidEncoding()
|
25 |
-
{
|
26 |
-
new Document(null, false, null);
|
27 |
-
}
|
28 |
-
|
29 |
-
/**
|
30 |
-
* @expectedException \RuntimeException
|
31 |
-
* @expectedExceptionMessage Could not load file path/to/file
|
32 |
-
*/
|
33 |
-
public function testConstructWithNotExistingFile()
|
34 |
-
{
|
35 |
-
new Document('path/to/file', true);
|
36 |
-
}
|
37 |
-
|
38 |
-
/**
|
39 |
-
* @expectedException \InvalidArgumentException
|
40 |
-
* @expectedExceptionMessage DiDom\Document::load expects parameter 3 to be string, NULL given
|
41 |
-
*/
|
42 |
-
public function testConstructorWithInvalidTypeOfDocumentTypeArgument()
|
43 |
-
{
|
44 |
-
new Document('foo', false, 'UTF-8', null);
|
45 |
-
}
|
46 |
-
|
47 |
-
/**
|
48 |
-
* @expectedException \RuntimeException
|
49 |
-
* @expectedExceptionMessage Document type must be "xml" or "html", bar given
|
50 |
-
*/
|
51 |
-
public function testConstructorWithInvalidDocumentType()
|
52 |
-
{
|
53 |
-
new Document('foo', false, 'UTF-8', 'bar');
|
54 |
-
}
|
55 |
-
|
56 |
-
/**
|
57 |
-
* @dataProvider loadHtmlCharsetTests
|
58 |
-
*/
|
59 |
-
public function testLoadHtmlCharset($html, $text)
|
60 |
-
{
|
61 |
-
$document = new Document($html, false, 'UTF-8');
|
62 |
-
|
63 |
-
$this->assertEquals($text, $document->first('div')->text());
|
64 |
-
}
|
65 |
-
|
66 |
-
public function loadHtmlCharsetTests()
|
67 |
-
{
|
68 |
-
return array(
|
69 |
-
array('<html><div class="foo">English language</html>', 'English language'),
|
70 |
-
array('<html><div class="foo">Русский язык</html>', 'Русский язык'),
|
71 |
-
array('<html><div class="foo">اللغة العربية</html>', 'اللغة العربية'),
|
72 |
-
array('<html><div class="foo">漢語</html>', '漢語'),
|
73 |
-
array('<html><div class="foo">Tiếng Việt</html>', 'Tiếng Việt'),
|
74 |
-
);
|
75 |
-
}
|
76 |
-
|
77 |
-
public function testCreate()
|
78 |
-
{
|
79 |
-
$this->assertInstanceOf('DiDom\Document', Document::create());
|
80 |
-
}
|
81 |
-
|
82 |
-
public function testCreateElement()
|
83 |
-
{
|
84 |
-
$html = $this->loadFixture('posts.html');
|
85 |
-
|
86 |
-
$document = new Document($html, false);
|
87 |
-
$element = $document->createElement('span', 'value');
|
88 |
-
|
89 |
-
$this->assertInstanceOf('DiDom\Element', $element);
|
90 |
-
$this->assertEquals('span', $element->getNode()->tagName);
|
91 |
-
$this->assertEquals('value', $element->getNode()->textContent);
|
92 |
-
|
93 |
-
$element = $document->createElement('span');
|
94 |
-
$this->assertEquals('', $element->text());
|
95 |
-
|
96 |
-
$element = $document->createElement('input', '', ['name' => 'username']);
|
97 |
-
$this->assertEquals('username', $element->getNode()->getAttribute('name'));
|
98 |
-
}
|
99 |
-
|
100 |
-
public function testCreateElementBySelector()
|
101 |
-
{
|
102 |
-
$document = new Document();
|
103 |
-
|
104 |
-
$element = $document->createElementBySelector('a.external-link[href=http://example.com]');
|
105 |
-
|
106 |
-
$this->assertEquals('a', $element->tag);
|
107 |
-
$this->assertEquals('', $element->text());
|
108 |
-
$this->assertEquals(['href' => 'http://example.com', 'class' => 'external-link'], $element->attributes());
|
109 |
-
|
110 |
-
$element = $document->createElementBySelector('#block', 'Foo');
|
111 |
-
|
112 |
-
$this->assertEquals('div', $element->tag);
|
113 |
-
$this->assertEquals('Foo', $element->text());
|
114 |
-
$this->assertEquals(['id' => 'block'], $element->attributes());
|
115 |
-
|
116 |
-
$element = $document->createElementBySelector('input', null, ['name' => 'name', 'placeholder' => 'Enter your name']);
|
117 |
-
|
118 |
-
$this->assertEquals('input', $element->tag);
|
119 |
-
$this->assertEquals('', $element->text());
|
120 |
-
$this->assertEquals(['name' => 'name', 'placeholder' => 'Enter your name'], $element->attributes());
|
121 |
-
}
|
122 |
-
|
123 |
-
public function testCreateTextNode()
|
124 |
-
{
|
125 |
-
$document = new Document();
|
126 |
-
|
127 |
-
$textNode = $document->createTextNode('foo bar baz');
|
128 |
-
|
129 |
-
$this->assertInstanceOf('DiDom\Element', $textNode);
|
130 |
-
$this->assertInstanceOf('DOMText', $textNode->getNode());
|
131 |
-
$this->assertEquals('foo bar baz', $textNode->text());
|
132 |
-
}
|
133 |
-
|
134 |
-
public function testCreateComment()
|
135 |
-
{
|
136 |
-
$document = new Document();
|
137 |
-
|
138 |
-
$comment = $document->createComment('foo bar baz');
|
139 |
-
|
140 |
-
$this->assertInstanceOf('DiDom\Element', $comment);
|
141 |
-
$this->assertInstanceOf('DOMComment', $comment->getNode());
|
142 |
-
$this->assertEquals('foo bar baz', $comment->text());
|
143 |
-
}
|
144 |
-
|
145 |
-
public function testCreateCDATASection()
|
146 |
-
{
|
147 |
-
$document = new Document();
|
148 |
-
|
149 |
-
$cdataSection = $document->createCdataSection('foo bar baz');
|
150 |
-
|
151 |
-
$this->assertInstanceOf('DiDom\Element', $cdataSection);
|
152 |
-
$this->assertInstanceOf('DOMCdataSection', $cdataSection->getNode());
|
153 |
-
$this->assertEquals('foo bar baz', $cdataSection->text());
|
154 |
-
}
|
155 |
-
|
156 |
-
/**
|
157 |
-
* @expectedException \InvalidArgumentException
|
158 |
-
* @expectedExceptionMessage Argument 1 passed to DiDom\Document::appendChild must be an instance of DiDom\Element or DOMNode, string given
|
159 |
-
*/
|
160 |
-
public function testAppendChildWithInvalidArgument()
|
161 |
-
{
|
162 |
-
$html = $this->loadFixture('posts.html');
|
163 |
-
|
164 |
-
$document = new Document($html);
|
165 |
-
|
166 |
-
$document->appendChild('foo');
|
167 |
-
}
|
168 |
-
|
169 |
-
public function testAppendChild()
|
170 |
-
{
|
171 |
-
$html = '<!DOCTYPE html>
|
172 |
-
<html lang="en">
|
173 |
-
<head>
|
174 |
-
<meta charset="UTF-8">
|
175 |
-
<title>Document</title>
|
176 |
-
</head>
|
177 |
-
<body>
|
178 |
-
|
179 |
-
</body>
|
180 |
-
</html>';
|
181 |
-
|
182 |
-
$document = new Document($html);
|
183 |
-
|
184 |
-
$this->assertCount(0, $document->find('span'));
|
185 |
-
|
186 |
-
$node = $document->createElement('span');
|
187 |
-
$appendedChild = $document->appendChild($node);
|
188 |
-
|
189 |
-
$this->assertCount(1, $document->find('span'));
|
190 |
-
$this->assertTrue($appendedChild->is($document->first('span')));
|
191 |
-
|
192 |
-
$appendedChild->remove();
|
193 |
-
|
194 |
-
$this->assertCount(0, $document->find('span'));
|
195 |
-
|
196 |
-
$nodes = [];
|
197 |
-
$nodes[] = $document->createElement('span');
|
198 |
-
$nodes[] = $document->createElement('span');
|
199 |
-
|
200 |
-
$appendedChildren = $document->appendChild($nodes);
|
201 |
-
|
202 |
-
$nodes = $document->find('span');
|
203 |
-
|
204 |
-
$this->assertCount(2, $appendedChildren);
|
205 |
-
$this->assertCount(2, $nodes);
|
206 |
-
|
207 |
-
foreach ($appendedChildren as $index => $child) {
|
208 |
-
$this->assertTrue($child->is($nodes[$index]));
|
209 |
-
}
|
210 |
-
}
|
211 |
-
|
212 |
-
/**
|
213 |
-
* @expectedException \InvalidArgumentException
|
214 |
-
* @expectedExceptionMessage DiDom\Document::load expects parameter 1 to be string, NULL given
|
215 |
-
*/
|
216 |
-
public function testLoadWithInvalidContentArgument()
|
217 |
-
{
|
218 |
-
$document = new Document();
|
219 |
-
|
220 |
-
$document->load(null);
|
221 |
-
}
|
222 |
-
|
223 |
-
/**
|
224 |
-
* @expectedException \RuntimeException
|
225 |
-
* @expectedExceptionMessage Could not load file path/to/file
|
226 |
-
*/
|
227 |
-
public function testLoadWithNotExistingFile()
|
228 |
-
{
|
229 |
-
$document = new Document();
|
230 |
-
|
231 |
-
$document->load('path/to/file', true);
|
232 |
-
}
|
233 |
-
|
234 |
-
/**
|
235 |
-
* @expectedException \InvalidArgumentException
|
236 |
-
* @expectedExceptionMessage DiDom\Document::load expects parameter 3 to be string, NULL given
|
237 |
-
*/
|
238 |
-
public function testLoadWithInvalidTypeOfDocumentTypeArgument()
|
239 |
-
{
|
240 |
-
$document = new Document();
|
241 |
-
|
242 |
-
$document->load('foo', false, null);
|
243 |
-
}
|
244 |
-
|
245 |
-
/**
|
246 |
-
* @expectedException \RuntimeException
|
247 |
-
* @expectedExceptionMessage Document type must be "xml" or "html", bar given
|
248 |
-
*/
|
249 |
-
public function testLoadWithInvalidDocumentType()
|
250 |
-
{
|
251 |
-
$document = new Document();
|
252 |
-
|
253 |
-
$document->load('foo', false, 'bar');
|
254 |
-
}
|
255 |
-
|
256 |
-
/**
|
257 |
-
* @expectedException \InvalidArgumentException
|
258 |
-
* @expectedExceptionMessage DiDom\Document::load expects parameter 4 to be integer, string given
|
259 |
-
*/
|
260 |
-
public function testLoadWithInvalidOptionsType()
|
261 |
-
{
|
262 |
-
$document = new Document();
|
263 |
-
|
264 |
-
$document->load('foo', false, 'html', 'bar');
|
265 |
-
}
|
266 |
-
|
267 |
-
public function testLoadHtmlDocument()
|
268 |
-
{
|
269 |
-
$html = '
|
270 |
-
<!DOCTYPE html>
|
271 |
-
<html>
|
272 |
-
<head>
|
273 |
-
<title>Document</title>
|
274 |
-
</head>
|
275 |
-
<body>
|
276 |
-
<div class="foo">Foo — Bar — Baz</div>
|
277 |
-
</body>
|
278 |
-
</html>
|
279 |
-
';
|
280 |
-
|
281 |
-
$document = new Document();
|
282 |
-
|
283 |
-
$document->load($html, false, 'html');
|
284 |
-
|
285 |
-
$this->assertEquals('Foo — Bar — Baz', $document->first('.foo')->text());
|
286 |
-
}
|
287 |
-
|
288 |
-
public function testLoadXmlDocument()
|
289 |
-
{
|
290 |
-
$xml = '
|
291 |
-
<?xml version="1.0" encoding="UTF-8"?>
|
292 |
-
<root>
|
293 |
-
<foo>Foo — Bar — Baz</foo>
|
294 |
-
</root>
|
295 |
-
';
|
296 |
-
|
297 |
-
$document = new Document();
|
298 |
-
|
299 |
-
$document->load($xml, false, 'xml');
|
300 |
-
|
301 |
-
$this->assertEquals('Foo — Bar — Baz', $document->first('foo')->text());
|
302 |
-
}
|
303 |
-
|
304 |
-
/**
|
305 |
-
* @expectedException \InvalidArgumentException
|
306 |
-
* @expectedExceptionMessage DiDom\Document::load expects parameter 1 to be string, NULL given
|
307 |
-
*/
|
308 |
-
public function testLoadHtmlWithInvalidArgument()
|
309 |
-
{
|
310 |
-
$document = new Document();
|
311 |
-
|
312 |
-
$document->loadHtml(null);
|
313 |
-
}
|
314 |
-
|
315 |
-
/**
|
316 |
-
* @expectedException \InvalidArgumentException
|
317 |
-
* @expectedExceptionMessage DiDom\Document::load expects parameter 1 to be string, array given
|
318 |
-
*/
|
319 |
-
public function testLoadHtmlFileWithInvalidArgument()
|
320 |
-
{
|
321 |
-
$document = new Document();
|
322 |
-
|
323 |
-
$document->loadHtmlFile(array('foo'));
|
324 |
-
}
|
325 |
-
|
326 |
-
/**
|
327 |
-
* @expectedException \RuntimeException
|
328 |
-
* @expectedExceptionMessage Could not load file path/to/file
|
329 |
-
*/
|
330 |
-
public function testLoadHtmlFileWithNotExistingFile()
|
331 |
-
{
|
332 |
-
$document = new Document();
|
333 |
-
|
334 |
-
$document->loadHtmlFile('path/to/file');
|
335 |
-
}
|
336 |
-
|
337 |
-
/**
|
338 |
-
* @expectedException \InvalidArgumentException
|
339 |
-
* @expectedExceptionMessage DiDom\Document::load expects parameter 1 to be string, NULL given
|
340 |
-
*/
|
341 |
-
public function testLoadXmlWithInvalidArgument()
|
342 |
-
{
|
343 |
-
$document = new Document();
|
344 |
-
|
345 |
-
$document->loadXml(null);
|
346 |
-
}
|
347 |
-
|
348 |
-
/**
|
349 |
-
* @expectedException \InvalidArgumentException
|
350 |
-
* @expectedExceptionMessage DiDom\Document::load expects parameter 1 to be string, array given
|
351 |
-
*/
|
352 |
-
public function testLoadXmlFileWithInvalidArgument()
|
353 |
-
{
|
354 |
-
$document = new Document();
|
355 |
-
|
356 |
-
$document->loadXmlFile(array('foo'));
|
357 |
-
}
|
358 |
-
|
359 |
-
/**
|
360 |
-
* @expectedException \RuntimeException
|
361 |
-
* @expectedExceptionMessage Could not load file path/to/file
|
362 |
-
*/
|
363 |
-
public function testLoadXmlFileWithNotExistingFile()
|
364 |
-
{
|
365 |
-
$document = new Document();
|
366 |
-
|
367 |
-
$document->loadXmlFile('path/to/file');
|
368 |
-
}
|
369 |
-
|
370 |
-
public function testHas()
|
371 |
-
{
|
372 |
-
$document = new Document($this->loadFixture('posts.html'));
|
373 |
-
|
374 |
-
$this->assertTrue($document->has('.posts'));
|
375 |
-
$this->assertFalse($document->has('.fake'));
|
376 |
-
}
|
377 |
-
|
378 |
-
/**
|
379 |
-
* @dataProvider findTests
|
380 |
-
*/
|
381 |
-
public function testFind($html, $selector, $type, $count)
|
382 |
-
{
|
383 |
-
$document = new Document($html);
|
384 |
-
$elements = $document->find($selector, $type);
|
385 |
-
|
386 |
-
$this->assertTrue(is_array($elements));
|
387 |
-
$this->assertEquals($count, count($elements));
|
388 |
-
|
389 |
-
foreach ($elements as $element) {
|
390 |
-
$this->assertInstanceOf('DiDom\Element', $element);
|
391 |
-
}
|
392 |
-
}
|
393 |
-
|
394 |
-
/**
|
395 |
-
* @dataProvider findTests
|
396 |
-
*/
|
397 |
-
public function testFindAndReturnDomElement($html, $selector, $type, $count)
|
398 |
-
{
|
399 |
-
$document = new Document($html);
|
400 |
-
$elements = $document->find($selector, $type, false);
|
401 |
-
|
402 |
-
$this->assertTrue(is_array($elements));
|
403 |
-
$this->assertEquals($count, count($elements));
|
404 |
-
|
405 |
-
foreach ($elements as $element) {
|
406 |
-
$this->assertInstanceOf('DOMElement', $element);
|
407 |
-
}
|
408 |
-
}
|
409 |
-
|
410 |
-
public function testFindWithContext()
|
411 |
-
{
|
412 |
-
$document = new Document($this->loadFixture('posts.html'));
|
413 |
-
|
414 |
-
$post = $document->find('.post')[1];
|
415 |
-
$title = $document->find('.post .title')[1];
|
416 |
-
|
417 |
-
$titleInContext = $document->find('.title', Query::TYPE_CSS, true, $post)[0];
|
418 |
-
|
419 |
-
$this->assertTrue($title->is($titleInContext));
|
420 |
-
$this->assertFalse($title->is($post->find('.title')[0]));
|
421 |
-
}
|
422 |
-
|
423 |
-
public function testFindText()
|
424 |
-
{
|
425 |
-
$html = $this->loadFixture('menu.html');
|
426 |
-
|
427 |
-
$document = new Document($html);
|
428 |
-
$texts = $document->find('//a/text()', Query::TYPE_XPATH);
|
429 |
-
|
430 |
-
$this->assertTrue(is_array($texts));
|
431 |
-
$this->assertEquals(3, count($texts));
|
432 |
-
|
433 |
-
$this->assertEquals(['Link 1', 'Link 2', 'Link 3'], $texts);
|
434 |
-
}
|
435 |
-
|
436 |
-
public function testFindComment()
|
437 |
-
{
|
438 |
-
$html = $this->loadFixture('menu.html');
|
439 |
-
|
440 |
-
$document = new Document($html);
|
441 |
-
|
442 |
-
$comment = $document->xpath('/html/body/ul/li/a/comment()');
|
443 |
-
$this->assertTrue($comment[0]->isCommentNode());
|
444 |
-
$this->assertTrue($comment[1]->isCommentNode());
|
445 |
-
|
446 |
-
$this->assertTrue(is_array($comment));
|
447 |
-
$this->assertEquals(2, count($comment));
|
448 |
-
|
449 |
-
$comment = $document->xpath('/html/body/comment()');
|
450 |
-
$this->assertTrue($comment[0]->isCommentNode());
|
451 |
-
|
452 |
-
$this->assertTrue(is_array($comment));
|
453 |
-
$this->assertEquals(1, count($comment));
|
454 |
-
}
|
455 |
-
|
456 |
-
public function testFindAttribute()
|
457 |
-
{
|
458 |
-
$html = $this->loadFixture('menu.html');
|
459 |
-
|
460 |
-
$document = new Document($html);
|
461 |
-
$links = $document->find('//a/@href', Query::TYPE_XPATH);
|
462 |
-
|
463 |
-
$this->assertTrue(is_array($links));
|
464 |
-
$this->assertEquals(3, count($links));
|
465 |
-
|
466 |
-
foreach ($links as $link) {
|
467 |
-
$this->assertEquals('http://example.com', $link);
|
468 |
-
}
|
469 |
-
}
|
470 |
-
|
471 |
-
public function findTests()
|
472 |
-
{
|
473 |
-
$html = $this->loadFixture('posts.html');
|
474 |
-
|
475 |
-
return array(
|
476 |
-
array($html, '.post h2', Query::TYPE_CSS, 3),
|
477 |
-
array($html, '.fake h2', Query::TYPE_CSS, 0),
|
478 |
-
array($html, '.post h2, .post p', Query::TYPE_CSS, 6),
|
479 |
-
array($html, "//*[contains(concat(' ', normalize-space(@class), ' '), ' post ')]", Query::TYPE_XPATH, 3),
|
480 |
-
);
|
481 |
-
}
|
482 |
-
|
483 |
-
public function testFirst()
|
484 |
-
{
|
485 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
486 |
-
|
487 |
-
$document = new Document($html, false);
|
488 |
-
|
489 |
-
$items = $document->find('ul > li');
|
490 |
-
|
491 |
-
$this->assertEquals($items[0]->getNode(), $document->first('ul > li')->getNode());
|
492 |
-
|
493 |
-
$this->assertEquals('One', $document->first('ul > li::text'));
|
494 |
-
|
495 |
-
$document = new Document();
|
496 |
-
|
497 |
-
$this->assertNull($document->first('ul > li'));
|
498 |
-
}
|
499 |
-
|
500 |
-
public function testFirstWithContext()
|
501 |
-
{
|
502 |
-
$html = '
|
503 |
-
<div class="root">
|
504 |
-
<span>Foo</span>
|
505 |
-
|
506 |
-
<div><span>Bar</span></div>
|
507 |
-
</div>
|
508 |
-
';
|
509 |
-
|
510 |
-
$document = new Document($html);
|
511 |
-
|
512 |
-
$div = $document->first('.root div');
|
513 |
-
$span = $document->first('.root div span');
|
514 |
-
|
515 |
-
$result = $document->first('span', Query::TYPE_CSS, true, $div);
|
516 |
-
|
517 |
-
$this->assertTrue($span->is($result));
|
518 |
-
}
|
519 |
-
|
520 |
-
public function testXpath()
|
521 |
-
{
|
522 |
-
$html = $this->loadFixture('posts.html');
|
523 |
-
|
524 |
-
$document = new Document($html, false);
|
525 |
-
$elements = $document->xpath("//*[contains(concat(' ', normalize-space(@class), ' '), ' post ')]");
|
526 |
-
|
527 |
-
$this->assertTrue(is_array($elements));
|
528 |
-
$this->assertEquals(3, count($elements));
|
529 |
-
|
530 |
-
foreach ($elements as $element) {
|
531 |
-
$this->assertInstanceOf('DiDom\Element', $element);
|
532 |
-
}
|
533 |
-
}
|
534 |
-
|
535 |
-
public function testCount()
|
536 |
-
{
|
537 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
538 |
-
|
539 |
-
$document = new Document($html, false);
|
540 |
-
|
541 |
-
$this->assertInternalType('int', $document->count('li'));
|
542 |
-
$this->assertEquals(3, $document->count('li'));
|
543 |
-
|
544 |
-
$document = new Document();
|
545 |
-
|
546 |
-
$this->assertInternalType('int', $document->count('li'));
|
547 |
-
$this->assertEquals(0, $document->count('li'));
|
548 |
-
}
|
549 |
-
|
550 |
-
public function testCreateXpath()
|
551 |
-
{
|
552 |
-
$document = new Document();
|
553 |
-
|
554 |
-
$xpath =$document->createXpath();
|
555 |
-
|
556 |
-
$this->assertInstanceOf('DOMXPath', $xpath);
|
557 |
-
$this->assertEquals($document->getDocument(), $xpath->document);
|
558 |
-
}
|
559 |
-
|
560 |
-
public function testHtml()
|
561 |
-
{
|
562 |
-
$html = '
|
563 |
-
<!DOCTYPE html>
|
564 |
-
<html lang="en">
|
565 |
-
<head>
|
566 |
-
<meta charset="UTF-8">
|
567 |
-
<title>Document</title>
|
568 |
-
</head>
|
569 |
-
<body>
|
570 |
-
English language <br>
|
571 |
-
Русский язык <br>
|
572 |
-
اللغة العربية <br>
|
573 |
-
漢語 <br>
|
574 |
-
Tiếng Việt <br>
|
575 |
-
|
576 |
-
< >
|
577 |
-
</body>
|
578 |
-
</html>
|
579 |
-
';
|
580 |
-
|
581 |
-
$document = new Document($html);
|
582 |
-
|
583 |
-
$this->assertEquals(trim($html), $document->html());
|
584 |
-
}
|
585 |
-
|
586 |
-
public function testXml()
|
587 |
-
{
|
588 |
-
$xml = $this->loadFixture('books.xml');
|
589 |
-
$document = new Document($xml, false, 'UTF-8', 'xml');
|
590 |
-
|
591 |
-
$this->assertTrue(is_string($document->xml()));
|
592 |
-
}
|
593 |
-
|
594 |
-
public function testXmlWithOptions()
|
595 |
-
{
|
596 |
-
$xml = '<foo><bar></bar></foo>';
|
597 |
-
|
598 |
-
$document = new Document();
|
599 |
-
$document->loadXml($xml);
|
600 |
-
|
601 |
-
$prolog = '<?xml version="1.0" encoding="UTF-8"?>'."\n";
|
602 |
-
|
603 |
-
$this->assertEquals($prolog.'<foo><bar/></foo>', $document->xml());
|
604 |
-
$this->assertEquals($prolog.'<foo><bar></bar></foo>', $document->xml(LIBXML_NOEMPTYTAG));
|
605 |
-
}
|
606 |
-
|
607 |
-
public function testFormat()
|
608 |
-
{
|
609 |
-
$html = $this->loadFixture('posts.html');
|
610 |
-
$document = new Document($html, false);
|
611 |
-
|
612 |
-
$this->assertFalse($document->getDocument()->formatOutput);
|
613 |
-
|
614 |
-
$document->format();
|
615 |
-
|
616 |
-
$this->assertTrue($document->getDocument()->formatOutput);
|
617 |
-
}
|
618 |
-
|
619 |
-
public function testText()
|
620 |
-
{
|
621 |
-
$html = '<html>foo</html>';
|
622 |
-
$document = new Document($html, false);
|
623 |
-
|
624 |
-
$this->assertEquals('foo', $document->text());
|
625 |
-
}
|
626 |
-
|
627 |
-
/**
|
628 |
-
* @expectedException InvalidArgumentException
|
629 |
-
*/
|
630 |
-
public function testIsWithInvalidArgument()
|
631 |
-
{
|
632 |
-
$document = new Document();
|
633 |
-
$document->is(null);
|
634 |
-
}
|
635 |
-
|
636 |
-
public function testIs()
|
637 |
-
{
|
638 |
-
$html = $this->loadFixture('posts.html');
|
639 |
-
|
640 |
-
$document = new Document($html, false);
|
641 |
-
$document2 = new Document($html, false);
|
642 |
-
|
643 |
-
$this->assertTrue($document->is($document));
|
644 |
-
$this->assertFalse($document->is($document2));
|
645 |
-
}
|
646 |
-
|
647 |
-
public function testIsWithEmptyDocument()
|
648 |
-
{
|
649 |
-
$html = $this->loadFixture('posts.html');
|
650 |
-
|
651 |
-
$document = new Document($html, false);
|
652 |
-
$document2 = new Document();
|
653 |
-
|
654 |
-
$this->assertFalse($document->is($document2));
|
655 |
-
}
|
656 |
-
|
657 |
-
public function testGetType()
|
658 |
-
{
|
659 |
-
// empty document
|
660 |
-
|
661 |
-
$document = new Document();
|
662 |
-
|
663 |
-
$this->assertNull($document->getType());
|
664 |
-
|
665 |
-
// html
|
666 |
-
|
667 |
-
$html = $this->loadFixture('posts.html');
|
668 |
-
|
669 |
-
$document = new Document($html);
|
670 |
-
$this->assertEquals('html', $document->getType());
|
671 |
-
|
672 |
-
$document = new Document();
|
673 |
-
$document->loadHtml($html);
|
674 |
-
$this->assertEquals('html', $document->getType());
|
675 |
-
|
676 |
-
$document = new Document();
|
677 |
-
$document->load($html, false, 'html');
|
678 |
-
$this->assertEquals('html', $document->getType());
|
679 |
-
|
680 |
-
// xml
|
681 |
-
|
682 |
-
$xml = $this->loadFixture('books.xml');
|
683 |
-
|
684 |
-
$document = new Document($xml, false, 'UTF-8', 'xml');
|
685 |
-
$this->assertEquals('xml', $document->getType());
|
686 |
-
|
687 |
-
$document = new Document();
|
688 |
-
$document->loadXml($xml);
|
689 |
-
$this->assertEquals('xml', $document->getType());
|
690 |
-
|
691 |
-
$document = new Document();
|
692 |
-
$document->load($xml, false, 'xml');
|
693 |
-
$this->assertEquals('xml', $document->getType());
|
694 |
-
}
|
695 |
-
|
696 |
-
public function testGetEncoding()
|
697 |
-
{
|
698 |
-
$document = new Document();
|
699 |
-
|
700 |
-
$this->assertEquals('UTF-8', $document->getEncoding());
|
701 |
-
|
702 |
-
$document = new Document(null, false, 'CP-1251');
|
703 |
-
|
704 |
-
$this->assertEquals('CP-1251', $document->getEncoding());
|
705 |
-
}
|
706 |
-
|
707 |
-
public function testGetDocument()
|
708 |
-
{
|
709 |
-
$domDocument = new \DOMDocument();
|
710 |
-
$document = new Document($domDocument);
|
711 |
-
|
712 |
-
$this->assertEquals($domDocument, $document->getDocument());
|
713 |
-
}
|
714 |
-
|
715 |
-
public function testGetElement()
|
716 |
-
{
|
717 |
-
$html = $this->loadFixture('posts.html');
|
718 |
-
$document = new Document($html, false);
|
719 |
-
|
720 |
-
$this->assertInstanceOf('DOMElement', $document->getElement());
|
721 |
-
}
|
722 |
-
|
723 |
-
/**
|
724 |
-
* @expectedException RuntimeException
|
725 |
-
*/
|
726 |
-
public function testEmptyDocumentToElement()
|
727 |
-
{
|
728 |
-
$document = new Document();
|
729 |
-
|
730 |
-
$document->toElement();
|
731 |
-
}
|
732 |
-
|
733 |
-
public function testToElement()
|
734 |
-
{
|
735 |
-
$html = $this->loadFixture('posts.html');
|
736 |
-
$document = new Document($html, false);
|
737 |
-
|
738 |
-
$this->assertInstanceOf('DiDom\Element', $document->toElement());
|
739 |
-
}
|
740 |
-
|
741 |
-
public function testToStringHtml()
|
742 |
-
{
|
743 |
-
$html = $this->loadFixture('posts.html');
|
744 |
-
$document = new Document($html, false);
|
745 |
-
|
746 |
-
$this->assertEquals($document->html(), $document->__toString());
|
747 |
-
}
|
748 |
-
|
749 |
-
public function testToStringXml()
|
750 |
-
{
|
751 |
-
$xml = $this->loadFixture('books.xml');
|
752 |
-
$document = new Document($xml, false, 'UTF-8', 'xml');
|
753 |
-
|
754 |
-
$this->assertEquals($document->xml(), $document->__toString());
|
755 |
-
}
|
756 |
-
|
757 |
-
/**
|
758 |
-
* @dataProvider findTests
|
759 |
-
*/
|
760 |
-
public function testInvoke($html, $selector, $type, $count)
|
761 |
-
{
|
762 |
-
$document = new Document($html, false);
|
763 |
-
$elements = $document($selector, $type);
|
764 |
-
|
765 |
-
$this->assertTrue(is_array($elements));
|
766 |
-
$this->assertEquals($count, count($elements));
|
767 |
-
|
768 |
-
foreach ($elements as $element) {
|
769 |
-
$this->assertInstanceOf('DiDom\Element', $element);
|
770 |
-
}
|
771 |
-
}
|
772 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/imangazaliev/didom/tests/DiDom/ElementTest.php
DELETED
@@ -1,2094 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Tests\DiDom;
|
4 |
-
|
5 |
-
use DiDom\Document;
|
6 |
-
use DiDom\Element;
|
7 |
-
use DiDom\Query;
|
8 |
-
use Tests\TestCase;
|
9 |
-
|
10 |
-
class ElementTest extends TestCase
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* @expectedException \InvalidArgumentException
|
14 |
-
*/
|
15 |
-
public function testConstructorWithNullTagName()
|
16 |
-
{
|
17 |
-
new Element(null);
|
18 |
-
}
|
19 |
-
|
20 |
-
/**
|
21 |
-
* @expectedException \InvalidArgumentException
|
22 |
-
*/
|
23 |
-
public function testConstructorWithInvalidTagNameType()
|
24 |
-
{
|
25 |
-
new Element([]);
|
26 |
-
}
|
27 |
-
|
28 |
-
/**
|
29 |
-
* @expectedException \InvalidArgumentException
|
30 |
-
*/
|
31 |
-
public function testConstructorWithInvalidObject()
|
32 |
-
{
|
33 |
-
new Element(new \StdClass());
|
34 |
-
}
|
35 |
-
|
36 |
-
/**
|
37 |
-
* @expectedException \InvalidArgumentException
|
38 |
-
*/
|
39 |
-
public function testConstructorWithInvalidValue()
|
40 |
-
{
|
41 |
-
new Element('span', []);
|
42 |
-
}
|
43 |
-
|
44 |
-
public function testConstructorWithInvalidAttributes()
|
45 |
-
{
|
46 |
-
if (PHP_VERSION_ID >= 70000) {
|
47 |
-
$this->setExpectedException('TypeError');
|
48 |
-
} else {
|
49 |
-
$this->setExpectedException('PHPUnit_Framework_Error');
|
50 |
-
}
|
51 |
-
|
52 |
-
new Element('span', 'Foo', null);
|
53 |
-
}
|
54 |
-
|
55 |
-
public function testConstructor()
|
56 |
-
{
|
57 |
-
$element = new Element('input', null, ['name' => 'username', 'value' => 'John']);
|
58 |
-
|
59 |
-
$this->assertEquals('input', $element->getNode()->tagName);
|
60 |
-
$this->assertEquals('username', $element->getNode()->getAttribute('name'));
|
61 |
-
$this->assertEquals('John', $element->getNode()->getAttribute('value'));
|
62 |
-
|
63 |
-
// create from DOMElement
|
64 |
-
$node = new \DOMElement('span', 'Foo');
|
65 |
-
$element = new Element($node);
|
66 |
-
|
67 |
-
$this->assertEquals($node, $element->getNode());
|
68 |
-
|
69 |
-
// create from DOMText
|
70 |
-
$node = new \DOMText('Foo');
|
71 |
-
$element = new Element($node);
|
72 |
-
|
73 |
-
$this->assertEquals($node, $element->getNode());
|
74 |
-
|
75 |
-
// create from DOMComment
|
76 |
-
$node = new \DOMComment('Foo');
|
77 |
-
$element = new Element($node);
|
78 |
-
|
79 |
-
$this->assertEquals($node, $element->getNode());
|
80 |
-
}
|
81 |
-
|
82 |
-
public function testCreate()
|
83 |
-
{
|
84 |
-
$element = Element::create('span', 'Foo', ['class' => 'bar']);
|
85 |
-
|
86 |
-
$this->assertEquals('span', $element->tag);
|
87 |
-
$this->assertEquals('Foo', $element->text());
|
88 |
-
$this->assertEquals(['class' => 'bar'], $element->attributes());
|
89 |
-
}
|
90 |
-
|
91 |
-
public function testCreateBySelector()
|
92 |
-
{
|
93 |
-
$element = Element::createBySelector('li.item.active', 'Foo', ['data-id' => 1]);
|
94 |
-
|
95 |
-
$this->assertEquals('li', $element->tag);
|
96 |
-
$this->assertEquals('Foo', $element->text());
|
97 |
-
$this->assertEquals(['class' => 'item active', 'data-id' => 1], $element->attributes());
|
98 |
-
}
|
99 |
-
|
100 |
-
/**
|
101 |
-
* @expectedException \InvalidArgumentException
|
102 |
-
*/
|
103 |
-
public function testPrependChildWithInvalidArgument()
|
104 |
-
{
|
105 |
-
$element = new Element('span', 'hello');
|
106 |
-
|
107 |
-
$element->prependChild('foo');
|
108 |
-
}
|
109 |
-
|
110 |
-
/**
|
111 |
-
* @expectedException \LogicException
|
112 |
-
* @expectedExceptionMessage Can not prepend child to element without owner document
|
113 |
-
*/
|
114 |
-
public function testPrependChildWithoutParentNode()
|
115 |
-
{
|
116 |
-
$element = new Element(new \DOMElement('div'));
|
117 |
-
|
118 |
-
$element->prependChild(new Element('div'));
|
119 |
-
}
|
120 |
-
|
121 |
-
public function testPrependChild()
|
122 |
-
{
|
123 |
-
$list = new Element('ul');
|
124 |
-
|
125 |
-
$this->assertEquals(0, $list->getNode()->childNodes->length);
|
126 |
-
|
127 |
-
$item = new Element('li', 'bar');
|
128 |
-
|
129 |
-
$prependedChild = $list->prependChild($item);
|
130 |
-
|
131 |
-
$this->assertEquals(1, $list->getNode()->childNodes->length);
|
132 |
-
$this->assertInstanceOf('DiDom\Element', $prependedChild);
|
133 |
-
$this->assertEquals('bar', $prependedChild->getNode()->textContent);
|
134 |
-
|
135 |
-
$item = new Element('li', 'foo');
|
136 |
-
|
137 |
-
$prependedChild = $list->prependChild($item);
|
138 |
-
|
139 |
-
$this->assertEquals(2, $list->getNode()->childNodes->length);
|
140 |
-
$this->assertInstanceOf('DiDom\Element', $prependedChild);
|
141 |
-
$this->assertEquals('foo', $prependedChild->getNode()->textContent);
|
142 |
-
|
143 |
-
$this->assertEquals('foo', $list->getNode()->childNodes->item(0)->textContent);
|
144 |
-
$this->assertEquals('bar', $list->getNode()->childNodes->item(1)->textContent);
|
145 |
-
}
|
146 |
-
|
147 |
-
public function testPrependChildWithArrayOfNodes()
|
148 |
-
{
|
149 |
-
$list = new Element('ul');
|
150 |
-
|
151 |
-
$prependedChild = $list->prependChild(new Element('li', 'foo'));
|
152 |
-
|
153 |
-
$this->assertEquals(1, $list->getNode()->childNodes->length);
|
154 |
-
$this->assertInstanceOf('DiDom\Element', $prependedChild);
|
155 |
-
$this->assertEquals('foo', $prependedChild->getNode()->textContent);
|
156 |
-
|
157 |
-
$items = [];
|
158 |
-
|
159 |
-
$items[] = new Element('li', 'bar');
|
160 |
-
$items[] = new Element('li', 'baz');
|
161 |
-
|
162 |
-
$appendedChildren = $list->prependChild($items);
|
163 |
-
|
164 |
-
$this->assertCount(2, $appendedChildren);
|
165 |
-
$this->assertEquals(3, $list->getNode()->childNodes->length);
|
166 |
-
|
167 |
-
foreach ($appendedChildren as $appendedChild) {
|
168 |
-
$this->assertInstanceOf('DiDom\Element', $appendedChild);
|
169 |
-
}
|
170 |
-
|
171 |
-
foreach (['bar', 'baz', 'foo'] as $index => $value) {
|
172 |
-
$this->assertEquals($value, $list->getNode()->childNodes->item($index)->textContent);
|
173 |
-
}
|
174 |
-
}
|
175 |
-
|
176 |
-
/**
|
177 |
-
* @expectedException \InvalidArgumentException
|
178 |
-
*/
|
179 |
-
public function testAppendChildWithInvalidArgument()
|
180 |
-
{
|
181 |
-
$element = new Element('span', 'hello');
|
182 |
-
|
183 |
-
$element->appendChild('foo');
|
184 |
-
}
|
185 |
-
|
186 |
-
/**
|
187 |
-
* @expectedException \LogicException
|
188 |
-
* @expectedExceptionMessage Can not append child to element without owner document
|
189 |
-
*/
|
190 |
-
public function testAppendChildWithoutParentNode()
|
191 |
-
{
|
192 |
-
$element = new Element(new \DOMElement('div'));
|
193 |
-
|
194 |
-
$element->appendChild(new Element('div'));
|
195 |
-
}
|
196 |
-
|
197 |
-
public function testAppendChild()
|
198 |
-
{
|
199 |
-
$list = new Element('ul');
|
200 |
-
|
201 |
-
$this->assertEquals(0, $list->getNode()->childNodes->length);
|
202 |
-
|
203 |
-
$item = new Element('li', 'foo');
|
204 |
-
$appendedChild = $list->appendChild($item);
|
205 |
-
|
206 |
-
$this->assertEquals(1, $list->getNode()->childNodes->length);
|
207 |
-
$this->assertInstanceOf('DiDom\Element', $appendedChild);
|
208 |
-
$this->assertEquals('foo', $appendedChild->getNode()->textContent);
|
209 |
-
|
210 |
-
$item = new Element('li', 'bar');
|
211 |
-
$appendedChild = $list->appendChild($item);
|
212 |
-
|
213 |
-
$this->assertEquals(2, $list->getNode()->childNodes->length);
|
214 |
-
$this->assertInstanceOf('DiDom\Element', $appendedChild);
|
215 |
-
$this->assertEquals('bar', $appendedChild->getNode()->textContent);
|
216 |
-
|
217 |
-
$this->assertEquals('foo', $list->getNode()->childNodes->item(0)->textContent);
|
218 |
-
$this->assertEquals('bar', $list->getNode()->childNodes->item(1)->textContent);
|
219 |
-
}
|
220 |
-
|
221 |
-
public function testAppendChildWithArray()
|
222 |
-
{
|
223 |
-
$list = new Element('ul');
|
224 |
-
|
225 |
-
$appendedChild = $list->appendChild(new Element('li', 'foo'));
|
226 |
-
|
227 |
-
$this->assertEquals(1, $list->getNode()->childNodes->length);
|
228 |
-
$this->assertInstanceOf('DiDom\Element', $appendedChild);
|
229 |
-
$this->assertEquals('foo', $appendedChild->getNode()->textContent);
|
230 |
-
|
231 |
-
$items = [];
|
232 |
-
|
233 |
-
$items[] = new Element('li', 'bar');
|
234 |
-
$items[] = new Element('li', 'baz');
|
235 |
-
|
236 |
-
$appendedChildren = $list->appendChild($items);
|
237 |
-
|
238 |
-
$this->assertCount(2, $appendedChildren);
|
239 |
-
$this->assertEquals(3, $list->getNode()->childNodes->length);
|
240 |
-
|
241 |
-
foreach ($appendedChildren as $appendedChild) {
|
242 |
-
$this->assertInstanceOf('DiDom\Element', $appendedChild);
|
243 |
-
}
|
244 |
-
|
245 |
-
foreach (['foo', 'bar', 'baz'] as $index => $value) {
|
246 |
-
$this->assertEquals($value, $list->getNode()->childNodes->item($index)->textContent);
|
247 |
-
}
|
248 |
-
}
|
249 |
-
|
250 |
-
/**
|
251 |
-
* @expectedException \InvalidArgumentException
|
252 |
-
*/
|
253 |
-
public function testInsertBeforeWithInvalidNodeArgument()
|
254 |
-
{
|
255 |
-
$list = new Element('ul');
|
256 |
-
|
257 |
-
$list->insertBefore('foo');
|
258 |
-
}
|
259 |
-
|
260 |
-
/**
|
261 |
-
* @expectedException \InvalidArgumentException
|
262 |
-
* @expectedExceptionMessage Argument 2 passed to DiDom\Element::insertBefore must be an instance of DiDom\Element or DOMNode, string given
|
263 |
-
*/
|
264 |
-
public function testInsertBeforeWithInvalidReferenceNodeArgument()
|
265 |
-
{
|
266 |
-
$list = new Element('ul');
|
267 |
-
|
268 |
-
$list->insertBefore(new Element('li', 'foo'), 'foo');
|
269 |
-
}
|
270 |
-
|
271 |
-
/**
|
272 |
-
* @expectedException \LogicException
|
273 |
-
* @expectedExceptionMessage Can not insert child to element without owner document
|
274 |
-
*/
|
275 |
-
public function testInsertBeforeWithoutParentNode()
|
276 |
-
{
|
277 |
-
$list = new Element(new \DOMElement('ul'));
|
278 |
-
|
279 |
-
$list->insertBefore(new Element('li', 'foo'));
|
280 |
-
}
|
281 |
-
|
282 |
-
public function testInsertBefore()
|
283 |
-
{
|
284 |
-
$list = new Element('ul');
|
285 |
-
|
286 |
-
$insertedNode = $list->insertBefore(new Element('li', 'qux'));
|
287 |
-
|
288 |
-
$this->assertInstanceOf('DiDom\Element', $insertedNode);
|
289 |
-
$this->assertEquals('qux', $insertedNode->getNode()->textContent);
|
290 |
-
|
291 |
-
foreach (['qux'] as $index => $value) {
|
292 |
-
$this->assertEquals($value, $list->getNode()->childNodes->item($index)->textContent);
|
293 |
-
}
|
294 |
-
|
295 |
-
$list->insertBefore(new Element('li', 'foo'), $list->getNode()->childNodes->item(0));
|
296 |
-
|
297 |
-
foreach (['foo', 'qux'] as $index => $value) {
|
298 |
-
$this->assertEquals($value, $list->getNode()->childNodes->item($index)->textContent);
|
299 |
-
}
|
300 |
-
|
301 |
-
$list->insertBefore(new Element('li', 'baz'), $list->getNode()->childNodes->item(1));
|
302 |
-
|
303 |
-
foreach (['foo', 'baz', 'qux'] as $index => $value) {
|
304 |
-
$this->assertEquals($value, $list->getNode()->childNodes->item($index)->textContent);
|
305 |
-
}
|
306 |
-
|
307 |
-
$list->insertBefore(new Element('li', 'bar'), $list->getNode()->childNodes->item(1));
|
308 |
-
|
309 |
-
foreach (['foo', 'bar', 'baz', 'qux'] as $index => $value) {
|
310 |
-
$this->assertEquals($value, $list->getNode()->childNodes->item($index)->textContent);
|
311 |
-
}
|
312 |
-
}
|
313 |
-
|
314 |
-
public function testInsertBeforeWithoutReferenceNode()
|
315 |
-
{
|
316 |
-
$list = new Element('ul');
|
317 |
-
|
318 |
-
$list->insertBefore(new Element('li', 'foo'));
|
319 |
-
$list->insertBefore(new Element('li', 'bar'));
|
320 |
-
|
321 |
-
foreach (['foo', 'bar'] as $index => $value) {
|
322 |
-
$this->assertEquals($value, $list->getNode()->childNodes->item($index)->textContent);
|
323 |
-
}
|
324 |
-
}
|
325 |
-
|
326 |
-
/**
|
327 |
-
* @expectedException \InvalidArgumentException
|
328 |
-
*/
|
329 |
-
public function testInsertAfterWithInvalidNodeArgument()
|
330 |
-
{
|
331 |
-
$list = new Element('ul');
|
332 |
-
|
333 |
-
$list->insertAfter('foo');
|
334 |
-
}
|
335 |
-
|
336 |
-
/**
|
337 |
-
* @expectedException \InvalidArgumentException
|
338 |
-
* @expectedExceptionMessage Argument 2 passed to DiDom\Element::insertAfter must be an instance of DiDom\Element or DOMNode, string given
|
339 |
-
*/
|
340 |
-
public function testInsertAfterWithInvalidReferenceNodeArgument()
|
341 |
-
{
|
342 |
-
$list = new Element('ul');
|
343 |
-
|
344 |
-
$list->insertAfter(new Element('li', 'foo'), 'foo');
|
345 |
-
}
|
346 |
-
|
347 |
-
/**
|
348 |
-
* @expectedException \LogicException
|
349 |
-
* @expectedExceptionMessage Can not insert child to element without owner document
|
350 |
-
*/
|
351 |
-
public function testInsertAfterWithoutParentNode()
|
352 |
-
{
|
353 |
-
$list = new Element(new \DOMElement('ul'));
|
354 |
-
|
355 |
-
$list->insertAfter(new Element('li', 'foo'));
|
356 |
-
}
|
357 |
-
|
358 |
-
public function testInsertAfter()
|
359 |
-
{
|
360 |
-
$list = new Element('ul');
|
361 |
-
|
362 |
-
$insertedNode = $list->insertAfter(new Element('li', 'foo'));
|
363 |
-
|
364 |
-
$this->assertInstanceOf('DiDom\Element', $insertedNode);
|
365 |
-
$this->assertEquals('foo', $insertedNode->getNode()->textContent);
|
366 |
-
|
367 |
-
foreach (['foo'] as $index => $value) {
|
368 |
-
$this->assertEquals($value, $list->getNode()->childNodes->item($index)->textContent);
|
369 |
-
}
|
370 |
-
|
371 |
-
$list->insertAfter(new Element('li', 'qux'), $list->getNode()->childNodes->item(0));
|
372 |
-
|
373 |
-
foreach (['foo', 'qux'] as $index => $value) {
|
374 |
-
$this->assertEquals($value, $list->getNode()->childNodes->item($index)->textContent);
|
375 |
-
}
|
376 |
-
|
377 |
-
$list->insertAfter(new Element('li', 'bar'), $list->getNode()->childNodes->item(0));
|
378 |
-
|
379 |
-
foreach (['foo', 'bar', 'qux'] as $index => $value) {
|
380 |
-
$this->assertEquals($value, $list->getNode()->childNodes->item($index)->textContent);
|
381 |
-
}
|
382 |
-
|
383 |
-
$list->insertAfter(new Element('li', 'baz'), $list->getNode()->childNodes->item(1));
|
384 |
-
|
385 |
-
foreach (['foo', 'bar', 'baz', 'qux'] as $index => $value) {
|
386 |
-
$this->assertEquals($value, $list->getNode()->childNodes->item($index)->textContent);
|
387 |
-
}
|
388 |
-
}
|
389 |
-
|
390 |
-
public function testInsertAfterWithoutReferenceNode()
|
391 |
-
{
|
392 |
-
$list = new Element('ul');
|
393 |
-
|
394 |
-
$list->insertAfter(new Element('li', 'foo'));
|
395 |
-
$list->insertAfter(new Element('li', 'bar'));
|
396 |
-
|
397 |
-
foreach (['foo', 'bar'] as $index => $value) {
|
398 |
-
$this->assertEquals($value, $list->getNode()->childNodes->item($index)->textContent);
|
399 |
-
}
|
400 |
-
}
|
401 |
-
|
402 |
-
public function testHas()
|
403 |
-
{
|
404 |
-
$document = new \DOMDocument();
|
405 |
-
$document->loadHTML('<div><span class="foo">bar</span></div>');
|
406 |
-
|
407 |
-
$node = $document->getElementsByTagName('div')->item(0);
|
408 |
-
$element = new Element($node);
|
409 |
-
|
410 |
-
$this->assertTrue($element->has('.foo'));
|
411 |
-
$this->assertFalse($element->has('.bar'));
|
412 |
-
}
|
413 |
-
|
414 |
-
/**
|
415 |
-
* @dataProvider findTests
|
416 |
-
*/
|
417 |
-
public function testFind($html, $selector, $type, $count)
|
418 |
-
{
|
419 |
-
$document = new \DOMDocument();
|
420 |
-
$document->loadHTML($html);
|
421 |
-
|
422 |
-
$domElement = $document->getElementsByTagName('body')->item(0);
|
423 |
-
$element = new Element($domElement);
|
424 |
-
|
425 |
-
$elements = $element->find($selector, $type);
|
426 |
-
|
427 |
-
$this->assertTrue(is_array($elements));
|
428 |
-
$this->assertEquals($count, count($elements));
|
429 |
-
|
430 |
-
foreach ($elements as $element) {
|
431 |
-
$this->assertInstanceOf('DiDom\Element', $element);
|
432 |
-
}
|
433 |
-
}
|
434 |
-
|
435 |
-
/**
|
436 |
-
* @expectedException \LogicException
|
437 |
-
*/
|
438 |
-
public function testFindInDocumentWithoutOwnerDocument()
|
439 |
-
{
|
440 |
-
$element = new Element(new \DOMElement('div'));
|
441 |
-
|
442 |
-
$element->findInDocument('.foo');
|
443 |
-
}
|
444 |
-
|
445 |
-
public function testFindInDocument()
|
446 |
-
{
|
447 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
448 |
-
|
449 |
-
$document = new Document($html);
|
450 |
-
|
451 |
-
$items = $document->find('li');
|
452 |
-
$list = $document->first('ul');
|
453 |
-
|
454 |
-
foreach ($list->find('li') as $index => $item) {
|
455 |
-
$this->assertFalse($item->is($items[$index]));
|
456 |
-
}
|
457 |
-
|
458 |
-
foreach ($list->findInDocument('li') as $index => $item) {
|
459 |
-
$this->assertTrue($item->is($items[$index]));
|
460 |
-
}
|
461 |
-
|
462 |
-
$this->assertCount(3, $document->find('li'));
|
463 |
-
|
464 |
-
$list->findInDocument('li')[0]->remove();
|
465 |
-
|
466 |
-
$this->assertCount(2, $document->find('li'));
|
467 |
-
}
|
468 |
-
|
469 |
-
/**
|
470 |
-
* @expectedException \LogicException
|
471 |
-
*/
|
472 |
-
public function testFirstInDocumentWithoutOwnerDocument()
|
473 |
-
{
|
474 |
-
$element = new Element(new \DOMElement('div'));
|
475 |
-
|
476 |
-
$element->firstInDocument('.foo');
|
477 |
-
}
|
478 |
-
|
479 |
-
public function testFirstInDocument()
|
480 |
-
{
|
481 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
482 |
-
|
483 |
-
$document = new Document($html);
|
484 |
-
|
485 |
-
$item = $document->first('li');
|
486 |
-
$list = $document->first('ul');
|
487 |
-
|
488 |
-
$this->assertFalse($item->is($list->first('li')));
|
489 |
-
$this->assertTrue($item->is($list->firstInDocument('li')));
|
490 |
-
|
491 |
-
$this->assertCount(3, $document->find('li'));
|
492 |
-
|
493 |
-
$list->findInDocument('li')[0]->remove();
|
494 |
-
|
495 |
-
$this->assertCount(2, $document->find('li'));
|
496 |
-
}
|
497 |
-
|
498 |
-
public function testFirst()
|
499 |
-
{
|
500 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
501 |
-
|
502 |
-
$document = new Document($html);
|
503 |
-
|
504 |
-
$list = $document->first('ul');
|
505 |
-
|
506 |
-
$item = $list->getNode()->childNodes->item(0);
|
507 |
-
|
508 |
-
$this->assertEquals($item, $list->first('li')->getNode());
|
509 |
-
|
510 |
-
$list = new Element('ul');
|
511 |
-
|
512 |
-
$this->assertNull($list->first('li'));
|
513 |
-
}
|
514 |
-
|
515 |
-
/**
|
516 |
-
* @dataProvider findTests
|
517 |
-
*/
|
518 |
-
public function testFindAndReturnDomElement($html, $selector, $type, $count)
|
519 |
-
{
|
520 |
-
$document = new \DOMDocument();
|
521 |
-
$document->loadHTML($html);
|
522 |
-
|
523 |
-
$node = $document->getElementsByTagName('body')->item(0);
|
524 |
-
$element = new Element($node);
|
525 |
-
|
526 |
-
$elements = $element->find($selector, $type, false);
|
527 |
-
|
528 |
-
$this->assertTrue(is_array($elements));
|
529 |
-
$this->assertEquals($count, count($elements));
|
530 |
-
|
531 |
-
foreach ($elements as $element) {
|
532 |
-
$this->assertInstanceOf('DOMElement', $element);
|
533 |
-
}
|
534 |
-
}
|
535 |
-
|
536 |
-
public function findTests()
|
537 |
-
{
|
538 |
-
$html = $this->loadFixture('posts.html');
|
539 |
-
|
540 |
-
return array(
|
541 |
-
array($html, '.post h2', Query::TYPE_CSS, 3),
|
542 |
-
array($html, '.fake h2', Query::TYPE_CSS, 0),
|
543 |
-
array($html, '.post h2, .post p', Query::TYPE_CSS, 6),
|
544 |
-
array($html, "//*[contains(concat(' ', normalize-space(@class), ' '), ' post ')]", Query::TYPE_XPATH, 3),
|
545 |
-
);
|
546 |
-
}
|
547 |
-
|
548 |
-
public function testXpath()
|
549 |
-
{
|
550 |
-
$html = $this->loadFixture('posts.html');
|
551 |
-
|
552 |
-
$document = new \DOMDocument();
|
553 |
-
$document->loadHTML($html);
|
554 |
-
|
555 |
-
$node = $document->getElementsByTagName('body')->item(0);
|
556 |
-
$element = new Element($node);
|
557 |
-
|
558 |
-
$elements = $element->xpath("//*[contains(concat(' ', normalize-space(@class), ' '), ' post ')]");
|
559 |
-
|
560 |
-
$this->assertTrue(is_array($elements));
|
561 |
-
$this->assertEquals(3, count($elements));
|
562 |
-
|
563 |
-
foreach ($elements as $element) {
|
564 |
-
$this->assertInstanceOf('DiDom\Element', $element);
|
565 |
-
}
|
566 |
-
}
|
567 |
-
|
568 |
-
public function testCount()
|
569 |
-
{
|
570 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
571 |
-
|
572 |
-
$document = new Document($html, false);
|
573 |
-
$list = $document->first('ul');
|
574 |
-
|
575 |
-
$this->assertEquals(3, $list->count('li'));
|
576 |
-
|
577 |
-
$document = new Element('ul');
|
578 |
-
|
579 |
-
$this->assertEquals(0, $document->count('li'));
|
580 |
-
}
|
581 |
-
|
582 |
-
/**
|
583 |
-
* @expectedException \InvalidArgumentException
|
584 |
-
*/
|
585 |
-
public function testMatchesWithInvalidSelectorType()
|
586 |
-
{
|
587 |
-
$element = new Element('p');
|
588 |
-
|
589 |
-
$element->matches(null);
|
590 |
-
}
|
591 |
-
|
592 |
-
/**
|
593 |
-
* @expectedException \RuntimeException
|
594 |
-
*/
|
595 |
-
public function testMatchesStrictWithoutTagName()
|
596 |
-
{
|
597 |
-
$element = new Element('ul', null, ['id' => 'foo', 'class' => 'bar baz']);
|
598 |
-
|
599 |
-
$element->matches('#foo.bar.baz', true);
|
600 |
-
}
|
601 |
-
|
602 |
-
public function testMatches()
|
603 |
-
{
|
604 |
-
$element = new Element('ul', null, ['id' => 'foo', 'class' => 'bar baz']);
|
605 |
-
|
606 |
-
$this->assertTrue($element->matches('ul'));
|
607 |
-
$this->assertTrue($element->matches('#foo'));
|
608 |
-
$this->assertTrue($element->matches('.bar'));
|
609 |
-
$this->assertTrue($element->matches('ul#foo.bar.baz'));
|
610 |
-
$this->assertFalse($element->matches('a#foo.bar.baz'));
|
611 |
-
|
612 |
-
// strict
|
613 |
-
$this->assertTrue($element->matches('ul#foo.bar.baz', true));
|
614 |
-
$this->assertFalse($element->matches('ul#foo.bar', true));
|
615 |
-
$this->assertFalse($element->matches('ul#foo', true));
|
616 |
-
$this->assertFalse($element->matches('ul.bar.baz', true));
|
617 |
-
$this->assertFalse($element->matches('ul.bar.baz', true));
|
618 |
-
|
619 |
-
$element = new Element('p');
|
620 |
-
|
621 |
-
$this->assertTrue($element->matches('p', true));
|
622 |
-
|
623 |
-
$html = '<!DOCTYPE html>
|
624 |
-
<html lang="en">
|
625 |
-
<head>
|
626 |
-
<meta charset="UTF-8">
|
627 |
-
<title>Document</title>
|
628 |
-
</head>
|
629 |
-
<body>
|
630 |
-
<a href="#"><img src="foo.jpg" alt="Foo"></a>
|
631 |
-
</body>
|
632 |
-
</html>';
|
633 |
-
|
634 |
-
$document = new Document($html, false);
|
635 |
-
$anchor = $document->first('a');
|
636 |
-
|
637 |
-
$this->assertTrue($anchor->matches('a:has(img[src$=".jpg"])'));
|
638 |
-
$this->assertTrue($anchor->matches('a img'));
|
639 |
-
$this->assertFalse($anchor->matches('a img[alt="Bar"]'));
|
640 |
-
$this->assertFalse($anchor->matches('img'));
|
641 |
-
|
642 |
-
$textNode = new \DOMText('Foo');
|
643 |
-
$element = new Element($textNode);
|
644 |
-
|
645 |
-
$this->assertFalse($element->matches('#foo'));
|
646 |
-
|
647 |
-
$commentNode = new \DOMComment('Foo');
|
648 |
-
$element = new Element($commentNode);
|
649 |
-
|
650 |
-
$this->assertFalse($element->matches('#foo'));
|
651 |
-
}
|
652 |
-
|
653 |
-
public function testHasAttribute()
|
654 |
-
{
|
655 |
-
$node = $this->createDomElement('input');
|
656 |
-
$element = new Element($node);
|
657 |
-
|
658 |
-
$this->assertFalse($element->hasAttribute('value'));
|
659 |
-
|
660 |
-
$node->setAttribute('value', 'test');
|
661 |
-
|
662 |
-
$this->assertTrue($element->hasAttribute('value'));
|
663 |
-
}
|
664 |
-
|
665 |
-
/**
|
666 |
-
* @expectedException \InvalidArgumentException
|
667 |
-
*/
|
668 |
-
public function testSetAttributeWithInvalidValue()
|
669 |
-
{
|
670 |
-
$element = new Element('input');
|
671 |
-
$element->setAttribute('value', []);
|
672 |
-
}
|
673 |
-
|
674 |
-
public function testSetAttribute()
|
675 |
-
{
|
676 |
-
$node = $this->createDomElement('input');
|
677 |
-
|
678 |
-
$element = new Element($node);
|
679 |
-
|
680 |
-
$element->setAttribute('value', 'foo');
|
681 |
-
$this->assertEquals('foo', $element->getNode()->getAttribute('value'));
|
682 |
-
|
683 |
-
$element->setAttribute('value', 10);
|
684 |
-
$this->assertEquals('10', $element->getNode()->getAttribute('value'));
|
685 |
-
|
686 |
-
$element->setAttribute('value', 3.14);
|
687 |
-
$this->assertEquals('3.14', $element->getNode()->getAttribute('value'));
|
688 |
-
}
|
689 |
-
|
690 |
-
public function testGetAttribute()
|
691 |
-
{
|
692 |
-
$node = $this->createDomElement('input');
|
693 |
-
|
694 |
-
$element = new Element($node);
|
695 |
-
|
696 |
-
$this->assertEquals(null, $element->getAttribute('value'));
|
697 |
-
$this->assertEquals('default', $element->getAttribute('value', 'default'));
|
698 |
-
|
699 |
-
$node->setAttribute('value', 'test');
|
700 |
-
|
701 |
-
$this->assertEquals('test', $element->getAttribute('value'));
|
702 |
-
}
|
703 |
-
|
704 |
-
public function testRemoveAttribute()
|
705 |
-
{
|
706 |
-
$domElement = $this->createDomElement('input', null, ['name' => 'username']);
|
707 |
-
|
708 |
-
$element = new Element($domElement);
|
709 |
-
|
710 |
-
$this->assertTrue($element->getNode()->hasAttribute('name'));
|
711 |
-
|
712 |
-
$result = $element->removeAttribute('name');
|
713 |
-
|
714 |
-
$this->assertEquals(0, $element->getNode()->attributes->length);
|
715 |
-
$this->assertFalse($element->getNode()->hasAttribute('name'));
|
716 |
-
$this->assertEquals($result, $element);
|
717 |
-
}
|
718 |
-
|
719 |
-
public function testRemoveAllAttributes()
|
720 |
-
{
|
721 |
-
$attributes = ['type' => 'text', 'name' => 'username'];
|
722 |
-
|
723 |
-
$domElement = $this->createDomElement('input', null, $attributes);
|
724 |
-
|
725 |
-
$element = new Element($domElement);
|
726 |
-
|
727 |
-
$result = $element->removeAllAttributes();
|
728 |
-
|
729 |
-
$this->assertEquals(0, $element->getNode()->attributes->length);
|
730 |
-
$this->assertEquals($result, $element);
|
731 |
-
}
|
732 |
-
|
733 |
-
public function testRemoveAllAttributesWithExclusion()
|
734 |
-
{
|
735 |
-
$attributes = ['type' => 'text', 'name' => 'username'];
|
736 |
-
|
737 |
-
$domElement = $this->createDomElement('input', null, $attributes);
|
738 |
-
|
739 |
-
$element = new Element($domElement);
|
740 |
-
|
741 |
-
$element->removeAllAttributes(['name']);
|
742 |
-
|
743 |
-
$this->assertEquals(1, $element->getNode()->attributes->length);
|
744 |
-
$this->assertEquals('username', $element->getNode()->getAttribute('name'));
|
745 |
-
}
|
746 |
-
|
747 |
-
public function testAttrSet()
|
748 |
-
{
|
749 |
-
$element = new Element('input');
|
750 |
-
|
751 |
-
$element->attr('name', 'username');
|
752 |
-
|
753 |
-
$this->assertEquals('username', $element->getNode()->getAttribute('name'));
|
754 |
-
}
|
755 |
-
|
756 |
-
public function testAttrGet()
|
757 |
-
{
|
758 |
-
$element = new Element('input', null, ['name' => 'username']);
|
759 |
-
|
760 |
-
$this->assertEquals('username', $element->attr('name'));
|
761 |
-
}
|
762 |
-
|
763 |
-
public function testAttributes()
|
764 |
-
{
|
765 |
-
$attributes = ['type' => 'text', 'name' => 'username', 'value' => 'John'];
|
766 |
-
|
767 |
-
$domElement = $this->createDomElement('input', null, $attributes);
|
768 |
-
|
769 |
-
$element = new Element($domElement);
|
770 |
-
|
771 |
-
$this->assertEquals($attributes, $element->attributes());
|
772 |
-
$this->assertEquals(['name' => 'username', 'value' => 'John'], $element->attributes(['name', 'value']));
|
773 |
-
}
|
774 |
-
|
775 |
-
|
776 |
-
public function testAttributesWithText()
|
777 |
-
{
|
778 |
-
$element = new Element(new \DOMText('Foo'));
|
779 |
-
|
780 |
-
$this->assertNull($element->attributes());
|
781 |
-
}
|
782 |
-
|
783 |
-
|
784 |
-
public function testAttributesWithComment()
|
785 |
-
{
|
786 |
-
$element = new Element(new \DOMComment('Foo'));
|
787 |
-
|
788 |
-
$this->assertNull($element->attributes());
|
789 |
-
}
|
790 |
-
|
791 |
-
/**
|
792 |
-
* @expectedException \LogicException
|
793 |
-
* @expectedExceptionMessage Style attribute is available only for element nodes
|
794 |
-
*/
|
795 |
-
public function testStyleWithTextNode()
|
796 |
-
{
|
797 |
-
$element = new Element(new \DOMText('foo'));
|
798 |
-
|
799 |
-
$element->style();
|
800 |
-
}
|
801 |
-
|
802 |
-
/**
|
803 |
-
* @expectedException \LogicException
|
804 |
-
* @expectedExceptionMessage Style attribute is available only for element nodes
|
805 |
-
*/
|
806 |
-
public function testStyleWithCommentNode()
|
807 |
-
{
|
808 |
-
$element = new Element(new \DOMComment('foo'));
|
809 |
-
|
810 |
-
$element->style();
|
811 |
-
}
|
812 |
-
|
813 |
-
public function testStyle()
|
814 |
-
{
|
815 |
-
$element = new Element('div');
|
816 |
-
|
817 |
-
$styleAttribute = $element->style();
|
818 |
-
|
819 |
-
$this->assertInstanceOf('DiDom\\StyleAttribute', $styleAttribute);
|
820 |
-
$this->assertSame($element, $styleAttribute->getElement());
|
821 |
-
|
822 |
-
$this->assertSame($styleAttribute, $element->style());
|
823 |
-
|
824 |
-
$element2 = new Element('div');
|
825 |
-
|
826 |
-
$this->assertNotSame($element->style(), $element2->style());
|
827 |
-
}
|
828 |
-
|
829 |
-
public function testHtml()
|
830 |
-
{
|
831 |
-
$element = new Element('span', 'hello');
|
832 |
-
|
833 |
-
$this->assertEquals('<span>hello</span>', $element->html());
|
834 |
-
}
|
835 |
-
|
836 |
-
public function testOuterHtml()
|
837 |
-
{
|
838 |
-
$innerHtml = 'Plain text <span>Lorem ipsum.</span><span>Lorem ipsum.</span>';
|
839 |
-
$html = "<div id=\"foo\" class=\"bar baz\">$innerHtml</div>";
|
840 |
-
|
841 |
-
$document = new Document($html);
|
842 |
-
|
843 |
-
$this->assertEquals('<div id="foo" class="bar baz"></div>', $document->first('#foo')->outerHtml());
|
844 |
-
}
|
845 |
-
|
846 |
-
public function testInnerHtml()
|
847 |
-
{
|
848 |
-
$innerHtml = ' Plain text <span>Lorem ipsum.</span><span>Lorem ipsum.</span>';
|
849 |
-
$html = "<div id=\"root\">$innerHtml</div>";
|
850 |
-
|
851 |
-
$document = new Document($html);
|
852 |
-
|
853 |
-
$this->assertEquals($innerHtml, $document->first('#root')->innerHtml());
|
854 |
-
|
855 |
-
$html = '
|
856 |
-
<!DOCTYPE html>
|
857 |
-
<html lang="en">
|
858 |
-
<head>
|
859 |
-
<meta charset="UTF-8">
|
860 |
-
<title>Document</title>
|
861 |
-
</head>
|
862 |
-
<body>
|
863 |
-
English language <br>
|
864 |
-
Русский язык <br>
|
865 |
-
اللغة العربية <br>
|
866 |
-
漢語 <br>
|
867 |
-
Tiếng Việt <br>
|
868 |
-
|
869 |
-
< >
|
870 |
-
</body>
|
871 |
-
</html>
|
872 |
-
';
|
873 |
-
|
874 |
-
$expectedContent = '
|
875 |
-
English language <br>
|
876 |
-
Русский язык <br>
|
877 |
-
اللغة العربية <br>
|
878 |
-
漢語 <br>
|
879 |
-
Tiếng Việt <br>
|
880 |
-
|
881 |
-
< >
|
882 |
-
';
|
883 |
-
|
884 |
-
$document = new Document($html);
|
885 |
-
|
886 |
-
$this->assertEquals($expectedContent, $document->first('body')->innerHtml());
|
887 |
-
}
|
888 |
-
|
889 |
-
public function testInnerHtmlOnXmlElement()
|
890 |
-
{
|
891 |
-
$innerXml = 'Plain text <span>Lorem <single-tag/> ipsum.</span><span>Lorem ipsum.</span>';
|
892 |
-
$xml = "<div id=\"root\">$innerXml</div>";
|
893 |
-
|
894 |
-
$document = new Document($xml, false, 'UTF-8', Document::TYPE_XML);
|
895 |
-
|
896 |
-
$expectedXml = 'Plain text <span>Lorem <single-tag></single-tag> ipsum.</span><span>Lorem ipsum.</span>';
|
897 |
-
|
898 |
-
$this->assertEquals($expectedXml, $document->first('#root')->innerHtml());
|
899 |
-
}
|
900 |
-
|
901 |
-
public function testInnerXml()
|
902 |
-
{
|
903 |
-
$innerXml = 'Plain text <span>Lorem <single-tag/> ipsum.</span><span>Lorem ipsum.</span>';
|
904 |
-
$xml = "<div id=\"root\">$innerXml</div>";
|
905 |
-
|
906 |
-
$document = new Document($xml, false, 'UTF-8', Document::TYPE_XML);
|
907 |
-
|
908 |
-
$this->assertEquals($innerXml, $document->first('#root')->innerXml());
|
909 |
-
}
|
910 |
-
|
911 |
-
public function testSetInnerHtml()
|
912 |
-
{
|
913 |
-
$list = new Element('ul');
|
914 |
-
|
915 |
-
$html = '<li>One</li><li>Two</li><li>Three</li>';
|
916 |
-
|
917 |
-
$this->assertEquals($list, $list->setInnerHtml($html));
|
918 |
-
$this->assertEquals(['One', 'Two', 'Three'], $list->find('li::text'));
|
919 |
-
|
920 |
-
// check inner HTML rewrite works
|
921 |
-
|
922 |
-
$html = '<li>Foo</li><li>Bar</li><li>Baz</li>';
|
923 |
-
|
924 |
-
$this->assertEquals($list, $list->setInnerHtml($html));
|
925 |
-
$this->assertEquals(['Foo', 'Bar', 'Baz'], $list->find('li::text'));
|
926 |
-
|
927 |
-
$html = '<div id="root"></div>';
|
928 |
-
$innerHtml = ' Plain text <span>Lorem ipsum.</span><span>Lorem ipsum.</span>';
|
929 |
-
|
930 |
-
$document = new Document($html, false);
|
931 |
-
|
932 |
-
$document->first('#root')->setInnerHtml($innerHtml);
|
933 |
-
|
934 |
-
$this->assertEquals($innerHtml, $document->first('#root')->innerHtml());
|
935 |
-
}
|
936 |
-
|
937 |
-
public function testXml()
|
938 |
-
{
|
939 |
-
$element = new Element('span', 'hello');
|
940 |
-
|
941 |
-
$prolog = '<?xml version="1.0" encoding="UTF-8"?>'."\n";
|
942 |
-
|
943 |
-
$this->assertEquals($prolog.'<span>hello</span>', $element->xml());
|
944 |
-
}
|
945 |
-
|
946 |
-
public function testXmlWithOptions()
|
947 |
-
{
|
948 |
-
$html = '<html><body><span></span></body></html>';
|
949 |
-
|
950 |
-
$document = new Document();
|
951 |
-
$document->loadHtml($html);
|
952 |
-
|
953 |
-
$element = $document->find('span')[0];
|
954 |
-
|
955 |
-
$prolog = '<?xml version="1.0" encoding="UTF-8"?>'."\n";
|
956 |
-
|
957 |
-
$this->assertEquals($prolog.'<span/>', $element->xml());
|
958 |
-
$this->assertEquals($prolog.'<span></span>', $element->xml(LIBXML_NOEMPTYTAG));
|
959 |
-
}
|
960 |
-
|
961 |
-
public function testGetText()
|
962 |
-
{
|
963 |
-
$element = new Element('span', 'hello');
|
964 |
-
|
965 |
-
$this->assertEquals('hello', $element->text());
|
966 |
-
}
|
967 |
-
|
968 |
-
public function testSetValue()
|
969 |
-
{
|
970 |
-
$element = new Element('span', 'hello');
|
971 |
-
$element->setValue('test');
|
972 |
-
|
973 |
-
$this->assertEquals('test', $element->text());
|
974 |
-
}
|
975 |
-
|
976 |
-
public function testIsElementNode()
|
977 |
-
{
|
978 |
-
$element = new Element('div');
|
979 |
-
|
980 |
-
$element->setInnerHtml(' Foo <span>Bar</span><!-- Baz -->');
|
981 |
-
|
982 |
-
$children = $element->children();
|
983 |
-
|
984 |
-
$this->assertFalse($children[0]->isElementNode());
|
985 |
-
$this->assertTrue($children[1]->isElementNode());
|
986 |
-
$this->assertFalse($children[2]->isElementNode());
|
987 |
-
}
|
988 |
-
|
989 |
-
public function testIsTextNode()
|
990 |
-
{
|
991 |
-
$element = new Element('div');
|
992 |
-
|
993 |
-
$element->setInnerHtml(' Foo <span>Bar</span><!-- Baz -->');
|
994 |
-
|
995 |
-
$children = $element->children();
|
996 |
-
|
997 |
-
$this->assertTrue($children[0]->isTextNode());
|
998 |
-
$this->assertFalse($children[1]->isTextNode());
|
999 |
-
$this->assertFalse($children[2]->isTextNode());
|
1000 |
-
}
|
1001 |
-
|
1002 |
-
public function testIsCommentNode()
|
1003 |
-
{
|
1004 |
-
$element = new Element('div');
|
1005 |
-
|
1006 |
-
$element->setInnerHtml(' Foo <span>Bar</span><!-- Baz -->');
|
1007 |
-
|
1008 |
-
$children = $element->children();
|
1009 |
-
|
1010 |
-
$this->assertFalse($children[0]->isCommentNode());
|
1011 |
-
$this->assertFalse($children[1]->isCommentNode());
|
1012 |
-
$this->assertTrue($children[2]->isCommentNode());
|
1013 |
-
}
|
1014 |
-
|
1015 |
-
public function testIs()
|
1016 |
-
{
|
1017 |
-
$element = new Element('span', 'hello');
|
1018 |
-
$element2 = new Element('span', 'hello');
|
1019 |
-
|
1020 |
-
$this->assertTrue($element->is($element));
|
1021 |
-
$this->assertFalse($element->is($element2));
|
1022 |
-
}
|
1023 |
-
|
1024 |
-
/**
|
1025 |
-
* @expectedException \InvalidArgumentException
|
1026 |
-
*/
|
1027 |
-
public function testIsWithInvalidArgument()
|
1028 |
-
{
|
1029 |
-
$element = new Element('span', 'hello');
|
1030 |
-
$element->is(null);
|
1031 |
-
}
|
1032 |
-
|
1033 |
-
public function testParent()
|
1034 |
-
{
|
1035 |
-
$html = $this->loadFixture('posts.html');
|
1036 |
-
$document = new Document($html, false);
|
1037 |
-
$element = $document->createElement('span', 'value');
|
1038 |
-
|
1039 |
-
$this->assertEquals($document->getDocument(), $element->getDocument()->getDocument());
|
1040 |
-
}
|
1041 |
-
|
1042 |
-
public function testClosest()
|
1043 |
-
{
|
1044 |
-
// without body and html tags
|
1045 |
-
$html = '
|
1046 |
-
<nav>
|
1047 |
-
<ul class="menu">
|
1048 |
-
<li><a href="#">Foo</a></li>
|
1049 |
-
<li><a href="#">Bar</a></li>
|
1050 |
-
<li><a href="#">Baz</a></li>
|
1051 |
-
</ul>
|
1052 |
-
</nav>
|
1053 |
-
';
|
1054 |
-
|
1055 |
-
$document = new Document($html);
|
1056 |
-
|
1057 |
-
$menu = $document->first('.menu');
|
1058 |
-
$link = $document->first('a');
|
1059 |
-
|
1060 |
-
$this->assertNull($link->closest('.unknown-class'));
|
1061 |
-
$this->assertEquals($menu, $link->closest('.menu'));
|
1062 |
-
|
1063 |
-
$html = '<!DOCTYPE html>
|
1064 |
-
<html>
|
1065 |
-
<body>
|
1066 |
-
<nav></nav>
|
1067 |
-
<ul class="menu">
|
1068 |
-
<li><a href="#">Foo</a></li>
|
1069 |
-
<li><a href="#">Bar</a></li>
|
1070 |
-
<li><a href="#">Baz</a></li>
|
1071 |
-
</ul>
|
1072 |
-
</body>
|
1073 |
-
</html>';
|
1074 |
-
|
1075 |
-
$document = new Document($html);
|
1076 |
-
|
1077 |
-
$this->assertNull($document->first('ul.menu')->closest('nav'));
|
1078 |
-
}
|
1079 |
-
|
1080 |
-
// =========================
|
1081 |
-
// previousSibling
|
1082 |
-
// =========================
|
1083 |
-
|
1084 |
-
public function testPreviousSibling()
|
1085 |
-
{
|
1086 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
1087 |
-
|
1088 |
-
$document = new Document($html, false);
|
1089 |
-
|
1090 |
-
$list = $document->first('ul')->getNode();
|
1091 |
-
|
1092 |
-
$item = $list->childNodes->item(0);
|
1093 |
-
$item = new Element($item);
|
1094 |
-
|
1095 |
-
$this->assertNull($item->previousSibling());
|
1096 |
-
|
1097 |
-
$item = $list->childNodes->item(1);
|
1098 |
-
$item = new Element($item);
|
1099 |
-
|
1100 |
-
$expectedNode = $list->childNodes->item(0);
|
1101 |
-
|
1102 |
-
$this->assertEquals($expectedNode, $item->previousSibling()->getNode());
|
1103 |
-
}
|
1104 |
-
|
1105 |
-
public function testPreviousSiblingWithTextNode()
|
1106 |
-
{
|
1107 |
-
$html = '<p>Foo <span>Bar</span> Baz</p>';
|
1108 |
-
|
1109 |
-
$document = new Document($html, false);
|
1110 |
-
|
1111 |
-
$span = $document->first('span');
|
1112 |
-
|
1113 |
-
$expectedNode = $span->getNode()->previousSibling;
|
1114 |
-
|
1115 |
-
$this->assertEquals($expectedNode, $span->previousSibling()->getNode());
|
1116 |
-
}
|
1117 |
-
|
1118 |
-
public function testPreviousSiblingWithCommentNode()
|
1119 |
-
{
|
1120 |
-
$html = '<p><!-- Foo --><span>Bar</span> Baz</p>';
|
1121 |
-
|
1122 |
-
$document = new Document($html, false);
|
1123 |
-
|
1124 |
-
$span = $document->first('span');
|
1125 |
-
|
1126 |
-
$expectedNode = $span->getNode()->previousSibling;
|
1127 |
-
|
1128 |
-
$this->assertEquals($expectedNode, $span->previousSibling()->getNode());
|
1129 |
-
}
|
1130 |
-
|
1131 |
-
public function testPreviousSiblingWithSelector()
|
1132 |
-
{
|
1133 |
-
$html =
|
1134 |
-
'<ul>'.
|
1135 |
-
'<li><a href="https://amazon.com">Amazon</a></li>'.
|
1136 |
-
'<li><a href="https://facebook.com">Facebook</a></li>'.
|
1137 |
-
'<li><a href="https://google.com">Google</a></li>'.
|
1138 |
-
'<li><a href="https://www.w3.org">W3C</a></li>'.
|
1139 |
-
'<li><a href="https://wikipedia.org">Wikipedia</a></li>'.
|
1140 |
-
'</ul>'
|
1141 |
-
;
|
1142 |
-
|
1143 |
-
$document = new Document($html, false);
|
1144 |
-
|
1145 |
-
$list = $document->first('ul');
|
1146 |
-
|
1147 |
-
$item = $list->getNode()->childNodes->item(4);
|
1148 |
-
$item = new Element($item);
|
1149 |
-
|
1150 |
-
$expectedNode = $list->getNode()->childNodes->item(2);
|
1151 |
-
|
1152 |
-
$this->assertEquals($expectedNode, $item->previousSibling('li:has(a[href$=".com"])')->getNode());
|
1153 |
-
}
|
1154 |
-
|
1155 |
-
public function testPreviousSiblingWithNodeType()
|
1156 |
-
{
|
1157 |
-
$html = '<p>Foo <span>Bar</span><!--qwe--> Baz <span>Qux</span></p>';
|
1158 |
-
|
1159 |
-
$document = new Document($html, false);
|
1160 |
-
|
1161 |
-
$paragraph = $document->first('p');
|
1162 |
-
$span = $document->find('span')[1];
|
1163 |
-
|
1164 |
-
$expectedNode = $paragraph->getNode()->childNodes->item(1);
|
1165 |
-
$this->assertEquals($expectedNode, $span->previousSibling(null, 'DOMElement')->getNode());
|
1166 |
-
|
1167 |
-
$expectedNode = $paragraph->getNode()->childNodes->item(2);
|
1168 |
-
$this->assertEquals($expectedNode, $span->previousSibling(null, 'DOMComment')->getNode());
|
1169 |
-
}
|
1170 |
-
|
1171 |
-
/**
|
1172 |
-
* @expectedException \InvalidArgumentException
|
1173 |
-
*/
|
1174 |
-
public function testPreviousSiblingWithInvalidTypeOfNodeTypeArgument()
|
1175 |
-
{
|
1176 |
-
$html = '<p>Foo <span>Bar</span><!--qwe--> Baz <span>Qux</span></p>';
|
1177 |
-
|
1178 |
-
$document = new Document($html, false);
|
1179 |
-
|
1180 |
-
$span = $document->find('span')[1];
|
1181 |
-
|
1182 |
-
$span->previousSibling(null, []);
|
1183 |
-
}
|
1184 |
-
|
1185 |
-
/**
|
1186 |
-
* @expectedException \RuntimeException
|
1187 |
-
*/
|
1188 |
-
public function testPreviousSiblingWithInvalidNodeType()
|
1189 |
-
{
|
1190 |
-
$html = '<p>Foo <span>Bar</span><!--qwe--> Baz <span>Qux</span></p>';
|
1191 |
-
|
1192 |
-
$document = new Document($html, false);
|
1193 |
-
|
1194 |
-
$span = $document->find('span')[1];
|
1195 |
-
|
1196 |
-
$span->previousSibling(null, 'foo');
|
1197 |
-
}
|
1198 |
-
|
1199 |
-
/**
|
1200 |
-
* @dataProvider previousSiblingWithSelectorAndNotDomElementNodeTypeDataProvider
|
1201 |
-
*
|
1202 |
-
* @expectedException \LogicException
|
1203 |
-
*/
|
1204 |
-
public function testPreviousSiblingWithSelectorAndNotDomElement($nodeType)
|
1205 |
-
{
|
1206 |
-
$html =
|
1207 |
-
'<ul>'.
|
1208 |
-
'<li><a href="https://amazon.com">Amazon</a></li>'.
|
1209 |
-
'<li><a href="https://facebook.com">Facebook</a></li>'.
|
1210 |
-
'<li><a href="https://google.com">Google</a></li>'.
|
1211 |
-
'<li><a href="https://www.w3.org">W3C</a></li>'.
|
1212 |
-
'<li><a href="https://wikipedia.org">Wikipedia</a></li>'.
|
1213 |
-
'</ul>'
|
1214 |
-
;
|
1215 |
-
|
1216 |
-
$document = new Document($html, false);
|
1217 |
-
|
1218 |
-
$list = $document->first('ul');
|
1219 |
-
|
1220 |
-
$item = $list->getNode()->childNodes->item(4);
|
1221 |
-
$item = new Element($item);
|
1222 |
-
|
1223 |
-
$item->previousSibling('li:has(a[href$=".com"])', $nodeType);
|
1224 |
-
}
|
1225 |
-
|
1226 |
-
public function previousSiblingWithSelectorAndNotDomElementNodeTypeDataProvider()
|
1227 |
-
{
|
1228 |
-
return [['DOMText'], ['DOMComment']];
|
1229 |
-
}
|
1230 |
-
|
1231 |
-
// =========================
|
1232 |
-
// previousSiblings
|
1233 |
-
// =========================
|
1234 |
-
|
1235 |
-
public function testPreviousSiblings()
|
1236 |
-
{
|
1237 |
-
$html = '<p>Foo <span>Bar</span> Baz <span>Qux</span></p>';
|
1238 |
-
|
1239 |
-
$document = new Document($html, false);
|
1240 |
-
|
1241 |
-
$paragraph = $document->first('p');
|
1242 |
-
$span = $paragraph->find('span')[1];
|
1243 |
-
|
1244 |
-
$childNodes = $paragraph->getNode()->childNodes;
|
1245 |
-
|
1246 |
-
$expectedResult = [
|
1247 |
-
$childNodes->item(0),
|
1248 |
-
$childNodes->item(1),
|
1249 |
-
$childNodes->item(2),
|
1250 |
-
];
|
1251 |
-
|
1252 |
-
$previousSiblings = $span->previousSiblings();
|
1253 |
-
|
1254 |
-
$this->assertCount(count($expectedResult), $previousSiblings);
|
1255 |
-
|
1256 |
-
foreach ($previousSiblings as $index => $previousSibling) {
|
1257 |
-
$this->assertEquals($expectedResult[$index], $previousSibling->getNode());
|
1258 |
-
}
|
1259 |
-
}
|
1260 |
-
|
1261 |
-
public function testPreviousSiblingsWithSelector()
|
1262 |
-
{
|
1263 |
-
$html =
|
1264 |
-
'<ul>'.
|
1265 |
-
'<li><a href="https://amazon.com">Amazon</a></li>'.
|
1266 |
-
'<li><a href="https://facebook.com">Facebook</a></li>'.
|
1267 |
-
'<li><a href="https://google.com">Google</a></li>'.
|
1268 |
-
'<li><a href="https://www.w3.org">W3C</a></li>'.
|
1269 |
-
'<li><a href="https://wikipedia.org">Wikipedia</a></li>'.
|
1270 |
-
'</ul>'
|
1271 |
-
;
|
1272 |
-
|
1273 |
-
$document = new Document($html, false);
|
1274 |
-
|
1275 |
-
$list = $document->first('ul');
|
1276 |
-
|
1277 |
-
$item = $list->getNode()->childNodes->item(4);
|
1278 |
-
$item = new Element($item);
|
1279 |
-
|
1280 |
-
$childNodes = $list->getNode()->childNodes;
|
1281 |
-
|
1282 |
-
$expectedResult = [
|
1283 |
-
$childNodes->item(0),
|
1284 |
-
$childNodes->item(1),
|
1285 |
-
$childNodes->item(2),
|
1286 |
-
];
|
1287 |
-
|
1288 |
-
$previousSiblings = $item->previousSiblings('li:has(a[href$=".com"])');
|
1289 |
-
|
1290 |
-
$this->assertCount(count($expectedResult), $previousSiblings);
|
1291 |
-
|
1292 |
-
foreach ($previousSiblings as $index => $previousSibling) {
|
1293 |
-
$this->assertEquals($expectedResult[$index], $previousSibling->getNode());
|
1294 |
-
}
|
1295 |
-
}
|
1296 |
-
|
1297 |
-
public function testPreviousSiblingsWithNodeType()
|
1298 |
-
{
|
1299 |
-
$html = '<p>Foo <span>Bar</span><!--qwe--> Baz <span>Qux</span></p>';
|
1300 |
-
|
1301 |
-
$document = new Document($html, false);
|
1302 |
-
|
1303 |
-
$paragraph = $document->first('p');
|
1304 |
-
$span = $document->find('span')[1];
|
1305 |
-
|
1306 |
-
$childNodes = $paragraph->getNode()->childNodes;
|
1307 |
-
|
1308 |
-
$expectedResult = [
|
1309 |
-
$childNodes->item(1),
|
1310 |
-
];
|
1311 |
-
|
1312 |
-
$previousSiblings = $span->previousSiblings(null, 'DOMElement');
|
1313 |
-
|
1314 |
-
$this->assertCount(count($expectedResult), $previousSiblings);
|
1315 |
-
|
1316 |
-
foreach ($previousSiblings as $index => $previousSibling) {
|
1317 |
-
$this->assertEquals($expectedResult[$index], $previousSibling->getNode());
|
1318 |
-
}
|
1319 |
-
|
1320 |
-
$expectedResult = [
|
1321 |
-
$childNodes->item(2),
|
1322 |
-
];
|
1323 |
-
|
1324 |
-
$previousSiblings = $span->previousSiblings(null, 'DOMComment');
|
1325 |
-
|
1326 |
-
$this->assertCount(count($expectedResult), $previousSiblings);
|
1327 |
-
|
1328 |
-
foreach ($previousSiblings as $index => $previousSibling) {
|
1329 |
-
$this->assertEquals($expectedResult[$index], $previousSibling->getNode());
|
1330 |
-
}
|
1331 |
-
}
|
1332 |
-
|
1333 |
-
/**
|
1334 |
-
* @expectedException \InvalidArgumentException
|
1335 |
-
*/
|
1336 |
-
public function testPreviousSiblingsWithInvalidTypeOfNodeTypeArgument()
|
1337 |
-
{
|
1338 |
-
$html = '<p>Foo <span>Bar</span><!--qwe--> Baz <span>Qux</span></p>';
|
1339 |
-
|
1340 |
-
$document = new Document($html, false);
|
1341 |
-
|
1342 |
-
$span = $document->find('span')[1];
|
1343 |
-
|
1344 |
-
$span->previousSiblings(null, []);
|
1345 |
-
}
|
1346 |
-
|
1347 |
-
/**
|
1348 |
-
* @expectedException \RuntimeException
|
1349 |
-
*/
|
1350 |
-
public function testPreviousSiblingsWithInvalidNodeType()
|
1351 |
-
{
|
1352 |
-
$html = '<p>Foo <span>Bar</span><!--qwe--> Baz <span>Qux</span></p>';
|
1353 |
-
|
1354 |
-
$document = new Document($html, false);
|
1355 |
-
|
1356 |
-
$span = $document->find('span')[1];
|
1357 |
-
|
1358 |
-
$span->previousSibling(null, 'foo');
|
1359 |
-
}
|
1360 |
-
|
1361 |
-
/**
|
1362 |
-
* @dataProvider previousSiblingsWithSelectorAndNotDomElementNodeTypeDataProvider
|
1363 |
-
*
|
1364 |
-
* @expectedException \LogicException
|
1365 |
-
*/
|
1366 |
-
public function testPreviousSiblingsWithSelectorAndNotDomElement($nodeType)
|
1367 |
-
{
|
1368 |
-
$html =
|
1369 |
-
'<ul>'.
|
1370 |
-
'<li><a href="https://amazon.com">Amazon</a></li>'.
|
1371 |
-
'<li><a href="https://facebook.com">Facebook</a></li>'.
|
1372 |
-
'<li><a href="https://google.com">Google</a></li>'.
|
1373 |
-
'<li><a href="https://www.w3.org">W3C</a></li>'.
|
1374 |
-
'<li><a href="https://wikipedia.org">Wikipedia</a></li>'.
|
1375 |
-
'</ul>'
|
1376 |
-
;
|
1377 |
-
|
1378 |
-
$document = new Document($html, false);
|
1379 |
-
|
1380 |
-
$list = $document->first('ul');
|
1381 |
-
|
1382 |
-
$item = $list->getNode()->childNodes->item(4);
|
1383 |
-
$item = new Element($item);
|
1384 |
-
|
1385 |
-
$item->previousSiblings('li:has(a[href$=".com"])', $nodeType);
|
1386 |
-
}
|
1387 |
-
|
1388 |
-
public function previousSiblingsWithSelectorAndNotDomElementNodeTypeDataProvider()
|
1389 |
-
{
|
1390 |
-
return [['DOMText'], ['DOMComment']];
|
1391 |
-
}
|
1392 |
-
|
1393 |
-
// =========================
|
1394 |
-
// nextSibling
|
1395 |
-
// =========================
|
1396 |
-
|
1397 |
-
public function testNextSibling()
|
1398 |
-
{
|
1399 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
1400 |
-
|
1401 |
-
$document = new Document($html, false);
|
1402 |
-
|
1403 |
-
$list = $document->first('ul');
|
1404 |
-
|
1405 |
-
$item = $list->getNode()->childNodes->item(2);
|
1406 |
-
$item = new Element($item);
|
1407 |
-
|
1408 |
-
$this->assertNull($item->nextSibling());
|
1409 |
-
|
1410 |
-
$item = $list->getNode()->childNodes->item(0);
|
1411 |
-
$item = new Element($item);
|
1412 |
-
|
1413 |
-
$expectedNode = $list->getNode()->childNodes->item(1);
|
1414 |
-
|
1415 |
-
$this->assertEquals($expectedNode, $item->nextSibling()->getNode());
|
1416 |
-
}
|
1417 |
-
|
1418 |
-
public function testNextSiblingWithTextNode()
|
1419 |
-
{
|
1420 |
-
$html = '<p>Foo <span>Bar</span> Baz</p>';
|
1421 |
-
|
1422 |
-
$document = new Document($html, false);
|
1423 |
-
|
1424 |
-
$paragraph = $document->first('p');
|
1425 |
-
$span = $paragraph->first('span');
|
1426 |
-
|
1427 |
-
$expectedNode = $span->getNode()->nextSibling;
|
1428 |
-
|
1429 |
-
$this->assertEquals($expectedNode, $span->nextSibling()->getNode());
|
1430 |
-
}
|
1431 |
-
|
1432 |
-
public function testNextSiblingWithCommentNode()
|
1433 |
-
{
|
1434 |
-
$html = '<p>Foo <span>Bar</span><!-- Baz --></p>';
|
1435 |
-
|
1436 |
-
$document = new Document($html, false);
|
1437 |
-
|
1438 |
-
$paragraph = $document->first('p');
|
1439 |
-
$span = $paragraph->first('span');
|
1440 |
-
|
1441 |
-
$expectedNode = $span->getNode()->nextSibling;
|
1442 |
-
|
1443 |
-
$this->assertEquals($expectedNode, $span->nextSibling()->getNode());
|
1444 |
-
}
|
1445 |
-
|
1446 |
-
public function testNextSiblingWithSelector()
|
1447 |
-
{
|
1448 |
-
$html =
|
1449 |
-
'<ul>'.
|
1450 |
-
'<li><a href="https://amazon.com">Amazon</a></li>'.
|
1451 |
-
'<li><a href="https://facebook.com">Facebook</a></li>'.
|
1452 |
-
'<li><a href="https://google.com">Google</a></li>'.
|
1453 |
-
'<li><a href="https://www.w3.org">W3C</a></li>'.
|
1454 |
-
'<li><a href="https://wikipedia.org">Wikipedia</a></li>'.
|
1455 |
-
'</ul>'
|
1456 |
-
;
|
1457 |
-
|
1458 |
-
$document = new Document($html, false);
|
1459 |
-
|
1460 |
-
$list = $document->first('ul');
|
1461 |
-
|
1462 |
-
$item = $list->getNode()->childNodes->item(0);
|
1463 |
-
$item = new Element($item);
|
1464 |
-
|
1465 |
-
$expectedNode = $list->getNode()->childNodes->item(3);
|
1466 |
-
|
1467 |
-
$this->assertEquals($expectedNode, $item->nextSibling('li:has(a[href$=".org"])')->getNode());
|
1468 |
-
}
|
1469 |
-
|
1470 |
-
public function testNextSiblingWithNodeType()
|
1471 |
-
{
|
1472 |
-
$html = '<p>Foo <span>Bar</span> Baz <!--qwe--><span>Qux</span></p>';
|
1473 |
-
|
1474 |
-
$document = new Document($html, false);
|
1475 |
-
|
1476 |
-
$paragraph = $document->first('p');
|
1477 |
-
$span = $document->find('span')[0];
|
1478 |
-
|
1479 |
-
$expectedNode = $paragraph->getNode()->childNodes->item(4);
|
1480 |
-
$this->assertEquals($expectedNode, $span->nextSibling(null, 'DOMElement')->getNode());
|
1481 |
-
|
1482 |
-
$expectedNode = $paragraph->getNode()->childNodes->item(3);
|
1483 |
-
$this->assertEquals($expectedNode, $span->nextSibling(null, 'DOMComment')->getNode());
|
1484 |
-
}
|
1485 |
-
|
1486 |
-
/**
|
1487 |
-
* @expectedException \InvalidArgumentException
|
1488 |
-
*/
|
1489 |
-
public function testNextSiblingWithInvalidTypeOfNodeTypeArgument()
|
1490 |
-
{
|
1491 |
-
$html = '<p>Foo <span>Bar</span> Baz <!--qwe--><span>Qux</span></p>';
|
1492 |
-
|
1493 |
-
$document = new Document($html, false);
|
1494 |
-
|
1495 |
-
$span = $document->find('span')[0];
|
1496 |
-
|
1497 |
-
$span->nextSibling(null, []);
|
1498 |
-
}
|
1499 |
-
|
1500 |
-
/**
|
1501 |
-
* @expectedException \RuntimeException
|
1502 |
-
*/
|
1503 |
-
public function testNextSiblingWithInvalidNodeType()
|
1504 |
-
{
|
1505 |
-
$html = '<p>Foo <span>Bar</span> Baz <!--qwe--><span>Qux</span></p>';
|
1506 |
-
|
1507 |
-
$document = new Document($html, false);
|
1508 |
-
|
1509 |
-
$span = $document->find('span')[0];
|
1510 |
-
|
1511 |
-
$span->nextSibling(null, 'foo');
|
1512 |
-
}
|
1513 |
-
|
1514 |
-
/**
|
1515 |
-
* @dataProvider nextSiblingWithSelectorAndNotDomElementNodeTypeDataProvider
|
1516 |
-
*
|
1517 |
-
* @expectedException \LogicException
|
1518 |
-
*/
|
1519 |
-
public function testNextSiblingWithSelectorAndNotDomElement($nodeType)
|
1520 |
-
{
|
1521 |
-
$html =
|
1522 |
-
'<ul>'.
|
1523 |
-
'<li><a href="https://amazon.com">Amazon</a></li>'.
|
1524 |
-
'<li><a href="https://facebook.com">Facebook</a></li>'.
|
1525 |
-
'<li><a href="https://google.com">Google</a></li>'.
|
1526 |
-
'<li><a href="https://www.w3.org">W3C</a></li>'.
|
1527 |
-
'<li><a href="https://wikipedia.org">Wikipedia</a></li>'.
|
1528 |
-
'</ul>'
|
1529 |
-
;
|
1530 |
-
|
1531 |
-
$document = new Document($html, false);
|
1532 |
-
|
1533 |
-
$list = $document->first('ul');
|
1534 |
-
|
1535 |
-
$item = $list->getNode()->childNodes->item(0);
|
1536 |
-
$item = new Element($item);
|
1537 |
-
|
1538 |
-
$item->nextSibling('li:has(a[href$=".com"])', $nodeType);
|
1539 |
-
}
|
1540 |
-
|
1541 |
-
public function nextSiblingWithSelectorAndNotDomElementNodeTypeDataProvider()
|
1542 |
-
{
|
1543 |
-
return [['DOMText'], ['DOMComment']];
|
1544 |
-
}
|
1545 |
-
|
1546 |
-
// =========================
|
1547 |
-
// nextSiblings
|
1548 |
-
// =========================
|
1549 |
-
|
1550 |
-
public function testNextSiblings()
|
1551 |
-
{
|
1552 |
-
$html = '<p>Foo <span>Bar</span> Baz <span>Qux</span></p>';
|
1553 |
-
|
1554 |
-
$document = new Document($html, false);
|
1555 |
-
|
1556 |
-
$paragraph = $document->first('p');
|
1557 |
-
$span = $paragraph->find('span')[0];
|
1558 |
-
|
1559 |
-
$childNodes = $paragraph->getNode()->childNodes;
|
1560 |
-
|
1561 |
-
$expectedResult = [
|
1562 |
-
$childNodes->item(2),
|
1563 |
-
$childNodes->item(3),
|
1564 |
-
];
|
1565 |
-
|
1566 |
-
$nextSiblings = $span->nextSiblings();
|
1567 |
-
|
1568 |
-
$this->assertCount(count($expectedResult), $nextSiblings);
|
1569 |
-
|
1570 |
-
foreach ($nextSiblings as $index => $nextSibling) {
|
1571 |
-
$this->assertEquals($expectedResult[$index], $nextSibling->getNode());
|
1572 |
-
}
|
1573 |
-
}
|
1574 |
-
|
1575 |
-
public function testNextSiblingsWithSelector()
|
1576 |
-
{
|
1577 |
-
$html =
|
1578 |
-
'<ul>'.
|
1579 |
-
'<li><a href="https://amazon.com">Amazon</a></li>'.
|
1580 |
-
'<li><a href="https://facebook.com">Facebook</a></li>'.
|
1581 |
-
'<li><a href="https://google.com">Google</a></li>'.
|
1582 |
-
'<li><a href="https://www.w3.org">W3C</a></li>'.
|
1583 |
-
'<li><a href="https://wikipedia.org">Wikipedia</a></li>'.
|
1584 |
-
'</ul>'
|
1585 |
-
;
|
1586 |
-
|
1587 |
-
$document = new Document($html, false);
|
1588 |
-
|
1589 |
-
$list = $document->first('ul');
|
1590 |
-
|
1591 |
-
$item = $list->getNode()->childNodes->item(0);
|
1592 |
-
$item = new Element($item);
|
1593 |
-
|
1594 |
-
$childNodes = $list->getNode()->childNodes;
|
1595 |
-
|
1596 |
-
$expectedResult = [
|
1597 |
-
$childNodes->item(1),
|
1598 |
-
$childNodes->item(2),
|
1599 |
-
];
|
1600 |
-
|
1601 |
-
$nextSiblings = $item->nextSiblings('li:has(a[href$=".com"])');
|
1602 |
-
|
1603 |
-
$this->assertCount(count($expectedResult), $nextSiblings);
|
1604 |
-
|
1605 |
-
foreach ($nextSiblings as $index => $nextSibling) {
|
1606 |
-
$this->assertEquals($expectedResult[$index], $nextSibling->getNode());
|
1607 |
-
}
|
1608 |
-
}
|
1609 |
-
|
1610 |
-
public function testNextSiblingsWithNodeType()
|
1611 |
-
{
|
1612 |
-
$html = '<p>Foo <span>Bar</span><!--qwe--> Baz <span>Qux</span></p>';
|
1613 |
-
|
1614 |
-
$document = new Document($html, false);
|
1615 |
-
|
1616 |
-
$paragraph = $document->first('p');
|
1617 |
-
$span = $document->find('span')[0];
|
1618 |
-
|
1619 |
-
$childNodes = $paragraph->getNode()->childNodes;
|
1620 |
-
|
1621 |
-
$expectedResult = [
|
1622 |
-
$childNodes->item(4),
|
1623 |
-
];
|
1624 |
-
|
1625 |
-
$previousSiblings = $span->nextSiblings(null, 'DOMElement');
|
1626 |
-
|
1627 |
-
$this->assertCount(count($expectedResult), $previousSiblings);
|
1628 |
-
|
1629 |
-
foreach ($previousSiblings as $index => $previousSibling) {
|
1630 |
-
$this->assertEquals($expectedResult[$index], $previousSibling->getNode());
|
1631 |
-
}
|
1632 |
-
|
1633 |
-
$expectedResult = [
|
1634 |
-
$childNodes->item(2),
|
1635 |
-
];
|
1636 |
-
|
1637 |
-
$previousSiblings = $span->nextSiblings(null, 'DOMComment');
|
1638 |
-
|
1639 |
-
$this->assertCount(count($expectedResult), $previousSiblings);
|
1640 |
-
|
1641 |
-
foreach ($previousSiblings as $index => $previousSibling) {
|
1642 |
-
$this->assertEquals($expectedResult[$index], $previousSibling->getNode());
|
1643 |
-
}
|
1644 |
-
}
|
1645 |
-
|
1646 |
-
/**
|
1647 |
-
* @expectedException \InvalidArgumentException
|
1648 |
-
*/
|
1649 |
-
public function testNextSiblingsWithInvalidTypeOfNodeTypeArgument()
|
1650 |
-
{
|
1651 |
-
$html = '<p>Foo <span>Bar</span><!--qwe--> Baz <span>Qux</span></p>';
|
1652 |
-
|
1653 |
-
$document = new Document($html, false);
|
1654 |
-
|
1655 |
-
$span = $document->find('span')[0];
|
1656 |
-
|
1657 |
-
$span->nextSiblings(null, []);
|
1658 |
-
}
|
1659 |
-
|
1660 |
-
/**
|
1661 |
-
* @expectedException \RuntimeException
|
1662 |
-
*/
|
1663 |
-
public function testNextSiblingsWithInvalidNodeType()
|
1664 |
-
{
|
1665 |
-
$html = '<p>Foo <span>Bar</span><!--qwe--> Baz <span>Qux</span></p>';
|
1666 |
-
|
1667 |
-
$document = new Document($html, false);
|
1668 |
-
|
1669 |
-
$span = $document->find('span')[0];
|
1670 |
-
|
1671 |
-
$span->nextSiblings(null, 'foo');
|
1672 |
-
}
|
1673 |
-
|
1674 |
-
/**
|
1675 |
-
* @dataProvider nextSiblingsWithSelectorAndNotDomElementNodeTypeDataProvider
|
1676 |
-
*
|
1677 |
-
* @expectedException \LogicException
|
1678 |
-
*/
|
1679 |
-
public function testNextSiblingsWithSelectorAndNotDomElement($nodeType)
|
1680 |
-
{
|
1681 |
-
$html =
|
1682 |
-
'<ul>'.
|
1683 |
-
'<li><a href="https://amazon.com">Amazon</a></li>'.
|
1684 |
-
'<li><a href="https://facebook.com">Facebook</a></li>'.
|
1685 |
-
'<li><a href="https://google.com">Google</a></li>'.
|
1686 |
-
'<li><a href="https://www.w3.org">W3C</a></li>'.
|
1687 |
-
'<li><a href="https://wikipedia.org">Wikipedia</a></li>'.
|
1688 |
-
'</ul>'
|
1689 |
-
;
|
1690 |
-
|
1691 |
-
$document = new Document($html, false);
|
1692 |
-
|
1693 |
-
$list = $document->first('ul');
|
1694 |
-
|
1695 |
-
$item = $list->getNode()->childNodes->item(0);
|
1696 |
-
$item = new Element($item);
|
1697 |
-
|
1698 |
-
$item->nextSiblings('li:has(a[href$=".com"])', $nodeType);
|
1699 |
-
}
|
1700 |
-
|
1701 |
-
public function nextSiblingsWithSelectorAndNotDomElementNodeTypeDataProvider()
|
1702 |
-
{
|
1703 |
-
return [['DOMText'], ['DOMComment']];
|
1704 |
-
}
|
1705 |
-
|
1706 |
-
public function testChild()
|
1707 |
-
{
|
1708 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
1709 |
-
|
1710 |
-
$document = new Document($html, false);
|
1711 |
-
|
1712 |
-
$list = $document->first('ul');
|
1713 |
-
|
1714 |
-
$this->assertEquals($list->getNode()->childNodes->item(0), $list->child(0)->getNode());
|
1715 |
-
$this->assertEquals($list->getNode()->childNodes->item(2), $list->child(2)->getNode());
|
1716 |
-
$this->assertNull($list->child(3));
|
1717 |
-
|
1718 |
-
// with text nodes
|
1719 |
-
$html = '<p>Foo <span>Bar</span> Baz</p>';
|
1720 |
-
|
1721 |
-
$document = new Document($html, false);
|
1722 |
-
|
1723 |
-
$paragraph = $document->first('p');
|
1724 |
-
|
1725 |
-
$child = $paragraph->getNode()->childNodes->item(0);
|
1726 |
-
|
1727 |
-
$this->assertEquals($child, $paragraph->child(0)->getNode());
|
1728 |
-
}
|
1729 |
-
|
1730 |
-
public function testFirstChild()
|
1731 |
-
{
|
1732 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
1733 |
-
|
1734 |
-
$document = new Document($html, false);
|
1735 |
-
|
1736 |
-
$list = $document->first('ul');
|
1737 |
-
|
1738 |
-
$this->assertEquals($list->getNode()->firstChild, $list->firstChild()->getNode());
|
1739 |
-
|
1740 |
-
$list = new Element('ul');
|
1741 |
-
|
1742 |
-
$this->assertNull($list->firstChild());
|
1743 |
-
|
1744 |
-
// with text nodes
|
1745 |
-
$html = '<p>Foo <span>Bar</span> Baz</p>';
|
1746 |
-
|
1747 |
-
$document = new Document($html, false);
|
1748 |
-
|
1749 |
-
$paragraph = $document->first('p');
|
1750 |
-
|
1751 |
-
$firstChild = $paragraph->getNode()->firstChild;
|
1752 |
-
|
1753 |
-
$this->assertEquals($firstChild, $paragraph->firstChild()->getNode());
|
1754 |
-
}
|
1755 |
-
|
1756 |
-
public function testLastChild()
|
1757 |
-
{
|
1758 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
1759 |
-
|
1760 |
-
$document = new Document($html, false);
|
1761 |
-
$list = $document->first('ul');
|
1762 |
-
|
1763 |
-
$this->assertEquals($list->getNode()->lastChild, $list->lastChild()->getNode());
|
1764 |
-
|
1765 |
-
$list = new Element('ul');
|
1766 |
-
|
1767 |
-
$this->assertNull($list->lastChild());
|
1768 |
-
|
1769 |
-
// with text nodes
|
1770 |
-
$html = '<p>Foo <span>Bar</span> Baz</p>';
|
1771 |
-
|
1772 |
-
$document = new Document($html, false);
|
1773 |
-
$paragraph = $document->first('p');
|
1774 |
-
|
1775 |
-
$lastChild = $paragraph->getNode()->lastChild;
|
1776 |
-
|
1777 |
-
$this->assertEquals($lastChild, $paragraph->lastChild()->getNode());
|
1778 |
-
}
|
1779 |
-
|
1780 |
-
public function testHasChildren()
|
1781 |
-
{
|
1782 |
-
$html = '
|
1783 |
-
<p class="element"><br></p>
|
1784 |
-
<p class="text">Foo</p>
|
1785 |
-
<p class="comment"><!-- Foo --></p>
|
1786 |
-
<p class="empty"></p>
|
1787 |
-
';
|
1788 |
-
|
1789 |
-
$document = new Document($html);
|
1790 |
-
|
1791 |
-
$this->assertTrue($document->first('.element')->hasChildren());
|
1792 |
-
$this->assertTrue($document->first('.text')->hasChildren());
|
1793 |
-
$this->assertTrue($document->first('.comment')->hasChildren());
|
1794 |
-
$this->assertFalse($document->first('.empty')->hasChildren());
|
1795 |
-
}
|
1796 |
-
|
1797 |
-
public function testChildren()
|
1798 |
-
{
|
1799 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
1800 |
-
|
1801 |
-
$document = new Document($html, false);
|
1802 |
-
|
1803 |
-
$list = $document->first('ul');
|
1804 |
-
|
1805 |
-
$children = $list->children();
|
1806 |
-
|
1807 |
-
foreach ($list->getNode()->childNodes as $index => $node) {
|
1808 |
-
$this->assertEquals($node, $children[$index]->getNode());
|
1809 |
-
}
|
1810 |
-
|
1811 |
-
// with text nodes
|
1812 |
-
$html = '<p>Foo <span>Bar</span> Baz</p>';
|
1813 |
-
|
1814 |
-
$document = new Document($html, false);
|
1815 |
-
|
1816 |
-
$paragraph = $document->first('p');
|
1817 |
-
|
1818 |
-
$children = $paragraph->children();
|
1819 |
-
|
1820 |
-
foreach ($paragraph->getNode()->childNodes as $index => $node) {
|
1821 |
-
$this->assertEquals($node, $children[$index]->getNode());
|
1822 |
-
}
|
1823 |
-
}
|
1824 |
-
|
1825 |
-
public function testParentWithoutOwner()
|
1826 |
-
{
|
1827 |
-
$element = new Element(new \DOMElement('span', 'hello'));
|
1828 |
-
|
1829 |
-
$this->assertNull($element->parent());
|
1830 |
-
}
|
1831 |
-
|
1832 |
-
public function testRemoveChild()
|
1833 |
-
{
|
1834 |
-
$html = '<div><span>Foo</span></div>';
|
1835 |
-
$document = new Document($html, false);
|
1836 |
-
|
1837 |
-
$div = $document->first('div');
|
1838 |
-
$span = $document->first('span');
|
1839 |
-
|
1840 |
-
$this->assertEquals($span->getNode(), $div->removeChild($span)->getNode());
|
1841 |
-
$this->assertCount(0, $document->find('span'));
|
1842 |
-
}
|
1843 |
-
|
1844 |
-
public function testRemoveChildren()
|
1845 |
-
{
|
1846 |
-
$html = '<div><span>Foo</span>Bar<!-- Baz --></div>';
|
1847 |
-
$document = new Document($html, false);
|
1848 |
-
|
1849 |
-
$div = $document->first('div');
|
1850 |
-
$span = $document->first('span');
|
1851 |
-
|
1852 |
-
$childNodes = $div->children();
|
1853 |
-
$removedNodes = $div->removeChildren();
|
1854 |
-
|
1855 |
-
foreach ($childNodes as $index => $childNode) {
|
1856 |
-
$this->assertEquals($childNode->getNode(), $removedNodes[$index]->getNode());
|
1857 |
-
}
|
1858 |
-
|
1859 |
-
$this->assertCount(0, $document->find('span'));
|
1860 |
-
}
|
1861 |
-
|
1862 |
-
public function testRemove()
|
1863 |
-
{
|
1864 |
-
$html = '<div><span>Foo</span></div>';
|
1865 |
-
$document = new Document($html, false);
|
1866 |
-
|
1867 |
-
$span = $document->first('span');
|
1868 |
-
|
1869 |
-
$this->assertEquals($span->getNode(), $span->remove()->getNode());
|
1870 |
-
$this->assertCount(0, $document->find('span'));
|
1871 |
-
}
|
1872 |
-
|
1873 |
-
/**
|
1874 |
-
* @expectedException \LogicException
|
1875 |
-
*/
|
1876 |
-
public function testRemoveWithoutParentNode()
|
1877 |
-
{
|
1878 |
-
$element = new Element('div', 'Foo');
|
1879 |
-
|
1880 |
-
$element->remove();
|
1881 |
-
}
|
1882 |
-
|
1883 |
-
public function testReplace()
|
1884 |
-
{
|
1885 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
1886 |
-
|
1887 |
-
$document = new Document($html, false);
|
1888 |
-
|
1889 |
-
$first = $document->find('li')[0];
|
1890 |
-
$third = $document->find('li')[2];
|
1891 |
-
|
1892 |
-
$this->assertEquals($first->getNode(), $first->replace($third)->getNode());
|
1893 |
-
$this->assertEquals($third->getNode(), $document->find('li')[0]->getNode());
|
1894 |
-
$this->assertCount(3, $document->find('li'));
|
1895 |
-
|
1896 |
-
// replace without cloning
|
1897 |
-
$document = new Document($html, false);
|
1898 |
-
|
1899 |
-
$first = $document->find('li')[0];
|
1900 |
-
$third = $document->find('li')[2];
|
1901 |
-
|
1902 |
-
$this->assertEquals($first->getNode(), $first->replace($third, false)->getNode());
|
1903 |
-
$this->assertEquals($third->getNode(), $document->find('li')[0]->getNode());
|
1904 |
-
$this->assertCount(2, $document->find('li'));
|
1905 |
-
}
|
1906 |
-
|
1907 |
-
public function testReplaceToNewElement()
|
1908 |
-
{
|
1909 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
1910 |
-
|
1911 |
-
$document = new Document($html, false);
|
1912 |
-
|
1913 |
-
$first = $document->find('li')[0];
|
1914 |
-
|
1915 |
-
$newElement = new Element('li', 'Foo');
|
1916 |
-
|
1917 |
-
$this->assertEquals($first->getNode(), $first->replace($newElement)->getNode());
|
1918 |
-
$this->assertEquals('Foo', $document->find('li')[0]->text());
|
1919 |
-
$this->assertCount(3, $document->find('li'));
|
1920 |
-
|
1921 |
-
// replace with new node
|
1922 |
-
$html = '<span>Foo <a href="#">Bar</a> Baz</span>';
|
1923 |
-
|
1924 |
-
$document = new Document($html, false);
|
1925 |
-
|
1926 |
-
$anchor = $document->first('a');
|
1927 |
-
|
1928 |
-
$textNode = new \DOMText($anchor->text());
|
1929 |
-
|
1930 |
-
$anchor->replace($textNode);
|
1931 |
-
}
|
1932 |
-
|
1933 |
-
public function testReplaceWithDifferentDocuments()
|
1934 |
-
{
|
1935 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
1936 |
-
|
1937 |
-
$document = new Document($html, false);
|
1938 |
-
$document2 = new Document($html, false);
|
1939 |
-
|
1940 |
-
$first = $document->find('li')[0];
|
1941 |
-
$third = $document2->find('li')[2];
|
1942 |
-
|
1943 |
-
$first->replace($third);
|
1944 |
-
}
|
1945 |
-
|
1946 |
-
/**
|
1947 |
-
* @expectedException \InvalidArgumentException
|
1948 |
-
*/
|
1949 |
-
public function testReplaceWithInvalidArgument()
|
1950 |
-
{
|
1951 |
-
$html = '<ul><li>One</li><li>Two</li><li>Three</li></ul>';
|
1952 |
-
|
1953 |
-
$document = new Document($html, false);
|
1954 |
-
|
1955 |
-
$document->find('li')[0]->replace(null);
|
1956 |
-
}
|
1957 |
-
|
1958 |
-
/**
|
1959 |
-
* @expectedException \LogicException
|
1960 |
-
*/
|
1961 |
-
public function testReplaceElementWithoutParentNode()
|
1962 |
-
{
|
1963 |
-
$element = new Element('div', 'Foo');
|
1964 |
-
|
1965 |
-
$element->replace(new Element('div', 'Bar'));
|
1966 |
-
}
|
1967 |
-
|
1968 |
-
public function testGetLineNo()
|
1969 |
-
{
|
1970 |
-
$element = new Element('div');
|
1971 |
-
|
1972 |
-
$this->assertEquals(0, $element->getLineNo());
|
1973 |
-
|
1974 |
-
$html = '<ul>
|
1975 |
-
<li>One</li>
|
1976 |
-
<li>Two</li>
|
1977 |
-
<li>Three</li>
|
1978 |
-
</ul>';
|
1979 |
-
|
1980 |
-
$document = new Document($html, false);
|
1981 |
-
|
1982 |
-
$this->assertEquals(4, $document->find('li')[2]->getLineNo());
|
1983 |
-
}
|
1984 |
-
|
1985 |
-
public function testCloneNode()
|
1986 |
-
{
|
1987 |
-
$element = new Element('input');
|
1988 |
-
|
1989 |
-
$cloned = $element->cloneNode(true);
|
1990 |
-
|
1991 |
-
$this->assertFalse($element->is($cloned));
|
1992 |
-
}
|
1993 |
-
|
1994 |
-
public function testGetNode()
|
1995 |
-
{
|
1996 |
-
$node = $this->createDomElement('input');
|
1997 |
-
$element = new Element($node);
|
1998 |
-
|
1999 |
-
$this->assertEquals($node, $element->getNode());
|
2000 |
-
}
|
2001 |
-
|
2002 |
-
public function testGetDocument()
|
2003 |
-
{
|
2004 |
-
$html = $this->loadFixture('posts.html');
|
2005 |
-
|
2006 |
-
$document = new Document($html, false);
|
2007 |
-
$element = $document->createElement('span', 'value');
|
2008 |
-
|
2009 |
-
$this->assertEquals($document->getDocument(), $element->getDocument()->getDocument());
|
2010 |
-
}
|
2011 |
-
|
2012 |
-
public function testToDocument()
|
2013 |
-
{
|
2014 |
-
$element = new Element('input');
|
2015 |
-
|
2016 |
-
$document = $element->toDocument();
|
2017 |
-
|
2018 |
-
$this->assertInstanceOf('DiDom\Document', $document);
|
2019 |
-
$this->assertEquals('UTF-8', $document->getDocument()->encoding);
|
2020 |
-
|
2021 |
-
$document = $element->toDocument('CP1251');
|
2022 |
-
|
2023 |
-
$this->assertEquals('CP1251', $document->getDocument()->encoding);
|
2024 |
-
}
|
2025 |
-
|
2026 |
-
public function testSetMagicMethod()
|
2027 |
-
{
|
2028 |
-
$node = $this->createDomElement('input');
|
2029 |
-
|
2030 |
-
$element = new Element($node);
|
2031 |
-
$element->name = 'username';
|
2032 |
-
|
2033 |
-
$this->assertEquals('username', $element->getNode()->getAttribute('name'));
|
2034 |
-
}
|
2035 |
-
|
2036 |
-
public function testGetMagicMethod()
|
2037 |
-
{
|
2038 |
-
$element = new Element('input', null, ['name' => 'username']);
|
2039 |
-
|
2040 |
-
$this->assertEquals('username', $element->name);
|
2041 |
-
}
|
2042 |
-
|
2043 |
-
public function testIssetMagicMethod()
|
2044 |
-
{
|
2045 |
-
$node = $this->createDomElement('input');
|
2046 |
-
$element = new Element($node);
|
2047 |
-
|
2048 |
-
$this->assertFalse(isset($element->value));
|
2049 |
-
|
2050 |
-
$node->setAttribute('value', 'test');
|
2051 |
-
$element = new Element($node);
|
2052 |
-
|
2053 |
-
$this->assertTrue(isset($element->value));
|
2054 |
-
}
|
2055 |
-
|
2056 |
-
public function testUnsetMagicMethod()
|
2057 |
-
{
|
2058 |
-
$element = new Element('input', null, ['name' => 'username']);
|
2059 |
-
|
2060 |
-
$this->assertTrue($element->hasAttribute('name'));
|
2061 |
-
|
2062 |
-
unset($element->name);
|
2063 |
-
|
2064 |
-
$this->assertFalse($element->hasAttribute('name'));
|
2065 |
-
}
|
2066 |
-
|
2067 |
-
public function testToString()
|
2068 |
-
{
|
2069 |
-
$element = new Element('span', 'hello');
|
2070 |
-
|
2071 |
-
$this->assertEquals($element->html(), $element->__toString());
|
2072 |
-
}
|
2073 |
-
|
2074 |
-
/**
|
2075 |
-
* @dataProvider findTests
|
2076 |
-
*/
|
2077 |
-
public function testInvoke($html, $selector, $type, $count)
|
2078 |
-
{
|
2079 |
-
$document = new \DOMDocument();
|
2080 |
-
$document->loadHTML($html);
|
2081 |
-
|
2082 |
-
$node = $document->getElementsByTagName('body')->item(0);
|
2083 |
-
$element = new Element($node);
|
2084 |
-
|
2085 |
-
$elements = $element($selector, $type);
|
2086 |
-
|
2087 |
-
$this->assertTrue(is_array($elements));
|
2088 |
-
$this->assertEquals($count, count($elements));
|
2089 |
-
|
2090 |
-
foreach ($elements as $element) {
|
2091 |
-
$this->assertInstanceOf('DiDom\Element', $element);
|
2092 |
-
}
|
2093 |
-
}
|
2094 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/imangazaliev/didom/tests/DiDom/QueryTest.php
DELETED
@@ -1,425 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Tests\DiDom;
|
4 |
-
|
5 |
-
use DiDom\Query;
|
6 |
-
use Tests\TestCase;
|
7 |
-
|
8 |
-
class QueryTest extends TestCase
|
9 |
-
{
|
10 |
-
/**
|
11 |
-
* @expectedException \InvalidArgumentException
|
12 |
-
* @expectedExceptionMessage DiDom\Query::compile expects parameter 1 to be string, NULL given
|
13 |
-
*/
|
14 |
-
public function testCompileWithNonStringExpression()
|
15 |
-
{
|
16 |
-
Query::compile(null);
|
17 |
-
}
|
18 |
-
|
19 |
-
/**
|
20 |
-
* @expectedException \InvalidArgumentException
|
21 |
-
* @expectedExceptionMessage DiDom\Query::compile expects parameter 2 to be string, NULL given
|
22 |
-
*/
|
23 |
-
public function testCompileWithNonStringExpressionType()
|
24 |
-
{
|
25 |
-
Query::compile('h1', null);
|
26 |
-
}
|
27 |
-
|
28 |
-
/**
|
29 |
-
* @expectedException \RuntimeException
|
30 |
-
* @expectedExceptionMessage Unknown expression type "foo"
|
31 |
-
*/
|
32 |
-
public function testCompileWithUnknownExpressionType()
|
33 |
-
{
|
34 |
-
Query::compile('h1', 'foo');
|
35 |
-
}
|
36 |
-
|
37 |
-
/**
|
38 |
-
* @dataProvider compileCssTests
|
39 |
-
*/
|
40 |
-
public function testCompileCssSelector($selector, $xpath)
|
41 |
-
{
|
42 |
-
$this->assertEquals($xpath, Query::compile($selector));
|
43 |
-
}
|
44 |
-
|
45 |
-
/**
|
46 |
-
* @dataProvider getSegmentsTests
|
47 |
-
*/
|
48 |
-
public function testGetSegments($selector, $segments)
|
49 |
-
{
|
50 |
-
$this->assertEquals($segments, Query::getSegments($selector));
|
51 |
-
}
|
52 |
-
|
53 |
-
/**
|
54 |
-
* @dataProvider buildXpathTests
|
55 |
-
*/
|
56 |
-
public function testBuildXpath($segments, $xpath)
|
57 |
-
{
|
58 |
-
$this->assertEquals($xpath, Query::buildXpath($segments));
|
59 |
-
}
|
60 |
-
|
61 |
-
/**
|
62 |
-
* @expectedException \InvalidArgumentException
|
63 |
-
*/
|
64 |
-
public function testBuildXpathWithEmptyArray()
|
65 |
-
{
|
66 |
-
Query::buildXpath([]);
|
67 |
-
}
|
68 |
-
|
69 |
-
/**
|
70 |
-
* @expectedException \DiDom\Exceptions\InvalidSelectorException
|
71 |
-
* @expectedExceptionMessage The expression must not be empty
|
72 |
-
*/
|
73 |
-
public function testCompileWithEmptyXpathExpression()
|
74 |
-
{
|
75 |
-
Query::compile('', Query::TYPE_XPATH);
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* @expectedException \DiDom\Exceptions\InvalidSelectorException
|
80 |
-
* @expectedExceptionMessage The expression must not be empty
|
81 |
-
*/
|
82 |
-
public function testCompileWithEmptyCssExpression()
|
83 |
-
{
|
84 |
-
Query::compile('', Query::TYPE_CSS);
|
85 |
-
}
|
86 |
-
|
87 |
-
/**
|
88 |
-
* @expectedException \DiDom\Exceptions\InvalidSelectorException
|
89 |
-
* @expectedExceptionMessage The selector must not be empty
|
90 |
-
*/
|
91 |
-
public function testGetSegmentsWithEmptySelector()
|
92 |
-
{
|
93 |
-
Query::getSegments('');
|
94 |
-
}
|
95 |
-
|
96 |
-
/**
|
97 |
-
* @expectedException \DiDom\Exceptions\InvalidSelectorException
|
98 |
-
* @expectedExceptionMessage Invalid selector "input[=foo]": attribute name must not be empty
|
99 |
-
*/
|
100 |
-
public function testEmptyAttributeName()
|
101 |
-
{
|
102 |
-
Query::compile('input[=foo]');
|
103 |
-
}
|
104 |
-
|
105 |
-
/**
|
106 |
-
* @expectedException \DiDom\Exceptions\InvalidSelectorException
|
107 |
-
* @expectedExceptionMessage Unknown pseudo-class "unknown-pseudo-class"
|
108 |
-
*/
|
109 |
-
public function testUnknownPseudoClass()
|
110 |
-
{
|
111 |
-
Query::compile('li:unknown-pseudo-class');
|
112 |
-
}
|
113 |
-
|
114 |
-
/**
|
115 |
-
* @dataProvider containsInvalidCaseSensitiveParameterDataProvider
|
116 |
-
*/
|
117 |
-
public function testContainsInvalidCaseSensitiveParameter($caseSensitive)
|
118 |
-
{
|
119 |
-
$message = sprintf('Parameter 2 of "contains" pseudo-class must be equal true or false, "%s" given', $caseSensitive);
|
120 |
-
|
121 |
-
$this->setExpectedException('DiDom\Exceptions\InvalidSelectorException', $message);
|
122 |
-
|
123 |
-
Query::compile("a:contains('Log in', {$caseSensitive})");
|
124 |
-
}
|
125 |
-
|
126 |
-
public function containsInvalidCaseSensitiveParameterDataProvider()
|
127 |
-
{
|
128 |
-
return [
|
129 |
-
['foo'],
|
130 |
-
['TRUE'],
|
131 |
-
['FALSE'],
|
132 |
-
];
|
133 |
-
}
|
134 |
-
|
135 |
-
/**
|
136 |
-
* @expectedException \DiDom\Exceptions\InvalidSelectorException
|
137 |
-
* @expectedExceptionMessage nth-child (or nth-last-child) expression must not be empty
|
138 |
-
*/
|
139 |
-
public function testEmptyNthExpression()
|
140 |
-
{
|
141 |
-
Query::compile('li:nth-child()');
|
142 |
-
}
|
143 |
-
|
144 |
-
/**
|
145 |
-
* @expectedException \DiDom\Exceptions\InvalidSelectorException
|
146 |
-
* @expectedExceptionMessage Invalid property "::"
|
147 |
-
*/
|
148 |
-
public function testEmptyProperty()
|
149 |
-
{
|
150 |
-
Query::compile('li::');
|
151 |
-
}
|
152 |
-
|
153 |
-
/**
|
154 |
-
* @expectedException \DiDom\Exceptions\InvalidSelectorException
|
155 |
-
* @expectedExceptionMessage Unknown property "foo"
|
156 |
-
*/
|
157 |
-
public function testInvalidProperty()
|
158 |
-
{
|
159 |
-
Query::compile('li::foo');
|
160 |
-
}
|
161 |
-
|
162 |
-
/**
|
163 |
-
* @expectedException \DiDom\Exceptions\InvalidSelectorException
|
164 |
-
* @expectedExceptionMessage Invalid nth-child expression "foo"
|
165 |
-
*/
|
166 |
-
public function testUnknownNthExpression()
|
167 |
-
{
|
168 |
-
Query::compile('li:nth-child(foo)');
|
169 |
-
}
|
170 |
-
|
171 |
-
/**
|
172 |
-
* @expectedException \DiDom\Exceptions\InvalidSelectorException
|
173 |
-
* @expectedExceptionMessage Invalid selector "."
|
174 |
-
*/
|
175 |
-
public function testGetSegmentsWithEmptyClassName()
|
176 |
-
{
|
177 |
-
Query::getSegments('.');
|
178 |
-
}
|
179 |
-
|
180 |
-
/**
|
181 |
-
* @expectedException \DiDom\Exceptions\InvalidSelectorException
|
182 |
-
* @expectedExceptionMessage Invalid selector "."
|
183 |
-
*/
|
184 |
-
public function testCompilehWithEmptyClassName()
|
185 |
-
{
|
186 |
-
Query::compile('span.');
|
187 |
-
}
|
188 |
-
|
189 |
-
public function testCompileXpath()
|
190 |
-
{
|
191 |
-
$this->assertEquals('//div', Query::compile('//div', Query::TYPE_XPATH));
|
192 |
-
}
|
193 |
-
|
194 |
-
public function testSetCompiledInvalidArgumentType()
|
195 |
-
{
|
196 |
-
if (PHP_VERSION_ID >= 70000) {
|
197 |
-
$this->setExpectedException('TypeError');
|
198 |
-
} else {
|
199 |
-
$this->setExpectedException('PHPUnit_Framework_Error');
|
200 |
-
}
|
201 |
-
|
202 |
-
Query::setCompiled(null);
|
203 |
-
}
|
204 |
-
|
205 |
-
public function testSetCompiled()
|
206 |
-
{
|
207 |
-
$xpath = "//*[@id='foo']//*[contains(concat(' ', normalize-space(@class), ' '), ' bar ')]//baz";
|
208 |
-
$compiled = ['#foo .bar baz' => $xpath];
|
209 |
-
|
210 |
-
Query::setCompiled($compiled);
|
211 |
-
|
212 |
-
$this->assertEquals($compiled, Query::getCompiled());
|
213 |
-
}
|
214 |
-
|
215 |
-
public function testGetCompiled()
|
216 |
-
{
|
217 |
-
Query::setCompiled([]);
|
218 |
-
|
219 |
-
$selector = '#foo .bar baz';
|
220 |
-
$xpath = '//*[@id="foo"]//*[contains(concat(" ", normalize-space(@class), " "), " bar ")]//baz';
|
221 |
-
$compiled = [$selector => $xpath];
|
222 |
-
|
223 |
-
Query::compile($selector);
|
224 |
-
|
225 |
-
$this->assertEquals($compiled, Query::getCompiled());
|
226 |
-
}
|
227 |
-
|
228 |
-
public function compileCssTests()
|
229 |
-
{
|
230 |
-
$compiled = [
|
231 |
-
['a', '//a'],
|
232 |
-
['foo bar baz', '//foo//bar//baz'],
|
233 |
-
['foo > bar > baz', '//foo/bar/baz'],
|
234 |
-
['#foo', '//*[@id="foo"]'],
|
235 |
-
['.bar', '//*[contains(concat(" ", normalize-space(@class), " "), " bar ")]'],
|
236 |
-
['*[foo=bar]', '//*[@foo="bar"]'],
|
237 |
-
['*[foo="bar"]', '//*[@foo="bar"]'],
|
238 |
-
['*[foo=\'bar\']', '//*[@foo="bar"]'],
|
239 |
-
['select[name=category] option[selected=selected]', '//select[@name="category"]//option[@selected="selected"]'],
|
240 |
-
['*[^data-]', '//*[@*[starts-with(name(), "data-")]]'],
|
241 |
-
['*[^data-=foo]', '//*[@*[starts-with(name(), "data-")]="foo"]'],
|
242 |
-
['a[href^=https]', '//a[starts-with(@href, "https")]'],
|
243 |
-
['img[src$=png]', '//img[substring(@src, string-length(@src) - string-length("png") + 1) = "png"]'],
|
244 |
-
['a[href*=example.com]', '//a[contains(@href, "example.com")]'],
|
245 |
-
['script[!src]', '//script[not(@src)]'],
|
246 |
-
['a[href!="http://foo.com/"]', '//a[not(@href="http://foo.com/")]'],
|
247 |
-
['a[foo~="bar"]', '//a[contains(concat(" ", normalize-space(@foo), " "), " bar ")]'],
|
248 |
-
['input, textarea, select', '//input|//textarea|//select'],
|
249 |
-
['input[name="name"], textarea[name="description"], select[name="type"]', '//input[@name="name"]|//textarea[@name="description"]|//select[@name="type"]'],
|
250 |
-
['li:first-child', '//li[position() = 1]'],
|
251 |
-
['li:last-child', '//li[position() = last()]'],
|
252 |
-
['*:not(a[href*="example.com"])', '//*[not(self::a[contains(@href, "example.com")])]'],
|
253 |
-
['ul:empty', '//ul[count(descendant::*) = 0]'],
|
254 |
-
['ul:not-empty', '//ul[count(descendant::*) > 0]'],
|
255 |
-
['li:nth-child(odd)', '//*[(name()="li") and (position() mod 2 = 1 and position() >= 1)]'],
|
256 |
-
['li:nth-child(even)', '//*[(name()="li") and (position() mod 2 = 0 and position() >= 0)]'],
|
257 |
-
['li:nth-child(3)', '//*[(name()="li") and (position() = 3)]'],
|
258 |
-
['li:nth-child(-3)', '//*[(name()="li") and (position() = -3)]'],
|
259 |
-
['li:nth-child(3n)', '//*[(name()="li") and ((position() + 0) mod 3 = 0 and position() >= 0)]'],
|
260 |
-
['li:nth-child(3n+1)', '//*[(name()="li") and ((position() - 1) mod 3 = 0 and position() >= 1)]'],
|
261 |
-
['li:nth-child(3n-1)', '//*[(name()="li") and ((position() + 1) mod 3 = 0 and position() >= 1)]'],
|
262 |
-
['li:nth-child(n+3)', '//*[(name()="li") and ((position() - 3) mod 1 = 0 and position() >= 3)]'],
|
263 |
-
['li:nth-child(n-3)', '//*[(name()="li") and ((position() + 3) mod 1 = 0 and position() >= 3)]'],
|
264 |
-
['li:nth-of-type(odd)', '//li[position() mod 2 = 1 and position() >= 1]'],
|
265 |
-
['li:nth-of-type(even)', '//li[position() mod 2 = 0 and position() >= 0]'],
|
266 |
-
['li:nth-of-type(3)', '//li[position() = 3]'],
|
267 |
-
['li:nth-of-type(-3)', '//li[position() = -3]'],
|
268 |
-
['li:nth-of-type(3n)', '//li[(position() + 0) mod 3 = 0 and position() >= 0]'],
|
269 |
-
['li:nth-of-type(3n+1)', '//li[(position() - 1) mod 3 = 0 and position() >= 1]'],
|
270 |
-
['li:nth-of-type(3n-1)', '//li[(position() + 1) mod 3 = 0 and position() >= 1]'],
|
271 |
-
['li:nth-of-type(n+3)', '//li[(position() - 3) mod 1 = 0 and position() >= 3]'],
|
272 |
-
['li:nth-of-type(n-3)', '//li[(position() + 3) mod 1 = 0 and position() >= 3]'],
|
273 |
-
['ul:has(li.item)', '//ul[.//li[contains(concat(" ", normalize-space(@class), " "), " item ")]]'],
|
274 |
-
['form[name=register]:has(input[name=foo])', '//form[(@name="register") and (.//input[@name="foo"])]'],
|
275 |
-
['ul li a::text', '//ul//li//a/text()'],
|
276 |
-
['ul li a::text()', '//ul//li//a/text()'],
|
277 |
-
['ul li a::attr(href)', '//ul//li//a/@*[name() = "href"]'],
|
278 |
-
['ul li a::attr(href, title)', '//ul//li//a/@*[name() = "href" or name() = "title"]'],
|
279 |
-
['> ul li a', '/ul//li//a'],
|
280 |
-
];
|
281 |
-
|
282 |
-
$compiled = array_merge($compiled, $this->getContainsPseudoClassTests());
|
283 |
-
$compiled = array_merge($compiled, $this->getPropertiesTests());
|
284 |
-
|
285 |
-
$compiled = array_merge($compiled, [
|
286 |
-
['a[title="foo, bar::baz"]', '//a[@title="foo, bar::baz"]'],
|
287 |
-
]);
|
288 |
-
|
289 |
-
return $compiled;
|
290 |
-
}
|
291 |
-
|
292 |
-
private function getContainsPseudoClassTests()
|
293 |
-
{
|
294 |
-
$strToLowerFunction = function_exists('mb_strtolower') ? 'mb_strtolower' : 'strtolower';
|
295 |
-
|
296 |
-
$containsXpath = [
|
297 |
-
// caseSensitive = true, fullMatch = false
|
298 |
-
['li:contains(foo)', '//li[contains(text(), "foo")]'],
|
299 |
-
['li:contains("foo")', '//li[contains(text(), "foo")]'],
|
300 |
-
['li:contains(\'foo\')', '//li[contains(text(), "foo")]'],
|
301 |
-
|
302 |
-
// caseSensitive = true, fullMatch = false
|
303 |
-
['li:contains(foo, true)', '//li[contains(text(), "foo")]'],
|
304 |
-
['li:contains("foo", true)', '//li[contains(text(), "foo")]'],
|
305 |
-
['li:contains(\'foo\', true)', '//li[contains(text(), "foo")]'],
|
306 |
-
|
307 |
-
// caseSensitive = true, fullMatch = false
|
308 |
-
['li:contains(foo, true, false)', '//li[contains(text(), "foo")]'],
|
309 |
-
['li:contains("foo", true, false)', '//li[contains(text(), "foo")]'],
|
310 |
-
['li:contains(\'foo\', true, false)', '//li[contains(text(), "foo")]'],
|
311 |
-
|
312 |
-
// caseSensitive = true, fullMatch = true
|
313 |
-
['li:contains(foo, true, true)', '//li[text() = "foo"]'],
|
314 |
-
['li:contains("foo", true, true)', '//li[text() = "foo"]'],
|
315 |
-
['li:contains(\'foo\', true, true)', '//li[text() = "foo"]'],
|
316 |
-
|
317 |
-
// caseSensitive = false, fullMatch = false
|
318 |
-
['li:contains(foo, false)', "//li[contains(php:functionString(\"{$strToLowerFunction}\", .), php:functionString(\"{$strToLowerFunction}\", \"foo\"))]"],
|
319 |
-
['li:contains("foo", false)', "//li[contains(php:functionString(\"{$strToLowerFunction}\", .), php:functionString(\"{$strToLowerFunction}\", \"foo\"))]"],
|
320 |
-
['li:contains(\'foo\', false)', "//li[contains(php:functionString(\"{$strToLowerFunction}\", .), php:functionString(\"{$strToLowerFunction}\", \"foo\"))]"],
|
321 |
-
|
322 |
-
// caseSensitive = false, fullMatch = false
|
323 |
-
['li:contains(foo, false, false)', "//li[contains(php:functionString(\"{$strToLowerFunction}\", .), php:functionString(\"{$strToLowerFunction}\", \"foo\"))]"],
|
324 |
-
['li:contains("foo", false, false)', "//li[contains(php:functionString(\"{$strToLowerFunction}\", .), php:functionString(\"{$strToLowerFunction}\", \"foo\"))]"],
|
325 |
-
['li:contains(\'foo\', false, false)', "//li[contains(php:functionString(\"{$strToLowerFunction}\", .), php:functionString(\"{$strToLowerFunction}\", \"foo\"))]"],
|
326 |
-
|
327 |
-
// caseSensitive = false, fullMatch = true
|
328 |
-
['li:contains(foo, false, true)', "//li[php:functionString(\"{$strToLowerFunction}\", .) = php:functionString(\"{$strToLowerFunction}\", \"foo\")]"],
|
329 |
-
['li:contains("foo", false, true)', "//li[php:functionString(\"{$strToLowerFunction}\", .) = php:functionString(\"{$strToLowerFunction}\", \"foo\")]"],
|
330 |
-
['li:contains(\'foo\', false, true)', "//li[php:functionString(\"{$strToLowerFunction}\", .) = php:functionString(\"{$strToLowerFunction}\", \"foo\")]"],
|
331 |
-
];
|
332 |
-
|
333 |
-
return $containsXpath;
|
334 |
-
}
|
335 |
-
|
336 |
-
private function getPropertiesTests()
|
337 |
-
{
|
338 |
-
return [
|
339 |
-
['a::text', '//a/text()'],
|
340 |
-
['a::text()', '//a/text()'],
|
341 |
-
['a::attr', '//a/@*'],
|
342 |
-
['a::attr()', '//a/@*'],
|
343 |
-
['a::attr(href)', '//a/@*[name() = "href"]'],
|
344 |
-
['a::attr(href,title)', '//a/@*[name() = "href" or name() = "title"]'],
|
345 |
-
['a::attr(href, title)', '//a/@*[name() = "href" or name() = "title"]'],
|
346 |
-
];
|
347 |
-
}
|
348 |
-
|
349 |
-
public function buildXpathTests()
|
350 |
-
{
|
351 |
-
$xpath = [
|
352 |
-
'//a',
|
353 |
-
'//*[@id="foo"]',
|
354 |
-
'//a[@id="foo"]',
|
355 |
-
'//a[contains(concat(" ", normalize-space(@class), " "), " foo ")]',
|
356 |
-
'//a[(contains(concat(" ", normalize-space(@class), " "), " foo ")) and (contains(concat(" ", normalize-space(@class), " "), " bar "))]',
|
357 |
-
'//a[@href]',
|
358 |
-
'//a[@href="http://example.com/"]',
|
359 |
-
'//a[(@href="http://example.com/") and (@title="Example Domain")]',
|
360 |
-
'//a[(@target="_blank") and (starts-with(@href, "https"))]',
|
361 |
-
'//a[substring(@href, string-length(@href) - string-length(".com") + 1) = ".com"]',
|
362 |
-
'//a[contains(@href, "example")]',
|
363 |
-
'//a[not(@href="http://foo.com/")]',
|
364 |
-
'//script[not(@src)]',
|
365 |
-
'//li[position() = 1]',
|
366 |
-
'//*[(@id="id") and (contains(concat(" ", normalize-space(@class), " "), " foo ")) and (@name="value") and (position() = 1)]',
|
367 |
-
];
|
368 |
-
|
369 |
-
$segments = [
|
370 |
-
['tag' => 'a'],
|
371 |
-
['id' => 'foo'],
|
372 |
-
['tag' => 'a', 'id' => 'foo'],
|
373 |
-
['tag' => 'a', 'classes' => ['foo']],
|
374 |
-
['tag' => 'a', 'classes' => ['foo', 'bar']],
|
375 |
-
['tag' => 'a', 'attributes' => ['href' => null]],
|
376 |
-
['tag' => 'a', 'attributes' => ['href' => 'http://example.com/']],
|
377 |
-
['tag' => 'a', 'attributes' => ['href' => 'http://example.com/', 'title' => 'Example Domain']],
|
378 |
-
['tag' => 'a', 'attributes' => ['target' => '_blank', 'href^' => 'https']],
|
379 |
-
['tag' => 'a', 'attributes' => ['href$' => '.com']],
|
380 |
-
['tag' => 'a', 'attributes' => ['href*' => 'example']],
|
381 |
-
['tag' => 'a', 'attributes' => ['href!' => 'http://foo.com/']],
|
382 |
-
['tag' => 'script', 'attributes' => ['!src' => null]],
|
383 |
-
['tag' => 'li', 'pseudo' => 'first-child'],
|
384 |
-
['tag' => '*', 'id' => 'id', 'classes' => ['foo'], 'attributes' => ['name' => 'value'], 'pseudo' => 'first-child', 'rel' => '>'],
|
385 |
-
];
|
386 |
-
|
387 |
-
$parameters = [];
|
388 |
-
|
389 |
-
foreach ($segments as $index => $segment) {
|
390 |
-
$parameters[] = [$segment, $xpath[$index]];
|
391 |
-
}
|
392 |
-
|
393 |
-
return $parameters;
|
394 |
-
}
|
395 |
-
|
396 |
-
public function getSegmentsTests()
|
397 |
-
{
|
398 |
-
$segments = [
|
399 |
-
['selector' => 'a', 'tag' => 'a'],
|
400 |
-
['selector' => '#foo', 'id' => 'foo'],
|
401 |
-
['selector' => 'a#foo', 'tag' => 'a', 'id' => 'foo'],
|
402 |
-
['selector' => 'a.foo', 'tag' => 'a', 'classes' => ['foo']],
|
403 |
-
['selector' => 'a.foo.bar', 'tag' => 'a', 'classes' => ['foo', 'bar']],
|
404 |
-
['selector' => 'a[href]', 'tag' => 'a', 'attributes' => ['href' => null]],
|
405 |
-
['selector' => 'a[href=http://example.com/]', 'tag' => 'a', 'attributes' => ['href' => 'http://example.com/']],
|
406 |
-
['selector' => 'a[href="http://example.com/"]', 'tag' => 'a', 'attributes' => ['href' => 'http://example.com/']],
|
407 |
-
['selector' => 'a[href=\'http://example.com/\']', 'tag' => 'a', 'attributes' => ['href' => 'http://example.com/']],
|
408 |
-
['selector' => 'a[href=http://example.com/][title=Example Domain]', 'tag' => 'a', 'attributes' => ['href' => 'http://example.com/', 'title' => 'Example Domain']],
|
409 |
-
['selector' => 'a[href=http://example.com/][href=http://example.com/404]', 'tag' => 'a', 'attributes' => ['href' => 'http://example.com/404']],
|
410 |
-
['selector' => 'a[href^=https]', 'tag' => 'a', 'attributes' => ['href^' => 'https']],
|
411 |
-
['selector' => 'li:first-child', 'tag' => 'li', 'pseudo' => 'first-child'],
|
412 |
-
['selector' => 'ul >', 'tag' => 'ul', 'rel' => '>'],
|
413 |
-
['selector' => '#id.foo[name=value]:first-child >', 'id' => 'id', 'classes' => ['foo'], 'attributes' => ['name' => 'value'], 'pseudo' => 'first-child', 'rel' => '>'],
|
414 |
-
['selector' => 'li.bar:nth-child(2n)', 'tag' => 'li', 'classes' => ['bar'], 'pseudo' => 'nth-child', 'expr' => '2n'],
|
415 |
-
];
|
416 |
-
|
417 |
-
$parameters = [];
|
418 |
-
|
419 |
-
foreach ($segments as $segment) {
|
420 |
-
$parameters[] = [$segment['selector'], $segment];
|
421 |
-
}
|
422 |
-
|
423 |
-
return $parameters;
|
424 |
-
}
|
425 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/imangazaliev/didom/tests/DiDom/SelectorTest.php
DELETED
@@ -1,327 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Tests\DiDom;
|
4 |
-
|
5 |
-
use DiDom\Document;
|
6 |
-
use Tests\TestCase;
|
7 |
-
|
8 |
-
class SelectorTest extends TestCase
|
9 |
-
{
|
10 |
-
public function testTag()
|
11 |
-
{
|
12 |
-
$html = '
|
13 |
-
<ul id="first">
|
14 |
-
<li><a href="#">Item 1</a></li>
|
15 |
-
<li><a href="#">Item 2</a></li>
|
16 |
-
<li><a href="#">Item 3</a></li>
|
17 |
-
</ul>
|
18 |
-
<ol id="second">
|
19 |
-
<li><a href="#">Item 1</a></li>
|
20 |
-
<li><a href="#">Item 2</a></li>
|
21 |
-
<li><a href="#">Item 3</a></li>
|
22 |
-
</ol>
|
23 |
-
';
|
24 |
-
|
25 |
-
$document = new Document($html);
|
26 |
-
|
27 |
-
$expected = ['Item 1', 'Item 2', 'Item 3', 'Item 1', 'Item 2', 'Item 3'];
|
28 |
-
|
29 |
-
$result = [];
|
30 |
-
|
31 |
-
foreach ($document->find('li') as $element) {
|
32 |
-
$result[] = $element->text();
|
33 |
-
}
|
34 |
-
|
35 |
-
$this->assertEquals($expected, $result);
|
36 |
-
}
|
37 |
-
|
38 |
-
public function testNestedTag()
|
39 |
-
{
|
40 |
-
$html = '
|
41 |
-
<ul id="first">
|
42 |
-
<li><a href="#">Item 1</a></li>
|
43 |
-
<li><a href="#">Item 2</a></li>
|
44 |
-
<li><a href="#">Item 3</a></li>
|
45 |
-
</ul>
|
46 |
-
<ol id="second">
|
47 |
-
<li><a href="#">Item 1</a></li>
|
48 |
-
<li><a href="#">Item 2</a></li>
|
49 |
-
<li><a href="#">Item 3</a></li>
|
50 |
-
</ol>
|
51 |
-
';
|
52 |
-
|
53 |
-
$document = new Document($html);
|
54 |
-
|
55 |
-
$expected = ['Item 1', 'Item 2', 'Item 3'];
|
56 |
-
|
57 |
-
$result = [];
|
58 |
-
|
59 |
-
foreach ($document->find('ul a') as $element) {
|
60 |
-
$result[] = $element->text();
|
61 |
-
}
|
62 |
-
|
63 |
-
$this->assertEquals($expected, $result);
|
64 |
-
}
|
65 |
-
|
66 |
-
public function testDirectChild()
|
67 |
-
{
|
68 |
-
$html = '
|
69 |
-
<div>
|
70 |
-
<p><span>Lorem ipsum.</span></p>
|
71 |
-
<span>Lorem ipsum.</span>
|
72 |
-
</div>
|
73 |
-
';
|
74 |
-
|
75 |
-
$document = new Document($html);
|
76 |
-
|
77 |
-
$expected = ['Lorem ipsum.'];
|
78 |
-
|
79 |
-
$result = [];
|
80 |
-
|
81 |
-
foreach ($document->find('div > span') as $element) {
|
82 |
-
$result[] = $element->text();
|
83 |
-
}
|
84 |
-
|
85 |
-
$this->assertEquals($expected, $result);
|
86 |
-
}
|
87 |
-
|
88 |
-
public function testId()
|
89 |
-
{
|
90 |
-
$html = '
|
91 |
-
<span>Lorem ipsum dolor.</span>
|
92 |
-
<span id="second">Tenetur totam, nostrum.</span>
|
93 |
-
<span>Iste, doloremque, praesentium.</span>
|
94 |
-
';
|
95 |
-
|
96 |
-
$document = new Document($html);
|
97 |
-
|
98 |
-
$expected = ['Tenetur totam, nostrum.'];
|
99 |
-
|
100 |
-
$result = [];
|
101 |
-
|
102 |
-
foreach ($document->find('#second') as $element) {
|
103 |
-
$result[] = $element->text();
|
104 |
-
}
|
105 |
-
|
106 |
-
$this->assertEquals($expected, $result);
|
107 |
-
}
|
108 |
-
|
109 |
-
public function testClass()
|
110 |
-
{
|
111 |
-
$html = '
|
112 |
-
<span class="odd first">Lorem ipsum dolor.</span>
|
113 |
-
<span class="even second">Tenetur totam, nostrum.</span>
|
114 |
-
<span class="odd third">Iste, doloremque, praesentium.</span>
|
115 |
-
';
|
116 |
-
|
117 |
-
$document = new Document($html);
|
118 |
-
|
119 |
-
$expected = ['Lorem ipsum dolor.', 'Iste, doloremque, praesentium.'];
|
120 |
-
|
121 |
-
$result = [];
|
122 |
-
|
123 |
-
foreach ($document->find('.odd') as $element) {
|
124 |
-
$result[] = $element->text();
|
125 |
-
}
|
126 |
-
|
127 |
-
$this->assertEquals($expected, $result);
|
128 |
-
|
129 |
-
$expected = ['Iste, doloremque, praesentium.'];
|
130 |
-
|
131 |
-
$result = [];
|
132 |
-
|
133 |
-
foreach ($document->find('.odd.third') as $element) {
|
134 |
-
$result[] = $element->text();
|
135 |
-
}
|
136 |
-
|
137 |
-
$this->assertEquals($expected, $result);
|
138 |
-
}
|
139 |
-
|
140 |
-
public function testAttributes()
|
141 |
-
{
|
142 |
-
$html = '
|
143 |
-
<ul class="links">
|
144 |
-
<li>
|
145 |
-
<a href="https://foo.com" title="Foo" target="_blank">Foo</a>
|
146 |
-
<a href="http://bar.com" title="Bar" rel="noreferrer">Bar</a>
|
147 |
-
<a href="https://baz.org" title="Baz" rel="nofollow noreferrer">Baz</a>
|
148 |
-
<a href="http://qux.org" title="Qux" target="_blank" rel="nofollow">Qux</a>
|
149 |
-
</li>
|
150 |
-
</ul>
|
151 |
-
';
|
152 |
-
|
153 |
-
$document = new Document($html);
|
154 |
-
|
155 |
-
// has attribute
|
156 |
-
|
157 |
-
$expected = ['Foo', 'Qux'];
|
158 |
-
|
159 |
-
$result = [];
|
160 |
-
|
161 |
-
foreach ($document->find('a[target]') as $element) {
|
162 |
-
$result[] = $element->text();
|
163 |
-
}
|
164 |
-
|
165 |
-
$this->assertEquals($expected, $result);
|
166 |
-
|
167 |
-
// has no attribute
|
168 |
-
|
169 |
-
$expected = ['Bar', 'Baz'];
|
170 |
-
|
171 |
-
$result = [];
|
172 |
-
|
173 |
-
foreach ($document->find('a[!target]') as $element) {
|
174 |
-
$result[] = $element->text();
|
175 |
-
}
|
176 |
-
|
177 |
-
$this->assertEquals($expected, $result);
|
178 |
-
|
179 |
-
// equals
|
180 |
-
|
181 |
-
$expected = ['Baz'];
|
182 |
-
|
183 |
-
$result = [];
|
184 |
-
|
185 |
-
foreach ($document->find('a[href="https://baz.org"]') as $element) {
|
186 |
-
$result[] = $element->text();
|
187 |
-
}
|
188 |
-
|
189 |
-
$this->assertEquals($expected, $result);
|
190 |
-
|
191 |
-
// not equals
|
192 |
-
|
193 |
-
$expected = ['Foo', 'Bar', 'Qux'];
|
194 |
-
|
195 |
-
$result = [];
|
196 |
-
|
197 |
-
foreach ($document->find('a[href!="https://baz.org"]') as $element) {
|
198 |
-
$result[] = $element->text();
|
199 |
-
}
|
200 |
-
|
201 |
-
$this->assertEquals($expected, $result);
|
202 |
-
|
203 |
-
// starts with
|
204 |
-
|
205 |
-
$expected = ['Foo', 'Baz'];
|
206 |
-
|
207 |
-
$result = [];
|
208 |
-
|
209 |
-
foreach ($document->find('a[href^="https"]') as $element) {
|
210 |
-
$result[] = $element->text();
|
211 |
-
}
|
212 |
-
|
213 |
-
$this->assertEquals($expected, $result);
|
214 |
-
|
215 |
-
// ends with
|
216 |
-
|
217 |
-
$expected = ['Baz', 'Qux'];
|
218 |
-
|
219 |
-
$result = [];
|
220 |
-
|
221 |
-
foreach ($document->find('a[href$="org"]') as $element) {
|
222 |
-
$result[] = $element->text();
|
223 |
-
}
|
224 |
-
|
225 |
-
$this->assertEquals($expected, $result);
|
226 |
-
|
227 |
-
// contains word
|
228 |
-
|
229 |
-
$expected = ['Bar', 'Baz'];
|
230 |
-
|
231 |
-
$result = [];
|
232 |
-
|
233 |
-
foreach ($document->find('a[rel~="noreferrer"]') as $element) {
|
234 |
-
$result[] = $element->text();
|
235 |
-
}
|
236 |
-
|
237 |
-
$this->assertEquals($expected, $result);
|
238 |
-
$this->assertEquals([], $document->find('a[rel~="noref"]'));
|
239 |
-
|
240 |
-
// contains substring
|
241 |
-
|
242 |
-
$expected = ['Bar', 'Baz'];
|
243 |
-
|
244 |
-
$result = [];
|
245 |
-
|
246 |
-
foreach ($document->find('a[href*="ba"]') as $element) {
|
247 |
-
$result[] = $element->text();
|
248 |
-
}
|
249 |
-
|
250 |
-
$this->assertEquals($expected, $result);
|
251 |
-
|
252 |
-
// multiple attribute conditions
|
253 |
-
|
254 |
-
$expected = ['Qux'];
|
255 |
-
|
256 |
-
$result = [];
|
257 |
-
|
258 |
-
foreach ($document->find('a[target="_blank"][rel="nofollow"]') as $element) {
|
259 |
-
$result[] = $element->text();
|
260 |
-
}
|
261 |
-
|
262 |
-
$this->assertEquals($expected, $result);
|
263 |
-
}
|
264 |
-
|
265 |
-
/**
|
266 |
-
* @param $selector
|
267 |
-
* @param $expectedResult
|
268 |
-
*
|
269 |
-
* @dataProvider containsPseudoClassTests
|
270 |
-
*/
|
271 |
-
public function testContainsPseudoClass($selector, $expectedResult)
|
272 |
-
{
|
273 |
-
$html = '
|
274 |
-
<ul class="links">
|
275 |
-
<li>
|
276 |
-
<a href="https://foo.com" title="Foo" target="_blank">Foo</a>
|
277 |
-
<a href="http://bar.com" title="Bar" rel="noreferrer">Bar</a>
|
278 |
-
<a href="https://baz.org" title="Baz" rel="nofollow noreferrer">Baz</a>
|
279 |
-
<a href="http://qux.org" title="Qux" target="_blank" rel="nofollow">Qux</a>
|
280 |
-
<a href="https://foobar.com" title="FooBar" target="_blank">FooBar</a>
|
281 |
-
</li>
|
282 |
-
</ul>
|
283 |
-
';
|
284 |
-
|
285 |
-
$document = new Document($html);
|
286 |
-
|
287 |
-
$result = [];
|
288 |
-
|
289 |
-
foreach ($document->find($selector) as $element) {
|
290 |
-
$result[] = $element->text();
|
291 |
-
}
|
292 |
-
|
293 |
-
$this->assertEquals($expectedResult, $result);
|
294 |
-
}
|
295 |
-
|
296 |
-
public function containsPseudoClassTests()
|
297 |
-
{
|
298 |
-
return [
|
299 |
-
['a:contains(Baz)', ['Baz']],
|
300 |
-
['a:contains(a)', ['Bar', 'Baz', 'FooBar']],
|
301 |
-
['a:contains(Bar)', ['Bar', 'FooBar']],
|
302 |
-
['a:contains(Bar, true, true)', ['Bar']],
|
303 |
-
['a:contains(bar)', []],
|
304 |
-
['a:contains(bar, false)', ['Bar', 'FooBar']],
|
305 |
-
['a:contains(bar, false, true)', ['Bar']],
|
306 |
-
];
|
307 |
-
}
|
308 |
-
|
309 |
-
public function testUnicodeSupport()
|
310 |
-
{
|
311 |
-
$html = '
|
312 |
-
<ul class="links">
|
313 |
-
<li>
|
314 |
-
<a href="http://foo.com" title="Foo">Foo</a>
|
315 |
-
<a href="http://example.com" title="Пример">Example</a>
|
316 |
-
<a href="http://bar.com" title="Foo">Bar</a>
|
317 |
-
<a href="http://example.ru" title="Example">Пример</a>
|
318 |
-
</li>
|
319 |
-
</ul>
|
320 |
-
';
|
321 |
-
|
322 |
-
$document = new Document($html);
|
323 |
-
|
324 |
-
$this->assertEquals('Example', $document->first('a[title=Пример]')->text());
|
325 |
-
$this->assertEquals('Example', $document->first('a:contains(Пример)')->attr('title'));
|
326 |
-
}
|
327 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/imangazaliev/didom/tests/DiDom/StyleAttributeTest.php
DELETED
@@ -1,515 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Tests\DiDom;
|
4 |
-
|
5 |
-
use DiDom\Element;
|
6 |
-
use DiDom\StyleAttribute;
|
7 |
-
use Tests\TestCase;
|
8 |
-
|
9 |
-
class StyleAttributeTest extends TestCase
|
10 |
-
{
|
11 |
-
/**
|
12 |
-
* @expectedException \InvalidArgumentException
|
13 |
-
* @expectedExceptionMessage The element must contain DOMElement node
|
14 |
-
*/
|
15 |
-
public function testConstructorWithTextNode()
|
16 |
-
{
|
17 |
-
$element = new Element(new \DOMText('foo'));
|
18 |
-
|
19 |
-
new StyleAttribute($element);
|
20 |
-
}
|
21 |
-
|
22 |
-
/**
|
23 |
-
* @expectedException \InvalidArgumentException
|
24 |
-
* @expectedExceptionMessage The element must contain DOMElement node
|
25 |
-
*/
|
26 |
-
public function testConstructorWithCommentNode()
|
27 |
-
{
|
28 |
-
$element = new Element(new \DOMComment('foo'));
|
29 |
-
|
30 |
-
new StyleAttribute($element);
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* @expectedException \InvalidArgumentException
|
35 |
-
* @expectedExceptionMessage DiDom\StyleAttribute::setProperty expects parameter 1 to be string, NULL given
|
36 |
-
*/
|
37 |
-
public function testSetPropertyWithInvalidPropertyName()
|
38 |
-
{
|
39 |
-
$element = new Element('div', null, [
|
40 |
-
'style' => 'color: blue; border: 1px solid black',
|
41 |
-
]);
|
42 |
-
|
43 |
-
$styleAttribute = new StyleAttribute($element);
|
44 |
-
|
45 |
-
$styleAttribute->setProperty(null, '16px');
|
46 |
-
}
|
47 |
-
|
48 |
-
/**
|
49 |
-
* @expectedException \InvalidArgumentException
|
50 |
-
* @expectedExceptionMessage DiDom\StyleAttribute::setProperty expects parameter 2 to be string, NULL given
|
51 |
-
*/
|
52 |
-
public function testSetPropertyWithInvalidPropertyValue()
|
53 |
-
{
|
54 |
-
$element = new Element('div', null, [
|
55 |
-
'style' => 'color: blue; border: 1px solid black',
|
56 |
-
]);
|
57 |
-
|
58 |
-
$styleAttribute = new StyleAttribute($element);
|
59 |
-
|
60 |
-
$styleAttribute->setProperty('font-size', null);
|
61 |
-
}
|
62 |
-
|
63 |
-
public function testSetProperty()
|
64 |
-
{
|
65 |
-
$element = new Element('div', null, [
|
66 |
-
'style' => 'color: blue; border: 1px solid black',
|
67 |
-
]);
|
68 |
-
|
69 |
-
$styleAttribute = new StyleAttribute($element);
|
70 |
-
|
71 |
-
$this->assertEquals('color: blue; border: 1px solid black', $element->getAttribute('style'));
|
72 |
-
|
73 |
-
$styleAttribute->setProperty('font-size', '16px');
|
74 |
-
|
75 |
-
$this->assertEquals('color: blue; border: 1px solid black; font-size: 16px', $element->getAttribute('style'));
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* @expectedException \InvalidArgumentException
|
80 |
-
* @expectedExceptionMessage Property name must be a string, integer given
|
81 |
-
*/
|
82 |
-
public function testSetMultiplePropertiesWithInvalidPropertyName()
|
83 |
-
{
|
84 |
-
$element = new Element('div', null, [
|
85 |
-
'style' => 'color: blue; border: 1px solid black',
|
86 |
-
]);
|
87 |
-
|
88 |
-
$styleAttribute = new StyleAttribute($element);
|
89 |
-
|
90 |
-
$styleAttribute->setMultipleProperties([
|
91 |
-
'width' => '50px',
|
92 |
-
'height',
|
93 |
-
]);
|
94 |
-
}
|
95 |
-
|
96 |
-
/**
|
97 |
-
* @expectedException \InvalidArgumentException
|
98 |
-
* @expectedExceptionMessage Property value must be a string, NULL given
|
99 |
-
*/
|
100 |
-
public function testSetMultiplePropertiesWithInvalidPropertyValue()
|
101 |
-
{
|
102 |
-
$element = new Element('div', null, [
|
103 |
-
'style' => 'color: blue; border: 1px solid black',
|
104 |
-
]);
|
105 |
-
|
106 |
-
$styleAttribute = new StyleAttribute($element);
|
107 |
-
|
108 |
-
$styleAttribute->setMultipleProperties([
|
109 |
-
'width' => '50px',
|
110 |
-
'height' => null,
|
111 |
-
]);
|
112 |
-
}
|
113 |
-
|
114 |
-
public function testSetMultipleProperties()
|
115 |
-
{
|
116 |
-
$element = new Element('div', null, [
|
117 |
-
'style' => 'color: blue; border: 1px solid black',
|
118 |
-
]);
|
119 |
-
|
120 |
-
$styleAttribute = new StyleAttribute($element);
|
121 |
-
|
122 |
-
$this->assertEquals('color: blue; border: 1px solid black', $element->getAttribute('style'));
|
123 |
-
|
124 |
-
$styleAttribute->setMultipleProperties([
|
125 |
-
'font-size' => '16px',
|
126 |
-
'font-family' => 'Times',
|
127 |
-
]);
|
128 |
-
|
129 |
-
$this->assertEquals('color: blue; border: 1px solid black; font-size: 16px; font-family: Times', $element->getAttribute('style'));
|
130 |
-
}
|
131 |
-
|
132 |
-
/**
|
133 |
-
* @expectedException \InvalidArgumentException
|
134 |
-
* @expectedExceptionMessage DiDom\StyleAttribute::getProperty expects parameter 1 to be string, NULL given
|
135 |
-
*/
|
136 |
-
public function testGetPropertyWithInvalidPropertyName()
|
137 |
-
{
|
138 |
-
$element = new Element('div', null, [
|
139 |
-
'style' => 'color: blue; border: 1px solid black',
|
140 |
-
]);
|
141 |
-
|
142 |
-
$styleAttribute = new StyleAttribute($element);
|
143 |
-
|
144 |
-
$styleAttribute->getProperty(null);
|
145 |
-
}
|
146 |
-
|
147 |
-
/**
|
148 |
-
* @param string $styleString
|
149 |
-
* @param string $propertyName
|
150 |
-
* @param string $expectedResult
|
151 |
-
*
|
152 |
-
* @dataProvider getPropertyDataProvider
|
153 |
-
*/
|
154 |
-
public function testGetProperty($styleString, $propertyName, $expectedResult)
|
155 |
-
{
|
156 |
-
$element = new Element('div', null, [
|
157 |
-
'style' => $styleString,
|
158 |
-
]);
|
159 |
-
|
160 |
-
$styleAttribute = new StyleAttribute($element);
|
161 |
-
|
162 |
-
$this->assertEquals($expectedResult, $styleAttribute->getProperty($propertyName));
|
163 |
-
}
|
164 |
-
|
165 |
-
public function getPropertyDataProvider()
|
166 |
-
{
|
167 |
-
return [
|
168 |
-
[
|
169 |
-
'color: blue; font-size: 16px; border: 1px solid black',
|
170 |
-
'font-size',
|
171 |
-
'16px',
|
172 |
-
],
|
173 |
-
[
|
174 |
-
'color: blue; font-size: 16px; border: 1px solid black;',
|
175 |
-
'font-size',
|
176 |
-
'16px',
|
177 |
-
],
|
178 |
-
[
|
179 |
-
'color: blue; font-size: 16px; border: 1px solid black;',
|
180 |
-
'foo',
|
181 |
-
null,
|
182 |
-
],
|
183 |
-
];
|
184 |
-
}
|
185 |
-
|
186 |
-
public function testGetPropertyWithDefaultValue()
|
187 |
-
{
|
188 |
-
$element = new Element('div', null, [
|
189 |
-
'style' => 'color: blue',
|
190 |
-
]);
|
191 |
-
|
192 |
-
$styleAttribute = new StyleAttribute($element);
|
193 |
-
|
194 |
-
$this->assertNull($styleAttribute->getProperty('font-size'));
|
195 |
-
$this->assertEquals('16px', $styleAttribute->getProperty('font-size', '16px'));
|
196 |
-
}
|
197 |
-
|
198 |
-
/**
|
199 |
-
* @expectedException \InvalidArgumentException
|
200 |
-
* @expectedExceptionMessage Property name must be a string, NULL given
|
201 |
-
*/
|
202 |
-
public function testGetMultiplePropertiesWithInvalidPropertyName()
|
203 |
-
{
|
204 |
-
$element = new Element('div', null, [
|
205 |
-
'style' => 'color: blue; border: 1px solid black',
|
206 |
-
]);
|
207 |
-
|
208 |
-
$styleAttribute = new StyleAttribute($element);
|
209 |
-
|
210 |
-
$styleAttribute->getMultipleProperties(['color', null]);
|
211 |
-
}
|
212 |
-
|
213 |
-
/**
|
214 |
-
* @param string $styleString
|
215 |
-
* @param array $propertyNames
|
216 |
-
* @param string $expectedResult
|
217 |
-
*
|
218 |
-
* @dataProvider getMultiplePropertiesDataProvider
|
219 |
-
*/
|
220 |
-
public function testGetMultipleProperties($styleString, $propertyNames, $expectedResult)
|
221 |
-
{
|
222 |
-
$element = new Element('div', null, [
|
223 |
-
'style' => $styleString,
|
224 |
-
]);
|
225 |
-
|
226 |
-
$styleAttribute = new StyleAttribute($element);
|
227 |
-
|
228 |
-
$this->assertEquals($expectedResult, $styleAttribute->getMultipleProperties($propertyNames));
|
229 |
-
}
|
230 |
-
|
231 |
-
public function getMultiplePropertiesDataProvider()
|
232 |
-
{
|
233 |
-
return [
|
234 |
-
[
|
235 |
-
'color: blue; font-size: 16px; font-family: Times; border: 1px solid black',
|
236 |
-
['font-size'],
|
237 |
-
[
|
238 |
-
'font-size' => '16px',
|
239 |
-
],
|
240 |
-
],
|
241 |
-
[
|
242 |
-
'color: blue; font-size: 16px; font-family: Times; border: 1px solid black',
|
243 |
-
['font-size', 'border'],
|
244 |
-
[
|
245 |
-
'font-size' => '16px',
|
246 |
-
'border' => '1px solid black',
|
247 |
-
],
|
248 |
-
],
|
249 |
-
[
|
250 |
-
'color: blue; font-size: 16px; font-family: Times; border: 1px solid black',
|
251 |
-
['font-size', 'border', 'width'],
|
252 |
-
[
|
253 |
-
'font-size' => '16px',
|
254 |
-
'border' => '1px solid black',
|
255 |
-
],
|
256 |
-
],
|
257 |
-
];
|
258 |
-
}
|
259 |
-
|
260 |
-
/**
|
261 |
-
* @param string $styleString
|
262 |
-
* @param string $expectedResult
|
263 |
-
*
|
264 |
-
* @dataProvider getAllPropertiesDataProvider
|
265 |
-
*/
|
266 |
-
public function testGetAllProperties($styleString, $expectedResult)
|
267 |
-
{
|
268 |
-
$element = new Element('div', null, [
|
269 |
-
'style' => $styleString,
|
270 |
-
]);
|
271 |
-
|
272 |
-
$styleAttribute = new StyleAttribute($element);
|
273 |
-
|
274 |
-
$this->assertEquals($expectedResult, $styleAttribute->getAllProperties());
|
275 |
-
}
|
276 |
-
|
277 |
-
public function getAllPropertiesDataProvider()
|
278 |
-
{
|
279 |
-
return [
|
280 |
-
[
|
281 |
-
'',
|
282 |
-
[],
|
283 |
-
],
|
284 |
-
[
|
285 |
-
'color: blue; font-size: 16px; border: 1px solid black',
|
286 |
-
[
|
287 |
-
'color' => 'blue',
|
288 |
-
'font-size' => '16px',
|
289 |
-
'border' => '1px solid black',
|
290 |
-
],
|
291 |
-
],
|
292 |
-
[
|
293 |
-
'color: blue; font-size: 16px; border: 1px solid black',
|
294 |
-
[
|
295 |
-
'color' => 'blue',
|
296 |
-
'font-size' => '16px',
|
297 |
-
'border' => '1px solid black',
|
298 |
-
],
|
299 |
-
],
|
300 |
-
];
|
301 |
-
}
|
302 |
-
|
303 |
-
public function testGetAllPropertiesAfterEmptyStyleAttribute()
|
304 |
-
{
|
305 |
-
$element = new Element('div', null, [
|
306 |
-
'style' => 'color: blue',
|
307 |
-
]);
|
308 |
-
|
309 |
-
$styleAttribute = new StyleAttribute($element);
|
310 |
-
|
311 |
-
$this->assertEquals(['color' => 'blue'], $styleAttribute->getAllProperties());
|
312 |
-
|
313 |
-
$element->setAttribute('style', '');
|
314 |
-
|
315 |
-
$this->assertEquals([], $styleAttribute->getAllProperties());
|
316 |
-
}
|
317 |
-
|
318 |
-
/**
|
319 |
-
* @expectedException \InvalidArgumentException
|
320 |
-
* @expectedExceptionMessage DiDom\StyleAttribute::hasProperty expects parameter 1 to be string, NULL given
|
321 |
-
*/
|
322 |
-
public function testHasPropertyWithInvalidPropertyName()
|
323 |
-
{
|
324 |
-
$element = new Element('div', null, [
|
325 |
-
'style' => 'color: blue; border: 1px solid black',
|
326 |
-
]);
|
327 |
-
|
328 |
-
$styleAttribute = new StyleAttribute($element);
|
329 |
-
|
330 |
-
$styleAttribute->hasProperty(null);
|
331 |
-
}
|
332 |
-
|
333 |
-
public function testHasProperty()
|
334 |
-
{
|
335 |
-
$element = new Element('div', null, [
|
336 |
-
'style' => 'color: blue; border: 1px solid black',
|
337 |
-
]);
|
338 |
-
|
339 |
-
$styleAttribute = new StyleAttribute($element);
|
340 |
-
|
341 |
-
$this->assertTrue($styleAttribute->hasProperty('color'));
|
342 |
-
$this->assertFalse($styleAttribute->hasProperty('width'));
|
343 |
-
}
|
344 |
-
|
345 |
-
/**
|
346 |
-
* @expectedException \InvalidArgumentException
|
347 |
-
* @expectedExceptionMessage DiDom\StyleAttribute::removeProperty expects parameter 1 to be string, NULL given
|
348 |
-
*/
|
349 |
-
public function testRemovePropertyWithInvalidPropertyName()
|
350 |
-
{
|
351 |
-
$element = new Element('div', null, [
|
352 |
-
'style' => 'color: blue; border: 1px solid black',
|
353 |
-
]);
|
354 |
-
|
355 |
-
$styleAttribute = new StyleAttribute($element);
|
356 |
-
|
357 |
-
$styleAttribute->removeProperty(null);
|
358 |
-
}
|
359 |
-
|
360 |
-
public function testRemoveProperty()
|
361 |
-
{
|
362 |
-
$styleString = 'color: blue; font-size: 16px; border: 1px solid black';
|
363 |
-
|
364 |
-
$element = new Element('span', 'foo', [
|
365 |
-
'style' => $styleString,
|
366 |
-
]);
|
367 |
-
|
368 |
-
$styleAttribute = new StyleAttribute($element);
|
369 |
-
|
370 |
-
$this->assertEquals($styleString, $element->getAttribute('style'));
|
371 |
-
|
372 |
-
$styleAttribute->removeProperty('font-size');
|
373 |
-
|
374 |
-
$this->assertEquals('color: blue; border: 1px solid black', $element->getAttribute('style'));
|
375 |
-
}
|
376 |
-
|
377 |
-
/**
|
378 |
-
* @expectedException \InvalidArgumentException
|
379 |
-
* @expectedExceptionMessage Property name must be a string, NULL given
|
380 |
-
*/
|
381 |
-
public function testRemoveMultiplePropertiesWithInvalidPropertyName()
|
382 |
-
{
|
383 |
-
$element = new Element('div', null, [
|
384 |
-
'style' => 'color: blue; border: 1px solid black',
|
385 |
-
]);
|
386 |
-
|
387 |
-
$styleAttribute = new StyleAttribute($element);
|
388 |
-
|
389 |
-
$styleAttribute->removeMultipleProperties(['color', null]);
|
390 |
-
}
|
391 |
-
|
392 |
-
/**
|
393 |
-
* @param string $styleString
|
394 |
-
* @param array $propertyNames
|
395 |
-
* @param string $expectedResult
|
396 |
-
*
|
397 |
-
* @dataProvider removeMultiplePropertiesDataProvider
|
398 |
-
*/
|
399 |
-
public function testRemoveMultipleProperties($styleString, $propertyNames, $expectedResult)
|
400 |
-
{
|
401 |
-
$element = new Element('div', null, [
|
402 |
-
'style' => $styleString,
|
403 |
-
]);
|
404 |
-
|
405 |
-
$styleAttribute = new StyleAttribute($element);
|
406 |
-
|
407 |
-
$this->assertEquals($styleString, $element->getAttribute('style'));
|
408 |
-
|
409 |
-
$styleAttribute->removeMultipleProperties($propertyNames);
|
410 |
-
|
411 |
-
$this->assertEquals($expectedResult, $element->getAttribute('style'));
|
412 |
-
}
|
413 |
-
|
414 |
-
public function removeMultiplePropertiesDataProvider()
|
415 |
-
{
|
416 |
-
return [
|
417 |
-
[
|
418 |
-
'color: blue; font-size: 16px; font-family: Times; border: 1px solid black',
|
419 |
-
[
|
420 |
-
'font-size',
|
421 |
-
],
|
422 |
-
'color: blue; font-family: Times; border: 1px solid black',
|
423 |
-
],
|
424 |
-
[
|
425 |
-
'color: blue; font-size: 16px; font-family: Times; border: 1px solid black',
|
426 |
-
[
|
427 |
-
'font-size', 'border',
|
428 |
-
],
|
429 |
-
'color: blue; font-family: Times',
|
430 |
-
],
|
431 |
-
[
|
432 |
-
'color: blue; font-size: 16px; font-family: Times; border: 1px solid black',
|
433 |
-
[
|
434 |
-
'font-size', 'border', 'width',
|
435 |
-
],
|
436 |
-
'color: blue; font-family: Times',
|
437 |
-
],
|
438 |
-
];
|
439 |
-
}
|
440 |
-
|
441 |
-
/**
|
442 |
-
* @expectedException \InvalidArgumentException
|
443 |
-
* @expectedExceptionMessage Property name must be a string, NULL given
|
444 |
-
*/
|
445 |
-
public function testRemoveAllPropertiesWithInvalidPropertyName()
|
446 |
-
{
|
447 |
-
$element = new Element('div', null, [
|
448 |
-
'style' => 'color: blue; border: 1px solid black',
|
449 |
-
]);
|
450 |
-
|
451 |
-
$styleAttribute = new StyleAttribute($element);
|
452 |
-
|
453 |
-
$styleAttribute->removeAllProperties(['color', null]);
|
454 |
-
}
|
455 |
-
|
456 |
-
/**
|
457 |
-
* @param string $styleString
|
458 |
-
* @param array $exclusions
|
459 |
-
* @param string $expectedResult
|
460 |
-
*
|
461 |
-
* @dataProvider removeAllPropertiesDataProvider
|
462 |
-
*/
|
463 |
-
public function testRemoveAllProperties($styleString, $exclusions, $expectedResult)
|
464 |
-
{
|
465 |
-
$element = new Element('div', null, [
|
466 |
-
'style' => $styleString,
|
467 |
-
]);
|
468 |
-
|
469 |
-
$styleAttribute = new StyleAttribute($element);
|
470 |
-
|
471 |
-
$this->assertEquals($styleString, $element->getAttribute('style'));
|
472 |
-
|
473 |
-
$styleAttribute->removeAllProperties($exclusions);
|
474 |
-
|
475 |
-
$this->assertEquals($expectedResult, $element->getAttribute('style'));
|
476 |
-
}
|
477 |
-
|
478 |
-
public function removeAllPropertiesDataProvider()
|
479 |
-
{
|
480 |
-
return [
|
481 |
-
[
|
482 |
-
'color: blue; font-size: 16px; font-family: Times; border: 1px solid black',
|
483 |
-
[
|
484 |
-
'font-size',
|
485 |
-
],
|
486 |
-
'font-size: 16px',
|
487 |
-
],
|
488 |
-
[
|
489 |
-
'color: blue; font-size: 16px; font-family: Times; border: 1px solid black',
|
490 |
-
[
|
491 |
-
'font-size', 'border',
|
492 |
-
],
|
493 |
-
'font-size: 16px; border: 1px solid black',
|
494 |
-
],
|
495 |
-
[
|
496 |
-
'color: blue; font-size: 16px; font-family: Times; border: 1px solid black',
|
497 |
-
[
|
498 |
-
'font-size', 'border', 'width',
|
499 |
-
],
|
500 |
-
'font-size: 16px; border: 1px solid black',
|
501 |
-
],
|
502 |
-
];
|
503 |
-
}
|
504 |
-
|
505 |
-
public function testGetElement()
|
506 |
-
{
|
507 |
-
$element = new Element('div', null, [
|
508 |
-
'style' => 'color: blue; font-size: 16px',
|
509 |
-
]);
|
510 |
-
|
511 |
-
$styleAttribute = new StyleAttribute($element);
|
512 |
-
|
513 |
-
$this->assertSame($element, $styleAttribute->getElement());
|
514 |
-
}
|
515 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/imangazaliev/didom/tests/TestCase.php
DELETED
@@ -1,40 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace Tests;
|
4 |
-
|
5 |
-
use PHPUnit_Framework_TestCase;
|
6 |
-
use DOMDocument;
|
7 |
-
use Exception;
|
8 |
-
|
9 |
-
class TestCase extends PHPUnit_Framework_TestCase
|
10 |
-
{
|
11 |
-
protected function tearDown()
|
12 |
-
{
|
13 |
-
if (class_exists('Mockery')) {
|
14 |
-
\Mockery::close();
|
15 |
-
}
|
16 |
-
}
|
17 |
-
|
18 |
-
protected function loadFixture($filename)
|
19 |
-
{
|
20 |
-
$path = __DIR__.'/fixtures/'.$filename;
|
21 |
-
|
22 |
-
if (file_exists($path)) {
|
23 |
-
return file_get_contents($path);
|
24 |
-
}
|
25 |
-
|
26 |
-
throw new Exception(sprintf('Fixture "%s" does not exist', $filename));
|
27 |
-
}
|
28 |
-
|
29 |
-
protected function createDomElement($name, $value = null, $attributes = [])
|
30 |
-
{
|
31 |
-
$document = new DOMDocument('1.0', 'UTF-8');
|
32 |
-
$node = $document->createElement($name, $value);
|
33 |
-
|
34 |
-
foreach ($attributes as $name => $value) {
|
35 |
-
$node->setAttribute($name, $value);
|
36 |
-
}
|
37 |
-
|
38 |
-
return $node;
|
39 |
-
}
|
40 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/imangazaliev/didom/tests/bootstrap.php
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
ini_set('error_reporting', E_ALL);
|
4 |
-
ini_set('display_errors', 1);
|
5 |
-
ini_set('display_startup_errors', 1);
|
6 |
-
|
7 |
-
require __DIR__.'/../vendor/autoload.php';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/imangazaliev/didom/tests/fixtures/books.xml
DELETED
@@ -1,120 +0,0 @@
|
|
1 |
-
<?xml version="1.0" encoding="utf-8"?>
|
2 |
-
<catalog>
|
3 |
-
<book id="bk101">
|
4 |
-
<author>Gambardella, Matthew</author>
|
5 |
-
<title>XML Developer's Guide</title>
|
6 |
-
<genre>Computer</genre>
|
7 |
-
<price>44.95</price>
|
8 |
-
<publish_date>2000-10-01</publish_date>
|
9 |
-
<description>An in-depth look at creating applications
|
10 |
-
with XML.</description>
|
11 |
-
</book>
|
12 |
-
<book id="bk102">
|
13 |
-
<author>Ralls, Kim</author>
|
14 |
-
<title>Midnight Rain</title>
|
15 |
-
<genre>Fantasy</genre>
|
16 |
-
<price>5.95</price>
|
17 |
-
<publish_date>2000-12-16</publish_date>
|
18 |
-
<description>A former architect battles corporate zombies,
|
19 |
-
an evil sorceress, and her own childhood to become queen
|
20 |
-
of the world.</description>
|
21 |
-
</book>
|
22 |
-
<book id="bk103">
|
23 |
-
<author>Corets, Eva</author>
|
24 |
-
<title>Maeve Ascendant</title>
|
25 |
-
<genre>Fantasy</genre>
|
26 |
-
<price>5.95</price>
|
27 |
-
<publish_date>2000-11-17</publish_date>
|
28 |
-
<description>After the collapse of a nanotechnology
|
29 |
-
society in England, the young survivors lay the
|
30 |
-
foundation for a new society.</description>
|
31 |
-
</book>
|
32 |
-
<book id="bk104">
|
33 |
-
<author>Corets, Eva</author>
|
34 |
-
<title>Oberon's Legacy</title>
|
35 |
-
<genre>Fantasy</genre>
|
36 |
-
<price>5.95</price>
|
37 |
-
<publish_date>2001-03-10</publish_date>
|
38 |
-
<description>In post-apocalypse England, the mysterious
|
39 |
-
agent known only as Oberon helps to create a new life
|
40 |
-
for the inhabitants of London. Sequel to Maeve
|
41 |
-
Ascendant.</description>
|
42 |
-
</book>
|
43 |
-
<book id="bk105">
|
44 |
-
<author>Corets, Eva</author>
|
45 |
-
<title>The Sundered Grail</title>
|
46 |
-
<genre>Fantasy</genre>
|
47 |
-
<price>5.95</price>
|
48 |
-
<publish_date>2001-09-10</publish_date>
|
49 |
-
<description>The two daughters of Maeve, half-sisters,
|
50 |
-
battle one another for control of England. Sequel to
|
51 |
-
Oberon's Legacy.</description>
|
52 |
-
</book>
|
53 |
-
<book id="bk106">
|
54 |
-
<author>Randall, Cynthia</author>
|
55 |
-
<title>Lover Birds</title>
|
56 |
-
<genre>Romance</genre>
|
57 |
-
<price>4.95</price>
|
58 |
-
<publish_date>2000-09-02</publish_date>
|
59 |
-
<description>When Carla meets Paul at an ornithology
|
60 |
-
conference, tempers fly as feathers get ruffled.</description>
|
61 |
-
</book>
|
62 |
-
<book id="bk107">
|
63 |
-
<author>Thurman, Paula</author>
|
64 |
-
<title>Splish Splash</title>
|
65 |
-
<genre>Romance</genre>
|
66 |
-
<price>4.95</price>
|
67 |
-
<publish_date>2000-11-02</publish_date>
|
68 |
-
<description>A deep sea diver finds true love twenty
|
69 |
-
thousand leagues beneath the sea.</description>
|
70 |
-
</book>
|
71 |
-
<book id="bk108">
|
72 |
-
<author>Knorr, Stefan</author>
|
73 |
-
<title>Creepy Crawlies</title>
|
74 |
-
<genre>Horror</genre>
|
75 |
-
<price>4.95</price>
|
76 |
-
<publish_date>2000-12-06</publish_date>
|
77 |
-
<description>An anthology of horror stories about roaches,
|
78 |
-
centipedes, scorpions and other insects.</description>
|
79 |
-
</book>
|
80 |
-
<book id="bk109">
|
81 |
-
<author>Kress, Peter</author>
|
82 |
-
<title>Paradox Lost</title>
|
83 |
-
<genre>Science Fiction</genre>
|
84 |
-
<price>6.95</price>
|
85 |
-
<publish_date>2000-11-02</publish_date>
|
86 |
-
<description>After an inadvertant trip through a Heisenberg
|
87 |
-
Uncertainty Device, James Salway discovers the problems
|
88 |
-
of being quantum.</description>
|
89 |
-
</book>
|
90 |
-
<book id="bk110">
|
91 |
-
<author>O'Brien, Tim</author>
|
92 |
-
<title>Microsoft .NET: The Programming Bible</title>
|
93 |
-
<genre>Computer</genre>
|
94 |
-
<price>36.95</price>
|
95 |
-
<publish_date>2000-12-09</publish_date>
|
96 |
-
<description>Microsoft's .NET initiative is explored in
|
97 |
-
detail in this deep programmer's reference.</description>
|
98 |
-
</book>
|
99 |
-
<book id="bk111">
|
100 |
-
<author>O'Brien, Tim</author>
|
101 |
-
<title>MSXML3: A Comprehensive Guide</title>
|
102 |
-
<genre>Computer</genre>
|
103 |
-
<price>36.95</price>
|
104 |
-
<publish_date>2000-12-01</publish_date>
|
105 |
-
<description>The Microsoft MSXML3 parser is covered in
|
106 |
-
detail, with attention to XML DOM interfaces, XSLT processing,
|
107 |
-
SAX and more.</description>
|
108 |
-
</book>
|
109 |
-
<book id="bk112">
|
110 |
-
<author>Galos, Mike</author>
|
111 |
-
<title>Visual Studio 7: A Comprehensive Guide</title>
|
112 |
-
<genre>Computer</genre>
|
113 |
-
<price>49.95</price>
|
114 |
-
<publish_date>2001-04-16</publish_date>
|
115 |
-
<description>Microsoft Visual Studio 7 is explored in depth,
|
116 |
-
looking at how Visual Basic, Visual C++, C#, and ASP+ are
|
117 |
-
integrated into a comprehensive development
|
118 |
-
environment.</description>
|
119 |
-
</book>
|
120 |
-
</catalog>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/imangazaliev/didom/tests/fixtures/menu.html
DELETED
@@ -1,15 +0,0 @@
|
|
1 |
-
<!DOCTYPE html>
|
2 |
-
<html lang="en">
|
3 |
-
<head>
|
4 |
-
<meta charset="UTF-8">
|
5 |
-
<title>Document</title>
|
6 |
-
</head>
|
7 |
-
<body>
|
8 |
-
<ul>
|
9 |
-
<li><a href="http://example.com">Link 1</a></li>
|
10 |
-
<li><a href="http://example.com">Link 2<!--- Comment 1 ---></a></li>
|
11 |
-
<li><a href="http://example.com">Link 3<!--- Comment 2 ---></a></li>
|
12 |
-
</ul>
|
13 |
-
<!--- Comment --->
|
14 |
-
</body>
|
15 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/imangazaliev/didom/tests/fixtures/posts.html
DELETED
@@ -1,25 +0,0 @@
|
|
1 |
-
<!DOCTYPE html>
|
2 |
-
<html lang="en">
|
3 |
-
<head>
|
4 |
-
<meta charset="UTF-8">
|
5 |
-
<title>Posts</title>
|
6 |
-
</head>
|
7 |
-
<body>
|
8 |
-
<h1 class="title">Posts</h1>
|
9 |
-
|
10 |
-
<div class="posts">
|
11 |
-
<div class="post">
|
12 |
-
<h2 class="title">Lorem ipsum dolor sit amet.</h2>
|
13 |
-
<p class="body">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore autem, in accusamus doloremque temporibus dolorem.</p>
|
14 |
-
</div>
|
15 |
-
<div class="post">
|
16 |
-
<h2 class="title">Distinctio nisi ab in facere.</h2>
|
17 |
-
<p class="body">Possimus adipisci atque voluptate non, voluptatum quam, saepe architecto repellat eum quaerat sed nam, quos.</p>
|
18 |
-
</div>
|
19 |
-
<div class="post">
|
20 |
-
<h2 class="title">Consequatur eligendi praesentium voluptatem incidunt.</h2>
|
21 |
-
<p class="body">Ad magnam optio maxime cupiditate eos eum. Perferendis voluptatum atque et nobis, facilis iusto! Ipsam.</p>
|
22 |
-
</div>
|
23 |
-
</div>
|
24 |
-
</body>
|
25 |
-
</html>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/kub-at/php-simple-html-dom-parser/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
php-simple-html-dom-parser
|
2 |
==========================
|
3 |
|
4 |
-
Version 1.
|
5 |
-
PHP Simple HTML DOM Parser changelog: https://sourceforge.net/projects/simplehtmldom/files/simplehtmldom/1.
|
6 |
|
7 |
|
8 |
Install
|
1 |
php-simple-html-dom-parser
|
2 |
==========================
|
3 |
|
4 |
+
Version 1.9.1 - PHP 7.3 compatible
|
5 |
+
PHP Simple HTML DOM Parser changelog: https://sourceforge.net/projects/simplehtmldom/files/simplehtmldom/1.9.1/
|
6 |
|
7 |
|
8 |
Install
|
vendor/kub-at/php-simple-html-dom-parser/src/KubAT/PhpSimple/lib/simple_html_dom.php
CHANGED
@@ -5,64 +5,24 @@ namespace simple_html_dom;
|
|
5 |
* Website: http://sourceforge.net/projects/simplehtmldom/
|
6 |
* Additional projects: http://sourceforge.net/projects/debugobject/
|
7 |
* Acknowledge: Jose Solorzano (https://sourceforge.net/projects/php-html/)
|
8 |
-
* Contributions by:
|
9 |
-
* Yousuke Kumakura (Attribute filters)
|
10 |
-
* Vadim Voituk (Negative indexes supports of "find" method)
|
11 |
-
* Antcs (Constructor with automatically load contents either text or file/url)
|
12 |
*
|
13 |
-
*
|
14 |
-
*
|
15 |
-
* Paperg - Added case insensitive testing of the value of the selector.
|
16 |
-
*
|
17 |
-
* Paperg - Added tag_start for the starting index of tags - NOTE: This works
|
18 |
-
* but not accurately. This tag_start gets counted AFTER \r\n have been crushed
|
19 |
-
* out, and after the remove_noice calls so it will not reflect the REAL
|
20 |
-
* position of the tag in the source, it will almost always be smaller by some
|
21 |
-
* amount. We use this to determine how far into the file the tag in question
|
22 |
-
* is. This "percentage" will never be accurate as the $dom->size is the "real"
|
23 |
-
* number of bytes the dom was created from. But for most purposes, it's a
|
24 |
-
* really good estimation.
|
25 |
-
*
|
26 |
-
* Paperg - Added the forceTagsClosed to the dom constructor. Forcing tags
|
27 |
-
* closed is great for malformed html, but it CAN lead to parsing errors.
|
28 |
-
*
|
29 |
-
* Allow the user to tell us how much they trust the html.
|
30 |
-
*
|
31 |
-
* Paperg add the text and plaintext to the selectors for the find syntax.
|
32 |
-
* plaintext implies text in the innertext of a node. text implies that the
|
33 |
-
* tag is a text node. This allows for us to find tags based on the text they
|
34 |
-
* contain.
|
35 |
-
*
|
36 |
-
* Create find_ancestor_tag to see if a tag is - at any level - inside of
|
37 |
-
* another specific tag.
|
38 |
-
*
|
39 |
-
* Paperg: added parse_charset so that we know about the character set of
|
40 |
-
* the source document. NOTE: If the user's system has a routine called
|
41 |
-
* get_last_retrieve_url_contents_content_type availalbe, we will assume it's
|
42 |
-
* returning the content-type header from the last transfer or curl_exec, and
|
43 |
-
* we will parse that and use it in preference to any other method of charset
|
44 |
-
* detection.
|
45 |
-
*
|
46 |
-
* Found infinite loop in the case of broken html in restore_noise. Rewrote to
|
47 |
-
* protect from that.
|
48 |
*
|
49 |
-
*
|
|
|
|
|
|
|
|
|
50 |
*
|
51 |
-
*
|
52 |
-
*
|
|
|
|
|
53 |
*
|
54 |
-
*
|
55 |
-
* @author John Schlick
|
56 |
-
* @author Rus Carroll
|
57 |
-
* @version Rev. 1.8.1 (247)
|
58 |
-
* @package PlaceLocalInclude
|
59 |
-
* @subpackage simple_html_dom
|
60 |
*/
|
61 |
|
62 |
-
/**
|
63 |
-
* All of the Defines for the classes below.
|
64 |
-
* @author S.C. Chen <me578022@gmail.com>
|
65 |
-
*/
|
66 |
define('HDOM_TYPE_ELEMENT', 1);
|
67 |
define('HDOM_TYPE_COMMENT', 2);
|
68 |
define('HDOM_TYPE_TEXT', 3);
|
@@ -81,25 +41,12 @@ define('HDOM_INFO_INNER', 5);
|
|
81 |
define('HDOM_INFO_OUTER', 6);
|
82 |
define('HDOM_INFO_ENDSPACE', 7);
|
83 |
|
84 |
-
/** The default target charset */
|
85 |
defined('DEFAULT_TARGET_CHARSET') || define('DEFAULT_TARGET_CHARSET', 'UTF-8');
|
86 |
-
|
87 |
-
/** The default <br> text used instead of <br> tags when returning text */
|
88 |
defined('DEFAULT_BR_TEXT') || define('DEFAULT_BR_TEXT', "\r\n");
|
89 |
-
|
90 |
-
/** The default <span> text used instead of <span> tags when returning text */
|
91 |
defined('DEFAULT_SPAN_TEXT') || define('DEFAULT_SPAN_TEXT', ' ');
|
92 |
-
|
93 |
-
/** The maximum file size the parser should load */
|
94 |
defined('MAX_FILE_SIZE') || define('MAX_FILE_SIZE', 600000);
|
95 |
-
|
96 |
-
/** Contents between curly braces "{" and "}" are interpreted as text */
|
97 |
define('HDOM_SMARTY_AS_TEXT', 1);
|
98 |
|
99 |
-
// helper functions
|
100 |
-
// -----------------------------------------------------------------------------
|
101 |
-
// get html dom from file
|
102 |
-
// $maxlen is defined in the code as PHP_STREAM_COPY_ALL which is defined as -1.
|
103 |
function file_get_html(
|
104 |
$url,
|
105 |
$use_include_path = false,
|
@@ -113,10 +60,8 @@ function file_get_html(
|
|
113 |
$defaultBRText = DEFAULT_BR_TEXT,
|
114 |
$defaultSpanText = DEFAULT_SPAN_TEXT)
|
115 |
{
|
116 |
-
// Ensure maximum length is greater than zero
|
117 |
if($maxLen <= 0) { $maxLen = MAX_FILE_SIZE; }
|
118 |
|
119 |
-
// We DO force the tags to be terminated.
|
120 |
$dom = new simple_html_dom(
|
121 |
null,
|
122 |
$lowercase,
|
@@ -124,7 +69,8 @@ function file_get_html(
|
|
124 |
$target_charset,
|
125 |
$stripRN,
|
126 |
$defaultBRText,
|
127 |
-
$defaultSpanText
|
|
|
128 |
|
129 |
/**
|
130 |
* For sourceforge users: uncomment the next line and comment the
|
@@ -135,19 +81,18 @@ function file_get_html(
|
|
135 |
$use_include_path,
|
136 |
$context,
|
137 |
$offset,
|
138 |
-
$maxLen
|
139 |
-
|
140 |
-
// Paperg - use our own mechanism for getting the contents as we want to
|
141 |
-
// control the timeout.
|
142 |
// $contents = retrieve_url_contents($url);
|
143 |
-
if (empty($contents) || strlen($contents) > $maxLen) { return false; }
|
144 |
|
145 |
-
|
146 |
-
|
147 |
-
|
|
|
|
|
|
|
148 |
}
|
149 |
|
150 |
-
// get html dom from string
|
151 |
function str_get_html(
|
152 |
$str,
|
153 |
$lowercase = true,
|
@@ -164,97 +109,34 @@ function str_get_html(
|
|
164 |
$target_charset,
|
165 |
$stripRN,
|
166 |
$defaultBRText,
|
167 |
-
$defaultSpanText
|
|
|
168 |
|
169 |
if (empty($str) || strlen($str) > MAX_FILE_SIZE) {
|
170 |
$dom->clear();
|
171 |
return false;
|
172 |
}
|
173 |
|
174 |
-
$dom->load($str, $lowercase, $stripRN);
|
175 |
-
return $dom;
|
176 |
}
|
177 |
|
178 |
-
// dump html dom tree
|
179 |
function dump_html_tree($node, $show_attr = true, $deep = 0)
|
180 |
{
|
181 |
$node->dump($node);
|
182 |
}
|
183 |
|
184 |
-
/**
|
185 |
-
* simple html dom node
|
186 |
-
* PaperG - added ability for "find" routine to lowercase the value of the
|
187 |
-
* selector.
|
188 |
-
*
|
189 |
-
* PaperG - added $tag_start to track the start position of the tag in the total
|
190 |
-
* byte index
|
191 |
-
*
|
192 |
-
* @package PlaceLocalInclude
|
193 |
-
*/
|
194 |
class simple_html_dom_node
|
195 |
{
|
196 |
-
/**
|
197 |
-
* Node type
|
198 |
-
*
|
199 |
-
* Default is {@see HDOM_TYPE_TEXT}
|
200 |
-
*
|
201 |
-
* @var int
|
202 |
-
*/
|
203 |
public $nodetype = HDOM_TYPE_TEXT;
|
204 |
-
|
205 |
-
/**
|
206 |
-
* Tag name
|
207 |
-
*
|
208 |
-
* Default is 'text'
|
209 |
-
*
|
210 |
-
* @var string
|
211 |
-
*/
|
212 |
public $tag = 'text';
|
213 |
-
|
214 |
-
/**
|
215 |
-
* List of attributes
|
216 |
-
*
|
217 |
-
* @var array
|
218 |
-
*/
|
219 |
public $attr = array();
|
220 |
-
|
221 |
-
/**
|
222 |
-
* List of child node objects
|
223 |
-
*
|
224 |
-
* @var array
|
225 |
-
*/
|
226 |
public $children = array();
|
227 |
public $nodes = array();
|
228 |
-
|
229 |
-
/**
|
230 |
-
* The parent node object
|
231 |
-
*
|
232 |
-
* @var object|null
|
233 |
-
*/
|
234 |
public $parent = null;
|
235 |
-
|
236 |
-
// The "info" array - see HDOM_INFO_... for what each element contains.
|
237 |
public $_ = array();
|
238 |
-
|
239 |
-
/**
|
240 |
-
* Start position of the tag in the document
|
241 |
-
*
|
242 |
-
* @var int
|
243 |
-
*/
|
244 |
public $tag_start = 0;
|
245 |
-
|
246 |
-
/**
|
247 |
-
* The DOM object
|
248 |
-
*
|
249 |
-
* @var object|null
|
250 |
-
*/
|
251 |
private $dom = null;
|
252 |
|
253 |
-
/**
|
254 |
-
* Construct new node object
|
255 |
-
*
|
256 |
-
* Adds itself to the list of DOM Nodes {@see simple_html_dom::$nodes}
|
257 |
-
*/
|
258 |
function __construct($dom)
|
259 |
{
|
260 |
$this->dom = $dom;
|
@@ -271,7 +153,6 @@ class simple_html_dom_node
|
|
271 |
return $this->outertext();
|
272 |
}
|
273 |
|
274 |
-
// clean up memory due to php5 circular references memory leak...
|
275 |
function clear()
|
276 |
{
|
277 |
$this->dom = null;
|
@@ -280,17 +161,14 @@ class simple_html_dom_node
|
|
280 |
$this->children = null;
|
281 |
}
|
282 |
|
283 |
-
|
284 |
-
function dump($show_attr = true, $deep = 0)
|
285 |
{
|
286 |
-
|
287 |
-
|
288 |
-
echo $lead . $this->tag;
|
289 |
|
290 |
if ($show_attr && count($this->attr) > 0) {
|
291 |
echo '(';
|
292 |
foreach ($this->attr as $k => $v) {
|
293 |
-
echo "[$k]=>\"
|
294 |
}
|
295 |
echo ')';
|
296 |
}
|
@@ -298,14 +176,12 @@ class simple_html_dom_node
|
|
298 |
echo "\n";
|
299 |
|
300 |
if ($this->nodes) {
|
301 |
-
foreach ($this->nodes as $
|
302 |
-
$
|
303 |
}
|
304 |
}
|
305 |
}
|
306 |
|
307 |
-
|
308 |
-
// Debugging function to dump a single dom node with a bunch of information about it.
|
309 |
function dump_node($echo = true)
|
310 |
{
|
311 |
$string = $this->tag;
|
@@ -313,7 +189,7 @@ class simple_html_dom_node
|
|
313 |
if (count($this->attr) > 0) {
|
314 |
$string .= '(';
|
315 |
foreach ($this->attr as $k => $v) {
|
316 |
-
$string .= "[$k]=>\"
|
317 |
}
|
318 |
$string .= ')';
|
319 |
}
|
@@ -324,24 +200,24 @@ class simple_html_dom_node
|
|
324 |
if (is_array($v)) {
|
325 |
$string .= "[$k]=>(";
|
326 |
foreach ($v as $k2 => $v2) {
|
327 |
-
$string .= "[$k2]=>\"
|
328 |
}
|
329 |
$string .= ')';
|
330 |
} else {
|
331 |
-
$string .= "[$k]=>\"
|
332 |
}
|
333 |
}
|
334 |
$string .= ')';
|
335 |
}
|
336 |
|
337 |
if (isset($this->text)) {
|
338 |
-
$string .=
|
339 |
}
|
340 |
|
341 |
-
$string .=
|
342 |
|
343 |
if (isset($node->_[HDOM_INFO_INNER])) {
|
344 |
-
$string .= $node->_[HDOM_INFO_INNER] . "'";
|
345 |
} else {
|
346 |
$string .= ' NULL ';
|
347 |
}
|
@@ -359,13 +235,6 @@ class simple_html_dom_node
|
|
359 |
}
|
360 |
}
|
361 |
|
362 |
-
/**
|
363 |
-
* Return or set parent node
|
364 |
-
*
|
365 |
-
* @param object|null $parent (optional) The parent node, `null` to return
|
366 |
-
* the current parent node.
|
367 |
-
* @return object|null The parent node
|
368 |
-
*/
|
369 |
function parent($parent = null)
|
370 |
{
|
371 |
// I am SURE that this doesn't work properly.
|
@@ -380,22 +249,11 @@ class simple_html_dom_node
|
|
380 |
return $this->parent;
|
381 |
}
|
382 |
|
383 |
-
/**
|
384 |
-
* @return bool True if the node has at least one child node
|
385 |
-
*/
|
386 |
function has_child()
|
387 |
{
|
388 |
return !empty($this->children);
|
389 |
}
|
390 |
|
391 |
-
/**
|
392 |
-
* Get child node at specified index
|
393 |
-
*
|
394 |
-
* @param int $idx The index of the child node to return, `-1` to return all
|
395 |
-
* child nodes.
|
396 |
-
* @return object|array|null The child node at the specified index, all child
|
397 |
-
* nodes or null if the index is invalid.
|
398 |
-
*/
|
399 |
function children($idx = -1)
|
400 |
{
|
401 |
if ($idx === -1) {
|
@@ -409,15 +267,6 @@ class simple_html_dom_node
|
|
409 |
return null;
|
410 |
}
|
411 |
|
412 |
-
/**
|
413 |
-
* Get first child node
|
414 |
-
*
|
415 |
-
* @return object|null The first child node or null if the current node has
|
416 |
-
* no child nodes.
|
417 |
-
*
|
418 |
-
* @todo Use `empty()` instead of `count()` to improve performance on large
|
419 |
-
* arrays.
|
420 |
-
*/
|
421 |
function first_child()
|
422 |
{
|
423 |
if (count($this->children) > 0) {
|
@@ -426,108 +275,70 @@ class simple_html_dom_node
|
|
426 |
return null;
|
427 |
}
|
428 |
|
429 |
-
/**
|
430 |
-
* Get last child node
|
431 |
-
*
|
432 |
-
* @return object|null The last child node or null if the current node has
|
433 |
-
* no child nodes.
|
434 |
-
*
|
435 |
-
* @todo Use `end()` to slightly improve performance on large arrays.
|
436 |
-
*/
|
437 |
function last_child()
|
438 |
{
|
439 |
-
if (
|
440 |
-
return $this->children
|
441 |
}
|
442 |
return null;
|
443 |
}
|
444 |
|
445 |
-
/**
|
446 |
-
* Get next sibling node
|
447 |
-
*
|
448 |
-
* @return object|null The sibling node or null if the current node has no
|
449 |
-
* sibling nodes.
|
450 |
-
*/
|
451 |
function next_sibling()
|
452 |
{
|
453 |
if ($this->parent === null) {
|
454 |
return null;
|
455 |
}
|
456 |
|
457 |
-
$idx =
|
458 |
-
$count = count($this->parent->children);
|
459 |
|
460 |
-
|
461 |
-
|
462 |
}
|
463 |
|
464 |
-
|
465 |
-
return null;
|
466 |
-
}
|
467 |
-
|
468 |
-
return $this->parent->children[$idx];
|
469 |
}
|
470 |
|
471 |
-
/**
|
472 |
-
* Get previous sibling node
|
473 |
-
*
|
474 |
-
* @return object|null The sibling node or null if the current node has no
|
475 |
-
* sibling nodes.
|
476 |
-
*/
|
477 |
function prev_sibling()
|
478 |
{
|
479 |
-
if ($this->parent === null) {
|
|
|
|
|
480 |
|
481 |
-
$idx =
|
482 |
-
$count = count($this->parent->children);
|
483 |
|
484 |
-
|
485 |
-
|
486 |
}
|
487 |
|
488 |
-
|
489 |
-
|
490 |
-
return $this->parent->children[$idx];
|
491 |
}
|
492 |
|
493 |
-
/**
|
494 |
-
* Traverse ancestors to the first matching tag.
|
495 |
-
*
|
496 |
-
* @param string $tag Tag to find
|
497 |
-
* @return object|null First matching node in the DOM tree or null if no
|
498 |
-
* match was found.
|
499 |
-
*
|
500 |
-
* @todo Null is returned implicitly by calling ->parent on the root node.
|
501 |
-
* This behaviour could change at any time, rendering this function invalid.
|
502 |
-
*/
|
503 |
function find_ancestor_tag($tag)
|
504 |
{
|
505 |
global $debug_object;
|
506 |
if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
|
507 |
|
508 |
-
|
509 |
-
|
|
|
510 |
|
511 |
-
|
|
|
|
|
512 |
if (is_object($debug_object)) {
|
513 |
-
$debug_object->debug_log(2, 'Current tag is: ' . $
|
514 |
}
|
515 |
|
516 |
-
if ($
|
517 |
break;
|
518 |
}
|
519 |
|
520 |
-
$
|
521 |
}
|
522 |
|
523 |
-
return $
|
524 |
}
|
525 |
|
526 |
-
/**
|
527 |
-
* Get node's inner text (everything inside the opening and closing tags)
|
528 |
-
*
|
529 |
-
* @return string
|
530 |
-
*/
|
531 |
function innertext()
|
532 |
{
|
533 |
if (isset($this->_[HDOM_INFO_INNER])) {
|
@@ -547,11 +358,6 @@ class simple_html_dom_node
|
|
547 |
return $ret;
|
548 |
}
|
549 |
|
550 |
-
/**
|
551 |
-
* Get node's outer text (everything including the opening and closing tags)
|
552 |
-
*
|
553 |
-
* @return string
|
554 |
-
*/
|
555 |
function outertext()
|
556 |
{
|
557 |
global $debug_object;
|
@@ -568,9 +374,11 @@ class simple_html_dom_node
|
|
568 |
$debug_object->debug_log(1, 'Innertext of tag: ' . $this->tag . $text);
|
569 |
}
|
570 |
|
571 |
-
if ($this->tag === 'root')
|
|
|
|
|
572 |
|
573 |
-
//
|
574 |
if ($this->dom && $this->dom->callback !== null) {
|
575 |
call_user_func_array($this->dom->callback, array($this));
|
576 |
}
|
@@ -583,29 +391,23 @@ class simple_html_dom_node
|
|
583 |
return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
|
584 |
}
|
585 |
|
586 |
-
|
|
|
587 |
if ($this->dom && $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]) {
|
588 |
$ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup();
|
589 |
-
} else {
|
590 |
-
$ret = '';
|
591 |
}
|
592 |
|
593 |
-
// render inner text
|
594 |
if (isset($this->_[HDOM_INFO_INNER])) {
|
595 |
-
//
|
596 |
-
// may or may not have added.
|
597 |
if ($this->tag !== 'br') {
|
598 |
$ret .= $this->_[HDOM_INFO_INNER];
|
599 |
}
|
600 |
-
}
|
601 |
-
|
602 |
-
|
603 |
-
$ret .= $this->convert_text($n->outertext());
|
604 |
-
}
|
605 |
}
|
606 |
}
|
607 |
|
608 |
-
// render end tag
|
609 |
if (isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END] != 0) {
|
610 |
$ret .= '</' . $this->tag . '>';
|
611 |
}
|
@@ -613,11 +415,6 @@ class simple_html_dom_node
|
|
613 |
return $ret;
|
614 |
}
|
615 |
|
616 |
-
/**
|
617 |
-
* Get node's plain text (everything excluding all tags)
|
618 |
-
*
|
619 |
-
* @return string
|
620 |
-
*/
|
621 |
function text()
|
622 |
{
|
623 |
if (isset($this->_[HDOM_INFO_INNER])) {
|
@@ -644,7 +441,7 @@ class simple_html_dom_node
|
|
644 |
foreach ($this->nodes as $n) {
|
645 |
// Start paragraph after a blank line
|
646 |
if ($n->tag === 'p') {
|
647 |
-
$ret
|
648 |
}
|
649 |
|
650 |
$ret .= $this->convert_text($n->text());
|
@@ -657,14 +454,9 @@ class simple_html_dom_node
|
|
657 |
}
|
658 |
}
|
659 |
}
|
660 |
-
return
|
661 |
}
|
662 |
|
663 |
-
/**
|
664 |
-
* Get node's xml text (inner text as a CDATA section)
|
665 |
-
*
|
666 |
-
* @return string
|
667 |
-
*/
|
668 |
function xmltext()
|
669 |
{
|
670 |
$ret = $this->innertext();
|
@@ -673,7 +465,6 @@ class simple_html_dom_node
|
|
673 |
return $ret;
|
674 |
}
|
675 |
|
676 |
-
// build node's text with tag
|
677 |
function makeup()
|
678 |
{
|
679 |
// text, comment, unknown
|
@@ -717,18 +508,6 @@ class simple_html_dom_node
|
|
717 |
return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>';
|
718 |
}
|
719 |
|
720 |
-
/**
|
721 |
-
* Find elements by CSS selector
|
722 |
-
*
|
723 |
-
* @param string $selector The CSS selector
|
724 |
-
* @param int|null $idx Index of element to return form the list of matching
|
725 |
-
* elements (default: `null` = disabled).
|
726 |
-
* @param bool $lowercase Matches tag names case insensitive (lowercase) if
|
727 |
-
* enabled (default: `false`)
|
728 |
-
* @return array|object|null A list of elements matching the specified CSS
|
729 |
-
* selector or a single element if $idx is specified or null if no element
|
730 |
-
* was found.
|
731 |
-
*/
|
732 |
function find($selector, $idx = null, $lowercase = false)
|
733 |
{
|
734 |
$selectors = $this->parse_selector($selector);
|
@@ -781,19 +560,6 @@ class simple_html_dom_node
|
|
781 |
return (isset($found[$idx])) ? $found[$idx] : null;
|
782 |
}
|
783 |
|
784 |
-
/**
|
785 |
-
* Seek DOM elements by selector
|
786 |
-
*
|
787 |
-
* **Note**
|
788 |
-
* The selector element must be compatible to a selector from
|
789 |
-
* {@see simple_html_dom_node::parse_selector()}
|
790 |
-
*
|
791 |
-
* @param array $selector A selector element
|
792 |
-
* @param array $ret An array of matches
|
793 |
-
* @param bool $lowercase Matches tag names case insensitive (lowercase) if
|
794 |
-
* enabled (default: `false`)
|
795 |
-
* @return void
|
796 |
-
*/
|
797 |
protected function seek($selector, &$ret, $parent_cmd, $lowercase = false)
|
798 |
{
|
799 |
global $debug_object;
|
@@ -825,7 +591,8 @@ class simple_html_dom_node
|
|
825 |
&& $this->parent
|
826 |
&& in_array($this, $this->parent->children)) { // Next-Sibling Combinator
|
827 |
$index = array_search($this, $this->parent->children, true) + 1;
|
828 |
-
$
|
|
|
829 |
} elseif ($parent_cmd === '~'
|
830 |
&& $this->parent
|
831 |
&& in_array($this, $this->parent->children)) { // Subsequent Sibling Combinator
|
@@ -844,6 +611,13 @@ class simple_html_dom_node
|
|
844 |
$pass = false;
|
845 |
}
|
846 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
847 |
// Skip if node isn't a child node (i.e. text nodes)
|
848 |
if($pass && !in_array($node, $node->parent->children, true)) {
|
849 |
$pass = false;
|
@@ -1008,24 +782,6 @@ class simple_html_dom_node
|
|
1008 |
}
|
1009 |
}
|
1010 |
|
1011 |
-
/**
|
1012 |
-
* Match value and pattern for a given CSS expression
|
1013 |
-
*
|
1014 |
-
* **Supported Expressions**
|
1015 |
-
*
|
1016 |
-
* | Expression | Description
|
1017 |
-
* | ---------- | -----------
|
1018 |
-
* | `=` | $value and $pattern must be equal
|
1019 |
-
* | `!=` | $value and $pattern must not be equal
|
1020 |
-
* | `^=` | $value must start with $pattern
|
1021 |
-
* | `$=` | $value must end with $pattern
|
1022 |
-
* | `*=` | $value must contain $pattern
|
1023 |
-
*
|
1024 |
-
* @param string $exp The expression.
|
1025 |
-
* @param string $pattern The pattern
|
1026 |
-
* @param string $value The value
|
1027 |
-
* @value bool True if $value matches $pattern
|
1028 |
-
*/
|
1029 |
protected function match($exp, $pattern, $value, $case_sensitivity)
|
1030 |
{
|
1031 |
global $debug_object;
|
@@ -1071,31 +827,6 @@ class simple_html_dom_node
|
|
1071 |
return false;
|
1072 |
}
|
1073 |
|
1074 |
-
/**
|
1075 |
-
* Parse CSS selector
|
1076 |
-
*
|
1077 |
-
* @param string $selector_string CSS selector string
|
1078 |
-
* @return array List of CSS selectors. The format depends on the type of
|
1079 |
-
* selector:
|
1080 |
-
*
|
1081 |
-
* ```php
|
1082 |
-
*
|
1083 |
-
* array( // list of selectors (each separated by a comma), i.e. 'img, p, div'
|
1084 |
-
* array( // list of combinator selectors, i.e. 'img > p > div'
|
1085 |
-
* array( // selector element
|
1086 |
-
* [0], // (string) The element tag
|
1087 |
-
* [1], // (string) The element id
|
1088 |
-
* [2], // (array<string>) The element classes
|
1089 |
-
* [3], // (array<array<string>>) The list of attributes, each
|
1090 |
-
* // with four elements: name, expression, value, inverted
|
1091 |
-
* [4] // (string) The selector combinator (' ' | '>' | '+' | '~')
|
1092 |
-
* )
|
1093 |
-
* )
|
1094 |
-
* )
|
1095 |
-
* ```
|
1096 |
-
*
|
1097 |
-
* @link https://www.w3.org/TR/selectors/#compound Compound selector
|
1098 |
-
*/
|
1099 |
protected function parse_selector($selector_string)
|
1100 |
{
|
1101 |
global $debug_object;
|
@@ -1187,7 +918,7 @@ class simple_html_dom_node
|
|
1187 |
*/
|
1188 |
if($m[4] !== '') {
|
1189 |
preg_match_all(
|
1190 |
-
"/\[@?(!?[\w:-]+)(?:([!*^$|~]?=)[\"']?(.*?)[\"']?)?(?:\s
|
1191 |
trim($m[4]),
|
1192 |
$attributes,
|
1193 |
PREG_SET_ORDER
|
@@ -1287,8 +1018,6 @@ class simple_html_dom_node
|
|
1287 |
if (isset($this->attr[$name])) { unset($this->attr[$name]); }
|
1288 |
}
|
1289 |
|
1290 |
-
// PaperG - Function to convert the text from one character set to another
|
1291 |
-
// if the two sets are not the same.
|
1292 |
function convert_text($text)
|
1293 |
{
|
1294 |
global $debug_object;
|
@@ -1339,12 +1068,6 @@ class simple_html_dom_node
|
|
1339 |
return $converted_text;
|
1340 |
}
|
1341 |
|
1342 |
-
/**
|
1343 |
-
* Returns true if $string is valid UTF-8 and false otherwise.
|
1344 |
-
*
|
1345 |
-
* @param mixed $str String to be tested
|
1346 |
-
* @return boolean
|
1347 |
-
*/
|
1348 |
static function is_utf8($str)
|
1349 |
{
|
1350 |
$c = 0; $b = 0;
|
@@ -1372,16 +1095,6 @@ class simple_html_dom_node
|
|
1372 |
return true;
|
1373 |
}
|
1374 |
|
1375 |
-
/**
|
1376 |
-
* Function to try a few tricks to determine the displayed size of an img on
|
1377 |
-
* the page. NOTE: This will ONLY work on an IMG tag. Returns FALSE on all
|
1378 |
-
* other tag types.
|
1379 |
-
*
|
1380 |
-
* @author John Schlick
|
1381 |
-
* @version April 19 2012
|
1382 |
-
* @return array an array containing the 'height' and 'width' of the image
|
1383 |
-
* on the page or -1 if we can't figure it out.
|
1384 |
-
*/
|
1385 |
function get_display_size()
|
1386 |
{
|
1387 |
global $debug_object;
|
@@ -1467,7 +1180,82 @@ class simple_html_dom_node
|
|
1467 |
return $result;
|
1468 |
}
|
1469 |
|
1470 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1471 |
function getAllAttributes()
|
1472 |
{
|
1473 |
return $this->attr;
|
@@ -1493,6 +1281,44 @@ class simple_html_dom_node
|
|
1493 |
$this->__set($name, null);
|
1494 |
}
|
1495 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1496 |
function getElementById($id)
|
1497 |
{
|
1498 |
return $this->find("#$id", 0);
|
@@ -1561,170 +1387,34 @@ class simple_html_dom_node
|
|
1561 |
|
1562 |
}
|
1563 |
|
1564 |
-
/**
|
1565 |
-
* simple html dom parser
|
1566 |
-
*
|
1567 |
-
* Paperg - in the find routine: allow us to specify that we want case
|
1568 |
-
* insensitive testing of the value of the selector.
|
1569 |
-
*
|
1570 |
-
* Paperg - change $size from protected to public so we can easily access it
|
1571 |
-
*
|
1572 |
-
* Paperg - added ForceTagsClosed in the constructor which tells us whether we
|
1573 |
-
* trust the html or not. Default is to NOT trust it.
|
1574 |
-
*
|
1575 |
-
* @package PlaceLocalInclude
|
1576 |
-
*/
|
1577 |
class simple_html_dom
|
1578 |
{
|
1579 |
-
/**
|
1580 |
-
* The root node of the document
|
1581 |
-
*
|
1582 |
-
* @var object
|
1583 |
-
*/
|
1584 |
public $root = null;
|
1585 |
-
|
1586 |
-
/**
|
1587 |
-
* List of nodes in the current DOM
|
1588 |
-
*
|
1589 |
-
* @var array
|
1590 |
-
*/
|
1591 |
public $nodes = array();
|
1592 |
-
|
1593 |
-
/**
|
1594 |
-
* Callback function to run for each element in the DOM.
|
1595 |
-
*
|
1596 |
-
* @var callable|null
|
1597 |
-
*/
|
1598 |
public $callback = null;
|
1599 |
-
|
1600 |
-
/**
|
1601 |
-
* Indicates how tags and attributes are matched
|
1602 |
-
*
|
1603 |
-
* @var bool When set to **true** tags and attributes will be converted to
|
1604 |
-
* lowercase before matching.
|
1605 |
-
*/
|
1606 |
public $lowercase = false;
|
1607 |
-
|
1608 |
-
/**
|
1609 |
-
* Original document size
|
1610 |
-
*
|
1611 |
-
* Holds the original document size.
|
1612 |
-
*
|
1613 |
-
* @var int
|
1614 |
-
*/
|
1615 |
public $original_size;
|
1616 |
-
|
1617 |
-
/**
|
1618 |
-
* Current document size
|
1619 |
-
*
|
1620 |
-
* Holds the current document size. The document size is determined by the
|
1621 |
-
* string length of ({@see simple_html_dom::$doc}).
|
1622 |
-
*
|
1623 |
-
* _Note_: Using this variable is more efficient than calling `strlen($doc)`
|
1624 |
-
*
|
1625 |
-
* @var int
|
1626 |
-
* */
|
1627 |
public $size;
|
1628 |
|
1629 |
-
/**
|
1630 |
-
* Current position in the document
|
1631 |
-
*
|
1632 |
-
* @var int
|
1633 |
-
*/
|
1634 |
protected $pos;
|
1635 |
-
|
1636 |
-
/**
|
1637 |
-
* The document
|
1638 |
-
*
|
1639 |
-
* @var string
|
1640 |
-
*/
|
1641 |
protected $doc;
|
1642 |
-
|
1643 |
-
/**
|
1644 |
-
* Current character
|
1645 |
-
*
|
1646 |
-
* Holds the current character at position {@see simple_html_dom::$pos} in
|
1647 |
-
* the document {@see simple_html_dom::$doc}
|
1648 |
-
*
|
1649 |
-
* _Note_: Using this variable is more efficient than calling
|
1650 |
-
* `substr($doc, $pos, 1)`
|
1651 |
-
*
|
1652 |
-
* @var string
|
1653 |
-
*/
|
1654 |
protected $char;
|
1655 |
|
1656 |
protected $cursor;
|
1657 |
-
|
1658 |
-
/**
|
1659 |
-
* Parent node of the next node detected by the parser
|
1660 |
-
*
|
1661 |
-
* @var object
|
1662 |
-
*/
|
1663 |
protected $parent;
|
1664 |
protected $noise = array();
|
1665 |
-
|
1666 |
-
/**
|
1667 |
-
* Tokens considered blank in HTML
|
1668 |
-
*
|
1669 |
-
* @var string
|
1670 |
-
*/
|
1671 |
protected $token_blank = " \t\r\n";
|
1672 |
-
|
1673 |
-
/**
|
1674 |
-
* Tokens to identify the equal sign for attributes, stopping either at the
|
1675 |
-
* closing tag ("/" i.e. "<html />") or the end of an opening tag (">" i.e.
|
1676 |
-
* "<html>")
|
1677 |
-
*
|
1678 |
-
* @var string
|
1679 |
-
*/
|
1680 |
protected $token_equal = ' =/>';
|
1681 |
-
|
1682 |
-
/**
|
1683 |
-
* Tokens to identify the end of a tag name. A tag name either ends on the
|
1684 |
-
* ending slash ("/" i.e. "<html/>") or whitespace ("\s\r\n\t")
|
1685 |
-
*
|
1686 |
-
* @var string
|
1687 |
-
*/
|
1688 |
protected $token_slash = " />\r\n\t";
|
1689 |
-
|
1690 |
-
/**
|
1691 |
-
* Tokens to identify the end of an attribute
|
1692 |
-
*
|
1693 |
-
* @var string
|
1694 |
-
*/
|
1695 |
protected $token_attr = ' >';
|
1696 |
|
1697 |
-
// Note that this is referenced by a child node, and so it needs to be
|
1698 |
-
// public for that node to see this information.
|
1699 |
public $_charset = '';
|
1700 |
public $_target_charset = '';
|
1701 |
|
1702 |
-
/**
|
1703 |
-
* Innertext for <br> elements
|
1704 |
-
*
|
1705 |
-
* @var string
|
1706 |
-
*/
|
1707 |
protected $default_br_text = '';
|
1708 |
|
1709 |
-
/**
|
1710 |
-
* Suffix for <span> elements
|
1711 |
-
*
|
1712 |
-
* @var string
|
1713 |
-
*/
|
1714 |
public $default_span_text = '';
|
1715 |
|
1716 |
-
/**
|
1717 |
-
* Defines a list of self-closing tags (Void elements) according to the HTML
|
1718 |
-
* Specification
|
1719 |
-
*
|
1720 |
-
* _Remarks_:
|
1721 |
-
* - Use `isset()` instead of `in_array()` on array elements to boost
|
1722 |
-
* performance about 30%
|
1723 |
-
* - Sort elements by name for better readability!
|
1724 |
-
*
|
1725 |
-
* @link https://www.w3.org/TR/html HTML Specification
|
1726 |
-
* @link https://www.w3.org/TR/html/syntax.html#void-elements Void elements
|
1727 |
-
*/
|
1728 |
protected $self_closing_tags = array(
|
1729 |
'area' => 1,
|
1730 |
'base' => 1,
|
@@ -1741,18 +1431,6 @@ class simple_html_dom
|
|
1741 |
'track' => 1,
|
1742 |
'wbr' => 1
|
1743 |
);
|
1744 |
-
|
1745 |
-
/**
|
1746 |
-
* Defines a list of tags which - if closed - close all optional closing
|
1747 |
-
* elements within if they haven't been closed yet. (So, an element where
|
1748 |
-
* neither opening nor closing tag is omissible consistently closes every
|
1749 |
-
* optional closing element within)
|
1750 |
-
*
|
1751 |
-
* _Remarks_:
|
1752 |
-
* - Use `isset()` instead of `in_array()` on array elements to boost
|
1753 |
-
* performance about 30%
|
1754 |
-
* - Sort elements by name for better readability!
|
1755 |
-
*/
|
1756 |
protected $block_tags = array(
|
1757 |
'body' => 1,
|
1758 |
'div' => 1,
|
@@ -1761,62 +1439,6 @@ class simple_html_dom
|
|
1761 |
'span' => 1,
|
1762 |
'table' => 1
|
1763 |
);
|
1764 |
-
|
1765 |
-
/**
|
1766 |
-
* Defines elements whose end tag is omissible.
|
1767 |
-
*
|
1768 |
-
* * key = Name of an element whose end tag is omissible.
|
1769 |
-
* * value = Names of elements whose end tag is omissible, that are closed
|
1770 |
-
* by the current element.
|
1771 |
-
*
|
1772 |
-
* _Remarks_:
|
1773 |
-
* - Use `isset()` instead of `in_array()` on array elements to boost
|
1774 |
-
* performance about 30%
|
1775 |
-
* - Sort elements by name for better readability!
|
1776 |
-
*
|
1777 |
-
* **Example**
|
1778 |
-
*
|
1779 |
-
* An `li` element’s end tag may be omitted if the `li` element is immediately
|
1780 |
-
* followed by another `li` element. To do that, add following element to the
|
1781 |
-
* array:
|
1782 |
-
*
|
1783 |
-
* ```php
|
1784 |
-
* 'li' => array('li'),
|
1785 |
-
* ```
|
1786 |
-
*
|
1787 |
-
* With this, the following two examples are considered equal. Note that the
|
1788 |
-
* second example is missing the closing tags on `li` elements.
|
1789 |
-
*
|
1790 |
-
* ```html
|
1791 |
-
* <ul><li>First Item</li><li>Second Item</li></ul>
|
1792 |
-
* ```
|
1793 |
-
*
|
1794 |
-
* <ul><li>First Item</li><li>Second Item</li></ul>
|
1795 |
-
*
|
1796 |
-
* ```html
|
1797 |
-
* <ul><li>First Item<li>Second Item</ul>
|
1798 |
-
* ```
|
1799 |
-
*
|
1800 |
-
* <ul><li>First Item<li>Second Item</ul>
|
1801 |
-
*
|
1802 |
-
* @var array A two-dimensional array where the key is the name of an
|
1803 |
-
* element whose end tag is omissible and the value is an array of elements
|
1804 |
-
* whose end tag is omissible, that are closed by the current element.
|
1805 |
-
*
|
1806 |
-
* @link https://www.w3.org/TR/html/syntax.html#optional-tags Optional tags
|
1807 |
-
*
|
1808 |
-
* @todo The implementation of optional closing tags doesn't work in all cases
|
1809 |
-
* because it only consideres elements who close other optional closing
|
1810 |
-
* tags, not taking into account that some (non-blocking) tags should close
|
1811 |
-
* these optional closing tags. For example, the end tag for "p" is omissible
|
1812 |
-
* and can be closed by an "address" element, whose end tag is NOT omissible.
|
1813 |
-
* Currently a "p" element without closing tag stops at the next "p" element
|
1814 |
-
* or blocking tag, even if it contains other elements.
|
1815 |
-
*
|
1816 |
-
* @todo Known sourceforge issue #2977341
|
1817 |
-
* B tags that are not closed cause us to return everything to the end of
|
1818 |
-
* the document.
|
1819 |
-
*/
|
1820 |
protected $optional_closing_tags = array(
|
1821 |
// Not optional, see
|
1822 |
// https://www.w3.org/TR/html/textlevel-semantics.html#the-b-element
|
@@ -1875,7 +1497,6 @@ class simple_html_dom
|
|
1875 |
$this->clear();
|
1876 |
}
|
1877 |
|
1878 |
-
// load html from string
|
1879 |
function load(
|
1880 |
$str,
|
1881 |
$lowercase = true,
|
@@ -1930,7 +1551,6 @@ class simple_html_dom
|
|
1930 |
return $this;
|
1931 |
}
|
1932 |
|
1933 |
-
// load html from file
|
1934 |
function load_file()
|
1935 |
{
|
1936 |
$args = func_get_args();
|
@@ -1942,29 +1562,16 @@ class simple_html_dom
|
|
1942 |
}
|
1943 |
}
|
1944 |
|
1945 |
-
/**
|
1946 |
-
* Set the callback function
|
1947 |
-
*
|
1948 |
-
* @param callable $function_name Callback function to run for each element
|
1949 |
-
* in the DOM.
|
1950 |
-
* @return void
|
1951 |
-
*/
|
1952 |
function set_callback($function_name)
|
1953 |
{
|
1954 |
$this->callback = $function_name;
|
1955 |
}
|
1956 |
|
1957 |
-
/**
|
1958 |
-
* Remove callback function
|
1959 |
-
*
|
1960 |
-
* @return void
|
1961 |
-
*/
|
1962 |
function remove_callback()
|
1963 |
{
|
1964 |
$this->callback = null;
|
1965 |
}
|
1966 |
|
1967 |
-
// save dom as string
|
1968 |
function save($filepath = '')
|
1969 |
{
|
1970 |
$ret = $this->root->innertext();
|
@@ -1972,18 +1579,18 @@ class simple_html_dom
|
|
1972 |
return $ret;
|
1973 |
}
|
1974 |
|
1975 |
-
// find dom node by css selector
|
1976 |
-
// Paperg - allow us to specify that we want case insensitive testing of the value of the selector.
|
1977 |
function find($selector, $idx = null, $lowercase = false)
|
1978 |
{
|
1979 |
return $this->root->find($selector, $idx, $lowercase);
|
1980 |
}
|
1981 |
|
1982 |
-
// clean up memory due to php5 circular references memory leak...
|
1983 |
function clear()
|
1984 |
{
|
1985 |
-
|
1986 |
-
$
|
|
|
|
|
|
|
1987 |
}
|
1988 |
|
1989 |
// This add next line is documented in the sourceforge repository.
|
@@ -1991,7 +1598,8 @@ class simple_html_dom
|
|
1991 |
// use of clear.
|
1992 |
if (isset($this->children)) {
|
1993 |
foreach ($this->children as $n) {
|
1994 |
-
$n->clear();
|
|
|
1995 |
}
|
1996 |
}
|
1997 |
|
@@ -2014,7 +1622,6 @@ class simple_html_dom
|
|
2014 |
$this->root->dump($show_attr);
|
2015 |
}
|
2016 |
|
2017 |
-
// prepare HTML data and init everything
|
2018 |
protected function prepare(
|
2019 |
$str, $lowercase = true,
|
2020 |
$defaultBRText = DEFAULT_BR_TEXT,
|
@@ -2040,11 +1647,6 @@ class simple_html_dom
|
|
2040 |
if ($this->size > 0) { $this->char = $this->doc[0]; }
|
2041 |
}
|
2042 |
|
2043 |
-
/**
|
2044 |
-
* Parse HTML content
|
2045 |
-
*
|
2046 |
-
* @return bool True on success
|
2047 |
-
*/
|
2048 |
protected function parse()
|
2049 |
{
|
2050 |
while (true) {
|
@@ -2066,13 +1668,6 @@ class simple_html_dom
|
|
2066 |
}
|
2067 |
}
|
2068 |
|
2069 |
-
// PAPERG - dkchou - added this to try to identify the character set of the
|
2070 |
-
// page we have just parsed so we know better how to spit it out later.
|
2071 |
-
// NOTE: IF you provide a routine called
|
2072 |
-
// get_last_retrieve_url_contents_content_type which returns the
|
2073 |
-
// CURLINFO_CONTENT_TYPE from the last curl_exec
|
2074 |
-
// (or the content_type header from the last transfer), we will parse THAT,
|
2075 |
-
// and if a charset is specified, we will use it over any other mechanism.
|
2076 |
protected function parse_charset()
|
2077 |
{
|
2078 |
global $debug_object;
|
@@ -2094,6 +1689,7 @@ class simple_html_dom
|
|
2094 |
}
|
2095 |
|
2096 |
if (empty($charset)) {
|
|
|
2097 |
$el = $this->root->find('meta[http-equiv=Content-Type]', 0, true);
|
2098 |
|
2099 |
if (!empty($el)) {
|
@@ -2130,53 +1726,77 @@ class simple_html_dom
|
|
2130 |
}
|
2131 |
}
|
2132 |
|
2133 |
-
// If we couldn't find a charset above, then lets try to detect one
|
2134 |
-
// based on the text we got...
|
2135 |
if (empty($charset)) {
|
2136 |
-
//
|
2137 |
-
|
2138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2139 |
if (function_exists('mb_detect_encoding')) {
|
2140 |
-
|
2141 |
-
|
2142 |
-
|
2143 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2144 |
);
|
2145 |
|
2146 |
-
if (
|
2147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
2148 |
}
|
2149 |
-
}
|
2150 |
|
2151 |
-
|
2152 |
-
|
2153 |
-
|
2154 |
-
|
2155 |
-
|
2156 |
-
$debug_object->debug_log(
|
2157 |
-
2,
|
2158 |
-
'since mb_detect failed - using default of utf-8'
|
2159 |
-
);
|
2160 |
}
|
|
|
|
|
2161 |
|
2162 |
-
|
|
|
|
|
|
|
|
|
2163 |
}
|
2164 |
}
|
2165 |
|
2166 |
// Since CP1252 is a superset, if we get one of it's subsets, we want
|
2167 |
// it instead.
|
2168 |
-
if ((strtolower($charset) ==
|
2169 |
-
|| (strtolower($charset) ==
|
2170 |
-
|| (strtolower($charset) ==
|
2171 |
-
|
2172 |
if (is_object($debug_object)) {
|
2173 |
-
$debug_object->debug_log(
|
2174 |
-
2,
|
2175 |
'replacing ' . $charset . ' with CP1252 as its a superset'
|
2176 |
);
|
2177 |
}
|
2178 |
-
|
2179 |
-
$charset = 'CP1252';
|
2180 |
}
|
2181 |
|
2182 |
if (is_object($debug_object)) {
|
@@ -2186,11 +1806,6 @@ class simple_html_dom
|
|
2186 |
return $this->_charset = $charset;
|
2187 |
}
|
2188 |
|
2189 |
-
/**
|
2190 |
-
* Parse tag from current document position.
|
2191 |
-
*
|
2192 |
-
* @return bool True if a tag was found, false otherwise
|
2193 |
-
*/
|
2194 |
protected function read_tag()
|
2195 |
{
|
2196 |
// Set end position if no further tags found
|
@@ -2469,63 +2084,50 @@ class simple_html_dom
|
|
2469 |
return true;
|
2470 |
}
|
2471 |
|
2472 |
-
/**
|
2473 |
-
* Parse attribute from current document position
|
2474 |
-
*
|
2475 |
-
* @param object $node Node for the attributes
|
2476 |
-
* @param string $name Name of the current attribute
|
2477 |
-
* @param array $space Array for spacing information
|
2478 |
-
* @return void
|
2479 |
-
*/
|
2480 |
protected function parse_attr($node, $name, &$space)
|
2481 |
{
|
2482 |
-
|
2483 |
-
// If the attribute is already defined inside a tag, only pay attention
|
2484 |
-
// to the first one as opposed to the last one.
|
2485 |
-
// https://stackoverflow.com/a/26341866
|
2486 |
-
if (isset($node->attr[$name])) {
|
2487 |
-
return;
|
2488 |
-
}
|
2489 |
|
2490 |
-
//
|
2491 |
-
|
2492 |
|
2493 |
switch ($this->char) {
|
2494 |
-
case '"':
|
2495 |
-
$
|
2496 |
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2497 |
-
$
|
2498 |
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2499 |
break;
|
2500 |
-
case '\'':
|
2501 |
-
$
|
2502 |
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2503 |
-
$
|
2504 |
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2505 |
break;
|
2506 |
-
default:
|
2507 |
-
$
|
2508 |
-
$
|
2509 |
}
|
|
|
|
|
|
|
2510 |
// PaperG: Attributes should not have \r or \n in them, that counts as
|
2511 |
// html whitespace.
|
2512 |
-
$
|
2513 |
-
$
|
|
|
2514 |
// PaperG: If this is a "class" selector, lets get rid of the preceeding
|
2515 |
// and trailing space since some people leave it in the multi class case.
|
2516 |
if ($name === 'class') {
|
2517 |
-
$
|
|
|
|
|
|
|
|
|
|
|
2518 |
}
|
2519 |
}
|
2520 |
|
2521 |
-
/**
|
2522 |
-
* Link node to parent node
|
2523 |
-
*
|
2524 |
-
* @param object $node Node to link to parent
|
2525 |
-
* @param bool $is_child True if the node is a child of parent
|
2526 |
-
* @return void
|
2527 |
-
*/
|
2528 |
-
// link node's parent
|
2529 |
protected function link_nodes(&$node, $is_child)
|
2530 |
{
|
2531 |
$node->parent = $this->parent;
|
@@ -2535,12 +2137,6 @@ class simple_html_dom
|
|
2535 |
}
|
2536 |
}
|
2537 |
|
2538 |
-
/**
|
2539 |
-
* Add tag as text node to current node
|
2540 |
-
*
|
2541 |
-
* @param string $tag Tag name
|
2542 |
-
* @return bool True on success
|
2543 |
-
*/
|
2544 |
protected function as_text_node($tag)
|
2545 |
{
|
2546 |
$node = new simple_html_dom_node($this);
|
@@ -2551,28 +2147,12 @@ class simple_html_dom
|
|
2551 |
return true;
|
2552 |
}
|
2553 |
|
2554 |
-
/**
|
2555 |
-
* Seek from the current document position to the first occurrence of a
|
2556 |
-
* character not defined by the provided string. Update the current document
|
2557 |
-
* position to the new position.
|
2558 |
-
*
|
2559 |
-
* @param string $chars A string containing every allowed character.
|
2560 |
-
* @return void
|
2561 |
-
*/
|
2562 |
protected function skip($chars)
|
2563 |
{
|
2564 |
$this->pos += strspn($this->doc, $chars, $this->pos);
|
2565 |
$this->char = ($this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2566 |
}
|
2567 |
|
2568 |
-
/**
|
2569 |
-
* Copy substring from the current document position to the first occurrence
|
2570 |
-
* of a character not defined by the provided string.
|
2571 |
-
*
|
2572 |
-
* @param string $chars A string containing every allowed character.
|
2573 |
-
* @return string Substring from the current document position to the first
|
2574 |
-
* occurrence of a character not defined by the provided string.
|
2575 |
-
*/
|
2576 |
protected function copy_skip($chars)
|
2577 |
{
|
2578 |
$pos = $this->pos;
|
@@ -2583,14 +2163,6 @@ class simple_html_dom
|
|
2583 |
return substr($this->doc, $pos, $len);
|
2584 |
}
|
2585 |
|
2586 |
-
/**
|
2587 |
-
* Copy substring from the current document position to the first occurrence
|
2588 |
-
* of any of the provided characters.
|
2589 |
-
*
|
2590 |
-
* @param string $chars A string containing every character to stop at.
|
2591 |
-
* @return string Substring from the current document position to the first
|
2592 |
-
* occurrence of any of the provided characters.
|
2593 |
-
*/
|
2594 |
protected function copy_until($chars)
|
2595 |
{
|
2596 |
$pos = $this->pos;
|
@@ -2600,14 +2172,6 @@ class simple_html_dom
|
|
2600 |
return substr($this->doc, $pos, $len);
|
2601 |
}
|
2602 |
|
2603 |
-
/**
|
2604 |
-
* Copy substring from the current document position to the first occurrence
|
2605 |
-
* of the provided string.
|
2606 |
-
*
|
2607 |
-
* @param string $char The string to stop at.
|
2608 |
-
* @return string Substring from the current document position to the first
|
2609 |
-
* occurrence of the provided string.
|
2610 |
-
*/
|
2611 |
protected function copy_until_char($char)
|
2612 |
{
|
2613 |
if ($this->char === null) { return ''; }
|
@@ -2627,15 +2191,6 @@ class simple_html_dom
|
|
2627 |
return substr($this->doc, $pos_old, $pos - $pos_old);
|
2628 |
}
|
2629 |
|
2630 |
-
/**
|
2631 |
-
* Remove noise from HTML content
|
2632 |
-
*
|
2633 |
-
* Noise is stored to {@see simple_html_dom::$noise}
|
2634 |
-
*
|
2635 |
-
* @param string $pattern The regex pattern used for finding noise
|
2636 |
-
* @param bool $remove_tag True to remove the entire match. Default is false
|
2637 |
-
* to only remove the captured data.
|
2638 |
-
*/
|
2639 |
protected function remove_noise($pattern, $remove_tag = false)
|
2640 |
{
|
2641 |
global $debug_object;
|
@@ -2668,14 +2223,6 @@ class simple_html_dom
|
|
2668 |
}
|
2669 |
}
|
2670 |
|
2671 |
-
/**
|
2672 |
-
* Restore noise to HTML content
|
2673 |
-
*
|
2674 |
-
* Noise is restored from {@see simple_html_dom::$noise}
|
2675 |
-
*
|
2676 |
-
* @param string $text A subset of HTML containing noise
|
2677 |
-
* @return string The same content with noise restored
|
2678 |
-
*/
|
2679 |
function restore_noise($text)
|
2680 |
{
|
2681 |
global $debug_object;
|
@@ -2722,7 +2269,6 @@ class simple_html_dom
|
|
2722 |
return $text;
|
2723 |
}
|
2724 |
|
2725 |
-
// Sometimes we NEED one of the noise elements.
|
2726 |
function search_noise($text)
|
2727 |
{
|
2728 |
global $debug_object;
|
@@ -2756,7 +2302,6 @@ class simple_html_dom
|
|
2756 |
}
|
2757 |
}
|
2758 |
|
2759 |
-
// camel naming conventions
|
2760 |
function childNodes($idx = -1)
|
2761 |
{
|
2762 |
return $this->root->childNodes($idx);
|
@@ -2774,7 +2319,7 @@ class simple_html_dom
|
|
2774 |
|
2775 |
function createElement($name, $value = null)
|
2776 |
{
|
2777 |
-
return @str_get_html("<$name>$value</$name>")->
|
2778 |
}
|
2779 |
|
2780 |
function createTextNode($value)
|
5 |
* Website: http://sourceforge.net/projects/simplehtmldom/
|
6 |
* Additional projects: http://sourceforge.net/projects/debugobject/
|
7 |
* Acknowledge: Jose Solorzano (https://sourceforge.net/projects/php-html/)
|
|
|
|
|
|
|
|
|
8 |
*
|
9 |
+
* Licensed under The MIT License
|
10 |
+
* See the LICENSE file in the project root for more information.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
*
|
12 |
+
* Authors:
|
13 |
+
* S.C. Chen
|
14 |
+
* John Schlick
|
15 |
+
* Rus Carroll
|
16 |
+
* logmanoriginal
|
17 |
*
|
18 |
+
* Contributors:
|
19 |
+
* Yousuke Kumakura
|
20 |
+
* Vadim Voituk
|
21 |
+
* Antcs
|
22 |
*
|
23 |
+
* Version Rev. 1.9.1 (291)
|
|
|
|
|
|
|
|
|
|
|
24 |
*/
|
25 |
|
|
|
|
|
|
|
|
|
26 |
define('HDOM_TYPE_ELEMENT', 1);
|
27 |
define('HDOM_TYPE_COMMENT', 2);
|
28 |
define('HDOM_TYPE_TEXT', 3);
|
41 |
define('HDOM_INFO_OUTER', 6);
|
42 |
define('HDOM_INFO_ENDSPACE', 7);
|
43 |
|
|
|
44 |
defined('DEFAULT_TARGET_CHARSET') || define('DEFAULT_TARGET_CHARSET', 'UTF-8');
|
|
|
|
|
45 |
defined('DEFAULT_BR_TEXT') || define('DEFAULT_BR_TEXT', "\r\n");
|
|
|
|
|
46 |
defined('DEFAULT_SPAN_TEXT') || define('DEFAULT_SPAN_TEXT', ' ');
|
|
|
|
|
47 |
defined('MAX_FILE_SIZE') || define('MAX_FILE_SIZE', 600000);
|
|
|
|
|
48 |
define('HDOM_SMARTY_AS_TEXT', 1);
|
49 |
|
|
|
|
|
|
|
|
|
50 |
function file_get_html(
|
51 |
$url,
|
52 |
$use_include_path = false,
|
60 |
$defaultBRText = DEFAULT_BR_TEXT,
|
61 |
$defaultSpanText = DEFAULT_SPAN_TEXT)
|
62 |
{
|
|
|
63 |
if($maxLen <= 0) { $maxLen = MAX_FILE_SIZE; }
|
64 |
|
|
|
65 |
$dom = new simple_html_dom(
|
66 |
null,
|
67 |
$lowercase,
|
69 |
$target_charset,
|
70 |
$stripRN,
|
71 |
$defaultBRText,
|
72 |
+
$defaultSpanText
|
73 |
+
);
|
74 |
|
75 |
/**
|
76 |
* For sourceforge users: uncomment the next line and comment the
|
81 |
$use_include_path,
|
82 |
$context,
|
83 |
$offset,
|
84 |
+
$maxLen
|
85 |
+
);
|
|
|
|
|
86 |
// $contents = retrieve_url_contents($url);
|
|
|
87 |
|
88 |
+
if (empty($contents) || strlen($contents) > $maxLen) {
|
89 |
+
$dom->clear();
|
90 |
+
return false;
|
91 |
+
}
|
92 |
+
|
93 |
+
return $dom->load($contents, $lowercase, $stripRN);
|
94 |
}
|
95 |
|
|
|
96 |
function str_get_html(
|
97 |
$str,
|
98 |
$lowercase = true,
|
109 |
$target_charset,
|
110 |
$stripRN,
|
111 |
$defaultBRText,
|
112 |
+
$defaultSpanText
|
113 |
+
);
|
114 |
|
115 |
if (empty($str) || strlen($str) > MAX_FILE_SIZE) {
|
116 |
$dom->clear();
|
117 |
return false;
|
118 |
}
|
119 |
|
120 |
+
return $dom->load($str, $lowercase, $stripRN);
|
|
|
121 |
}
|
122 |
|
|
|
123 |
function dump_html_tree($node, $show_attr = true, $deep = 0)
|
124 |
{
|
125 |
$node->dump($node);
|
126 |
}
|
127 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
class simple_html_dom_node
|
129 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
public $nodetype = HDOM_TYPE_TEXT;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
public $tag = 'text';
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
public $attr = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
public $children = array();
|
134 |
public $nodes = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
135 |
public $parent = null;
|
|
|
|
|
136 |
public $_ = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
public $tag_start = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
138 |
private $dom = null;
|
139 |
|
|
|
|
|
|
|
|
|
|
|
140 |
function __construct($dom)
|
141 |
{
|
142 |
$this->dom = $dom;
|
153 |
return $this->outertext();
|
154 |
}
|
155 |
|
|
|
156 |
function clear()
|
157 |
{
|
158 |
$this->dom = null;
|
161 |
$this->children = null;
|
162 |
}
|
163 |
|
164 |
+
function dump($show_attr = true, $depth = 0)
|
|
|
165 |
{
|
166 |
+
echo str_repeat("\t", $depth) . $this->tag;
|
|
|
|
|
167 |
|
168 |
if ($show_attr && count($this->attr) > 0) {
|
169 |
echo '(';
|
170 |
foreach ($this->attr as $k => $v) {
|
171 |
+
echo "[$k]=>\"$v\", ";
|
172 |
}
|
173 |
echo ')';
|
174 |
}
|
176 |
echo "\n";
|
177 |
|
178 |
if ($this->nodes) {
|
179 |
+
foreach ($this->nodes as $node) {
|
180 |
+
$node->dump($show_attr, $depth + 1);
|
181 |
}
|
182 |
}
|
183 |
}
|
184 |
|
|
|
|
|
185 |
function dump_node($echo = true)
|
186 |
{
|
187 |
$string = $this->tag;
|
189 |
if (count($this->attr) > 0) {
|
190 |
$string .= '(';
|
191 |
foreach ($this->attr as $k => $v) {
|
192 |
+
$string .= "[$k]=>\"$v\", ";
|
193 |
}
|
194 |
$string .= ')';
|
195 |
}
|
200 |
if (is_array($v)) {
|
201 |
$string .= "[$k]=>(";
|
202 |
foreach ($v as $k2 => $v2) {
|
203 |
+
$string .= "[$k2]=>\"$v2\", ";
|
204 |
}
|
205 |
$string .= ')';
|
206 |
} else {
|
207 |
+
$string .= "[$k]=>\"$v\", ";
|
208 |
}
|
209 |
}
|
210 |
$string .= ')';
|
211 |
}
|
212 |
|
213 |
if (isset($this->text)) {
|
214 |
+
$string .= " text: ({$this->text})";
|
215 |
}
|
216 |
|
217 |
+
$string .= ' HDOM_INNER_INFO: ';
|
218 |
|
219 |
if (isset($node->_[HDOM_INFO_INNER])) {
|
220 |
+
$string .= "'" . $node->_[HDOM_INFO_INNER] . "'";
|
221 |
} else {
|
222 |
$string .= ' NULL ';
|
223 |
}
|
235 |
}
|
236 |
}
|
237 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
238 |
function parent($parent = null)
|
239 |
{
|
240 |
// I am SURE that this doesn't work properly.
|
249 |
return $this->parent;
|
250 |
}
|
251 |
|
|
|
|
|
|
|
252 |
function has_child()
|
253 |
{
|
254 |
return !empty($this->children);
|
255 |
}
|
256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
function children($idx = -1)
|
258 |
{
|
259 |
if ($idx === -1) {
|
267 |
return null;
|
268 |
}
|
269 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
270 |
function first_child()
|
271 |
{
|
272 |
if (count($this->children) > 0) {
|
275 |
return null;
|
276 |
}
|
277 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
function last_child()
|
279 |
{
|
280 |
+
if (count($this->children) > 0) {
|
281 |
+
return end($this->children);
|
282 |
}
|
283 |
return null;
|
284 |
}
|
285 |
|
|
|
|
|
|
|
|
|
|
|
|
|
286 |
function next_sibling()
|
287 |
{
|
288 |
if ($this->parent === null) {
|
289 |
return null;
|
290 |
}
|
291 |
|
292 |
+
$idx = array_search($this, $this->parent->children, true);
|
|
|
293 |
|
294 |
+
if ($idx !== false && isset($this->parent->children[$idx + 1])) {
|
295 |
+
return $this->parent->children[$idx + 1];
|
296 |
}
|
297 |
|
298 |
+
return null;
|
|
|
|
|
|
|
|
|
299 |
}
|
300 |
|
|
|
|
|
|
|
|
|
|
|
|
|
301 |
function prev_sibling()
|
302 |
{
|
303 |
+
if ($this->parent === null) {
|
304 |
+
return null;
|
305 |
+
}
|
306 |
|
307 |
+
$idx = array_search($this, $this->parent->children, true);
|
|
|
308 |
|
309 |
+
if ($idx !== false && $idx > 0) {
|
310 |
+
return $this->parent->children[$idx - 1];
|
311 |
}
|
312 |
|
313 |
+
return null;
|
|
|
|
|
314 |
}
|
315 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
316 |
function find_ancestor_tag($tag)
|
317 |
{
|
318 |
global $debug_object;
|
319 |
if (is_object($debug_object)) { $debug_object->debug_log_entry(1); }
|
320 |
|
321 |
+
if ($this->parent === null) {
|
322 |
+
return null;
|
323 |
+
}
|
324 |
|
325 |
+
$ancestor = $this->parent;
|
326 |
+
|
327 |
+
while (!is_null($ancestor)) {
|
328 |
if (is_object($debug_object)) {
|
329 |
+
$debug_object->debug_log(2, 'Current tag is: ' . $ancestor->tag);
|
330 |
}
|
331 |
|
332 |
+
if ($ancestor->tag === $tag) {
|
333 |
break;
|
334 |
}
|
335 |
|
336 |
+
$ancestor = $ancestor->parent;
|
337 |
}
|
338 |
|
339 |
+
return $ancestor;
|
340 |
}
|
341 |
|
|
|
|
|
|
|
|
|
|
|
342 |
function innertext()
|
343 |
{
|
344 |
if (isset($this->_[HDOM_INFO_INNER])) {
|
358 |
return $ret;
|
359 |
}
|
360 |
|
|
|
|
|
|
|
|
|
|
|
361 |
function outertext()
|
362 |
{
|
363 |
global $debug_object;
|
374 |
$debug_object->debug_log(1, 'Innertext of tag: ' . $this->tag . $text);
|
375 |
}
|
376 |
|
377 |
+
if ($this->tag === 'root') {
|
378 |
+
return $this->innertext();
|
379 |
+
}
|
380 |
|
381 |
+
// todo: What is the use of this callback? Remove?
|
382 |
if ($this->dom && $this->dom->callback !== null) {
|
383 |
call_user_func_array($this->dom->callback, array($this));
|
384 |
}
|
391 |
return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]);
|
392 |
}
|
393 |
|
394 |
+
$ret = '';
|
395 |
+
|
396 |
if ($this->dom && $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]) {
|
397 |
$ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup();
|
|
|
|
|
398 |
}
|
399 |
|
|
|
400 |
if (isset($this->_[HDOM_INFO_INNER])) {
|
401 |
+
// todo: <br> should either never have HDOM_INFO_INNER or always
|
|
|
402 |
if ($this->tag !== 'br') {
|
403 |
$ret .= $this->_[HDOM_INFO_INNER];
|
404 |
}
|
405 |
+
} elseif ($this->nodes) {
|
406 |
+
foreach ($this->nodes as $n) {
|
407 |
+
$ret .= $this->convert_text($n->outertext());
|
|
|
|
|
408 |
}
|
409 |
}
|
410 |
|
|
|
411 |
if (isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END] != 0) {
|
412 |
$ret .= '</' . $this->tag . '>';
|
413 |
}
|
415 |
return $ret;
|
416 |
}
|
417 |
|
|
|
|
|
|
|
|
|
|
|
418 |
function text()
|
419 |
{
|
420 |
if (isset($this->_[HDOM_INFO_INNER])) {
|
441 |
foreach ($this->nodes as $n) {
|
442 |
// Start paragraph after a blank line
|
443 |
if ($n->tag === 'p') {
|
444 |
+
$ret = trim($ret) . "\n\n";
|
445 |
}
|
446 |
|
447 |
$ret .= $this->convert_text($n->text());
|
454 |
}
|
455 |
}
|
456 |
}
|
457 |
+
return $ret;
|
458 |
}
|
459 |
|
|
|
|
|
|
|
|
|
|
|
460 |
function xmltext()
|
461 |
{
|
462 |
$ret = $this->innertext();
|
465 |
return $ret;
|
466 |
}
|
467 |
|
|
|
468 |
function makeup()
|
469 |
{
|
470 |
// text, comment, unknown
|
508 |
return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>';
|
509 |
}
|
510 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
511 |
function find($selector, $idx = null, $lowercase = false)
|
512 |
{
|
513 |
$selectors = $this->parse_selector($selector);
|
560 |
return (isset($found[$idx])) ? $found[$idx] : null;
|
561 |
}
|
562 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
563 |
protected function seek($selector, &$ret, $parent_cmd, $lowercase = false)
|
564 |
{
|
565 |
global $debug_object;
|
591 |
&& $this->parent
|
592 |
&& in_array($this, $this->parent->children)) { // Next-Sibling Combinator
|
593 |
$index = array_search($this, $this->parent->children, true) + 1;
|
594 |
+
if ($index < count($this->parent->children))
|
595 |
+
$nodes[] = $this->parent->children[$index];
|
596 |
} elseif ($parent_cmd === '~'
|
597 |
&& $this->parent
|
598 |
&& in_array($this, $this->parent->children)) { // Subsequent Sibling Combinator
|
611 |
$pass = false;
|
612 |
}
|
613 |
|
614 |
+
// Handle 'text' selector
|
615 |
+
if($pass && $tag === 'text' && $node->tag === 'text') {
|
616 |
+
$ret[array_search($node, $this->dom->nodes, true)] = 1;
|
617 |
+
unset($node);
|
618 |
+
continue;
|
619 |
+
}
|
620 |
+
|
621 |
// Skip if node isn't a child node (i.e. text nodes)
|
622 |
if($pass && !in_array($node, $node->parent->children, true)) {
|
623 |
$pass = false;
|
782 |
}
|
783 |
}
|
784 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
785 |
protected function match($exp, $pattern, $value, $case_sensitivity)
|
786 |
{
|
787 |
global $debug_object;
|
827 |
return false;
|
828 |
}
|
829 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
830 |
protected function parse_selector($selector_string)
|
831 |
{
|
832 |
global $debug_object;
|
918 |
*/
|
919 |
if($m[4] !== '') {
|
920 |
preg_match_all(
|
921 |
+
"/\[@?(!?[\w:-]+)(?:([!*^$|~]?=)[\"']?(.*?)[\"']?)?(?:\s+?([iIsS])?)?\]/is",
|
922 |
trim($m[4]),
|
923 |
$attributes,
|
924 |
PREG_SET_ORDER
|
1018 |
if (isset($this->attr[$name])) { unset($this->attr[$name]); }
|
1019 |
}
|
1020 |
|
|
|
|
|
1021 |
function convert_text($text)
|
1022 |
{
|
1023 |
global $debug_object;
|
1068 |
return $converted_text;
|
1069 |
}
|
1070 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1071 |
static function is_utf8($str)
|
1072 |
{
|
1073 |
$c = 0; $b = 0;
|
1095 |
return true;
|
1096 |
}
|
1097 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1098 |
function get_display_size()
|
1099 |
{
|
1100 |
global $debug_object;
|
1180 |
return $result;
|
1181 |
}
|
1182 |
|
1183 |
+
function save($filepath = '')
|
1184 |
+
{
|
1185 |
+
$ret = $this->outertext();
|
1186 |
+
|
1187 |
+
if ($filepath !== '') {
|
1188 |
+
file_put_contents($filepath, $ret, LOCK_EX);
|
1189 |
+
}
|
1190 |
+
|
1191 |
+
return $ret;
|
1192 |
+
}
|
1193 |
+
|
1194 |
+
function addClass($class)
|
1195 |
+
{
|
1196 |
+
if (is_string($class)) {
|
1197 |
+
$class = explode(' ', $class);
|
1198 |
+
}
|
1199 |
+
|
1200 |
+
if (is_array($class)) {
|
1201 |
+
foreach($class as $c) {
|
1202 |
+
if (isset($this->class)) {
|
1203 |
+
if ($this->hasClass($c)) {
|
1204 |
+
continue;
|
1205 |
+
} else {
|
1206 |
+
$this->class .= ' ' . $c;
|
1207 |
+
}
|
1208 |
+
} else {
|
1209 |
+
$this->class = $c;
|
1210 |
+
}
|
1211 |
+
}
|
1212 |
+
} else {
|
1213 |
+
if (is_object($debug_object)) {
|
1214 |
+
$debug_object->debug_log(2, 'Invalid type: ', gettype($class));
|
1215 |
+
}
|
1216 |
+
}
|
1217 |
+
}
|
1218 |
+
|
1219 |
+
function hasClass($class)
|
1220 |
+
{
|
1221 |
+
if (is_string($class)) {
|
1222 |
+
if (isset($this->class)) {
|
1223 |
+
return in_array($class, explode(' ', $this->class), true);
|
1224 |
+
}
|
1225 |
+
} else {
|
1226 |
+
if (is_object($debug_object)) {
|
1227 |
+
$debug_object->debug_log(2, 'Invalid type: ', gettype($class));
|
1228 |
+
}
|
1229 |
+
}
|
1230 |
+
|
1231 |
+
return false;
|
1232 |
+
}
|
1233 |
+
|
1234 |
+
function removeClass($class = null)
|
1235 |
+
{
|
1236 |
+
if (!isset($this->class)) {
|
1237 |
+
return;
|
1238 |
+
}
|
1239 |
+
|
1240 |
+
if (is_null($class)) {
|
1241 |
+
$this->removeAttribute('class');
|
1242 |
+
return;
|
1243 |
+
}
|
1244 |
+
|
1245 |
+
if (is_string($class)) {
|
1246 |
+
$class = explode(' ', $class);
|
1247 |
+
}
|
1248 |
+
|
1249 |
+
if (is_array($class)) {
|
1250 |
+
$class = array_diff(explode(' ', $this->class), $class);
|
1251 |
+
if (empty($class)) {
|
1252 |
+
$this->removeAttribute('class');
|
1253 |
+
} else {
|
1254 |
+
$this->class = implode(' ', $class);
|
1255 |
+
}
|
1256 |
+
}
|
1257 |
+
}
|
1258 |
+
|
1259 |
function getAllAttributes()
|
1260 |
{
|
1261 |
return $this->attr;
|
1281 |
$this->__set($name, null);
|
1282 |
}
|
1283 |
|
1284 |
+
function remove()
|
1285 |
+
{
|
1286 |
+
if ($this->parent) {
|
1287 |
+
$this->parent->removeChild($this);
|
1288 |
+
}
|
1289 |
+
}
|
1290 |
+
|
1291 |
+
function removeChild($node)
|
1292 |
+
{
|
1293 |
+
$nidx = array_search($node, $this->nodes, true);
|
1294 |
+
$cidx = array_search($node, $this->children, true);
|
1295 |
+
$didx = array_search($node, $this->dom->nodes, true);
|
1296 |
+
|
1297 |
+
if ($nidx !== false && $cidx !== false && $didx !== false) {
|
1298 |
+
|
1299 |
+
foreach($node->children as $child) {
|
1300 |
+
$node->removeChild($child);
|
1301 |
+
}
|
1302 |
+
|
1303 |
+
foreach($node->nodes as $entity) {
|
1304 |
+
$enidx = array_search($entity, $node->nodes, true);
|
1305 |
+
$edidx = array_search($entity, $node->dom->nodes, true);
|
1306 |
+
|
1307 |
+
if ($enidx !== false && $edidx !== false) {
|
1308 |
+
unset($node->nodes[$enidx]);
|
1309 |
+
unset($node->dom->nodes[$edidx]);
|
1310 |
+
}
|
1311 |
+
}
|
1312 |
+
|
1313 |
+
unset($this->nodes[$nidx]);
|
1314 |
+
unset($this->children[$cidx]);
|
1315 |
+
unset($this->dom->nodes[$didx]);
|
1316 |
+
|
1317 |
+
$node->clear();
|
1318 |
+
|
1319 |
+
}
|
1320 |
+
}
|
1321 |
+
|
1322 |
function getElementById($id)
|
1323 |
{
|
1324 |
return $this->find("#$id", 0);
|
1387 |
|
1388 |
}
|
1389 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1390 |
class simple_html_dom
|
1391 |
{
|
|
|
|
|
|
|
|
|
|
|
1392 |
public $root = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
1393 |
public $nodes = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
1394 |
public $callback = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1395 |
public $lowercase = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1396 |
public $original_size;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1397 |
public $size;
|
1398 |
|
|
|
|
|
|
|
|
|
|
|
1399 |
protected $pos;
|
|
|
|
|
|
|
|
|
|
|
|
|
1400 |
protected $doc;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1401 |
protected $char;
|
1402 |
|
1403 |
protected $cursor;
|
|
|
|
|
|
|
|
|
|
|
|
|
1404 |
protected $parent;
|
1405 |
protected $noise = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
1406 |
protected $token_blank = " \t\r\n";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1407 |
protected $token_equal = ' =/>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1408 |
protected $token_slash = " />\r\n\t";
|
|
|
|
|
|
|
|
|
|
|
|
|
1409 |
protected $token_attr = ' >';
|
1410 |
|
|
|
|
|
1411 |
public $_charset = '';
|
1412 |
public $_target_charset = '';
|
1413 |
|
|
|
|
|
|
|
|
|
|
|
1414 |
protected $default_br_text = '';
|
1415 |
|
|
|
|
|
|
|
|
|
|
|
1416 |
public $default_span_text = '';
|
1417 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1418 |
protected $self_closing_tags = array(
|
1419 |
'area' => 1,
|
1420 |
'base' => 1,
|
1431 |
'track' => 1,
|
1432 |
'wbr' => 1
|
1433 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1434 |
protected $block_tags = array(
|
1435 |
'body' => 1,
|
1436 |
'div' => 1,
|
1439 |
'span' => 1,
|
1440 |
'table' => 1
|
1441 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1442 |
protected $optional_closing_tags = array(
|
1443 |
// Not optional, see
|
1444 |
// https://www.w3.org/TR/html/textlevel-semantics.html#the-b-element
|
1497 |
$this->clear();
|
1498 |
}
|
1499 |
|
|
|
1500 |
function load(
|
1501 |
$str,
|
1502 |
$lowercase = true,
|
1551 |
return $this;
|
1552 |
}
|
1553 |
|
|
|
1554 |
function load_file()
|
1555 |
{
|
1556 |
$args = func_get_args();
|
1562 |
}
|
1563 |
}
|
1564 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1565 |
function set_callback($function_name)
|
1566 |
{
|
1567 |
$this->callback = $function_name;
|
1568 |
}
|
1569 |
|
|
|
|
|
|
|
|
|
|
|
1570 |
function remove_callback()
|
1571 |
{
|
1572 |
$this->callback = null;
|
1573 |
}
|
1574 |
|
|
|
1575 |
function save($filepath = '')
|
1576 |
{
|
1577 |
$ret = $this->root->innertext();
|
1579 |
return $ret;
|
1580 |
}
|
1581 |
|
|
|
|
|
1582 |
function find($selector, $idx = null, $lowercase = false)
|
1583 |
{
|
1584 |
return $this->root->find($selector, $idx, $lowercase);
|
1585 |
}
|
1586 |
|
|
|
1587 |
function clear()
|
1588 |
{
|
1589 |
+
if (isset($this->nodes)) {
|
1590 |
+
foreach ($this->nodes as $n) {
|
1591 |
+
$n->clear();
|
1592 |
+
$n = null;
|
1593 |
+
}
|
1594 |
}
|
1595 |
|
1596 |
// This add next line is documented in the sourceforge repository.
|
1598 |
// use of clear.
|
1599 |
if (isset($this->children)) {
|
1600 |
foreach ($this->children as $n) {
|
1601 |
+
$n->clear();
|
1602 |
+
$n = null;
|
1603 |
}
|
1604 |
}
|
1605 |
|
1622 |
$this->root->dump($show_attr);
|
1623 |
}
|
1624 |
|
|
|
1625 |
protected function prepare(
|
1626 |
$str, $lowercase = true,
|
1627 |
$defaultBRText = DEFAULT_BR_TEXT,
|
1647 |
if ($this->size > 0) { $this->char = $this->doc[0]; }
|
1648 |
}
|
1649 |
|
|
|
|
|
|
|
|
|
|
|
1650 |
protected function parse()
|
1651 |
{
|
1652 |
while (true) {
|
1668 |
}
|
1669 |
}
|
1670 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1671 |
protected function parse_charset()
|
1672 |
{
|
1673 |
global $debug_object;
|
1689 |
}
|
1690 |
|
1691 |
if (empty($charset)) {
|
1692 |
+
// https://www.w3.org/TR/html/document-metadata.html#statedef-http-equiv-content-type
|
1693 |
$el = $this->root->find('meta[http-equiv=Content-Type]', 0, true);
|
1694 |
|
1695 |
if (!empty($el)) {
|
1726 |
}
|
1727 |
}
|
1728 |
|
|
|
|
|
1729 |
if (empty($charset)) {
|
1730 |
+
// https://www.w3.org/TR/html/document-metadata.html#character-encoding-declaration
|
1731 |
+
if ($meta = $this->root->find('meta[charset]', 0)) {
|
1732 |
+
$charset = $meta->charset;
|
1733 |
+
if (is_object($debug_object)) {
|
1734 |
+
$debug_object->debug_log(2, 'meta charset: ' . $charset);
|
1735 |
+
}
|
1736 |
+
}
|
1737 |
+
}
|
1738 |
+
|
1739 |
+
if (empty($charset)) {
|
1740 |
+
// Try to guess the charset based on the content
|
1741 |
+
// Requires Multibyte String (mbstring) support (optional)
|
1742 |
if (function_exists('mb_detect_encoding')) {
|
1743 |
+
/**
|
1744 |
+
* mb_detect_encoding() is not intended to distinguish between
|
1745 |
+
* charsets, especially single-byte charsets. Its primary
|
1746 |
+
* purpose is to detect which multibyte encoding is in use,
|
1747 |
+
* i.e. UTF-8, UTF-16, shift-JIS, etc.
|
1748 |
+
*
|
1749 |
+
* -- https://bugs.php.net/bug.php?id=38138
|
1750 |
+
*
|
1751 |
+
* Adding both CP1251/ISO-8859-5 and CP1252/ISO-8859-1 will
|
1752 |
+
* always result in CP1251/ISO-8859-5 and vice versa.
|
1753 |
+
*
|
1754 |
+
* Thus, only detect if it's either UTF-8 or CP1252/ISO-8859-1
|
1755 |
+
* to stay compatible.
|
1756 |
+
*/
|
1757 |
+
$encoding = mb_detect_encoding(
|
1758 |
+
$this->doc,
|
1759 |
+
array( 'UTF-8', 'CP1252', 'ISO-8859-1' )
|
1760 |
);
|
1761 |
|
1762 |
+
if ($encoding === 'CP1252' || $encoding === 'ISO-8859-1') {
|
1763 |
+
// Due to a limitation of mb_detect_encoding
|
1764 |
+
// 'CP1251'/'ISO-8859-5' will be detected as
|
1765 |
+
// 'CP1252'/'ISO-8859-1'. This will cause iconv to fail, in
|
1766 |
+
// which case we can simply assume it is the other charset.
|
1767 |
+
if (!@iconv('CP1252', 'UTF-8', $this->doc)) {
|
1768 |
+
$encoding = 'CP1251';
|
1769 |
+
}
|
1770 |
}
|
|
|
1771 |
|
1772 |
+
if ($encoding !== false) {
|
1773 |
+
$charset = $encoding;
|
1774 |
+
if (is_object($debug_object)) {
|
1775 |
+
$debug_object->debug_log(2, 'mb_detect: ' . $charset);
|
1776 |
+
}
|
|
|
|
|
|
|
|
|
1777 |
}
|
1778 |
+
}
|
1779 |
+
}
|
1780 |
|
1781 |
+
if (empty($charset)) {
|
1782 |
+
// Assume it's UTF-8 as it is the most likely charset to be used
|
1783 |
+
$charset = 'UTF-8';
|
1784 |
+
if (is_object($debug_object)) {
|
1785 |
+
$debug_object->debug_log(2, 'No match found, assume ' . $charset);
|
1786 |
}
|
1787 |
}
|
1788 |
|
1789 |
// Since CP1252 is a superset, if we get one of it's subsets, we want
|
1790 |
// it instead.
|
1791 |
+
if ((strtolower($charset) == 'iso-8859-1')
|
1792 |
+
|| (strtolower($charset) == 'latin1')
|
1793 |
+
|| (strtolower($charset) == 'latin-1')) {
|
1794 |
+
$charset = 'CP1252';
|
1795 |
if (is_object($debug_object)) {
|
1796 |
+
$debug_object->debug_log(2,
|
|
|
1797 |
'replacing ' . $charset . ' with CP1252 as its a superset'
|
1798 |
);
|
1799 |
}
|
|
|
|
|
1800 |
}
|
1801 |
|
1802 |
if (is_object($debug_object)) {
|
1806 |
return $this->_charset = $charset;
|
1807 |
}
|
1808 |
|
|
|
|
|
|
|
|
|
|
|
1809 |
protected function read_tag()
|
1810 |
{
|
1811 |
// Set end position if no further tags found
|
2084 |
return true;
|
2085 |
}
|
2086 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2087 |
protected function parse_attr($node, $name, &$space)
|
2088 |
{
|
2089 |
+
$is_duplicate = isset($node->attr[$name]);
|
|
|
|
|
|
|
|
|
|
|
|
|
2090 |
|
2091 |
+
if (!$is_duplicate) // Copy whitespace between "=" and value
|
2092 |
+
$space[2] = $this->copy_skip($this->token_blank);
|
2093 |
|
2094 |
switch ($this->char) {
|
2095 |
+
case '"':
|
2096 |
+
$quote_type = HDOM_QUOTE_DOUBLE;
|
2097 |
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2098 |
+
$value = $this->copy_until_char('"');
|
2099 |
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2100 |
break;
|
2101 |
+
case '\'':
|
2102 |
+
$quote_type = HDOM_QUOTE_SINGLE;
|
2103 |
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2104 |
+
$value = $this->copy_until_char('\'');
|
2105 |
$this->char = (++$this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2106 |
break;
|
2107 |
+
default:
|
2108 |
+
$quote_type = HDOM_QUOTE_NO;
|
2109 |
+
$value = $this->copy_until($this->token_attr);
|
2110 |
}
|
2111 |
+
|
2112 |
+
$value = $this->restore_noise($value);
|
2113 |
+
|
2114 |
// PaperG: Attributes should not have \r or \n in them, that counts as
|
2115 |
// html whitespace.
|
2116 |
+
$value = str_replace("\r", '', $value);
|
2117 |
+
$value = str_replace("\n", '', $value);
|
2118 |
+
|
2119 |
// PaperG: If this is a "class" selector, lets get rid of the preceeding
|
2120 |
// and trailing space since some people leave it in the multi class case.
|
2121 |
if ($name === 'class') {
|
2122 |
+
$value = trim($value);
|
2123 |
+
}
|
2124 |
+
|
2125 |
+
if (!$is_duplicate) {
|
2126 |
+
$node->_[HDOM_INFO_QUOTE][] = $quote_type;
|
2127 |
+
$node->attr[$name] = $value;
|
2128 |
}
|
2129 |
}
|
2130 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2131 |
protected function link_nodes(&$node, $is_child)
|
2132 |
{
|
2133 |
$node->parent = $this->parent;
|
2137 |
}
|
2138 |
}
|
2139 |
|
|
|
|
|
|
|
|
|
|
|
|
|
2140 |
protected function as_text_node($tag)
|
2141 |
{
|
2142 |
$node = new simple_html_dom_node($this);
|
2147 |
return true;
|
2148 |
}
|
2149 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2150 |
protected function skip($chars)
|
2151 |
{
|
2152 |
$this->pos += strspn($this->doc, $chars, $this->pos);
|
2153 |
$this->char = ($this->pos < $this->size) ? $this->doc[$this->pos] : null; // next
|
2154 |
}
|
2155 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2156 |
protected function copy_skip($chars)
|
2157 |
{
|
2158 |
$pos = $this->pos;
|
2163 |
return substr($this->doc, $pos, $len);
|
2164 |
}
|
2165 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2166 |
protected function copy_until($chars)
|
2167 |
{
|
2168 |
$pos = $this->pos;
|
2172 |
return substr($this->doc, $pos, $len);
|
2173 |
}
|
2174 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2175 |
protected function copy_until_char($char)
|
2176 |
{
|
2177 |
if ($this->char === null) { return ''; }
|
2191 |
return substr($this->doc, $pos_old, $pos - $pos_old);
|
2192 |
}
|
2193 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2194 |
protected function remove_noise($pattern, $remove_tag = false)
|
2195 |
{
|
2196 |
global $debug_object;
|
2223 |
}
|
2224 |
}
|
2225 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2226 |
function restore_noise($text)
|
2227 |
{
|
2228 |
global $debug_object;
|
2269 |
return $text;
|
2270 |
}
|
2271 |
|
|
|
2272 |
function search_noise($text)
|
2273 |
{
|
2274 |
global $debug_object;
|
2302 |
}
|
2303 |
}
|
2304 |
|
|
|
2305 |
function childNodes($idx = -1)
|
2306 |
{
|
2307 |
return $this->root->childNodes($idx);
|
2319 |
|
2320 |
function createElement($name, $value = null)
|
2321 |
{
|
2322 |
+
return @str_get_html("<$name>$value</$name>")->firstChild();
|
2323 |
}
|
2324 |
|
2325 |
function createTextNode($value)
|