Passed
Push — develop ( e54d12...6de964 )
by Andrew
04:20
created

AutocompleteService   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 164
Duplicated Lines 0 %

Importance

Changes 8
Bugs 0 Features 0
Metric Value
eloc 45
c 8
b 0
f 0
dl 0
loc 164
rs 10
wmc 8

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getAutocompleteCacheKey() 0 3 1
A getAllAutocompleteGenerators() 0 9 1
A init() 0 7 2
A clearAutocompleteCache() 0 5 1
A generateAutocompletes() 0 44 3
1
<?php
2
/**
3
 * Twigfield for Craft CMS
4
 *
5
 * Provides a twig editor field with Twig & Craft API 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\twigfield\services;
12
13
use Craft;
14
use craft\base\Component;
15
use nystudio107\twigfield\base\Autocomplete as BaseAutoComplete;
16
use nystudio107\twigfield\base\AutocompleteInterface;
17
use nystudio107\twigfield\events\RegisterTwigfieldAutocompletesEvent;
18
use nystudio107\twigfield\Twigfield;
19
use yii\caching\TagDependency;
20
21
/**
22
 * Class Autocomplete
23
 *
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   Twigfield
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     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...
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 AutocompleteService 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 RegisterTwigfieldAutocompletesEvent The event that is triggered when registering
35
     *        Twigfield Autocomplete types
36
     *
37
     * Autocomplete Generator types must implement [[AutocompleteInterface]]. [[AutoComplete]]
38
     * provides a base implementation.
39
     *
40
     * ```php
41
     * use nystudio107\twigfield\services\AutocompleteService;
42
     * use nystudio107\twigfield\events\RegisterTwigfieldAutocompletesEvent;
43
     * use yii\base\Event;
44
     *
45
     * Event::on(AutocompleteService::class,
46
     *     AutocompleteService::EVENT_REGISTER_TWIGFIELD_AUTOCOMPLETES,
47
     *     function(RegisterTwigfieldAutocompletesEvent $event) {
48
     *         $event->types[] = MyAutocomplete::class;
49
     *     }
50
     * );
51
     *
52
     * or to pass in a config array for the Autocomplete object:
53
     *
54
     * Event::on(AutocompleteService::class,
55
     *     AutocompleteService::EVENT_REGISTER_TWIGFIELD_AUTOCOMPLETES,
56
     *     function(RegisterTwigfieldAutocompletesEvent $event) {
57
     *         $config = [
58
     *             'property' => value,
59
     *         ];
60
     *         $event->types[] = [MyAutocomplete::class => $config];
61
     *     }
62
     * );
63
     *
64
     * ```
65
     */
66
    const EVENT_REGISTER_TWIGFIELD_AUTOCOMPLETES = 'registerTwigfieldAutocompletes';
67
68
    const AUTOCOMPLETE_CACHE_TAG = 'TwigFieldAutocompleteTag';
69
70
    // Public Properties
71
    // =========================================================================
72
73
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
74
     * @var string Prefix for the cache key
75
     */
76
    public $cacheKeyPrefix = 'TwigFieldAutocomplete';
77
78
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
79
     * @var int Cache duration
80
     */
81
    public $cacheDuration = 3600;
82
83
    // Public Methods
84
    // =========================================================================
85
86
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
87
     * @inerhitDoc
88
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
89
    public function init(): void
90
    {
91
        // Short cacheDuration if we're in devMode
92
        if (Craft::$app->getConfig()->getGeneral()->devMode) {
93
            $this->cacheDuration = 1;
94
        }
95
        parent::init();
96
    }
97
98
    /**
99
     * Call each of the autocompletes to generate their complete items
100
     * @param string $fieldType
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...
Coding Style introduced by
There must be exactly one blank line before the tags in a doc comment
Loading history...
101
     * @param array $twigfieldOptions
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
102
     * @return array
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
103
     */
104
    public function generateAutocompletes(string $fieldType = Twigfield::DEFAULT_FIELD_TYPE, array $twigfieldOptions = []): array
