This commit is contained in:
@@ -55,6 +55,7 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter. Kernbereiche sind l
|
||||
- Neue Kategorien bleiben dort sichtbar, bis sie von einem Berechtigten bestätigt oder mit einer bestehenden Kategorie zusammengeführt werden.
|
||||
- Im Bereich `Kategorien` gibt es zusätzlich eine Suche über bestehende Kategorien, damit sie gezielt gefunden und zusammengeführt werden können.
|
||||
- Beim Zusammenführen wird die nicht zu behaltende Kategorie anschließend vollständig entfernt und die Ansicht danach frisch neu geladen.
|
||||
- Zusammengeführte Kategorien werden zusätzlich intern als Redirect gesperrt, damit Standard-Seed oder spätere Eingaben sie nicht erneut auswählbar machen.
|
||||
- Beim Zusammenführen kann explizit festgelegt werden, welche der beiden Kategorien erhalten bleibt.
|
||||
- Community-Level können zusätzlich die Rechte für Kategorien sowie für die Freigabe von Orten und Veranstaltungen tragen.
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ Papa-Kind-Treff is a PHP-based platform for fathers. Core areas are local events
|
||||
- New categories remain visible there until an authorized user confirms them or merges them into an existing category.
|
||||
- The `Categories` area also includes a search across existing categories so they can be found and merged directly.
|
||||
- During merging, the category that should not be kept is removed completely and the view is reloaded fresh afterwards.
|
||||
- Merged categories are additionally blocked internally through redirects so default seeding or later inputs cannot make them selectable again.
|
||||
- During merging, it is now possible to explicitly choose which of the two categories should be kept.
|
||||
- Community levels can now additionally carry the rights for category handling as well as place and event approvals.
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter mit Fokus auf:
|
||||
- Neue Kategorien bleiben im Bereich `Kategorien` sichtbar, bis sie von einem Berechtigten bestätigt oder zusammengeführt werden
|
||||
- Im Bereich `Kategorien` gibt es zusätzlich eine Suche über bestehende Kategorien, damit sie gezielt gefunden und zusammengeführt werden können
|
||||
- Beim Zusammenführen wird die nicht zu behaltende Kategorie anschließend vollständig entfernt und die Ansicht danach frisch neu geladen
|
||||
- Zusammengeführte Kategorien werden zusätzlich intern als Redirect gesperrt, damit Standard-Seed oder spätere Eingaben sie nicht erneut auswählbar machen
|
||||
- Beim Zusammenführen von Kategorien kann jetzt explizit festgelegt werden, welche der beiden Kategorien erhalten bleibt
|
||||
- Community-Level können jetzt zusätzlich die Rechte für Kategorien sowie für die Freigabe von Orten und Veranstaltungen tragen
|
||||
- neue interne Grundstruktur: `listing_places`, `listings`, `listing_occurrences`, `listing_prices`, `listing_benefits`
|
||||
|
||||
@@ -24,6 +24,13 @@ final class ListingCatalog
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci',
|
||||
'CREATE TABLE IF NOT EXISTS listing_category_redirects (
|
||||
old_slug VARCHAR(120) NOT NULL PRIMARY KEY,
|
||||
old_title VARCHAR(160) NOT NULL,
|
||||
target_slug VARCHAR(120) NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_listing_category_redirects_target (target_slug)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci',
|
||||
'CREATE TABLE IF NOT EXISTS listing_places (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
created_by BIGINT UNSIGNED NULL,
|
||||
@@ -186,7 +193,15 @@ final class ListingCatalog
|
||||
VALUES (:slug, :title, :groupName, :sortOrder)
|
||||
ON DUPLICATE KEY UPDATE title = VALUES(title), category_group = VALUES(category_group), sort_order = VALUES(sort_order), updated_at = CURRENT_TIMESTAMP'
|
||||
);
|
||||
$redirectedSlugs = [];
|
||||
$redirectStmt = $this->pdo->query('SELECT old_slug FROM listing_category_redirects');
|
||||
foreach (($redirectStmt ? $redirectStmt->fetchAll(\PDO::FETCH_COLUMN) : []) as $redirectedSlug) {
|
||||
$redirectedSlugs[(string)$redirectedSlug] = true;
|
||||
}
|
||||
foreach ($this->defaultCategories() as $index => $category) {
|
||||
if (isset($redirectedSlugs[(string)$category['slug']])) {
|
||||
continue;
|
||||
}
|
||||
$seed->execute([
|
||||
'slug' => $category['slug'],
|
||||
'title' => $category['title'],
|
||||
@@ -247,6 +262,15 @@ final class ListingCatalog
|
||||
}
|
||||
|
||||
$slug = $this->slugify($input);
|
||||
$redirect = $this->findCategoryRedirect($slug, $input);
|
||||
if ($redirect !== null) {
|
||||
$resolved = $this->findCategoryBySlug($redirect['target_slug']);
|
||||
if ($resolved !== null) {
|
||||
$resolved['is_new'] = false;
|
||||
return $resolved;
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare(
|
||||
'SELECT id, slug, title, category_group, sort_order
|
||||
FROM listing_categories
|
||||
@@ -292,6 +316,8 @@ final class ListingCatalog
|
||||
(SELECT COUNT(*) FROM listing_category_map m WHERE m.category_id = c.id) AS listing_count,
|
||||
(SELECT COUNT(*) FROM listing_places p WHERE p.place_kind = c.slug) AS place_count
|
||||
FROM listing_categories c
|
||||
LEFT JOIN listing_category_redirects r ON r.old_slug = c.slug
|
||||
WHERE r.old_slug IS NULL
|
||||
ORDER BY
|
||||
CASE WHEN c.sort_order >= 900 THEN 0 ELSE 1 END,
|
||||
c.sort_order ASC,
|
||||
@@ -343,7 +369,9 @@ final class ListingCatalog
|
||||
(SELECT COUNT(*) FROM listing_category_map m WHERE m.category_id = c.id) AS listing_count,
|
||||
(SELECT COUNT(*) FROM listing_places p WHERE p.place_kind = c.slug) AS place_count
|
||||
FROM listing_categories c
|
||||
WHERE ' . implode(' AND ', $conditions) . '
|
||||
LEFT JOIN listing_category_redirects r ON r.old_slug = c.slug
|
||||
WHERE r.old_slug IS NULL
|
||||
AND ' . implode(' AND ', $conditions) . '
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN LOWER(c.title) = :exactTitle THEN 0
|
||||
@@ -400,6 +428,17 @@ final class ListingCatalog
|
||||
|
||||
$this->pdo->beginTransaction();
|
||||
try {
|
||||
$redirectUpsert = $this->pdo->prepare(
|
||||
'INSERT INTO listing_category_redirects (old_slug, old_title, target_slug)
|
||||
VALUES (:oldSlug, :oldTitle, :targetSlug)
|
||||
ON DUPLICATE KEY UPDATE old_title = VALUES(old_title), target_slug = VALUES(target_slug)'
|
||||
);
|
||||
$redirectUpsert->execute([
|
||||
'oldSlug' => $sourceSlug,
|
||||
'oldTitle' => $sourceTitle,
|
||||
'targetSlug' => $targetSlug,
|
||||
]);
|
||||
|
||||
$mapRows = $this->pdo->prepare('SELECT listing_id FROM listing_category_map WHERE category_id = :categoryId');
|
||||
$mapRows->execute(['categoryId' => $sourceId]);
|
||||
$listingIds = $mapRows->fetchAll(\PDO::FETCH_COLUMN) ?: [];
|
||||
@@ -484,6 +523,12 @@ final class ListingCatalog
|
||||
return null;
|
||||
}
|
||||
|
||||
$slug = $this->slugify($input);
|
||||
$redirect = $this->findCategoryRedirect($slug, $input);
|
||||
if ($redirect !== null) {
|
||||
return $redirect['target_slug'];
|
||||
}
|
||||
|
||||
$stmt = $this->pdo->prepare(
|
||||
'SELECT slug
|
||||
FROM listing_categories
|
||||
@@ -492,13 +537,42 @@ final class ListingCatalog
|
||||
LIMIT 1'
|
||||
);
|
||||
$stmt->execute([
|
||||
'slug' => $input,
|
||||
'slug' => $slug,
|
||||
'title' => $input,
|
||||
]);
|
||||
$slug = $stmt->fetchColumn();
|
||||
return $slug !== false ? (string)$slug : null;
|
||||
}
|
||||
|
||||
private function findCategoryRedirect(string $slug, string $title): ?array
|
||||
{
|
||||
$stmt = $this->pdo->prepare(
|
||||
'SELECT old_slug, old_title, target_slug
|
||||
FROM listing_category_redirects
|
||||
WHERE old_slug = :slug OR LOWER(old_title) = LOWER(:title)
|
||||
LIMIT 1'
|
||||
);
|
||||
$stmt->execute([
|
||||
'slug' => $slug,
|
||||
'title' => $title,
|
||||
]);
|
||||
$row = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||
return $row ?: null;
|
||||
}
|
||||
|
||||
private function findCategoryBySlug(string $slug): ?array
|
||||
{
|
||||
$stmt = $this->pdo->prepare(
|
||||
'SELECT id, slug, title, category_group, sort_order
|
||||
FROM listing_categories
|
||||
WHERE slug = :slug
|
||||
LIMIT 1'
|
||||
);
|
||||
$stmt->execute(['slug' => $slug]);
|
||||
$row = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||
return $row ?: null;
|
||||
}
|
||||
|
||||
public function listPublishedDirectoryEntries(): array
|
||||
{
|
||||
$this->ensureSchema();
|
||||
|
||||
Reference in New Issue
Block a user