dbxapp 4.1.3
CMS, Shop, Workflows und modulare Geschäftsanwendungen
Loading...
Searching...
No Matches
dbxContent_permalink.class.php
Go to the documentation of this file.
1<?php
2namespace dbx\dbxContent;
3
5
6 public static function segment($text, $fallback = 'seite') {
7 $text = trim((string)$text);
8 $text = str_replace(array('\\', '/'), '-', $text);
9 $text = str_replace(
10 array('Ä', 'Ö', 'Ü', 'ä', 'ö', 'ü', 'ß'),
11 array('Ae', 'Oe', 'Ue', 'ae', 'oe', 'ue', 'ss'),
12 $text
13 );
14 if (function_exists('iconv')) {
15 $ascii = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $text);
16 if (is_string($ascii) && $ascii !== '') {
17 $text = $ascii;
18 }
19 }
20 $text = strtolower($text);
21 $text = preg_replace('/\s+/', '-', $text);
22 $text = preg_replace('/[^a-z0-9-]+/', '-', $text);
23 $text = preg_replace('/-+/', '-', $text);
24 $text = trim($text, '-');
25
26 if (strlen($text) > 254) {
27 $text = rtrim(substr($text, 0, 254), '-');
28 }
29
30 return $text !== '' ? $text : $fallback;
31 }
32
33 public static function slug($text) {
34 return self::segment($text, 'seite-' . date('YmdHis'));
35 }
36
37 public static function normalize($permalink) {
38 return self::segment($permalink, '');
39 }
40
45 public static function canonicalFromLegacy($permalink): string {
46 $legacy = strtolower(trim(str_replace('\\', '/', (string)$permalink), '/'));
47 if ($legacy === '') {
48 return '';
49 }
50
51 $known = array(
52 'home/tutorial' => 'tutorials-dbxapp',
53 'home/tutorial/login-profil-passwort' => 'tutorial-login-profil-passwort',
54 'home/tutorial/admin-dashboard' => 'tutorial-admin-dashboard',
55 'home/tutorial/menue-benutzen' => 'tutorial-menue-benutzen',
56 'home/tutorial/frontpage-direkt-cms' => 'tutorial-frontpage-direkt-cms',
57 'home/tutorial/cms-content-tree' => 'tutorial-cms-content-tree',
58 'home/tutorial/cms-felder-editor' => 'tutorial-cms-felder-editor',
59 'home/tutorial/cms-medienverwendung' => 'tutorial-cms-medienverwendung',
60 'home/tutorial/medienbrowser' => 'tutorial-medienbrowser',
61 'home/tutorial/medienwartung-seo' => 'tutorial-medienwartung-seo',
62 'home/tutorial/dbxki-ki-cms' => 'tutorial-dbxki-ki-cms',
63 'home/tutorial/shop-admin' => 'tutorial-shop-admin',
64 'home/tutorial/shop-frontend' => 'tutorial-shop-frontend',
65 'home/tutorial/workflow-erstellen' => 'tutorial-workflow-erstellen',
66 'home/tutorial/workflow-nutzen' => 'tutorial-workflow-nutzen',
67 'home/tutorial/shop-dashboard' => 'tutorial-shop-dashboard',
68 'home/tutorial/cms-editor' => 'tutorial-cms-editor',
69 'shop/help-channel-groups' => 'help-shop-channel-gruppen',
70 'shop/help-channels' => 'help-shop-channels',
71 'shop/help-channel-shop' => 'help-shop-channel-shop',
72 'shop/help-channel-amazon' => 'help-shop-channel-amazon',
73 'shop/help-channel-ebay' => 'help-shop-channel-ebay',
74 'shop/help-channel-kleinanzeigen' => 'help-shop-channel-kleinanzeigen',
75 'shop/help-channel-mobile' => 'help-shop-channel-mobile',
76 'shop/help-shipping-groups' => 'help-shop-versandgruppen',
77 'shop/help-groups' => 'help-shop-artikelgruppen',
78 'shop/help-settings' => 'help-shop-einstellungen',
79 'shop/help-orders' => 'help-shop-bestellungen',
80 'shop/help-products' => 'help-shop-produkte',
81 'shop/help-product-channel-mapping' => 'help-shop-produkt-channel-mapping',
82 'shop/help-product-attributes' => 'help-shop-artikelattribute',
83 'shop/help-media' => 'help-shop-medien',
84 'shop/rechtstexte' => 'shop-rechtstexte',
85 'shop/widerruf' => 'shop-widerruf',
86 'outside/shop-media-usage' => 'shop-medienverwendung',
87 'outside/shop-medienverwendung' => 'shop-medienverwendung',
88 'help/admin-dashboard' => 'help-dashboard-admin',
89 );
90
91 // Eine fruehere Permalink-Migration ersetzte bei verschachtelten
92 // Tutorial-Links zuerst nur den Praefix "home/tutorial". Dadurch
93 // entstanden Zwischenwerte wie
94 // "tutorials-dbxapp/cms-medienverwendung". Diese Werte werden als
95 // kompatibler Alias auf denselben kanonischen Tutorial-Permalink
96 // aufgeloest. Neu gespeichert werden weiterhin ausschliesslich die
97 // flachen Werte aus $known.
98 if (strpos($legacy, 'tutorials-dbxapp/') === 0) {
99 $tutorialLegacy = 'home/tutorial/' . substr($legacy, strlen('tutorials-dbxapp/'));
100 if (isset($known[$tutorialLegacy])) {
101 return $known[$tutorialLegacy];
102 }
103 }
104
105 if (isset($known[$legacy])) {
106 return $known[$legacy];
107 }
108
109 if (strpos($legacy, 'outside/help/') === 0 || strpos($legacy, 'help/') === 0) {
110 $topicSlug = substr($legacy, strrpos($legacy, '/') + 1);
111 try {
112 if (function_exists('dbx')) {
113 $help = dbx()->get_include_obj('dbxAdminHelp', 'dbxAdmin');
114 if (is_object($help) && method_exists($help, 'topics')) {
115 foreach ($help->topics() as $topic => $meta) {
116 if (str_replace('_', '-', strtolower((string)$topic)) === $topicSlug) {
117 $canonical = trim((string)($meta['permalink'] ?? ''));
118 if (self::isValid($canonical)) {
119 return $canonical;
120 }
121 }
122 }
123 }
124 }
125 } catch (\Throwable $e) {
126 // Der generische flache Alias bleibt als sicherer Fallback.
127 }
128 }
129
130 return self::normalize($legacy);
131 }
132
133 public static function isValid($permalink): bool {
134 $permalink = (string)$permalink;
135 if ($permalink === '' || strlen($permalink) > 254) {
136 return false;
137 }
138
139 try {
140 $validator = function_exists('dbx') ? dbx()->get_system_obj('dbxValidator') : new \dbxValidator();
141 return is_object($validator) && $validator->validate($permalink, 'permalink|min=1|max=254');
142 } catch (\Throwable $e) {
143 return (bool)preg_match('/^[a-z0-9]+(?:-[a-z0-9]+)*$/', $permalink);
144 }
145 }
146
147 public static function exists($db, string $content_dd, string $permalink, int $exclude_id = 0): bool {
148 if (!is_object($db) || $content_dd === '' || !self::isValid($permalink)) {
149 return false;
150 }
151
152 $escaped = str_replace("'", "''", $permalink);
153 $rows = $db->select($content_dd, "permalink = '" . $escaped . "'", 'id', 'id', 'ASC', '', 0, 0, 0);
154 if (!is_array($rows)) {
155 return false;
156 }
157 foreach ($rows as $row) {
158 if ((int)($row['id'] ?? 0) !== $exclude_id) {
159 return true;
160 }
161 }
162 return false;
163 }
164
165 public static function unique($db, string $content_dd, string $permalink, int $exclude_id = 0): string {
166 $base = self::normalize($permalink);
167 if ($base === '') {
168 $base = 'seite';
169 }
170
171 $candidate = $base;
172 $number = 2;
173 while (self::exists($db, $content_dd, $candidate, $exclude_id)) {
174 $suffix = '-' . $number;
175 $candidate = rtrim(substr($base, 0, 254 - strlen($suffix)), '-') . $suffix;
176 $number++;
177 }
178 return $candidate;
179 }
180
181 public static function build($db, $folder_dd, $folder_id, $title, $exclude_id = 0) {
182 // Der Ordner ist bewusst kein Bestandteil mehr. Dadurch bleibt der
183 // Permalink beim Verschieben einer Seite unveraendert.
184 $content_dd = self::content_dd_from_folder_dd((string)$folder_dd);
185 return self::unique($db, $content_dd, self::slug($title), (int)$exclude_id);
186 }
187
188 private static function content_dd_from_folder_dd(string $folder_dd): string {
189 if (strpos($folder_dd, 'content_folder_') === 0) {
190 return 'content_' . substr($folder_dd, strlen('content_folder_'));
191 }
192 if (substr($folder_dd, -7) === '_folder') {
193 return substr($folder_dd, 0, -7);
194 }
195 return $folder_dd;
196 }
197}
198
199?>
dbx()
Liefert die zentrale dbXapp-API als Singleton.
Definition dbxApi.php:2805
if(!defined( 'IMG_WEBP')) define( 'IMG_WEBP'
DBX schema administration.