Passed
Push — v3 ( 9905e0...d51017 )
by Andrew
16:03 queued 16s
created

ShortLink::getElementValidationRules()   A

Complexity

Conditions 6
Paths 1

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 2
Bugs 1 Features 0
Metric Value
eloc 11
c 2
b 1
f 0
dl 0
loc 17
ccs 0
cts 14
cp 0
rs 9.2222
cc 6
nc 1
nop 0
crap 42
1
<?php
2
/**
3
 * Retour plugin for Craft CMS
4
 *
5
 * @link      https://nystudio107.com/
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @copyright tag
Loading history...
6
 * @copyright Copyright (c) 2022 nystudio107
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
7
 * @license   https://nystudio107.com/license
0 ignored issues
show
Coding Style introduced by
@license tag must contain a URL and a license name
Loading history...
8
 */
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...
9
10
namespace nystudio107\retour\fields;
11
12
use Craft;
13
use craft\base\ElementInterface;
14
use craft\base\Field;
15
use craft\base\PreviewableFieldInterface;
16
use craft\helpers\ElementHelper;
17
use craft\helpers\Html;
18
use craft\helpers\Json;
19
use craft\helpers\UrlHelper;
20
use nystudio107\retour\Retour as RetourPlugin;
21
use yii\helpers\StringHelper;
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.2.0
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
 *
28
 * @property-read string $contentColumnType
29
 */
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...
30
class ShortLink extends Field implements PreviewableFieldInterface
31
{
32
    protected static $allowShortLinkUpdates = true;
33
    public $redirectSrcMatch = 'pathonly';
34
    public $redirectHttpCode = 301;
35
36
    // Static Methods
37
38
    // =========================================================================
39
40
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
41
     * @inheritdoc
42
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
43
    public static function displayName(): string
44
    {
45
        return Craft::t('retour', 'Short Link');
46
    }
47
48
    /**
49
     * Prevent element updates from updating the short link redirects.
50
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
51
    public static function preventShortLinkUpdates()
52
    {
53
        self::$allowShortLinkUpdates = false;
54
    }
55
56
    /**
57
     * Allow element updates to update the short link redirects.
58
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
59
    public static function allowShortLinkUpdates()
60
    {
61
        self::$allowShortLinkUpdates = true;
62
    }
63
64
    // Public Methods
65
    // =========================================================================
66
67
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $value should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $element should have a doc-comment as per coding-style.
Loading history...
68
     * @inheritdoc
69
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
70
    public function getInputHtml($value, ElementInterface $element = null): string
71
    {
72
        // Get our id & namespaceId
73
        $craft35 = version_compare(Craft::$app->getVersion(), '3.5', '>=');
74
        if ($craft35) {
75
            $id = Html::id($this->handle);
0 ignored issues
show
Bug introduced by
It seems like $this->handle can also be of type null; however, parameter $id of craft\helpers\Html::id() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

75
            $id = Html::id(/** @scrutinizer ignore-type */ $this->handle);
Loading history...
76
        } else {
77
            $id = Craft::$app->getView()->formatInputId($this->handle);
78
        }
79
        $namespacedId = Craft::$app->getView()->namespaceInputId($id);
80
81
        // Render the input template
82
        return Craft::$app->getView()->renderTemplate(
83
            'retour/_components/fields/ShortLink_input',
84
            [
85
                'name' => $this->handle,
86
                'value' => $value,
87
                'field' => $this,
88
                'id' => $id,
89
                'namespacedId' => $namespacedId,
90
            ]
91
        );
92
    }
93
94
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
95
     * @inheritdoc
96
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
97
    public function getSettingsHtml()
98
    {
99
        return Craft::$app->getView()->renderTemplate('retour/_components/fields/ShortLink_settings',
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...
100
            [
101
                'field' => $this,
102
            ]);
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 8 spaces, but found 12.
Loading history...
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...
103
    }
104
105
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $element should have a doc-comment as per coding-style.
Loading history...
106
     * @inheritdoc
107
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
108
    public function getIsTranslatable(ElementInterface $element = null): bool
109
    {
110
        return false;
111
    }
112
113
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $element should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $isNew should have a doc-comment as per coding-style.
Loading history...
114
     * @inheritdoc
115
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
116
    public function afterElementSave(ElementInterface $element, bool $isNew)
