AutocompleteVariableGenerator   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 134
Duplicated Lines 0 %

Importance

Changes 16
Bugs 0 Features 2
Metric Value
eloc 58
c 16
b 0
f 2
dl 0
loc 134
rs 10
wmc 20

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getGeneratorName() 0 3 1
A regenerate() 0 3 1
A generate() 0 4 2
C generateInternal() 0 90 16
1
<?php
2
/**
3
 * Autocomplete module for Craft CMS
4
 *
5
 * Provides Twig template IDE autocomplete of Craft CMS & plugin variables
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
 * @link      https://putyourlightson.com
9
 * @copyright Copyright (c) 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
 * @copyright Copyright (c) PutYourLightsOn
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
11
 */
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...
12
13
namespace nystudio107\autocomplete\generators;
14
15
use Craft;
16
use craft\web\twig\variables\CraftVariable;
17
use nystudio107\autocomplete\base\Generator;
18
use nystudio107\autocomplete\events\DefineGeneratorValuesEvent;
19
use ReflectionClass;
20
use ReflectionMethod;
21
use ReflectionNamedType;
22
use ReflectionProperty;
23
use Throwable;
24
use yii\base\Event;
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   autocomplete
0 ignored issues
show
Coding Style introduced by
Package name "autocomplete" is not valid; consider "Autocomplete" instead
Loading history...
Coding Style introduced by
Tag value for @package tag indented incorrectly; expected 1 spaces but found 3
Loading history...
29
 * @since     1.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 AutocompleteVariableGenerator extends Generator
32
{
33
    // Constants
34
    // =========================================================================
35
36
    public const BEHAVIOR_PROPERTY_EXCLUDES = [
37
        'owner',
38
    ];
39
40
    // Public Static Methods
41
    // =========================================================================
42
43
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
44
     * @inheritDoc
45
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
46
    public static function getGeneratorName(): string
47
    {
48
        return 'AutocompleteVariable';
49
    }
50
51
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
52
     * @inheritDoc
53
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
54
    public static function generate()
55
    {
56
        if (self::shouldRegenerateFile()) {
57
            static::generateInternal();
58
        }
59
    }
60
61
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
62
     * @inheritDoc
63
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
64
    public static function regenerate()
65
    {
66
        static::generateInternal();
67
    }
68
69
    // Protected Static Methods
70
    // =========================================================================
71
72
    /**
73
     * Core function that generates the autocomplete class
74
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
75
    protected static function generateInternal()
76
    {
77
        $properties = [];
78
        $methods = [];
79
        /* @noinspection PhpInternalEntityUsedInspection */
80
        $globals = Craft::$app->view->getTwig()->getGlobals();
81
        /* @var CraftVariable $craftVariable */
82
        if (isset($globals['craft'])) {
83
            $craftVariable = $globals['craft'];
84
            // Handle the components
85
            foreach ($craftVariable->getComponents() as $key => $value) {
86
                try {
87
                    $properties[$key] = get_class($craftVariable->get($key));
88
                } catch (Throwable $e) {
89
                    // That's okay
90
                }
91
            }
92
            // Handle the behaviors
93
            foreach ($craftVariable->getBehaviors() as $behavior) {
94
                try {
95
                    $reflect = new ReflectionClass($behavior);
96
                    // Properties
97
                    foreach ($reflect->getProperties(ReflectionProperty::IS_PUBLIC) as $reflectProp) {
98
                        // Property name
99
                        $reflectPropName = $reflectProp->getName();
100
                        // Ensure the property exists only for this class and not any parent class
101
                        if (property_exists(get_parent_class($behavior), $reflectPropName)) {
102
                            continue;
103
                        }
104
                        // Do it this way because getType() reflection method is >= PHP 7.4
105
                        $reflectPropType = gettype($behavior->$reflectPropName);
106
                        switch ($reflectPropType) {
107
                            case 'object':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
108
                                $properties[$reflectPropName] = get_class($behavior->$reflectPropName);
109
                                break;
110
                            default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
111
                                $properties[$reflectPropName] = $reflectPropType;
112
                                break;
113
                        }
114
                    }
115
                    // Methods
116
                    foreach ($reflect->getMethods(ReflectionMethod::IS_PUBLIC) as $reflectMethod) {
117
                        // Method name
118
                        $reflectMethodName = $reflectMethod->getName();
119
                        // Ensure the method exists only for this class and not any parent class
120
                        if (method_exists(get_parent_class($behavior), $reflectMethodName)) {
121
                            continue;
122
                        }
123
                        // Method return type
124
                        $methodReturn = '';
125
                        $reflectMethodReturnType = $reflectMethod->getReturnType();
126
                        if ($reflectMethodReturnType instanceof ReflectionNamedType) {
127
                            $methodReturn = ': ' . $reflectMethodReturnType->getName();
128
                        }
129
                        // Method parameters
130
                        $methodParams = [];
131
                        foreach ($reflectMethod->getParameters() as $methodParam) {
132
                            $paramType = '';
133
                            $methodParamType = $methodParam->getType();
134
                            if ($methodParamType) {
135
                                $paramType = $methodParamType . ' ';
136
                            }
137
                            $methodParams[] = $paramType . '$' . $methodParam->getName();
138
                        }
139
                        $methods[$reflectMethodName] = '(' . implode(', ', $methodParams) . ')' . $methodReturn;
140
                    }
141
                } catch (\ReflectionException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
142
                }
143
            }
144
        }
145
146
        // Allow plugins to modify the values
147
        $event = new DefineGeneratorValuesEvent([
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...
148
            'values' => $properties,
149
        ]);
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...
150
        Event::trigger(self::class, self::EVENT_BEFORE_GENERATE, $event);
151
        $properties = $event->values;
152
153
        // Format the line output for each property
154
        foreach ($properties as $key => $value) {
155
            $properties[$key] = ' * @property \\' . $value . ' $' . $key;
156
        }
157
        // Format the line output for each method
158
        foreach ($methods as $key => $value) {
159
            $methods[$key] = ' * @method ' . $key . $value;
160
        }
161
162
        // Save the template with variable substitution
163
        self::saveTemplate([
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...
164
            '{{ properties }}' => implode(PHP_EOL, array_merge($properties, $methods)),
165
        ]);
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...
166
    }
167
}
168