Skip to content

Commit 09d17df

Browse files
committed
fix(integration): use PR817 page traversal recovery
1 parent 5eab52f commit 09d17df

1 file changed

Lines changed: 64 additions & 6 deletions

File tree

src/Smalot/PdfParser/Pages.php

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,11 @@ public function getPages(bool $deep = false): array
5656
return [];
5757
}
5858

59+
/** @var ElementArray $kidsElement */
5960
$kidsElement = $this->get('Kids');
60-
if ($kidsElement instanceof ElementArray) {
61-
$kids = $kidsElement->getContent();
62-
} else {
63-
$kids = [$kidsElement];
64-
}
6561

6662
if (!$deep) {
67-
return $kids;
63+
return $kidsElement->getContent();
6864
}
6965

7066
// Prepare to apply the Pages' object's fonts to each page
@@ -73,6 +69,10 @@ public function getPages(bool $deep = false): array
7369
}
7470
$fontsAvailable = 0 < \count($this->fonts);
7571

72+
$kids = $kidsElement->getContent();
73+
if (!\is_array($kids)) {
74+
$kids = [];
75+
}
7676
$pages = [];
7777

7878
foreach ($kids as $kid) {
@@ -83,12 +83,70 @@ public function getPages(bool $deep = false): array
8383
$kid->setFonts($this->fonts);
8484
}
8585
$pages[] = $kid;
86+
} elseif ($kid instanceof PDFObject && $this->isRecoverablePageObject($kid)) {
87+
$recoveredPage = new Page($kid->getDocument(), $kid->getHeader(), $kid->getContent(), $kid->getConfig());
88+
if ($fontsAvailable) {
89+
$recoveredPage->setFonts($this->fonts);
90+
}
91+
$pages[] = $recoveredPage;
92+
}
93+
}
94+
95+
if ([] === $pages) {
96+
$pages = $this->recoverPagesByParentReference($fontsAvailable);
97+
}
98+
99+
return $pages;
100+
}
101+
102+
/**
103+
* Recover page objects when Kids is malformed but child objects still point
104+
* to this node via Parent.
105+
*
106+
* @return array<Page>
107+
*/
108+
protected function recoverPagesByParentReference(bool $fontsAvailable): array
109+
{
110+
$pages = [];
111+
112+
foreach ($this->getDocument()->getObjects() as $object) {
113+
if ($object instanceof Page && $object->has('Parent') && $object->get('Parent') === $this) {
114+
if ($fontsAvailable) {
115+
$object->setFonts($this->fonts);
116+
}
117+
$pages[] = $object;
118+
continue;
119+
}
120+
121+
if (!$object instanceof PDFObject || !$this->isRecoverablePageObject($object)) {
122+
continue;
123+
}
124+
125+
if ($object->get('Parent') !== $this) {
126+
continue;
127+
}
128+
129+
$recoveredPage = new Page($object->getDocument(), $object->getHeader(), $object->getContent(), $object->getConfig());
130+
if ($fontsAvailable) {
131+
$recoveredPage->setFonts($this->fonts);
86132
}
133+
$pages[] = $recoveredPage;
87134
}
88135

89136
return $pages;
90137
}
91138

139+
protected function isRecoverablePageObject(PDFObject $object): bool
140+
{
141+
// Some malformed files corrupt the key name for /Type and objects are not
142+
// instantiated as Page. Recover only when page-specific keys are present.
143+
if (!$object->has('Parent')) {
144+
return false;
145+
}
146+
147+
return $object->has('MediaBox') || $object->has('Contents');
148+
}
149+
92150
/**
93151
* Gathers information about fonts and collects them in a list.
94152
*

0 commit comments

Comments
 (0)