Test Failed
Push — v5 ( bf5ae8...6034c6 )
by Andrew
34:49 queued 15:33
created

UrlHelper::stripSitePathPrefix()   A

Complexity

Conditions 5
Paths 16

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 13
c 1
b 1
f 0
dl 0
loc 21
rs 9.5222
cc 5
nc 16
nop 1
1
<?php
2
/**
3
 * Retour plugin for Craft CMS
4
 *
5
 * Retour allows you to intelligently redirect legacy URLs, so that you don't
6
 * lose SEO value when rebuilding & restructuring a website
7
 *
8
 * @link      https://nystudio107.com/
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @copyright tag
Loading history...
9
 * @copyright Copyright (c) 2020 nystudio107
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
10
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
Coding Style introduced by
Missing @package tag in file comment
Loading history...
Coding Style introduced by
Missing @author tag in file comment
Loading history...
Coding Style introduced by
Missing @license tag in file comment
Loading history...
11
12
namespace nystudio107\retour\helpers;
13
14
use Craft;
15
use craft\errors\SiteNotFoundException;
16
use craft\helpers\UrlHelper as CraftUrlHelper;
17
18
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
19
 * @author    nystudio107
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @package tag
Loading history...
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
Coding Style introduced by
Tag value for @author tag indented incorrectly; expected 2 spaces but found 4
Loading history...
20
 * @package   Retour
0 ignored issues
show
Coding Style introduced by
Tag value for @package tag indented incorrectly; expected 1 spaces but found 3
Loading history...
21
 * @since     3.1.34
0 ignored issues
show
Coding Style introduced by
The tag in position 3 should be the @author tag
Loading history...
Coding Style introduced by
Tag value for @since tag indented incorrectly; expected 3 spaces but found 5
Loading history...
22
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
23
class UrlHelper extends CraftUrlHelper
24
{
25
    // Public Static Methods
26
    // =========================================================================
27
28
    /**
29
     * Returns a query string that is a combination of al of the query strings from
30
     * the passed in $urls
31
     *
32
     * @param ...$urls
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
33
     * @return string
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
34
     */
35
    public static function combineQueryStringsFromUrls(...$urls): string
36
    {
37
        $queryParams = [];
38
        foreach ($urls as $url) {
39
            $parsedUrl = parse_url($url);
40
            $params = [];
41
            parse_str($parsedUrl['query'] ?? '', $params);
42
            $queryParams[] = $params;
43
        }
44
        $queryParams = array_unique(array_merge([], ...$queryParams), SORT_REGULAR);
45
46
        return http_build_query($queryParams);
47
    }
48
49
    /**
50
     * Strip out any site-defined sub-path from the incoming $path
51
     * e.g. if the Site's baseUrl is set to https://example.com/es and $path is /es/blog
52
     * this function will return /blog
53
     *
54
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
55
     * @return string
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
56
     */
57
    public static function stripSitePathPrefix(string $path): string
58
    {
59
        try {
60
            $baseSiteUrl = self::baseSiteUrl();
61
        } catch (SiteNotFoundException $e) {
62
            $baseSiteUrl = '';
63
        }
64
        $sitePath = parse_url($baseSiteUrl, PHP_URL_PATH);
65
        $addSlash = str_ends_with($path, '/');
66
        if (!empty($sitePath)) {
67
            // Normalizes a URI path by trimming leading/ trailing slashes and removing double slashes
68
            $sitePath = '/' . preg_replace('/\/\/+/', '/', trim($sitePath, '/'));
69
        }
70
        // Strip the $sitePath from the incoming $path
71
        if (str_starts_with($path, $sitePath)) {
72
            $path = substr($path, strlen($sitePath));
73
            $path = '/' . preg_replace('/\/\/+/', '/', trim($path, '/'));
74
        }
75
        $path = $addSlash ? $path . '/' : $path;
76
77
        return $path;
78
    }
79
80
    /**
81
     * See if the path includes a site prefix for any site
82
     *
83
     * @param string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
84
     * @return bool
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
85
     */
86
    public static function pathHasSitePrefix(string $path): bool
87
    {
88
        $sites = Craft::$app->getSites()->getAllSites();
89
        foreach ($sites as $site) {
90
            $sitePath = parse_url($site->baseUrl, PHP_URL_PATH);
91
            if (!empty($sitePath)) {
92
                // Normalizes a URI path by trimming leading/ trailing slashes and removing double slashes
93
                $sitePath = '/' . preg_replace('/\/\/+/', '/', trim($sitePath, '/'));
94
            }
95
            // Strip the $sitePath from the incoming $path
96
            if (str_starts_with($path, $sitePath)) {
97
                return true;
98
            }
99
        }
100
101
        return false;
102
    }
103
104
    /**
105
     * Merge the $url and $path together, combining any overlapping path segments
106
     *
107
     * @param ?string $url
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
108
     * @param ?string $path
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
109
     * @return string
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
110
     */
111
    public static function mergeUrlWithPath(?string $url, ?string $path): string
112
    {
113
        $overlap = 0;
114
        $url = $url ?? '';
115
        $path = $path ?? '';
116
        $url = rtrim($url, '/') . '/';
117
        $path = '/' . ltrim($path, '/');
118
        $urlOffset = strlen($url);
119
        $pathLength = strlen($path);
120
        $pathOffset = 0;
121
        while ($urlOffset > 0 && $pathOffset < $pathLength) {
122
            $urlOffset--;
123
            $pathOffset++;
124
            if (str_starts_with($path, substr($url, $urlOffset, $pathOffset))) {
125
                $overlap = $pathOffset;
126
            }
127
        }
128
129
        return rtrim($url, '/') . '/' . ltrim(substr($path, $overlap), '/');
130
    }
131
132
    /**
133
     * Return a sanitized URL
134
     *
135
     * @param string $url
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
136
     *
137
     * @return string
138
     */
139
    public static function sanitizeUrl(string $url): string
140
    {
141
        // HTML decode the entities, then strip out any tags
142
        $url = html_entity_decode($url, ENT_NOQUOTES, 'UTF-8');
143
        $url = urldecode($url);
144
        $url = strip_tags($url);
145
        // Remove any Twig tags that somehow are present in the incoming URL
146
        /** @noinspection CallableParameterUseCaseInTypeContextInspection */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
147
        $url = preg_replace('/{.*}/', '', $url);
148
        // Remove any linebreaks that may be errantly in the URL
149
        $url = (string)str_replace([
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
150
                PHP_EOL,
151
                "\r",
152
                "\n",
153
            ]
154
            , '', $url
0 ignored issues
show
Coding Style introduced by
Space found before comma in argument list
Loading history...
155
        );
156
157
        return $url;
158
    }
159
}
160