Chi
4 years ago
5 changed files with 281 additions and 37 deletions
@ -0,0 +1,96 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace Drupal\twig_tweak; |
||||||
|
|
||||||
|
use Drupal\Core\Entity\ContentEntityInterface; |
||||||
|
use Drupal\Core\Entity\EntityTypeManagerInterface; |
||||||
|
use Drupal\Core\Field\EntityReferenceFieldItemListInterface; |
||||||
|
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem; |
||||||
|
use Drupal\file\FileInterface; |
||||||
|
use Drupal\media\MediaInterface; |
||||||
|
use Drupal\media\Plugin\media\Source\OEmbedInterface; |
||||||
|
|
||||||
|
/** |
||||||
|
* UrlExtractor service. |
||||||
|
*/ |
||||||
|
class UrlExtractor { |
||||||
|
|
||||||
|
/** |
||||||
|
* The entity type manager. |
||||||
|
* |
||||||
|
* @var \Drupal\Core\Entity\EntityTypeManagerInterface |
||||||
|
*/ |
||||||
|
protected $entityTypeManager; |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructs a UrlExtractor object. |
||||||
|
*/ |
||||||
|
public function __construct(EntityTypeManagerInterface $entity_type_manager) { |
||||||
|
$this->entityTypeManager = $entity_type_manager; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Extracts file URL from a string or object. |
||||||
|
* |
||||||
|
* @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 function extractUrl($input, bool $relative = TRUE): ?string { |
||||||
|
if (is_string($input)) { |
||||||
|
$url = file_create_url($input); |
||||||
|
return $relative ? file_url_transform_relative($url) : $url; |
||||||
|
} |
||||||
|
elseif ($input instanceof ContentEntityInterface) { |
||||||
|
return $this->getUrlFromEntity($input, $relative); |
||||||
|
} |
||||||
|
elseif ($input instanceof EntityReferenceFieldItemListInterface) { |
||||||
|
if ($item = $input->first()) { |
||||||
|
return $this->getUrlFromEntity($item->entity, $relative); |
||||||
|
} |
||||||
|
} |
||||||
|
elseif ($input instanceof EntityReferenceItem) { |
||||||
|
return $this->getUrlFromEntity($input->entity, $relative); |
||||||
|
} |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Extracts file URL from content entity. |
||||||
|
* |
||||||
|
* @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. |
||||||
|
* |
||||||
|
* @return string|null |
||||||
|
* A URL that may be used to access the file. |
||||||
|
*/ |
||||||
|
private function getUrlFromEntity(ContentEntityInterface $entity, bool $relative = TRUE): ?string { |
||||||
|
if ($entity instanceof MediaInterface) { |
||||||
|
$source = $entity->getSource(); |
||||||
|
$value = $source->getSourceFieldValue($entity); |
||||||
|
if (!$value) { |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
elseif ($source instanceof OEmbedInterface) { |
||||||
|
return $value; |
||||||
|
} |
||||||
|
else { |
||||||
|
$file = $this->entityTypeManager->getStorage('file')->load($value); |
||||||
|
if ($file) { |
||||||
|
return $file->createFileUrl($relative); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
elseif ($entity instanceof FileInterface) { |
||||||
|
return $entity->createFileUrl($relative); |
||||||
|
} |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,168 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
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. |
||||||
|
* |
||||||
|
* @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); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Test callback. |
||||||
|
*/ |
||||||
|
public function testUrlExtractor(): void { |
||||||
|
|
||||||
|
$extractor = $this->container->get('twig_tweak.url_extractor'); |
||||||
|
$base_url = file_create_url(''); |
||||||
|
|
||||||
|
$request = \Drupal::request(); |
||||||
|
$absolute_url = "{$request->getScheme()}://{$request->getHost()}/foo/bar.txt"; |
||||||
|
$url = $extractor->extractUrl($absolute_url); |
||||||
|
self::assertSame('/foo/bar.txt', $url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl($absolute_url, FALSE); |
||||||
|
self::assertSame($base_url . 'foo/bar.txt', $url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl('foo/bar.jpg'); |
||||||
|
self::assertSame('/foo/bar.jpg', $url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl('foo/bar.jpg', FALSE); |
||||||
|
self::assertSame($base_url . 'foo/bar.jpg', $url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl(''); |
||||||
|
self::assertSame('/', $url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl('', FALSE); |
||||||
|
self::assertSame($base_url, $url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl(NULL); |
||||||
|
self::assertNull($url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl($this->node); |
||||||
|
self::assertNull($url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl($this->node->get('title')); |
||||||
|
self::assertNull($url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl($this->node->get('field_image')[0]); |
||||||
|
self::assertStringEndsWith('/files/image-test.png', $url); |
||||||
|
self::assertStringNotContainsString($base_url, $url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl($this->node->get('field_image')[0], FALSE); |
||||||
|
self::assertStringStartsWith($base_url, $url); |
||||||
|
self::assertStringEndsWith('/files/image-test.png', $url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl($this->node->get('field_image')[1]); |
||||||
|
self::assertNull($url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl($this->node->get('field_image')); |
||||||
|
self::assertStringEndsWith('/files/image-test.png', $url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl($this->node->get('field_image')->entity); |
||||||
|
self::assertStringEndsWith('/files/image-test.png', $url); |
||||||
|
|
||||||
|
$this->node->get('field_image')->removeItem(0); |
||||||
|
$url = $extractor->extractUrl($this->node->get('field_image')); |
||||||
|
self::assertNull($url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl($this->node->get('field_media')[0]); |
||||||
|
self::assertStringEndsWith('/files/image-test.gif', $url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl($this->node->get('field_media')[1]); |
||||||
|
self::assertNull($url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl($this->node->get('field_media')); |
||||||
|
self::assertStringEndsWith('/files/image-test.gif', $url); |
||||||
|
|
||||||
|
$url = $extractor->extractUrl($this->node->get('field_media')->entity); |
||||||
|
self::assertStringEndsWith('/files/image-test.gif', $url); |
||||||
|
|
||||||
|
$this->node->get('field_media')->removeItem(0); |
||||||
|
$url = $extractor->extractUrl($this->node->get('field_media')); |
||||||
|
self::assertNull($url); |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue