diff --git a/core/modules/file/src/Entity/File.php b/core/modules/file/src/Entity/File.php index b82d5a8..8571cb0 100644 --- a/core/modules/file/src/Entity/File.php +++ b/core/modules/file/src/Entity/File.php @@ -4,9 +4,12 @@ use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityChangedTrait; +use Drupal\Core\Entity\EntityMalformedException; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Entity\Exception\UndefinedLinkTemplateException; use Drupal\Core\Field\BaseFieldDefinition; +use Drupal\Core\Url; use Drupal\file\FileInterface; use Drupal\user\UserInterface; @@ -71,7 +74,50 @@ public function setFileUri($uri) { * @see file_url_transform_relative() */ public function url($rel = 'canonical', $options = array()) { - return file_create_url($this->getFileUri()); + /** @var Url $uri */ + $uri = $this->toUrl($rel); + $options += $uri->getOptions(); + $uri->setOptions($options); + return $uri->toString(); + } + + /** + * {@inheritdoc} + */ + public function toUrl($rel = 'canonical', array $options = []) { + // Core does not provide any link templates for files so build the canonical + // URL manually, but allow contrib to provide link templates. + try { + return parent::toUrl($rel, $options); + } catch (UndefinedLinkTemplateException $e) { + return $this->handleCanonicalUrlExceptions($rel, $options, $e); + } catch (EntityMalformedException $e) { + return $this->handleCanonicalUrlExceptions($rel, $options, $e); + } + } + + /** + * If we want to have a canoncial url, but don't have a linktemplate or a uri_callback, + * build an Url from the file uri + * + * @param string $rel + * The link relationship type, for example: canonical or edit-form. + * @param array $options + * See \Drupal\Core\Routing\UrlGeneratorInterface::generateFromRoute() for + * the available options. + * @param UndefinedLinkTemplateException|EntityMalformedException $e + * The Exceptions thrown from toUrl + * @return \Drupal\Core\Url + * @throws UndefinedLinkTemplateException|EntityMalformedException + * If we don't want a canonical Url + */ + private function handleCanonicalUrlExceptions($rel, $options, $e) { + if ($rel == 'canonical') { + return Url::fromUri(file_create_url($this->getFileUri()), $options); + } + else { + throw $e; + } } /** diff --git a/core/modules/file/tests/src/Kernel/LinkTest.php b/core/modules/file/tests/src/Kernel/LinkTest.php new file mode 100644 index 0000000..66a0ddb --- /dev/null +++ b/core/modules/file/tests/src/Kernel/LinkTest.php @@ -0,0 +1,48 @@ +createFile('druplicon.txt', NULL, 'public'); + $this->assertEquals($file->toLink() + ->toString(), "toUrl()->toString()}\">{$file->label()}"); + // Test the deprecated methods as well. + $this->assertEquals($file->link(), "url()}\">{$file->label()}"); + } + + /** + * Tests to_url against an uri_callback + */ + function testUriCallback() { + $file = $this->createFile('druplicon.txt', NULL, 'public'); + $expected = $file->toUrl()->toString() . '_test'; + $file->getEntityType()->setUriCallback(function ($fileEntity) { + return Url::fromUri(file_create_url($fileEntity->getFileUri()) . '_test'); + }); + $actual = $file->toUrl()->toString(); + $this->assertEquals($expected, $actual); + } + + /** + * Tests that only canonical links are supported. + */ + function testNonCanonicalLink() { + $this->setExpectedException(UndefinedLinkTemplateException::class); + + $file = $this->createFile('druplicon.txt', NULL, 'public'); + $file->toLink('', 'notcanonical'); + } +} \ No newline at end of file