Test Failed
Push — feature-laravel-5.4 ( 2b4b90...5bfdc4 )
by Kirill
03:52
created

LaravelDocsRenderer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 8
nc 1
nop 1
dl 0
loc 18
rs 9.4285
c 1
b 0
f 0
1
<?php
2
/**
3
 * This file is part of laravel.su package.
4
 * For the full copyright and license information, please view the LICENSE
5
 * file that was distributed with this source code.
6
 */
7
declare(strict_types = 1);
8
9
namespace App\Services\ContentRenderer;
10
11
use cebe\markdown\Parser;
12
13
/**
14
 * Class LaravelDocsRenderer.
15
 */
16
class LaravelDocsRenderer extends MarkdownRenderer
17
{
18
    /**
19
     * LaravelDocsRenderer constructor.
20
     *
21
     * @param Parser $parser
22
     */
23
    public function __construct(Parser $parser)
24
    {
25
        parent::__construct($parser);
26
27
        // Remove unused content (headers and nav)
28
        $this->before($this->removeDocumentTitle());
29
        $this->before($this->removeLeadingNavigation());
30
31
        // Remove custom quotes
32
        $this->before($this->removeTipQuotes());
33
        $this->before($this->removeNoteQuotes());
34
35
        // Force hide anchors
36
        $this->before($this->hideExternalAnchors());
37
38
        // Cross-page navigation
39
        $this->before($this->fixDocsNavigationLinks());
40
    }
41
42
    /**
43
     * Исправляет ссылки в документации "/docs/{version}/..."
44
     *
45
     * TODO Надо это не забыть реализовать =)
46
     *
47
     * @return \Closure
48
     */
49
    private function fixDocsNavigationLinks(): \Closure
50
    {
51
        return function (string $body) {
52
            return $body;
53
        };
54
    }
55
56
    /**
57
     * Удаляет из исходного текста все вхождения "> {tip}"
58
     *
59
     * @return \Closure
60
     */
61
    private function removeTipQuotes(): \Closure
62
    {
63
        return function (string $body) {
64
            return preg_replace('/>\s+{\s*tip\s*}\s+/iu', '> ', $body);
65
        };
66
    }
67
68
    /**
69
     * Удаляет навигацию из начала документа
70
     *
71
     * @return \Closure
72
     */
73
    private function removeLeadingNavigation(): \Closure
74
    {
75
        return function (string $body) {
76
            /**
77
             * TODO This expression are vulnerable: ReDoS-based exploit. Probably we can improve and fix it?
78
             *
79
             * @see https://en.wikipedia.org/wiki/ReDoS
80
             */
81
            return preg_replace('/^(?:[\n\s]*\-.*?\n)+/isu', '', $body);
82
        };
83
    }
84
85
    /**
86
     * Удаляет из исходного текста все вхождения "> {note}"
87
     *
88
     * @return \Closure
89
     */
90
    private function removeNoteQuotes(): \Closure
91
    {
92
        return function (string $body) {
93
            return preg_replace('/>\s+{\s*note\s*}\s+/iu', '> ', $body);
94
        };
95
    }
96
97
    /**
98
     * Скрывает из исходного текста все вхождения "<a .... name="some">...</a>".
99
     * Требуется для избежания конфликтов с вёрсткой.
100
     *
101
     * @return \Closure
102
     */
103
    private function hideExternalAnchors(): \Closure
104
    {
105
        $replacement = '<a href="#" style="display: none;" name="$1"></a>';
106
107
        return function (string $body) use ($replacement) {
108
            return preg_replace('/<a.+?name="(.*?)".*?>.*?<\/a>/isu', $replacement, $body);
109
        };
110
    }
111
112
    /**
113
     * Удаляет из документа заголовки первого уровня, находящиеся в самом начале статьи
114
     *
115
     * @return \Closure
116
     */
117
    private function removeDocumentTitle(): \Closure
118
    {
119
        return function (string $body) {
120
            return preg_replace('/^[\s\n]+?#\s+?.*?\n/isu', '', $body);
121
        };
122
    }
123
}
124