105
    {
106
        $autocompleteItems = [];
107
        $autocompletes = $this->getAllAutocompleteGenerators($fieldType);
108
        foreach ($autocompletes as $autocompleteGenerator) {
109
            /* @var BaseAutoComplete $autocomplete */
110
            // Assume the generator is a class name string
111
            $config = [
112
                'fieldType' => $fieldType,
113
                'twigfieldOptions' => $twigfieldOptions,
114
            ];
115
            $autocompleteClass = $autocompleteGenerator;
116
            // If we're passed in an array instead, extract the class name and config from the key/value pair
117
            // in the form of [className => configArray]
118
            if (is_array($autocompleteGenerator)) {
119
                $autocompleteClass = array_key_first($autocompleteGenerator);
120
                /** @noinspection SlowArrayOperationsInLoopInspection */
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...
121
                $config = array_merge($config, $autocompleteGenerator[$autocompleteClass]);
122
            }
123
            $autocomplete = new $autocompleteClass($config);
124
            $name = $autocomplete->name;
125
            // Set up the cache parameters
126
            $cache = Craft::$app->getCache();
127
            $cacheKey = $this->getAutocompleteCacheKey($autocomplete, $config);
128
            $dependency = new TagDependency([
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...
129
                'tags' => [
130
                    self::AUTOCOMPLETE_CACHE_TAG,
131
                    self::AUTOCOMPLETE_CACHE_TAG . $name,
132
                ],
133
            ]);
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...
134
            // Get the autocompletes from the cache, or generate them if they aren't cached
135
            $autocompleteItems[$name] = $cache->getOrSet($cacheKey, static function () use ($name, $autocomplete) {
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...
136
                $autocomplete->generateCompleteItems();
137
                return [
138
                    'name' => $name,
139
                    'type' => $autocomplete->type,
140
                    'hasSubProperties' => $autocomplete->hasSubProperties,
141
                    BaseAutoComplete::COMPLETION_KEY => $autocomplete->getCompleteItems(),
142
                ];
143
            }, $this->cacheDuration, $dependency);
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...
144
        }
145
        Craft::info('Twigfield Autocompletes generated', __METHOD__);
146
147
        return $autocompleteItems;
148
    }
149
150
    /**
151
     * Clear the specified autocomplete cache (or all autocomplete caches if left empty)
152
     *
153
     * @param string $autocompleteName
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...
154
     * @return void
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
155
     */
156
    public function clearAutocompleteCache(string $autocompleteName = ''): void
157
    {
158
        $cache = Craft::$app->getCache();
159
        TagDependency::invalidate($cache, self::AUTOCOMPLETE_CACHE_TAG . $autocompleteName);
160
        Craft::info('Twigfield caches invalidated', __METHOD__);
161
    }
162
163
    /**
164
     * Return the cache key to use for an Autocomplete's complete items
165
     *
166
     * @param AutocompleteInterface $autocomplete
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...
167
     * @param array $config
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Expected 17 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
168
     * @return string
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
169
     */
170
    public function getAutocompleteCacheKey(AutocompleteInterface $autocomplete, array $config): string
171
    {
172
        return $this->cacheKeyPrefix . $autocomplete->name . md5(serialize($config));
0 ignored issues
show
Bug introduced by
Accessing name on the interface nystudio107\twigfield\base\AutocompleteInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
173
    }
174
175
    // Protected Methods
176
    // =========================================================================
177
178
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $fieldType should have a doc-comment as per coding-style.
Loading history...
179
     * Returns all available autocompletes classes.
180
     *
181
     * @return string[] The available autocompletes classes
182
     */
183
    public function getAllAutocompleteGenerators(string $fieldType = Twigfield::DEFAULT_FIELD_TYPE): array
184
    {
185
        $event = new RegisterTwigfieldAutocompletesEvent([
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...
186
            'types' => Twigfield::$settings->defaultTwigfieldAutocompletes,
187
            'fieldType' => $fieldType,
188
        ]);
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
        $this->trigger(self::EVENT_REGISTER_TWIGFIELD_AUTOCOMPLETES, $event);
190
191
        return $event->types;
192
    }
193
}
194