Passed
Push — master ( 10105b...1efe78 )
by Caen
03:18 queued 12s
created

CreatesNewPageSourceFile::parseTitle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
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 $slug;
31
    protected string $outputPath;
32
    protected string $subDir = '';
33
    protected bool $force = false;
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->slug = $this->parseSlug($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 parseSlug(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
    protected function makeOutputPath(string $pageClass): string
76
    {
77
        /** @var \Hyde\Pages\Concerns\HydePage $pageClass */
78
        return Hyde::path($pageClass::sourcePath($this->formatIdentifier()));
79
    }
80
81
    protected function createPage(string $type): void
82
    {
83
        match ($type) {
84
            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...
85
            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...
86
            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...
87
        };
88
    }
89
90
    protected function createBladeFile(): void
91
    {
92
        $this->createFile(<<<BLADE
93
            @extends('hyde::layouts.app')
94
            @section('content')
95
            @php(\$title = "$this->title")
96
            
97
            <main class="mx-auto max-w-7xl py-16 px-8">
98
                <h1 class="text-center text-3xl font-bold">$this->title</h1>
99
            </main>
100
            
101
            @endsection
102
103
            BLADE
104
        );
105
    }
106
107
    protected function createMarkdownFile(): void
108
    {
109
        $this->createFile("---\ntitle: $this->title\n---\n\n# $this->title\n");
110
    }
111
112
    protected function createDocumentationFile(): void
113
    {
114
        $this->createFile("# $this->title\n");
115
    }
116
117
    protected function formatIdentifier(): string
118
    {
119
        return "$this->subDir/$this->slug";
120
    }
121
122
    protected function validateType(string $pageClass): void
123
    {
124
        if (! in_array($pageClass, [MarkdownPage::class, BladePage::class, DocumentationPage::class])) {
125
            throw new UnsupportedPageTypeException('The page type must be either "markdown", "blade", or "documentation"');
126
        }
127
    }
128
129
    protected function failIfFileCannotBeSaved(string $path): void
130
    {
131
        if (file_exists($path) && ! $this->force) {
132
            throw new FileConflictException($path);
133
        }
134
    }
135
136
    protected function prepareOutputDirectory(): void
137
    {
138
        $this->needsParentDirectory($this->outputPath);
139
        $this->failIfFileCannotBeSaved($this->outputPath);
140
    }
141
142
    protected function createFile(string $contents): void
143
    {
144
        $this->prepareOutputDirectory();
145
146
        file_put_contents($this->outputPath, $contents);
147
    }
148
}
149