teltek/pumukit-import-data-bundle
Symfony bundle for PuMuKIT that provides commands and services to import data from external sources into the platform, with configurable mappings, batch processing for videos, metadata, and related records, plus scheduled and on-demand imports with logging.
This is a Symfony bundle (PuMuKIT is Symfony-based, not Laravel — adjust your mental model from service providers to bundles/DI extensions). Start by requiring it and wiring it into the kernel.
composer require teltek/pumukit-import-data-bundle
Register the bundle:
app/AppKernel.php in registerBundles().config/bundles.php.Then clear cache and discover the actual entry points:
php bin/console cache:clear
php bin/console list | grep -i import
php bin/console list pumukit
Look here first, in this order:
Command/ — the console commands are the public API of this bundle. Every workflow goes through them.Resources/config/services.xml (or .yaml) — tells you what services exist, their IDs, and their constructor dependencies.DependencyInjection/Configuration.php — the bundle's config tree; tells you what's tunable under pumukit_import_data: in your app config.README.md — often the only documentation, and often stale; cross-check against Command/.First use case: batch-loading MultimediaObjects and their Series from an external catalog export (CSV/XML dump from a legacy CMS, a partner feed, or an old PuMuKIT instance). You run the import command, map external IDs to PuMuKIT reference/external_id fields, attach media files to Tracks, and let PuMuKIT's own MultimediaObjectService handle transcoding publication.
Run imports as scheduled jobs, not ad-hoc. Wrap the command in cron or a queue worker so re-runs are cheap. PuMuKIT's storage layer handles the heavy lifting; the import bundle is the thin orchestration layer.
Idempotency via external IDs. The single most important pattern: before creating a MultimediaObject, look it up by a stable external key (reference, external_id, or a property in properties). The bundle may or may not do this for you — verify by reading the command's execute(). If it blindly new MultimediaObject(...), wrap it in your own check or add a --update-existing option to your fork.
Chunk and bound the run. Feed the importer in fixed-size batches (e.g. 100–500 rows). Pattern:
php bin/console pumukit:import:<command> source.csv --limit=500 --offset=0
Even if --limit/--offset aren't built in, you can pre-split the source file and run the command per shard. This also gives you restartability — a failed shard doesn't force a full re-run.
Delegate to PuMuKIT services, don't reimplement. The bundle should be injecting pumukit.schema.multimedia_object / SeriesService / MultimediaObjectService. If you're writing a custom importer on top of it, inject the same services rather than hitting Doctrine repositories directly. That keeps transcoding, tagging, and publication flags consistent with the rest of the platform.
Map, then persist, then publish. A robust import has three distinct phases:
Series → MultimediaObjects → Tracks → Person/Role links.Don't interleave publication with persistence — you'll end up with half-published objects on error.
Override via decoration, not editing. If the mapping logic doesn't fit your source, decorate the importer service:
services:
App\Import\MyImporter:
decorates: teltek.pumukit_import_data.importer # check exact ID in services.xml
arguments: ['@App\Import\MyImporter.inner']
Alternatively, extend the bundle's command class and override configure() to add options, or execute() to post-process.
Logging. PuMuKIT is Monolog-based. Configure a dedicated import channel so you can tail var/log/import.log during long runs. Emit one log line per record with the external ID on both success and failure — it's the only way to reconcile after a crash.
Testing. Use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase (or WebTestCase) and test the service layer directly with a small fixture (a 3-row CSV and a temp media file). Console-command tests via CommandTester are the fastest way to catch mapping regressions.
No docs, zero stars, zero dependents — treat it as read-the-source territory. There is no community to lean on and the README is likely terse. Budget time for Command/ and DependencyInjection/ before you promise anything to stakeholders. If the bundle is older than your PuMuKIT version, expect breakage: Symfony 3.4 vs 4.4 vs 5.x DI syntax and Command return codes differ.
Bundle registration is easy to forget. If commands don't appear in bin/console list, 90% of the time the bundle isn't registered in AppKernel.php/bundles.php, or the cache wasn't cleared. Check php bin/console debug:container --tag=console.command | grep pumukit to confirm the command was tagged.
Config quirks. The bundle's extension key is almost certainly pumukit_import_data (Symfony derives it from the bundle name). Verify in DependencyInjection/PumukitImportDataExtension::getAlias(). If you get "unrecognized option" errors, you're passing a key the Configuration.php tree doesn't define — read the tree, don't guess.
Memory blows up on large imports. Doctrine keeps every managed entity in the UnitOfWork. If the importer doesn't $em->clear() periodically, a 10k-row import will OOM. Either patch the command to clear/detach every N records, or cap batch size with --limit and loop from an external driver script. Watch memory_get_peak_usage() in a staging run before touching production.
File paths and media attachment. Track creation expects absolute paths to media files; relative paths silently fail or produce broken tracks depending on PuMuKIT version. Use realpath() on inputs and validate is_readable() up front — fail the whole batch on the first missing file rather than importing a partial set.
Language and person references are the usual mapping bugs. PuMuKIT uses two-letter ISO 639-1 codes; if your source is en-US/pt_BR, normalize before persist. Same for Person — dedupe by email or a stable ID, otherwise every import run multiplies person records.
Transactions. Wrap each chunk in an explicit DB transaction ($em->getConnection()->beginTransaction() / commit() / rollBack() on exception). Without this, a crash mid-batch leaves orphan MultimediaObjects you'll be cleaning up by hand.
Extension points that actually work:
Event/ or grep for dispatch(), subscribe in your app rather than forking.Process — pragmatic when the bundle doesn't expose the internals you need.Debugging checklist when an import fails:
-vvv on the command — most Symfony commands surface the real exception at this verbosity.php bin/console debug:event-dispatcher | grep -i import — confirm nothing is silently swallowing events.multimedia_object and multimedia_object_track tables after a dry run; the count should match your input minus known rejects.var/log/dev.log for Doctrine warnings — the bundle may be persisting entities with unmapped fields that only fail on flush.Vendor-lock reminder. Zero dependents means the bundle's API is whatever the last commit made it. Pin the exact version in composer.json and, if you're going to rely on it heavily, vendor a fork under your org namespace so upstream drift can't break your pipeline.
How can I help you explore Laravel packages today?