diff --git a/README.md b/README.md index 4f3821d..d1f6e11 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,6 @@ drush ev "print_r(array_keys(\Drupal::service('plugin.manager.block')->getDefini {{ drupal_image('public://ocean.jpg', 'wide', responsive=true) }} ``` - ### Drupal Token ```twig {{ drupal_token('site:name') }} diff --git a/src/TwigTweakExtension.php b/src/TwigTweakExtension.php index ca94129..e74a33c 100644 --- a/src/TwigTweakExtension.php +++ b/src/TwigTweakExtension.php @@ -7,21 +7,15 @@ use Drupal\Component\Utility\Unicode; use Drupal\Component\Uuid\Uuid; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Extension\ModuleHandlerInterface; -use Drupal\Core\Field\EntityReferenceFieldItemListInterface; use Drupal\Core\Field\FieldItemInterface; use Drupal\Core\Field\FieldItemListInterface; -use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem; use Drupal\Core\Link; use Drupal\Core\Render\Element; use Drupal\Core\Render\Markup; use Drupal\Core\Site\Settings; use Drupal\Core\Theme\ThemeManagerInterface; use Drupal\Core\Url; -use Drupal\file\Entity\File; -use Drupal\file\FileInterface; use Drupal\image\Entity\ImageStyle; -use Drupal\media\MediaInterface; -use Drupal\media\Plugin\media\Source\OEmbedInterface; use Twig\Environment; use Twig\Extension\AbstractExtension; use Twig\Markup as TwigMarkup; @@ -581,18 +575,7 @@ class TwigTweakExtension extends AbstractExtension { * 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); - } + return \Drupal::service('twig_tweak.uri_extractor')->extractUri($input); } /** @@ -600,12 +583,14 @@ class TwigTweakExtension extends AbstractExtension { * * @param string|object $input * Can be either file URI or an object that contains the URI. + * @param bool $relative + * (optional) Whether the URL should be root-relative, defaults to true. * * @return string|null * A URL that may be used to access the file. */ - public static function fileUrlFilter($input): ?string { - return \Drupal::service('twig_tweak.url_extractor')->extractUrl($input); + public static function fileUrlFilter($input, bool $relative = TRUE): ?string { + return \Drupal::service('twig_tweak.url_extractor')->extractUrl($input, $relative); } /** @@ -630,29 +615,4 @@ 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(); - } - } - } diff --git a/src/UriExtractor.php b/src/UriExtractor.php new file mode 100644 index 0000000..f8fe577 --- /dev/null +++ b/src/UriExtractor.php @@ -0,0 +1,84 @@ +entityTypeManager = $entity_type_manager; + } + + /** + * Returns a URI to the file. + * + * @param object|null $input + * An object that contains the URI. + * + * @return string|null + * A URI that may be used to access the file. + */ + public function extractUri(?object $input): ?string { + if ($input instanceof ContentEntityInterface) { + return self::getUriFromEntity($input); + } + elseif ($input instanceof EntityReferenceFieldItemListInterface) { + if ($item = $input->first()) { + return $this->getUriFromEntity($item->entity); + } + } + elseif ($input instanceof EntityReferenceItem) { + return self::getUriFromEntity($input->entity); + } + return NULL; + } + + /** + * Extracts file URI from content entity. + * + * @param \Drupal\Core\Entity\ContentEntityInterface $entity + * Entity object that contains information about the file. + * + * @return string|null + * A URI that may be used to access the file. + */ + private function getUriFromEntity(ContentEntityInterface $entity): ?string { + if ($entity instanceof MediaInterface) { + $source = $entity->getSource(); + $value = $source->getSourceFieldValue($entity); + if ($source instanceof OEmbedInterface) { + return $value; + } + /** @var \Drupal\file\FileInterface $file */ + $file = $this->entityTypeManager->getStorage('file')->load($value); + if ($file) { + return $file->getFileUri(); + } + } + elseif ($entity instanceof FileInterface) { + return $entity->getFileUri(); + } + return NULL; + } + +} diff --git a/src/UrlExtractor.php b/src/UrlExtractor.php index 00c2795..a818e5c 100644 --- a/src/UrlExtractor.php +++ b/src/UrlExtractor.php @@ -11,7 +11,7 @@ use Drupal\media\MediaInterface; use Drupal\media\Plugin\media\Source\OEmbedInterface; /** - * UrlExtractor service. + * URL extractor service. */ class UrlExtractor { @@ -35,7 +35,7 @@ class UrlExtractor { * @param string|object $input * Can be either file URI or an object that contains the URI. * @param bool $relative - * (optional) Whether the URL should be root-relative, defaults to TRUE. + * (optional) Whether the URL should be root-relative, defaults to true. * * @return string|null * A URL that may be used to access the file. @@ -65,7 +65,7 @@ class UrlExtractor { * @param \Drupal\Core\Entity\ContentEntityInterface $entity * Entity object that contains information about the file. * @param bool $relative - * (optional) Whether the URL should be root-relative, defaults to TRUE. + * (optional) Whether the URL should be root-relative, defaults to true. * * @return string|null * A URL that may be used to access the file. @@ -81,6 +81,7 @@ class UrlExtractor { return $value; } else { + /** @var \Drupal\file\FileInterface $file */ $file = $this->entityTypeManager->getStorage('file')->load($value); if ($file) { return $file->createFileUrl($relative); diff --git a/tests/src/Functional/TwigTweakTest.php b/tests/src/Functional/TwigTweakTest.php index d317a8e..46b3d65 100644 --- a/tests/src/Functional/TwigTweakTest.php +++ b/tests/src/Functional/TwigTweakTest.php @@ -359,8 +359,12 @@ final class TwigTweakTest extends BrowserTestBase { $xpath = '//div[@class = "tt-image-style-from-file-uri-from-media-field" and contains(text(), "styles/thumbnail/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")]'; + // -- File URL from URI (relative). + $xpath = '//div[@class = "tt-file-url-from-uri" and contains(text(), "/files/image-test.png") and not(contains(text(), "http://"))]'; + $this->assertXpath($xpath); + + // -- File URL from URI (absolute). + $xpath = '//div[@class = "tt-file-url-from-uri-absolute" and contains(text(), "/files/image-test.png") and contains(text(), "http://")]'; $this->assertXpath($xpath); // -- File URL from image field. diff --git a/tests/src/Kernel/AbstractExtractorTest.php b/tests/src/Kernel/AbstractExtractorTest.php new file mode 100644 index 0000000..4f1f398 --- /dev/null +++ b/tests/src/Kernel/AbstractExtractorTest.php @@ -0,0 +1,91 @@ +installConfig(['node', 'twig_tweak_test']); + $this->installSchema('file', 'file_usage'); + $this->installEntitySchema('file'); + $this->installEntitySchema('media'); + + $test_files = $this->getTestFiles('image'); + // + $image_file = File::create([ + 'uri' => $test_files[0]->uri, + 'uuid' => 'a2cb2b6f-7bf8-4da4-9de5-316e93487518', + 'status' => FILE_STATUS_PERMANENT, + ]); + $image_file->save(); + + $media_file = File::create([ + 'uri' => $test_files[2]->uri, + 'uuid' => '5dd794d0-cb75-4130-9296-838aebc1fe74', + 'status' => FILE_STATUS_PERMANENT, + ]); + $media_file->save(); + + $media = Media::create([ + 'bundle' => 'image', + 'name' => 'Image 1', + 'field_media_image' => ['target_id' => $media_file->id()], + ]); + $media->save(); + + $node_values = [ + 'title' => 'Alpha', + 'type' => 'page', + 'field_image' => [ + 'target_id' => $image_file->id(), + ], + 'field_media' => [ + 'target_id' => $media->id(), + ], + ]; + $this->node = Node::create($node_values); + } + +} diff --git a/tests/src/Kernel/UriExtractorTest.php b/tests/src/Kernel/UriExtractorTest.php new file mode 100644 index 0000000..08786dc --- /dev/null +++ b/tests/src/Kernel/UriExtractorTest.php @@ -0,0 +1,61 @@ +container->get('twig_tweak.uri_extractor'); + + $url = $extractor->extractUri(NULL); + self::assertNull($url); + + $url = $extractor->extractUri($this->node); + self::assertNull($url); + + $url = $extractor->extractUri($this->node->get('title')); + self::assertNull($url); + + $url = $extractor->extractUri($this->node->get('field_image')[0]); + self::assertSame('public://image-test.png', $url); + + $url = $extractor->extractUri($this->node->get('field_image')[1]); + self::assertNull($url); + + $url = $extractor->extractUri($this->node->get('field_image')); + self::assertSame('public://image-test.png', $url); + + $url = $extractor->extractUri($this->node->get('field_image')->entity); + self::assertSame('public://image-test.png', $url); + + $this->node->get('field_image')->removeItem(0); + $url = $extractor->extractUri($this->node->get('field_image')); + self::assertNull($url); + + $url = $extractor->extractUri($this->node->get('field_media')[0]); + self::assertSame('public://image-test.gif', $url); + + $url = $extractor->extractUri($this->node->get('field_media')[1]); + self::assertNull($url); + + $url = $extractor->extractUri($this->node->get('field_media')); + self::assertSame('public://image-test.gif', $url); + + $url = $extractor->extractUri($this->node->get('field_media')->entity); + self::assertSame('public://image-test.gif', $url); + + $this->node->get('field_media')->removeItem(0); + $url = $extractor->extractUri($this->node->get('field_media')); + self::assertNull($url); + } + +} diff --git a/tests/src/Kernel/UrlExtractorTest.php b/tests/src/Kernel/UrlExtractorTest.php index 53d51f8..f8723fd 100644 --- a/tests/src/Kernel/UrlExtractorTest.php +++ b/tests/src/Kernel/UrlExtractorTest.php @@ -2,93 +2,12 @@ namespace Drupal\Tests\twig_tweak\Kernel; -use Drupal\file\Entity\File; -use Drupal\KernelTests\KernelTestBase; -use Drupal\media\Entity\Media; -use Drupal\node\Entity\Node; -use Drupal\Tests\TestFileCreationTrait; - /** - * A test for UrlExtractor. + * A test for URL Extractor service. * * @group twig_tweak */ -final class UrlExtractorTest extends KernelTestBase { - - use TestFileCreationTrait; - - /** - * A node to test. - * - * @var \Drupal\node\NodeInterface - */ - private $node; - - /** - * {@inheritdoc} - */ - public static $modules = [ - 'twig_tweak', - 'twig_tweak_test', - 'system', - 'views', - 'node', - 'block', - 'image', - 'field', - 'text', - 'media', - 'file', - 'user', - 'filter', - ]; - - /** - * {@inheritdoc} - */ - public function setUp(): void { - parent::setUp(); - - $this->installConfig(['node', 'twig_tweak_test']); - $this->installSchema('file', 'file_usage'); - $this->installEntitySchema('file'); - $this->installEntitySchema('media'); - - $test_files = $this->getTestFiles('image'); - // - $image_file = File::create([ - 'uri' => $test_files[0]->uri, - 'uuid' => 'a2cb2b6f-7bf8-4da4-9de5-316e93487518', - 'status' => FILE_STATUS_PERMANENT, - ]); - $image_file->save(); - - $media_file = File::create([ - 'uri' => $test_files[2]->uri, - 'uuid' => '5dd794d0-cb75-4130-9296-838aebc1fe74', - 'status' => FILE_STATUS_PERMANENT, - ]); - $media_file->save(); - - $media = Media::create([ - 'bundle' => 'image', - 'name' => 'Image 1', - 'field_media_image' => ['target_id' => $media_file->id()], - ]); - $media->save(); - - $node_values = [ - 'title' => 'Alpha', - 'type' => 'page', - 'field_image' => [ - 'target_id' => $image_file->id(), - ], - 'field_media' => [ - 'target_id' => $media->id(), - ], - ]; - $this->node = Node::create($node_values); - } +final class UrlExtractorTest extends AbstractExtractorTest { /** * Test callback. 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 00ed338..b4d292c 100644 --- a/tests/twig_tweak_test/templates/twig-tweak-test.html.twig +++ b/tests/twig_tweak_test/templates/twig-tweak-test.html.twig @@ -93,6 +93,7 @@
{{ media_uri|image_style('thumbnail') }}
{% endif %}
{{ 'public://image-test.png'|file_url }}
+
{{ 'public://image-test.png'|file_url(false) }}
{{ node.field_image|file_url }}
{{ node.field_image[0]|file_url }}
{{ node.field_media|file_url }}
diff --git a/twig_tweak.services.yml b/twig_tweak.services.yml index 582c740..c9d4f92 100644 --- a/twig_tweak.services.yml +++ b/twig_tweak.services.yml @@ -35,3 +35,7 @@ services: twig_tweak.url_extractor: class: Drupal\twig_tweak\UrlExtractor arguments: ['@entity_type.manager'] + + twig_tweak.uri_extractor: + class: Drupal\twig_tweak\UriExtractor + arguments: ['@entity_type.manager']