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 |
|
|
|
|
8
|
|
|
* @copyright Copyright (c) 2022 nystudio107 |
|
|
|
|
9
|
|
|
*/ |
|
|
|
|
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
|
|
|
/** |
|
|
|
|
21
|
|
|
* @author nystudio107 |
|
|
|
|
22
|
|
|
* @package twigfield |
|
|
|
|
23
|
|
|
* @since 1.0.0 |
|
|
|
|
24
|
|
|
*/ |
|
|
|
|
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
|
|
|
/** |
|
|
|
|
241
|
|
|
* @var string The name of the autocomplete |
242
|
|
|
*/ |
243
|
|
|
public $name = 'TwigLanguageAutocomplete'; |
244
|
|
|
|
245
|
|
|
/** |
|
|
|
|
246
|
|
|
* @var string The type of the autocomplete |
247
|
|
|
*/ |
248
|
|
|
public $type = AutocompleteTypes::TwigExpressionAutocomplete; |
249
|
|
|
|
250
|
|
|
/** |
|
|
|
|
251
|
|
|
* @var string Whether the autocomplete should be parsed with . -delimited nested sub-properties |
252
|
|
|
*/ |
253
|
|
|
public $hasSubProperties = false; |
254
|
|
|
|
255
|
|
|
/** |
|
|
|
|
256
|
|
|
* @var ?Environment The Twig environment to parse for functions/filters/tags |
257
|
|
|
*/ |
258
|
|
|
public $twig; |
259
|
|
|
|
260
|
|
|
// Public Methods |
261
|
|
|
// ========================================================================= |
262
|
|
|
|
263
|
|
|
/** |
|
|
|
|
264
|
|
|
* @inerhitDoc |
265
|
|
|
*/ |
|
|
|
|
266
|
|
|
public function init(): void |
267
|
|
|
{ |
268
|
|
|
if (empty($this->twig)) { |
269
|
|
|
$this->twig = Craft::$app->getView()->getTwig(); |
270
|
|
|
} |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
/** |
|
|
|
|
274
|
|
|
* @inerhitDoc |
275
|
|
|
*/ |
|
|
|
|
276
|
|
|
public function generateCompleteItems(): void |
277
|
|
|
{ |
278
|
|
|
$twig = $this->twig; |
279
|
|
|
// Twig Filters |
280
|
|
|
$filters = array_keys($twig->getFilters()); |
|
|
|
|
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
|
|
|
|