public function encodeMediaUrl(?MediaEntity $media): ?string
{
if ($media === null || !$media->hasFile()) {
return null;
}
return $this->encodeUrl($media->getUrl());
}
So far so good. So the big question is, where is \Shopware\Core\Content\Media\MediaEntity::getUrl from?
Database to MediaEntity::setUrl
When we start searching, where the url is set on the MediaEntity we’ll find \Shopware\Core\Content\Media\Subscriber\MediaLoadedSubscriber::addUrls, especially the following line:
The method is from an interface (\Shopware\Core\Content\Media\Pathname\UrlGeneratorInterface::getAbsoluteMediaUrl) and implemented here: \Shopware\Core\Content\Media\Pathname\UrlGenerator::getAbsoluteMediaUrl
public function getAbsoluteMediaUrl(MediaEntity $media): string
{
return $this->getBaseUrl() . '/' . $this->getRelativeMediaUrl($media);
}
public function getRelativeThumbnailUrl(MediaEntity $media, MediaThumbnailEntity $thumbnail): string
{
$this->validateMedia($media);
return $this->toPathString([
'thumbnail',
$this->pathnameStrategy->generatePathHash($media),
$this->pathnameStrategy->generatePathCacheBuster($media),
$this->pathnameStrategy->generatePhysicalFilename($media, $thumbnail),
]);
}
All these methods belong to the interface \Shopware\Core\Content\Media\Pathname\PathnameStrategy\PathnameStrategyInterface and are implemented by default in \Shopware\Core\Content\Media\Pathname\PathnameStrategy\IdPathnameStrategy
Why by default?
In your .env file you set a value for SHOPWARE_CDN_STRATEGY_DEFAULT="id" which defines via Shopware\Core\Content\Media\Pathname\PathnameStrategy\StrategyFactory which implementation of the PathnameStrategyInterface to use. The default is id
PathnameStrategy
The following methods are implementation in \Shopware\Core\Content\Media\Pathname\PathnameStrategy\IdPathnameStrategy (or inherited from ancestor classes.
generatePathHash
I don’t know why it is needed to generate a md5 hash from a GUID, but people which are smarter than me know. Maybe because it is shorter than the GUID or they don’t want to give away the GUIDs of the images? Another idea I have is to avoid having similar ids and therefore all images would end up in the same directory, but as far as I know GUIDs are built to distribute maximally like most hash algorithms as well (like md5) ?
public function generatePathHash(MediaEntity $media, ?MediaThumbnailEntity $thumbnail = null): ?string
{
return $this->generateMd5Path($media->getId());
}
generatePathCacheBuster
To make sure, that the current image is online and not an old one, the timestamp of the upload is used – important here is to note, that it is NOT the timestamp on the file, but the entry on the database in media.uploaded_at.
public function generatePathCacheBuster(MediaEntity $media, ?MediaThumbnailEntity $thumbnail = null): ?string
{
$uploadedAt = $media->getUploadedAt();
if ($uploadedAt === null) {
return null;
}
return (string) $uploadedAt->getTimestamp();
}
generatePhysicalFilename
And the filename is pretty straight forward, the filename and the extension. In case of a thumbnail the image size is added as a suffix.