Custom Asset Collections
Asset collections allow you to organize your assets into logical groups. You can create custom collections by implementing the AssetCollectionDefinitionInterface
:
Here's a simple example of a collection that only allows image files and limits the size to 5 MB:
class SingleImageCollection implements AssetCollectionDefinitionInterface, AssetVariantsInterface
{
public function definition(AssetCollectionSetterInterface $definition): void
{
$definition->singleFileCollection()
->setMaxFileSize(5 * 1024 * 1024) // 5 MB
->allowedExtensions(...AssetExtension::images());
}
public function checkAuthorization(array|Entity $entity, Asset $asset): bool
{
return true;
}
public function variants(CreateAssetVariantsInterface $variants, Asset $asset): void
{
// No variants needed
}
}
For more complex collections, you can customize the configuration further:
class ProfilePicturesCollection implements AssetCollectionDefinitionInterface, AssetVariantsInterface
{
public function definition(AssetCollectionSetterInterface $definition): void
{
// Allow specific file extensions using the AssetExtension enum
$definition->allowedExtensions(
AssetExtension::JPG,
AssetExtension::PNG,
AssetExtension::GIF,
// You can also use string values
'webp'
)
// Alternatively, you can use the spread operator with AssetExtension::images()
// to allow all image extensions at once
// ->allowedExtensions(...AssetExtension::images())
// Allow specific MIME types using the AssetMimeType enum
->allowedMimeTypes(
AssetMimeType::IMAGE_JPEG,
AssetMimeType::IMAGE_PNG,
AssetMimeType::IMAGE_GIF,
// You can also use string values
'image/webp'
)
// Set maximum file size (in bytes)
->setMaxFileSize(5 * 1024 * 1024) // 5MB
// Make this a single-file collection (only one file allowed)
// This is equivalent to calling onlyKeepLatest(1)
->singleFileCollection()
// OR set a maximum number of files to keep (deletes oldest when exceeded)
// ->onlyKeepLatest(10) // Keep only the 10 most recent files
// Set a custom path generator for this collection
->setPathGenerator(new CustomPathGenerator());
}
public function checkAuthorization(array|Entity $entity, Asset $asset): bool
{
// Check if the user is authorized to access this asset
return true;
}
public function variants(CreateAssetVariantsInterface $variants, Asset $asset): void
{
// Define file variants (e.g., thumbnails)
}
}
Understanding AssetCollectionDefinitionInterface
The AssetCollectionDefinitionInterface
requires you to implement the following method:
definition
public function definition(AssetCollectionSetterInterface $definition): void
This method is where you configure the collection's settings, such as allowed file types, maximum file size, and other constraints.
Understanding AuthorizableAssetCollectionDefinitionInterface
The AuthorizableAssetCollectionDefinitionInterface
extends AssetCollectionDefinitionInterface
and adds authorization capabilities to asset collections. This interface is used when you need to control access to assets based on user permissions or other criteria.
checkAuthorization
public function checkAuthorization(Asset $asset): bool
This method determines whether a user is authorized to access an asset. It's called when an asset is requested through the AssetConnectController. The method should return true
if access is allowed and false
if access should be denied.
Files typically stored in collections implementing this interface are user-specific, such as profile pictures or documents that should only be accessible to certain users.
Example Implementation
class SecureDocumentsCollection implements AuthorizableAssetCollectionDefinitionInterface
{
public function definition(AssetCollectionSetterInterface $definition): void
{
$definition
->allowedExtensions(
AssetExtension::PDF,
AssetExtension::DOC,
AssetExtension::DOCX
)
->setMaxFileSize(10 * 1024 * 1024); // 10MB
}
public function checkAuthorization(Asset $asset): bool
{
// Get the current user
$user = service('auth')->user();
// Get the entity that owns the asset
$entity = $asset->getSubjectEntity();
// Check if the user is the owner of the entity or an admin
return ($user->id === $entity->user_id) || $user->isAdmin();
}
}
In this example, the checkAuthorization
method checks if the current user is either the owner of the entity that the asset belongs to or an admin. If either condition is true, access is granted; otherwise, it's denied.
Understanding AssetVariantsInterface
If your collection needs to support variants (like thumbnails or different sizes of images), you should also implement the AssetVariantsInterface
:
variants
public function variants(CreateAssetVariantsInterface $variants, Asset $asset): void
This method is where you define the variants that should be created for assets in this collection.
Available Configuration Options
The AssetCollectionSetterInterface
provides several methods for configuring your collections:
allowedExtensions
public function allowedExtensions(string|AssetExtension ...$extensions): self
Specifies which file extensions are allowed in the collection. You can use the AssetExtension
enum or string values.
allowedMimeTypes
public function allowedMimeTypes(string|AssetMimeType ...$mimeTypes): self
Specifies which MIME types are allowed in the collection. You can use the AssetMimeType
enum or string values.
setMaxFileSize
public function setMaxFileSize(int $maxFileSize): self
Sets the maximum file size (in bytes) allowed for assets in the collection.
singleFileCollection
public function singleFileCollection(): self
Makes the collection a single-file collection, meaning it can only contain one asset at a time. When a new asset is added, any existing assets are automatically deleted.
onlyKeepLatest
public function onlyKeepLatest(int $count): self
Sets the maximum number of assets to keep in the collection. When this limit is exceeded, the oldest assets are automatically deleted.
setPathGenerator
public function setPathGenerator(PathGeneratorInterface $pathGenerator): self
Sets a custom path generator for the collection, which determines how file paths are generated for stored assets.
Best Practices
When creating custom asset collections, consider the following best practices:
Validate File Types
Always validate file types to ensure that only the expected types of files are stored in your collections. This helps prevent security issues and ensures that your application can properly handle the files.
$definition->allowedExtensions(...AssetExtension::images())
->allowedMimeTypes(...AssetMimeType::getImageMimeTypes());
Limit File Sizes
Set appropriate file size limits to prevent users from uploading excessively large files that could cause performance issues or storage problems.
$definition->setMaxFileSize(10 * 1024 * 1024); // 10MB
Use Single-File Collections When Appropriate
If your entity should only have one file of a certain type (like a profile picture), use a single-file collection to automatically handle the replacement of old files.
$definition->singleFileCollection();
Implement Proper Authorization
Always implement proper authorization checks in the checkAuthorization
method to ensure that only authorized users can access assets.
public function checkAuthorization(array|Entity $entity, Asset $asset): bool
{
// Check if the user is authorized to access this asset
$user = service('auth')->user();
return $user->id === $entity->user_id || $user->isAdmin();
}
Conclusion
Custom asset collections provide a powerful way to organize and manage files in your application. By implementing the AssetCollectionDefinitionInterface
and configuring your collections appropriately, you can ensure that your application handles files in a secure, efficient, and organized manner.