Skip to content

Commit 53e5d32

Browse files
committed
1.0.0-beta.13
1 parent b60b2fa commit 53e5d32

12 files changed

Lines changed: 515 additions & 275 deletions

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@
22

33
Dieses Changelog wird ab Version `1.0.0` neu geführt.
44

5+
## 1.0.0-beta.13 (07. Mai 2026)
6+
7+
**Artikel / LocalBusiness:**
8+
- Multi-Select für LocalBusiness-Standorte in `article_jsonld` wiederhergestellt und AJAX-Speicherung über separaten Speichern-Button ergänzt
9+
- Gespeicherte Standort-Auswahl wird nach Reload korrekt wieder im Select vorausgewählt
10+
- Hauptstandort wird als effektiver Fallback im Select ebenfalls vorausgewählt, wenn keine eigene Auswahl gespeichert ist
11+
- JSON-LD Vorschau und Frontend-Ausgabe erzeugen jetzt für alle gewählten Standorte eigene `LocalBusiness`-Einträge
12+
- Statusliste zeigt pro zusätzlichem Nicht-Hauptstandort einen eigenen Place-Marker (`1-x`)
13+
14+
**Bereinigung:**
15+
- Unbenutzten Parameter in `generateArticleJsonLd()` entfernt
16+
- Standort-Auswahl-Handling für Einzelwert- und Array-Speicherung vereinheitlicht
17+
18+
**UI / Artikelübersicht:**
19+
- Zeilenhintergrund in der Artikelübersicht über die volle Breite bis hinter die Status-Marker vereinheitlicht
20+
- Hover-Zustand für Artikelzeilen ergänzt, damit inaktive Zeilen klarer erfassbar sind
21+
522
## 1.0.0-beta.12 (07. Mai 2026)
623

724
**Bugfixes & Wartung:**

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Nach der Installation solltest du zuerst unter `Allgemeine Angaben` die Basisdat
2222
- `WebSite Schema`
2323
- optional `LocalBusiness`
2424

25-
Wenn du ein lokales Unternehmen mit realem Standort hast, ist es sinnvoll, mindestens ein `LocalBusiness` anzulegen. Wenn es mehrere Standorte gibt, können auch mehrere Filialen gepflegt werden.
25+
Wenn du ein lokales Unternehmen mit realem Standort hast, ist es sinnvoll, mindestens ein `LocalBusiness` anzulegen. Wenn es mehrere Standorte gibt, können auch mehrere Standorte gepflegt werden.
2626

2727
Diese Angaben sind die Grundlage für die spätere Ausgabe auf den Artikeln.
2828

@@ -33,7 +33,7 @@ Anschließend kannst du pro Artikel festlegen, wie mit JSON-LD umgegangen werden
3333
Dort sind vor allem diese Möglichkeiten wichtig:
3434

3535
- Standard-Ausgabe für den Artikel verwenden
36-
- eine bestimmte `LocalBusiness`-Filiale zuordnen
36+
- einen bestimmten `LocalBusiness`-Standort zuordnen
3737
- eigenes Custom-JSON für einen Artikel hinterlegen
3838
- JSON-LD für einen Artikel bewusst deaktivieren
3939

@@ -99,15 +99,15 @@ Das ist optional und nicht nötig, um die normale JSON-LD-Ausgabe für Website u
9999
- Sprachauswahl mit persistenter Auswahl innerhalb des AddOns
100100
- Custom JSON pro Artikel und Sprache
101101
- JSON-LD pro Artikel deaktivierbar (pro Sprache)
102-
- Zuordnung einer LocalBusiness-Filiale pro Artikel und Sprache
102+
- Zuordnung eines LocalBusiness-Standorts pro Artikel und Sprache
103103
- Dynamische URL-Profile mit Schema-Mapping (wenn URL-Addon aktiv ist)
104104
- Debug-Modus mit JSON-LD Overlay im Frontend
105105

106106
### Allgemeine Angaben
107107

108108
- Organization Schema (sprachabhängig)
109109
- WebSite Schema (sprachabhängig)
110-
- LocalBusiness Filialverwaltung (sprachabhängig)
110+
- LocalBusiness Standortverwaltung (sprachabhängig)
111111

112112
### Frontend
113113

@@ -122,7 +122,7 @@ Das AddOn ist auf Mehrsprachigkeit ausgelegt:
122122

123123
- Sprachbezogene Konfigurationen über `LanguageConfig`
124124
- Artikel-Zuordnungen (Branch, Custom JSON, Disable-Flag) pro Sprache
125-
- LocalBusiness-Filialen pro Sprache (`clang_id`)
125+
- LocalBusiness-Standorte pro Sprache (`clang_id`)
126126
- Sprachwahl wird im AddOn gespeichert und beim Seitenwechsel beibehalten
127127

