1<?php
2/**
3 * This file is part of FPDI
4 *
5 * @package   setasign\Fpdi
6 * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
7 * @license   http://opensource.org/licenses/mit-license The MIT License
8 */
9
10namespace setasign\Fpdi\Tfpdf;
11
12use setasign\Fpdi\FpdiTrait;
13use setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException;
14use setasign\Fpdi\PdfParser\PdfParserException;
15use setasign\Fpdi\PdfParser\Type\PdfIndirectObject;
16use setasign\Fpdi\PdfParser\Type\PdfNull;
17
18/**
19 * Class Fpdi
20 *
21 * This class let you import pages of existing PDF documents into a reusable structure for tFPDF.
22 *
23 * @package setasign\Fpdi
24 */
25class Fpdi extends FpdfTpl
26{
27    use FpdiTrait;
28
29    /**
30     * FPDI version
31     *
32     * @string
33     */
34    const VERSION = '2.3.1';
35
36    public function _enddoc()
37    {
38        parent::_enddoc();
39        $this->cleanUp();
40    }
41
42    /**
43     * Draws an imported page or a template onto the page or another template.
44     *
45     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
46     * aspect ratio.
47     *
48     * @param mixed $tpl The template id
49     * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array
50     *                           with the keys "x", "y", "width", "height", "adjustPageSize".
51     * @param float|int $y The ordinate of upper-left corner.
52     * @param float|int|null $width The width.
53     * @param float|int|null $height The height.
54     * @param bool $adjustPageSize
55     * @return array The size
56     * @see Fpdi::getTemplateSize()
57     */
58    public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false)
59    {
60        if (isset($this->importedPages[$tpl])) {
61            $size = $this->useImportedPage($tpl, $x, $y, $width, $height, $adjustPageSize);
62            if ($this->currentTemplateId !== null) {
63                $this->templates[$this->currentTemplateId]['resources']['templates']['importedPages'][$tpl] = $tpl;
64            }
65            return $size;
66        }
67
68        return parent::useTemplate($tpl, $x, $y, $width, $height, $adjustPageSize);
69    }
70
71    /**
72     * Get the size of an imported page or template.
73     *
74     * Give only one of the size parameters (width, height) to calculate the other one automatically in view to the
75     * aspect ratio.
76     *
77     * @param mixed $tpl The template id
78     * @param float|int|null $width The width.
79     * @param float|int|null $height The height.
80     * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P)
81     */
82    public function getTemplateSize($tpl, $width = null, $height = null)
83    {
84        $size = parent::getTemplateSize($tpl, $width, $height);
85        if ($size === false) {
86            return $this->getImportedPageSize($tpl, $width, $height);
87        }
88
89        return $size;
90    }
91
92    /**
93     * @inheritdoc
94     * @throws CrossReferenceException
95     * @throws PdfParserException
96     */
97    public function _putimages()
98    {
99        $this->currentReaderId = null;
100        parent::_putimages();
101
102        foreach ($this->importedPages as $key => $pageData) {
103            $this->_newobj();
104            $this->importedPages[$key]['objectNumber'] = $this->n;
105            $this->currentReaderId = $pageData['readerId'];
106            $this->writePdfType($pageData['stream']);
107            $this->_put('endobj');
108        }
109
110        foreach (\array_keys($this->readers) as $readerId) {
111            $parser = $this->getPdfReader($readerId)->getParser();
112            $this->currentReaderId = $readerId;
113
114            while (($objectNumber = \array_pop($this->objectsToCopy[$readerId])) !== null) {
115                try {
116                    $object = $parser->getIndirectObject($objectNumber);
117
118                } catch (CrossReferenceException $e) {
119                    if ($e->getCode() === CrossReferenceException::OBJECT_NOT_FOUND) {
120                        $object = PdfIndirectObject::create($objectNumber, 0, new PdfNull());
121                    } else {
122                        throw $e;
123                    }
124                }
125
126                $this->writePdfType($object);
127            }
128        }
129
130        $this->currentReaderId = null;
131    }
132
133    /**
134     * @inheritdoc
135     */
136    protected function _putxobjectdict()
137    {
138        foreach ($this->importedPages as $key => $pageData) {
139            $this->_put('/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R');
140        }
141
142        parent::_putxobjectdict();
143    }
144
145    /**
146     * @inheritdoc
147     */
148    protected function _put($s, $newLine = true)
149    {
150        if ($newLine) {
151            $this->buffer .= $s . "\n";
152        } else {
153            $this->buffer .= $s;
154        }
155    }
156}