Passed
Push — master ( e6d507...3647e7 )
by Arnaud
06:59
created

Url::__construct()   F

Complexity

Conditions 30
Paths 384

Size

Total Lines 92
Code Lines 59

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 49
CRAP Score 32.4908

Importance

Changes 3
Bugs 1 Features 0
Metric Value
cc 30
eloc 59
c 3
b 1
f 0
nc 384
nop 3
dl 0
loc 92
ccs 49
cts 57
cp 0.8596
crap 32.4908
rs 1.0333

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
introduced by
self::slugifier is never a sub-type of Cocur\Slugify\Slugify.
Loading history...
56 1
            self::$slugifier = Slugify::create(['regexp' => Page::SLUGIFY_PATTERN]);
0 ignored issues
show
Documentation Bug introduced by
It seems like Cocur\Slugify\Slugify::c...Page::SLUGIFY_PATTERN)) of type Cocur\Slugify\Slugify is incompatible with the declared type Cecil\Collection\Page\Page of property $slugifier.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
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
introduced by
The condition $canonical === false is always true.
Loading history...
73 1
            $base = '';
74
        }
75
        // use base path if exists
76 1
        if ($base == '' && $basepath = trim(parse_url((string) $this->config->get('baseurl'), PHP_URL_PATH), '/')) {
77
            $base = $basepath;
78
        }
79
80
        // if value is empty (i.e.: `url()`) returns home URL
81 1
        if (\is_null($value) || empty($value) || $value == '/') {
82 1
            $this->url = $base . '/';
83
84 1
            return;
85
        }
86
87
        switch (true) {
88 1
            case $value instanceof Page: // $value is a Page
89
                /** @var Page $value */
90 1
                if (!$format) {
91 1
                    $format = $value->getVariable('output');
92 1
                    if (\is_array($value->getVariable('output'))) {
93 1
                        $default = array_search('html', $value->getVariable('output')) ?: 0;
94 1
                        $format = $value->getVariable('output')[$default];
95
                    }
96 1
                    if (!$format) {
97 1
                        $format = 'html';
98
                    }
99
                }
100 1
                $this->url = $base . '/' . ltrim((new PageRenderer($this->config))->getPublicFilePath($value, $format), '/');
101 1
                if ($canonical && $value->hasVariable('canonical') && $value->getVariable('canonical')['url']) { // canonical URL
102
                    $this->url = $value->getVariable('canonical')['url'];
103
                }
104 1
                break;
105 1
            case $value instanceof MenuEntry: // $value is a Menu Entry
106
                /** @var MenuEntry $value */
107
                if (Util\File::isRemote($value['url'])) {
108
                    $this->url = $value['url'];
109
                    break;
110
                }
111
                $this->url = $base . '/' . ltrim($value['url'], '/');
112
                break;
113 1
            case $value instanceof Asset: // $value is an Asset
114
                /** @var Asset $value */
115 1
                $this->url = $base . '/' . ltrim($value['path'], '/');
116 1
                if ($value->isImageInCdn()) {
117
                    $this->url = (string) $value;
118
                }
119 1
                break;
120 1
            case \is_string($value): // others cases
121
                /** @var string $value */
122
                // $value is a potential Page ID
123 1
                $pageId = self::$slugifier->slugify($value);
124
                // should force language?
125 1
                $lang = '';
126 1
                if ($language !== null && $language != $this->config->getLanguageDefault()) {
127 1
                    $pageId = "$language/$pageId";
128 1
                    $lang = "$language/";
129
                }
130
                switch (true) {
131 1
                    case Util\File::isRemote($value): // $value is an external URL
132 1
                        $this->url = $value;
133 1
                        break;
134 1
                    case $this->builder->getPages()->has($pageId): // $pageId exists in pages collection
135 1
                        $this->url = (string) new self($this->builder, $this->builder->getPages()->get($pageId), $options);
136 1
                        break;
137
                    default:
138
                        // remove double language prefix
139 1
                        if ($lang && Util\Str::startsWith($value, $lang)) {
140 1
                            $value = substr($value, \strlen($lang));
141
                        }
142 1
                        $this->url = $base . '/' . $lang . ltrim($value, '/');
143
                }
144
        }
145
    }
146
147
    /**
148
     * If called like a string returns built URL.
149
     */
150 1
    public function __toString(): string
151
    {
152 1
        return $this->getUrl();
153
    }
154
155
    /**
156
     * Returns built URL.
157
     */
158 1
    public function getUrl(): string
159
    {
160 1
        return (string) $this->url;
161
    }
162
}
163