From b5a4505468aad6b0f30ec64a4724ab3d0ae38dee Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Tue, 18 Nov 2025 18:20:09 +0200 Subject: [PATCH] Sync historic metadata to the plugin's tables --- .../HistoricPetitionViewer/config/plugin.json | 31 ++++---- .../HistoricPetitionViewer/config/routes.php | 21 ++--- ...php => HistoricPetitionMetadataRecord.php} | 2 +- .../Table/HistoricPetitionAttributesTable.php | 3 + ... HistoricPetitionMetadataRecordsTable.php} | 5 +- .../Cell/HistoricPetitionStepLinksCell.php | 4 +- .../HistoricPetitionStepLinks/display.php | 4 +- app/plugins/Transmogrify/README.md | 77 +++++++++++++++++++ .../Transmogrify/config/schema/tables.json | 31 ++++++++ .../src/Command/TransmogrifyCommand.php | 6 ++ 10 files changed, 150 insertions(+), 34 deletions(-) rename app/plugins/HistoricPetitionViewer/src/Model/Entity/{HistoricPetitionMetadata.php => HistoricPetitionMetadataRecord.php} (96%) rename app/plugins/HistoricPetitionViewer/src/Model/Table/{HistoricPetitionMetadatasTable.php => HistoricPetitionMetadataRecordsTable.php} (96%) diff --git a/app/plugins/HistoricPetitionViewer/config/plugin.json b/app/plugins/HistoricPetitionViewer/config/plugin.json index b1c36cfc..3cd8921a 100644 --- a/app/plugins/HistoricPetitionViewer/config/plugin.json +++ b/app/plugins/HistoricPetitionViewer/config/plugin.json @@ -5,7 +5,7 @@ "types": {}, "schema": { "tables": { - "historic_petition_attributes": { + "petition_hist_attrs": { "comment": "Transmogrified from cm_co_petition_attributes", "columns": { "id": { "type": "integer", "autoincrement": true, "primarykey": true }, @@ -14,18 +14,20 @@ "value": { "type": "text" }, "created": { "type": "datetime" }, "modified": { "type": "datetime" }, - "historic_petition_attribute_id": { "type": "integer", "foreignkey": { "table": "historic_petition_attributes", "column": "id" } }, + "historic_petition_attribute_id": { "type": "integer", "foreignkey": { "table": "petition_hist_attrs", "column": "id" } }, "revision": { "type": "integer" }, "deleted": { "type": "boolean" }, "actor_identifier": { "type": "string", "size": 256 } }, "indexes": { - "historic_petition_attributes_i1": { "columns": [ "petition_id" ] }, - "historic_petition_attributes_i2": { "columns": [ "attribute" ] }, - "historic_petition_attributes_i3": { "columns": [ "historic_petition_attribute_id" ] } - } + "petition_hist_attrs_i1": { "columns": [ "petition_id" ] }, + "petition_hist_attrs_i2": { "columns": [ "attribute" ] }, + "petition_hist_attrs_i3": { "columns": [ "historic_petition_attribute_id" ] } + }, + "timestamps": false, + "changelog": false }, - "historic_petition_metadata": { + "petition_meta_hist_recs": { "comment": "Transmogrified from cm_co_petitions fields that no longer map to petitions", "columns": { "id": { "type": "integer", "autoincrement": true, "primarykey": true }, @@ -39,7 +41,6 @@ "co_invite_id": { "type": "integer" }, "vetting_request_id": { "type": "integer" }, - "token": { "type": "string", "size": 256 }, "enrollee_token": { "type": "string", "size": 48 }, "petitioner_token": { "type": "string", "size": 48 }, "return_url": { "type": "string", "size": 512 }, @@ -47,24 +48,24 @@ "created": { "type": "datetime" }, "modified": { "type": "datetime" }, - "historic_petition_metadata_id": { "type": "integer", "foreignkey": { "table": "historic_petition_metadata", "column": "id" } }, + "petition_meta_hist_rec_id": { "type": "integer", "foreignkey": { "table": "petition_meta_hist_recs", "column": "id" } }, "revision": { "type": "integer" }, "deleted": { "type": "boolean" }, "actor_identifier": { "type": "string", "size": 256 } }, "indexes": { - "historic_petition_metadata_i1": { "columns": [ "petition_id" ] }, - "historic_petition_metadata_i2": { "columns": [ "historic_petition_metadata_id" ] } - } + "petition_meta_hist_recs_i1": { "columns": [ "petition_id" ] }, + "petition_meta_hist_recs_i2": { "columns": [ "petition_meta_hist_rec_id" ] } + }, + "timestamps": false, + "changelog": false }, "historic_petition_step_links": { "comment": "Associates a Petition’s historic data to a specific Enrollment Flow Step for read-only viewing", "columns": { "id": { "type": "integer", "autoincrement": true, "primarykey": true }, "petition_id": { "type": "integer", "foreignkey": { "table": "petitions", "column": "id" } }, - "enrollment_flow_step_id": { "type": "integer", "foreignkey": { "table": "enrollment_flow_steps", "column": "id" } }, - "created": { "type": "datetime" }, - "modified": { "type": "datetime" } + "enrollment_flow_step_id": { "type": "integer", "foreignkey": { "table": "enrollment_flow_steps", "column": "id" } } }, "indexes": { "historic_petition_step_links_i1": { "columns": [ "petition_id" ] }, diff --git a/app/plugins/HistoricPetitionViewer/config/routes.php b/app/plugins/HistoricPetitionViewer/config/routes.php index 8ddd6432..eea3ee23 100644 --- a/app/plugins/HistoricPetitionViewer/config/routes.php +++ b/app/plugins/HistoricPetitionViewer/config/routes.php @@ -1,7 +1,7 @@ '/historic-petition'], - function (RouteBuilder $routes) { - $routes->connect( - '/', - ['controller' => 'HistoricPetitionViews', - 'action' => 'index'] - ); - $routes->fallbacks(); +$routes->plugin( + 'HistoricPetitionViewer', + ['path' => '/historic-petition-viewer/'], + function ($routes) { + $routes->setRouteClass(DashedRoute::class); } -); \ No newline at end of file +); diff --git a/app/plugins/HistoricPetitionViewer/src/Model/Entity/HistoricPetitionMetadata.php b/app/plugins/HistoricPetitionViewer/src/Model/Entity/HistoricPetitionMetadataRecord.php similarity index 96% rename from app/plugins/HistoricPetitionViewer/src/Model/Entity/HistoricPetitionMetadata.php rename to app/plugins/HistoricPetitionViewer/src/Model/Entity/HistoricPetitionMetadataRecord.php index afe5849c..24d3607b 100644 --- a/app/plugins/HistoricPetitionViewer/src/Model/Entity/HistoricPetitionMetadata.php +++ b/app/plugins/HistoricPetitionViewer/src/Model/Entity/HistoricPetitionMetadataRecord.php @@ -31,7 +31,7 @@ use Cake\ORM\Entity; -class HistoricPetitionMetadata extends Entity +class HistoricPetitionMetadataRecord extends Entity { use \App\Lib\Traits\EntityMetaTrait; diff --git a/app/plugins/HistoricPetitionViewer/src/Model/Table/HistoricPetitionAttributesTable.php b/app/plugins/HistoricPetitionViewer/src/Model/Table/HistoricPetitionAttributesTable.php index 6b711196..556e3256 100644 --- a/app/plugins/HistoricPetitionViewer/src/Model/Table/HistoricPetitionAttributesTable.php +++ b/app/plugins/HistoricPetitionViewer/src/Model/Table/HistoricPetitionAttributesTable.php @@ -45,6 +45,9 @@ class HistoricPetitionAttributesTable extends Table { public function initialize(array $config): void { parent::initialize($config); + // Map model to shorter physical table name + $this->setTable('petition_hist_attrs'); + $this->addBehavior('Changelog'); $this->addBehavior('Log'); $this->addBehavior('Timestamp'); diff --git a/app/plugins/HistoricPetitionViewer/src/Model/Table/HistoricPetitionMetadatasTable.php b/app/plugins/HistoricPetitionViewer/src/Model/Table/HistoricPetitionMetadataRecordsTable.php similarity index 96% rename from app/plugins/HistoricPetitionViewer/src/Model/Table/HistoricPetitionMetadatasTable.php rename to app/plugins/HistoricPetitionViewer/src/Model/Table/HistoricPetitionMetadataRecordsTable.php index 0388315d..89a6da23 100644 --- a/app/plugins/HistoricPetitionViewer/src/Model/Table/HistoricPetitionMetadatasTable.php +++ b/app/plugins/HistoricPetitionViewer/src/Model/Table/HistoricPetitionMetadataRecordsTable.php @@ -33,7 +33,7 @@ use Cake\ORM\Table; use Cake\Validation\Validator; -class HistoricPetitionMetadatasTable extends Table { +class HistoricPetitionMetadataRecordsTable extends Table { use \App\Lib\Traits\LabeledLogTrait; use \App\Lib\Traits\LayoutTrait; use \App\Lib\Traits\PermissionsTrait; @@ -45,6 +45,9 @@ class HistoricPetitionMetadatasTable extends Table { public function initialize(array $config): void { parent::initialize($config); + // Map model to shorter physical table name + $this->setTable('petition_meta_hist_recs'); + $this->addBehavior('Changelog'); $this->addBehavior('Log'); $this->addBehavior('Timestamp'); diff --git a/app/plugins/HistoricPetitionViewer/src/View/Cell/HistoricPetitionStepLinksCell.php b/app/plugins/HistoricPetitionViewer/src/View/Cell/HistoricPetitionStepLinksCell.php index 5810af1b..e2345518 100644 --- a/app/plugins/HistoricPetitionViewer/src/View/Cell/HistoricPetitionStepLinksCell.php +++ b/app/plugins/HistoricPetitionViewer/src/View/Cell/HistoricPetitionStepLinksCell.php @@ -86,7 +86,7 @@ public function initialize(): void public function display(int $petitionId): void { // Fetch historic metadata rows for this petition (could be zero or more) - $historicMetadata = $this->fetchTable('HistoricPetitionViewer.HistoricPetitionMetadata') + $historicMetadataRecords = $this->fetchTable('HistoricPetitionViewer.HistoricPetitionMetadataRecords') ->find() ->where(['petition_id' => $petitionId]) ->all(); @@ -98,7 +98,7 @@ public function display(int $petitionId): void ->orderBy(['attribute' => 'ASC', 'id' => 'ASC']) ->all(); - $this->set('vv_historic_petition_metadata', $historicMetadata); + $this->set('vv_historic_petition_metadata_records', $historicMetadataRecords); $this->set('vv_historic_petition_attributes', $historicAttributes); $this->set('vv_obj', $this->vv_obj); } diff --git a/app/plugins/HistoricPetitionViewer/templates/cell/HistoricPetitionStepLinks/display.php b/app/plugins/HistoricPetitionViewer/templates/cell/HistoricPetitionStepLinks/display.php index 851d577a..4055cd21 100644 --- a/app/plugins/HistoricPetitionViewer/templates/cell/HistoricPetitionStepLinks/display.php +++ b/app/plugins/HistoricPetitionViewer/templates/cell/HistoricPetitionStepLinks/display.php @@ -9,7 +9,7 @@ // Expecting: // - $vv_obj (Petition entity) -// - $vv_historic_petition_metadata (ResultSet|array of entities) +// - $vv_historic_petition_metadata_records (ResultSet|array of entities) // - $vv_historic_petition_attributes (ResultSet|array of entities) use Cake\Utility\Hash; @@ -20,7 +20,7 @@ } // Normalize collections -$metaRows = $vv_historic_petition_metadata ?? []; +$metaRows = $vv_historic_petition_metadata_records ?? []; $attrRows = $vv_historic_petition_attributes ?? []; // Helper: render a KV list from an entity/array, excluding technical fields diff --git a/app/plugins/Transmogrify/README.md b/app/plugins/Transmogrify/README.md index 5556143c..72ae342a 100644 --- a/app/plugins/Transmogrify/README.md +++ b/app/plugins/Transmogrify/README.md @@ -241,3 +241,80 @@ For every other character, use the full option: ```bash bin/cake transmogrify --groups-colon-replacement '@' ``` + +## Developers + +### Transmogrify SourceToTarget Command + +What it does +- Prints a JSON template (shaped like the __EXAMPLE_TABLE_TEMPLATE__) that maps a source (v4/classic) table to a target (v5/PE) table. +- Reads the source database schema definition (XML) and the target transmogrify config (JSON), inspects both, and generates a ready-to-insert JSON snippet for tables.json. +- Optionally prints an association tree for a given source table to aid reverse-engineering of relationships. + +Constraints for this command in this project +- Source file must be XML. +- Target file must be JSON. +- All paths provided must be absolute. + +Usage +```bash +bin/cake transmogrify_source_to_target [options] +``` + +Available options +- --source-path, -s PATH + - Absolute path to the SOURCE configuration file (XML required). +- --target-path, -t PATH + - Absolute path to the TARGET configuration file (JSON required). +- --source-table, -S NAME + - Table key/name in the source schema (eg, cm_co_people). +- --target-table, -T NAME + - Table key/name in the target config (eg, people). +- --source-prefix, -p STRING + - Optional prefix to prepend/normalize the source table name in the output (eg, cm_). +- --assoc-tree, -A + - Print an ASCII association tree rooted at --source-table using the source XML, then exit. Requires -s and -S. + +Notes +- The output is a single JSON object keyed by the target table name, ready to paste into a tables.json mapping. +- The command validates absolute paths and readability before processing. + +Examples + +1) Generate a mapping for cm_co_people -> people (source XML, target JSON) +```bash +./bin/cake transmogrify_source_to_target \ + --source-path /abs/path/to/schema.xml \ + --target-path /abs/path/to/tables.json \ + --source-table cm_co_people \ + --target-table people \ + --source-prefix cm_ +``` + +2) Generate a mapping for cm_cous -> cous (with explicit prefix) +```bash +./bin/cake transmogrify_source_to_target \ + -s /abs/path/to/registry/schema.xml \ + -t /abs/path/to/transmogrify/tables.json \ + -S cm_cous \ + -T cous \ + -p cm_ +``` + +3) Print an association tree from a source XML table +```bash + bin/cake transmogrify_source_to_target \ + -s /abs/path/to/schema.xml \ + -S cm_co_people \ + -A +``` + +File expectations + +- Source (XML) + - A schema-style XML file that defines legacy/Classic tables and fields (eg, schema.xml). + - Example table names often start with cm_ (eg, cm_co_people, cm_co_groups). + +- Target (JSON) + - A transmogrify config JSON (eg, tables.json) that already contains __EXAMPLE_TABLE_TEMPLATE__ and the current set of mappings. + - The command reads the example template shape and produces a JSON object keyed by your --target-table, including fieldMap, booleans, and helper hints (targetUnmapped). diff --git a/app/plugins/Transmogrify/config/schema/tables.json b/app/plugins/Transmogrify/config/schema/tables.json index 92e76dbb..6edfb35d 100644 --- a/app/plugins/Transmogrify/config/schema/tables.json +++ b/app/plugins/Transmogrify/config/schema/tables.json @@ -516,5 +516,36 @@ "approver_comment": null, "co_petition_id": "petition_id" } + }, + "petition_meta_hist_recs": { + "source": "cm_co_petitions", + "displayField": "id", + "fieldMap": { + "co_enrollment_flow_id": null, + "co_id": null, + "cou_id": null, + "enrollee_org_identity_id": "enrollee_org_identity_id", + "archived_org_identity_id": "archived_org_identity_id", + "enrollee_co_person_id": null, + "enrollee_co_person_role_id": "enrollee_person_role_id", + "petitioner_co_person_id": null, + "sponsor_co_person_id": "sponsor_person_id", + "approver_co_person_id": "approver_person_id", + "authenticated_identifier": null, + "reference_identifier": null, + "status": null, + "co_petition_id": "petition_id" + } + }, + "petition_hist_attrs": { + "source": "cm_co_petition_attributes", + "displayField": "id", + "fieldMap": { + "co_petition_id": "petition_id", + "co_enrollment_attribute_id": null, + "attribute_foreign_key": null, + "co_petition_attribute_id": null + }, + "addChangelog": true } } diff --git a/app/plugins/Transmogrify/src/Command/TransmogrifyCommand.php b/app/plugins/Transmogrify/src/Command/TransmogrifyCommand.php index 452f8447..35e9965d 100644 --- a/app/plugins/Transmogrify/src/Command/TransmogrifyCommand.php +++ b/app/plugins/Transmogrify/src/Command/TransmogrifyCommand.php @@ -284,6 +284,12 @@ public function execute(Arguments $args, ConsoleIo $io): int $replyBool = filter_var($reply, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); if ($replyBool === true) { $this->cmdPrinter->info(sprintf('Skipping transmogrification for table %s as requested.', $t)); + + // We need to skip the petiton metadata migration if the petitions table is not present + if ($t === 'petitions') { + unset($this->tables['historic_petition_metadata_records']); + unset($this->tables['historic_petition_attributes']); + } continue; } // Proceed for false, null, or empty responses