127 lines
4.2 KiB
PHP
127 lines
4.2 KiB
PHP
<?php
|
|
|
|
namespace App\Support\Archivio;
|
|
|
|
final class ArchiveQrXmlPayload
|
|
{
|
|
public const VERSION = '1';
|
|
|
|
public const PROFILE_LITE = 'MASTER-XML-LITE';
|
|
|
|
public const PROFILE_NFC = 'MASTER-NFC-LITE';
|
|
|
|
public const COMPRESSED_PREFIX = 'NGXZ1:';
|
|
|
|
/** @param array<string, mixed> $data */
|
|
public static function build(array $data, string $profile = self::PROFILE_LITE): string
|
|
{
|
|
$normalized = self::normalize($data);
|
|
$checksum = self::checksum($normalized + ['profile' => $profile]);
|
|
|
|
$fields = [
|
|
'id' => $normalized['id'],
|
|
'legacy' => $normalized['legacy'],
|
|
'type' => $normalized['type'],
|
|
'sid' => $normalized['stabile_id'],
|
|
'parent' => $normalized['parent'],
|
|
'code' => $normalized['code'],
|
|
'title' => $normalized['title'],
|
|
'doc' => $normalized['document_code'],
|
|
'class' => $normalized['archive_class'],
|
|
'loc' => $normalized['location'],
|
|
'cs' => $checksum,
|
|
];
|
|
|
|
$xml = '<ngxa v="' . self::VERSION . '" p="' . self::escape($profile) . '">';
|
|
|
|
foreach ($fields as $tag => $value) {
|
|
if ($value === '') {
|
|
continue;
|
|
}
|
|
|
|
$xml .= '<' . $tag . '>' . self::escape($value) . '</' . $tag . '>';
|
|
}
|
|
|
|
$xml .= '</ngxa>';
|
|
|
|
return $xml;
|
|
}
|
|
|
|
/** @param array<string, mixed> $data */
|
|
public static function buildCompressed(array $data, string $profile = self::PROFILE_LITE): string
|
|
{
|
|
$xml = self::build($data, $profile);
|
|
$compressed = gzcompress($xml, 9);
|
|
|
|
if ($compressed === false) {
|
|
return self::COMPRESSED_PREFIX . base64_encode($xml);
|
|
}
|
|
|
|
return self::COMPRESSED_PREFIX . base64_encode($compressed);
|
|
}
|
|
|
|
/** @param array<string, mixed> $data */
|
|
public static function buildNfcLite(array $data): string
|
|
{
|
|
return self::build([
|
|
'id' => $data['id'] ?? '',
|
|
'legacy' => $data['legacy'] ?? '',
|
|
'type' => $data['type'] ?? '',
|
|
'stabile_id' => $data['stabile_id'] ?? '',
|
|
'parent' => $data['parent'] ?? 'RADICE',
|
|
'code' => $data['code'] ?? '',
|
|
'archive_class' => $data['archive_class'] ?? '',
|
|
], self::PROFILE_NFC);
|
|
}
|
|
|
|
/** @param array<string, mixed> $data
|
|
* @return array<string, mixed>
|
|
*/
|
|
public static function buildProfiles(array $data): array
|
|
{
|
|
$xmlOpen = self::build($data, self::PROFILE_LITE);
|
|
$xmlNfc = self::buildNfcLite($data);
|
|
|
|
return [
|
|
'xml_open' => $xmlOpen,
|
|
'xml_open_length' => strlen($xmlOpen),
|
|
'xml_zip' => self::buildCompressed($data, self::PROFILE_LITE),
|
|
'xml_nfc' => $xmlNfc,
|
|
'xml_nfc_length' => strlen($xmlNfc),
|
|
];
|
|
}
|
|
|
|
/** @param array<string, mixed> $data
|
|
* @return array<string, string>
|
|
*/
|
|
private static function normalize(array $data): array
|
|
{
|
|
$id = trim((string) ($data['id'] ?? ''));
|
|
|
|
return [
|
|
'id' => $id,
|
|
'legacy' => trim((string) ($data['legacy'] ?? ($id !== '' ? 'AF:' . $id : ''))),
|
|
'type' => trim((string) ($data['type'] ?? '')),
|
|
'stabile_id' => trim((string) ($data['stabile_id'] ?? '')),
|
|
'parent' => trim((string) ($data['parent'] ?? 'RADICE')),
|
|
'code' => trim((string) ($data['code'] ?? '')),
|
|
'title' => trim((string) ($data['title'] ?? '')),
|
|
'document_code'=> trim((string) ($data['document_code'] ?? '')),
|
|
'archive_class'=> trim((string) ($data['archive_class'] ?? '')),
|
|
'location' => trim((string) ($data['location'] ?? '')),
|
|
];
|
|
}
|
|
|
|
/** @param array<string, string> $data */
|
|
private static function checksum(array $data): string
|
|
{
|
|
ksort($data);
|
|
|
|
return strtoupper(substr(sha1(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) ?: ''), 0, 12));
|
|
}
|
|
|
|
private static function escape(string $value): string
|
|
{
|
|
return htmlspecialchars($value, ENT_XML1 | ENT_COMPAT, 'UTF-8');
|
|
}
|
|
} |