diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..e172d4a --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,16 @@ + + + PHP CodeSniffer configuration for Twig Tweak module. + + + + + + + + + + + + + diff --git a/src/TwigExtension.php b/src/TwigExtension.php index 597959d..d2a0d0f 100644 --- a/src/TwigExtension.php +++ b/src/TwigExtension.php @@ -40,27 +40,204 @@ class TwigExtension extends \Twig_Extension { public function getFunctions() { $context_options = ['needs_context' => TRUE]; $all_options = ['needs_environment' => TRUE, 'needs_context' => TRUE]; + return [ + // - Drupal View - + // + // @code + // {{ drupal_view('who_s_new', 'block_1') }} + // @endcode new \Twig_SimpleFunction('drupal_view', 'views_embed_view'), + + // - Drupal View Result - + // + // @code + // {{ drupal_view('who_s_new', 'block_1') }} + // @endcode new \Twig_SimpleFunction('drupal_view_result', 'views_get_view_result'), + + // - Drupal Block - + // + // In order to list all registered plugin IDs fetch them with block plugin + // manager. With Drush it can be done like follows: + // @code + // drush ev "print_r(array_keys(\Drupal::service('plugin.manager.block')->getDefinitions()));" + // @endcode + // + // @code + // {# Print block using default configuration. #} + // {{ drupal_block('system_branding_block') }} + // + // {# Print block using custom configuration. #} + // {{ drupal_block('system_branding_block', {label: 'Branding', use_site_name: false}) + // + // {# Bypass block.html.twig theming. #} + // {{ drupal_block('system_branding_block', wrapper=false) }} + // @endcode + // + // @see https://www.drupal.org/node/2964457#block-plugin new \Twig_SimpleFunction('drupal_block', [$this, 'drupalBlock']), + + // - Drupal Region - + // + // @code + // {# Print 'Sidebar First' region of the default site theme. #} + // {{ drupal_region('sidebar_first') }} + // + // {# Print 'Sidebar First' region of Bartik theme. #} + // {{ drupal_region('sidebar_first', 'bartik') }} + // @endcode new \Twig_SimpleFunction('drupal_region', [$this, 'drupalRegion']), + + // - Drupal Entity - + // + // @code + // {# Print a content block which ID is 1. #} + // {{ drupal_entity('block_content', 1) }} + // + // {# Print a node's teaser. #} + // {{ drupal_entity('node', 123, 'teaser') }} + // + // {# Print Branding block which was previously disabled on #} + // {# admin/structure/block page. #} + // {{ drupal_entity('block', 'bartik_branding', check_access=false) }} + // @endcode new \Twig_SimpleFunction('drupal_entity', [$this, 'drupalEntity']), + + // - Drupal Entity Form - + // + // @code + // {# Print edit form for node 1. #} + // {{ drupal_entity_form('node', 1) }} + // + // {# Print add form for Article content type. #} + // {{ drupal_entity_form('node', values={type: 'article'}) }} + // + // {# Print user register form. #} + // {{ drupal_entity_form('user', NULL, 'register', check_access=false) }} + // @endcode new \Twig_SimpleFunction('drupal_entity_form', [$this, 'drupalEntityForm']), + + // - Drupal Field - + // + // @code + // {{ drupal_field('field_image', 'node', 1) }} + // {{ drupal_field('field_image', 'node', 1, 'teaser') }} + // {{ drupal_field('field_image', 'node', 1, {type: 'image_url', settings: {image_style: 'large'}}) }} + // @endcode new \Twig_SimpleFunction('drupal_field', [$this, 'drupalField']), + + // - Drupal Menu - + // + // @code + // {{ drupal_menu('main') }} + // @endcode new \Twig_SimpleFunction('drupal_menu', [$this, 'drupalMenu']), + + // - Drupal Form - + // + // @code + // {{ drupal_form('Drupal\\search\\Form\\SearchBlockForm') }} + // @endcode new \Twig_SimpleFunction('drupal_form', [$this, 'drupalForm']), + + // - Drupal Image - + // + // @code + // {# Render image specified by file ID. #} + // {{ drupal_image(123) }} + // + // {# Render image specified by file UUID. #} + // {{ drupal_image('9bb27144-e6b2-4847-bd24-adcc59613ec0') }} + // + // {# Render image specified by file URI. #} + // {{ drupal_image('public://ocean.jpg') }} + // + // {# Render image using 'thumbnail' image style and custom attributes. #} + // {{ drupal_image('public://ocean.jpg', 'thumbnail', {alt: 'The alternative text'|t, title: 'The title text'|t}) }} + // + // {# Render responsive image. #} + // {{ drupal_image('public://ocean.jpg', 'wide', responsive=true) }} + // @endcode new \Twig_SimpleFunction('drupal_image', [$this, 'drupalImage']), + + // - Drupal Token - + // + // @code + // {{ drupal_token('site:name') }} + // @endcode new \Twig_SimpleFunction('drupal_token', [$this, 'drupalToken']), + + // - Drupal Config - + // + // @code + // {{ drupal_config('system.site', 'name') }} + // @endcode new \Twig_SimpleFunction('drupal_config', [$this, 'drupalConfig']), + + // - Drupal Dump - + // + // @code + // {# Basic usage. #} + // {{ drupal_dump(var) }} + // + // {# Same as above but shorter. #} + // {{ dd(var) }} + // + // {# Dump all available variables for the current template. #} + // {{ dd() }} + // @endcode new \Twig_SimpleFunction('drupal_dump', [$this, 'drupalDump'], $context_options), new \Twig_SimpleFunction('dd', [$this, 'drupalDump'], $context_options), + + // - Drupal Title - new \Twig_SimpleFunction('drupal_title', [$this, 'drupalTitle']), + + // - Drupal URL - + // + // @code + // {# Basic usage. #} + // {{ drupal_url('node/1) }} + // + // {# Complex URL. #} + // {{ drupal_url('node/1', {query: {foo: 'bar'}, fragment: 'example', absolute: true}) }} + // @endcode new \Twig_SimpleFunction('drupal_url', [$this, 'drupalUrl']), + + // - Drupal Link - + // + // @code + // {# It supports the same options as drupal_url(), plus attributes. #} + // {{ drupal_link('View'|t, 'node/1', {attributes: {target: '_blank'}}) }} + // + // {# This link will only be shown for privileged users. #} + // {{ drupal_link('Example'|t, '/admin', check_access=true) }} + // @endcode new \Twig_SimpleFunction('drupal_link', [$this, 'drupalLink']), + + // - Drupal Messages - new \Twig_SimpleFunction('drupal_messages', [$this, 'drupalMessages']), + + // - Drupal Breadcrumb - new \Twig_SimpleFunction('drupal_breadcrumb', [$this, 'drupalBreadcrumb']), + + // - Drupal Breakpoint - new \Twig_SimpleFunction('drupal_breakpoint', [$this, 'drupalBreakpoint'], $all_options), + + // - Contextual Links - + // + // @code + // {# Basic usage. #} + //
+ // {{ contextual_links('entity.view.edit_form:view=frontpage&display_id=feed_1') }} + // {{ drupal_view('frontpage') }} + //
+ // {# Multiple links. #} + //
+ // {{ contextual_links('node:node=123|block_content:block_content=123') }} + // {{ content }} + //
+ // @endcode new \Twig_SimpleFunction('contextual_links', [$this, 'contextualLinks']), ]; } @@ -69,20 +246,138 @@ class TwigExtension extends \Twig_Extension { * {@inheritdoc} */ public function getFilters() { + $filters = [ + // - Token Replace - + // + // @code + // {# Basic usage. #} + // {{ '

[site:name]

[site:slogan]
'|token_replace }} + // + // {# This is more suited to large markup (requires Twig >= 1.41). #} + // {% apply token_replace %} + //

[site:name]

+ //
[site:slogan]
+ // {% endapply %} + // @endcode new \Twig_SimpleFilter('token_replace', [$this, 'tokenReplaceFilter']), + + // - Preg Replace - + // + // @code + // {{ 'Drupal - community plumbing!'|preg_replace('/(Drupal)/', '$1') }} + // @endcode + // + // For simple string interpolation consider using built-in 'replace' or + // 'format' Twig filters. new \Twig_SimpleFilter('preg_replace', [$this, 'pregReplaceFilter']), + + // - Image Style - + // + // @code + // {{ 'public://images/ocean.jpg'|image_style('thumbnail') }} + // @endcode new \Twig_SimpleFilter('image_style', [$this, 'imageStyle']), + + // - Transliterate - + // + // @code + // {{ 'Привет!'|transliterate }} + // @endcod new \Twig_SimpleFilter('transliterate', [$this, 'transliterate']), + + // - Check Markup - + // + // @code + // {{ 'bold strong'|check_markup('restricted_html') }} + // @endcode new \Twig_SimpleFilter('check_markup', [$this, 'checkMarkup']), + + // - Truncate - + // + // @code + // {{ 'Some long text'|truncate(10, true) }} + // @endcode new \Twig_SimpleFilter('truncate', [$this, 'truncate']), + + // - View - + // + // @code + // {# Do not put this into node.html.twig template to avoid recursion. #} + // {{ node|view }} + // {{ node|view('teaser') }} + // + // {{ node.field_image|view }} + // {{ node.field_image[0]|view }} + // {{ node.field_image|view('teaser') }} + // {{ node.field_image|view({settings: {image_style: 'thumbnail'}}) }} + // @endcode new \Twig_SimpleFilter('view', [$this, 'view']), + + // - With - + // + // @code + // {# Set top level value. #} + // {{ content.field_image|with('#title', 'Photo'|t) }} + // + // {# Set nested value. #} + // {{ content|with(['field_image', '#title'], 'Photo'|t) }} + // @endcode new \Twig_SimpleFilter('with', [$this, 'with']), + + // - Children - + // + // @code + // + // @endcode new \Twig_SimpleFilter('children', [$this, 'children']), + + // - File URL - + // + // For string arguments it works similar to core file_url() Twig function. + // @code + // {{ 'public://sea.jpg'|file_url }} + // @endcode + // + // When field item list passed the URL will be extracted from the first + // item. In order to get URL of specific item specify its delta explicitly + // using array notation. + // @code + // {{ node.field_image|file_url }} + // {{ node.field_image[0]|file_url }} + // @endcode + // + // Media fields are fully supported including OEmbed resources. + // @code + // {{ node.field_media|file_url }} + // @endcode new \Twig_SimpleFilter('file_url', [$this, 'fileUrl']), ]; - // PHP filter should be enabled in settings.php file. + if (Settings::get('twig_tweak_enable_php_filter')) { + // - PHP - + // + // PHP filter is disabled by default. You can enable it in settings.php + // file as follows: + // @code + // $settings['twig_tweak_enable_php_filter'] = TRUE; + // @endcode + // + // @code + // {{ 'return date('Y');'|php }} + // @endcode + // + // Using PHP filter is discouraged as it may cause security implications. + // In fact it is very rarely needed. + // + // The above code can be replaced with following. + // @code + // {{ 'now'|date('Y') }} + // @endcode $filters[] = new \Twig_SimpleFilter('php', [$this, 'phpFilter']); } return $filters; @@ -98,26 +393,6 @@ class TwigExtension extends \Twig_Extension { /** * Builds the render array for a block. * - * In order to list all registered plugin IDs fetch them with block plugin - * manager. With Drush it can be done like follows: - * @code - * drush ev "print_r(array_keys(\Drupal::service('plugin.manager.block')->getDefinitions()));" - * @endcode - * - * Examples: - * @code - * {# Print block using default configuration. #} - * {{ drupal_block('system_branding_block') }} - * - * {# Print block using custom configuration. #} - * {{ drupal_block('system_branding_block', {label: 'Branding', use_site_name: false}) - * - * {# Bypass block.html.twig theming. #} - * {{ drupal_block('system_branding_block', wrapper=false) }} - * @endcode - * - * @see https://www.drupal.org/node/2964457#block-plugin - * * @param mixed $id * The string of block plugin to render. * @param array $configuration @@ -183,15 +458,6 @@ class TwigExtension extends \Twig_Extension { /** * Builds the render array of a given region. * - * Examples: - * @code - * {# Print 'Sidebar First' region of the default site theme. #} - * {{ drupal_region('sidebar_first') }} - * - * {# Print 'Sidebar First' region of Bartik theme. #} - * {{ drupal_region('sidebar_first', 'bartik') }} - * @endcode - * * @param string $region * The region to build. * @param string $theme @@ -243,19 +509,6 @@ class TwigExtension extends \Twig_Extension { /** * Returns the render array to represent and entity. * - * Examples: - * @code - * {# Print a content block which ID is 1. #} - * {{ drupal_entity('block_content', 1) }} - * - * {# Print a node's teaser. #} - * {{ drupal_entity('node', 123, 'teaser') }} - * - * {# Print Branding block which was previously disabled on #} - * {# admin/structure/block page. #} - * {{ drupal_entity('block', 'bartik_branding', check_access=false) }} - * @endcode - * * @param string $entity_type * The entity type. * @param mixed $id @@ -299,18 +552,6 @@ class TwigExtension extends \Twig_Extension { /** * Gets the built and processed entity form for the given entity type. * - * Examples: - * @code - * {# Print edit form for node 1. #} - * {{ drupal_entity_form('node', 1) }} - * - * {# Print add form for Article content type. #} - * {{ drupal_entity_form('node', values={type: 'article'}) }} - * - * {# Print user register form. #} - * {{ drupal_entity_form('user', NULL, 'register', check_access=false) }} - * @endcode - * * @param string $entity_type * The entity type. * @param mixed $id @@ -353,13 +594,6 @@ class TwigExtension extends \Twig_Extension { /** * Returns the render array for a single entity field. * - * Example: - * @code - * {{ drupal_field('field_image', 'node', 1) }} - * {{ drupal_field('field_image', 'node', 1, 'teaser') }} - * {{ drupal_field('field_image', 'node', 1, {type: 'image_url', settings: {image_style: 'large'}}) }} - * @endcode - * * @param string $field_name * The field name. * @param string $entity_type @@ -407,11 +641,6 @@ class TwigExtension extends \Twig_Extension { /** * Returns the render array for Drupal menu. * - * Example: - * @code - * {{ drupal_menu('main') }} - * @endcode - * * @param string $menu_name * The name of the menu. * @param int $level @@ -456,11 +685,6 @@ class TwigExtension extends \Twig_Extension { /** * Builds and processes a form for a given form ID. * - * Example: - * @code - * {{ drupal_form('Drupal\\search\\Form\\SearchBlockForm') }} - * @endcode - * * @param string $form_id * The form ID. * @param ... @@ -477,24 +701,6 @@ class TwigExtension extends \Twig_Extension { /** * Builds an image. * - * Examples: - * @code - * {# Render image specified by file ID. #} - * {{ drupal_image(123) }} - * - * {# Render image specified by file UUID. #} - * {{ drupal_image('9bb27144-e6b2-4847-bd24-adcc59613ec0') }} - * - * {# Render image specified by file URI. #} - * {{ drupal_image('public://ocean.jpg') }} - * - * {# Render image using 'thumbnail' image style and custom attributes. #} - * {{ drupal_image('public://ocean.jpg', 'thumbnail', {alt: 'The alternative text'|t, title: 'The title text'|t}) }} - * - * {# Render responsive image. #} - * {{ drupal_image('public://ocean.jpg', 'wide', responsive=true) }} - * @endcode - * * @param mixed $property * A property to identify the image. * @param string $style @@ -567,11 +773,6 @@ class TwigExtension extends \Twig_Extension { /** * Replaces a given tokens with appropriate value. * - * Example: - * @code - * {{ drupal_token('site:name') }} - * @endcode - * * @param string $token * A replaceable token. * @param array $data @@ -596,11 +797,6 @@ class TwigExtension extends \Twig_Extension { /** * Retrieves data from a given configuration object. * - * Example: - * @code - * {{ drupal_config('system.site', 'name') }} - * @endcode - * * @param string $name * The name of the configuration object to construct. * @param string $key @@ -616,18 +812,6 @@ class TwigExtension extends \Twig_Extension { /** * Dumps information about variables. * - * Examples: - * @code - * {# Basic usage. #} - * {{ drupal_dump(var) }} - * - * {# Same as above but shorter. #} - * {{ dd(var) }} - * - * {# Dump all available variables for the current template. #} - * {{ dd() }} - * @endcode - * * @param array $context * Variables from the Twig template. * @param mixed $variable @@ -662,15 +846,6 @@ class TwigExtension extends \Twig_Extension { /** * Generates a URL from an internal path. * - * Examples: - * @code - * {# Basic usage. #} - * {{ drupal_url('node/1) }} - * - * {# Complex URL. #} - * {{ drupal_url('node/1', {query: {foo: 'bar'}, fragment: 'example', absolute: true}) }} - * @endcode - * * @param string $user_input * User input for a link or path. * @param array $options @@ -702,15 +877,6 @@ class TwigExtension extends \Twig_Extension { /** * Generates a link from an internal path. * - * Examples: - * @code - * {# It supports the same options as drupal_url(), plus attributes. #} - * {{ drupal_link('View'|t, 'node/1', {attributes: {target: '_blank'}}) }} - * - * {# This link will only be shown for privileged users. #} - * {{ drupal_link('Example'|t, '/admin', check_access=true) }} - * @endcode - * * @param string $text * The text to be used for the link. * @param string $user_input @@ -757,21 +923,6 @@ class TwigExtension extends \Twig_Extension { /** * Builds contextual links. * - * Examples: - * @code - * {# Basic usage. #} - *
- * {{ contextual_links('entity.view.edit_form:view=frontpage&display_id=feed_1') }} - * {{ drupal_view('frontpage') }} - *
- * - * {# Multiple links. #} - *
- * {{ contextual_links('node:node=123|block_content:block_content=123') }} - * {{ content }} - *
- * @endcode - * * @param string $id * A serialized representation of a #contextual_links property value array. * @@ -809,18 +960,6 @@ class TwigExtension extends \Twig_Extension { /** * Replaces all tokens in a given string with appropriate values. * - * Example: - * @code - * {# Basic usage. #} - * {{ '

[site:name]

[site:slogan]
'|token_replace }} - * - * {# This is more suited to large markup (requires Twig >= 1.41). #} - * {% apply token_replace %} - *

[site:name]

- *
[site:slogan]
- * {% endapply %} - * @endcode - * * @param string $text * An HTML string containing replaceable tokens. * @@ -834,14 +973,6 @@ class TwigExtension extends \Twig_Extension { /** * Performs a regular expression search and replace. * - * Example: - * @code - * {{ 'Drupal - community plumbing!'|preg_replace('/(Drupal)/', '$1') }} - * @endcode - * - * For simple string interpolation consider using built-in 'replace' or - * 'format' Twig filters. - * * @param string $text * The text to search and replace. * @param string $pattern @@ -859,11 +990,6 @@ class TwigExtension extends \Twig_Extension { /** * Returns the URL of this image derivative for an original image path or URI. * - * Example: - * @code - * {{ 'public://images/ocean.jpg'|image_style('thumbnail') }} - * @endcode - * * @param string $path * The path or URI to the original image. * @param string $style @@ -891,11 +1017,6 @@ class TwigExtension extends \Twig_Extension { /** * Transliterates text from Unicode to US-ASCII. * - * Example: - * @code - * {{ 'Привет!'|transliterate }} - * @endcod - * * @param string $string * The string to transliterate. * @param string $langcode @@ -920,11 +1041,6 @@ class TwigExtension extends \Twig_Extension { /** * Runs all the enabled filters on a piece of text. * - * Example. - * @code - * {{ 'bold strong'|check_markup('restricted_html') }} - * @endcode - * * @param string $text * The text to be filtered. * @param string|null $format_id @@ -948,11 +1064,6 @@ class TwigExtension extends \Twig_Extension { /** * Truncates a UTF-8-encoded string safely to a number of characters. * - * Example: - * @code - * {{ 'Some long text'|truncate(10, true) }} - * @endcode - * * @param string $string * The string to truncate. * @param int $max_length @@ -977,15 +1088,6 @@ class TwigExtension extends \Twig_Extension { /** * Adds new element to the array. * - * Examples: - * @code - * {# Set top level value. #} - * {{ content.field_image|with('#title', 'Photo'|t) }} - * - * {# Set nested value. #} - * {{ content|with(['field_image', '#title'], 'Photo'|t) }} - * @endcode - * * @param array $build * The renderable array to add the child item. * @param mixed $key @@ -1009,21 +1111,6 @@ class TwigExtension extends \Twig_Extension { /** * Returns a render array for entity, field list or field item. * - * Examples: - * - * Do not put this into node.html.twig template to avoid recursion. - * @code - * {{ node|view }} - * {{ node|view('teaser') }} - * @endcode - * - * @code - * {{ node.field_image|view }} - * {{ node.field_image[0]|view }} - * {{ node.field_image|view('teaser') }} - * {{ node.field_image|view({settings: {image_style: 'thumbnail'}}) }} - * @endcode - * * @param mixed $object * The object to build a render array from. * @param string|array $display_options @@ -1059,15 +1146,6 @@ class TwigExtension extends \Twig_Extension { /** * Filters out the children of a render array, optionally sorted by weight. * - * Example: - * @code - * - * @endcode - * * @param array $build * The render array whose children are to be filtered. * @param bool $sort @@ -1084,26 +1162,6 @@ class TwigExtension extends \Twig_Extension { /** * Returns a URL path to the file. * - * Examples: - * - * For string arguments it works similar to core file_url() Twig function. - * @code - * {{ 'public://sea.jpg'|file_url }} - * @endcode - * - * When field item list passed the URL will be extracted from the first item. - * In order to get URL of specific item specify its delta explicitly using - * array notation. - * @code - * {{ node.field_image|file_url }} - * {{ node.field_image[0]|file_url }} - * @endcode - * - * Media fields are fully supported including OEmbed resources. - * @code - * {{ node.field_media|file_url }} - * @endcode - * * @param string|object $input * Can be either file URI or an object that contains the URI. * @@ -1153,25 +1211,6 @@ class TwigExtension extends \Twig_Extension { /** * Evaluates a string of PHP code. * - * PHP filter is disabled by default. You can enable it in settings.php file - * as follows: - * @code - * $settings['twig_tweak_enable_php_filter'] = TRUE; - * @endcode - * - * Usage example: - * @code - * {{ 'return date('Y');'|php }} - * @endcode - * - * Using PHP filter is discouraged as it may cause security implications. In - * fact it is very rarely needed. - * - * The above code can be replaced with following. - * @code - * {{ 'now'|date('Y') }} - * @endcode - * * @param string $code * Valid PHP code to be evaluated. *