Skip to content

Commit d7595c4

Browse files
committed
[BUGFIX] Handle "dirty" objects.inv.json data
Handle null values as not set, ignore inventory entries that have non-scalar values or null in the URI. Until now those were causing type errors
1 parent 9b0b3e4 commit d7595c4

File tree

3 files changed

+86
-4
lines changed

3 files changed

+86
-4
lines changed

packages/guides/src/ReferenceResolvers/Interlink/DefaultInventoryLoader.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
use function count;
2222
use function is_array;
23+
use function is_scalar;
24+
use function is_string;
2325
use function strval;
2426

2527
final class DefaultInventoryLoader implements InventoryLoader
@@ -46,11 +48,22 @@ public function loadInventoryFromJson(Inventory $inventory, array $json): void
4648
if (is_array($groupArray)) {
4749
foreach ($groupArray as $linkKey => $linkArray) {
4850
if (!is_array($linkArray) || count($linkArray) < 4) {
51+
$this->logger->warning('Invalid Inventory entry found. ');
52+
continue;
53+
}
54+
55+
if (!is_string($linkArray[2])) {
56+
$this->logger->warning('Invalid Inventory entry found. ');
57+
continue;
58+
}
59+
60+
if (!is_scalar($linkArray[0] ?? '') || !is_scalar($linkArray[1] ?? '') || !is_scalar($linkArray[3] ?? '')) {
61+
$this->logger->warning('Invalid Inventory entry found. ');
4962
continue;
5063
}
5164

5265
$reducedLinkKey = $groupAnchorNormalizer->reduceAnchor(strval($linkKey));
53-
$link = new InventoryLink($linkArray[0], $linkArray[1], $linkArray[2], $linkArray[3]);
66+
$link = new InventoryLink(strval($linkArray[0] ?? ''), strval($linkArray[1] ?? ''), $linkArray[2], strval($linkArray[3] ?? '-'));
5467
$group->addLink($reducedLinkKey, $link);
5568
}
5669
}

packages/guides/tests/unit/Interlink/InventoryLoaderTest.php

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@
1414
namespace phpDocumentor\Guides\Interlink;
1515

1616
use Generator;
17+
use JsonException;
1718
use phpDocumentor\Guides\Nodes\Inline\CrossReferenceNode;
1819
use phpDocumentor\Guides\Nodes\Inline\DocReferenceNode;
1920
use phpDocumentor\Guides\Nodes\Inline\ReferenceNode;
2021
use phpDocumentor\Guides\ReferenceResolvers\Interlink\DefaultInventoryLoader;
2122
use phpDocumentor\Guides\ReferenceResolvers\Interlink\DefaultInventoryRepository;
2223
use phpDocumentor\Guides\ReferenceResolvers\Interlink\Inventory;
2324
use phpDocumentor\Guides\ReferenceResolvers\Interlink\InventoryLink;
24-
use phpDocumentor\Guides\ReferenceResolvers\Interlink\InventoryRepository;
2525
use phpDocumentor\Guides\ReferenceResolvers\Interlink\JsonLoader;
2626
use phpDocumentor\Guides\ReferenceResolvers\Messages;
2727
use phpDocumentor\Guides\ReferenceResolvers\SluggerAnchorNormalizer;
@@ -42,7 +42,7 @@ final class InventoryLoaderTest extends TestCase
4242
{
4343
private DefaultInventoryLoader $inventoryLoader;
4444
private JsonLoader&MockObject $jsonLoader;
45-
private InventoryRepository $inventoryRepository;
45+
private DefaultInventoryRepository $inventoryRepository;
4646
private RenderContext&MockObject $renderContext;
4747
/** @var array<string, mixed> */
4848
private array $json;
@@ -57,7 +57,13 @@ protected function setUp(): void
5757
);
5858
$this->renderContext = $this->createMock(RenderContext::class);
5959
$this->inventoryRepository = new DefaultInventoryRepository(new SluggerAnchorNormalizer(), $this->inventoryLoader, []);
60-
$jsonString = file_get_contents(__DIR__ . '/fixtures/objects.inv.json');
60+
$this->loadObjectsJsonInv(__DIR__ . '/fixtures/objects.inv.json');
61+
}
62+
63+
/** @throws JsonException */
64+
public function loadObjectsJsonInv(string $filename): void
65+
{
66+
$jsonString = file_get_contents($filename);
6167
assertIsString($jsonString);
6268
$this->json = (array) json_decode($jsonString, true, 512, JSON_THROW_ON_ERROR);
6369
$inventory = new Inventory('https://example.com/', new SluggerAnchorNormalizer());
@@ -83,6 +89,15 @@ public function testInventoryIsLoadedExactlyOnce(): void
8389
self::assertGreaterThan(1, count($inventory->getGroups()));
8490
}
8591

92+
public function testInventoryLoaderAcceptsNull(): void
93+
{
94+
$this->loadObjectsJsonInv(__DIR__ . '/fixtures/null-in-objects.inv.json');
95+
$node = new DocReferenceNode('SomeDocument', '', 'somekey');
96+
$inventory = $this->inventoryRepository->getInventory($node, $this->renderContext, new Messages());
97+
self::assertTrue($inventory instanceof Inventory);
98+
self::assertGreaterThan(1, count($inventory->getGroups()));
99+
}
100+
86101
#[DataProvider('rawAnchorProvider')]
87102
public function testInventoryContainsLink(string $expected, CrossReferenceNode $node): void
88103
{
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"std:doc": {
3+
"Index": [
4+
"<project>",
5+
"<version>",
6+
"index.html",
7+
null
8+
],
9+
"Page1": [
10+
null,
11+
"<version>",
12+
"Page1.html",
13+
"-"
14+
],
15+
"Page1/Subpage1": [
16+
"<project>",
17+
null,
18+
"Page1/Subpage1.html",
19+
"-"
20+
],
21+
"Page2/Subpage2": [
22+
"<project>",
23+
"<version>",
24+
null,
25+
"-"
26+
]
27+
},
28+
"std:label": {
29+
"modindex": [
30+
null,
31+
"<version>",
32+
"some_page.html#modindex",
33+
"Module Index"
34+
],
35+
"php-modindex": [
36+
"<project>",
37+
null,
38+
"some_page.html#php-modindex",
39+
"PHP Namespace Index"
40+
],
41+
"php_objectsindex": [
42+
"<project>",
43+
"<version>",
44+
null,
45+
"PHP Objects Index"
46+
],
47+
"php_8-modindex": [
48+
"<project>",
49+
"<version>",
50+
"php-objectsindex.html#php-8-objectsindex",
51+
null
52+
]
53+
}
54+
}

0 commit comments

Comments
 (0)