Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add metadata #40

Merged
merged 13 commits into from
Dec 29, 2024
2 changes: 1 addition & 1 deletion ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ It is structured mainly into:

The Backend itself is divided into multiple parts

- *Content* contains a minimal structure of supported structures by the backend (hence the "frontend" for the IR). It
- *Structure* contains a minimal structure of supported structures by the backend (hence the "frontend" for the IR). It
renders content types such as text / images into a stream consumable for PDFs, and creates the catalog structure of
the PDF.
- *Catalog* contains the logical structure of a PDF. It is capable of converting this logical structure into a structure
Expand Down
Binary file modified examples/book.pdf
Binary file not shown.
4 changes: 3 additions & 1 deletion examples/book.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
use Famoser\PdfGenerator\Frontend\Layout\Style\FlowDirection;
use Famoser\PdfGenerator\Frontend\LinearDocument;
use Famoser\PdfGenerator\Frontend\Resource\Font;
use Famoser\PdfGenerator\IR\Document\Meta;

$document = new LinearDocument([210, 297], 20);
$meta = Meta::createMeta('en', 'Cat in the rain', ['Ernest Hemingway']);
$document = new LinearDocument([210, 297], 20, $meta);

$font = Font::createFromFile('cruft.ttf');
$normalText = new TextStyle($font, 6.6);
Expand Down
Binary file modified examples/invoice.pdf
Binary file not shown.
4 changes: 3 additions & 1 deletion examples/invoice.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
use Famoser\PdfGenerator\Frontend\LinearDocument;
use Famoser\PdfGenerator\Frontend\Resource\Font;
use Famoser\PdfGenerator\IR\Document\Content\Common\Color;
use Famoser\PdfGenerator\IR\Document\Meta;

$margin = 15;
$document = new LinearDocument([210, 297], $margin);
$meta = Meta::createMeta('en', 'Invoice UZH-ZI-5', ['Florian Moser']);
$document = new LinearDocument([210, 297], $margin, $meta);

$normalFont = Font::createFromDefault();
$normalText = new TextStyle($normalFont);
Expand Down
116 changes: 0 additions & 116 deletions examples/signature.php

This file was deleted.

7 changes: 6 additions & 1 deletion src/Backend/Catalog/Catalog.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

readonly class Catalog extends BaseStructure
{
public function __construct(private Pages $pages)
public function __construct(private Pages $pages, private Metadata $metadata)
{
}

Expand All @@ -32,6 +32,11 @@ public function getPages(): Pages
return $this->pages;
}

public function getMetadata(): Metadata
{
return $this->metadata;
}

public function render(): File
{
$file = new File();
Expand Down
6 changes: 2 additions & 4 deletions src/Backend/Catalog/Content.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Famoser\PdfGenerator\Backend\Catalog\Base\BaseStructure;
use Famoser\PdfGenerator\Backend\CatalogVisitor;
use Famoser\PdfGenerator\Backend\File\Object\Base\BaseObject;
use Famoser\PdfGenerator\Backend\File\Object\StreamObject;

readonly class Content extends BaseStructure
{
Expand All @@ -26,10 +27,7 @@ public function getContent(): string
return $this->content;
}

/**
* @return BaseObject|BaseObject[]
*/
public function accept(CatalogVisitor $visitor): BaseObject|array
public function accept(CatalogVisitor $visitor): StreamObject
{
return $visitor->visitContent($this);
}
Expand Down
4 changes: 4 additions & 0 deletions src/Backend/Catalog/Font.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
namespace Famoser\PdfGenerator\Backend\Catalog;

use Famoser\PdfGenerator\Backend\Catalog\Base\BaseIdentifiableStructure;
use Famoser\PdfGenerator\Backend\CatalogVisitor;
use Famoser\PdfGenerator\Backend\File\Object\Base\BaseObject;

abstract readonly class Font extends BaseIdentifiableStructure
{
Expand All @@ -21,4 +23,6 @@ public function __construct(string $identifier)
}

abstract public function encode(string $value): string;

abstract public function accept(CatalogVisitor $visitor): BaseObject;
}
3 changes: 2 additions & 1 deletion src/Backend/Catalog/Font/Type1.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Famoser\PdfGenerator\Backend\Catalog\Font;
use Famoser\PdfGenerator\Backend\CatalogVisitor;
use Famoser\PdfGenerator\Backend\File\Object\Base\BaseObject;
use Famoser\PdfGenerator\Backend\File\Object\DictionaryObject;

readonly class Type1 extends Font
{
Expand Down Expand Up @@ -49,7 +50,7 @@ public function getEncoding(): string
return self::ENCODING_WIN_ANSI_ENCODING;
}

public function accept(CatalogVisitor $visitor): BaseObject
public function accept(CatalogVisitor $visitor): DictionaryObject
{
return $visitor->visitType1Font($this);
}
Expand Down
48 changes: 48 additions & 0 deletions src/Backend/Catalog/Metadata.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

