Passed
Push — master ( 900da9...f74619 )
by Caen
03:31 queued 12s
created

Hyperlinks::route()   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
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Hyde\Foundation\Kernel;
6
7
use Hyde\Facades\Config;
8
use Hyde\Support\Models\Route;
9
use Hyde\Foundation\HydeKernel;
10
use Hyde\Framework\Exceptions\BaseUrlNotSetException;
11
use Hyde\Framework\Exceptions\FileNotFoundException;
12
use Illuminate\Support\Str;
13
14
use function str_ends_with;
15
use function str_starts_with;
16
use function substr_count;
17
use function file_exists;
18
use function str_replace;
19
use function str_repeat;
20
use function substr;
21
use function blank;
22
use function rtrim;
23
use function trim;
24
25
/**
26
 * Contains helpers and logic for resolving web paths for compiled files.
27
 *
28
 * It's bound to the HydeKernel instance, and is an integral part of the framework.
29
 */
30
class Hyperlinks
31
{
32
    protected HydeKernel $kernel;
33
34
    public function __construct(HydeKernel $kernel)
35
    {
36
        $this->kernel = $kernel;
37
    }
38
39
    /**
40
     * Format a web link to an HTML file, allowing for pretty URLs, if enabled.
41
     *
42
     * @see \Hyde\Framework\Testing\Unit\Foundation\HyperlinkFormatHtmlPathTest
43
     */
44
    public function formatLink(string $destination): string
45
    {
46
        if (Config::getBool('hyde.pretty_urls', false) === true) {
47
            if (str_ends_with($destination, '.html')) {
48
                if ($destination === 'index.html') {
49
                    return '/';
50
                }
51
52
                if (str_ends_with($destination, 'index.html')) {
53
                    return substr($destination, 0, -10);
54
                }
55
56
                return substr($destination, 0, -5);
57
            }
58
        }
59
60
        return $destination;
61
    }
62
63
    /**
64
     * Inject the proper number of `../` before the links in Blade templates.
65
     *
66
     * @param  string  $destination  relative to output directory on compiled site
67
     *
68
     * @see \Hyde\Framework\Testing\Unit\Foundation\HyperlinkFileHelperRelativeLinkTest
69
     */
70
    public function relativeLink(string $destination): string
71
    {
72
        if (str_starts_with($destination, '../')) {
73
            return $destination;
74
        }
75
76
        $nestCount = substr_count($this->kernel->currentRouteKey() ?? '', '/');
77
        $route = '';
78
        if ($nestCount > 0) {
79
            $route .= str_repeat('../', $nestCount);
80
        }
81
        $route .= $this->formatLink($destination);
82
83
        if (Config::getBool('hyde.pretty_urls', false) === true && $route === '/') {
84
            return './';
85
        }
86
87
        return str_replace('//', '/', $route);
88
    }
89
90
    /**
91
     * Gets a relative web link to the given file stored in the _site/media folder.
92
     *
93
     * An exception will be thrown if the file does not exist in the _media directory,
94
     * and the second argument is set to true.
95
     */
96
    public function mediaLink(string $destination, bool $validate = false): string
97
    {
98
        if ($validate && ! file_exists($sourcePath = "{$this->kernel->getMediaDirectory()}/$destination")) {
99
            throw new FileNotFoundException($sourcePath);
100
        }
101
102
        return $this->relativeLink("{$this->kernel->getMediaOutputDirectory()}/$destination");
103
    }
104
105
    /**
106
     * Gets a relative web link to the given image stored in the _site/media folder.
107
     * If the image is remote (starts with http) it will be returned as is.
108
     *
109
     * If true is passed as the second argument, and a base URL is set,
110
     * the image will be returned with a qualified absolute URL.
111
     */
112
    public function asset(string $name, bool $preferQualifiedUrl = false): string
113
    {
114
        if (str_starts_with($name, 'http')) {
115
            return $name;
116
        }
117
118
        $name = Str::start($name, "{$this->kernel->getMediaOutputDirectory()}/");
119
120
        if ($preferQualifiedUrl && $this->hasSiteUrl()) {
121
            return $this->url($name);
122
        }
123
124
        return $this->relativeLink($name);
125
    }
126
127
    /**
128
     * Check if a site base URL has been set in config (or .env).
129
     */
130
    public function hasSiteUrl(): bool
131
    {
132
        return ! blank(Config::getNullableString('hyde.url'));
133
    }
134
135
    /**
136
     * Return a qualified URL to the supplied path if a base URL is set.
137
     *
138
     * @param  string  $path  optional relative path suffix. Omit to return base url.
139
     *
140
     * @throws BaseUrlNotSetException If no site URL is set and no default is provided
141
     */
142
    public function url(string $path = ''): string
143
    {
144
        $path = $this->formatLink(trim($path, '/'));
145
146
        if ($this->hasSiteUrl()) {
147
            return rtrim(rtrim((string) Config::getNullableString('hyde.url'), '/')."/$path", '/');
148
        }
149
150
        throw new BaseUrlNotSetException();
151
    }
152
153
    /**
154
     * Get a route instance by its key from the kernel's route collection.
155
     */
156
    public function route(string $key): ?Route
157
    {
158
        return $this->kernel->routes()->get($key);
159
    }
160
}
161