Gallery Custom Links - Version 1.0.2

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 Icon 128x128 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 CHANGED
@@ -8,22 +8,25 @@
8
  "packages": [
9
  {
10
  "name": "imangazaliev/didom",
11
- "version": "1.13",
12
  "source": {
13
  "type": "git",
14
  "url": "https://github.com/Imangazaliev/DiDOM.git",
15
- "reference": "10c4033d56e599f09183959ed90bf17519b9e38b"
16
  },
17
  "dist": {
18
  "type": "zip",
19
- "url": "https://api.github.com/repos/Imangazaliev/DiDOM/zipball/10c4033d56e599f09183959ed90bf17519b9e38b",
20
- "reference": "10c4033d56e599f09183959ed90bf17519b9e38b",
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": "2017-12-08T15:20:07+00:00"
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.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.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
- foreach ( $html->find('.wp-block-gallery img') as $element )
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.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.13",
5
- "version_normalized": "1.13.0.0",
6
  "source": {
7
  "type": "git",
8
  "url": "https://github.com/Imangazaliev/DiDOM.git",
9
- "reference": "10c4033d56e599f09183959ed90bf17519b9e38b"
10
  },
11
  "dist": {
12
  "type": "zip",
13
- "url": "https://api.github.com/repos/Imangazaliev/DiDOM/zipball/10c4033d56e599f09183959ed90bf17519b9e38b",
14
- "reference": "10c4033d56e599f09183959ed90bf17519b9e38b",
15
  "shasum": ""
16
  },
17
  "require": {
 
 
18
  "php": ">=5.4"
19
  },
20
  "require-dev": {
 
21
  "phpunit/phpunit": "^4.8"
22
  },
23
- "time": "2017-12-08T15:20:07+00:00",
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
- При изменении, замене или удалении элемента, найденного в другом элементе, документ не будет изменен. Данное поведение связано с тем, что в методах `find()` и `first()` класса `Element` создается новый документ, в котором и производится поиск.
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
- **Внимание:** метод `findInDocument()` работает только для элементов, которые принадлежат какому-либо документу, либо созданых через `new Element(...)`. Если элемент не принадлежит к какому-либо документу, будет выброшено исключение `LogicException`;
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
- - [Creating a new element](#creating-a-new-element)
22
- - [Getting the name of an element](#getting-the-name-of-an-element)
23
- - [Getting parent element](#getting-parent-element)
24
- - [Getting sibling elements](#getting-sibling-elements)
25
- - [Getting the child elements](#getting-the-child-elements)
26
- - [Getting document](#getting-document)
27
- - [Working with element attributes](#working-with-element-attributes)
28
- - [Comparing elements](#comparing-elements)
29
- - [Adding a child element](#adding-a-child-element)
30
- - [Replacing element](#replacing-element)
31
- - [Removing element](#removing-element)
 
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 requests.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 should contain DOMElement node'));
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 in first parameter was passed to the file path
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
- * Create new document.
70
  *
71
- * @param string|null $string HTML or XML string or file path
72
- * @param bool $isFile Indicates that in first parameter was passed to the file path
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
- * Create new element node.
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
- $element = new Element($node, $value, $attributes);
97
-
98
- return $element;
99
  }
100
 
101
  /**
102
- * Create new element node by CSS selector.
103
  *
104
- * @param string $selector
105
  * @param string|null $value
106
- * @param array $attributes
107
  *
108
  * @return \DiDom\Element
109
  */
@@ -129,7 +132,37 @@ class Document
129
  }
130
 
131
  /**
132
- * Add new child at the end of the children.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 \DOMNode) {
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 (\DOMNode $node) {
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 (!is_integer($options)) {
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 $xpath->evaluate($expression);
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 \DOMElement) {
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 = '.'.$expression;
404
  }
405
  }
406
 
407
- $nodeList = $xpath->query($expression, $contextNode);
408
 
409
  $result = [];
410
 
@@ -435,8 +458,8 @@ class Document
435
  {
436
  $expression = Query::compile($expression, $type);
437
 
438
- if ($contextNode !== null and $type === Query::TYPE_CSS) {
439
- $expression = '.'.$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 an node in the DOM tree for a given XPath expression.
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
- $expression = Query::compile($expression, $type);
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 $name The tag name of the element
38
  * @param string|null $value The value of the element
39
  * @param array $attributes The attributes of the element
40
  */
41
- public function __construct($name, $value = null, array $attributes = [])
42
  {
43
- if (is_string($name)) {
44
  $document = new DOMDocument('1.0', 'UTF-8');
45
 
46
- $node = $document->createElement($name);
47
 
48
  $this->setNode($node);
49
  } else {
50
- $this->setNode($name);
51
  }
52
 
53
  if ($value !== null) {
54
  $this->setValue($value);
55
  }
56
 
57
- foreach ($attributes as $name => $value) {
58
- $this->setAttribute($name, $value);
59
  }
60
  }
61
 
62
  /**
63
- * Create new element.
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
- * Create new element node by CSS selector.
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 \DOMNode) {
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 (\DOMNode $node) {
175
  return new Element($node);
176
  }, $result);
177
 
@@ -200,7 +203,7 @@ class Element
200
  $node = $node->getNode();
201
  }
202
 
203
- if (!$node instanceof \DOMNode) {
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 \DOMNode) {
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 \DOMNode) {
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 \RuntimeException if tag name is not specified in strict mode
 
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 \DOMElement) {
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 and $segments['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 or count($diff2) > 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 (count($diff1) > 0 or count($diff2) > 0) {
 
442
  return false;
443
  }
444
 
@@ -471,7 +475,7 @@ class Element
471
  $value = (string) $value;
472
  }
473
 
474
- if (!is_string($value) and $value !== null) {
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) and $value !== null) {
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 \DOMElement;
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 \DOMText;
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 \DOMComment;
 
 
 
 
 
 
 
 
 
 
783
  }
784
 
785
  /**
@@ -813,7 +845,7 @@ class Element
813
  return null;
814
  }
815
 
816
- if ($this->node->parentNode instanceof \DOMDocument) {
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 or $parent instanceof Document) {
839
  return null;
840
  }
841
 
@@ -863,11 +895,11 @@ class Element
863
  return null;
864
  }
865
 
866
- if ($selector === null and $nodeType === null) {
867
  return new Element($this->node->previousSibling);
868
  }
869
 
870
- if ($selector !== null and $nodeType === 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 and $nodeType !== 'DOMElement') {
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 and $nodeType === 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 and $nodeType !== 'DOMElement') {
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 and $nodeType === null) {
1005
  return new Element($this->node->nextSibling);
1006
  }
1007
 
1008
- if ($selector !== null and $nodeType === 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 and $nodeType !== 'DOMElement') {
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 and $nodeType === 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 and $nodeType !== 'DOMElement') {
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 or !$this->getDocument()->is($newNode->ownerDocument)) {
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 DOMComment, %s given', __METHOD__, (is_object($node) ? get_class($node) : gettype($node))));
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
- switch ($name) {
1390
- case 'tag':
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 .= '&#'.$code.';';
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 and strcasecmp($type, self::TYPE_CSS) !== 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 === '' or substr($selector, 0, 2) === '::' or substr($selector, 0, 1) === ',') {
114
  break;
115
  }
116
 
@@ -143,7 +143,7 @@ class Query
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,8 +224,8 @@ class Query
224
  return self::convertContains($string);
225
  }
226
 
227
- if ($parameters[1] !== 'true' and $parameters[1] !== 'false') {
228
- throw new InvalidSelectorException(sprintf('Parameter 2 of "contains" pseudo-class should be equal true or false, "%s" given', $parameters[1]));
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' and $parameters[2] !== 'false') {
238
- throw new InvalidSelectorException(sprintf('Parameter 3 of "contains" pseudo-class should be equal true or false, "%s" given', $parameters[2]));
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 and !isset($segments['tag'])) {
309
- throw new InvalidArgumentException('The array of segments should 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,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']) and $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 and $fullMatch) {
430
  return sprintf('text() = "%s"', $string);
431
  }
432
 
433
- if ($caseSensitive and !$fullMatch) {
434
  return sprintf('contains(text(), "%s")', $string);
435
  }
436
 
437
  $strToLowerFunction = function_exists('mb_strtolower') ? 'mb_strtolower' : 'strtolower';
438
 
439
- if (!$caseSensitive and $fullMatch) {
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']) and $segments['tag'] !== '') {
483
  $result['tag'] = $segments['tag'];
484
  }
485
 
486
  // if the id attribute specified
487
- if (isset($segments['id']) and $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']) and $segments['pseudo'] !== '') {
524
  $result['pseudo'] = $segments['pseudo'];
525
 
526
- if (isset($segments['expr']) and $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 should contain DOMElement node'));
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.': '.$value;
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 should contain DOMElement node
14
  */
15
  public function testConstructorWithTextNode()
16
  {
@@ -21,7 +21,7 @@ class ClassAttributeTest extends TestCase
21
 
22
  /**
23
  * @expectedException \InvalidArgumentException
24
- * @expectedExceptionMessage The element should contain DOMElement node
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 testConstructorWithInvalidName()
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 should be equal true or false, "%s" given', $caseSensitive);
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 should contain DOMElement node
14
  */
15
  public function testConstructorWithTextNode()
16
  {
@@ -21,7 +21,7 @@ class StyleAttributeTest extends TestCase
21
 
22
  /**
23
  * @expectedException \InvalidArgumentException
24
- * @expectedExceptionMessage The element should contain DOMElement node
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</a></li>
11
- <li><a href="http://example.com">Link 3</a></li>
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>