Issues (17)

Branch: master

src/Url.php (2 issues)

1
<?php
2
3
/**
4
 * This file is part of Cecil.
5
 *
6
 * (c) Arnaud Ligny <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Cecil;
15
16
use Cecil\Assets\Asset;
17
use Cecil\Builder;
18
use Cecil\Collection\Menu\Entry as MenuEntry;
19
use Cecil\Collection\Page\Page;
20
use Cecil\Config;
21
use Cecil\Renderer\Page as PageRenderer;
22
use Cecil\Util;
23
use Cocur\Slugify\Slugify;
24
25
/**
26
 * URL class.
27
 *
28
 * Builds an URL from a Page, a Menu Entry, an Asset or a string.
29
 */
30
class Url
31
{
32
    /** @var Builder */
33
    protected $builder;
34
35
    /** @var Config */
36
    protected $config;
37
38
    /** @var string */
39
    protected $url;
40
41
    /** @var Page Slugifier */
42
    private static $slugifier;
43
44
    /**
45
     * Creates an URL from a Page, a Menu Entry, an Asset or a string.
46
     *
47
     * @param Builder                          $builder
48
     * @param Page|MenuEntry|Asset|string|null $value
49
     * @param array|null                       $options Rendering options, e.g.: ['canonical' => true, 'format' => 'html', 'language' => 'fr']
50
     */
51 1
    public function __construct(Builder $builder, $value, ?array $options = null)
52
    {
53 1
        $this->builder = $builder;
54 1
        $this->config = $builder->getConfig();
55 1
        if (!self::$slugifier instanceof Slugify) {
0 ignored issues
show
self::slugifier is never a sub-type of Cocur\Slugify\Slugify.
Loading history...
56 1
            self::$slugifier = Slugify::create(['regexp' => Page::SLUGIFY_PATTERN]);
57
        }
58
59
        // handles options
60 1
        $canonical = null; // if true prefix url with baseurl config
61 1
        $format = null;    // output format
62 1
        $language = null;  // force language
63 1
        extract(\is_array($options) ? $options : [], EXTR_IF_EXISTS);
64
65
        // base URL
66 1
        $base = '';
67
        // enable canonical URL
68 1
        if ($this->config->isEnabled('canonicalurl') || $canonical === true) {
69 1
            $base = rtrim((string) $this->config->get('baseurl'), '/');
70
        }
71
        // disable canonical URL by option
72 1
        if ($canonical === false) {
0 ignored issues
show
The condition $canonical === false is always true.
Loading history...
73 1
            $base = '';
74
        }
75
        // use URL path as base if exists
76 1
        if ($base == '' && '/' != $basepath = parse_url((string) $this->config->get('baseurl'), PHP_URL_PATH)) {
77
            if (\is_string($basepath)) {
78
                $base = '/' . trim($basepath, '/');
79
            }
80
        }
81
82
        // if value is empty (i.e.: `url()`) returns home URL
83 1
        if (\is_null($value) || empty($value) || $value == '/') {
84 1
            $this->url = '/';
85
86 1
            return;
87
        }
88
89
        switch (true) {
90 1
            case $value instanceof Page: // $value is a Page
91
                /** @var Page $value */
92 1
                if (!$format) {
93 1
                    $format = $value->getVariable('output');
94 1
                    if (\is_array($value->getVariable('output'))) {
95 1
                        $default = array_search('html', $value->getVariable('output')) ?: 0;
96 1
                        $format = $value->getVariable('output')[$default];
97
                    }
98 1
                    if (!$format) {
99 1
                        $format = 'html';
100
                    }
101
                }
102 1
                $this->url = $base . '/' . ltrim((new PageRenderer($this->config))->getPublicFilePath($value, $format), '/');
103 1
                if ($canonical && $value->hasVariable('canonical') && $value->getVariable('canonical')['url']) { // canonical URL
104
                    $this->url = $value->getVariable('canonical')['url'];
105
                }
106 1
                break;
107 1
            case $value instanceof MenuEntry: // $value is a Menu Entry
108
                /** @var MenuEntry $value */
109
                if (Util\File::isRemote($value['url'])) {
110
                    $this->url = $value['url'];
111
                    break;
112
                }
113
                $this->url = $base . '/' . ltrim($value['url'], '/');
114
                break;
115 1
            case $value instanceof Asset: // $value is an Asset
116
                /** @var Asset $value */
117 1
                $this->url = $base . '/' . ltrim($value['path'], '/');
118 1
                if ($value->isImageInCdn()) {
119
                    $this->url = (string) $value;
120
                }
121 1
                break;
122 1
            case \is_string($value): // others cases
123
                /** @var string $value */
124
                // $value is a potential Page ID
125 1
                $pageId = self::$slugifier->slugify($value);
126
                // should force language?
127 1
                $lang = '';
128 1
                if ($language !== null && $language != $this->config->getLanguageDefault()) {
129 1
                    $pageId = "$language/$pageId";
130 1
                    $lang = "$language/";
131
                }
132
                switch (true) {
133 1
                    case Util\File::isRemote($value): // $value is an external URL
134 1
                        $this->url = $value;
135 1
                        break;
136 1
                    case $this->builder->getPages()->has($pageId): // $pageId exists in pages collection
137 1
                        $this->url = (string) new self($this->builder, $this->builder->getPages()->get($pageId), $options);
138 1
                        break;
139
                    default:
140
                        // remove double language prefix
141 1
                        if ($lang && Util\Str::startsWith($value, $lang)) {
142 1
                            $value = substr($value, \strlen($lang));
143
                        }
144 1
                        $this->url = $base . '/' . $lang . ltrim($value, '/');
145
                }
146
        }
147
    }
148
149
    /**
150
     * If called like a string returns built URL.
151
     */
152 1
    public function __toString(): string
153
    {
154 1
        return $this->getUrl();
155
    }
156
157
    /**
158
     * Returns built URL.
159
     */
160 1
    public function getUrl(): string
161
    {
162 1
        return (string) $this->url ?: '/';
163
    }
164
}
165