Passed
Pull Request — master (#646)
by Daniel
14:35
created

UrlFormatter::truncate()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
nc 3
nop 1
dl 0
loc 11
rs 10
c 1
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\Match\Details\Detail;
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected T_MATCH, expecting T_STRING or '{' on line 7 at column 21
Loading history...
8
use TRegx\CleanRegex\Pattern;
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`!(\[\]{};:\'".,<>?«»“”‘’]';
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
    /** @var Pattern */
25
    private $urlPattern;
26
27
    public function __construct(string $host, HtmlBuilder $html, ParenthesesParser $parser)
28
    {
29
        $this->host = $host;
30
        $this->html = $html;
31
        $this->parser = $parser;
32
        $this->urlPattern = Pattern::of(self::REGEXP_URL, 'i');
33
    }
34
35
    public function parse(string $text): string
36
    {
37
        return $this->urlPattern->replace($text)->callback(fn(Detail $match) => $this->processLink($match->text()));
38
    }
39
40
    private function processLink(string $url): string
41
    {
42
        return join(array_map([$this, 'buildLink'], $this->parser->parse($url)));
43
    }
44
45
    private function buildLink(string $url): string
46
    {
47
        if ($this->urlPattern->test($url)) {
48
            return $this->html->link($this->prependSchema($url), $this->truncate($url));
49
        }
50
51
        return $url;
52
    }
53
54
    private function prependSchema(string $url): string
55
    {
56
        if (pattern('^[\w]+?://', 'i')->fails($url)) {
57
            return "http://$url";
58
        }
59
60
        return $url;
61
    }
62
63
    private function truncate(string $text): string
64
    {
65
        if (mb_strlen($text) < self::TITLE_LEN) {
66
            return $text;
67
        }
68
69
        if ($this->host === parse_url($text, PHP_URL_HOST)) {
70
            return $text;
71
        }
72
73
        return $this->truncateToLengthWith($text, self::TITLE_LEN, '[...]');
74
    }
75
76
    private function truncateToLengthWith(string $text, int $length, string $substitute): string
77
    {
78
        $padding = ($length - mb_strlen($substitute)) / 2;
79
80
        return mb_substr($text, 0, $padding) . $substitute . mb_substr($text, -$padding);
81
    }
82
}
83