1<?php
2
3/*
4 * This file is part of the league/commonmark package.
5 *
6 * (c) Colin O'Dell <colinodell@gmail.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace League\CommonMark\Input;
13
14use League\CommonMark\Exception\UnexpectedEncodingException;
15
16final class MarkdownInput implements MarkdownInputInterface
17{
18    /** @var array<int, string>|null */
19    private $lines;
20
21    /** @var string */
22    private $content;
23
24    /** @var int|null */
25    private $lineCount;
26
27    public function __construct(string $content)
28    {
29        if (!\mb_check_encoding($content, 'UTF-8')) {
30            throw new UnexpectedEncodingException('Unexpected encoding - UTF-8 or ASCII was expected');
31        }
32
33        $this->content = $content;
34    }
35
36    public function getContent(): string
37    {
38        return $this->content;
39    }
40
41    /**
42     * @return \Traversable<int, string>
43     */
44    public function getLines(): \Traversable
45    {
46        $this->splitLinesIfNeeded();
47
48        foreach ($this->lines as $lineNumber => $line) {
49            yield $lineNumber => $line;
50        }
51    }
52
53    public function getLineCount(): int
54    {
55        $this->splitLinesIfNeeded();
56
57        return $this->lineCount;
58    }
59
60    private function splitLinesIfNeeded(): void
61    {
62        if ($this->lines !== null) {
63            return;
64        }
65
66        $lines = \preg_split('/\r\n|\n|\r/', $this->content);
67        if ($lines === false) {
68            throw new UnexpectedEncodingException('Failed to split Markdown content by line');
69        }
70
71        $this->lines = $lines;
72
73        // Remove any newline which appears at the very end of the string.
74        // We've already split the document by newlines, so we can simply drop
75        // any empty element which appears on the end.
76        if (\end($this->lines) === '') {
77            \array_pop($this->lines);
78        }
79
80        $this->lineCount = \count($this->lines);
81    }
82}
83