addKid($page), new Entry(new NameType('PrivateOriginal'), new IndirectReference($old))); $initial = (new FileStructure(new FileHeader(), new FileBody($catalog), crossReferenceFormat: CrossReferenceFormat::Stream))->toRevision(); $identifier = $initial->binding($old)->identifier; // Deletion removes no historical bytes. It records the number in the // free list with the next generation, here 1. The old generation 0 // reference now represents null, following ISO 7.3.9. $released = (new IncrementalUpdate($initial, new FileBody(), objectOperations: new ReleaseIndirectObject($identifier)))->toRevision(); // A new identity can reuse this number with its free generation. // Its type is independent: the old string becomes a dictionary here. $new = new DictionaryType(new Entry(new NameType('Message'), new LiteralString('Nouvelle identite, generation 1.'))); $updatedCatalog = $released->binding($catalog)->dictionary ?? throw new LogicException('Le catalogue possède un instantané.'); $updatedCatalog = $updatedCatalog->with(new Entry(new NameType('PrivateCurrent'), new IndirectReference($new))); $reused = (new IncrementalUpdate( $released, new FileBody(new IndirectObject($updatedCatalog, $initial->binding($catalog)->identifier)), objectOperations: new ReuseObjectNumber($identifier->objectNumber, $new), ))->toRevision(); // Both references stay distinct despite sharing a number. The core // keeps obsolete aliases to write their original generation without // aliasing them to the new value or resurrecting the old object. $oldReference = $reused->reference($old); $currentReference = $reused->reference($new); $path = $argv[1] ?? __DIR__ . '/object-lifecycle.pdf'; $reused->writeTo($path); echo $oldReference->identifier, ' R -> null ; ', $currentReference->identifier, ' R -> dictionnaire', PHP_EOL; echo $path, PHP_EOL;