Passed
Push — master ( 6a0eb4...c7f34a )
by Caen
03:47 queued 13s
created

SourceFileParser::constructDynamicData()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 6
rs 10
1
<?php
2
3
namespace Hyde\Framework\Actions;
4
5
use Hyde\Framework\Concerns\ValidatesExistence;
6
use Hyde\Framework\Contracts\AbstractMarkdownPage;
7
use Hyde\Framework\Contracts\PageContract;
8
use Hyde\Framework\Hyde;
9
use Hyde\Framework\Models\Pages\BladePage;
10
use Hyde\Framework\Models\Pages\DocumentationPage;
11
use Hyde\Framework\Modules\Markdown\MarkdownFileParser;
12
use Illuminate\Support\Str;
13
14
/**
15
 * Parses a source file and returns a new page model instance for it.
16
 *
17
 * Page Parsers are responsible for parsing a source file into a Page object,
18
 * and may also conduct pre-processing and/or data validation/assembly.
19
 *
20
 * Note that the Page Parsers do not compile any HTML or Markdown.
21
 *
22
 * @see \Hyde\Framework\Testing\Feature\SourceFileParserTest
23
 */
24
class SourceFileParser
25
{
26
    use ValidatesExistence;
27
28
    protected string $slug;
29
    protected PageContract $page;
30
31
    public function __construct(string $pageClass, string $slug)
32
    {
33
        $this->validateExistence($pageClass, $slug);
34
        $this->slug = $slug;
35
36
        $this->page = $this->constructBaseModel($pageClass);
0 ignored issues
show
Bug introduced by
$pageClass of type Hyde\Framework\Contracts\AbstractPage is incompatible with the type string expected by parameter $pageClass of Hyde\Framework\Actions\S...r::constructBaseModel(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

36
        $this->page = $this->constructBaseModel(/** @scrutinizer ignore-type */ $pageClass);
Loading history...
37
        $this->constructDynamicData();
38
    }
39
40
    protected function constructBaseModel(string $pageClass): BladePage|AbstractMarkdownPage
41
    {
42
        return $pageClass === BladePage::class
43
            ? $this->parseBladePage()
44
            : $this->parseMarkdownPage($pageClass);
45
    }
46
47
    protected function parseBladePage(): BladePage
48
    {
49
        return new BladePage($this->slug);
50
    }
51
52
    protected function parseMarkdownPage(string $pageClass): AbstractMarkdownPage
53
    {
54
        /** @var AbstractMarkdownPage $pageClass */
55
        $document = MarkdownFileParser::parse(
56
            $pageClass::qualifyBasename($this->slug)
57
        );
58
59
        $matter = $document->matter;
60
        $body = $document->body;
61
62
        return new $pageClass(
63
            matter: $matter,
64
            body: $body,
65
            slug: $this->slug
66
        );
67
    }
68
69
    protected function constructDynamicData(): void
70
    {
71
        $this->page->title = $this->findTitleForPage();
0 ignored issues
show
Bug introduced by
Accessing title on the interface Hyde\Framework\Contracts\PageContract suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
72
73
        if ($this->page instanceof DocumentationPage) {
74
            $this->page->category = $this->getDocumentationPageCategory();
0 ignored issues
show
Bug introduced by
Accessing category on the interface Hyde\Framework\Contracts\PageContract suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
75
        }
76
    }
77
78
    protected function findTitleForPage(): string
79
    {
80
        if ($this->page instanceof BladePage) {
81
            return Hyde::makeTitle($this->slug);
82
        }
83
84
        if ($this->page->matter('title')) {
0 ignored issues
show
Bug introduced by
The method matter() does not exist on Hyde\Framework\Contracts\PageContract. It seems like you code against a sub-type of Hyde\Framework\Contracts\PageContract such as Hyde\Framework\Contracts\AbstractMarkdownPage. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

84
        if ($this->page->/** @scrutinizer ignore-call */ matter('title')) {
Loading history...
85
            return $this->page->matter('title');
86
        }
87
88
        return $this->findTitleFromMarkdownHeadings() ?? Hyde::makeTitle($this->slug);
89
    }
90
91
    protected function findTitleFromMarkdownHeadings(): ?string
92
    {
93
        foreach ($this->page->markdown()->toArray() as $line) {
0 ignored issues
show
Bug introduced by
The method markdown() does not exist on Hyde\Framework\Contracts\PageContract. It seems like you code against a sub-type of Hyde\Framework\Contracts\PageContract such as Hyde\Framework\Contracts\AbstractMarkdownPage. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

93
        foreach ($this->page->/** @scrutinizer ignore-call */ markdown()->toArray() as $line) {
Loading history...
94
            if (str_starts_with($line, '# ')) {
95
                return trim(substr($line, 2), ' ');
96
            }
97
        }
98
99
        return null;
100
    }
101
102
    protected function getDocumentationPageCategory(): ?string
103
    {
104
        // If the documentation page is in a subdirectory,
105
        // then we can use that as the category name.
106
        // Otherwise, we look in the front matter.
107
108
        return str_contains($this->slug, '/')
109
            ? Str::before($this->slug, '/')
110
            : $this->page->matter('category');
111
    }
112
113
    public function get(): PageContract
114
    {
115
        return $this->page;
116
    }
117
}
118