teltek/pumukit-oai-bundle
Symfony bundle that adds an OAI-PMH endpoint to Pumukit, exposing your video catalogue metadata for harvesting by external repositories and aggregators. Configurable sets and metadata formats make it easy to integrate with Europeana, OpenAIRE and other OAI-compliant services.
This bundle exposes a Pumukit (Symfony) installation as an OAI-PMH repository so external aggregators — Europeana, Hispana, OpenAIRE, university library catalogues — can harvest series and multimedia object metadata. Expect a Symfony 2.x/3.x–era bundle; there is no Symfony 5/6 support and effectively no active maintenance (1 star, 0 dependents), so treat it as a starting point to fork rather than a drop-in dependency.
Minimum steps:
Controller/, Resources/config/, and DependencyInjection/ first. The whole surface area is usually one HTTP controller plus a metadata mapper.composer require teltek/pumukit-oai-bundle. Do this inside an existing Pumukit 2.x/3.x app, not standalone — the bundle depends on pumukit/schema and Pumukit's MongoDB document model for Series and MultimediaObject.app/AppKernel.php (Symfony 2/3) or config/bundles.php if a Symfony 4 port exists in your fork.Resources/config/routing.yml typically defines the /oai (or /oai/request) endpoint. Ensure oai_request or similar route is exposed and not behind authentication./oai?verb=Identify and confirm a valid Identify response with repositoryName, baseURL, adminEmail, earliestDatestamp, and granularity. Then ?verb=ListMetadataFormats and ?verb=ListRecords&metadataPrefix=oai_dc.If Identify returns 500 or a Symfony exception page, the Mongo connection or Pumukit schema version is the usual culprit — not OAI logic.
Verb dispatch at the controller. OAI-PMH is a single endpoint with six verbs: Identify, ListMetadataFormats, ListSets, ListIdentifiers, ListRecords, GetRecord. The bundle routes on the verb query param and streams back XML. When extending, follow the existing pattern rather than adding new controllers — harvesters only know one URL.
Metadata format mapping. Customising what gets exported (e.g. adding oai_dc, marc21, or a domain-specific prefix) is the common extension point. Look for the metadata formatter/mapper service and either decorate it or replace its service definition in services.yml. Pumukit objects carry tags, series, broadcast, public_date, description, and track info — map these into dc: elements carefully; dc:identifier should be a stable, resolvable URL.
Records and sets from Pumukit models. ListSets is normally derived from series or from a Pumukit tag/collection convention. ListRecords queries the multimedia repository. If you need richer filtering (by publication status, by public_date, hiding non-public objects), override the query builder in the repository service. Never expose draft/unpublished objects — OAI harvesters will cache them permanently.
Resumption tokens. OAI-PMH mandates paging with resumptionToken for ListRecords/ListIdentifiers. The bundle implements this; if you change result ordering between calls, tokens break. Keep cursor state server-side (MongoId or offset), not in the token itself, or make the token self-contained and versioned.
Integration with Symfony. For custom behaviour use a compiler pass or event subscriber only if the bundle emits events — most of these small bundles don't, so overrides are usually a service decoration or a fork. Prefer a fork with a dev- VCS require in Composer ("teltek/pumukit-oai-bundle": "dev-main") so you can patch and keep the change.
Validation workflow. Test with the Open Archives OAI-PMH validator and curl -s 'https://host/oai?verb=Identify' | xmllint --format -. Add this to CI as a smoke test against a fixture database.
YYYY-MM-DDThh:mm:ssZ in UTC for datestamp and earliestDatestamp. Local timezone drift is the #1 cause of harvest failures and silent re-harvest loops.deleted records. If you hard-delete Pumukit objects, the OAI record vanishes and harvesters never learn to purge. Track deletions and emit <header status="deleted"> — the bundle likely doesn't handle this out of the box.ListSets from a Mongo aggregation over series on every call will hammer the DB. Cache the set list.public_date.&, <, UTF-8 accents, and embedded HTML from Pumukit track descriptions. Confirm output goes through proper XML escaping; wrap raw descriptions in CDATA and strip tags.<error code="...">), not HTTP 500 HTML. If a harvester sees a Symfony stack trace, treat it as a bug in the bundle's exception handling — add a listener that converts OaiException to XML responses.baseURL are usually in config.yml under the bundle key. baseURL must match the public host exactly (scheme, port, trailing slash rules), or harvesters reject Identify. Behind a reverse proxy, set trusted_proxies so Request::getSchemeAndHttpHost() is correct.ContainerAware, old routing loader). Plan a migration to a modern OAI-PMH library (e.g. caseyamcl/phpoaipmh + a thin Pumukit adapter) if you're on a current stack./oai contract intact and makes future forks easier to merge.How can I help you explore Laravel packages today?