Passed
Push — master ( 5f2501...2c7eb4 )
by Caen
03:56 queued 12s
created

CreatesNewPageSourceFile::createFile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
c 0
b 0
f 0
dl 0
loc 5
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 function file_exists;
8
use Hyde\Framework\Concerns\InteractsWithDirectories;
9
use Hyde\Framework\Exceptions\FileConflictException;
10
use Hyde\Framework\Exceptions\UnsupportedPageTypeException;
11
use Hyde\Hyde;
12
use Hyde\Pages\BladePage;
13
use Hyde\Pages\DocumentationPage;
14
use Hyde\Pages\MarkdownPage;
15
use Illuminate\Support\Str;
16
use function in_array;
17
use function rtrim;
18
use function unslash;
19
20
/**
21
 * Scaffold a new Markdown, Blade, or documentation page.
22
 *
23
 * @see \Hyde\Framework\Testing\Feature\Actions\CreatesNewPageSourceFileTest
24
 */
25
class CreatesNewPageSourceFile
26
{
27
    use InteractsWithDirectories;
28
29
    protected string $title;
30
    protected string $filename;
31
    protected string $outputPath;
32
    protected string $subDir = '';
33
    protected bool $force;
34
35
    public function __construct(string $title, string $type = MarkdownPage::class, bool $force = false)
36
    {
37
        $this->validateType($type);
38
39
        $this->title = $this->parseTitle($title);
40
        $this->filename = $this->fileName($title);
41
        $this->force = $force;
42
43
        $this->outputPath = $this->makeOutputPath($type);
44
45
        $this->createPage($type);
46
    }
47
48
    public function getOutputPath(): string
49
    {
50
        return $this->outputPath;
51
    }
52
53
    protected function parseTitle(string $title): string
54
    {
55
        return Str::afterLast($title, '/');
56
    }
57
58
    protected function fileName(string $title): string
59
    {
60
        // If title contains a slash, it's a subdirectory
61
        if (str_contains($title, '/')) {
62
            // So we normalize the subdirectory name
63
            $this->subDir = $this->normalizeSubdirectory($title);
64
        }
65
66
        // And return a slug made from just the title without the subdirectory
67
        return Str::slug(basename($title));
68
    }
69
70
    protected function normalizeSubdirectory(string $title): string
71
    {
72
        return unslash('/'.rtrim(Str::beforeLast($title, '/').'/', '/\\'));
73
    }
74
75
    /** @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...
76
    protected function makeOutputPath(string $pageClass): string
77
    {
78
        return Hyde::path($pageClass::sourcePath($this->formatIdentifier()));
79
    }
80
81
    protected function createPage(string $type): void
82
    {
83
        $this->failIfFileCannotBeSaved($this->outputPath);
84
85
        match ($type) {
86
            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...
87
            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...
88
            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...
89
        };
90
    }
91
92
    protected function createBladeFile(): void
93
    {
94
        $this->needsParentDirectory($this->outputPath);
95
96
        file_put_contents($this->outputPath, Hyde::normalizeNewlines(<<<BLADE
97
            @extends('hyde::layouts.app')
98
            @section('content')
99
            @php(\$title = "$this->title")
100
            
101
            <main class="mx-auto max-w-7xl py-16 px-8">
102
                <h1 class="text-center text-3xl font-bold">$this->title</h1>
103
            </main>
104
            
105
            @endsection
106
107
            BLADE
108
        ));
109
    }
110
111
    protected function createMarkdownFile(): void
112
    {
113
        (new MarkdownPage($this->formatIdentifier(), ['title' => $this->title], "# $this->title"))->save();
114
    }
115
116
    protected function createDocumentationFile(): void
117
    {
118
        (new DocumentationPage($this->formatIdentifier(), [], "# $this->title"))->save();
119
    }
120
121
    protected function formatIdentifier(): string
122
    {
123
        return "$this->subDir/$this->filename";
124
    }
125
126
    protected function validateType(string $pageClass): void
127
    {
128
        if (! in_array($pageClass, [MarkdownPage::class, BladePage::class, DocumentationPage::class])) {
129
            throw new UnsupportedPageTypeException('The page type must be either "markdown", "blade", or "documentation"');
130
        }
131
    }
132
133
    protected function failIfFileCannotBeSaved(string $path): void
134
    {
135
        if ($this->force !== true && file_exists($path)) {
136
            throw new FileConflictException($path);
137
        }
138
    }
139
}
140