128128
## Multi-Domain-Support
@@ -150,7 +150,7 @@ Das AddOn unterstützt vollständig YRewrite Multi-Domain-Installationen:
150150
### Strikte Domain-Trennung
151151
- **Keine automatische Migration** zwischen Domains
152152
- **Separate Datenbankeinträge** für jede Domain
153-
- **Manuelle Zuordnung**: LocalBusiness-Filialen können manuell zugeordnet werden
153+
- **Manuelle Zuordnung**: LocalBusiness-Standorte können manuell zugeordnet werden
154154
- **Eigenständige Konfiguration**: Jede Domain startet mit leeren Einstellungen
155155

156156
## Sicherheit

assets/css/jsonld_manager.css

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,23 @@
377377
cursor: pointer;
378378
}
379379

380+
.article-table .article-row td {
381+
background-color: #2a3642;
382+
transition: background-color 0.18s ease, color 0.18s ease;
383+
}
384+
385+
.article-table .article-row td:first-child {
386+
border-radius: 3px 0 0 3px;
387+
}
388+
389+
.article-table .article-row td:last-child {
390+
border-radius: 0 3px 3px 0;
391+
}
392+
393+
.article-table .article-row:hover td {
394+
background-color: #324150;
395+
}
396+
380397
.article-table .article-row.active,
381398
.article-table .article-row.active:hover {
382399
background-color: #256ea8;
@@ -394,6 +411,11 @@
394411
background: transparent !important;
395412
}
396413

414+
.article-table .article-row:hover .article-name,
415+
.article-table .article-row:hover .article-path {
416+
background: transparent !important;
417+
}
418+
397419
.article-table .article-row.active .article-icons,
398420
.article-table .article-row.active .article-status,
399421
.article-table .article-row.active:hover .article-icons,
@@ -450,8 +472,8 @@
450472

451473
.article-table .article-row[class*="article-level-"] .article-name,
452474
.article-table .article-row[class*="article-level-"] .article-path {
453-
background: rgba(255, 255, 255, 0.03);
454-
border-radius: 2px;
475+
background: transparent;
476+
border-radius: 0;
455477
}
456478

457479
.article-table .article-row.article-level-1 .article-name,

boot.php

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,6 @@
1414
require_once __DIR__ . '/lib/LanguageConfig.php';
1515
require_once __DIR__ . '/lib/DynamicJsonLd.php';
1616

