Installation
composer require anzusystems/core-dam-bundle
Add to config/bundles.php:
return [
// ...
AnzuSystems\CoreDamBundle\AnzuSystemsCoreDamBundle::class => ['all' => true],
];
Environment Configuration
Update .env with required variables (e.g., DB_CORE_DAM_BUNDLE_* for database connections, GOOGLE_PUBSUB_SA_KEY for PubSub).
First Use Case Generate a public URL for an asset:
use AnzuSystems\CoreDamBundle\Facades\AssetFacade;
$asset = AssetFacade::getAssetById(1);
$publicUrl = AssetFacade::getPublicUrl($asset);
Key Facades
AssetFacade (CRUD, metadata, search)AssetFileFacade (file operations, copies)DistributionFacade (export configurations)PodcastFacade (RSS/podcast management)Documentation
src/Resources/config/ for YAML configs.src/Command/ for CLI tools (e.g., GeneratePodcastImportJobsCommand).// Upload from URL (e.g., Unsplash)
$asset = AssetFacade::createFromUrl(
'https://example.com/image.jpg',
['authors' => ['John Doe'], 'keywords' => ['nature']]
);
// Trigger async processing (metadata extraction, resizing)
AssetFacade::processAsset($asset);
Key Events:
AssetCreatedEvent (post-upload)AssetMetadataProcessedEvent (after metadata extraction)AssetFileCopiedEvent (after file copies)// Update metadata for multiple assets
AssetFacade::bulkUpdateMetadata([
1 => ['title' => 'Updated Title', 'authors' => ['Jane Smith']],
2 => ['keywords' => ['travel']],
]);
Use AssetMetadataBulkEventDispatcher for event-driven workflows.
// Generate public URLs (supports slugs or direct IDs)
$url = AssetFacade::getPublicUrl($asset, [
'width' => 800,
'height' => 600,
'format' => 'webp',
]);
// Stream optimized images (AVIF, WebP, PNG)
return new StreamedResponse(
AssetFileFacade::streamOptimizedImage($asset->getMainFile(), $request),
200,
['Content-Type' => 'image/webp']
);
Config:
# config/packages/anzu_core_dam.yaml
anzusystems_core_dam:
image:
optimal_resize_quality: 90
disable_crop_cache: false
// Import podcast from RSS URL
$podcast = PodcastFacade::importFromUrl('https://example.com/rss.xml');
// Generate RSS feed
$rssContent = PodcastFacade::generateRssFeed($podcast);
CLI:
php bin/console anzusystems:core-dam:generate-podcast-import-jobs
// Create a JWPlayer distribution
$distribution = DistributionFacade::createJwDistribution($asset, [
'thumbnailUrl' => 'https://example.com/thumb.jpg',
'directSourceUrl' => true,
]);
// Export to external systems (e.g., PubSub)
DistributionFacade::notifyExternalSystems($distribution);
PubSub Config:
anzusystems_core_dam:
pubsub:
notifications_enabled: true
topics:
image_changed: 'projects/your-project/topics/image-changed'
// Search assets with filters
$results = AssetFacade::search([
'query' => 'nature',
'filters' => [
'authors' => ['John Doe'],
'licences' => ['cc-by'],
'mainFileInternal' => true,
],
'sort' => ['createdAt' => 'desc'],
]);
// Reindex Elasticsearch (e.g., after bulk updates)
php bin/console anzusystems:core-dam:elasticsearch:reindex --since=2023-01-01
Elasticsearch Boosting:
// Prioritize assets with specific keywords
$results = AssetFacade::search([
'query' => 'travel',
'boosters' => [
'keywords' => ['landscape' => 2.0, 'photography' => 1.5],
],
]);
// Assign a licence group to an asset
$asset->setLicenceGroup(LicenceGroupFacade::findById(1));
AssetFacade::save($asset);
// Validate asset usage rules
if (AssetFacade::canBeUsed($asset, $context)) {
// Proceed
}
Validators:
AssetLicenceAwareVoter (role-based access)AssetCopyEqualExtSystemValidator (external system checks)Use the bundle’s built-in jobs for async tasks:
# config/packages/messenger.yaml
framework:
messenger:
transports:
core_dam: '%env(MESSENGER_TRANSPORT_DSN)%'
routing:
'AnzuSystems\CoreDamBundle\Message\ProcessAssetMessage': core_dam
Listen for asset lifecycle events:
// src/EventListener/AssetListener.php
public function onAssetCreated(AssetCreatedEvent $event)
{
$asset = $event->getAsset();
// Custom logic (e.g., log, notify)
}
Register in services.yaml:
services:
App\EventListener\AssetListener:
tags:
- { name: kernel.event_listener, event: anzusystems.core_dam.asset.created }
Extend metadata processing:
// src/EventSubscriber/AssetMetadataSubscriber.php
public function onMetadataProcessed(AssetMetadataProcessedEvent $event)
{
$metadata = $event->getMetadata();
$metadata->setCustomData('app_specific_field', 'value');
}
Register:
tags:
- { name: kernel.event_subscriber, tag: anzusystems.core_dam.metadata }
Use the provided Docker image:
# docker-compose.yml
services:
core_dam:
image: anzusystems/php:4.1.0-php83-cli-vipsffmpeg
environment:
- DB_CORE_DAM_BUNDLE_DATABASE_URL=postgres://user:pass@db:5432/core_dam
- DOCKER_COMPOSE_SERVICE_NAME=core_dam
CI Pipeline:
# Example GitHub Actions step
- name: Run DAM tests
run: |
php bin/phpunit --configuration phpunit.xml.dist
php bin/console anzusystems:core-dam:elasticsearch:rebuild
htmlspecialchars with ENT_SUBSTITUTE). Use AssetMetadataProcessor events to sanitize custom fields.
// Avoid double-encoding
$cleanValue = htmlspecialchars($rawValue, ENT_QUOTES, 'UTF-8');
AuthorCleanPhrase to improve fuzzy matching for EXIF authors.--since for large datasets to avoid timeouts:
php bin/console anzusystems:core-dam:elasticsearch:reindex --since=2023-01-01
DBALIndexable for schema-aware reindexing.disable_crop_cache: true) may improve performance but increases storage usage.
How can I help you explore Laravel packages today?