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
![]() |
|||||
8 | * @copyright Copyright (c) 2022 nystudio107 |
||||
0 ignored issues
–
show
|
|||||
9 | */ |
||||
0 ignored issues
–
show
|
|||||
10 | |||||
11 | namespace nystudio107\twigfield\autocompletes; |
||||
12 | |||||
13 | use Craft; |
||||
14 | use nystudio107\twigfield\base\Autocomplete; |
||||
15 | use nystudio107\twigfield\models\CompleteItem; |
||||
16 | use nystudio107\twigfield\types\AutocompleteTypes; |
||||
17 | use nystudio107\twigfield\types\CompleteItemKind; |
||||
18 | use Twig\Environment; |
||||
19 | |||||
20 | /** |
||||
0 ignored issues
–
show
|
|||||
21 | * @author nystudio107 |
||||
0 ignored issues
–
show
Content of the @author tag must be in the form "Display Name <[email protected]>"
![]() |
|||||
22 | * @package twigfield |
||||
0 ignored issues
–
show
|
|||||
23 | * @since 1.0.0 |
||||
0 ignored issues
–
show
|
|||||
24 | */ |
||||
0 ignored issues
–
show
|
|||||
25 | class TwigLanguageAutocomplete extends Autocomplete |
||||
26 | { |
||||
27 | // Constants |
||||
28 | // ========================================================================= |
||||
29 | |||||
30 | const CRAFT_FILTER_DOCS_URL = 'https://craftcms.com/docs/4.x/dev/filters.html'; |
||||
31 | const FILTER_DOCS = [ |
||||
32 | 'abs' => '[abs](https://twig.symfony.com/doc/3.x/filters/abs.html) | Returns the absolute value of a number.', |
||||
33 | 'address' => '[address](#address) | Formats an address.', |
||||
34 | 'append' => '[append](#append) | Appends HTML to the end of another element.', |
||||
35 | 'ascii' => '[ascii](#ascii) | Converts a string to ASCII characters.', |
||||
36 | 'atom' => '[atom](#atom) | Converts a date to an ISO-8601 timestamp.', |
||||
37 | 'attr' => '[attr](#attr) | Modifies an HTML tag’s attributes.', |
||||
38 | 'batch' => '[batch](https://twig.symfony.com/doc/3.x/filters/batch.html) | Batches items in an array.', |
||||
39 | 'camel' => '[camel](#camel) | Formats a string into camelCase.', |
||||
40 | 'capitalize' => '[capitalize](https://twig.symfony.com/doc/3.x/filters/capitalize.html) | Capitalizes the first character of a string.', |
||||
41 | 'column' => '[column](#column) | Returns the values from a single property or key in an array.', |
||||
42 | 'contains' => '[contains](#contains) | Returns whether an array contains a nested item with a given key-value pair.', |
||||
43 | 'convert_encoding' => '[convert_encoding](https://twig.symfony.com/doc/3.x/filters/convert_encoding.html) | Converts a string from one encoding to another.', |
||||
44 | 'currency' => '[currency](#currency) | Formats a number as currency.', |
||||
45 | 'date' => '[date](#date) | Formats a date.', |
||||
46 | 'date_modify' => '[date_modify](https://twig.symfony.com/doc/3.x/filters/date_modify.html) | Modifies a date.', |
||||
47 | 'datetime' => '[datetime](#datetime) | Formats a date with its time.', |
||||
48 | 'default' => '[default](https://twig.symfony.com/doc/3.x/filters/default.html) | Returns the value or a default value if empty.', |
||||
49 | 'diff' => '[diff](#diff) | Returns the difference between arrays.', |
||||
50 | 'duration' => '[duration](#duration) | Returns a `DateInterval` object.', |
||||
51 | 'e' => '[e](https://twig.symfony.com/doc/3.x/filters/escape.html) | Escapes a string.', |
||||
52 | 'encenc' => '[encenc](#encenc) | Encrypts and base64-encodes a string.', |
||||
53 | 'escape' => '[escape](https://twig.symfony.com/doc/3.x/filters/escape.html) | Escapes a string.', |
||||
54 | 'explodeClass' => '[explodeClass](#explodeclass) | Converts a `class` attribute value into an array of class names.', |
||||
55 | 'explodeStyle' => '[explodeStyle](#explodestyle) | Converts a `style` attribute value into an array of property name/value pairs.', |
||||
56 | 'filesize' => '[filesize](#filesize) | Formats a number of bytes into something else.', |
||||
57 | 'filter' => '[filter](#filter) | Filters the items in an array.', |
||||
58 | 'first' => '[first](https://twig.symfony.com/doc/3.x/filters/first.html) | Returns the first character/item of a string/array.', |
||||
59 | 'format' => '[format](https://twig.symfony.com/doc/3.x/filters/format.html) | Formats a string by replacing placeholders.', |
||||
60 | 'group' => '[group](#group) | Groups items in an array.', |
||||
61 | 'hash' => '[hash](#hash) | Prefixes a string with a keyed-hash message authentication code (HMAC).', |
||||
62 | 'httpdate' => '[httpdate](#httpdate) | Converts a date to the HTTP format.', |
||||
63 | 'id' => '[id](#id) | Normalizes an element ID into only alphanumeric characters, underscores, and dashes.', |
||||
64 | 'index' => '[index](#index) | Indexes the items in an array.', |
||||
65 | 'indexOf' => '[indexOf](#indexof) | Returns the index of a given value within an array, or the position of a passed-in string within another string.', |
||||
66 | 'intersect' => '[intersect](#intersect) | Returns the intersecting items of two arrays.', |
||||
67 | 'join' => '[join](https://twig.symfony.com/doc/3.x/filters/join.html) | Concatenates multiple strings into one.', |
||||
68 | 'json_decode' => '[json_decode](#json_decode) | JSON-decodes a value.', |
||||
69 | 'json_encode' => '[json_encode](#json_encode) | JSON-encodes a value.', |
||||
70 | 'kebab' => '[kebab](#kebab) | Formats a string into “kebab-case”.', |
||||
71 | 'keys' => '[keys](https://twig.symfony.com/doc/3.x/filters/keys.html) | Returns the keys of an array.', |
||||
72 | 'last' => '[last](https://twig.symfony.com/doc/3.x/filters/last.html) | Returns the last character/item of a string/array.', |
||||
73 | 'lcfirst' => '[lcfirst](#lcfirst) | Lowercases the first character of a string.', |
||||
74 | 'length' => '[length](https://twig.symfony.com/doc/3.x/filters/length.html) | Returns the length of a string or array.', |
||||
75 | 'literal' => '[literal](#literal) | Escapes an untrusted string for use with element query params.', |
||||
76 | 'lower' => '[lower](https://twig.symfony.com/doc/3.x/filters/lower.html) | Lowercases a string.', |
||||
77 | 'map' => '[map](https://twig.symfony.com/doc/3.x/filters/map.html) | Applies an arrow function to the items in an array.', |
||||
78 | 'markdown' => '[markdown](#markdown-or-md) | Processes a string as Markdown.', |
||||
79 | 'md' => '[md](#markdown-or-md) | Processes a string as Markdown.', |
||||
80 | 'merge' => '[merge](#merge) | Merges an array with another one.', |
||||
81 | 'money' => '[money](#money) | Outputs a value from a Money object.', |
||||
82 | 'multisort' => '[multisort](#multisort) | Sorts an array by one or more keys within its sub-arrays.', |
||||
83 | 'namespace' => '[namespace](#namespace) | Namespaces input names and other HTML attributes, as well as CSS selectors.', |
||||
84 | 'namespaceAttributes' => '', |
||||
85 | 'namespaceInputId' => '[namespaceInputId](#namespaceinputid) | Namespaces an element ID.', |
||||
86 | 'namespaceInputName' => '[namespaceInputName](#namespaceinputname) | Namespaces an input name.', |
||||
87 | 'nl2br' => '[nl2br](https://twig.symfony.com/doc/3.x/filters/nl2br.html) | Replaces newlines with `<br>` tags.', |
||||
88 | 'ns' => '[ns](#namespace) | Namespaces input names and other HTML attributes, as well as CSS selectors.', |
||||
89 | 'number' => '[number](#number) | Formats a number.', |
||||
90 | 'number_format' => '[number_format](https://twig.symfony.com/doc/3.x/filters/number_format.html) | Formats numbers.', |
||||
91 | 'parseAttr' => '', |
||||
92 | 'parseRefs' => '[parseRefs](#parserefs) | Parses a string for reference tags.', |
||||
93 | 'pascal' => '[pascal](#pascal) | Formats a string into “PascalCase”.', |
||||
94 | 'percentage' => '[percentage](#percentage) | Formats a percentage.', |
||||
95 | 'prepend' => '[prepend](#prepend) | Prepends HTML to the beginning of another element.', |
||||
96 | 'purify' => '[purify](#purify) | Runs HTML code through HTML Purifier.', |
||||
97 | 'push' => '[push](#push) | Appends one or more items onto the end of an array.', |
||||
98 | 'raw' => '[raw](https://twig.symfony.com/doc/3.x/filters/raw.html) | Marks as value as safe for the current escaping strategy.', |
||||
99 | 'reduce' => '[reduce](https://twig.symfony.com/doc/3.x/filters/reduce.html) | Iteratively reduces a sequence or mapping to a single value.', |
||||
100 | 'removeClass' => '[removeClass](#removeclass) | Removes a class (or classes) from the given HTML tag.', |
||||
101 | 'replace' => '[replace](#replace) | Replaces parts of a string with other things.', |
||||
102 | 'reverse' => '[reverse](https://twig.symfony.com/doc/3.x/filters/reverse.html) | Reverses a string or array.', |
||||
103 | 'round' => '[round](https://twig.symfony.com/doc/3.x/filters/round.html) | Rounds a number.', |
||||
104 | 'rss' => '[rss](#rss) | Converts a date to RSS date format.', |
||||
105 | 'slice' => '[slice](https://twig.symfony.com/doc/3.x/filters/slice.html) | Extracts a slice of a string or array.', |
||||
106 | 'snake' => '[snake](#snake) | Formats a string into “snake_case”.', |
||||
107 | 'sort' => '[sort](https://twig.symfony.com/doc/3.x/filters/sort.html) | Sorts an array.', |
||||
108 | 'spaceless' => '[spaceless](https://twig.symfony.com/doc/3.x/filters/spaceless.html) | Removes whitespace between HTML tags.', |
||||
109 | 'split' => '[split](https://twig.symfony.com/doc/3.x/filters/split.html) | Splits a string by a delimiter.', |
||||
110 | 'striptags' => '[striptags](https://twig.symfony.com/doc/3.x/filters/striptags.html) | Strips SGML/XML tags from a string.', |
||||
111 | 't' => '[t](#translate-or-t) | Translates a message.', |
||||
112 | 'time' => '[time](#time) | Formats a time.', |
||||
113 | 'timestamp' => '[timestamp](#timestamp) | Formats a human-readable timestamp.', |
||||
114 | 'title' => '[title](https://twig.symfony.com/doc/3.x/filters/title.html) | Formats a string into “Title Case”.', |
||||
115 | 'translate' => '[translate](#translate-or-t) | Translates a message.', |
||||
116 | 'trim' => '[trim](https://twig.symfony.com/doc/3.x/filters/trim.html) | Strips whitespace from the beginning and end of a string.', |
||||
117 | 'truncate' => '[truncate](#truncate) | Truncates a string to a given length, while ensuring that it does not split words.', |
||||
118 | 'ucfirst' => '[ucfirst](#ucfirst) | Capitalizes the first character of a string.', |
||||
119 | 'ucwords' => '', |
||||
120 | 'unique' => '[unique](#unique) | Removes duplicate values from an array.', |
||||
121 | 'unshift' => '[unshift](#unshift) | Prepends one or more items to the beginning of an array.', |
||||
122 | 'upper' => '[upper](https://twig.symfony.com/doc/3.x/filters/upper.html) | Formats a string into “UPPER CASE”.', |
||||
123 | 'url_encode' => '[url_encode](https://twig.symfony.com/doc/3.x/filters/url_encode.html) | Percent-encodes a string as a URL segment or an array as a query string.', |
||||
124 | 'values' => '[values](#values) | Returns all the values in an array, resetting its keys.', |
||||
125 | 'where' => '[where](#where) | Filters an array by key-value pairs.', |
||||
126 | 'widont' => '', |
||||
127 | 'without' => '[without](#without) | Returns an array without the specified element(s).', |
||||
128 | 'withoutKey' => '[withoutKey](#withoutkey) | Returns an array without the specified key.', |
||||
129 | ]; |
||||
130 | |||||
131 | const CRAFT_FUNCTION_DOCS_URL = 'https://craftcms.com/docs/4.x/dev/functions.html'; |
||||
132 | const FUNCTION_DOCS = [ |
||||
133 | 'actionInput' => '[actionInput](#actioninput) | Outputs a hidden `action` input.', |
||||
134 | 'actionUrl' => '[actionUrl](#actionurl) | Generates a controller action URL.', |
||||
135 | 'alias' => '[alias](#alias) | Parses a string as an alias.', |
||||
136 | 'attr' => '[attr](#attr) | Generates HTML attributes.', |
||||
137 | 'beginBody' => '[beginBody](#beginbody) | Outputs scripts and styles that were registered for the “begin body” position.', |
||||
138 | 'ceil' => '[ceil](#ceil) | Rounds a number up.', |
||||
139 | 'className' => '[className](#classname) | Returns the fully qualified class name of a given object.', |
||||
140 | 'clone' => '[clone](#clone) | Clones an object.', |
||||
141 | 'collect' => '[collect](#collect) | Returns a new collection.', |
||||
142 | 'combine' => '[combine](#combine) | Combines two arrays into one.', |
||||
143 | 'configure' => '[configure](#configure) | Sets attributes on the passed object.', |
||||
144 | 'constant' => '[constant](https://twig.symfony.com/doc/3.x/functions/constant.html) | Returns the constant value for a given string.', |
||||
145 | 'cpUrl' => '[cpUrl](#cpurl) | Generates a control panel URL.', |
||||
146 | 'create' => '[create](#create) | Creates a new object.', |
||||
147 | 'csrfInput' => '[csrfInput](#csrfinput) | Returns a hidden CSRF token input.', |
||||
148 | 'cycle' => '[cycle](https://twig.symfony.com/doc/3.x/functions/cycle.html) | Cycles on an array of values.', |
||||
149 | 'dataUrl' => '[dataUrl](#dataurl) | Outputs an asset or file as a base64-encoded data URL.', |
||||
150 | 'date' => '[date](#date) | Creates a date.', |
||||
151 | 'dump' => '[dump](https://twig.symfony.com/doc/3.x/functions/dump.html) | Dumps information about a variable.', |
||||
152 | 'endBody' => '[endBody](#endbody) | Outputs scripts and styles that were registered for the “end body” position.', |
||||
153 | 'expression' => '[expression](#expression) | Creates a database expression object.', |
||||
154 | 'failMessageInput' => '[failMessageInput](#failmessageinput) | Outputs a hidden `failMessage` input.', |
||||
155 | 'floor' => '[floor](#floor) | Rounds a number down.', |
||||
156 | 'getenv' => '[getenv](#getenv) | Returns the value of an environment variable.', |
||||
157 | 'gql' => '[gql](#gql) | Executes a GraphQL query against the full schema.', |
||||
158 | 'head' => '[head](#head) | Outputs scripts and styles that were registered for the “head” position.', |
||||
159 | 'hiddenInput' => '[hiddenInput](#hiddeninput) | Outputs a hidden input.', |
||||
160 | 'include' => '[include](https://twig.symfony.com/doc/3.x/functions/include.html) | Returns the rendered content of a template.', |
||||
161 | 'input' => '[input](#input) | Outputs an HTML input.', |
||||
162 | 'max' => '[max](https://twig.symfony.com/doc/3.x/functions/max.html) | Returns the biggest value in an array.', |
||||
163 | 'min' => '[min](https://twig.symfony.com/doc/3.x/functions/min.html) | Returns the lowest value in an array.', |
||||
164 | 'ol' => '[ol](#ol) | Outputs an array of items as an ordered list.', |
||||
165 | 'parseBooleanEnv' => '[parseBooleanEnv](#parsebooleanenv) | Parses a string as an environment variable or alias having a boolean value.', |
||||
166 | 'parseEnv' => '[parseEnv](#parseenv) | Parses a string as an environment variable or alias.', |
||||
167 | 'plugin' => '[plugin](#plugin) | Returns a plugin instance by its handle.', |
||||
168 | 'random' => '[random](https://twig.symfony.com/doc/3.x/functions/random.html) | Returns a random value.', |
||||
169 | 'range' => '[range](https://twig.symfony.com/doc/3.x/functions/range.html) | Returns a list containing an arithmetic progression of integers.', |
||||
170 | 'raw' => '[raw](#raw) | Wraps the given string in a `Twig\Markup` object to prevent it from getting HTML-encoded when output.', |
||||
171 | 'redirectInput' => '[redirectInput](#redirectinput) | Outputs a hidden `redirect` input.', |
||||
172 | 'renderObjectTemplate' => '', |
||||
173 | 'seq' => '[seq](#seq) | Outputs the next or current number in a sequence.', |
||||
174 | 'shuffle' => '[shuffle](#shuffle) | Randomizes the order of the items in an array.', |
||||
175 | 'siteUrl' => '[siteUrl](#siteurl) | Generates a front-end URL.', |
||||
176 | 'source' => '[source](https://twig.symfony.com/doc/3.x/functions/source.html) | Returns the content of a template without rendering it.', |
||||
177 | 'successMessageInput' => '[successMessageInput](#successmessageinput) | Outputs a hidden `successMessage` input.', |
||||
178 | 'svg' => '[svg](#svg) | Outputs an SVG document.', |
||||
179 | 'tag' => '[tag](#tag) | Outputs an HTML tag.', |
||||
180 | 'template_from_string' => '[template_from_string](https://twig.symfony.com/doc/3.x/functions/template_from_string.html) | Loads a template from a string.', |
||||
181 | 'ul' => '[ul](#ul) | Outputs an array of items as an unordered list.', |
||||
182 | 'url' => '[url](#url) | Generates a URL.', |
||||
183 | ]; |
||||
184 | |||||
185 | const CRAFT_TAG_DOCS_URL = 'https://craftcms.com/docs/4.x/dev/tags.html'; |
||||
186 | const TAG_DOCS = [ |
||||
187 | 'apply' => '[apply](https://twig.symfony.com/doc/3.x/tags/apply.html) | Applies Twig filters to the nested template code.', |
||||
188 | 'autoescape' => '[autoescape](https://twig.symfony.com/doc/3.x/tags/autoescape.html) | Controls the escaping strategy for the nested template code.', |
||||
189 | 'block' => '[block](https://twig.symfony.com/doc/3.x/tags/block.html) | Defines a template block.', |
||||
190 | 'cache' => '[cache](#cache) | Caches a portion of your template.', |
||||
191 | 'css' => '[css](#css) | Registers a `<style>` tag on the page.', |
||||
192 | 'dd' => '[dd](#dd) | Dump and die.', |
||||
193 | 'deprecated' => '[deprecated](https://twig.symfony.com/doc/3.x/tags/deprecated.html) | Triggers a PHP deprecation error.', |
||||
194 | 'do' => '[do](https://twig.symfony.com/doc/3.x/tags/do.html) | Does.', |
||||
195 | 'else' => '[else](https://twig.symfony.com/doc/3.x/tags/if.html) | Else conditional.', |
||||
196 | 'elseif' => '[else](https://twig.symfony.com/doc/3.x/tags/if.html) | Else if conditional.', |
||||
197 | 'embed' => '[embed](https://twig.symfony.com/doc/3.x/tags/embed.html) | Embeds another template.', |
||||
198 | 'endblock' => '[endblock](https://twig.symfony.com/doc/3.x/tags/block.html) | End a template block.', |
||||
199 | 'endif' => '[endif](https://twig.symfony.com/doc/3.x/tags/if.html) | End a conditional if block.', |
||||
200 | 'exit' => '[exit](#exit) | Ends the request.', |
||||
201 | 'extends' => '[extends](https://twig.symfony.com/doc/3.x/tags/extends.html) | Extends another template.', |
||||
202 | 'flush' => '', |
||||
203 | 'for' => '[for](https://twig.symfony.com/doc/3.x/tags/for.html) | Loops through an array.', |
||||
204 | 'from' => '[from](https://twig.symfony.com/doc/3.x/tags/from.html) | Imports macros from a template.', |
||||
205 | 'header' => '[header](#header) | Sets an HTTP header on the response.', |
||||
206 | 'hook' => '[hook](#hook) | Invokes a template hook.', |
||||
207 | 'html' => '[html](#html) | Registers arbitrary HTML code on the page.', |
||||
208 | 'if' => '[if](https://twig.symfony.com/doc/3.x/tags/if.html) | Conditionally executes the nested template code.', |
||||
209 | 'import' => '[import](https://twig.symfony.com/doc/3.x/tags/import.html) | Imports macros from a template.', |
||||
210 | 'include' => '[include](https://twig.symfony.com/doc/3.x/tags/include.html) | Includes another template.', |
||||
211 | 'js' => '[js](#js) | Registers a `<script>` tag on the page.', |
||||
212 | 'macro' => '[macro](https://twig.symfony.com/doc/3.x/tags/macro.html) | Defines a macro.', |
||||
213 | 'namespace' => '[namespace](#namespace) | Namespaces input names and other HTML attributes, as well as CSS selectors.', |
||||
214 | 'nav' => '[nav](#nav) | Creates a hierarchical nav menu.', |
||||
215 | 'paginate' => '[paginate](#paginate) | Paginates an element query.', |
||||
216 | 'redirect' => '[redirect](#redirect) | Redirects the browser.', |
||||
217 | 'requireAdmin' => '', |
||||
218 | 'requireEdition' => '', |
||||
219 | 'requireGuest' => '[requireGuest](#requireguest) | Requires that no user is logged-in.', |
||||
220 | 'requireLogin' => '[requireLogin](#requirelogin) | Requires that a user is logged-in.', |
||||
221 | 'requirePermission' => '[requirePermission](#requirepermission) | Requires that a user is logged-in with a given permission.', |
||||
222 | 'script' => '[script](#script) | Renders an HTML script tag on the page.', |
||||
223 | 'set' => '[set](https://twig.symfony.com/doc/3.x/tags/set.html) | Sets a variable.', |
||||
224 | 'switch' => '[switch](#switch) | Switch the template output based on a give value.', |
||||
225 | 'tag' => '[tag](#tag) | Renders an HTML tag on the page.', |
||||
226 | 'use' => '[use](https://twig.symfony.com/doc/3.x/tags/use.html) | Inherits from another template horizontally.', |
||||
227 | 'with' => '[with](https://twig.symfony.com/doc/3.x/tags/with.html) | Creates a nested template scope.', |
||||
228 | ]; |
||||
229 | |||||
230 | const ADDITIONAL_TAGS = [ |
||||
231 | 'else', |
||||
232 | 'elseif', |
||||
233 | 'endblock', |
||||
234 | 'endif', |
||||
235 | ]; |
||||
236 | |||||
237 | // Public Properties |
||||
238 | // ========================================================================= |
||||
239 | |||||
240 | /** |
||||
0 ignored issues
–
show
|
|||||
241 | * @var string The name of the autocomplete |
||||
242 | */ |
||||
243 | public $name = 'TwigLanguageAutocomplete'; |
||||
244 | |||||
245 | /** |
||||
0 ignored issues
–
show
|
|||||
246 | * @var string The type of the autocomplete |
||||
247 | */ |
||||
248 | public $type = AutocompleteTypes::TwigExpressionAutocomplete; |
||||
249 | |||||
250 | /** |
||||
0 ignored issues
–
show
|
|||||
251 | * @var string Whether the autocomplete should be parsed with . -delimited nested sub-properties |
||||
252 | */ |
||||
253 | public $hasSubProperties = false; |
||||
254 | |||||
255 | /** |
||||
0 ignored issues
–
show
|
|||||
256 | * @var ?Environment The Twig environment to parse for functions/filters/tags |
||||
257 | */ |
||||
258 | public $twig; |
||||
259 | |||||
260 | // Public Methods |
||||
261 | // ========================================================================= |
||||
262 | |||||
263 | /** |
||||
0 ignored issues
–
show
|
|||||
264 | * @inerhitDoc |
||||
265 | */ |
||||
0 ignored issues
–
show
|
|||||
266 | public function init(): void |
||||
267 | { |
||||
268 | if (empty($this->twig)) { |
||||
269 | $this->twig = Craft::$app->getView()->getTwig(); |
||||
270 | } |
||||
271 | } |
||||
272 | |||||
273 | /** |
||||
0 ignored issues
–
show
|
|||||
274 | * @inerhitDoc |
||||
275 | */ |
||||
0 ignored issues
–
show
|
|||||
276 | public function generateCompleteItems(): void |
||||
277 | { |
||||
278 | $twig = $this->twig; |
||||
279 | // Twig Filters |
||||
280 | $filters = array_keys($twig->getFilters()); |
||||
0 ignored issues
–
show
The method
getFilters() 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
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. ![]() |
|||||
281 | foreach ($filters as $filter) { |
||||
282 | $docs = self::FILTER_DOCS[$filter] ?? ''; |
||||
283 | $docs = str_replace('(#', '(' . self::CRAFT_FILTER_DOCS_URL . '#', $docs); |
||||
284 | CompleteItem::create() |
||||
285 | ->label($filter) |
||||
286 | ->insertText($filter) |
||||
287 | ->detail(Craft::t('twigfield', 'Twig Filter')) |
||||
288 | ->documentation($docs) |
||||
289 | ->kind(CompleteItemKind::MethodKind) |
||||
290 | ->add($this); |
||||
291 | } |
||||
292 | // Twig Functions |
||||
293 | $functions = array_keys($twig->getFunctions()); |
||||
294 | foreach ($functions as $function) { |
||||
295 | $functionLabel = $function . '()'; |
||||
296 | $docs = self::FUNCTION_DOCS[$function] ?? ''; |
||||
297 | $docs = str_replace('(#', '(' . self::CRAFT_FUNCTION_DOCS_URL . '#', $docs); |
||||
298 | CompleteItem::create() |
||||
299 | ->label($functionLabel) |
||||
300 | ->insertText($functionLabel) |
||||
301 | ->detail(Craft::t('twigfield', 'Twig Function')) |
||||
302 | ->documentation($docs) |
||||
303 | ->kind(CompleteItemKind::FunctionKind) |
||||
304 | ->add($this); |
||||
305 | } |
||||
306 | // Twig Tags |
||||
307 | $tags = array_merge(self::ADDITIONAL_TAGS, array_keys($twig->getTokenParsers())); |
||||
308 | foreach ($tags as $tag) { |
||||
309 | $docs = self::TAG_DOCS[$tag] ?? ''; |
||||
310 | $docs = str_replace('(#', '(' . self::CRAFT_TAG_DOCS_URL . '#', $docs); |
||||
311 | CompleteItem::create() |
||||
312 | ->label($tag) |
||||
313 | ->insertText($tag) |
||||
314 | ->detail(Craft::t('twigfield', 'Twig Tag')) |
||||
315 | ->documentation($docs) |
||||
316 | ->kind(CompleteItemKind::FieldKind) |
||||
317 | ->add($this); |
||||
318 | } |
||||
319 | } |
||||
320 | } |
||||
321 |