Add breadcrumbs function, docs and tests
This commit is contained in:
parent
4448798bf5
commit
2bdb432a9f
12 changed files with 451 additions and 0 deletions
21
devel/tests/helpers/build_breadcrumbs_empty_path.phpt
Normal file
21
devel/tests/helpers/build_breadcrumbs_empty_path.phpt
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
--TEST--
|
||||
buildBreadcrumbs: returns empty array for empty request path (frontpage)
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/context.php';
|
||||
require '/var/www/app/hooks.php';
|
||||
require '/var/www/app/constants.php';
|
||||
require '/var/www/app/helpers.php';
|
||||
|
||||
$ctx = new Context(
|
||||
contentDir: '/tmp/test_content',
|
||||
templates: new Templates('/tmp/base.php', '/tmp/page.php', '/tmp/list.php'),
|
||||
requestPath: '',
|
||||
hasTrailingSlash: false
|
||||
);
|
||||
|
||||
$result = buildBreadcrumbs($ctx);
|
||||
echo count($result) . "\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
0
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
--TEST--
|
||||
buildBreadcrumbs: extracts title from content file when metadata has no title
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/context.php';
|
||||
require '/var/www/app/hooks.php';
|
||||
require '/var/www/app/constants.php';
|
||||
require '/var/www/app/helpers.php';
|
||||
require '/var/www/app/content.php';
|
||||
|
||||
// Create temp directory structure with no metadata title
|
||||
$tempBase = sys_get_temp_dir() . '/phpt_' . getmypid();
|
||||
$tempContent = $tempBase . '/content';
|
||||
$tempLevel1 = $tempContent . '/nyheter';
|
||||
$tempLevel2 = $tempLevel1 . '/riksrevisjonen';
|
||||
|
||||
mkdir($tempLevel1, 0777, true);
|
||||
mkdir($tempLevel2, 0777, true);
|
||||
|
||||
// Create content file with h1 title
|
||||
file_put_contents($tempLevel2 . '/index.md', "# Riksrevisjonen\n\nSome content here.");
|
||||
|
||||
// Metadata without title
|
||||
file_put_contents($tempLevel2 . '/metadata.ini', "slug = riksrevisjonen\n");
|
||||
|
||||
$ctx = new Context(
|
||||
contentDir: $tempContent,
|
||||
templates: new Templates('/tmp/base.php', '/tmp/page.php', '/tmp/list.php'),
|
||||
requestPath: 'nyheter/riksrevisjonen/artikkel',
|
||||
hasTrailingSlash: false
|
||||
);
|
||||
|
||||
$result = buildBreadcrumbs($ctx);
|
||||
|
||||
// Output count and titles
|
||||
echo count($result) . "\n";
|
||||
echo $result[0]['title'] . "\n";
|
||||
echo $result[1]['title'] . "\n";
|
||||
|
||||
// Cleanup
|
||||
unlink($tempLevel2 . '/metadata.ini');
|
||||
unlink($tempLevel2 . '/index.md');
|
||||
rmdir($tempLevel2);
|
||||
rmdir($tempLevel1);
|
||||
rmdir($tempContent);
|
||||
rmdir($tempBase);
|
||||
?>
|
||||
--EXPECT--
|
||||
2
|
||||
Nyheter
|
||||
Riksrevisjonen
|
||||
21
devel/tests/helpers/build_breadcrumbs_level1.phpt
Normal file
21
devel/tests/helpers/build_breadcrumbs_level1.phpt
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
--TEST--
|
||||
buildBreadcrumbs: returns empty array for level 1 path (should not show breadcrumbs)
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/context.php';
|
||||
require '/var/www/app/hooks.php';
|
||||
require '/var/www/app/constants.php';
|
||||
require '/var/www/app/helpers.php';
|
||||
|
||||
$ctx = new Context(
|
||||
contentDir: '/tmp/test_content',
|
||||
templates: new Templates('/tmp/base.php', '/tmp/page.php', '/tmp/list.php'),
|
||||
requestPath: 'nyheter',
|
||||
hasTrailingSlash: false
|
||||
);
|
||||
|
||||
$result = buildBreadcrumbs($ctx);
|
||||
echo count($result) . "\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
0
|
||||
21
devel/tests/helpers/build_breadcrumbs_level2.phpt
Normal file
21
devel/tests/helpers/build_breadcrumbs_level2.phpt
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
--TEST--
|
||||
buildBreadcrumbs: returns empty array for level 2 path (should not show breadcrumbs)
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/context.php';
|
||||
require '/var/www/app/hooks.php';
|
||||
require '/var/www/app/constants.php';
|
||||
require '/var/www/app/helpers.php';
|
||||
|
||||
$ctx = new Context(
|
||||
contentDir: '/tmp/test_content',
|
||||
templates: new Templates('/tmp/base.php', '/tmp/page.php', '/tmp/list.php'),
|
||||
requestPath: 'nyheter/riksrevisjonen',
|
||||
hasTrailingSlash: false
|
||||
);
|
||||
|
||||
$result = buildBreadcrumbs($ctx);
|
||||
echo count($result) . "\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
0
|
||||
57
devel/tests/helpers/build_breadcrumbs_level3.phpt
Normal file
57
devel/tests/helpers/build_breadcrumbs_level3.phpt
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
--TEST--
|
||||
buildBreadcrumbs: builds breadcrumb array for level 3+ path
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/context.php';
|
||||
require '/var/www/app/hooks.php';
|
||||
require '/var/www/app/constants.php';
|
||||
require '/var/www/app/helpers.php';
|
||||
require '/var/www/app/content.php';
|
||||
|
||||
// Create temp directory structure
|
||||
$tempBase = sys_get_temp_dir() . '/phpt_' . getmypid();
|
||||
$tempContent = $tempBase . '/content';
|
||||
$tempLevel1 = $tempContent . '/nyheter';
|
||||
$tempLevel2 = $tempLevel1 . '/riksrevisjonen';
|
||||
|
||||
mkdir($tempLevel1, 0777, true);
|
||||
mkdir($tempLevel2, 0777, true);
|
||||
|
||||
// Create metadata files
|
||||
file_put_contents($tempLevel1 . '/metadata.ini', "title = Nyheter\nslug = nyheter\n");
|
||||
file_put_contents($tempLevel2 . '/metadata.ini', "title = Riksrevisjonen\nslug = riksrevisjonen\n");
|
||||
|
||||
$ctx = new Context(
|
||||
contentDir: $tempContent,
|
||||
templates: new Templates('/tmp/base.php', '/tmp/page.php', '/tmp/list.php'),
|
||||
requestPath: 'nyheter/riksrevisjonen/artikkel',
|
||||
hasTrailingSlash: false
|
||||
);
|
||||
|
||||
$result = buildBreadcrumbs($ctx);
|
||||
|
||||
// Output count and first item details
|
||||
echo count($result) . "\n";
|
||||
if (count($result) > 0) {
|
||||
echo $result[0]['title'] . "\n";
|
||||
echo $result[0]['url'] . "\n";
|
||||
}
|
||||
if (count($result) > 1) {
|
||||
echo $result[1]['title'] . "\n";
|
||||
echo $result[1]['url'] . "\n";
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
unlink($tempLevel2 . '/metadata.ini');
|
||||
unlink($tempLevel1 . '/metadata.ini');
|
||||
rmdir($tempLevel2);
|
||||
rmdir($tempLevel1);
|
||||
rmdir($tempContent);
|
||||
rmdir($tempBase);
|
||||
?>
|
||||
--EXPECT--
|
||||
2
|
||||
Nyheter
|
||||
/nyheter/
|
||||
Riksrevisjonen
|
||||
/riksrevisjonen/
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
--TEST--
|
||||
buildBreadcrumbs: skips path traversal attempts (security)
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/context.php';
|
||||
require '/var/www/app/hooks.php';
|
||||
require '/var/www/app/constants.php';
|
||||
require '/var/www/app/helpers.php';
|
||||
require '/var/www/app/content.php';
|
||||
|
||||
// Create temp directory structure
|
||||
$tempBase = sys_get_temp_dir() . '/phpt_' . getmypid();
|
||||
$tempContent = $tempBase . '/content';
|
||||
$tempLevel1 = $tempContent . '/nyheter';
|
||||
$tempLevel2 = $tempLevel1 . '/riksrevisjonen';
|
||||
|
||||
mkdir($tempLevel1, 0777, true);
|
||||
mkdir($tempLevel2, 0777, true);
|
||||
|
||||
// Create metadata files
|
||||
file_put_contents($tempLevel1 . '/metadata.ini', "title = Nyheter\n");
|
||||
file_put_contents($tempLevel2 . '/metadata.ini', "title = Riksrevisjonen\n");
|
||||
|
||||
// Path with ".." should be skipped - the .. segment is ignored but valid dirs before it are included
|
||||
$ctx = new Context(
|
||||
contentDir: $tempContent,
|
||||
templates: new Templates('/tmp/base.php', '/tmp/page.php', '/tmp/list.php'),
|
||||
requestPath: 'nyheter/riksrevisjonen/../test',
|
||||
hasTrailingSlash: false
|
||||
);
|
||||
|
||||
$result = buildBreadcrumbs($ctx);
|
||||
|
||||
// Output count - nyheter and riksrevisjonen exist, .. is skipped, test doesn't exist
|
||||
echo count($result) . "\n";
|
||||
// Verify no ".." appears in any URL
|
||||
$hasTraversal = false;
|
||||
foreach ($result as $crumb) {
|
||||
if (str_contains($crumb['url'], '..')) {
|
||||
$hasTraversal = true;
|
||||
}
|
||||
}
|
||||
echo ($hasTraversal ? "traversal" : "safe") . "\n";
|
||||
|
||||
// Cleanup
|
||||
unlink($tempLevel2 . '/metadata.ini');
|
||||
unlink($tempLevel1 . '/metadata.ini');
|
||||
rmdir($tempLevel2);
|
||||
rmdir($tempLevel1);
|
||||
rmdir($tempContent);
|
||||
rmdir($tempBase);
|
||||
?>
|
||||
--EXPECT--
|
||||
2
|
||||
safe
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
--TEST--
|
||||
buildBreadcrumbs: skips non-existent directories gracefully
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/context.php';
|
||||
require '/var/www/app/hooks.php';
|
||||
require '/var/www/app/constants.php';
|
||||
require '/var/www/app/helpers.php';
|
||||
require '/var/www/app/content.php';
|
||||
|
||||
// Create temp directory structure with only level 1
|
||||
$tempBase = sys_get_temp_dir() . '/phpt_' . getmypid();
|
||||
$tempContent = $tempBase . '/content';
|
||||
$tempLevel1 = $tempContent . '/nyheter';
|
||||
|
||||
mkdir($tempLevel1, 0777, true);
|
||||
file_put_contents($tempLevel1 . '/metadata.ini', "title = Nyheter\n");
|
||||
|
||||
// Request path has middle directories that don't exist
|
||||
$ctx = new Context(
|
||||
contentDir: $tempContent,
|
||||
templates: new Templates('/tmp/base.php', '/tmp/page.php', '/tmp/list.php'),
|
||||
requestPath: 'nyheter/nonexistent/artikkel',
|
||||
hasTrailingSlash: false
|
||||
);
|
||||
|
||||
$result = buildBreadcrumbs($ctx);
|
||||
|
||||
// Only nyheter exists, so only 1 breadcrumb
|
||||
echo count($result) . "\n";
|
||||
|
||||
// Cleanup
|
||||
unlink($tempLevel1 . '/metadata.ini');
|
||||
rmdir($tempLevel1);
|
||||
rmdir($tempContent);
|
||||
rmdir($tempBase);
|
||||
?>
|
||||
--EXPECT--
|
||||
1
|
||||
49
devel/tests/helpers/build_breadcrumbs_slug_override.phpt
Normal file
49
devel/tests/helpers/build_breadcrumbs_slug_override.phpt
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
--TEST--
|
||||
buildBreadcrumbs: uses slug from metadata for URL when available
|
||||
--FILE--
|
||||
<?php
|
||||
require '/var/www/app/context.php';
|
||||
require '/var/www/app/hooks.php';
|
||||
require '/var/www/app/constants.php';
|
||||
require '/var/www/app/helpers.php';
|
||||
require '/var/www/app/content.php';
|
||||
|
||||
// Create temp directory structure with slug override
|
||||
$tempBase = sys_get_temp_dir() . '/phpt_' . getmypid();
|
||||
$tempContent = $tempBase . '/content';
|
||||
$tempLevel1 = $tempContent . '/nyheter';
|
||||
$tempLevel2 = $tempLevel1 . '/riksrevisjonen';
|
||||
|
||||
mkdir($tempLevel1, 0777, true);
|
||||
mkdir($tempLevel2, 0777, true);
|
||||
|
||||
// Metadata with custom slug
|
||||
file_put_contents($tempLevel1 . '/metadata.ini', "title = Nyheter\nslug = nyheter-custom\n");
|
||||
file_put_contents($tempLevel2 . '/metadata.ini', "title = Riksrevisjonen\nslug = statens-revisor\n");
|
||||
|
||||
$ctx = new Context(
|
||||
contentDir: $tempContent,
|
||||
templates: new Templates('/tmp/base.php', '/tmp/page.php', '/tmp/list.php'),
|
||||
requestPath: 'nyheter/riksrevisjonen/artikkel',
|
||||
hasTrailingSlash: false
|
||||
);
|
||||
|
||||
$result = buildBreadcrumbs($ctx);
|
||||
|
||||
// Output count and URLs
|
||||
echo count($result) . "\n";
|
||||
echo $result[0]['url'] . "\n";
|
||||
echo $result[1]['url'] . "\n";
|
||||
|
||||
// Cleanup
|
||||
unlink($tempLevel2 . '/metadata.ini');
|
||||
unlink($tempLevel1 . '/metadata.ini');
|
||||
rmdir($tempLevel2);
|
||||
rmdir($tempLevel1);
|
||||
rmdir($tempContent);
|
||||
rmdir($tempBase);
|
||||
?>
|
||||
--EXPECT--
|
||||
2
|
||||
/nyheter-custom/
|
||||
/statens-revisor/
|
||||
Loading…
Add table
Add a link
Reference in a new issue