Completed
Pull Request — master (#532)
by Daniel
04:11
created

UrlFormatter::truncate()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 1
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
namespace Coyote\Services\Parser\Parsers;
4
5
use Collective\Html\HtmlBuilder;
6
use Coyote\Services\Parser\Parsers\Parentheses\ParenthesesParser;
7
use TRegx\CleanRegex\Pattern;
8
use TRegx\SafeRegex\preg;
9
10
class UrlFormatter
11
{
12
    // http://daringfireball.net/2010/07/improved_regex_for_matching_urls
13
    // modified - removed part with parsing of parentheses, because that's
14
    // done by ParenthesesParser
15
    private const REGEXP_URL = '~\b(?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)[^\s<>]+[^\s`!(\[\]{};:\'".,<>?«»“”‘’]~i';
16
    private const TITLE_LEN = 64;
17
18
    /** @var string */
19
    private $host;
20
    /** @var HtmlBuilder */
21
    private $html;
22
    /** @var ParenthesesParser */
23
    private $parser;
24
25
    public function __construct(string $host, HtmlBuilder $html, ParenthesesParser $parser)
26
    {
27
        $this->host = $host;
28
        $this->html = $html;
29
        $this->parser = $parser;
30
    }
31
32
    public function parse(string $text): string
33
    {
34
        return preg::replace_callback(self::REGEXP_URL, function (array $match): string {
35
            return $this->processLink($match[0]);
36
        }, $text);
37
    }
38
39
    private function processLink(string $url): string
40
    {
41
        return join(array_map([$this, 'buildLink'], $this->parser->parse($url)));
42
    }
43
44
    private function buildLink(string $url): string
45
    {
46
        if (Pattern::pcre(self::REGEXP_URL)->test($url)) {
47
            return $this->html->link($this->prependSchema($url), $this->truncate($url));
48
        }
49
        return $url;
50
    }
51
52
    private function prependSchema(string $url): string
53
    {
54
        if (pattern('^[\w]+?://', 'i')->fails($url)) {
55
            return "http://$url";
56
        }
57
        return $url;
58
    }
59
60
    private function truncate(string $text): string
61
    {
62
        if (mb_strlen($text) < self::TITLE_LEN) {
63
            return $text;
64
        }
65
        if ($this->host === parse_url($text, PHP_URL_HOST)) {
66
            return $text;
67
        }
68
        return $this->truncateToLengthWith($text, self::TITLE_LEN, '[...]');
69
    }
70
71
    private function truncateToLengthWith(string $text, int $length, string $substitute): string
72
    {
73
        $padding = ($length - mb_strlen($substitute)) / 2;
74
        return mb_substr($text, 0, $padding) . $substitute . mb_substr($text, -$padding);
75
    }
76
}
77