twig_tweak-8.x-2.8/src/UrlExtractor.php
src/UrlExtractor.php
<?php
declare(strict_types=1);
namespace Drupal\twig_tweak;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
use Drupal\Core\File\FileUrlGeneratorInterface;
use Drupal\file\FileInterface;
use Drupal\link\LinkItemInterface;
use Drupal\media\MediaInterface;
use Drupal\media\Plugin\media\Source\OEmbedInterface;
/**
* The URL extractor service.
*/
final readonly class UrlExtractor {
/**
* {@selfdoc}
*/
public function __construct(
private EntityTypeManagerInterface $entityTypeManager,
private FileUrlGeneratorInterface $fileUrlGenerator,
) {}
/**
* Extracts file URL from a string or object.
*
* @param object|string|null $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(object|string|null $input, bool $relative = TRUE): ?string {
if (\is_string($input)) {
return $this->fileUrlGenerator->{$relative ? 'generateString' : 'generateAbsoluteString'}($input);
}
elseif ($input instanceof LinkItemInterface) {
return $input->getUrl()->toString();
}
elseif ($input instanceof FieldItemList && $input->first() instanceof LinkItemInterface) {
return $input->first()->getUrl()->toString();
}
$entity = $input;
if ($input instanceof EntityReferenceFieldItemListInterface) {
// @phpstan-ignore method.unresolvableReturnType
if ($item = $input->first()) {
$entity = $item->entity;
}
}
elseif ($input instanceof EntityReferenceItem) {
$entity = $input->entity;
}
// Drupal doesn't clean up references to deleted entities, so the entity
// property might be empty even when the field item exists.
// @see https://www.drupal.org/project/drupal/issues/2723323
return $entity instanceof ContentEntityInterface ?
$this->getUrlFromEntity($entity, $relative) : NULL;
}
/**
* Extracts file URL from content entity.
*/
private function getUrlFromEntity(ContentEntityInterface $entity, bool $relative = TRUE): ?string {
if ($entity instanceof MediaInterface) {
$source = $entity->getSource();
$value = $source->getSourceFieldValue($entity);
if ($source instanceof OEmbedInterface) {
return $value;
}
$file = $this->entityTypeManager->getStorage('file')->load($value);
if ($file) {
return $file->createFileUrl($relative);
}
}
elseif ($entity instanceof FileInterface) {
return $entity->createFileUrl($relative);
}
return NULL;
}
}
