Version Description
- Fix: Now works with thumbnails in src.
- Update: Optimization (does not regenerate pages which aren't impacted by changes).
- Update: DiDom from 1.13 to 1.14.1.
Download this release
Release Info
Developer | TigrouMeow |
Plugin | Gallery Custom Links |
Version | 1.0.2 |
Comparing to | |
See all releases |
Code changes from version 1.0.0 to 1.0.2
- composer.lock +8 -5
- gallery_custom_links.php +2 -2
- mgcl_core.php +11 -7
- readme.txt +6 -1
- vendor/composer/installed.json +9 -6
- vendor/imangazaliev/didom/README-RU.md +2 -2
- vendor/imangazaliev/didom/README.md +85 -13
- vendor/imangazaliev/didom/composer.json +5 -2
- vendor/imangazaliev/didom/src/DiDom/ClassAttribute.php +5 -5
- vendor/imangazaliev/didom/src/DiDom/Document.php +79 -42
- vendor/imangazaliev/didom/src/DiDom/Element.php +99 -67
- vendor/imangazaliev/didom/src/DiDom/Encoder.php +1 -1
- vendor/imangazaliev/didom/src/DiDom/Query.php +20 -20
- vendor/imangazaliev/didom/src/DiDom/StyleAttribute.php +2 -2
- vendor/imangazaliev/didom/tests/DiDom/ClassAttributeTest.php +2 -2
- vendor/imangazaliev/didom/tests/DiDom/DocumentTest.php +63 -0
- vendor/imangazaliev/didom/tests/DiDom/ElementTest.php +39 -1
- vendor/imangazaliev/didom/tests/DiDom/QueryTest.php +1 -1
- vendor/imangazaliev/didom/tests/DiDom/StyleAttributeTest.php +2 -2
- vendor/imangazaliev/didom/tests/fixtures/books.xml +1 -1
- vendor/imangazaliev/didom/tests/fixtures/menu.html +3 -2
composer.lock
CHANGED
@@ -8,22 +8,25 @@
|
|
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": {
|
|
|
|
|
24 |
"php": ">=5.4"
|
25 |
},
|
26 |
"require-dev": {
|
|
|
27 |
"phpunit/phpunit": "^4.8"
|
28 |
},
|
29 |
"type": "library",
|
@@ -50,7 +53,7 @@
|
|
50 |
"parser",
|
51 |
"xml"
|
52 |
],
|
53 |
-
"time": "
|
54 |
}
|
55 |
],
|
56 |
"packages-dev": [],
|
8 |
"packages": [
|
9 |
{
|
10 |
"name": "imangazaliev/didom",
|
11 |
+
"version": "1.14.1",
|
12 |
"source": {
|
13 |
"type": "git",
|
14 |
"url": "https://github.com/Imangazaliev/DiDOM.git",
|
15 |
+
"reference": "a8389cc26897f6bb8843363b4ea16e7ef16fb3c3"
|
16 |
},
|
17 |
"dist": {
|
18 |
"type": "zip",
|
19 |
+
"url": "https://api.github.com/repos/Imangazaliev/DiDOM/zipball/a8389cc26897f6bb8843363b4ea16e7ef16fb3c3",
|
20 |
+
"reference": "a8389cc26897f6bb8843363b4ea16e7ef16fb3c3",
|
21 |
"shasum": ""
|
22 |
},
|
23 |
"require": {
|
24 |
+
"ext-dom": "*",
|
25 |
+
"ext-iconv": "*",
|
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 |
"parser",
|
54 |
"xml"
|
55 |
],
|
56 |
+
"time": "2019-01-17T11:01:36+00:00"
|
57 |
}
|
58 |
],
|
59 |
"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.0.
|
7 |
Author: Jordy Meow
|
8 |
Text Domain: gallery-custom-links
|
9 |
Domain Path: /languages
|
@@ -22,7 +22,7 @@ if ( class_exists( 'Meow_Gallery_Custom_Links' ) ) {
|
|
22 |
}
|
23 |
|
24 |
global $mgcl_version;
|
25 |
-
$mgcl_version = '1.0.
|
26 |
|
27 |
// Admin
|
28 |
// include "mgcl_admin.php";
|
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.0.2
|
7 |
Author: Jordy Meow
|
8 |
Text Domain: gallery-custom-links
|
9 |
Domain Path: /languages
|
22 |
}
|
23 |
|
24 |
global $mgcl_version;
|
25 |
+
$mgcl_version = '1.0.2';
|
26 |
|
27 |
// Admin
|
28 |
// include "mgcl_admin.php";
|
mgcl_core.php
CHANGED
@@ -64,6 +64,8 @@ class Meow_Gallery_Custom_Links
|
|
64 |
|
65 |
function resolve_image_id( $url ) {
|
66 |
global $wpdb;
|
|
|
|
|
67 |
$url = $this->get_pathinfo_from_image_src( $url );
|
68 |
$query = $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid LIKE '%s'", '%' . $url . '%' );
|
69 |
$attachment = $wpdb->get_col( $query );
|
@@ -93,6 +95,7 @@ class Meow_Gallery_Custom_Links
|
|
93 |
if ( $parent->tag === 'a' ) {
|
94 |
$parent->attr( 'href', $url );
|
95 |
$parent->attr( 'target', $target );
|
|
|
96 |
}
|
97 |
else {
|
98 |
if ( $parent->tag === 'figure' )
|
@@ -106,26 +109,27 @@ class Meow_Gallery_Custom_Links
|
|
106 |
$img->remove();
|
107 |
}
|
108 |
$parent->appendChild( $a );
|
|
|
109 |
}
|
110 |
}
|
111 |
}
|
112 |
-
|
113 |
}
|
114 |
|
115 |
function linkify( $buffer ) {
|
116 |
if ( !isset( $buffer ) || trim( $buffer ) === '' )
|
117 |
return $buffer;
|
118 |
-
|
119 |
$html = new Document( $buffer );
|
120 |
-
|
121 |
-
$this->linkify_element( $element );
|
122 |
foreach ( $html->find('.gallery img') as $element )
|
123 |
-
$this->linkify_element( $element );
|
|
|
|
|
124 |
if ( class_exists( 'Meow_Gallery_Core' ) ) {
|
125 |
foreach ( $html->find('.mgl-gallery img') as $element )
|
126 |
-
$this->linkify_element( $element );
|
127 |
}
|
128 |
-
return $html;
|
129 |
}
|
130 |
|
131 |
function wp_footer() {
|
64 |
|
65 |
function resolve_image_id( $url ) {
|
66 |
global $wpdb;
|
67 |
+
$pattern = '/[_-]\d+x\d+(?=\.[a-z]{3,4}$)/';
|
68 |
+
$url = preg_replace( $pattern, '', $url );
|
69 |
$url = $this->get_pathinfo_from_image_src( $url );
|
70 |
$query = $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid LIKE '%s'", '%' . $url . '%' );
|
71 |
$attachment = $wpdb->get_col( $query );
|
95 |
if ( $parent->tag === 'a' ) {
|
96 |
$parent->attr( 'href', $url );
|
97 |
$parent->attr( 'target', $target );
|
98 |
+
return true;
|
99 |
}
|
100 |
else {
|
101 |
if ( $parent->tag === 'figure' )
|
109 |
$img->remove();
|
110 |
}
|
111 |
$parent->appendChild( $a );
|
112 |
+
return true;
|
113 |
}
|
114 |
}
|
115 |
}
|
116 |
+
return false;
|
117 |
}
|
118 |
|
119 |
function linkify( $buffer ) {
|
120 |
if ( !isset( $buffer ) || trim( $buffer ) === '' )
|
121 |
return $buffer;
|
|
|
122 |
$html = new Document( $buffer );
|
123 |
+
$hasChanges = false;
|
|
|
124 |
foreach ( $html->find('.gallery img') as $element )
|
125 |
+
$hasChanges = $this->linkify_element( $element ) || $hasChanges;
|
126 |
+
foreach ( $html->find('.wp-block-gallery img') as $element )
|
127 |
+
$hasChanges = $this->linkify_element( $element ) || $hasChanges;
|
128 |
if ( class_exists( 'Meow_Gallery_Core' ) ) {
|
129 |
foreach ( $html->find('.mgl-gallery img') as $element )
|
130 |
+
$hasChanges = $this->linkify_element( $element ) || $hasChanges;
|
131 |
}
|
132 |
+
return $hasChanges ? $html : $buffer;
|
133 |
}
|
134 |
|
135 |
function wp_footer() {
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: TigrouMeow
|
|
3 |
Tags: custom, links, gallery, gutenberg
|
4 |
Requires at least: 4.9
|
5 |
Tested up to: 5.0
|
6 |
-
Stable tag: 1.0.
|
7 |
|
8 |
Gallery Custom Links allows you to link images from galleries to a specified URL. Tested with WordPress Gallery, Gutenberg, the Meow Gallery and others.
|
9 |
|
@@ -36,6 +36,11 @@ Replace all the files. Nothing else to do.
|
|
36 |
|
37 |
== Changelog ==
|
38 |
|
|
|
|
|
|
|
|
|
|
|
39 |
= 1.0.0 =
|
40 |
* Update: If the ID of the Media is not found in the HTML, it will resolve it through the DB from the filename.
|
41 |
|
3 |
Tags: custom, links, gallery, gutenberg
|
4 |
Requires at least: 4.9
|
5 |
Tested up to: 5.0
|
6 |
+
Stable tag: 1.0.2
|
7 |
|
8 |
Gallery Custom Links allows you to link images from galleries to a specified URL. Tested with WordPress Gallery, Gutenberg, the Meow Gallery and others.
|
9 |
|
36 |
|
37 |
== Changelog ==
|
38 |
|
39 |
+
= 1.0.2 =
|
40 |
+
* Fix: Now works with thumbnails in src.
|
41 |
+
* Update: Optimization (does not regenerate pages which aren't impacted by changes).
|
42 |
+
* Update: DiDom from 1.13 to 1.14.1.
|
43 |
+
|
44 |
= 1.0.0 =
|
45 |
* Update: If the ID of the Media is not found in the HTML, it will resolve it through the DB from the filename.
|
46 |
|
vendor/composer/installed.json
CHANGED
@@ -1,26 +1,29 @@
|
|
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": {
|
|
|
|
|
18 |
"php": ">=5.4"
|
19 |
},
|
20 |
"require-dev": {
|
|
|
21 |
"phpunit/phpunit": "^4.8"
|
22 |
},
|
23 |
-
"time": "
|
24 |
"type": "library",
|
25 |
"installation-source": "dist",
|
26 |
"autoload": {
|
1 |
[
|
2 |
{
|
3 |
"name": "imangazaliev/didom",
|
4 |
+
"version": "1.14.1",
|
5 |
+
"version_normalized": "1.14.1.0",
|
6 |
"source": {
|
7 |
"type": "git",
|
8 |
"url": "https://github.com/Imangazaliev/DiDOM.git",
|
9 |
+
"reference": "a8389cc26897f6bb8843363b4ea16e7ef16fb3c3"
|
10 |
},
|
11 |
"dist": {
|
12 |
"type": "zip",
|
13 |
+
"url": "https://api.github.com/repos/Imangazaliev/DiDOM/zipball/a8389cc26897f6bb8843363b4ea16e7ef16fb3c3",
|
14 |
+
"reference": "a8389cc26897f6bb8843363b4ea16e7ef16fb3c3",
|
15 |
"shasum": ""
|
16 |
},
|
17 |
"require": {
|
18 |
+
"ext-dom": "*",
|
19 |
+
"ext-iconv": "*",
|
20 |
"php": ">=5.4"
|
21 |
},
|
22 |
"require-dev": {
|
23 |
+
"friendsofphp/php-cs-fixer": "2.9",
|
24 |
"phpunit/phpunit": "^4.8"
|
25 |
},
|
26 |
+
"time": "2019-01-17T11:01:36+00:00",
|
27 |
"type": "library",
|
28 |
"installation-source": "dist",
|
29 |
"autoload": {
|
vendor/imangazaliev/didom/README-RU.md
CHANGED
@@ -220,7 +220,7 @@ echo $document->find('nav')[0]->first('ul.menu')->xpath('//li')[0]->text();
|
|
220 |
|
221 |
#### Метод `findInDocument()`
|
222 |
|
223 |
-
При изменении, замене или удалении элемента, найденного в другом элементе, документ не будет изменен. Данное поведение связано с тем, что в
|
224 |
|
225 |
Для поиска элементов в исходном документе необходимо использовать методы `findInDocument()` и `firstInDocument()`:
|
226 |
|
@@ -232,7 +232,7 @@ $document->first('head')->first('title')->remove();
|
|
232 |
$document->first('head')->firstInDocument('title')->remove();
|
233 |
```
|
234 |
|
235 |
-
**Внимание:**
|
236 |
|
237 |
## Поддерживамые селекторы
|
238 |
|
220 |
|
221 |
#### Метод `findInDocument()`
|
222 |
|
223 |
+
При изменении, замене или удалении элемента, найденного в другом элементе, документ не будет изменен. Данное поведение связано с тем, что в методе `find()` класса `Element` (а, соответственно, и в методах `first()` и `xpath`) создается новый документ, в котором и производится поиск.
|
224 |
|
225 |
Для поиска элементов в исходном документе необходимо использовать методы `findInDocument()` и `firstInDocument()`:
|
226 |
|
232 |
$document->first('head')->firstInDocument('title')->remove();
|
233 |
```
|
234 |
|
235 |
+
**Внимание:** методы `findInDocument()` и `firstInDocument()` работают только для элементов, которые принадлежат какому-либо документу, либо созданых через `new Element(...)`. Если элемент не принадлежит к какому-либо документу, будет выброшено исключение `LogicException`;
|
236 |
|
237 |
## Поддерживамые селекторы
|
238 |
|
vendor/imangazaliev/didom/README.md
CHANGED
@@ -16,19 +16,21 @@ DiDOM - simple and fast HTML parser.
|
|
16 |
- [Creating new document](#creating-new-document)
|
17 |
- [Search for elements](#search-for-elements)
|
18 |
- [Verify if element exists](#verify-if-element-exists)
|
|
|
19 |
- [Supported selectors](#supported-selectors)
|
20 |
- [Output](#output)
|
21 |
-
- [
|
22 |
-
- [
|
23 |
-
- [Getting
|
24 |
-
- [Getting
|
25 |
-
- [Getting
|
26 |
-
- [Getting
|
27 |
-
- [
|
28 |
-
- [
|
29 |
-
- [
|
30 |
-
- [
|
31 |
-
- [
|
|
|
32 |
- [Working with cache](#working-with-cache)
|
33 |
- [Miscellaneous](#miscellaneous)
|
34 |
- [Comparison with other parsers](#comparison-with-other-parsers)
|
@@ -72,6 +74,20 @@ $document = new Document('http://www.example.com/', true);
|
|
72 |
|
73 |
The second parameter specifies if you need to load file. Default is `false`.
|
74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
##### With separate methods
|
76 |
|
77 |
```php
|
@@ -86,10 +102,14 @@ $document->loadHtmlFile('http://www.example.com/');
|
|
86 |
|
87 |
There are two methods available for loading XML: `loadXml` and `loadXmlFile`.
|
88 |
|
89 |
-
These methods accept additional options:
|
90 |
|
91 |
```php
|
92 |
$document->loadHtml($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
|
|
|
|
|
|
|
|
|
93 |
```
|
94 |
|
95 |
## Search for elements
|
@@ -119,6 +139,8 @@ If the elements that match a given expression are found, then method returns an
|
|
119 |
$posts = $document('.post');
|
120 |
```
|
121 |
|
|
|
|
|
122 |
##### With method `xpath()`:
|
123 |
|
124 |
```php
|
@@ -158,7 +180,33 @@ if (count($elements = $document->find('.post')) > 0) {
|
|
158 |
}
|
159 |
```
|
160 |
|
161 |
-
because in the first case it makes two
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
|
163 |
## Supported selectors
|
164 |
|
@@ -501,12 +549,36 @@ $element = new Element('span', 'hello');
|
|
501 |
$document->find('.post')[0]->replace($element);
|
502 |
```
|
503 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
504 |
## Removing element
|
505 |
|
506 |
```php
|
507 |
$document->find('.post')[0]->remove();
|
508 |
```
|
509 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
510 |
## Working with cache
|
511 |
|
512 |
Cache is an array of XPath expressions, that were converted from CSS.
|
16 |
- [Creating new document](#creating-new-document)
|
17 |
- [Search for elements](#search-for-elements)
|
18 |
- [Verify if element exists](#verify-if-element-exists)
|
19 |
+
- [Search in element](#search-in-element)
|
20 |
- [Supported selectors](#supported-selectors)
|
21 |
- [Output](#output)
|
22 |
+
- [Working with elements](#working-with-elements)
|
23 |
+
- [Creating a new element](#creating-a-new-element)
|
24 |
+
- [Getting the name of an element](#getting-the-name-of-an-element)
|
25 |
+
- [Getting parent element](#getting-parent-element)
|
26 |
+
- [Getting sibling elements](#getting-sibling-elements)
|
27 |
+
- [Getting the child elements](#getting-the-child-elements)
|
28 |
+
- [Getting document](#getting-document)
|
29 |
+
- [Working with element attributes](#working-with-element-attributes)
|
30 |
+
- [Comparing elements](#comparing-elements)
|
31 |
+
- [Adding a child element](#adding-a-child-element)
|
32 |
+
- [Replacing element](#replacing-element)
|
33 |
+
- [Removing element](#removing-element)
|
34 |
- [Working with cache](#working-with-cache)
|
35 |
- [Miscellaneous](#miscellaneous)
|
36 |
- [Comparison with other parsers](#comparison-with-other-parsers)
|
74 |
|
75 |
The second parameter specifies if you need to load file. Default is `false`.
|
76 |
|
77 |
+
Signature:
|
78 |
+
|
79 |
+
```php
|
80 |
+
__construct($string = null, $isFile = false, $encoding = 'UTF-8', $type = Document::TYPE_HTML)
|
81 |
+
```
|
82 |
+
|
83 |
+
`$string` - an HTML or XML string or a file path.
|
84 |
+
|
85 |
+
`$isFile` - indicates that the first parameter is a path to a file.
|
86 |
+
|
87 |
+
`$encoding` - the document encoding.
|
88 |
+
|
89 |
+
`$type` - the document type (HTML - `Document::TYPE_HTML`, XML - `Document::TYPE_XML`).
|
90 |
+
|
91 |
##### With separate methods
|
92 |
|
93 |
```php
|
102 |
|
103 |
There are two methods available for loading XML: `loadXml` and `loadXmlFile`.
|
104 |
|
105 |
+
These methods accept additional [options](http://php.net/manual/en/libxml.constants.php):
|
106 |
|
107 |
```php
|
108 |
$document->loadHtml($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
|
109 |
+
$document->loadHtmlFile($url, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
|
110 |
+
|
111 |
+
$document->loadXml($xml, LIBXML_PARSEHUGE);
|
112 |
+
$document->loadXmlFile($url, LIBXML_PARSEHUGE);
|
113 |
```
|
114 |
|
115 |
## Search for elements
|
139 |
$posts = $document('.post');
|
140 |
```
|
141 |
|
142 |
+
**Warning:** using this method is undesirable because it may be removed in the future.
|
143 |
+
|
144 |
##### With method `xpath()`:
|
145 |
|
146 |
```php
|
180 |
}
|
181 |
```
|
182 |
|
183 |
+
because in the first case it makes two queries.
|
184 |
+
|
185 |
+
## Search in element
|
186 |
+
|
187 |
+
Methods `find()`, `first()`, `xpath()`, `has()`, `count()` are available in Element too.
|
188 |
+
|
189 |
+
Example:
|
190 |
+
|
191 |
+
```php
|
192 |
+
echo $document->find('nav')[0]->first('ul.menu')->xpath('//li')[0]->text();
|
193 |
+
```
|
194 |
+
|
195 |
+
#### Method `findInDocument()`
|
196 |
+
|
197 |
+
If you change, replace, or remove an element that was found in another element, the document will not be changed. This happens because method `find()` of `Element` class (a, respectively, the `first ()` and `xpath` methods) creates a new document to search.
|
198 |
+
|
199 |
+
To search for elements in the source document, you must use the methods `findInDocument()` and `firstInDocument()`:
|
200 |
+
|
201 |
+
```php
|
202 |
+
// nothing will happen
|
203 |
+
$document->first('head')->first('title')->remove();
|
204 |
+
|
205 |
+
// but this will do
|
206 |
+
$document->first('head')->firstInDocument('title')->remove();
|
207 |
+
```
|
208 |
+
|
209 |
+
**Warning:** methods `findInDocument()` and `firstInDocument()` work only for elements, which belong to a document, and for elements created via `new Element(...)`. If an element does not belong to a document, `LogicException` will be thrown;
|
210 |
|
211 |
## Supported selectors
|
212 |
|
549 |
$document->find('.post')[0]->replace($element);
|
550 |
```
|
551 |
|
552 |
+
**Waning:** you can replace only those elements that were found directly in the document:
|
553 |
+
|
554 |
+
```php
|
555 |
+
// nothing will happen
|
556 |
+
$document->first('head')->first('title')->replace($title);
|
557 |
+
|
558 |
+
// but this will do
|
559 |
+
$document->first('head title')->replace($title);
|
560 |
+
```
|
561 |
+
|
562 |
+
More about this in section [Search for elements](#search-for-elements).
|
563 |
+
|
564 |
## Removing element
|
565 |
|
566 |
```php
|
567 |
$document->find('.post')[0]->remove();
|
568 |
```
|
569 |
|
570 |
+
**Warning:** you can remove only those elements that were found directly in the document:
|
571 |
+
|
572 |
+
```php
|
573 |
+
// nothing will happen
|
574 |
+
$document->first('head')->first('title')->remove();
|
575 |
+
|
576 |
+
// but this will do
|
577 |
+
$document->first('head title')->remove();
|
578 |
+
```
|
579 |
+
|
580 |
+
More about this in section [Search for elements](#search-for-elements).
|
581 |
+
|
582 |
## Working with cache
|
583 |
|
584 |
Cache is an array of XPath expressions, that were converted from CSS.
|
vendor/imangazaliev/didom/composer.json
CHANGED
@@ -12,10 +12,13 @@
|
|
12 |
}
|
13 |
],
|
14 |
"require": {
|
15 |
-
"php": ">=5.4"
|
|
|
|
|
16 |
},
|
17 |
"require-dev": {
|
18 |
-
"phpunit/phpunit": "^4.8"
|
|
|
19 |
},
|
20 |
"autoload": {
|
21 |
"psr-4": {
|
12 |
}
|
13 |
],
|
14 |
"require": {
|
15 |
+
"php": ">=5.4",
|
16 |
+
"ext-dom": "*",
|
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": {
|
vendor/imangazaliev/didom/src/DiDom/ClassAttribute.php
CHANGED
@@ -33,7 +33,7 @@ class ClassAttribute
|
|
33 |
public function __construct(Element $element)
|
34 |
{
|
35 |
if (!$element->isElementNode()) {
|
36 |
-
throw new InvalidArgumentException(sprintf('The element
|
37 |
}
|
38 |
|
39 |
$this->element = $element;
|
@@ -106,7 +106,7 @@ class ClassAttribute
|
|
106 |
|
107 |
$this->parseClassAttribute();
|
108 |
|
109 |
-
if (in_array($className, $this->classes)) {
|
110 |
return $this;
|
111 |
}
|
112 |
|
@@ -133,7 +133,7 @@ class ClassAttribute
|
|
133 |
throw new InvalidArgumentException(sprintf('Class name must be a string, %s given', (is_object($className) ? get_class($className) : gettype($className))));
|
134 |
}
|
135 |
|
136 |
-
if (in_array($className, $this->classes)) {
|
137 |
continue;
|
138 |
}
|
139 |
|
@@ -168,7 +168,7 @@ class ClassAttribute
|
|
168 |
|
169 |
$this->parseClassAttribute();
|
170 |
|
171 |
-
return in_array($className, $this->classes);
|
172 |
}
|
173 |
|
174 |
/**
|
@@ -245,7 +245,7 @@ class ClassAttribute
|
|
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)) {
|
249 |
continue;
|
250 |
}
|
251 |
|
33 |
public function __construct(Element $element)
|
34 |
{
|
35 |
if (!$element->isElementNode()) {
|
36 |
+
throw new InvalidArgumentException(sprintf('The element must contain DOMElement node'));
|
37 |
}
|
38 |
|
39 |
$this->element = $element;
|
106 |
|
107 |
$this->parseClassAttribute();
|
108 |
|
109 |
+
if (in_array($className, $this->classes, true)) {
|
110 |
return $this;
|
111 |
}
|
112 |
|
133 |
throw new InvalidArgumentException(sprintf('Class name must be a string, %s given', (is_object($className) ? get_class($className) : gettype($className))));
|
134 |
}
|
135 |
|
136 |
+
if (in_array($className, $this->classes, true)) {
|
137 |
continue;
|
138 |
}
|
139 |
|
168 |
|
169 |
$this->parseClassAttribute();
|
170 |
|
171 |
+
return in_array($className, $this->classes, true);
|
172 |
}
|
173 |
|
174 |
/**
|
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 |
|
vendor/imangazaliev/didom/src/DiDom/Document.php
CHANGED
@@ -2,7 +2,12 @@
|
|
2 |
|
3 |
namespace DiDom;
|
4 |
|
|
|
|
|
5 |
use DOMDocument;
|
|
|
|
|
|
|
6 |
use DOMXPath;
|
7 |
use InvalidArgumentException;
|
8 |
use RuntimeException;
|
@@ -10,7 +15,7 @@ use RuntimeException;
|
|
10 |
class Document
|
11 |
{
|
12 |
/**
|
13 |
-
* Types of document.
|
14 |
*
|
15 |
* @const string
|
16 |
*/
|
@@ -35,8 +40,8 @@ class Document
|
|
35 |
/**
|
36 |
* Constructor.
|
37 |
*
|
38 |
-
* @param string|null $string HTML or XML string or file path
|
39 |
-
* @param bool $isFile Indicates that
|
40 |
* @param string $encoding The document encoding
|
41 |
* @param string $type The document type
|
42 |
*
|
@@ -66,10 +71,10 @@ class Document
|
|
66 |
}
|
67 |
|
68 |
/**
|
69 |
-
*
|
70 |
*
|
71 |
-
* @param string|null $string HTML or XML string or file path
|
72 |
-
* @param bool $isFile Indicates that
|
73 |
* @param string $encoding The document encoding
|
74 |
* @param string $type The document type
|
75 |
*
|
@@ -81,7 +86,7 @@ class Document
|
|
81 |
}
|
82 |
|
83 |
/**
|
84 |
-
*
|
85 |
*
|
86 |
* @param string $name The tag name of the element
|
87 |
* @param string|null $value The value of the element
|
@@ -93,17 +98,15 @@ class Document
|
|
93 |
{
|
94 |
$node = $this->document->createElement($name);
|
95 |
|
96 |
-
|
97 |
-
|
98 |
-
return $element;
|
99 |
}
|
100 |
|
101 |
/**
|
102 |
-
*
|
103 |
*
|
104 |
-
* @param string
|
105 |
* @param string|null $value
|
106 |
-
* @param array
|
107 |
*
|
108 |
* @return \DiDom\Element
|
109 |
*/
|
@@ -129,7 +132,37 @@ class Document
|
|
129 |
}
|
130 |
|
131 |
/**
|
132 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
*
|
134 |
* @param \DiDom\Element|\DOMNode|array $nodes The appended child
|
135 |
*
|
@@ -154,7 +187,7 @@ class Document
|
|
154 |
$node = $node->getNode();
|
155 |
}
|
156 |
|
157 |
-
if (!$node instanceof
|
158 |
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))));
|
159 |
}
|
160 |
|
@@ -168,7 +201,7 @@ class Document
|
|
168 |
Errors::restore();
|
169 |
}
|
170 |
|
171 |
-
$result = array_map(function (
|
172 |
return new Element($node);
|
173 |
}, $result);
|
174 |
|
@@ -217,7 +250,7 @@ class Document
|
|
217 |
throw new InvalidArgumentException(sprintf('%s expects parameter 3 to be string, %s given', __METHOD__, (is_object($type) ? get_class($type) : gettype($type))));
|
218 |
}
|
219 |
|
220 |
-
if (!in_array(strtolower($type), [Document::TYPE_HTML, Document::TYPE_XML])) {
|
221 |
throw new RuntimeException(sprintf('Document type must be "xml" or "html", %s given', $type));
|
222 |
}
|
223 |
|
@@ -226,7 +259,7 @@ class Document
|
|
226 |
$options = LIBXML_HTML_NODEFDTD;
|
227 |
}
|
228 |
|
229 |
-
if (!
|
230 |
throw new InvalidArgumentException(sprintf('%s expects parameter 4 to be integer, %s given', __METHOD__, (is_object($options) ? get_class($options) : gettype($options))));
|
231 |
}
|
232 |
|
@@ -358,15 +391,10 @@ class Document
|
|
358 |
*/
|
359 |
public function has($expression, $type = Query::TYPE_CSS)
|
360 |
{
|
361 |
-
$xpath = new DOMXPath($this->document);
|
362 |
-
|
363 |
-
$xpath->registerNamespace('php', 'http://php.net/xpath');
|
364 |
-
$xpath->registerPhpFunctions();
|
365 |
-
|
366 |
$expression = Query::compile($expression, $type);
|
367 |
$expression = sprintf('count(%s) > 0', $expression);
|
368 |
|
369 |
-
return $
|
370 |
}
|
371 |
|
372 |
/**
|
@@ -385,26 +413,21 @@ class Document
|
|
385 |
{
|
386 |
$expression = Query::compile($expression, $type);
|
387 |
|
388 |
-
$xpath = new DOMXPath($this->document);
|
389 |
-
|
390 |
-
$xpath->registerNamespace('php', 'http://php.net/xpath');
|
391 |
-
$xpath->registerPhpFunctions();
|
392 |
-
|
393 |
if ($contextNode !== null) {
|
394 |
if ($contextNode instanceof Element) {
|
395 |
$contextNode = $contextNode->getNode();
|
396 |
}
|
397 |
|
398 |
-
if (!$contextNode instanceof
|
399 |
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))));
|
400 |
}
|
401 |
|
402 |
if ($type === Query::TYPE_CSS) {
|
403 |
-
$expression = '.'
|
404 |
}
|
405 |
}
|
406 |
|
407 |
-
$nodeList = $
|
408 |
|
409 |
$result = [];
|
410 |
|
@@ -435,8 +458,8 @@ class Document
|
|
435 |
{
|
436 |
$expression = Query::compile($expression, $type);
|
437 |
|
438 |
-
if ($contextNode !== null
|
439 |
-
$expression = '.'
|
440 |
}
|
441 |
|
442 |
$expression = sprintf('(%s)[1]', $expression);
|
@@ -455,7 +478,7 @@ class Document
|
|
455 |
*
|
456 |
* @return \DiDom\Element|string
|
457 |
*
|
458 |
-
* @throws InvalidArgumentException if node is not DOMElement, DOMText or DOMAttr
|
459 |
*/
|
460 |
protected function wrapNode($node)
|
461 |
{
|
@@ -466,6 +489,12 @@ class Document
|
|
466 |
case 'DOMText':
|
467 |
return $node->data;
|
468 |
|
|
|
|
|
|
|
|
|
|
|
|
|
469 |
case 'DOMAttr':
|
470 |
return $node->value;
|
471 |
}
|
@@ -474,7 +503,7 @@ class Document
|
|
474 |
}
|
475 |
|
476 |
/**
|
477 |
-
* Searches for
|
478 |
*
|
479 |
* @param string $expression XPath expression
|
480 |
* @param bool $wrapNode Returns array of \DiDom\Element if true, otherwise array of \DOMElement
|
@@ -496,16 +525,24 @@ class Document
|
|
496 |
* @return int
|
497 |
*/
|
498 |
public function count($expression, $type = Query::TYPE_CSS)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
499 |
{
|
500 |
$xpath = new DOMXPath($this->document);
|
501 |
|
502 |
$xpath->registerNamespace('php', 'http://php.net/xpath');
|
503 |
$xpath->registerPhpFunctions();
|
504 |
|
505 |
-
|
506 |
-
$expression = sprintf('count(%s)', $expression);
|
507 |
-
|
508 |
-
return (int) $xpath->evaluate($expression);
|
509 |
}
|
510 |
|
511 |
/**
|
@@ -587,7 +624,7 @@ class Document
|
|
587 |
}
|
588 |
|
589 |
/**
|
590 |
-
* Returns the type of document (XML or HTML).
|
591 |
*
|
592 |
* @return string
|
593 |
*/
|
@@ -597,7 +634,7 @@ class Document
|
|
597 |
}
|
598 |
|
599 |
/**
|
600 |
-
* Returns the encoding of document (XML or HTML).
|
601 |
*
|
602 |
* @return string
|
603 |
*/
|
2 |
|
3 |
namespace DiDom;
|
4 |
|
5 |
+
use DOMCdataSection;
|
6 |
+
use DOMComment;
|
7 |
use DOMDocument;
|
8 |
+
use DOMElement;
|
9 |
+
use DOMNode;
|
10 |
+
use DOMText;
|
11 |
use DOMXPath;
|
12 |
use InvalidArgumentException;
|
13 |
use RuntimeException;
|
15 |
class Document
|
16 |
{
|
17 |
/**
|
18 |
+
* Types of a document.
|
19 |
*
|
20 |
* @const string
|
21 |
*/
|
40 |
/**
|
41 |
* Constructor.
|
42 |
*
|
43 |
+
* @param string|null $string An HTML or XML string or a file path
|
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 |
*
|
71 |
}
|
72 |
|
73 |
/**
|
74 |
+
* Creates a new document.
|
75 |
*
|
76 |
+
* @param string|null $string An HTML or XML string or a file path
|
77 |
+
* @param bool $isFile Indicates that the first parameter is a path to a file
|
78 |
* @param string $encoding The document encoding
|
79 |
* @param string $type The document type
|
80 |
*
|
86 |
}
|
87 |
|
88 |
/**
|
89 |
+
* Creates a new element node.
|
90 |
*
|
91 |
* @param string $name The tag name of the element
|
92 |
* @param string|null $value The value of the element
|
98 |
{
|
99 |
$node = $this->document->createElement($name);
|
100 |
|
101 |
+
return new Element($node, $value, $attributes);
|
|
|
|
|
102 |
}
|
103 |
|
104 |
/**
|
105 |
+
* Creates a new element node by CSS selector.
|
106 |
*
|
107 |
+
* @param string $selector
|
108 |
* @param string|null $value
|
109 |
+
* @param array $attributes
|
110 |
*
|
111 |
* @return \DiDom\Element
|
112 |
*/
|
132 |
}
|
133 |
|
134 |
/**
|
135 |
+
* @param string $content
|
136 |
+
*
|
137 |
+
* @return Element
|
138 |
+
*/
|
139 |
+
public function createTextNode($content)
|
140 |
+
{
|
141 |
+
return new Element(new DOMText($content));
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* @param string $data
|
146 |
+
*
|
147 |
+
* @return Element
|
148 |
+
*/
|
149 |
+
public function createComment($data)
|
150 |
+
{
|
151 |
+
return new Element(new DOMComment($data));
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* @param string $data
|
156 |
+
*
|
157 |
+
* @return Element
|
158 |
+
*/
|
159 |
+
public function createCdataSection($data)
|
160 |
+
{
|
161 |
+
return new Element(new DOMCdataSection($data));
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Adds a new child at the end of the children.
|
166 |
*
|
167 |
* @param \DiDom\Element|\DOMNode|array $nodes The appended child
|
168 |
*
|
187 |
$node = $node->getNode();
|
188 |
}
|
189 |
|
190 |
+
if (!$node instanceof DOMNode) {
|
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 |
|
201 |
Errors::restore();
|
202 |
}
|
203 |
|
204 |
+
$result = array_map(function (DOMNode $node) {
|
205 |
return new Element($node);
|
206 |
}, $result);
|
207 |
|
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 |
$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 |
|
391 |
*/
|
392 |
public function has($expression, $type = Query::TYPE_CSS)
|
393 |
{
|
|
|
|
|
|
|
|
|
|
|
394 |
$expression = Query::compile($expression, $type);
|
395 |
$expression = sprintf('count(%s) > 0', $expression);
|
396 |
|
397 |
+
return $this->createXpath()->evaluate($expression);
|
398 |
}
|
399 |
|
400 |
/**
|
413 |
{
|
414 |
$expression = Query::compile($expression, $type);
|
415 |
|
|
|
|
|
|
|
|
|
|
|
416 |
if ($contextNode !== null) {
|
417 |
if ($contextNode instanceof Element) {
|
418 |
$contextNode = $contextNode->getNode();
|
419 |
}
|
420 |
|
421 |
+
if (!$contextNode instanceof DOMElement) {
|
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 |
|
425 |
if ($type === Query::TYPE_CSS) {
|
426 |
+
$expression = '.' . $expression;
|
427 |
}
|
428 |
}
|
429 |
|
430 |
+
$nodeList = $this->createXpath()->query($expression, $contextNode);
|
431 |
|
432 |
$result = [];
|
433 |
|
458 |
{
|
459 |
$expression = Query::compile($expression, $type);
|
460 |
|
461 |
+
if ($contextNode !== null && $type === Query::TYPE_CSS) {
|
462 |
+
$expression = '.' . $expression;
|
463 |
}
|
464 |
|
465 |
$expression = sprintf('(%s)[1]', $expression);
|
478 |
*
|
479 |
* @return \DiDom\Element|string
|
480 |
*
|
481 |
+
* @throws InvalidArgumentException if node is not DOMElement, DOMText, DOMComment, DOMCdataSection or DOMAttr
|
482 |
*/
|
483 |
protected function wrapNode($node)
|
484 |
{
|
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 |
}
|
503 |
}
|
504 |
|
505 |
/**
|
506 |
+
* Searches for a node in the DOM tree for a given XPath expression.
|
507 |
*
|
508 |
* @param string $expression XPath expression
|
509 |
* @param bool $wrapNode Returns array of \DiDom\Element if true, otherwise array of \DOMElement
|
525 |
* @return int
|
526 |
*/
|
527 |
public function count($expression, $type = Query::TYPE_CSS)
|
528 |
+
{
|
529 |
+
$expression = Query::compile($expression, $type);
|
530 |
+
$expression = sprintf('count(%s)', $expression);
|
531 |
+
|
532 |
+
return (int) $this->createXpath()->evaluate($expression);
|
533 |
+
}
|
534 |
+
|
535 |
+
/**
|
536 |
+
* @return DOMXPath
|
537 |
+
*/
|
538 |
+
public function createXpath()
|
539 |
{
|
540 |
$xpath = new DOMXPath($this->document);
|
541 |
|
542 |
$xpath->registerNamespace('php', 'http://php.net/xpath');
|
543 |
$xpath->registerPhpFunctions();
|
544 |
|
545 |
+
return $xpath;
|
|
|
|
|
|
|
546 |
}
|
547 |
|
548 |
/**
|
624 |
}
|
625 |
|
626 |
/**
|
627 |
+
* Returns the type of the document (XML or HTML).
|
628 |
*
|
629 |
* @return string
|
630 |
*/
|
634 |
}
|
635 |
|
636 |
/**
|
637 |
+
* Returns the encoding of the document (XML or HTML).
|
638 |
*
|
639 |
* @return string
|
640 |
*/
|
vendor/imangazaliev/didom/src/DiDom/Element.php
CHANGED
@@ -2,9 +2,12 @@
|
|
2 |
|
3 |
namespace DiDom;
|
4 |
|
|
|
|
|
5 |
use DOMDocument;
|
6 |
use DOMElement;
|
7 |
use DOMNode;
|
|
|
8 |
use InvalidArgumentException;
|
9 |
use LogicException;
|
10 |
use RuntimeException;
|
@@ -17,7 +20,7 @@ class Element
|
|
17 |
/**
|
18 |
* The DOM element instance.
|
19 |
*
|
20 |
-
* @var \DOMElement|\DOMText|\DOMComment
|
21 |
*/
|
22 |
protected $node;
|
23 |
|
@@ -34,33 +37,33 @@ class Element
|
|
34 |
/**
|
35 |
* Constructor.
|
36 |
*
|
37 |
-
* @param \DOMElement|\DOMText|\DOMComment|string $
|
38 |
* @param string|null $value The value of the element
|
39 |
* @param array $attributes The attributes of the element
|
40 |
*/
|
41 |
-
public function __construct($
|
42 |
{
|
43 |
-
if (is_string($
|
44 |
$document = new DOMDocument('1.0', 'UTF-8');
|
45 |
|
46 |
-
$node = $document->createElement($
|
47 |
|
48 |
$this->setNode($node);
|
49 |
} else {
|
50 |
-
$this->setNode($
|
51 |
}
|
52 |
|
53 |
if ($value !== null) {
|
54 |
$this->setValue($value);
|
55 |
}
|
56 |
|
57 |
-
foreach ($attributes as $
|
58 |
-
$this->setAttribute($
|
59 |
}
|
60 |
}
|
61 |
|
62 |
/**
|
63 |
-
*
|
64 |
*
|
65 |
* @param \DOMNode|string $name The tag name of the element
|
66 |
* @param string|null $value The value of the element
|
@@ -74,7 +77,7 @@ class Element
|
|
74 |
}
|
75 |
|
76 |
/**
|
77 |
-
*
|
78 |
*
|
79 |
* @param string $selector
|
80 |
* @param string|null $value
|
@@ -88,7 +91,7 @@ class Element
|
|
88 |
}
|
89 |
|
90 |
/**
|
91 |
-
* Adds new child at the start of the children.
|
92 |
*
|
93 |
* @param \DiDom\Element|\DOMNode|array $nodes The prepended child
|
94 |
*
|
@@ -127,7 +130,7 @@ class Element
|
|
127 |
}
|
128 |
|
129 |
/**
|
130 |
-
* Adds new child at the end of the children.
|
131 |
*
|
132 |
* @param \DiDom\Element|\DOMNode|array $nodes The appended child
|
133 |
*
|
@@ -159,7 +162,7 @@ class Element
|
|
159 |
$node = $node->getNode();
|
160 |
}
|
161 |
|
162 |
-
if (!$node instanceof
|
163 |
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))));
|
164 |
}
|
165 |
|
@@ -171,7 +174,7 @@ class Element
|
|
171 |
|
172 |
Errors::restore();
|
173 |
|
174 |
-
$result = array_map(function (
|
175 |
return new Element($node);
|
176 |
}, $result);
|
177 |
|
@@ -200,7 +203,7 @@ class Element
|
|
200 |
$node = $node->getNode();
|
201 |
}
|
202 |
|
203 |
-
if (!$node instanceof
|
204 |
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))));
|
205 |
}
|
206 |
|
@@ -209,7 +212,7 @@ class Element
|
|
209 |
$referenceNode = $referenceNode->getNode();
|
210 |
}
|
211 |
|
212 |
-
if (!$referenceNode instanceof
|
213 |
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))));
|
214 |
}
|
215 |
}
|
@@ -248,7 +251,7 @@ class Element
|
|
248 |
$referenceNode = $referenceNode->getNode();
|
249 |
}
|
250 |
|
251 |
-
if (!$referenceNode instanceof
|
252 |
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))));
|
253 |
}
|
254 |
|
@@ -372,7 +375,8 @@ class Element
|
|
372 |
*
|
373 |
* @return bool
|
374 |
*
|
375 |
-
* @throws \
|
|
|
376 |
*/
|
377 |
public function matches($selector, $strict = false)
|
378 |
{
|
@@ -380,7 +384,7 @@ class Element
|
|
380 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, gettype($selector)));
|
381 |
}
|
382 |
|
383 |
-
if (!$this->node instanceof
|
384 |
return false;
|
385 |
}
|
386 |
|
@@ -392,7 +396,7 @@ class Element
|
|
392 |
$innerHtml = $this->html();
|
393 |
$html = "<root>$innerHtml</root>";
|
394 |
|
395 |
-
$selector = 'root > '.trim($selector);
|
396 |
|
397 |
$document = new Document();
|
398 |
|
@@ -407,7 +411,7 @@ class Element
|
|
407 |
throw new RuntimeException(sprintf('Tag name must be specified in %s', $selector));
|
408 |
}
|
409 |
|
410 |
-
if ($segments['tag'] !== $this->tag
|
411 |
return false;
|
412 |
}
|
413 |
|
@@ -424,21 +428,21 @@ class Element
|
|
424 |
$diff1 = array_diff($segments['classes'], $classes);
|
425 |
$diff2 = array_diff($classes, $segments['classes']);
|
426 |
|
427 |
-
if (count($diff1) > 0
|
428 |
return false;
|
429 |
}
|
430 |
|
431 |
$attributes = $this->attributes();
|
432 |
|
433 |
-
unset($attributes['id']);
|
434 |
-
unset($attributes['class']);
|
435 |
|
436 |
$segments['attributes'] = array_key_exists('attributes', $segments) ? $segments['attributes'] : [];
|
437 |
|
438 |
$diff1 = array_diff_assoc($segments['attributes'], $attributes);
|
439 |
$diff2 = array_diff_assoc($attributes, $segments['attributes']);
|
440 |
|
441 |
-
if
|
|
|
442 |
return false;
|
443 |
}
|
444 |
|
@@ -471,7 +475,7 @@ class Element
|
|
471 |
$value = (string) $value;
|
472 |
}
|
473 |
|
474 |
-
if (!is_string($value)
|
475 |
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string or null, %s given', __METHOD__, (is_object($value) ? get_class($value) : gettype($value))));
|
476 |
}
|
477 |
|
@@ -525,7 +529,7 @@ class Element
|
|
525 |
}
|
526 |
|
527 |
foreach ($this->attributes() as $name => $value) {
|
528 |
-
if (in_array($name, $exclusions)) {
|
529 |
continue;
|
530 |
}
|
531 |
|
@@ -578,7 +582,7 @@ class Element
|
|
578 |
$result = [];
|
579 |
|
580 |
foreach ($this->node->attributes as $name => $attribute) {
|
581 |
-
if (in_array($name, $names)) {
|
582 |
$result[$name] = $attribute->value;
|
583 |
}
|
584 |
}
|
@@ -668,6 +672,24 @@ class Element
|
|
668 |
return implode($delimiter, $innerHtml);
|
669 |
}
|
670 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
671 |
/**
|
672 |
* Sets inner HTML.
|
673 |
*
|
@@ -743,7 +765,7 @@ class Element
|
|
743 |
$value = (string) $value;
|
744 |
}
|
745 |
|
746 |
-
if (!is_string($value)
|
747 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, (is_object($value) ? get_class($value) : gettype($value))));
|
748 |
}
|
749 |
|
@@ -753,33 +775,43 @@ class Element
|
|
753 |
}
|
754 |
|
755 |
/**
|
756 |
-
* Returns true if current node is DOMElement.
|
757 |
*
|
758 |
* @return bool
|
759 |
*/
|
760 |
public function isElementNode()
|
761 |
{
|
762 |
-
return $this->node instanceof
|
763 |
}
|
764 |
|
765 |
/**
|
766 |
-
* Returns true if current node is DOMText.
|
767 |
*
|
768 |
* @return bool
|
769 |
*/
|
770 |
public function isTextNode()
|
771 |
{
|
772 |
-
return $this->node instanceof
|
773 |
}
|
774 |
|
775 |
/**
|
776 |
-
* Returns true if current node is DOMComment.
|
777 |
*
|
778 |
* @return bool
|
779 |
*/
|
780 |
public function isCommentNode()
|
781 |
{
|
782 |
-
return $this->node instanceof
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
783 |
}
|
784 |
|
785 |
/**
|
@@ -813,7 +845,7 @@ class Element
|
|
813 |
return null;
|
814 |
}
|
815 |
|
816 |
-
if ($this->node->parentNode instanceof
|
817 |
return new Document($this->node->parentNode);
|
818 |
}
|
819 |
|
@@ -835,7 +867,7 @@ class Element
|
|
835 |
while (true) {
|
836 |
$parent = $node->parent();
|
837 |
|
838 |
-
if ($parent === null
|
839 |
return null;
|
840 |
}
|
841 |
|
@@ -863,11 +895,11 @@ class Element
|
|
863 |
return null;
|
864 |
}
|
865 |
|
866 |
-
if ($selector === null
|
867 |
return new Element($this->node->previousSibling);
|
868 |
}
|
869 |
|
870 |
-
if ($selector !== null
|
871 |
$nodeType = 'DOMElement';
|
872 |
}
|
873 |
|
@@ -875,13 +907,13 @@ class Element
|
|
875 |
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($nodeType)));
|
876 |
}
|
877 |
|
878 |
-
$allowedTypes = ['DOMElement', 'DOMText', 'DOMComment'];
|
879 |
|
880 |
-
if (!in_array($nodeType, $allowedTypes)) {
|
881 |
throw new RuntimeException(sprintf('Unknown node type "%s". Allowed types: %s', $nodeType, implode(', ', $allowedTypes)));
|
882 |
}
|
883 |
|
884 |
-
if ($selector !== null
|
885 |
throw new LogicException(sprintf('Selector can be used only with DOMElement node type, %s given', $nodeType));
|
886 |
}
|
887 |
|
@@ -926,7 +958,7 @@ class Element
|
|
926 |
return [];
|
927 |
}
|
928 |
|
929 |
-
if ($selector !== null
|
930 |
$nodeType = 'DOMElement';
|
931 |
}
|
932 |
|
@@ -935,14 +967,14 @@ class Element
|
|
935 |
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($nodeType)));
|
936 |
}
|
937 |
|
938 |
-
$allowedTypes = ['DOMElement', 'DOMText', 'DOMComment'];
|
939 |
|
940 |
-
if (!in_array($nodeType, $allowedTypes)) {
|
941 |
throw new RuntimeException(sprintf('Unknown node type "%s". Allowed types: %s', $nodeType, implode(', ', $allowedTypes)));
|
942 |
}
|
943 |
}
|
944 |
|
945 |
-
if ($selector !== null
|
946 |
throw new LogicException(sprintf('Selector can be used only with DOMElement node type, %s given', $nodeType));
|
947 |
}
|
948 |
|
@@ -1001,11 +1033,11 @@ class Element
|
|
1001 |
return null;
|
1002 |
}
|
1003 |
|
1004 |
-
if ($selector === null
|
1005 |
return new Element($this->node->nextSibling);
|
1006 |
}
|
1007 |
|
1008 |
-
if ($selector !== null
|
1009 |
$nodeType = 'DOMElement';
|
1010 |
}
|
1011 |
|
@@ -1013,13 +1045,13 @@ class Element
|
|
1013 |
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($nodeType)));
|
1014 |
}
|
1015 |
|
1016 |
-
$allowedTypes = ['DOMElement', 'DOMText', 'DOMComment'];
|
1017 |
|
1018 |
-
if (!in_array($nodeType, $allowedTypes)) {
|
1019 |
throw new RuntimeException(sprintf('Unknown node type "%s". Allowed types: %s', $nodeType, implode(', ', $allowedTypes)));
|
1020 |
}
|
1021 |
|
1022 |
-
if ($selector !== null
|
1023 |
throw new LogicException(sprintf('Selector can be used only with DOMElement node type, %s given', $nodeType));
|
1024 |
}
|
1025 |
|
@@ -1064,7 +1096,7 @@ class Element
|
|
1064 |
return [];
|
1065 |
}
|
1066 |
|
1067 |
-
if ($selector !== null
|
1068 |
$nodeType = 'DOMElement';
|
1069 |
}
|
1070 |
|
@@ -1073,14 +1105,14 @@ class Element
|
|
1073 |
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($nodeType)));
|
1074 |
}
|
1075 |
|
1076 |
-
$allowedTypes = ['DOMElement', 'DOMText', 'DOMComment'];
|
1077 |
|
1078 |
-
if (!in_array($nodeType, $allowedTypes)) {
|
1079 |
throw new RuntimeException(sprintf('Unknown node type "%s". Allowed types: %s', $nodeType, implode(', ', $allowedTypes)));
|
1080 |
}
|
1081 |
}
|
1082 |
|
1083 |
-
if ($selector !== null
|
1084 |
throw new LogicException(sprintf('Selector can be used only with DOMElement node type, %s given', $nodeType));
|
1085 |
}
|
1086 |
|
@@ -1124,6 +1156,8 @@ class Element
|
|
1124 |
}
|
1125 |
|
1126 |
/**
|
|
|
|
|
1127 |
* @return \DiDom\Element|null
|
1128 |
*/
|
1129 |
public function child($index)
|
@@ -1273,7 +1307,7 @@ class Element
|
|
1273 |
$newNode = $newNode->cloneNode(true);
|
1274 |
}
|
1275 |
|
1276 |
-
if ($newNode->ownerDocument === null
|
1277 |
$newNode = $this->node->ownerDocument->importNode($newNode, true);
|
1278 |
}
|
1279 |
|
@@ -1307,16 +1341,16 @@ class Element
|
|
1307 |
/**
|
1308 |
* Sets current node instance.
|
1309 |
*
|
1310 |
-
* @param \DOMElement|\DOMText|\DOMComment $node
|
1311 |
*
|
1312 |
* @return \DiDom\Element
|
1313 |
*/
|
1314 |
protected function setNode($node)
|
1315 |
{
|
1316 |
-
$allowedClasses = ['DOMElement', 'DOMText', 'DOMComment'];
|
1317 |
|
1318 |
-
if (!in_array(get_class($node), $allowedClasses)) {
|
1319 |
-
throw new InvalidArgumentException(sprintf('Argument 1 passed to %s must be an instance of DOMElement, DOMText or
|
1320 |
}
|
1321 |
|
1322 |
$this->node = $node;
|
@@ -1327,7 +1361,7 @@ class Element
|
|
1327 |
/**
|
1328 |
* Returns current node instance.
|
1329 |
*
|
1330 |
-
* @return \DOMElement|\DOMText|\DOMComment
|
1331 |
*/
|
1332 |
public function getNode()
|
1333 |
{
|
@@ -1386,13 +1420,11 @@ class Element
|
|
1386 |
*/
|
1387 |
public function __get($name)
|
1388 |
{
|
1389 |
-
|
1390 |
-
|
1391 |
-
return $this->node->tagName;
|
1392 |
-
break;
|
1393 |
-
default:
|
1394 |
-
return $this->getAttribute($name);
|
1395 |
}
|
|
|
|
|
1396 |
}
|
1397 |
|
1398 |
/**
|
2 |
|
3 |
namespace DiDom;
|
4 |
|
5 |
+
use DOMCdataSection;
|
6 |
+
use DOMComment;
|
7 |
use DOMDocument;
|
8 |
use DOMElement;
|
9 |
use DOMNode;
|
10 |
+
use DOMText;
|
11 |
use InvalidArgumentException;
|
12 |
use LogicException;
|
13 |
use RuntimeException;
|
20 |
/**
|
21 |
* The DOM element instance.
|
22 |
*
|
23 |
+
* @var \DOMElement|\DOMText|\DOMComment|\DOMCdataSection
|
24 |
*/
|
25 |
protected $node;
|
26 |
|
37 |
/**
|
38 |
* Constructor.
|
39 |
*
|
40 |
+
* @param \DOMElement|\DOMText|\DOMComment|\DOMCdataSection|string $tagName The tag name of the element
|
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 |
{
|
46 |
+
if (is_string($tagName)) {
|
47 |
$document = new DOMDocument('1.0', 'UTF-8');
|
48 |
|
49 |
+
$node = $document->createElement($tagName);
|
50 |
|
51 |
$this->setNode($node);
|
52 |
} else {
|
53 |
+
$this->setNode($tagName);
|
54 |
}
|
55 |
|
56 |
if ($value !== null) {
|
57 |
$this->setValue($value);
|
58 |
}
|
59 |
|
60 |
+
foreach ($attributes as $attrName => $attrValue) {
|
61 |
+
$this->setAttribute($attrName, $attrValue);
|
62 |
}
|
63 |
}
|
64 |
|
65 |
/**
|
66 |
+
* Creates a new element.
|
67 |
*
|
68 |
* @param \DOMNode|string $name The tag name of the element
|
69 |
* @param string|null $value The value of the element
|
77 |
}
|
78 |
|
79 |
/**
|
80 |
+
* Creates a new element node by CSS selector.
|
81 |
*
|
82 |
* @param string $selector
|
83 |
* @param string|null $value
|
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 |
*
|
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 |
*
|
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 |
|
174 |
|
175 |
Errors::restore();
|
176 |
|
177 |
+
$result = array_map(function (DOMNode $node) {
|
178 |
return new Element($node);
|
179 |
}, $result);
|
180 |
|
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 |
|
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 |
}
|
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 |
|
375 |
*
|
376 |
* @return bool
|
377 |
*
|
378 |
+
* @throws \InvalidArgumentException if the tag name is not a string
|
379 |
+
* @throws \RuntimeException if the tag name is not specified in strict mode
|
380 |
*/
|
381 |
public function matches($selector, $strict = false)
|
382 |
{
|
384 |
throw new InvalidArgumentException(sprintf('%s expects parameter 1 to be string, %s given', __METHOD__, gettype($selector)));
|
385 |
}
|
386 |
|
387 |
+
if (!$this->node instanceof DOMElement) {
|
388 |
return false;
|
389 |
}
|
390 |
|
396 |
$innerHtml = $this->html();
|
397 |
$html = "<root>$innerHtml</root>";
|
398 |
|
399 |
+
$selector = 'root > ' . trim($selector);
|
400 |
|
401 |
$document = new Document();
|
402 |
|
411 |
throw new RuntimeException(sprintf('Tag name must be specified in %s', $selector));
|
412 |
}
|
413 |
|
414 |
+
if ($segments['tag'] !== $this->tag && $segments['tag'] !== '*') {
|
415 |
return false;
|
416 |
}
|
417 |
|
428 |
$diff1 = array_diff($segments['classes'], $classes);
|
429 |
$diff2 = array_diff($classes, $segments['classes']);
|
430 |
|
431 |
+
if (count($diff1) > 0 || count($diff2) > 0) {
|
432 |
return false;
|
433 |
}
|
434 |
|
435 |
$attributes = $this->attributes();
|
436 |
|
437 |
+
unset($attributes['id'], $attributes['class']);
|
|
|
438 |
|
439 |
$segments['attributes'] = array_key_exists('attributes', $segments) ? $segments['attributes'] : [];
|
440 |
|
441 |
$diff1 = array_diff_assoc($segments['attributes'], $attributes);
|
442 |
$diff2 = array_diff_assoc($attributes, $segments['attributes']);
|
443 |
|
444 |
+
// if the attributes are not equal
|
445 |
+
if (count($diff1) > 0 || count($diff2) > 0) {
|
446 |
return false;
|
447 |
}
|
448 |
|
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 |
|
529 |
}
|
530 |
|
531 |
foreach ($this->attributes() as $name => $value) {
|
532 |
+
if (in_array($name, $exclusions, true)) {
|
533 |
continue;
|
534 |
}
|
535 |
|
582 |
$result = [];
|
583 |
|
584 |
foreach ($this->node->attributes as $name => $attribute) {
|
585 |
+
if (in_array($name, $names, true)) {
|
586 |
$result[$name] = $attribute->value;
|
587 |
}
|
588 |
}
|
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 |
*
|
765 |
$value = (string) $value;
|
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 |
|
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 |
+
* Returns true if current node is a a DOMText instance.
|
789 |
*
|
790 |
* @return bool
|
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 isCommentNode()
|
803 |
{
|
804 |
+
return $this->node instanceof DOMComment;
|
805 |
+
}
|
806 |
+
|
807 |
+
/**
|
808 |
+
* Returns true if current node is a DOMCdataSection instance.
|
809 |
+
*
|
810 |
+
* @return bool
|
811 |
+
*/
|
812 |
+
public function isCdataSectionNode()
|
813 |
+
{
|
814 |
+
return $this->node instanceof DOMCdataSection;
|
815 |
}
|
816 |
|
817 |
/**
|
845 |
return null;
|
846 |
}
|
847 |
|
848 |
+
if ($this->node->parentNode instanceof DOMDocument) {
|
849 |
return new Document($this->node->parentNode);
|
850 |
}
|
851 |
|
867 |
while (true) {
|
868 |
$parent = $node->parent();
|
869 |
|
870 |
+
if ($parent === null || $parent instanceof Document) {
|
871 |
return null;
|
872 |
}
|
873 |
|
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 |
|
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 |
|
958 |
return [];
|
959 |
}
|
960 |
|
961 |
+
if ($selector !== null && $nodeType === null) {
|
962 |
$nodeType = 'DOMElement';
|
963 |
}
|
964 |
|
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 |
|
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 |
|
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 |
|
1096 |
return [];
|
1097 |
}
|
1098 |
|
1099 |
+
if ($selector !== null && $nodeType === null) {
|
1100 |
$nodeType = 'DOMElement';
|
1101 |
}
|
1102 |
|
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 |
|
1156 |
}
|
1157 |
|
1158 |
/**
|
1159 |
+
* @param int $index
|
1160 |
+
*
|
1161 |
* @return \DiDom\Element|null
|
1162 |
*/
|
1163 |
public function child($index)
|
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 |
|
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;
|
1361 |
/**
|
1362 |
* Returns current node instance.
|
1363 |
*
|
1364 |
+
* @return \DOMElement|\DOMText|\DOMComment|\DOMCdataSection
|
1365 |
*/
|
1366 |
public function getNode()
|
1367 |
{
|
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 |
/**
|
vendor/imangazaliev/didom/src/DiDom/Encoder.php
CHANGED
@@ -50,7 +50,7 @@ class Encoder
|
|
50 |
$code = (($codes[$characterIndex++] - 0xC0) << 6) + $codes[$characterIndex++] - 0x80;
|
51 |
}
|
52 |
|
53 |
-
$entities .= '&#'
|
54 |
}
|
55 |
|
56 |
return $entities;
|
50 |
$code = (($codes[$characterIndex++] - 0xC0) << 6) + $codes[$characterIndex++] - 0x80;
|
51 |
}
|
52 |
|
53 |
+
$entities .= '&#' . $code . ';';
|
54 |
}
|
55 |
|
56 |
return $entities;
|
vendor/imangazaliev/didom/src/DiDom/Query.php
CHANGED
@@ -41,7 +41,7 @@ class Query
|
|
41 |
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($type)));
|
42 |
}
|
43 |
|
44 |
-
if (strcasecmp($type, self::TYPE_XPATH) !== 0
|
45 |
throw new RuntimeException(sprintf('Unknown expression type "%s"', $type));
|
46 |
}
|
47 |
|
@@ -110,7 +110,7 @@ class Query
|
|
110 |
$selector = trim(substr($selector, strlen($segments['selector'])));
|
111 |
$prefix = isset($segments['rel']) ? '/' : '//';
|
112 |
|
113 |
-
if ($selector === ''
|
114 |
break;
|
115 |
}
|
116 |
|
@@ -143,7 +143,7 @@ class Query
|
|
143 |
$name = '(?P<name>[\w\-]+)';
|
144 |
$args = '(?:\((?P<args>[^\)]+)?\))?';
|
145 |
|
146 |
-
$regexp = '/^::'
|
147 |
|
148 |
if (preg_match($regexp, $selector, $matches) !== 1) {
|
149 |
throw new InvalidSelectorException(sprintf('Invalid property "%s"', $selector));
|
@@ -224,8 +224,8 @@ class Query
|
|
224 |
return self::convertContains($string);
|
225 |
}
|
226 |
|
227 |
-
if ($parameters[1] !== 'true'
|
228 |
-
throw new InvalidSelectorException(sprintf('Parameter 2 of "contains" pseudo-class
|
229 |
}
|
230 |
|
231 |
$caseSensitive = $parameters[1] === 'true';
|
@@ -234,8 +234,8 @@ class Query
|
|
234 |
return self::convertContains($string, $caseSensitive);
|
235 |
}
|
236 |
|
237 |
-
if ($parameters[2] !== 'true'
|
238 |
-
throw new InvalidSelectorException(sprintf('Parameter 3 of "contains" pseudo-class
|
239 |
}
|
240 |
|
241 |
$fullMatch = $parameters[2] === 'true';
|
@@ -305,11 +305,11 @@ class Query
|
|
305 |
$attributes[] = self::convertPseudo($segments['pseudo'], $tagName, $parameters);
|
306 |
}
|
307 |
|
308 |
-
if (count($attributes) === 0
|
309 |
-
throw new InvalidArgumentException('The array of segments
|
310 |
}
|
311 |
|
312 |
-
$xpath = $prefix
|
313 |
|
314 |
if ($count = count($attributes)) {
|
315 |
$xpath .= ($count > 1) ? sprintf('[(%s)]', implode(') and (', $attributes)) : sprintf('[%s]', $attributes[0]);
|
@@ -326,8 +326,8 @@ class Query
|
|
326 |
*/
|
327 |
protected static function convertAttribute($name, $value)
|
328 |
{
|
329 |
-
$isSimpleSelector = !in_array(substr($name, 0, 1), ['^', '!']);
|
330 |
-
$isSimpleSelector = $isSimpleSelector && (!in_array(substr($name, -1), ['^', '$', '*', '!', '~']));
|
331 |
|
332 |
if ($isSimpleSelector) {
|
333 |
// if specified only the attribute name
|
@@ -407,7 +407,7 @@ class Query
|
|
407 |
if (preg_match("/^(?P<mul>[0-9]?n)(?:(?P<sign>\+|\-)(?P<pos>[0-9]+))?$/is", $expression, $segments)) {
|
408 |
if (isset($segments['mul'])) {
|
409 |
$multiplier = $segments['mul'] === 'n' ? 1 : trim($segments['mul'], 'n');
|
410 |
-
$sign = (isset($segments['sign'])
|
411 |
$position = isset($segments['pos']) ? $segments['pos'] : 0;
|
412 |
|
413 |
return sprintf('(position() %s %d) mod %d = 0 and position() >= %d', $sign, $position, $multiplier, $position);
|
@@ -426,17 +426,17 @@ class Query
|
|
426 |
*/
|
427 |
protected static function convertContains($string, $caseSensitive = true, $fullMatch = false)
|
428 |
{
|
429 |
-
if ($caseSensitive
|
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 (!$caseSensitive
|
440 |
return sprintf("php:functionString(\"{$strToLowerFunction}\", .) = php:functionString(\"{$strToLowerFunction}\", \"%s\")", $string);
|
441 |
}
|
442 |
|
@@ -479,12 +479,12 @@ class Query
|
|
479 |
|
480 |
$result['selector'] = $segments[0];
|
481 |
|
482 |
-
if (isset($segments['tag'])
|
483 |
$result['tag'] = $segments['tag'];
|
484 |
}
|
485 |
|
486 |
// if the id attribute specified
|
487 |
-
if (isset($segments['id'])
|
488 |
$result['id'] = $segments['id'];
|
489 |
}
|
490 |
|
@@ -520,10 +520,10 @@ class Query
|
|
520 |
}
|
521 |
|
522 |
// if the pseudo class specified
|
523 |
-
if (isset($segments['pseudo'])
|
524 |
$result['pseudo'] = $segments['pseudo'];
|
525 |
|
526 |
-
if (isset($segments['expr'])
|
527 |
$result['expr'] = $segments['expr'];
|
528 |
}
|
529 |
}
|
41 |
throw new InvalidArgumentException(sprintf('%s expects parameter 2 to be string, %s given', __METHOD__, gettype($type)));
|
42 |
}
|
43 |
|
44 |
+
if (strcasecmp($type, self::TYPE_XPATH) !== 0 && strcasecmp($type, self::TYPE_CSS) !== 0) {
|
45 |
throw new RuntimeException(sprintf('Unknown expression type "%s"', $type));
|
46 |
}
|
47 |
|
110 |
$selector = trim(substr($selector, strlen($segments['selector'])));
|
111 |
$prefix = isset($segments['rel']) ? '/' : '//';
|
112 |
|
113 |
+
if ($selector === '' || substr($selector, 0, 2) === '::' || substr($selector, 0, 1) === ',') {
|
114 |
break;
|
115 |
}
|
116 |
|
143 |
$name = '(?P<name>[\w\-]+)';
|
144 |
$args = '(?:\((?P<args>[^\)]+)?\))?';
|
145 |
|
146 |
+
$regexp = '/^::' . $name . $args . '/is';
|
147 |
|
148 |
if (preg_match($regexp, $selector, $matches) !== 1) {
|
149 |
throw new InvalidSelectorException(sprintf('Invalid property "%s"', $selector));
|
224 |
return self::convertContains($string);
|
225 |
}
|
226 |
|
227 |
+
if ($parameters[1] !== 'true' && $parameters[1] !== 'false') {
|
228 |
+
throw new InvalidSelectorException(sprintf('Parameter 2 of "contains" pseudo-class must be equal true or false, "%s" given', $parameters[1]));
|
229 |
}
|
230 |
|
231 |
$caseSensitive = $parameters[1] === 'true';
|
234 |
return self::convertContains($string, $caseSensitive);
|
235 |
}
|
236 |
|
237 |
+
if ($parameters[2] !== 'true' && $parameters[2] !== 'false') {
|
238 |
+
throw new InvalidSelectorException(sprintf('Parameter 3 of "contains" pseudo-class must be equal true or false, "%s" given', $parameters[2]));
|
239 |
}
|
240 |
|
241 |
$fullMatch = $parameters[2] === 'true';
|
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 |
|
312 |
+
$xpath = $prefix . $tagName;
|
313 |
|
314 |
if ($count = count($attributes)) {
|
315 |
$xpath .= ($count > 1) ? sprintf('[(%s)]', implode(') and (', $attributes)) : sprintf('[%s]', $attributes[0]);
|
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
|
407 |
if (preg_match("/^(?P<mul>[0-9]?n)(?:(?P<sign>\+|\-)(?P<pos>[0-9]+))?$/is", $expression, $segments)) {
|
408 |
if (isset($segments['mul'])) {
|
409 |
$multiplier = $segments['mul'] === 'n' ? 1 : trim($segments['mul'], 'n');
|
410 |
+
$sign = (isset($segments['sign']) && $segments['sign'] === '+') ? '-' : '+';
|
411 |
$position = isset($segments['pos']) ? $segments['pos'] : 0;
|
412 |
|
413 |
return sprintf('(position() %s %d) mod %d = 0 and position() >= %d', $sign, $position, $multiplier, $position);
|
426 |
*/
|
427 |
protected static function convertContains($string, $caseSensitive = true, $fullMatch = false)
|
428 |
{
|
429 |
+
if ($caseSensitive && $fullMatch) {
|
430 |
return sprintf('text() = "%s"', $string);
|
431 |
}
|
432 |
|
433 |
+
if ($caseSensitive && !$fullMatch) {
|
434 |
return sprintf('contains(text(), "%s")', $string);
|
435 |
}
|
436 |
|
437 |
$strToLowerFunction = function_exists('mb_strtolower') ? 'mb_strtolower' : 'strtolower';
|
438 |
|
439 |
+
if (!$caseSensitive && $fullMatch) {
|
440 |
return sprintf("php:functionString(\"{$strToLowerFunction}\", .) = php:functionString(\"{$strToLowerFunction}\", \"%s\")", $string);
|
441 |
}
|
442 |
|
479 |
|
480 |
$result['selector'] = $segments[0];
|
481 |
|
482 |
+
if (isset($segments['tag']) && $segments['tag'] !== '') {
|
483 |
$result['tag'] = $segments['tag'];
|
484 |
}
|
485 |
|
486 |
// if the id attribute specified
|
487 |
+
if (isset($segments['id']) && $segments['id'] !== '') {
|
488 |
$result['id'] = $segments['id'];
|
489 |
}
|
490 |
|
520 |
}
|
521 |
|
522 |
// if the pseudo class specified
|
523 |
+
if (isset($segments['pseudo']) && $segments['pseudo'] !== '') {
|
524 |
$result['pseudo'] = $segments['pseudo'];
|
525 |
|
526 |
+
if (isset($segments['expr']) && $segments['expr'] !== '') {
|
527 |
$result['expr'] = $segments['expr'];
|
528 |
}
|
529 |
}
|
vendor/imangazaliev/didom/src/DiDom/StyleAttribute.php
CHANGED
@@ -33,7 +33,7 @@ class StyleAttribute
|
|
33 |
public function __construct(Element $element)
|
34 |
{
|
35 |
if (!$element->isElementNode()) {
|
36 |
-
throw new InvalidArgumentException(sprintf('The element
|
37 |
}
|
38 |
|
39 |
$this->element = $element;
|
@@ -102,7 +102,7 @@ class StyleAttribute
|
|
102 |
$properties = [];
|
103 |
|
104 |
foreach ($this->properties as $propertyName => $value) {
|
105 |
-
$properties[] = $propertyName.': '
|
106 |
}
|
107 |
|
108 |
return implode('; ', $properties);
|
33 |
public function __construct(Element $element)
|
34 |
{
|
35 |
if (!$element->isElementNode()) {
|
36 |
+
throw new InvalidArgumentException(sprintf('The element must contain DOMElement node'));
|
37 |
}
|
38 |
|
39 |
$this->element = $element;
|
102 |
$properties = [];
|
103 |
|
104 |
foreach ($this->properties as $propertyName => $value) {
|
105 |
+
$properties[] = $propertyName . ': ' . $value;
|
106 |
}
|
107 |
|
108 |
return implode('; ', $properties);
|
vendor/imangazaliev/didom/tests/DiDom/ClassAttributeTest.php
CHANGED
@@ -10,7 +10,7 @@ class ClassAttributeTest extends TestCase
|
|
10 |
{
|
11 |
/**
|
12 |
* @expectedException \InvalidArgumentException
|
13 |
-
* @expectedExceptionMessage The element
|
14 |
*/
|
15 |
public function testConstructorWithTextNode()
|
16 |
{
|
@@ -21,7 +21,7 @@ class ClassAttributeTest extends TestCase
|
|
21 |
|
22 |
/**
|
23 |
* @expectedException \InvalidArgumentException
|
24 |
-
* @expectedExceptionMessage The element
|
25 |
*/
|
26 |
public function testConstructorWithCommentNode()
|
27 |
{
|
10 |
{
|
11 |
/**
|
12 |
* @expectedException \InvalidArgumentException
|
13 |
+
* @expectedExceptionMessage The element must contain DOMElement node
|
14 |
*/
|
15 |
public function testConstructorWithTextNode()
|
16 |
{
|
21 |
|
22 |
/**
|
23 |
* @expectedException \InvalidArgumentException
|
24 |
+
* @expectedExceptionMessage The element must contain DOMElement node
|
25 |
*/
|
26 |
public function testConstructorWithCommentNode()
|
27 |
{
|
vendor/imangazaliev/didom/tests/DiDom/DocumentTest.php
CHANGED
@@ -120,6 +120,39 @@ class DocumentTest extends TestCase
|
|
120 |
$this->assertEquals(['name' => 'name', 'placeholder' => 'Enter your name'], $element->attributes());
|
121 |
}
|
122 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
/**
|
124 |
* @expectedException \InvalidArgumentException
|
125 |
* @expectedExceptionMessage Argument 1 passed to DiDom\Document::appendChild must be an instance of DiDom\Element or DOMNode, string given
|
@@ -400,6 +433,26 @@ class DocumentTest extends TestCase
|
|
400 |
$this->assertEquals(['Link 1', 'Link 2', 'Link 3'], $texts);
|
401 |
}
|
402 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
403 |
public function testFindAttribute()
|
404 |
{
|
405 |
$html = $this->loadFixture('menu.html');
|
@@ -494,6 +547,16 @@ class DocumentTest extends TestCase
|
|
494 |
$this->assertEquals(0, $document->count('li'));
|
495 |
}
|
496 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
497 |
public function testHtml()
|
498 |
{
|
499 |
$html = '
|
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
|
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');
|
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 = '
|
vendor/imangazaliev/didom/tests/DiDom/ElementTest.php
CHANGED
@@ -12,11 +12,27 @@ class ElementTest extends TestCase
|
|
12 |
/**
|
13 |
* @expectedException \InvalidArgumentException
|
14 |
*/
|
15 |
-
public function
|
16 |
{
|
17 |
new Element(null);
|
18 |
}
|
19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
/**
|
21 |
* @expectedException \InvalidArgumentException
|
22 |
*/
|
@@ -870,6 +886,28 @@ Tiếng Việt <br>
|
|
870 |
$this->assertEquals($expectedContent, $document->first('body')->innerHtml());
|
871 |
}
|
872 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
873 |
public function testSetInnerHtml()
|
874 |
{
|
875 |
$list = new Element('ul');
|
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 |
*/
|
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');
|
vendor/imangazaliev/didom/tests/DiDom/QueryTest.php
CHANGED
@@ -116,7 +116,7 @@ class QueryTest extends TestCase
|
|
116 |
*/
|
117 |
public function testContainsInvalidCaseSensitiveParameter($caseSensitive)
|
118 |
{
|
119 |
-
$message = sprintf('Parameter 2 of "contains" pseudo-class
|
120 |
|
121 |
$this->setExpectedException('DiDom\Exceptions\InvalidSelectorException', $message);
|
122 |
|
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 |
|
vendor/imangazaliev/didom/tests/DiDom/StyleAttributeTest.php
CHANGED
@@ -10,7 +10,7 @@ class StyleAttributeTest extends TestCase
|
|
10 |
{
|
11 |
/**
|
12 |
* @expectedException \InvalidArgumentException
|
13 |
-
* @expectedExceptionMessage The element
|
14 |
*/
|
15 |
public function testConstructorWithTextNode()
|
16 |
{
|
@@ -21,7 +21,7 @@ class StyleAttributeTest extends TestCase
|
|
21 |
|
22 |
/**
|
23 |
* @expectedException \InvalidArgumentException
|
24 |
-
* @expectedExceptionMessage The element
|
25 |
*/
|
26 |
public function testConstructorWithCommentNode()
|
27 |
{
|
10 |
{
|
11 |
/**
|
12 |
* @expectedException \InvalidArgumentException
|
13 |
+
* @expectedExceptionMessage The element must contain DOMElement node
|
14 |
*/
|
15 |
public function testConstructorWithTextNode()
|
16 |
{
|
21 |
|
22 |
/**
|
23 |
* @expectedException \InvalidArgumentException
|
24 |
+
* @expectedExceptionMessage The element must contain DOMElement node
|
25 |
*/
|
26 |
public function testConstructorWithCommentNode()
|
27 |
{
|
vendor/imangazaliev/didom/tests/fixtures/books.xml
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
<?xml version="1.0"?>
|
2 |
<catalog>
|
3 |
<book id="bk101">
|
4 |
<author>Gambardella, Matthew</author>
|
1 |
+
<?xml version="1.0" encoding="utf-8"?>
|
2 |
<catalog>
|
3 |
<book id="bk101">
|
4 |
<author>Gambardella, Matthew</author>
|
vendor/imangazaliev/didom/tests/fixtures/menu.html
CHANGED
@@ -7,8 +7,9 @@
|
|
7 |
<body>
|
8 |
<ul>
|
9 |
<li><a href="http://example.com">Link 1</a></li>
|
10 |
-
<li><a href="http://example.com">Link 2
|
11 |
-
<li><a href="http://example.com">Link 3
|
12 |
</ul>
|
|
|
13 |
</body>
|
14 |
</html>
|
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>
|