survos / data-bundle
NOT survos/dataset-bundle. Namespace: Survos\DataBundle (no 'set'). Database and tooling layer for survos/data-contracts: keyword→ContentType classification cache (VocabMap) and ContentType display-label translations (VocabLabel).
Fund package maintenance!
Requires
- php: ^8.5
- doctrine/dbal: ^3.9||^4.2
- doctrine/doctrine-bundle: ^3.2
- doctrine/orm: ^3.6
- survos/data-contracts: ^2.5
- survos/field-bundle: ^2.5
- survos/import-bundle: ^2.5
- survos/kit-bundle: ^2.5
- symfony/console: ^8.1
- symfony/framework-bundle: ^8.1
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- 2.10.25
- 2.10.22
- 2.10.21
- 2.10.19
- 2.10.18
- 2.10.17
- 2.10.16
- 2.10.15
- 2.10.14
- 2.10.13
- 2.10.12
- 2.10.11
- 2.10.10
- 2.10.9
- 2.10.8
- 2.10.7
- 2.10.6
- 2.10.5
- 2.10.4
- 2.10.3
- 2.10.2
- 2.10.1
- 2.10.0
- 2.9.4
- 2.9.3
- 2.9.2
- 2.9.1
- 2.9.0
- 2.8.4
- 2.8.3
- 2.8.1
- 2.8.0
- 2.7.23
- 2.7.22
- 2.7.21
- 2.7.20
- 2.7.19
- 2.7.18
- 2.7.17
- 2.7.16
- 2.7.15
- 2.7.14
- 2.7.13
- 2.7.12
- 2.7.11
- 2.7.10
- 2.7.9
- 2.7.8
- 2.7.7
- 2.7.6
- 2.7.5
- 2.7.4
- 2.7.3
- 2.7.2
- 2.7.1
- 2.7.0
- 2.6.0
- 2.5.8
- 2.5.7
- 2.5.6
- 2.5.5
- 2.5.3
- 2.5.2
- 2.5.1
- 2.5.0
- 2.4.4
- 2.4.3
- 2.4.2
- 2.4.1
- 2.4.0
- 2.3.0
- 2.2.5
- 2.2.4
- 2.2.3
- 2.2.2
- 2.2.1
- 2.2.0
- 2.1.2
- 2.1.1
- 2.0.220
- 2.0.219
- 2.0.218
- 2.0.217
- 2.0.216
- 2.0.215
- 2.0.214
- 2.0.213
- 2.0.212
- 2.0.211
- 2.0.210
- 2.0.209
- 2.0.208
- 2.0.207
- 2.0.206
- 2.0.205
- 2.0.204
- 2.0.203
- 2.0.202
- 2.0.201
- 2.0.200
- 2.0.199
- 2.0.198
- 2.0.197
- 2.0.196
- 2.0.195
- 2.0.194
- 2.0.193
- 2.0.192
- 2.0.191
- 2.0.190
- 2.0.189
- 2.0.188
- 2.0.187
- 2.0.186
- 2.0.185
- 2.0.184
- 2.0.183
- 2.0.182
- 2.0.181
- 2.0.180
- 2.0.179
- 2.0.178
- 2.0.177
- 2.0.176
- 2.0.175
- 2.0.173
- 2.0.172
- 2.0.171
- 2.0.170
- 2.0.169
- 2.0.168
- 2.0.167
- 2.0.166
- 2.0.165
- 2.0.164
- 2.0.163
- 2.0.162
- 2.0.161
- 2.0.160
- 2.0.159
- 2.0.158
- 2.0.156
- 2.0.155
- 2.0.154
- 2.0.146
- 2.0.145
- 2.0.144
- 2.0.143
- 2.0.142
- 2.0.141
- 2.0.140
- 2.0.139
- 2.0.138
- 2.0.137
- 2.0.136
- 2.0.135
- 2.0.134
- 2.0.133
- 2.0.132
- 2.0.131
- 2.0.130
- 2.0.129
- 2.0.128
- 2.0.127
- 2.0.126
- 2.0.125
- 2.0.124
- 2.0.123
- 2.0.122
- 2.0.121
- 2.0.120
- 2.0.119
- 2.0.117
- 2.0.116
- 2.0.115
- 2.0.114
- 2.0.113
- 2.0.112
- 2.0.111
- 2.0.110
- 2.0.109
This package is auto-updated.
Last update: 2026-08-25 11:58:02 UTC
README
⚠️ NOT
survos/dataset-bundle(note the extraset). Different package, different namespace.
Package Namespace Bundle class Purpose survos/data-bundle(this)Survos\DataBundleSurvosDataBundleNormalize-time term extraction + a parked vocab/authority classifier survos/dataset-bundleSurvos\DatasetBundleSurvosDatasetBundleDataset filesystem conventions ( APP_DATA_DIR)Both bundles can be installed side-by-side. Don't merge their namespaces in
composer.jsonautoload — it silently masks classes from the other.
⚠️ Status (2026-06): mostly dormant, slated to move
This bundle is not the home of shared semantic contracts — those are item DTOs,
vocabularies, and ContentType, which live in
survos/data-contracts (being renamed cho-contracts,
Survos\Cho). The contracts are what consumers across the monorepo actually need.
What's left in this bundle is a small set of normalize-time helpers plus a parked authority/classifier feature that was started and never finished. After re-reading the code (2026-06), the honest accounting is below. The leading plan is to stop requiring this bundle in non-normalizing apps and move the surviving pieces into the normalizer (md) — see Direction.
What actually runs today
| Component | Trigger | Notes |
|---|---|---|
VocabTermExtractorListener |
auto-registered on ImportConvertFinishedEvent |
Scans the normalize JSONL and writes a per-dataset term inventory to {dataset}/30_terms/{termType}.{lang}.jsonl (e.g. genre.en.jsonl, medium.fr.jsonl). Term types come from ItemField / MuseumVocab constants. These files feed folio:ingest as TermSet + Term rows. This is the one genuinely useful, wired path. |
NormalizeFallbackListener |
auto-registered on ImportConvertRowEvent (priority -10) |
Sets iiif_base to the best source image URL when unset. This is not vocab-related — it's a generic normalize fallback that happens to live here. Candidate to move to import/media/md. |
vocab:export / vocab:import |
CLI | JSONL round-trip of the two tables below. The only way rows ever get into those tables. |
Dormant / not wired (the parked classifier)
| Component | State |
|---|---|
VocabMap (vocab_map table) — (lang, normKeyword) → contentType cache |
No consuming app migrates or populates this table. The confidence/model columns anticipate an AI classifier that does not exist. |
VocabLabel (vocab_label table) — (contentType, lang) → label |
Same: no migration, no producer. |
VocabResolver — wraps ContentType::fromRecord() with a VocabMap lookup |
Injected by nobody. A complete consumer with no caller. |
TermSetExtractor — derives termSet.jsonl/term.jsonl from obj.profile.json |
Injected by nobody. Overlaps conceptually with the listener above. |
Things the old README claimed that aren't true
- There is no
vocab:mapcommand and nodto_map.jsonl/labels.jsonlunder$APP_DATA_DIR/vocab/. That whole "diff + AI call for misses → shared language-level map" pipeline was aspirational and never built. VocabMapis not "populated by the AI classifier viaai-workflow-bundle." The AI bundles consumeContentTypefrom contracts directly; they never touch these tables.- The extractor writes
30_terms/{termType}.{lang}.jsonl, not30_terms/vocab.jsonl.
How it got here
This bundle was born when harvest (formerly mus) and md were both in the
normalizing business, and it needed a shared place for term extraction and a
keyword→type classifier. That dual-normalizer situation still holds (2026-06):
md has 18 provider normalizers (Singleton/*), harvest still has 15 (Dataset/*),
and ssai's MaracRegistrantsListener fires the same ImportConvert* events. So this
is a normalize-layer bundle shared by md + harvest + ssai — not yet an md-only
concern. The classifier ambition — using extensive Europeana / musdig vocabularies as
portable controlled authorities — was valuable but got parked before the AI loop was wired.
Authority / controlled-vocabulary lists are still worth having. Parking them does not mean abandoning them.
Direction
Under active discussion (not yet executed):
- Contracts →
cho-contracts. The portable, language-neutral DTO/vocabulary/ContentTypelayer (todaysurvos/data-contracts) is what most consumers actually need. ssai, for example, needs the contracts, not this bundle. - Drop it from the apps that don't normalize. Required by md, zm, ssai, harvest,
mediary, mus, rsun — but the live listeners only matter where
ImportConvert*events fire. md, harvest, ssai normalize and should keep it; zm, mus, mediary, rsun have zero normalizers and inject nothing, so it's pure dead weight there (and drags in ORM +import-bundle+dataset-bundle+field-bundle+kit-bundle). - Fold the survivors into md only after normalization consolidates there. Today the
term-extraction listener is shared by three normalizers, so it can't collapse into md
until harvest's
Dataset/*and ssai's Marac import either retire or delegate to md.NormalizeFallbackListener(iiif_base) isn't vocab and should move out independently — to import/media — regardless of the rest. - If the authority/vocab classifier is revived, prefer a shared SQLite registry
(the same pattern now used for the dataset/provider registry) over per-application
sync — one shared
vocab_map/vocab_labelsource instead of migrating and importing into every app's database.
Install (current)
composer require survos/data-bundle
// config/bundles.php Survos\DataBundle\SurvosDataBundle::class => ['all' => true],
File locations are resolved via DataPaths (now in survos/dataset-bundle):
| Path | Purpose |
|---|---|
{dataset}/30_terms/{termType}.{lang}.jsonl |
Per-dataset extracted term inventory (live) |
Note for future schema/type work
Symfony 8.1 TypeInfo now supports object shapes. This may be useful when we need
to describe folio/archive custom payloads with a compact, typed PHPDoc contract before (or
instead of) introducing a full formal schema layer.
Reference syntax:
use Symfony\Component\TypeInfo\TypeResolver\StringTypeResolver; $resolver = new StringTypeResolver(); $type = $resolver->resolve('object{name: string, age: int, email?: string}');
Equivalent programmatic form:
use Symfony\Component\TypeInfo\Type; $type = Type::objectShape([ 'name' => Type::string(), 'age' => Type::int(), 'email' => ['type' => Type::string(), 'optional' => true], ]);