Retire the six old-taxonomy category stubs under /products
- diagnosis first (migrations/check_old_stubs.php, kept): the six old-taxonomy pages (#451-454, #456, #458) were completely empty - no content elements and NO family child pages (the family workbooks were deliberately never imported), so nothing needed moving - migrations/retire_old_category_stubs.php (dry-run by default, guards against children/content) soft-deletes each stub and queues a 301 sys_redirect onto its new-taxonomy equivalent; existing redirects for a path are kept - applied and verified live: all six old paths answer with the 301 redirect envelope onto the correct new category page, and the main navigation now shows exactly the nine new categories in sitemap order Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b0690c4cdc
commit
80f6da7949
2 files changed
+135
No files matched your search
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Diagnose: the six old-taxonomy category stubs under /products
|
||||||
|
* (#451-454, #456, #458) - their own content, their child pages (family
|
||||||
|
* level) and those children's content/state. Basis for the
|
||||||
|
* hide/move/redirect decision (2026-10-27).
|
||||||
|
*
|
||||||
|
* READ-ONLY. Usage: php migrations/check_old_stubs.php
|
||||||
|
*/
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
ini_set('display_errors', '1');
|
||||||
|
|
||||||
|
$root = null;
|
||||||
|
$dir = __DIR__;
|
||||||
|
for ($i = 0; $i < 5; $i++) {
|
||||||
|
if (is_file($dir . '/config/system/settings.php')) { $root = $dir; break; }
|
||||||
|
$dir = dirname($dir);
|
||||||
|
}
|
||||||
|
if ($root === null) { exit("no project root\n"); }
|
||||||
|
$settings = require $root . '/config/system/settings.php';
|
||||||
|
$db = $settings['DB']['Connections']['Default'];
|
||||||
|
$pdo = new PDO(
|
||||||
|
sprintf('mysql:host=%s;port=%s;dbname=%s;charset=utf8mb4', $db['host'] ?? 'localhost', $db['port'] ?? 3306, $db['dbname'] ?? ''),
|
||||||
|
$db['user'] ?? '', $db['password'] ?? '',
|
||||||
|
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
|
||||||
|
);
|
||||||
|
|
||||||
|
function tree(PDO $pdo, int $pid, int $depth): void
|
||||||
|
{
|
||||||
|
$rows = $pdo->query("SELECT uid, title, slug, doktype, layout, hidden, nav_hide, sorting
|
||||||
|
FROM pages WHERE deleted = 0 AND pid = $pid ORDER BY sorting")->fetchAll();
|
||||||
|
foreach ($rows as $r) {
|
||||||
|
$ce = (int)$pdo->query("SELECT COUNT(*) FROM tt_content WHERE deleted = 0 AND hidden = 0 AND pid = {$r['uid']}")->fetchColumn();
|
||||||
|
printf("%s#%-5d dok=%d lay=%-2d hid=%d nav=%d ce=%-3d %-55s %s\n",
|
||||||
|
str_repeat(' ', $depth), $r['uid'], $r['doktype'], $r['layout'], $r['hidden'], $r['nav_hide'], $ce, $r['slug'], $r['title']);
|
||||||
|
tree($pdo, (int)$r['uid'], $depth + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ([451, 452, 453, 454, 456, 458] as $stub) {
|
||||||
|
$r = $pdo->query("SELECT uid, title, slug, hidden, nav_hide FROM pages WHERE uid = $stub")->fetch();
|
||||||
|
$ce = (int)$pdo->query("SELECT COUNT(*) FROM tt_content WHERE deleted = 0 AND hidden = 0 AND pid = $stub")->fetchColumn();
|
||||||
|
printf("STUB #%-4d hid=%d nav=%d ce=%-3d %-50s %s\n", $r['uid'], $r['hidden'], $r['nav_hide'], $ce, $r['slug'], $r['title']);
|
||||||
|
tree($pdo, $stub, 1);
|
||||||
|
echo "\n";
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retires the six old-taxonomy category stubs under /products (decision
|
||||||
|
* Olli 2026-10-27; diagnosis check_old_stubs.php: all six are EMPTY -
|
||||||
|
* no content elements, no child pages, so nothing needs moving):
|
||||||
|
*
|
||||||
|
* soft-delete the stub page and queue a 301 sys_redirect onto its new
|
||||||
|
* category equivalent. Guards: a stub with children or visible content
|
||||||
|
* is skipped and reported; an existing redirect for the path is kept.
|
||||||
|
*
|
||||||
|
* Usage: php migrations/retire_old_category_stubs.php (dry run)
|
||||||
|
* php migrations/retire_old_category_stubs.php --apply
|
||||||
|
*/
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
ini_set('display_errors', '1');
|
||||||
|
|
||||||
|
$apply = in_array('--apply', $argv, true);
|
||||||
|
|
||||||
|
$root = null;
|
||||||
|
$dir = __DIR__;
|
||||||
|
for ($i = 0; $i < 5; $i++) {
|
||||||
|
if (is_file($dir . '/config/system/settings.php')) { $root = $dir; break; }
|
||||||
|
$dir = dirname($dir);
|
||||||
|
}
|
||||||
|
if ($root === null) { exit("no project root\n"); }
|
||||||
|
$settings = require $root . '/config/system/settings.php';
|
||||||
|
$db = $settings['DB']['Connections']['Default'];
|
||||||
|
$pdo = new PDO(
|
||||||
|
sprintf('mysql:host=%s;port=%s;dbname=%s;charset=utf8mb4', $db['host'] ?? 'localhost', $db['port'] ?? 3306, $db['dbname'] ?? ''),
|
||||||
|
$db['user'] ?? '', $db['password'] ?? '',
|
||||||
|
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
|
||||||
|
);
|
||||||
|
|
||||||
|
$map = [
|
||||||
|
'/products/platforms-and-end-points' => '/products/iptv-and-digital-signage',
|
||||||
|
'/products/ip-video-streaming' => '/products/video-encoding-and-streaming',
|
||||||
|
'/products/control-room-solutions' => '/products/control-room-platforms',
|
||||||
|
'/products/avoip-distribution-kvm' => '/products/av-over-ip-and-kvm',
|
||||||
|
'/products/graphics-multi-display' => '/products/graphics-and-multi-display',
|
||||||
|
'/products/infrastructure-accessories' => '/products/infrastructure-and-accessories',
|
||||||
|
];
|
||||||
|
|
||||||
|
echo ($apply ? "APPLY\n" : "DRY-RUN\n");
|
||||||
|
foreach ($map as $oldSlug => $newSlug) {
|
||||||
|
$stub = $pdo->prepare('SELECT uid, title FROM pages WHERE deleted = 0 AND slug = ?');
|
||||||
|
$stub->execute([$oldSlug]);
|
||||||
|
$stub = $stub->fetch();
|
||||||
|
if (!$stub) {
|
||||||
|
echo " = $oldSlug: already gone\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$uid = (int)$stub['uid'];
|
||||||
|
$children = (int)$pdo->query("SELECT COUNT(*) FROM pages WHERE deleted = 0 AND pid = $uid")->fetchColumn();
|
||||||
|
$content = (int)$pdo->query("SELECT COUNT(*) FROM tt_content WHERE deleted = 0 AND pid = $uid")->fetchColumn();
|
||||||
|
if ($children > 0 || $content > 0) {
|
||||||
|
echo " !! #$uid $oldSlug has $children child page(s) / $content element(s) - SKIPPED, decide manually\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$target = $pdo->prepare('SELECT uid FROM pages WHERE deleted = 0 AND slug = ?');
|
||||||
|
$target->execute([$newSlug]);
|
||||||
|
$targetUid = (int)($target->fetchColumn() ?: 0);
|
||||||
|
if ($targetUid === 0) {
|
||||||
|
echo " !! target $newSlug not found - #$uid skipped\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$stmt = $pdo->prepare('SELECT COUNT(*) FROM sys_redirect WHERE deleted = 0 AND source_path = ?');
|
||||||
|
$stmt->execute([$oldSlug]);
|
||||||
|
$hasRedirect = (int)$stmt->fetchColumn();
|
||||||
|
echo " ~ DELETE #$uid \"{$stub['title']}\" ($oldSlug) -> 301 to $newSlug (#$targetUid)" . ($hasRedirect ? ' [redirect exists, kept]' : '') . "\n";
|
||||||
|
if (!$apply) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$pdo->prepare('UPDATE pages SET deleted = 1, tstamp = UNIX_TIMESTAMP() WHERE uid = ?')->execute([$uid]);
|
||||||
|
if (!$hasRedirect) {
|
||||||
|
$pdo->prepare(
|
||||||
|
"INSERT INTO sys_redirect (pid, createdon, updatedon, source_host, source_path, target, target_statuscode)
|
||||||
|
VALUES (0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '*', ?, ?, 301)"
|
||||||
|
)->execute([$oldSlug, 't3://page?uid=' . $targetUid]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo $apply ? "Done. Flush the cache (redirects are cached).\n" : "DRY RUN - add --apply to write.\n";
|
||||||
Reference in new issue
Block a user