Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions docroot/modules/custom/foia_raw_data_to_report/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,16 @@ Use a lease longer than the maximum processing duration and avoid overlapping
runners. Revisit the lease and server PHP resource limits when CSV conversion
is implemented; a lease is not a processing timeout.

`RawDataToReportProcessing::generateXmlReport()` is the conversion stub. It
currently writes a **zero-byte placeholder**, not valid XML, and attaches it to
`field_request_data_xml`. It uses the field's configured directory and storage
`RawDataToReportProcessing::generateXmlReport()` uses `XmlReportBuilder` to
create a **metadata-only XML stub** and attaches it to `field_request_data_xml`.
The document uses the example's `iepd:FoiaAnnualReport` root and namespaces,
with `nc:DocumentApplicationName` set to `FOIA Annual Report Workbook`
(application version `1.1`), `nc:DocumentCreationDate/nc:Date` set to the current
generation date (`YYYY-MM-DD`, Drupal runtime timezone), and
`nc:DocumentDescriptionText` set to `FOIA Annual Report`. It is well-formed XML,
but is not yet a complete, schema-valid annual report. CSV-derived sections
will be added to this module's builder; `foia_export_xml` is not modified.
It uses the field's configured directory and storage
scheme, with a unique filename, and replaces the current field reference.
Each filename includes the generation timestamp in `YYYY-MM-DD-HH-MM-SS`
format using the Drupal runtime timezone (normally the site default). Drupal
Expand All @@ -49,8 +56,8 @@ manage file permanence and usage on node save.
Each click creates a separate job. The worker reads the latest node state when
processing; it does not snapshot the CSV selection. Deleted nodes are skipped.
Processing exceptions leave the item available for retry after its lease expires.
The CSV is validated before the placeholder XML is generated; conversion is not
implemented yet.
The CSV is validated before the XML stub is generated; CSV-derived report
sections are not implemented yet.

## CSV validation and messages

Expand Down Expand Up @@ -219,7 +226,7 @@ Import the exported configuration and rebuild caches before running the queue.
The old node-level CSV field is replaced, with no migration of existing uploads.
This follows the pre-launch assumption that existing upload content is disposable.
The queue payload remains the parent node ID. Edits during processing are not
locked or snapshotted. CSV conversion remains a stub, producing one empty XML
locked or snapshotted. CSV conversion remains a stub, producing one metadata-only XML document
only after every component upload passes validation.

Local integration verification (creates and removes temporary fixtures):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Drupal\node\NodeInterface;
use Drupal\foia_raw_data_to_report\CsvValidator;
use Drupal\foia_raw_data_to_report\UploadAssignments;
use Drupal\foia_raw_data_to_report\XmlReportBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
Expand Down Expand Up @@ -108,9 +109,10 @@ public function processItem($data) {
}

/**
* Attaches an empty XML placeholder; future CSV conversion belongs here.
* Builds and attaches report XML after all component CSVs pass validation.
*/
protected function generateXmlReport(NodeInterface $node): void {
$xml = (new XmlReportBuilder())->build();
$field = $node->get('field_request_data_xml');
$previous_file = $field->entity;
$item = $field->first() ?? $field->appendItem();
Expand All @@ -124,7 +126,7 @@ protected function generateXmlReport(NodeInterface $node): void {

// Include the generation time so users can identify the latest report.
$filename = 'raw-data-report-' . $node->id() . '-' . date('Y-m-d-H-i-s') . '.xml';
$file = $this->fileRepository->writeData('', $directory . '/' . $filename, FileExists::Rename);
$file = $this->fileRepository->writeData($xml, $directory . '/' . $filename, FileExists::Rename);
$file->setOwnerId($node->getOwnerId());
$file->save();
$node->set('field_request_data_xml', ['target_id' => $file->id()]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace Drupal\foia_raw_data_to_report;

/**
* Builds annual report XML independently of the node-based foia_export_xml.
*/
final class XmlReportBuilder {

/**
* Namespaces used by the annual report example and existing XML exporter.
*/
private const NAMESPACES = [
'iepd' => 'http://leisp.usdoj.gov/niem/FoiaAnnualReport/exchange/1.03',
'foia' => 'http://leisp.usdoj.gov/niem/FoiaAnnualReport/extension/1.03',
'i' => 'http://niem.gov/niem/appinfo/2.0',
'j' => 'http://niem.gov/niem/domains/jxdm/4.1',
'nc' => 'http://niem.gov/niem/niem-core/2.0',
's' => 'http://niem.gov/niem/structures/2.0',
'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
];

/**
* Builds the metadata stub; CSV-derived report sections will be added later.
*/
public function build(): string {
$document = new \DOMDocument('1.0', 'UTF-8');
$document->formatOutput = TRUE;
$root = $document->createElementNS(self::NAMESPACES['iepd'], 'iepd:FoiaAnnualReport');
$document->appendChild($root);
foreach (self::NAMESPACES as $prefix => $uri) {
$root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $prefix, $uri);
}
$root->setAttributeNS(self::NAMESPACES['xsi'], 'xsi:schemaLocation', self::NAMESPACES['iepd'] . ' ../schema/exchange/FoiaAnnualReport.xsd');

$application = $document->createElementNS(self::NAMESPACES['nc'], 'nc:DocumentApplicationName', 'FOIA Annual Report Workbook');
$application->setAttributeNS(self::NAMESPACES['nc'], 'nc:applicationVersionText', '1.1');
$root->appendChild($application);

// Use the current generation date in Drupal's runtime timezone.
$creation_date = $document->createElementNS(self::NAMESPACES['nc'], 'nc:DocumentCreationDate');
$creation_date->appendChild($document->createElementNS(self::NAMESPACES['nc'], 'nc:Date', date('Y-m-d')));
$root->appendChild($creation_date);
$root->appendChild($document->createElementNS(self::NAMESPACES['nc'], 'nc:DocumentDescriptionText', 'FOIA Annual Report'));

$xml = $document->saveXML();
if ($xml === FALSE) {
throw new \RuntimeException('Unable to serialize the raw data report XML.');
}
return $xml;
}

}
Loading