CreatesNewPageSourceFile::normalizeSubdirectory()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Hyde\Framework\Actions;
6
7
use Hyde\Hyde;
8
use Hyde\Pages\BladePage;
9
use Illuminate\Support\Str;
10
use Hyde\Pages\MarkdownPage;
11
use Hyde\Pages\DocumentationPage;
12
use Hyde\Framework\Exceptions\FileConflictException;
13
use Hyde\Framework\Concerns\InteractsWithDirectories;
14
use Hyde\Framework\Exceptions\UnsupportedPageTypeException;
15
16
use function trim;
17
use function sprintf;
18
use function file_put_contents;
19
use function file_exists;
20
use function basename;
21
use function in_array;
22
use function str_contains;
23
use function Hyde\unslash;
24
use function rtrim;
25
26
/**
27
 * Scaffold a new Markdown, Blade, or documentation page.
28
 */
29
class CreatesNewPageSourceFile
30
{
31
    use InteractsWithDirectories;
32
33
    /** @var class-string<\Hyde\Pages\Concerns\HydePage> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<\Hyde\Pages\Concerns\HydePage> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<\Hyde\Pages\Concerns\HydePage>.
Loading history...
34
    protected string $pageClass;
35
36
    protected string $title;
37
    protected string $filename;
38
    protected string $outputPath;
39
    protected string $subDir = '';
40
    protected bool $force;
41
42
    protected ?string $customContent;
43
44
    public function __construct(string $title, string $pageClass = MarkdownPage::class, bool $force = false, ?string $customContent = null)
45
    {
46
        $this->validateType($pageClass);
47
        $this->pageClass = $pageClass;
48
49
        $this->title = $this->parseTitle($title);
50
        $this->filename = $this->fileName($title);
51
        $this->force = $force;
52
        $this->customContent = $customContent;
53
54
        $this->outputPath = $this->makeOutputPath($pageClass);
55
    }
56
57
    public function save(): string
58
    {
59
        $this->failIfFileCannotBeSaved($this->outputPath);
60
61
        match ($this->pageClass) {
62
            BladePage::class => $this->createBladeFile(),
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->createBladeFile() targeting Hyde\Framework\Actions\C...File::createBladeFile() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
63
            MarkdownPage::class => $this->createMarkdownFile(),
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->createMarkdownFile() targeting Hyde\Framework\Actions\C...e::createMarkdownFile() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
64
            DocumentationPage::class => $this->createDocumentationFile(),
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->createDocumentationFile() targeting Hyde\Framework\Actions\C...eateDocumentationFile() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
65
        };
66
67
        return $this->outputPath;
68
    }
69
70
    protected function parseTitle(string $title): string
71
    {
72
        return Str::afterLast($title, '/');
73
    }
74
75
    protected function fileName(string $title): string
76
    {
77
        // If title contains a slash, it's a subdirectory
78
        if (str_contains($title, '/')) {
79
            // So we normalize the subdirectory name
80
            $this->subDir = $this->normalizeSubdirectory($title);
81
        }
82
83
        // And return a slug made from just the title without the subdirectory
84
        return Hyde::makeSlug(basename($title));
0 ignored issues
show
Bug introduced by
The method makeSlug() does not exist on Hyde\Hyde. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

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

84
        return Hyde::/** @scrutinizer ignore-call */ makeSlug(basename($title));
Loading history...
85
    }
86
87
    protected function normalizeSubdirectory(string $title): string
88
    {
89
        return unslash('/'.rtrim(Str::beforeLast($title, '/').'/', '/\\'));
90
    }
91
92
    /** @param class-string<\Hyde\Pages\Concerns\HydePage> $pageClass */
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<\Hyde\Pages\Concerns\HydePage> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<\Hyde\Pages\Concerns\HydePage>.
Loading history...
93
    protected function makeOutputPath(string $pageClass): string
94
    {
95
        return Hyde::path($pageClass::sourcePath($this->formatIdentifier()));
0 ignored issues
show
Bug introduced by
The method path() does not exist on Hyde\Hyde. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

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

95
        return Hyde::/** @scrutinizer ignore-call */ path($pageClass::sourcePath($this->formatIdentifier()));
Loading history...
96
    }
97
98
    protected function createBladeFile(): void
99
    {
100
        $this->needsParentDirectory($this->outputPath);
101
102
        file_put_contents($this->outputPath, Hyde::normalizeNewlines(<<<BLADE
0 ignored issues
show
Bug introduced by
The method normalizeNewlines() does not exist on Hyde\Hyde. Since you implemented __callStatic, consider adding a @method annotation. ( Ignorable by Annotation )

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

102
        file_put_contents($this->outputPath, Hyde::/** @scrutinizer ignore-call */ normalizeNewlines(<<<BLADE
Loading history...
103
            @extends('hyde::layouts.app')
104
            @section('content')
105
            @php(\$title = "$this->title")
106
107
            <main class="mx-auto max-w-7xl py-16 px-8">
108
                {$this->getBladePageContent()}
109
            </main>
110
111
            @endsection
112
113
            BLADE
114
        ));
115
    }
116
117
    protected function createMarkdownFile(): void
118
    {
119
        (new MarkdownPage($this->formatIdentifier(), ['title' => $this->title], $this->getMarkdownPageContent()))->save();
120
    }
121
122
    protected function createDocumentationFile(): void
123
    {
124
        (new DocumentationPage($this->formatIdentifier(), [], "# $this->title"))->save();
125
    }
126
127
    protected function formatIdentifier(): string
128
    {
129
        return "$this->subDir/$this->filename";
130
    }
131
132
    protected function validateType(string $pageClass): void
133
    {
134
        if (! in_array($pageClass, [MarkdownPage::class, BladePage::class, DocumentationPage::class])) {
135
            throw new UnsupportedPageTypeException('The page type must be either "markdown", "blade", or "documentation"');
136
        }
137
    }
138
139
    protected function failIfFileCannotBeSaved(string $path): void
140
    {
141
        if ($this->force !== true && file_exists($path)) {
142
            throw new FileConflictException($path);
143
        }
144
    }
145
146
    protected function getBladePageContent(): string
147
    {
148
        $baseContent = "<h1 class=\"text-center text-3xl font-bold\">$this->title</h1>";
149
150
        return $this->customContent
151
            ? trim(sprintf("%s\n\n    <div>\n        %s\n    </div>", $baseContent, $this->customContent))
152
            : $baseContent;
153
    }
154
155
    protected function getMarkdownPageContent(): string
156
    {
157
        return trim(sprintf("# $this->title\n\n%s", $this->customContent ?? ''));
158
    }
159
}
160