Browse Source

Add entity_url and entity_link filters

merge-requests/14/head
Chi 3 years ago
parent
commit
d4a7cf8af5
  1. 22
      docs/cheat-sheet.md
  2. 26
      src/TwigTweakExtension.php
  3. 24
      tests/src/Functional/TwigTweakTest.php
  4. 6
      tests/twig_tweak_test/templates/twig-tweak-test.html.twig

22
docs/cheat-sheet.md

@ -311,6 +311,28 @@ It is also possible to extract file URL directly from an entity.
{{ media|file_url }} {{ media|file_url }}
``` ```
## Entity URL
Gets the URL object for the entity.
See \Drupal\Core\Entity\EntityInterface::toUrl()
```twig
{# Creates canonical URL for the node. #}
{{ node|entity_url }}
{# Creates URL for the node edit form. #}
{{ node|entity_url('edit-form') }}
```
## Entity Link
Generates the HTML for a link to this entity.
See \Drupal\Core\Entity\EntityInterface::toLink()
```twig
{# Creates a link to the node using the node's label. #}
{{ node|entity_link }}
{# Creates link to node comment form. #}
{{ node|entity_link('Add new comment'|t, 'canonical', {fragment: 'comment-form'}) }}
```
## Entity translation ## Entity translation
That is typically needed when printing data from referenced entities. That is typically needed when printing data from referenced entities.
```twig ```twig

26
src/TwigTweakExtension.php

@ -112,6 +112,8 @@ class TwigTweakExtension extends AbstractExtension {
new TwigFilter('children', [self::class, 'childrenFilter']), new TwigFilter('children', [self::class, 'childrenFilter']),
new TwigFilter('file_uri', [self::class, 'fileUriFilter']), new TwigFilter('file_uri', [self::class, 'fileUriFilter']),
new TwigFilter('file_url', [self::class, 'fileUrlFilter']), new TwigFilter('file_url', [self::class, 'fileUrlFilter']),
new TwigFilter('entity_url', [self::class, 'entityUrl']),
new TwigFilter('entity_link', [self::class, 'entityLink']),
new TwigFilter('translation', [self::class, 'entityTranslation']), new TwigFilter('translation', [self::class, 'entityTranslation']),
new TwigFilter('cache_metadata', [self::class, 'CacheMetadata']), new TwigFilter('cache_metadata', [self::class, 'CacheMetadata']),
]; ];
@ -624,6 +626,30 @@ class TwigTweakExtension extends AbstractExtension {
return \Drupal::service('twig_tweak.url_extractor')->extractUrl($input, $relative); return \Drupal::service('twig_tweak.url_extractor')->extractUrl($input, $relative);
} }
/**
* Gets the URL object for the entity.
*
* @todo Remove this once Drupal allows `toUrl` method in the sandbox policy.
*
* @see https://www.drupal.org/node/2907810
* @see \Drupal\Core\Entity\EntityInterface::toUrl()
*/
public static function entityUrl(EntityInterface $entity, string $rel = 'canonical', array $options = []): Url {
return $entity->toUrl($rel, $options);
}
/**
* Gets the URL object for the entity.
*
* @todo Remove this once Drupal allows `toLink` method in the sandbox policy.
*
* @see https://www.drupal.org/node/2907810
* @see \Drupal\Core\Entity\EntityInterface::toLink()
*/
public static function entityLink(EntityInterface $entity, ?string $text = NULL, string $rel = 'canonical', array $options = []): Link {
return $entity->toLink($text, $rel, $options);
}
/** /**
* Returns the translation for the given entity. * Returns the translation for the given entity.
* *

24
tests/src/Functional/TwigTweakTest.php

@ -390,6 +390,30 @@ final class TwigTweakTest extends BrowserTestBase {
$xpath = '//div[@class = "tt-file-url-from-media-field" and contains(text(), "/files/image-1.png")]'; $xpath = '//div[@class = "tt-file-url-from-media-field" and contains(text(), "/files/image-1.png")]';
$this->assertXpath($xpath); $this->assertXpath($xpath);
// -- Entity URL (canonical).
$xpath = '//div[@class = "tt-entity-url" and contains(text(), "/node/1#test") and not(contains(text(), "http"))]';
$this->assertXpath($xpath);
// -- Entity URL (absolute).
$xpath = '//div[@class = "tt-entity-url-absolute" and contains(text(), "/node/1") and contains(text(), "http")]';
$this->assertXpath($xpath);
// -- Entity URL (edit form).
$xpath = '//div[@class = "tt-entity-url-edit-form" and contains(text(), "/node/1/edit")]';
$this->assertXpath($xpath);
// -- Entity Link (canonical).
$xpath = '//div[@class = "tt-entity-link"]/a[text() = "Alpha" and contains(@href, "/node/1") and not(contains(@href, "http"))]';
$this->assertXpath($xpath);
// -- Entity Link (absolute).
$xpath = '//div[@class = "tt-entity-link-absolute"]/a[text() = "Example" and contains(@href, "/node/1") and contains(@href, "http")]';
$this->assertXpath($xpath);
// -- Entity Link (edit form).
$xpath = '//div[@class = "tt-entity-link-edit-form"]/a[text() = "Edit" and contains(@href, "/node/1/edit")]';
$this->assertXpath($xpath);
// -- Entity translation. // -- Entity translation.
// This is just a smoke test because the node is not translatable. // This is just a smoke test because the node is not translatable.
$xpath = '//div[@class = "tt-translation" and contains(text(), "Alpha")]'; $xpath = '//div[@class = "tt-translation" and contains(text(), "Alpha")]';

6
tests/twig_tweak_test/templates/twig-tweak-test.html.twig

@ -99,6 +99,12 @@
<div class="tt-file-url-from-image-field">{{ node.field_image|file_url }}</div> <div class="tt-file-url-from-image-field">{{ node.field_image|file_url }}</div>
<div class="tt-file-url-from-image-field-delta">{{ node.field_image[0]|file_url }}</div> <div class="tt-file-url-from-image-field-delta">{{ node.field_image[0]|file_url }}</div>
<div class="tt-file-url-from-media-field">{{ node.field_media|file_url }}</div> <div class="tt-file-url-from-media-field">{{ node.field_media|file_url }}</div>
<div class="tt-entity-url">{{ node|entity_url(options={fragment: 'test'}) }}</div>
<div class="tt-entity-url-absolute">{{ node|entity_url(options={absolute: true}) }}</div>
<div class="tt-entity-url-edit-form">{{ node|entity_url('edit-form') }}</div>
<div class="tt-entity-link">{{ node|entity_link }}</div>
<div class="tt-entity-link-absolute">{{ node|entity_link('Example', options={absolute: true}) }}</div>
<div class="tt-entity-link-edit-form">{{ node|entity_link('Edit', 'edit-form') }}</div>
<div class="tt-translation">{{ (node|translation).title.value }}</div> <div class="tt-translation">{{ (node|translation).title.value }}</div>
<div class="tt-functions_alter">{{ foo('bar') }}</div> <div class="tt-functions_alter">{{ foo('bar') }}</div>
<div class="tt-filters_alter">{{ 'foo'|bar }}</div> <div class="tt-filters_alter">{{ 'foo'|bar }}</div>

Loading…
Cancel
Save