OSDN Git Service

Добавлена возможность создавать новую запись предмета оборудования на основании уже...
[invent/invent.git] / vendor / symfony / dom-crawler / AbstractUriElement.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\DomCrawler;
13
14 /**
15  * Any HTML element that can link to an URI.
16  *
17  * @author Fabien Potencier <fabien@symfony.com>
18  */
19 abstract class AbstractUriElement
20 {
21     /**
22      * @var \DOMElement
23      */
24     protected $node;
25
26     /**
27      * @var string|null The method to use for the element
28      */
29     protected $method;
30
31     /**
32      * @var string The URI of the page where the element is embedded (or the base href)
33      */
34     protected $currentUri;
35
36     /**
37      * @param \DOMElement $node       A \DOMElement instance
38      * @param string      $currentUri The URI of the page where the link is embedded (or the base href)
39      * @param string|null $method     The method to use for the link (GET by default)
40      *
41      * @throws \InvalidArgumentException if the node is not a link
42      */
43     public function __construct(\DOMElement $node, string $currentUri = null, ?string $method = 'GET')
44     {
45         $this->setNode($node);
46         $this->method = $method ? strtoupper($method) : null;
47         $this->currentUri = $currentUri;
48
49         $elementUriIsRelative = null === parse_url(trim($this->getRawUri()), \PHP_URL_SCHEME);
50         $baseUriIsAbsolute = \in_array(strtolower(substr($this->currentUri, 0, 4)), ['http', 'file']);
51         if ($elementUriIsRelative && !$baseUriIsAbsolute) {
52             throw new \InvalidArgumentException(sprintf('The URL of the element is relative, so you must define its base URI passing an absolute URL to the constructor of the "%s" class ("%s" was passed).', __CLASS__, $this->currentUri));
53         }
54     }
55
56     /**
57      * Gets the node associated with this link.
58      *
59      * @return \DOMElement A \DOMElement instance
60      */
61     public function getNode()
62     {
63         return $this->node;
64     }
65
66     /**
67      * Gets the method associated with this link.
68      *
69      * @return string The method
70      */
71     public function getMethod()
72     {
73         return $this->method ?? 'GET';
74     }
75
76     /**
77      * Gets the URI associated with this link.
78      *
79      * @return string The URI
80      */
81     public function getUri()
82     {
83         $uri = trim($this->getRawUri());
84
85         // absolute URL?
86         if (null !== parse_url($uri, \PHP_URL_SCHEME)) {
87             return $uri;
88         }
89
90         // empty URI
91         if (!$uri) {
92             return $this->currentUri;
93         }
94
95         // an anchor
96         if ('#' === $uri[0]) {
97             return $this->cleanupAnchor($this->currentUri).$uri;
98         }
99
100         $baseUri = $this->cleanupUri($this->currentUri);
101
102         if ('?' === $uri[0]) {
103             return $baseUri.$uri;
104         }
105
106         // absolute URL with relative schema
107         if (0 === strpos($uri, '//')) {
108             return preg_replace('#^([^/]*)//.*$#', '$1', $baseUri).$uri;
109         }
110
111         $baseUri = preg_replace('#^(.*?//[^/]*)(?:\/.*)?$#', '$1', $baseUri);
112
113         // absolute path
114         if ('/' === $uri[0]) {
115             return $baseUri.$uri;
116         }
117
118         // relative path
119         $path = parse_url(substr($this->currentUri, \strlen($baseUri)), \PHP_URL_PATH);
120         $path = $this->canonicalizePath(substr($path, 0, strrpos($path, '/')).'/'.$uri);
121
122         return $baseUri.('' === $path || '/' !== $path[0] ? '/' : '').$path;
123     }
124
125     /**
126      * Returns raw URI data.
127      *
128      * @return string
129      */
130     abstract protected function getRawUri();
131
132     /**
133      * Returns the canonicalized URI path (see RFC 3986, section 5.2.4).
134      *
135      * @param string $path URI path
136      *
137      * @return string
138      */
139     protected function canonicalizePath($path)
140     {
141         if ('' === $path || '/' === $path) {
142             return $path;
143         }
144
145         if ('.' === substr($path, -1)) {
146             $path .= '/';
147         }
148
149         $output = [];
150
151         foreach (explode('/', $path) as $segment) {
152             if ('..' === $segment) {
153                 array_pop($output);
154             } elseif ('.' !== $segment) {
155                 $output[] = $segment;
156             }
157         }
158
159         return implode('/', $output);
160     }
161
162     /**
163      * Sets current \DOMElement instance.
164      *
165      * @param \DOMElement $node A \DOMElement instance
166      *
167      * @throws \LogicException If given node is not an anchor
168      */
169     abstract protected function setNode(\DOMElement $node);
170
171     /**
172      * Removes the query string and the anchor from the given uri.
173      */
174     private function cleanupUri(string $uri): string
175     {
176         return $this->cleanupQuery($this->cleanupAnchor($uri));
177     }
178
179     /**
180      * Remove the query string from the uri.
181      */
182     private function cleanupQuery(string $uri): string
183     {
184         if (false !== $pos = strpos($uri, '?')) {
185             return substr($uri, 0, $pos);
186         }
187
188         return $uri;
189     }
190
191     /**
192      * Remove the anchor from the uri.
193      */
194     private function cleanupAnchor(string $uri): string
195     {
196         if (false !== $pos = strpos($uri, '#')) {
197             return substr($uri, 0, $pos);
198         }
199
200         return $uri;
201     }
202 }