/*
* This file is part of the famoser/pdf-generator project.
*
* (c) Florian Moser <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Famoser\PdfGenerator\Backend\Catalog;

use Famoser\PdfGenerator\Backend\Catalog\Base\BaseStructure;
use Famoser\PdfGenerator\Backend\CatalogVisitor;
use Famoser\PdfGenerator\Backend\File\Object\Base\BaseObject;

readonly class Metadata extends BaseStructure
{
public function __construct(private string $xml, private ?string $title, private ?string $author, private ?string $keywords)
{
}

public function getXml(): string
{
return $this->xml;
}

public function getTitle(): ?string
{
return $this->title;
}

public function getAuthor(): ?string
{
return $this->author;
}

public function getKeywords(): ?string
{
return $this->keywords;
}

public function accept(CatalogVisitor $visitor): BaseObject
{
return $visitor->visitMetadata($this);
}
}
28 changes: 24 additions & 4 deletions src/Backend/CatalogVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
class CatalogVisitor
{
private ?DictionaryObject $currentPages = null;
public const GENERATOR_VERSION = '0.7';

public function __construct(private readonly File $file)
{
Expand All @@ -38,9 +39,17 @@ public function visitCatalog(Catalog\Catalog $structure): BaseObject
$reference = $structure->getPages()->accept($this);
$dictionary->addReferenceEntry('Pages', $reference);

$metadata = $structure->getMetadata()->accept($this);
$dictionary->addReferenceEntry('Metadata', $metadata);

$dictionary = $this->file->addInfoDictionaryObject();
$dictionary->addTextEntry('Creator', 'famoser/pdf-generator/0.6');
$dictionary->addTextEntry('Producer', 'famoser/pdf-generator/'.self::GENERATOR_VERSION);
$dictionary->addTextEntry('Creator', 'famoser/pdf-generator/'.self::GENERATOR_VERSION);
$dictionary->addDateEntry('CreationDate', new \DateTime());
$addTextIfNotNull = function (string $key, ?string $text) use ($dictionary) { if ($text) { $dictionary->addTextEntry($key, $text); }};
$addTextIfNotNull('Title', $structure->getMetadata()->getTitle());
$addTextIfNotNull('Author', $structure->getMetadata()->getAuthor());
$addTextIfNotNull('Keywords', $structure->getMetadata()->getKeywords());

return $dictionary;
}
Expand Down Expand Up @@ -81,6 +90,17 @@ public function visitPage(Page $structure): BaseObject
return $dictionary;
}

public function visitMetadata(Catalog\Metadata $structure): BaseObject
{
$stream = $this->file->addStreamObject($structure->getXml());

$dictionary = $stream->getMetaData();
$dictionary->setNameEntry('Type', 'Metadata');
$dictionary->setNameEntry('Subtype', 'XML');

return $stream;
}

public function visitResources(Catalog\Resources $structure): BaseObject
{
$dictionary = $this->file->addDictionaryObject();
Expand All @@ -106,12 +126,12 @@ public function visitResources(Catalog\Resources $structure): BaseObject
}

/**
* @var BaseObject[]
* @var array<string, BaseObject>
*/
private array $referenceLookup = [];

/**
* @param BaseIdentifiableStructure[] $structures
* @param Catalog\Font[]|Catalog\Image[] $structures
*/
private function createReferenceDictionary(array $structures): DictionaryToken
{
Expand Down Expand Up @@ -145,7 +165,7 @@ public function visitContents(Catalog\Contents $structure): array
return $baseObjects;
}

public function visitType1Font(Catalog\Font\Type1 $structure): BaseObject
public function visitType1Font(Catalog\Font\Type1 $structure): DictionaryObject
{
$dictionary = $this->file->addDictionaryObject();

Expand Down
9 changes: 5 additions & 4 deletions src/Backend/Structure/Document.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Famoser\PdfGenerator\Backend\Catalog\Pages;
use Famoser\PdfGenerator\Backend\Structure\Document\DocumentResources;
use Famoser\PdfGenerator\Backend\Structure\Document\Page;
use Famoser\PdfGenerator\Backend\Structure\Document\XmpMeta;
use Famoser\PdfGenerator\Backend\Structure\Optimization\Configuration;

class Document
Expand All @@ -27,7 +28,7 @@ class Document

private readonly Configuration $configuration;

public function __construct()
public function __construct(private readonly XmpMeta $meta)
{
$this->configuration = new Configuration();
}
Expand All @@ -40,17 +41,17 @@ public function addPage(Page $page): void
public function render(): Catalog
{
$documentVisitor = new DocumentVisitor($this->configuration);
$documentResources = new DocumentResources($documentVisitor);
$meta = $this->meta->accept($documentVisitor);

/** @var CatalogPage[] $pageEntries */
$documentResources = new DocumentResources($documentVisitor);
$pageEntries = [];
foreach ($this->pages as $page) {
$pageEntries[] = $page->render($documentResources);
}

$pages = new Pages($pageEntries);

return new Catalog($pages);
return new Catalog($pages, $meta);
}

public function save(): string
Expand Down
Loading
Loading