Passed
Push — master ( dd2993...187472 )
by Frank
44s queued 11s
created

Marksimple::initDefaultRules()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 2
b 0
f 0
nc 2
nop 0
dl 0
loc 4
ccs 4
cts 4
cp 1
crap 2
rs 10
1
<?php # -*- coding: utf-8 -*-
2
declare(strict_types=1);
3
4
namespace Bueltge\Marksimple;
5
6
use Psr\Log\LoggerInterface;
7
use Psr\Log\NullLogger;
8
use Bueltge\Marksimple\Exception\InvalideFileException;
9
use Bueltge\Marksimple\Exception\UnknownRuleException;
10
use Bueltge\Marksimple\Rule\ElementRuleInterface;
11
12
class Marksimple
13
{
14
    /**
15
     * Error log level number
16
     *
17
     * @var integer
18
     */
19
    private $errorLogLevel = 200;
20
21
    /**
22
     * logger class
23
     *
24
     * @var LoggerInterface
25
     */
26
    private $logger;
27
28
    /**
29
     * Define the default rules.
30
     *
31
     * @var array
32
     */
33
    protected $defaultRules = [
34
        'header' => Rule\Header::class,
35
        'image' => Rule\Image::class,
36
        'link' => Rule\Link::class,
37
        'strong' => Rule\Strong::class,
38
        'italic' => Rule\Italic::class,
39
        'ul' => Rule\UnorderedList::class,
40
        'cleanuplist' => Rule\CleanUpList::class,
41
        'pre' => Rule\Pre::class,
42
        'cleanuppre' => Rule\CleanUpPre::class,
43
        'githubpre' => Rule\GithubPre::class,
44
        'code' => Rule\Code::class,
45
        'hr' => Rule\HorizontalLine::class,
46
        'br' => Rule\NewLine::class,
47
        'p' => Rule\Paragraph::class,
48
    ];
49
50
    /**
51
     * Store the tags that we parse and render to html.
52
     *
53
     * @var array
54
     */
55
    protected $rules = [];
56
57
    /**
58
     * Marksimple constructor.
59
     *
60
     * @param LoggerInterface|null $logger
61
     */
62 10
    public function __construct(LoggerInterface $logger = null)
63 10
    {
64 10
        $this->logger = $logger ?? new NullLogger();
65
66 10
        $this->initDefaultRules();
67 10
    }
68
69
    /**
70
     * Add default rules.
71
     */
72 10
    protected function initDefaultRules()
73 10
    {
74 10
        foreach ($this->defaultRules as $name => $class) {
75 10
            $this->addRule($name, new $class);
76
        }
77 10
    }
78
79
    /**
80
     * Add rule to parse content with an regex string.
81
     *
82
     * @param string $name
83
     * @param ElementRuleInterface $rule
84
     */
85 10
    public function addRule(string $name, ElementRuleInterface $rule)
86 10
    {
87 10
        $this->rules[$name] = $rule;
88 10
    }
89
90
    /**
91
     * Parse content from a markdown file.
92
     *
93
     * @param string $file The path to the file that we parse.
94
     *
95
     * @return string
96
     * @throws InvalideFileException
97
     */
98 2
    public function parseFile(string $file): string
99 2
    {
100 2
        if (!is_file($file)) {
101 1
            $errorMessage = sprintf('File "%s" does not exist.', $file);
102 1
            $this->logger->log($this->errorLogLevel, $errorMessage);
103 1
            throw new InvalideFileException($errorMessage);
104
        }
105
106 1
        if (!is_readable($file)) {
107 1
            $errorMessage = sprintf('File "%s" cannot be read.', $file);
108 1
            $this->logger->log($this->errorLogLevel, $errorMessage);
109 1
            throw new InvalideFileException($errorMessage);
110
        }
111
112
        return $this->parse((string) file_get_contents($file, true));
113
    }
114
115
    /**
116
     * Get the markdown formatted content.
117
     *
118
     * @param string $content
119
     *
120
     * @return string
121
     */
122 1
    public function parse(string $content): string
123 1
    {
124 1
        return array_reduce(
125 1
            $this->rules,
126
            function (string $content, ElementRuleInterface $rule): string {
127 1
                return $rule->parse($content);
128 1
            },
129
            $this->sanitize($content)
130
        );
131
    }
132
133
    /**
134
     * Filter the content for not necessary strings.
135
     *
136
     * @param string $content The content from the Markdown file.
137
     *
138
     * @return string
139
     */
140
    protected function sanitize(string $content): string
141
    {
142
        // Add new line to get the first character of a string.
143
        $content = "\n" . $content;
144
145
        // Standardize line breaks.
146
        $content = str_replace(["\n\n", "\r\n", "\r"], "\n", $content);
147
148
        // Remove surrounding line breaks.
149
        $content = trim($content, "\n");
150
151
        // Filter html.
152
        $content = htmlentities($content, ENT_NOQUOTES, 'UTF-8');
153
154
        return $content;
155
    }
156
157
    /**
158
     * @param string $name
159
     *
160
     * @throws UnknownRuleException
161
     *
162
     * @return bool
163
     */
164 2
    public function removeRule(string $name): bool
165 2
    {
166 1
        if (!$this->hasRule($name)) {
167 1
            throw new UnknownRuleException(
168 1
                sprintf(
169 1
                    'No rule found for the given name "%s".',
170
                    $name
171
                )
172
            );
173
        }
174
175
        unset($this->rules[$name]);
176
177
        return true;
178
    }
179
180
    /**
181
     * @param string $name
182
     *
183
     * @return bool
184
     */
185 3
    public function hasRule(string $name): bool
186 3
    {
187
        return isset($this->rules[$name]);
188
    }
189
190
    /**
191
     * Remove all rules, reset the variable that store the rules.
192
     *
193
     * @return bool
194
     */
195 1
    public function removeAllRules(): bool
196 1
    {
197
        $this->rules = [];
198
199
        return true;
200
    }
201
202
    /**
203
     * Get the logger class instance
204
     *
205
     * @return LoggerInterface
206
     */
207 2
    public function logger(): LoggerInterface
208 2
    {
209
        return $this->logger;
210
    }
211
}
212