117
    {
118
        if (!self::$allowShortLinkUpdates || $element->getIsDraft() || !$element->getSite()->hasUrls) {
119
            return;
120
        }
121
122
        $value = $element->getFieldValue($this->handle);
0 ignored issues
show
Bug introduced by
It seems like $this->handle can also be of type null; however, parameter $fieldHandle of craft\base\ElementInterface::getFieldValue() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

122
        $value = $element->getFieldValue(/** @scrutinizer ignore-type */ $this->handle);
Loading history...
123
124
        // Return for propagating elements
125
        if ($this->redirectSrcMatch === 'pathonly') {
126
            $parentElement = ElementHelper::rootElement($element);
127
            if ($this->translationMethod === Field::TRANSLATION_METHOD_NONE && ($element->propagating || $parentElement->propagating)) {
0 ignored issues
show
Bug introduced by
Accessing propagating on the interface craft\base\ElementInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
128
                return;
129
            }
130
        } elseif (!empty($value) && !StringHelper::startsWith($value, 'http')) {
131
            $value = UrlHelper::siteUrl($value, null, null, $element->siteId);
0 ignored issues
show
Bug introduced by
Accessing siteId on the interface craft\base\ElementInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
132
        }
133
134
        $parentElement = ElementHelper::rootElement($element);
135
        RetourPlugin::$plugin->redirects->removeElementRedirect($parentElement, false);
136
137
        if (!empty($value)) {
138
            $redirectSrcMatch = $this->redirectSrcMatch;
139
140
            if ($this->translationMethod !== Field::TRANSLATION_METHOD_NONE) {
141
                if (!UrlHelper::isAbsoluteUrl($value)) {
142
                    $value = UrlHelper::siteUrl($value, null, null, $parentElement->siteId);
143
                    $redirectSrcMatch = 'fullurl';
144
                }
145
            }
146
147
            RetourPlugin::$plugin->redirects->enableElementRedirect($parentElement, $value, $redirectSrcMatch, $this->redirectHttpCode);
148
        }
149
150
        parent::afterElementSave($element, $isNew);
151
    }
152
153
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $element should have a doc-comment as per coding-style.
Loading history...
154
     * @inheritdoc
155
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
156
    public function afterElementDelete(ElementInterface $element)
157
    {
158
        if ($element->getIsDraft() || $element->getIsRevision()) {
159
            return;
160
        }
161
162
        RetourPlugin::$plugin->redirects->removeElementRedirect($element, true, true);
163
        parent::afterElementDelete($element);
164
    }
165
166
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $value should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $element should have a doc-comment as per coding-style.
Loading history...
167
     * @inheritdoc
168
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
169
    public function getTableAttributeHtml($value, ElementInterface $element): string
170
    {
171
        $decoded = Json::decodeIfJson($value);
172
        if (is_array($decoded)) {
173
            $value = $decoded['legacyUrl'] ?? '';
174
        }
175
        // Render the preview template
176
        return Craft::$app->getView()->renderTemplate(
177
            'retour/_components/fields/ShortLink_preview',
178
            [
179
                'name' => $this->handle,
180
                'value' => $value,
181
                'field' => $this,
182
            ]
183
        );
184
    }
185
186
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
187
     * @inheritdoc
188
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
189
    public function getElementValidationRules(): array
190
    {
191
        return [
192
            [
193
                /** @var ElementInterface $element */
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...
194
                function($element) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
195
                    $value = $element->getFieldValue($this->handle);
0 ignored issues
show
Bug introduced by
It seems like $this->handle can also be of type null; however, parameter $fieldHandle of craft\base\ElementInterface::getFieldValue() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

195
                    $value = $element->getFieldValue(/** @scrutinizer ignore-type */ $this->handle);
Loading history...
196
                    $redirect = RetourPlugin::$plugin->getRedirects()->getRedirectByRedirectSrcUrl($value);
197
                    if (method_exists($element, 'getCanonical')) {
198
                        // Handle drafts
199
                        $element = $element->getCanonical();
200
                    }
201
                    if ($redirect && isset($redirect['associatedElementId'])) {
202
                        if ($redirect['associatedElementId'] == 0) {
203
                            $element->addError($this->handle, Craft::t('retour', 'A Retour redirect with this Legacy URL already exists.'));
204
                        } elseif ($redirect['associatedElementId'] !== $element->id) {
0 ignored issues
show
Bug introduced by
Accessing id on the interface craft\base\ElementInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
205
                            $element->addError($this->handle, Craft::t('retour', 'A Short Link with this URL already exists.'));
206
                        }
207
                    }
208
                },
209
            ],
210
        ];
211
    }
212
}
213