Events::handleElementUriChange()   C
last analyzed

Complexity

Conditions 12
Paths 62

Size

Total Lines 69
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 49
c 1
b 0
f 0
dl 0
loc 69
rs 6.9666
cc 12
nc 62
nop 1

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
 * 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) 2018 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\services;
13
14
use Craft;
15
use craft\base\Component;
16
use craft\base\Element;
17
use craft\helpers\ElementHelper;
18
use nystudio107\retour\events\RedirectEvent;
19
use nystudio107\retour\helpers\UrlHelper;
20
use nystudio107\retour\Retour;
21
use yii\base\Exception;
22
23
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
24
 * @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...
25
 * @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...
26
 * @since     3.1.64
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...
27
 */
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...
28
class Events extends Component
29
{
30
    // Constants
31
    // =========================================================================
32
33
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
34
     * @event RedirectEvent The event that is triggered before an Entry redirect is automatically
35
     * saved when an Entry's URI is changed (assuming the **Create Entry Redirects** setting is enabled).
36
     * You may set [[RedirectEvent::isValid]] to `false` to prevent the redirect from getting saved.
37
     *
38
     * ```php
39
     * use nystudio107\retour\services\Events;
40
     * use nystudio107\retour\events\RedirectEvent;
41
     *
42
     * Event::on(Events::class,
43
     *     Events::EVENT_BEFORE_SAVE_ENTRY_REDIRECT,
44
     *     function(RedirectEvent $event) {
45
     *         // potentially set $event->isValid;
46
     *     }
47
     * );
48
     * ```
49
     */
50
    public const EVENT_BEFORE_SAVE_ENTRY_REDIRECT = 'beforeSaveEntryRedirect';
51
52
    // Public Properties
53
    // =========================================================================
54
55
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
56
     * @var array The URIs for the element before it was saved
57
     */
58
    public array $oldElementUris = [];
59
60
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
61
     * @var array A list of element ids that have their redirects already created
62
     */
63
    protected array $elementsWithCreatedRedirects = [];
64
65
    // Public Methods
66
    // =========================================================================
67
68
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
69
     * @param $element
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
70
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
71
    public function stashElementUris($element): void
72
    {
73
        // Stash the old URLs by element id, and do so only once,
74
        // in case we are called more than once per request
75
        if (empty($this->oldElementUris[$element->id])) {
76
            $this->oldElementUris[$element->id] = $this->getAllElementUris($element);
77
        }
78
    }
79
80
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
81
     * @param Element $element
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
82
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
83
    public function handleElementUriChange(Element $element): void
84
    {
85
        if (array_key_exists($element->id, $this->elementsWithCreatedRedirects)) {
86
            return;
87
        }
88
        $this->elementsWithCreatedRedirects[] = $element->id;
89
90
        $uris = $this->getAllElementUris($element);
91
        if (!empty($this->oldElementUris[$element->id])) {
92
            $oldElementUris = $this->oldElementUris[$element->id];
93
            foreach ($uris as $siteId => $newUri) {
94
                if (!empty($oldElementUris[$siteId])) {
95
                    $oldUri = $oldElementUris[$siteId];
96
                    Craft::debug(
97
                        Craft::t(
98
                            'retour',
99
                            'Comparing old: {oldUri} to new: {newUri}',
100
                            ['oldUri' => print_r($oldUri, true), 'newUri' => print_r($newUri, true)]
101
                        ),
102
                        __METHOD__
103
                    );
104
                    // Handle the siteId
105
                    $redirectSiteId = null;
106
                    if (Craft::$app->getIsMultiSite()) {
107
                        $redirectSiteId = $siteId;
108
                    }
109
                    // Make sure the URIs are not the same
110
                    if (strcmp($oldUri, $newUri) !== 0) {
111
                        // Handle trailing slash config setting
112
                        if (Craft::$app->config->general->addTrailingSlashesToUrls) {
113
                            $oldUri = rtrim($oldUri, '/') . '/';
114
                            $newUri = rtrim($newUri, '/') . '/';
115
                        }
116
                        // Handle the URL match type
117
                        if (Retour::$settings->uriChangeRedirectSrcMatch === 'fullurl') {
118
                            try {
119
                                if ($redirectSiteId !== null) {
120
                                    $redirectSiteId = (int)$redirectSiteId;
121
                                }
122
                                $oldUri = \craft\helpers\UrlHelper::siteUrl($oldUri, null, null, $redirectSiteId);
123
                                $newUri = UrlHelper::siteUrl($newUri, null, null, $redirectSiteId);
124
                            } catch (Exception $e) {
125
                                // That's fine
126
                            }
127
                        }
128
                        $redirectConfig = [
129
                            'id' => 0,
130
                            'redirectMatchType' => 'exactmatch',
131
                            'redirectHttpCode' => 301,
132
                            'redirectSrcMatch' => Retour::$settings->uriChangeRedirectSrcMatch,
133
                            'redirectSrcUrl' => $oldUri,
134
                            'redirectDestUrl' => $newUri,
135
                            'siteId' => $redirectSiteId,
136
                        ];
137
                        // Trigger a 'beforeSaveEntryRedirect' event
138
                        $isNew = (int)$redirectConfig['id'] === 0;
139
                        $event = new RedirectEvent([
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...
140
                            'isNew' => $isNew,
141
                            'legacyUrl' => $redirectConfig['redirectSrcUrl'],
142
                            'destinationUrl' => $redirectConfig['redirectDestUrl'],
143
                            'matchType' => $redirectConfig['redirectSrcMatch'],
144
                            'redirectType' => $redirectConfig['redirectHttpCode'],
145
                            'siteId' => $redirectConfig['siteId'],
146
                        ]);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
147
                        $this->trigger(self::EVENT_BEFORE_SAVE_ENTRY_REDIRECT, $event);
148
                        if (!$event->isValid) {
149
                            return;
150
                        }
151
                        Retour::$plugin->redirects->saveRedirect($redirectConfig);
0 ignored issues
show
Bug introduced by
The method saveRedirect() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

151
                        Retour::$plugin->redirects->/** @scrutinizer ignore-call */ 
152
                                                    saveRedirect($redirectConfig);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
152
                    }
153
                }
154
            }
155
        }
156
    }
157
158
    /**
159
     * Get the URIs for each site for the element
160
     *
161
     * @param Element $element
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
162
     *
163
     * @return array
164
     */
165
    protected function getAllElementUris(Element $element): array
166
    {
167
        $uris = [];
168
        if (!ElementHelper::isDraftOrRevision($element)) {
169
            $sites = Craft::$app->getSites()->getAllSites();
170
            foreach ($sites as $site) {
171
                $uri = Craft::$app->getElements()->getElementUriForSite($element->id, $site->id);
172
                if ($uri !== null) {
173
                    $uris[$site->id] = $uri;
174
                }
175
            }
176
        }
177
178
        Craft::debug(
179
            Craft::t(
180
                'retour',
181
                'Getting Element URIs: {uris}',
182
                ['uris' => print_r($uris, true)]
183
            ),
184
            __METHOD__
185
        );
186
187
        return $uris;
188
    }
189
}
190