{"id":15647027,"url":"https://github.com/tbaddade/redaxo_url","last_synced_at":"2025-03-16T09:08:23.676Z","repository":{"id":37734225,"uuid":"51355175","full_name":"tbaddade/redaxo_url","owner":"tbaddade","description":"REDAXO 5 AddOn zur URL-Generierung für eigene AddOns (ehemals Url Control, ehemals Frau Schultze)","archived":false,"fork":false,"pushed_at":"2024-09-09T14:31:24.000Z","size":445,"stargazers_count":44,"open_issues_count":14,"forks_count":22,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-03-01T00:48:23.795Z","etag":null,"topics":["addoff","redaxo","redaxo-addon","rewrite"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tbaddade.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-02-09T08:37:16.000Z","updated_at":"2025-02-09T14:30:41.000Z","dependencies_parsed_at":"2023-12-18T15:43:12.342Z","dependency_job_id":"2bc5e3a4-bb59-4147-8324-c90d380598c2","html_url":"https://github.com/tbaddade/redaxo_url","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbaddade%2Fredaxo_url","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbaddade%2Fredaxo_url/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbaddade%2Fredaxo_url/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tbaddade%2Fredaxo_url/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tbaddade","download_url":"https://codeload.github.com/tbaddade/redaxo_url/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243847062,"owners_count":20357317,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["addoff","redaxo","redaxo-addon","rewrite"],"created_at":"2024-10-03T12:16:28.333Z","updated_at":"2025-03-16T09:08:23.653Z","avatar_url":"https://github.com/tbaddade.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Url AddOn für REDAXO 5\n\n## Beschreibung\n\nREDAXO 5 AddOn zur URL-Generierung für Daten aus den Datenbanktabellen (ehemals Url Control, ehemals Frau Schultze)\n\n## Features\n\n* Generieren von suchmaschinenfreundlichen URLs anhand von Datenbanktabellen und eines REDAXO-Artikels, z.B: `www.example.org/artikel/datensatz/` anstelle von `www.example.org/artikel/?id=1` \n* Automatische Oberkategorien anhand von Relationen `www.example.org/kategorie/datensatz/` möglich\n* Mit und ohne YForm-Tabellen nutzbar\n* Zusätzliche Methoden für `\u003ctitle /\u003e`-Felder, SEO- und OpenGraph-Metadaten wie `description` und `og:image`\n* Integration in die `sitemap.xml` von YRewrite\n* Multi-Domain fähig\n* URLs werden vom Addon `search_it` erkannt und Inhalte indexiert\n\n## Installation\n\n* Via Install AddOn im Backend herunterladen\n* AddOn installieren und aktivieren\n\n\u003e Hinweis: Benötigt [yrewrite](https://github.com/yakamara/redaxo_yrewrite). \n\n## Beispiel: Filme\n\nNormalerweise wird ein Film über eine Url wie `/filme/?movie_id=1` geholt.\n\nMit dem AddOn ist es möglich Urls wie `/filme/the-big-lebowski/` zu erzeugen.\n\nDer REDAXO Artikel `/the-big-lebowski/` selbst existiert dabei nicht. Es wird alles im REDAXO Artikel `/filme/` abgehandelt.\n**The Big Lebowski** ist dabei der Titel eines Filmes, welcher in einer eigenen Datenbanktabelle hinterlegt wurde. \n\n\n### Url holen \nUm die Url eines einzelnen Filmes auszugeben verwendet man:\n\n```php\necho rex_getUrl('', '', ['movie-id' =\u003e $movieId]);\n```\n\n| Variable         | Beschreibung                 |\n| ---------------- | ---------------------------- |\n| `movie-id` | ist der im Profil hinterlegte Namensraum |\n| `$movieId`    | Datensatz-Id des Filmes |\n\n\n### Id holen \nNach dem der Film mit der eigenen Url aufgerufen wurde (Darstellung der Detailseite), muss jetzt die dazugehörige Datensatz-Id ermittelt werden. Erst dann können die eigentlichen Daten aus der Tabelle abgerufen und ausgegeben werden.\n\n```php\n// versuche die Url aufzulösen\n$manager = Url\\Url::resolveCurrent();\nif($manager) {\n    $movieId = $manager-\u003egetDatasetId();\n}\n```\n\n### Beispiel Code\n\n```php\n\u003c?php\nuse Url\\Url;\n\n$manager = Url::resolveCurrent();\n\nif ($manager) {\n    $movie = rex_yform_manager_table::get('rex_movie')-\u003equery()-\u003efindId($manager-\u003egetDatasetId());\n    // oder wenn ModelClass genutzt wird\n    $movie = Movie::get($manager-\u003egetDatasetId());\n    if ($movie) {\n        dump($movie);\n    }\n} else {\n    $movies = rex_yform_manager_table::get('rex_movie')-\u003equery()-\u003efind();\n    // oder wenn ModelClass genutzt wird\n    $movies = Movie::getAll();\n    if (count($movies)) {\n        foreach ($movies as $movie) {\n            echo '\u003ca href=\"' . rex_getUrl('', '', ['movie-id' =\u003e $movie-\u003egetId()]) . '\"\u003e' . $movie-\u003egetValue('title') . '\u003c/a\u003e';\n        }\n    }\n}\n```\n\n### Zusätzliche Pfade aus Relationen bilden\n\nMöchte man den Filmen Genres zuordnen, passiert dies meist über eine Relation zu diesen Kategorien.\nDie Urls dazu könnten dann so aussehen: `/filme/komoedie/the-big-lebowski/`\n \n\n### Zusätzliche Pfade für die Url\n\n#### eigene Pfade an die Url hängen\n\nIm Feld **eigene Pfade an die Url hängen** lassen sich zusätzliche Pfade eintragen, die als gültige Urls verwendet werden können. So ließe sich beispielsweise bei einem Film noch eine zusätzliche Seite über `/filme/the-big-lebowski/zitate/` anzeigen. Dann muss in dem Textfeld einfach nur `zitate` eingetragen werden - ohne vorangestellten und abschließenden Schrägstrich.\n\n\n#### Unterkategorien anhängen?\n\nEs können an die erzeugte Url auch die Unterkategorien des Artikels angehangen werden\nDie Urls dazu könnten dann so aussehen: `/filme/the-big-lebowski/schauspieler/`\n\n`Schauspieler` ist dabei eine Unterkategorie der Kategorie `Filme` innerhalb der Strukturverwaltung.\n\n### Beispiel: URLs neu generieren\n\nWenn Datenbanktabellen außerhalb des YForm-Table-Managers befüllt werden, greift der passende Extension Point nicht und die URLs werden nicht neu generiert. Dies lässt sich mit folgendem Code erledigen.\n\n```php\n$profiles = \\Url\\Profile::getAll();\nif ($profiles) {\n    foreach ($profiles as $profile) {\n        $profile-\u003edeleteUrls();\n        $profile-\u003ebuildUrls();\n    }\n}\n```\n\n### Beispiel: Auslesen, über welchen Profil-Key der Artikel aufgerufen wurde / die URL generiert wurde\n\n```php\n$manager = Url::resolveCurrent();\nif ($manager \u0026\u0026 $profile = $manager-\u003egetProfile()) {\n    dump($profile-\u003egetNamespace());\n}\n```\n\n## Extension Points\n\n- URL_PRE_SAVE\n- URL_PROFILE_RESTRICTION\n- URL_SEO_TAGS\n- URL_TABLE_UPDATED\n\n### URL_PRE_SAVE\n\nDer Extension Point `URL_PRE_SAVE` gibt die Möglichkeit eine URL vor dem Speichern in der URL Tabelle zu manipulieren.\n\n#### Beispiel Code URL_PRE_SAVE\n\n```php\nrex_extension::register('URL_PRE_SAVE', 'rex_url_shortener');\n\n/**\n * Kürzt URL für ALLE Profile indem es die Artikel und Kategorienamen aus der URL entfernt.\n * @param rex_extension_point $ep Redaxo extension point\n * @return Url Neue URL\n */\nfunction rex_url_shortener(rex_extension_point $ep)\n{\n    $params = $ep-\u003egetParams();\n    $url = $params['object'];\n    $article_id = $params['article_id'];\n    $clang_id = $params['clang_id'];\n\n    // URL muss nur gekürzt werden, wenn es sich nicht im den Startartikel der Domain handelt\n    if ($article_id != rex_yrewrite::getDomainByArticleId($article_id, $clang_id)-\u003egetStartId()) {\n        $article_url = rex_getUrl($article_id, $clang_id);\n        $start_article_url = rex_getUrl(rex_yrewrite::getDomainByArticleId($article_id, $clang_id)-\u003egetStartId(), $clang_id);\n        $article_url_without_lang_slug = '';\n        if (strlen($start_article_url) == 1) {\n            // Wenn lang slug  im Startartikel nicht angezeigt wird\n            $article_url_without_lang_slug = str_replace('/'.strtolower(rex_clang::get($clang_id)-\u003egetCode()).'/', '/', $article_url);\n        } else {\n            $article_url_without_lang_slug = str_replace($start_article_url, '/', $article_url);\n        }\n\n        // Im Fall $url ist urlencoded, muss Artikel URL ebenfalls encoded werden\n        $article_url_without_lang_slug_split = explode(\"/\", $article_url_without_lang_slug);\n        for ($i = 0; $i \u003c count($article_url_without_lang_slug_split); $i++) {\n            $article_url_without_lang_slug_split[$i] = urlencode($article_url_without_lang_slug_split[$i]);\n        }\n        $article_url_without_lang_slug_split_encoded = implode(\"/\", $article_url_without_lang_slug_split);\n\n        $new_url = new \\Url\\Url(str_replace($article_url_without_lang_slug_split_encoded, '/', $url-\u003e__toString()));\n\n        // Auf Duplikate prüfen\n        $query = \"SELECT * FROM \".\\rex::getTablePrefix().\"url_generator_url \"\n            .\"WHERE url = '\".$new_url-\u003e__toString().\"'\";\n\n        $result = \\rex_sql::factory();\n        $result-\u003esetQuery($query);\n        if ($result-\u003egetRows() \u003e 0) {\n            // FALSE zurückgeben, Duplikate sind nicht erlaubt\n            return false;\n        }\n\n        return $new_url;\n    }\n\n    return $url;\n}\n```\n\n### URL_PROFILE_RESTRICTION\n\nMit diesem Extension Point kann man die Einschränkungen von außen beeinflussen.\n\n#### Beispiel Code URL_PROFILE_RESTRICTION\n\nIm nachfolgenden Beispiel werden Urls für News erzeugt, die erst 3 Tage später online gehen und damit bereits auch in der sitemap.xml erscheinen.\n\n```php\nrex_extension::register('URL_PROFILE_RESTRICTION', function (\\rex_extension_point $ep) {\n    $restrictions = $ep-\u003egetSubject();\n    $profile = $ep-\u003egetParam('profile');\n\n    if ($profile-\u003egetTableName() === 'rex_ao_news') {\n        $profile-\u003eaddColumnName('online_from');\n        $restrictions[] = [\n            'column'              =\u003e 'online_from',\n            'comparison_operator' =\u003e '\u003c=',\n            'value'               =\u003e date('Y-m-d', strtotime('+3 days')),\n        ];\n        $ep-\u003esetSubject($restrictions);\n    }\n});\n```\n\n### URL_SEO_TAGS\n\nHiermit können die verschiedenen HTML-Tags nachträglich beeinflusst werden. \n\n#### Beispiel\n\n```php\n\\rex_extension::register('URL_SEO_TAGS', function(\\rex_extension_point $ep) {\n    $tags = $ep-\u003egetSubject();\n    dump($tags);\n    $ep-\u003esetSubject($tags);\n});\n```\n\n### URL_TABLE_UPDATED\n\nDieser ExtensionPoint wird getriggert, sobald die Tabelle der Urls sich ändert.\n\n#### Beispiel\n```php\n\\rex_extension::register('URL_PROFILE_RESTRICTION', function () {\n});\n```\n\n\n\n## SEO-Methoden\n\nURL verwendet die Standard-Methode des YRewrite-SEO-Objekts.\n\n```php\n$seo = new rex_yrewrite_seo();\necho $seo-\u003egetTags();\n```\n\nEine Anpassung der einzelnen Tags kann über den Extension Point `URL_SEO_TAGS` erreicht werden.\n\n#### Beispiel\n \n```php\nuse Url\\Seo;\nuse Url\\Url;\n\n$seo = new Seo();\n$manager = Url::resolveCurrent();\nif ($manager) {\n    \\rex_extension::register('URL_SEO_TAGS', function(\\rex_extension_point $ep) use ($manager) {\n        $tags = $ep-\u003egetSubject();\n\n        $titleValues = [];\n        $article = rex_article::get($manager-\u003egetArticleId());\n        $title = strip_tags($tags['title']);\n\n        if ($manager-\u003egetSeoTitle()) {\n            $titleValues[] = $manager-\u003egetSeoTitle();\n        }\n        if ($article) {\n            $domain = rex_yrewrite::getDomainByArticleId($article-\u003egetId());\n            $title = $domain-\u003egetTitle();\n            $titleValues[] = $article-\u003egetName();\n        }\n        if (count($titleValues)) {\n            $title = rex_escape(str_replace('%T', implode(' / ', $titleValues), $title));\n        }\n        if ('' !== rex::getServerName()) {\n            $title = rex_escape(str_replace('%SN', rex::getServerName(), $title));\n        }\n\n        $tags['title'] = sprintf('\u003ctitle\u003e%s\u003c/title\u003e', $title);\n        $ep-\u003esetSubject($tags);\n    });\n}\n$tags = $seo-\u003egetTags();\n```\n\n## Weitere Tipps \n\n### Leere Einträge vermeiden\n\nWerden URLs selbst erzeugt, z.B. über eine YForm-Tabelle, dann sollte das Feld oder die Feldkombination, aus der die URL generiert wird, nur einmal vorkommen (prüfen auf `unique`) und außerdem niemals leer sein (prüfen auf `empty`). Kommt das Feld oder die Feldkombination mehrfach vor, so wird ab der zweiten URL zusätzlich automatisch die ID des Datensatzes angehangen.\n\n### YForm-Formular auf einer von Url-AddOn erzeugten Url \n\nBefindet sich ein Formular auf einer Seite, die über eine URL des URL-Addon aufgerufen wurde, so muss die Ziel-URL des Formulars angepasst werden. \n\n```php\n$yform-\u003esetObjectparams('form_action', rex_getUrl('', '', [$manager-\u003egetProfile()-\u003egetNamespace() =\u003e $manager-\u003egetDatasetId()]));\n``` \n\noder\n\n```php\n$yform-\u003esetObjectparams('form_action', Url::getCurrent());\n``` \n\nWeiere Infos zu den Objekt-Parametern von YForm befinden sich in der YForm-Doku.\n\n\n### Einzelne Datensätze nicht in der sitemap.xml aufnehmen \n\nDazu kann man ein zusätzliches YFormfeld anlegen der das Indexieren speichert. Im Url-AddOn werden dann zwei Profile angelegt und auf das Index-Feld gefiltert. Das eine Profil erhält zusätzlich die Info \"In Sitemap aufnehmen\".\n\n## Debugging\n\n\n* Sind alle gewünschten Domains in YRewrite vollständig und korrekt angegeben, einschließlich separater 404-Fehlerseite?\n* Wurden Änderungen an der Datenbank vorgenommen, die sich mit dem Löschen des REDAXO-Caches. Datensätze, die außerhalb von REDAXO erstellt, verändert oder gelöscht werden, benötigen ein Auffrischen des Caches.\n* Sind die URL-Profile korrekt oder haben sich Änderungen am verknüpften REDAXO-Artikel oder der Struktur der Datenbankfelder ergeben?\n* Sind innerhalb der URL-Profile Einschränkungen vorgenommen worden? Bspw. können Datensätze gefiltert werden, die dann keine URL erzeugen. Die erzeugten URLs lassen sich im REDAXO-Backend überprüfen.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftbaddade%2Fredaxo_url","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftbaddade%2Fredaxo_url","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftbaddade%2Fredaxo_url/lists"}