Passed
Push — master ( 99cab5...2782fc )
by Caen
04:06 queued 13s
created

BuildTaskService::canCleanSiteDirectory()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 3
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Hyde\Framework\Services;
6
7
use Hyde\Facades\Config;
8
use Hyde\Facades\Features;
9
use Hyde\Facades\Filesystem;
10
use Hyde\Framework\Actions\PostBuildTasks\GenerateBuildManifest;
11
use Hyde\Framework\Actions\PostBuildTasks\GenerateRssFeed;
12
use Hyde\Framework\Actions\PostBuildTasks\GenerateSearch;
13
use Hyde\Framework\Actions\PostBuildTasks\GenerateSitemap;
14
use Hyde\Framework\Actions\PreBuildTasks\CleanSiteDirectory;
15
use Hyde\Framework\Features\BuildTasks\BuildTask;
16
use Hyde\Framework\Features\BuildTasks\PostBuildTask;
17
use Hyde\Framework\Features\BuildTasks\PreBuildTask;
18
use Illuminate\Console\OutputStyle;
19
use Illuminate\Support\Str;
20
use function array_map;
21
use function array_values;
22
use function class_basename;
23
use function is_string;
24
use function str_replace;
25
26
/**
27
 * This service manages the build tasks that are called before and after the site is compiled using the build command.
28
 *
29
 * The class is registered as a singleton in the Laravel service container and is run by the build command.
30
 * Build Tasks can be registered programmatically, through the config, and through autodiscovery.
31
 * The service determines when to run a task depending on which class it extends.
32
 *
33
 * @see \Hyde\Framework\Testing\Feature\Services\BuildTaskServiceTest
34
 * @see \Hyde\Framework\Testing\Unit\BuildTaskServiceUnitTest
35
 */
36
class BuildTaskService
37
{
38
    /** @var array<string, \Hyde\Framework\Features\BuildTasks\BuildTask> */
39
    protected array $buildTasks = [];
40
41
    protected ?OutputStyle $output = null;
42
43
    public function __construct()
44
    {
45
        $this->registerFrameworkTasks();
46
47
        $this->registerTasks(Config::getArray('hyde.build_tasks', []));
48
49
        $this->registerTasks($this->findTasksInAppDirectory());
50
    }
51
52
    public function setOutput(?OutputStyle $output): void
53
    {
54
        $this->output = $output;
55
    }
56
57
    /** @return array<class-string<\Hyde\Framework\Features\BuildTasks\BuildTask>> */
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<class-string<\Hyde...\BuildTasks\BuildTask>> at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in array<class-string<\Hyde\Framework\Features\BuildTasks\BuildTask>>.
Loading history...
58
    public function getRegisteredTasks(): array
59
    {
60
        return array_map(fn (BuildTask $task): string => $task::class, array_values($this->buildTasks));
61
    }
62
63
    public function runPreBuildTasks(): void
64
    {
65
        foreach ($this->buildTasks as $task) {
66
            if ($task instanceof PreBuildTask) {
67
                $task->run($this->output);
68
            }
69
        }
70
    }
71
72
    public function runPostBuildTasks(): void
73
    {
74
        foreach ($this->buildTasks as $task) {
75
            if ($task instanceof PostBuildTask) {
76
                $task->run($this->output);
77
            }
78
        }
79
    }
80
81
    /** @param  \Hyde\Framework\Features\BuildTasks\PreBuildTask|\Hyde\Framework\Features\BuildTasks\PostBuildTask|class-string<\Hyde\Framework\Features\BuildTasks\PreBuildTask|\Hyde\Framework\Features\BuildTasks\PostBuildTask>  $task */
0 ignored issues
show
Documentation Bug introduced by
The doc comment \Hyde\Framework\Features...ildTasks\PostBuildTask> at position 4 could not be parsed: Unknown type name 'class-string' at position 4 in \Hyde\Framework\Features\BuildTasks\PreBuildTask|\Hyde\Framework\Features\BuildTasks\PostBuildTask|class-string<\Hyde\Framework\Features\BuildTasks\PreBuildTask|\Hyde\Framework\Features\BuildTasks\PostBuildTask>.
Loading history...
82
    public function registerTask(PreBuildTask|PostBuildTask|string $task): void
83
    {
84
        $this->registerTaskInService(is_string($task) ? new $task() : $task);
85
    }
86
87
    protected function registerTaskInService(PreBuildTask|PostBuildTask $task): void
88
    {
89
        $this->buildTasks[$this->makeTaskIdentifier($task)] = $task;
90
    }
91
92
    protected function registerIf(string $task, bool $condition): void
93
    {
94
        if ($condition) {
95
            $this->registerTask($task);
96
        }
97
    }
98
99
    protected function registerTasks(array $tasks): void
100
    {
101
        foreach ($tasks as $task) {
102
            $this->registerTask($task);
103
        }
104
    }
105
106
    protected function findTasksInAppDirectory(): array
107
    {
108
        return Filesystem::smartGlob('app/Actions/*BuildTask.php')->map(function (string $file): string {
109
            return static::pathToClassName($file);
110
        })->toArray();
111
    }
112
113
    protected static function pathToClassName(string $file): string
114
    {
115
        return str_replace(['app', '.php', '/'], ['App', '', '\\'], $file);
116
    }
117
118
    protected function makeTaskIdentifier(BuildTask $class): string
119
    {
120
        // If a user-land task is registered with the same class name (excluding namespaces) as a framework task,
121
        // this will allow the user-land task to override the framework task, making them easy to swap out.
122
123
        return Str::kebab(class_basename($class));
124
    }
125
126
    private function registerFrameworkTasks(): void
127
    {
128
        $this->registerIf(CleanSiteDirectory::class, $this->canCleanSiteDirectory());
129
        $this->registerIf(GenerateBuildManifest::class, $this->canGenerateManifest());
130
        $this->registerIf(GenerateSitemap::class, $this->canGenerateSitemap());
131
        $this->registerIf(GenerateRssFeed::class, $this->canGenerateFeed());
132
        $this->registerIf(GenerateSearch::class, $this->canGenerateSearch());
133
    }
134
135
    private function canCleanSiteDirectory(): bool
136
    {
137
        return Config::getBool('hyde.empty_output_directory', true);
138
    }
139
140
    private function canGenerateManifest(): bool
141
    {
142
        return Config::getBool('hyde.generate_build_manifest', true);
143
    }
144
145
    private function canGenerateSitemap(): bool
146
    {
147
        return Features::sitemap();
148
    }
149
150
    private function canGenerateFeed(): bool
151
    {
152
        return Features::rss();
153
    }
154
155
    private function canGenerateSearch(): bool
156
    {
157
        return Features::hasDocumentationSearch();
158
    }
159
}
160