Passed
Push — develop-v4 ( 01b70c...6dd727 )
by Andrew
20:58 queued 15:04
created

Code   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 220
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 16
eloc 92
c 3
b 0
f 0
dl 0
loc 220
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getContentColumnType() 0 3 1
A getContentGqlType() 0 8 1
A rules() 0 15 1
B normalizeValue() 0 37 7
A getInputHtml() 0 32 4
A getSettingsHtml() 0 9 1
A displayName() 0 3 1
1
<?php
2
/**
3
 * Code Field plugin for Craft CMS
4
 *
5
 * Provides a Code Field that has a full-featured code editor with syntax highlighting & autocomplete
6
 *
7
 * @link      https://nystudio107.com
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @copyright tag
Loading history...
8
 * @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...
9
 */
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...
10
11
namespace nystudio107\codefield\fields;
12
13
use Craft;
14
use craft\base\ElementInterface;
0 ignored issues
show
Bug introduced by
The type craft\base\ElementInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use craft\base\Field;
16
use craft\base\PreviewableFieldInterface;
17
use craft\helpers\Html;
18
use craft\helpers\Json;
19
use craft\validators\ArrayValidator;
20
use GraphQL\Type\Definition\Type;
21
use nystudio107\codefield\gql\types\generators\CodeDataGenerator;
22
use nystudio107\codefield\models\CodeData;
23
use nystudio107\codefield\validators\JsonValidator;
24
use yii\db\Schema;
25
26
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
27
 * @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...
28
 * @package   CodeField
0 ignored issues
show
Coding Style introduced by
Tag value for @package tag indented incorrectly; expected 1 spaces but found 3
Loading history...
29
 * @since     4.0.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...
30
 */
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...
31
class Code extends Field implements PreviewableFieldInterface
32
{
33
    // Public Properties
34
    // =========================================================================
35
36
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
37
     * @var string The theme to use for the Code Editor field.
38
     */
39
    public string $theme = 'auto';
40
41
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
42
     * @var string The language to use for the Code Editor field.
43
     */
44
    public string $language = 'javascript';
45
46
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
47
     * @var bool Whether the Code Editor field display as a single line
48
     */
49
    public bool $singleLineEditor = false;
50
51
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
52
     * @var int The font size to use for the Code Editor field
53
     */
54
    public int $fontSize = 14;
55
56
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
57
     * @var bool Whether line numbers should be displayed in the Code Editor field
58
     */
59
    public bool $lineNumbers = false;
60
61
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
62
     * @var bool Whether code folding should be used in the Code Editor field
63
     */
64
    public bool $codeFolding = false;
65
66
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
67
     * @var string The text that will be shown if the code field is empty.
68
     */
69
    public string $placeholder = '';
70
71
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
72
     * @var bool Whether the language selector dropdown menu should be displayed.
73
     */
74
    public bool $showLanguageDropdown = true;
75
76
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
77
     * @var array The languages that should be listed in the language selector dropdown menu.
78
     */
79
    public array $availableLanguages = [
80
        'css',
81
        'graphql',
82
        'html',
83
        'javascript',
84
        'json',
85
        'markdown',
86
        'mysql',
87
        'php',
88
        'shell',
89
        'twig',
90
        'typescript',
91
        'yaml',
92
    ];
93
94
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
95
     * @var string JSON blob of Monaco [EditorOptions](https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IEditorOptions.html) that will override the default settings
96
     */
97
    public string $monacoEditorOptions = '';
98
99
    // Static Methods
100
    // =========================================================================
101
102
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
103
     * @inheritdoc
104
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
105
    public static function displayName(): string
106
    {
107
        return Craft::t('codefield', 'Code');
108
    }
109
110
    // Public Methods
111
    // =========================================================================
112
113
    /**
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...
114
     * @inheritdoc
115
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
116
    public function normalizeValue($value, ElementInterface $element = null): mixed
117
    {
118
        if ($value instanceof CodeData) {
119
            return $value;
120
        }
121
        // Default config
122
        $config = [
123
            'value' => '',
124
            'language' => $this->language,
125
        ];
126
        // Handle incoming values potentially being JSON or an array
127
        if (!empty($value)) {
128
            // Handle JSON-encoded values coming in
129
            if (\is_string($value)) {
130
                $jsonValue = Json::decodeIfJson($value);
131
                // If this is still a string (meaning it's not valid JSON), treat it as the value
132
                if (\is_string($jsonValue)) {
133
                    $config['value'] = $jsonValue;
134
                } else {
135
                    $value = $jsonValue;
136
                }
137
            }
138
            if (\is_array($value)) {
139
                $config = array_merge($config, array_filter($value));
140
            }
141
        }
142
        // Create and validate the model
143
        $codeData = new CodeData($config);
144
        if (!$codeData->validate()) {
145
            Craft::error(
146
                Craft::t('codefield', 'CodeData failed validation: ')
147
                . print_r($codeData->getErrors(), true),
0 ignored issues
show
Bug introduced by
Are you sure print_r($codeData->getErrors(), true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

147
                . /** @scrutinizer ignore-type */ print_r($codeData->getErrors(), true),
Loading history...
148
                __METHOD__
149
            );
