Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
HydeRebuildStaticSiteCommand
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
5 / 5
15
100.00% covered (success)
100.00%
1 / 1
 handle
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
3
 sanitizePathString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 validate
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
6
 handleException
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getOutputPath
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3namespace Hyde\Framework\Commands;
4
5use Exception;
6use Hyde\Framework\Concerns\Internal\TransfersMediaAssetsForBuildCommands;
7use Hyde\Framework\Hyde;
8use Hyde\Framework\Services\DiscoveryService;
9use Hyde\Framework\Services\RebuildService;
10use LaravelZero\Framework\Commands\Command;
11
12/**
13 * Hyde Command to build a single static site file.
14 */
15class HydeRebuildStaticSiteCommand extends Command
16{
17    use TransfersMediaAssetsForBuildCommands;
18
19    /**
20     * The signature of the command.
21     *
22     * @var string
23     */
24    protected $signature = 'rebuild
25        {path : The relative file path (example: _posts/hello-world.md)}';
26
27    /**
28     * The description of the command.
29     *
30     * @var string
31     */
32    protected $description = 'Run the static site builder for a single file';
33
34    /**
35     * The source path.
36     *
37     * @var string
38     */
39    public string $path;
40
41    /**
42     * Execute the console command.
43     *
44     * @return int
45     */
46    public function handle(): int
47    {
48        $time_start = microtime(true);
49
50        if ($this->argument('path') === '_media') {
51            $this->transferMediaAssets();
52
53            return 0;
54        }
55
56        $this->path = $this->sanitizePathString($this->argument('path'));
57
58        try {
59            $this->validate();
60        } catch (Exception $exception) {
61            return $this->handleException($exception);
62        }
63
64        (new RebuildService($this->path))->execute();
65
66        $time_end = microtime(true);
67        $execution_time = ($time_end - $time_start);
68
69        $this->info(sprintf(
70            'Created %s in %s seconds. (%sms)',
71            DiscoveryService::createClickableFilepath($this->getOutputPath($this->path)),
72            number_format(
73                $execution_time,
74                2
75            ),
76            number_format(($execution_time * 1000), 2)
77        ));
78
79        return 0;
80    }
81
82    /**
83     * Perform a basic sanitation to strip trailing characters.
84     *
85     * @param  string  $path
86     * @return string
87     */
88    public function sanitizePathString(string $path): string
89    {
90        return str_replace('\\', '/', trim($path, '.\\/'));
91    }
92
93    /**
94     * Validate the path to catch common errors.
95     *
96     * @throws Exception
97     */
98    public function validate(): void
99    {
100        if (! (
101            str_starts_with($this->path, Hyde::pathToRelative(Hyde::getDocumentationPagePath())) ||
102            str_starts_with($this->path, Hyde::pathToRelative(Hyde::getMarkdownPostPath())) ||
103            str_starts_with($this->path, Hyde::pathToRelative(Hyde::getBladePagePath())) ||
104            str_starts_with($this->path, Hyde::pathToRelative(Hyde::getMarkdownPostPath()))
105        )) {
106            throw new Exception("Path [$this->path] is not in a valid source directory.", 400);
107        }
108
109        if (! file_exists(Hyde::path($this->path))) {
110            throw new Exception("File [$this->path] not found.", 404);
111        }
112    }
113
114    /**
115     * Output the contents of an exception.
116     *
117     * @param  Exception  $exception
118     * @return int Error code
119     */
120    public function handleException(Exception $exception): int
121    {
122        $this->error('Something went wrong!');
123        $this->warn($exception->getMessage());
124
125        return $exception->getCode();
126    }
127
128    /**
129     * Get the output path for the given source file path.
130     * Will fall back to the input path when using non-standard source paths.
131     *
132     * @deprecated reimplementing path information in StaticPageBuilder,
133     *              alternatively, recreating in the DiscoveryService
134     *
135     * @param  string  $path
136     * @return string
137     */
138    public function getOutputPath(string $path): string
139    {
140        $path = str_replace(Hyde::path(), '', $path);
141
142        if (str_starts_with($path, '_posts')) {
143            return Hyde::path(str_replace('_posts', '_site/posts', rtrim($path, '.md').'.html'));
144        }
145
146        if (str_starts_with($path, '_docs')) {
147            return Hyde::path(str_replace('_docs', '_site/docs', rtrim($path, '.md').'.html'));
148        }
149
150        if (str_starts_with($path, '_pages')) {
151            $path = str_replace('.blade.php', '.md', $path);
152
153            return Hyde::path(str_replace('_pages', '_site/', rtrim($path, '.md').'.html'));
154        }
155
156        return $path;
157    }
158}