zend-blog-3-backend

Форк
0
/
ExternalLinkProcessor.php 
170 строк · 4.2 Кб
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: morontt
5
 * Date: 20.04.18
6
 * Time: 1:41
7
 */
8

9
namespace App\Utils;
10

11
class ExternalLinkProcessor
12
{
13
    /**
14
     * @var array
15
     */
16
    protected $hrefs = [];
17

18
    /**
19
     * @var array
20
     */
21
    protected $replaces = [];
22

23
    /**
24
     * @var array
25
     */
26
    protected $internalHosts;
27

28
    /**
29
     * @param array $hosts
30
     */
31
    public function __construct(array $hosts = [])
32
    {
33
        $this->internalHosts = $hosts;
34
    }
35

36
    /**
37
     * @param string|null $content
38
     *
39
     * @return string|null
40
     */
41
    public function upgradeLinks(string $content = null): ?string
42
    {
43
        if ($content === null) {
44
            return null;
45
        }
46

47
        $this->hrefs = [];
48
        $this->replaces = [];
49

50
        $oldHash = sha1($content);
51

52
        $content0 = $content;
53
        $fuse = 0;
54
        do {
55
            $r = $this->externalLinksProcessing($content0);
56
            $fuse++;
57
        } while ($r && $fuse < 200);
58

59
        if (count($this->hrefs)) {
60
            $content1 = $content;
61
            $fuse = 0;
62
            do {
63
                $r = $this->linksAndAttributeProcessing($content1);
64
                $fuse++;
65
            } while ($r && $fuse < 200);
66

67
            foreach ($this->replaces as $replacePair) {
68
                $content = str_replace($replacePair['old'], $replacePair['new'], $content);
69
            }
70

71
            return ($oldHash === sha1($content)) ? null : $content;
72
        }
73

74
        return null;
75
    }
76

77
    /**
78
     * @param string $text
79
     *
80
     * @return bool
81
     */
82
    protected function externalLinksProcessing(&$text): bool
83
    {
84
        $result = false;
85
        $matches = [];
86

87
        $pattern = '/href="(?P<url>https?:\/\/(?P<host>[^\/]+)(\/?[^"]*))"/';
88

89
        if (preg_match($pattern, $text, $matches)) {
90
            $result = true;
91

92
            if (!in_array($matches['host'], $this->internalHosts, true)) {
93
                $this->hrefs[] = ['url' => $matches['url'], 'host' => $matches['host']];
94
            }
95

96
            $text = str_replace('href="' . $matches['url'] . '"', '', $text);
97
        }
98

99
        return $result;
100
    }
101

102
    /**
103
     * @param string $text
104
     *
105
     * @return bool
106
     */
107
    protected function linksAndAttributeProcessing(&$text): bool
108
    {
109
        $result = false;
110
        $matches = [];
111

112
        $pattern = '/<a(?:\s+(?:[^>]+))>/';
113
        if (preg_match($pattern, $text, $matches)) {
114
            $result = true;
115

116
            $this->checkAttributes($matches[0]);
117

118
            $text = str_replace($matches[0], '', $text);
119
        }
120

121
        return $result;
122
    }
123

124
    /**
125
     * @param string $link
126
     */
127
    protected function checkAttributes(string $link): void
128
    {
129
        foreach ($this->hrefs as $externalLink) {
130
            if (strpos($link, $externalLink['url']) !== false) {
131
                $attributes = [];
132

133
                $linkItem = str_replace('>', '/>', $link);
134
                try {
135
                    $xml = simplexml_load_string($linkItem);
136
                    foreach ($xml->attributes() as $k => $v) {
137
                        $attributes[] = sprintf('%s="%s"', $k, (string)$v);
138
                    }
139
                } catch (\ErrorException $e) {
140
                    break;
141
                }
142

143
                $findRel = false;
144
                $newAttributes = [];
145
                foreach ($attributes as $attribute) {
146
                    $matches = [];
147
                    if (preg_match('/rel="([^"]+)"/', $attribute, $matches)) {
148
                        $findRel = true;
149
                        if (strpos($matches[1], 'nofollow') === false) {
150
                            $newAttributes[] = sprintf('rel="%s nofollow"', $matches[1]);
151
                        } else {
152
                            $newAttributes[] = $attribute;
153
                        }
154
                    } else {
155
                        $newAttributes[] = $attribute;
156
                    }
157
                }
158
                if (!$findRel) {
159
                    $newAttributes[] = 'rel="nofollow"';
160
                }
161

162
                $this->replaces[] = [
163
                    'old' => $link,
164
                    'new' => sprintf('<a %s>', implode(' ', $newAttributes)),
165
                ];
166
                break;
167
            }
168
        }
169
    }
170
}
171

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.