150
        }
151
152
        return $codeData;
153
    }
154
155
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
156
     * @inheritdoc
157
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
158
    public function getSettingsHtml(): ?string
159
    {
160
        $monacoLanguages = require(__DIR__ . '/MonacoLanguages.php');
0 ignored issues
show
Coding Style introduced by
"require" is a statement not a function; no parentheses are required
Loading history...
Coding Style introduced by
File is being conditionally included; use "include" instead
Loading history...
161
        // Render the settings template
162
        return Craft::$app->getView()->renderTemplate(
163
            'codefield/_components/fields/Code_settings',
164
            [
165
                'field' => $this,
166
                'monacoLanguages' => $monacoLanguages,
167
            ]
168
        );
169
    }
170
171
    /**
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...
172
     * @inheritdoc
173
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
174
    public function getInputHtml($value, ElementInterface $element = null): string
175
    {
176
        // Get our id and namespace
177
        $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

177
        $id = Html::id(/** @scrutinizer ignore-type */ $this->handle);
Loading history...
178
        $namespacedId = Craft::$app->getView()->namespaceInputId($id);
179
180
        // Extract just the languages that have been selected for display
181
        $displayLanguages = [];
182
        if ($this->showLanguageDropdown) {
183
            $monacoLanguages = require(__DIR__ . '/MonacoLanguages.php');
0 ignored issues
show
Coding Style introduced by
"require" is a statement not a function; no parentheses are required
Loading history...
Coding Style introduced by
File is being conditionally included; use "include" instead
Loading history...
184
            $decomposedLanguages = array_column($monacoLanguages, 'label', 'value');
185
            $displayLanguages = array_intersect_key($decomposedLanguages, array_flip($this->availableLanguages));
186
            $displayLanguages = array_map(static function ($k, $v) {
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...
187
                return ['value' => $k, 'label' => $v];
188
            }, array_keys($displayLanguages), array_values($displayLanguages));
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...
189
        }
190
        $monacoOptionsOverride = Json::decodeIfJson($this->monacoEditorOptions);
191
        if ($monacoOptionsOverride === null || is_string($monacoOptionsOverride)) {
192
            $monacoOptionsOverride = [];
193
        }
194
        // Render the input template
195
        return Craft::$app->getView()->renderTemplate(
196
            'codefield/_components/fields/Code_input',
197
            [
198
                'name' => $this->handle,
199
                'value' => $value,
200
                'field' => $this,
201
                'orientation' => $this->getOrientation($element),
202
                'id' => $id,
203
                'namespacedId' => $namespacedId,
204
                'displayLanguages' => $displayLanguages,
205
                'monacoOptionsOverride' => $monacoOptionsOverride,
206
            ]
207
        );
208
    }
209
210
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
211
     * @inheritdoc
212
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
213
    public function getContentGqlType(): Type|array
214
    {
215
        $typeArray = CodeDataGenerator::generateTypes($this);
216
217
        return [
218
            'name' => $this->handle,
219
            'description' => 'Code Editor field',
220
            'type' => array_shift($typeArray),
221
        ];
222
    }
223
224
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
225
     * @inheritdoc
226
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
227
    public function rules(): array
228
    {
229
        $rules = parent::rules();
230
        return array_merge($rules, [
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...
231
            ['theme', 'in', 'range' => ['auto', 'vs', 'vs-dark', 'hc-black']],
232
            ['theme', 'default', 'value' => 'auto'],
233
            ['language', 'string'],
234
            ['language', 'default', 'value' => 'javascript'],
235
            [['singleLineEditor', 'showLanguageDropdown', 'lineNumbers', 'codeFolding'], 'boolean'],
236
            ['placeholder', 'string'],
237
            ['placeholder', 'default', 'value' => ''],
238
            ['fontSize', 'integer'],
239
            ['fontSize', 'default', 'value' => 14],
240
            ['availableLanguages', ArrayValidator::class],
241
            ['monacoEditorOptions', JsonValidator::class],
242
        ]);
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...
243
    }
244
245
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
246
     * @inheritdoc
247
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
248
    public function getContentColumnType(): string
249
    {
250
        return Schema::TYPE_TEXT;
251
    }
252
}
253