17-
// Backend CSS und JS einbinden
18-
if (rex::isBackend() && rex_be_controller::getCurrentPagePart(1) == 'jsonld_manager') {
19-
rex_view::addCssFile($this->getAssetsUrl('css/jsonld_manager.css'));
20-
rex_view::addJsFile($this->getAssetsUrl('js/jsonld_manager.js'));
21-
}
22-
2317
// Nur im Frontend
2418
if (!rex::isBackend() && rex_addon::get('jsonld_manager')->isAvailable()) {
2519
// Extension Point für automatische JSON-LD Ausgabe
@@ -84,10 +78,11 @@
8478

8579
// Bedingte Menüanzeige für Dynamische URLs
8680
if (rex::isBackend()) {
87-
// CSS-Datei im Backend laden
88-
rex_view::addCssFile(rex_url::addonAssets('jsonld_manager', 'jsonld_manager.css'));
89-
// JS-Datei im Backend laden (u.a. für Select Live-Suche)
90-
rex_view::addJsFile(rex_url::addonAssets('jsonld_manager', 'js/jsonld_manager.js'));
81+
// CSS/JS nur auf Addon-Seiten im Backend laden
82+
if (rex_be_controller::getCurrentPagePart(1) === 'jsonld_manager') {
83+
rex_view::addCssFile(rex_url::addonAssets('jsonld_manager', 'css/jsonld_manager.css'));
84+
rex_view::addJsFile(rex_url::addonAssets('jsonld_manager', 'js/jsonld_manager.js'));
85+
}
9186

9287
$hideDynamicUrlsSubpage = static function (): void {
9388
$filter = static function ($page) {

install.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
5757
');
5858

59-
// Tabelle: rex_jsonld_localbusiness_branches - Filialenverwaltung
59+
// Tabelle: rex_jsonld_localbusiness_branches - Standorteverwaltung
6060
$sql->setQuery('
6161
CREATE TABLE IF NOT EXISTS `'.rex::getTable('jsonld_localbusiness_branches').'` (
6262
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,

lib/Frontend/Renderer.php

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,22 +54,22 @@ public static function render($schemaType = null, $additionalData = [])
5454
}
5555

5656
// Branch-ID für diesen Artikel laden
57-
$useBranchId = self::resolveBranchIdForArticle($article->getId(), (int) $article->getClangId());
58-
$cacheKey = md5($article->getId() . '_' . $article->getClangId() . '_' . ($schemaType ?: 'auto') . '_' . (string) ($useBranchId ?? 0) . '_' . serialize($additionalData));
57+
$useBranchIds = self::resolveBranchIdsForArticle($article->getId(), (int) $article->getClangId());
58+
$cacheKey = md5($article->getId() . '_' . $article->getClangId() . '_' . ($schemaType ?: 'auto') . '_' . serialize($useBranchIds) . '_' . serialize($additionalData));
5959

6060
// Cache-Check
6161
if (isset(self::$cache[$cacheKey])) {
6262
if ($isDebugMode) {
6363
self::addDebugInfo('cache_hit', 'Cache-Treffer', [
6464
'cache_key' => $cacheKey,
65-
'branch_id' => $useBranchId
65+
'branch_ids' => $useBranchIds
6666
]);
6767
}
6868
return self::$cache[$cacheKey];
6969
}
7070

7171
// Einheitliche Backend/Frontend-Logik: zentralen Generator verwenden
72-
$jsonLdItems = \FriendsOfRedaxo\JsonLdManager\JsonLdGenerator::generateForArticle($article->getId(), $useBranchId, $isDebugMode, (int) $article->getClangId());
72+
$jsonLdItems = \FriendsOfRedaxo\JsonLdManager\JsonLdGenerator::generateForArticle($article->getId(), $useBranchIds, $isDebugMode, (int) $article->getClangId());
7373

7474
if (empty($jsonLdItems)) {
7575
return '';
@@ -101,13 +101,13 @@ public static function render($schemaType = null, $additionalData = [])
101101
'items_count' => count($jsonLdItems ?? []),
102102
'output_length' => strlen($output),
103103
'cached' => self::getSetting($addon, 'cache_enabled', true),
104-
'branch_id' => $useBranchId
104+
'branch_ids' => $useBranchIds
105105
]);
106106

107107
self::outputConsoleDebug('JSON-LD erfolgreich generiert', [
108108
'JSON-LD Items' => count($jsonLdItems ?? []),
109109
'Output-Länge' => strlen($output) . ' Zeichen',
110-
'Branch-ID' => $useBranchId,
110+
'Branch-IDs' => implode(', ', $useBranchIds),
111111
'Gecacht' => self::getSetting($addon, 'cache_enabled', true) ? 'Ja' : 'Nein'
112112
]);
113113

@@ -231,7 +231,14 @@ private static function getActiveLocalBusinessBranch($articleId, $clangId)
231231
}
232232

233233
$config = json_decode($sql->getValue('config'), true) ?: [];
234-
$branchId = $config['localbusiness_branch_id'] ?? 0;
234+
$branchIds = $config['localbusiness_branch_ids'] ?? [];
235+
if (!is_array($branchIds)) {
236+
$branchIds = $branchIds ? [(int) $branchIds] : [];
237+
}
238+
if (empty($branchIds) && !empty($config['localbusiness_branch_id'])) {
239+
$branchIds = [(int) $config['localbusiness_branch_id']];
240+
}
241+
$branchId = (int) ($branchIds[0] ?? 0);
235242

236243
if ($branchId <= 0) {
237244
return null; // Keine LocalBusiness Zuordnung
@@ -668,30 +675,36 @@ private static function getSetting(\rex_addon $addon, $key, $default = null)
668675
* @param int $articleId
669676
* @return int|null
670677
*/
671-
private static function resolveBranchIdForArticle($articleId, $clangId = 1)
678+
private static function resolveBranchIdsForArticle($articleId, $clangId = 1)
672679
{
673680
$localizedKey = 'article_branch_' . $articleId . '_clang_' . (int) $clangId;
674-
$selectedBranchId = (int) \rex_config::get('jsonld_manager', $localizedKey, 0);
675-
if ($selectedBranchId > 0) {
676-
return $selectedBranchId;
681+
$storedBranchConfig = \rex_config::get('jsonld_manager', $localizedKey, 0);
682+
if (is_array($storedBranchConfig)) {
683+
$selectedBranchIds = array_values(array_unique(array_filter(array_map('intval', $storedBranchConfig))));
684+
} else {
685+
$selectedBranchId = (int) $storedBranchConfig;
686+
$selectedBranchIds = $selectedBranchId > 0 ? [$selectedBranchId] : [];
687+
}
688+
if (!empty($selectedBranchIds)) {
689+
return $selectedBranchIds;
677690
}
678691

679692
try {
680693
$sql = \rex_sql::factory();
681694
$sql->setQuery('SELECT id FROM ' . \rex::getTable('jsonld_localbusiness_branches') . ' WHERE is_main_branch = 1 AND clang_id = ? LIMIT 1', [(int) $clangId]);
682695
if ($sql->getRows() > 0) {
683-
return (int) $sql->getValue('id');
696+
return [(int) $sql->getValue('id')];
684697
}
685698

686699
$sql->setQuery('SELECT id FROM ' . \rex::getTable('jsonld_localbusiness_branches') . ' WHERE clang_id = ? ORDER BY sort_order ASC, id ASC LIMIT 1', [(int) $clangId]);
687700
if ($sql->getRows() > 0) {
688-
return (int) $sql->getValue('id');
701+
return [(int) $sql->getValue('id')];
689702
}
690703
} catch (\Exception $e) {
691704
// Fallback: Keine Branch verwenden
692705
}
693706

694-
return null;
707+
return [];
695708
}
696709

697710
/**

0 commit comments

Comments
 (0)