nystudio107 /
craft-twigfield
| 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
Loading history...
|
|||||
| 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]>"
Loading history...
|
|||||
| 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. Loading history...
|
|||||
| 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 |