diff --git a/README.md b/README.md index baa5b51..87a08a7 100644 --- a/README.md +++ b/README.md @@ -273,6 +273,26 @@ This is an opposite of core `without` filter. ``` +### File URI +When field item list passed the URI will be extracted from the first item. In +order to get URI of specific item specify its delta explicitly using array +notation. +```twig +{{ node.field_image|file_uri }} +{{ node.field_image[0]|file_uri }} +``` + +Media fields are fully supported including OEmbed resources, in which case +it will return the URL to the resource, similar to the `file_url` filter. +```twig +{{ node.field_media|file_uri }} +``` + +Useful to apply the `image_style` filter to Media fields. +```twig +{{ node.field_media|file_uri|image_style('thumbnail') }} +``` + ### File URL For string arguments it works similar to core `file_url()` Twig function. ```twig diff --git a/src/TwigTweakExtension.php b/src/TwigTweakExtension.php index b23ec21..873403c 100644 --- a/src/TwigTweakExtension.php +++ b/src/TwigTweakExtension.php @@ -114,6 +114,7 @@ class TwigTweakExtension extends AbstractExtension { new TwigFilter('view', [self::class, 'viewFilter']), new TwigFilter('with', [self::class, 'withFilter']), new TwigFilter('children', [self::class, 'childrenFilter']), + new TwigFilter('file_uri', [self::class, 'fileUriFilter']), new TwigFilter('file_url', [self::class, 'fileUrlFilter']), ]; @@ -570,6 +571,30 @@ class TwigTweakExtension extends AbstractExtension { return array_intersect_key($build, array_flip($keys)); } + /** + * Returns a URI to the file. + * + * @param object $input + * An object that contains the URI. + * + * @return string|null + * A URI that may be used to access the file. + */ + public static function fileUriFilter($input): ?string { + if ($input instanceof EntityReferenceFieldItemListInterface) { + $referenced_entities = $input->referencedEntities(); + if (isset($referenced_entities[0])) { + return self::getUriFromEntity($referenced_entities[0]); + } + } + elseif ($input instanceof EntityReferenceItem) { + return self::getUriFromEntity($input->entity); + } + elseif ($input instanceof EntityInterface) { + return self::getUriFromEntity($input); + } + } + /** * Returns a URL path to the file. * @@ -613,6 +638,31 @@ class TwigTweakExtension extends AbstractExtension { return $output; } + /** + * Extracts file URI from content entity. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * Entity object that contains information about the file. + * + * @return string|null + * A URI that may be used to access the file. + */ + private static function getUriFromEntity(EntityInterface $entity): ?string { + if ($entity instanceof MediaInterface) { + $source = $entity->getSource(); + $value = $source->getSourceFieldValue($entity); + if ($source instanceof OEmbedInterface) { + return $value; + } + elseif ($file = File::load($value)) { + return $file->getFileUri(); + } + } + elseif ($entity instanceof FileInterface) { + return $entity->getFileUri(); + } + } + /** * Extracts file URL from content entity. * diff --git a/tests/src/Functional/TwigTweakTest.php b/tests/src/Functional/TwigTweakTest.php index 042a8e7..05eb194 100644 --- a/tests/src/Functional/TwigTweakTest.php +++ b/tests/src/Functional/TwigTweakTest.php @@ -302,6 +302,10 @@ final class TwigTweakTest extends BrowserTestBase { $xpath = '//div[@class = "tt-image-style" and contains(text(), "styles/thumbnail/public/images/ocean.jpg")]'; $this->assertXpath($xpath); + // -- Image style from File URI from media field. + $xpath = '//div[@class = "tt-image-style-from-file-uri-from-media-field" and contains(text(), "styles/thumbnail/public/image-1.png")]'; + $this->assertXpath($xpath); + // -- Transliterate. $xpath = '//div[@class = "tt-transliterate" and contains(text(), "Privet!")]'; $this->assertXpath($xpath); @@ -343,6 +347,18 @@ final class TwigTweakTest extends BrowserTestBase { $xpath = '//div[@class = "tt-field-item-view" and text() = "Alpha"]'; $this->assertXpath($xpath); + // -- File URI from image field. + $xpath = '//div[@class = "tt-file-uri-from-image-field" and contains(text(), "public://image-test.png")]'; + $this->assertXpath($xpath); + + // -- File URI from a specific image field item. + $xpath = '//div[@class = "tt-file-uri-from-image-field-delta" and contains(text(), "public://image-test.png")]'; + $this->assertXpath($xpath); + + // -- File URI from media field. + $xpath = '//div[@class = "tt-file-uri-from-media-field" and contains(text(), "public://image-1.png")]'; + $this->assertXpath($xpath); + // -- File URL from URI. $xpath = '//div[@class = "tt-file-url-from-uri" and contains(text(), "/files/image-test.png")]'; $this->assertXpath($xpath); diff --git a/tests/twig_tweak_test/templates/twig-tweak-test.html.twig b/tests/twig_tweak_test/templates/twig-tweak-test.html.twig index 0cca8eb..b3fe761 100644 --- a/tests/twig_tweak_test/templates/twig-tweak-test.html.twig +++ b/tests/twig_tweak_test/templates/twig-tweak-test.html.twig @@ -62,6 +62,7 @@
{{ 'Site name: [site:name]'|token_replace }}
{{ 'FOO'|preg_replace('/(foo)/i', '$1-bar') }}
{{ 'public://images/ocean.jpg'|image_style('thumbnail') }}
+
{{ node.field_media|file_uri|image_style('thumbnail') }}
{{ 'Привет!'|transliterate('ru') }}
{{ 'bold strong'|check_markup('twig_tweak_test') }}
{{ 12345|format_size() }}
@@ -85,6 +86,9 @@
{{ node|view }}
{{ node.title|view }}
{{ node.title[0]|view }}
+
{{ node.field_image|file_uri }}
+
{{ node.field_image[0]|file_uri }}
+
{{ node.field_media|file_uri }}
{{ 'public://image-test.png'|file_url }}
{{ node.field_image|file_url }}
{{ node.field_image[0]|file_url }}