-
Notifications
You must be signed in to change notification settings - Fork 148
Expand file tree
/
Copy pathHtmlNodeUnfurlLink.class.php
More file actions
98 lines (81 loc) · 2.73 KB
/
HtmlNodeUnfurlLink.class.php
File metadata and controls
98 lines (81 loc) · 2.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<?php
namespace wcf\system\html\node;
use Laminas\Diactoros\Exception\InvalidArgumentException;
use Laminas\Diactoros\Uri;
use wcf\command\unfurl\url\FindOrCreateUnfurlUrl;
use wcf\util\DOMUtil;
use wcf\util\Url;
/**
* Helper class to unfurl link objects.
*
* @author Joshua Ruesweg
* @copyright 2001-2021 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @since 5.4
*/
class HtmlNodeUnfurlLink extends HtmlNodePlainLink
{
public const UNFURL_URL_ID_ATTRIBUTE_NAME = "data-unfurl-url-id";
/**
* Marks a link element with the UnfurlUrlID.
*/
public static function setUnfurl(HtmlNodePlainLink $link): void
{
if (!$link->isStandalone()) {
return;
}
try {
$uri = new Uri($link->href);
} catch (InvalidArgumentException) {
return;
}
$path = $uri->getPath();
if ($path !== '') {
// This is a simplified transformation that will only replace
// characters that are known to be always invalid in URIs and must
// be encoded at all times according to RFC 1738.
$path = \preg_replace_callback(
'~[^0-9a-zA-Z$-_.+!*\'(),;/?:@=&]~',
static fn(array $matches) => \rawurlencode($matches[0]),
$path
);
$uri = $uri->withPath($path);
// The above replacement excludes certain characters from the
// replacement that are conditionally unsafe.
if (!Url::is($uri->__toString())) {
return;
}
}
// Ignore non-standard ports.
if ($uri->getPort() !== null) {
return;
}
// Ignore non-HTTP schemes.
if (!\in_array($uri->getScheme(), ['http', 'https'])) {
return;
}
self::removeStyling($link);
$uri = self::lowercaseHostname($uri);
$urlID = self::findOrCreate($uri);
$link->link->setAttribute(self::UNFURL_URL_ID_ATTRIBUTE_NAME, (string)$urlID);
}
private static function removeStyling(HtmlNodePlainLink $element): void
{
if (!$element->aloneInParagraph) {
return;
}
foreach ($element->topLevelParent->childNodes as $child) {
DOMUtil::removeNode($child);
}
$element->topLevelParent->appendChild($element->link);
}
private static function lowercaseHostname(Uri $uri): Uri
{
return $uri->withHost(\mb_strtolower($uri->getHost()));
}
private static function findOrCreate(Uri $uri): int
{
$unfurlUrl = (new FindOrCreateUnfurlUrl($uri->__toString()))();
return $unfurlUrl->urlID;
}
}