This commit is contained in:
2026-03-19 02:01:54 +01:00
parent 291ce9f0c7
commit f55667ba83
2 changed files with 813 additions and 0 deletions

445
BASE_FILES.md Normal file
View File

@@ -0,0 +1,445 @@
# Basisdateien fuer neue Projekte
Dieses Dokument enthaelt die Basisdateien, die bei einem neuen Projekt direkt angelegt werden sollen. Der Schwerpunkt liegt auf den Config-Dateien, weil diese fuer den ersten lauffaehigen Stand zwingend benoetigt werden.
Dieses Dokument ist dafuer gedacht, zusammen mit `GENERAL.md` in ein neues GitLab-Projekt kopiert zu werden. Danach kann die Projektstruktur inklusive Basisdateien direkt erstellt werden.
## Wichtige Regel vor der Erstellung
Ein neues Projekt darf nur erstellt werden, wenn beide Domains bekannt sind:
- Live-Domain
- Staging-Domain
Wenn eine oder beide Angaben fehlen, muss die Erstellung gestoppt werden. Vor dem Anlegen der Dateien ist dann explizit nach beiden Domains zu fragen.
Ohne beide Domains duerfen insbesondere diese Dateien nicht final erzeugt werden:
- `config/prod/domaindata.php`
- `config/prod/settings.php`
- `config/staging/domaindata.php`
- `config/staging/settings.php`
Vor der Neuerstellung ist das Repository ausserdem auf den neuen Projektstand zurueckzusetzen:
- alle bestehenden Dateien und Ordner loeschen
- `.gitlab-ci.yml` ausdruecklich behalten
- `.gitlab-ci.yml` anschliessend auf alte Domainreferenzen, Umgebungs-URLs und projektspezifische Angaben pruefen
- gefundene Domainreferenzen in `.gitlab-ci.yml` auf die neue Live- und Staging-Domain anpassen
## Platzhalter fuer neue Projekte
In den folgenden Vorlagen werden diese Platzhalter verwendet:
- `<LIVE_DOMAIN>` fuer die Produktiv-Domain
- `<STAGING_DOMAIN>` fuer die Staging-Domain
- `<APP_PREFIX>` fuer den Cookie- und App-Prefix
- `<APP_NAME>` fuer einen allgemeinen Projektnamen oder OIDC-Client-Namen
## Datei: `config/fileload.php`
```php
<?php
declare(strict_types=1);
spl_autoload_register(function ($class) {
if (str_starts_with($class, 'App\\Repository\\')) {
$prefix = 'App\\Repository\\';
$baseDir = __DIR__ . '/../src/Repository/';
} elseif (str_starts_with($class, 'App\\')) {
$prefix = 'App\\';
$baseDir = __DIR__ . '/../src/App/';
} else {
return;
}
$len = strlen($prefix);
$relativeClass = substr($class, $len);
$file = $baseDir . str_replace('\\', '/', $relativeClass) . '.php';
if (file_exists($file)) {
require $file;
}
});
require_once __DIR__ . '/../src/App/functions.php';
$domainFile = __DIR__ . '/domaindata.php';
$settingsFile = __DIR__ . '/settings.php';
$configFile = __DIR__ . '/db.php';
$baseConfigFile = __DIR__ . '/base_db.php';
$fallbackBaseConfigStaging = __DIR__ . '/staging/db_settings_basic.php';
$fallbackBaseConfigProd = __DIR__ . '/prod/db_settings_basic.php';
if (file_exists($domainFile)) {
require_once $domainFile;
}
if (file_exists($settingsFile)) {
require_once $settingsFile;
}
$dbConfig = [];
if (file_exists($configFile)) {
$dbConfig = require $configFile;
}
$baseDbConfig = [];
if (file_exists($baseConfigFile)) {
$baseDbConfig = require $baseConfigFile;
}
if (empty($baseDbConfig) && file_exists($fallbackBaseConfigStaging)) {
$baseDbConfig = require $fallbackBaseConfigStaging;
}
if (empty($baseDbConfig) && file_exists($fallbackBaseConfigProd)) {
$baseDbConfig = require $fallbackBaseConfigProd;
}
global $appConfig;
$dbEnabled = defined('APP_DB_ENABLED') ? APP_DB_ENABLED : true;
$baseDbEnabled = defined('APP_BASE_DB_ENABLED') ? APP_BASE_DB_ENABLED : false;
$appConfig = new \App\Config($dbConfig, $dbEnabled, $baseDbConfig, $baseDbEnabled);
\App\App::init($appConfig);
```
## Datei: `config/config.php`
```php
<?php
declare(strict_types=1);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
foreach (['domaindata.php', 'settings.php'] as $cfgFile) {
$rootPath = __DIR__ . '/' . $cfgFile;
if (file_exists($rootPath)) {
require_once $rootPath;
} else {
throw new \RuntimeException("Missing required config file: $cfgFile (expected $rootPath)");
}
}
if (!defined('ASSET_VERSION')) {
define('ASSET_VERSION', 'dev-' . date('Ymd-His'));
}
if (!defined('APP_DOMAIN_PRIMARY')) {
define('APP_DOMAIN_PRIMARY', APP_DOMAIN_NAME);
}
if (!defined('APP_URL_PRIMARY')) {
define('APP_URL_PRIMARY', 'https://' . APP_DOMAIN_PRIMARY);
}
if (!defined('APP_API_BASE')) {
define('APP_API_BASE', 'https://api.' . APP_DOMAIN_PRIMARY);
}
if (!defined('APP_DB_ENABLED')) {
define('APP_DB_ENABLED', false);
}
```
## Datei: `config/base_db.php`
```php
<?php
declare(strict_types=1);
$path = __DIR__ . '/db_settings_basic.php';
if (!file_exists($path)) {
throw new RuntimeException('Missing base DB config: expected config/db_settings_basic.php');
}
return require $path;
```
## Datei: `config/staging/domaindata.php`
```php
<?php
declare(strict_types=1);
if (!defined('APP_DOMAIN_NAME')) {
define('APP_DOMAIN_NAME', '<STAGING_DOMAIN>');
}
if (!defined('APP_PREFIX')) {
define('APP_PREFIX', '<APP_PREFIX>');
}
```
## Datei: `config/prod/domaindata.php`
```php
<?php
declare(strict_types=1);
if (!defined('APP_DOMAIN_NAME')) {
define('APP_DOMAIN_NAME', '<LIVE_DOMAIN>');
}
if (!defined('APP_PREFIX')) {
define('APP_PREFIX', '<APP_PREFIX>');
}
```
## Datei: `config/staging/settings.php`
```php
<?php
define('ASSET_VERSION', 'dev-' . date('Ymd-His'));
define('APP_DOMAIN_PRIMARY', APP_DOMAIN_NAME);
define('APP_URL_PRIMARY', 'https://' . APP_DOMAIN_PRIMARY);
define('APP_API_BASE', 'https://api.' . APP_DOMAIN_PRIMARY);
define('APP_DB_ENABLED', false);
define('APP_DB_DEBUG', true);
define('APP_DB_AUTO_INIT', true);
define('APP_BASE_DB_ENABLED', true);
define('APP_BASIC_AUTH', true);
define('APP_AUTH_ENABLED', false);
define('APP_DEBUG_TOOL', true);
define('APP_AUTH_DEBUG', true);
/*
Optional fuer Projekte mit OIDC:
define('APP_OIDC_ISSUER', 'https://auth.example.tld/realms/<APP_NAME>');
define('APP_OIDC_AUTH_ENDPOINT', 'https://auth.example.tld/realms/<APP_NAME>/protocol/openid-connect/auth');
define('APP_OIDC_TOKEN_ENDPOINT', 'https://auth.example.tld/realms/<APP_NAME>/protocol/openid-connect/token');
define('APP_OIDC_USERINFO_ENDPOINT', 'https://auth.example.tld/realms/<APP_NAME>/protocol/openid-connect/userinfo');
define('APP_OIDC_LOGOUT_ENDPOINT', 'https://auth.example.tld/realms/<APP_NAME>/protocol/openid-connect/logout');
define('APP_OIDC_CLIENT_ID', '<APP_NAME>');
define('APP_OIDC_CLIENT_SECRET', 'CHANGE_ME');
define('APP_OIDC_REDIRECT_URI', 'https://<STAGING_DOMAIN>/auth/callback');
define('APP_OIDC_POST_LOGOUT_REDIRECT_URI', 'https://<STAGING_DOMAIN>/');
define('APP_OIDC_GROUP_CLAIM', 'groups');
define('APP_OIDC_ADMIN_GROUP', 'appadmin');
define('APP_OIDC_USER_GROUP', 'user');
*/
```
## Datei: `config/prod/settings.php`
```php
<?php
define('ASSET_VERSION', 'dev-' . date('Ymd-His'));
define('APP_DOMAIN_PRIMARY', APP_DOMAIN_NAME);
define('APP_URL_PRIMARY', 'https://' . APP_DOMAIN_PRIMARY);
define('APP_API_BASE', 'https://api.' . APP_DOMAIN_PRIMARY);
define('APP_DB_ENABLED', false);
define('APP_DB_DEBUG', false);
define('APP_DB_AUTO_INIT', true);
define('APP_BASE_DB_ENABLED', true);
define('APP_BASIC_AUTH', false);
define('APP_AUTH_ENABLED', false);
define('APP_DEBUG_TOOL', false);
define('APP_AUTH_DEBUG', false);
/*
Optional fuer Projekte mit OIDC:
define('APP_OIDC_ISSUER', 'https://auth.example.tld/realms/<APP_NAME>');
define('APP_OIDC_AUTH_ENDPOINT', 'https://auth.example.tld/realms/<APP_NAME>/protocol/openid-connect/auth');
define('APP_OIDC_TOKEN_ENDPOINT', 'https://auth.example.tld/realms/<APP_NAME>/protocol/openid-connect/token');
define('APP_OIDC_USERINFO_ENDPOINT', 'https://auth.example.tld/realms/<APP_NAME>/protocol/openid-connect/userinfo');
define('APP_OIDC_LOGOUT_ENDPOINT', 'https://auth.example.tld/realms/<APP_NAME>/protocol/openid-connect/logout');
define('APP_OIDC_CLIENT_ID', '<APP_NAME>');
define('APP_OIDC_CLIENT_SECRET', 'CHANGE_ME');
define('APP_OIDC_REDIRECT_URI', 'https://<LIVE_DOMAIN>/auth/callback');
define('APP_OIDC_POST_LOGOUT_REDIRECT_URI', 'https://<LIVE_DOMAIN>/');
define('APP_OIDC_GROUP_CLAIM', 'groups');
define('APP_OIDC_ADMIN_GROUP', 'appadmin');
define('APP_OIDC_USER_GROUP', 'user');
*/
```
## Datei: `config/staging/db_settings_basic.php`
```php
<?php
declare(strict_types=1);
return [
'dsn' => 'sqlite:' . __DIR__ . '/../../data/app_staging.sqlite',
'user' => null,
'password' => null,
'options' => [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
],
];
```
## Datei: `config/prod/db_settings_basic.php`
```php
<?php
declare(strict_types=1);
return [
'dsn' => 'sqlite:' . __DIR__ . '/../../data/app_prod.sqlite',
'user' => null,
'password' => null,
'options' => [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
],
];
```
## Datei: `public/index.php`
Minimaler Einstiegspunkt fuer den Webzugriff:
```php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../config/fileload.php';
$uriPath = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?: '/';
$uriPath = preg_replace('~/{2,}~', '/', $uriPath);
$uriPath = trim($uriPath, '/');
if (str_contains($uriPath, '..')) {
http_response_code(400);
exit('Bad request');
}
$pagesBase = realpath(__DIR__ . '/../partials/landingpages') ?: (__DIR__ . '/../partials/landingpages');
$page404 = $pagesBase . '/404.php';
if (preg_match('~^module/([a-zA-Z0-9_-]+)(?:/(.+))?$~', $uriPath, $m)) {
$module = $m[1];
$page = isset($m[2]) && $m[2] !== '' ? trim($m[2], '/') : 'index';
$modulePage = app()->modules()->resolvePage($module, $page);
$target = $modulePage ?: $page404;
if (!$modulePage) {
http_response_code(404);
}
} elseif ($uriPath === '' || $uriPath === 'index' || $uriPath === 'index.php') {
$target = $pagesBase . '/index.php';
} else {
$base = $pagesBase . '/' . $uriPath;
if (is_dir($base) && is_file($base . '/index.php')) {
$target = $base . '/index.php';
} elseif (is_file($base . '.php')) {
$target = $base . '.php';
} else {
http_response_code(404);
$target = $page404;
}
}
ob_start();
require $target;
$content = ob_get_clean();
tpl('layout_start', 'structure');
echo $content;
tpl('layout_end', 'structure');
```
## Datei: `partials/landingpages/index.php`
```php
<div class="card">
<h1>Projektstart</h1>
<p>Die Grundstruktur wurde erfolgreich erstellt.</p>
</div>
```
## Datei: `partials/landingpages/404.php`
```php
<div class="card">
<h1>404</h1>
<p>Die angeforderte Seite wurde nicht gefunden.</p>
</div>
```
## Datei: `partials/structure/layout_start.php`
```php
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Projektbasis</title>
<link rel="stylesheet" href="/assets/css/app.css?v=<?= urlencode(app()->config()->assetVersion) ?>">
</head>
<body>
<main class="main-content">
```
## Datei: `partials/structure/layout_end.php`
```php
</main>
<script src="/assets/js/app.js?v=<?= urlencode(app()->config()->assetVersion) ?>" defer></script>
</body>
</html>
```
## Datei: `public/assets/css/app.css`
```css
body {
margin: 0;
font-family: sans-serif;
background: #f5f5f5;
color: #111;
}
.main-content {
max-width: 960px;
margin: 0 auto;
padding: 32px 16px;
}
.card {
background: #fff;
border: 1px solid #ddd;
border-radius: 12px;
padding: 24px;
}
```
## Datei: `public/assets/js/app.js`
```js
document.documentElement.classList.add('js');
```
## Datei: `public/.htaccess`
```apache
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]
```
## Empfohlene Startreihenfolge in einem neuen Projekt
1. Neues GitLab-Projekt anlegen.
2. Repository lokal mit VS Code verknuepfen.
3. Alle bestehenden Dateien und Ordner entfernen, `.gitlab-ci.yml` jedoch behalten.
4. `GENERAL.md` und `BASE_FILES.md` in das neue Repository kopieren.
5. `.gitlab-ci.yml` auf alte Domain- und Projektreferenzen pruefen und anpassen.
6. Pflichtstruktur aus `GENERAL.md` anlegen.
7. Basisdateien aus `BASE_FILES.md` anlegen.
8. Live- und Staging-Domain einsetzen.
9. Danach erst die eigentliche Projekterstellung oder Modulentwicklung starten.
## Kurzregel
Ohne `GENERAL.md`, ohne `BASE_FILES.md` oder ohne beide Domains ist die saubere Erstellung eines neuen Projekts auf dieser Basis nicht vollstaendig und soll nicht ausgefuehrt werden.

368
GENERAL.md Normal file
View File

@@ -0,0 +1,368 @@
# Projektbasis fuer neue Projekte
Dieses Dokument kombiniert die Erklaerung des allgemeinen Projektaufbaus mit einer konkreten Startstruktur fuer neue Projekte. Ziel ist, dass neue Projekte dieselbe technische Basis verwenden und dieselben Regeln fuer Routing, Verzeichnisse, Module, Assets und Konfiguration einhalten.
## Grundprinzip
Das Projekt basiert auf einer schlanken PHP-Struktur mit:
- einem zentralen Web-Einstiegspunkt in `public/index.php`
- einem zentralen Bootstrap in `config/fileload.php`
- globalen Seiten unter `partials/landingpages/`
- globalem Layout unter `partials/structure/`
- optionalen Fachmodulen unter `modules/`
- globalen Assets unter `public/assets/`
- einer Deployment-gesteuerten Config-Aufteilung mit `config/staging/` und `config/prod/`
## Verbindliche Startstruktur fuer neue Projekte
Die folgende Struktur soll als Basis fuer neue Projekte verwendet werden. Sie beruecksichtigt ausdruecklich auch die Basisverzeichnisse aus `.gitlab-ci.yml`.
```text
/
|-- .gitlab-ci.yml
|-- GENERAL.md
|-- api/
| `-- .gitkeep
|-- config/
| |-- .gitkeep
| |-- base_db.php
| |-- config.php
| |-- fileload.php
| |-- prod/
| | |-- .gitkeep
| | |-- db_settings_basic.php
| | |-- domaindata.php
| | `-- settings.php
| `-- staging/
| |-- .gitkeep
| |-- db_settings_basic.php
| |-- domaindata.php
| `-- settings.php
|-- data/
| `-- .gitkeep
|-- debug/
| `-- .gitkeep
|-- modules/
| `-- .gitkeep
|-- partials/
| |-- landingpages/
| | |-- .gitkeep
| | `-- index.php
| `-- structure/
| |-- .gitkeep
| |-- layout_end.php
| `-- layout_start.php
|-- public/
| |-- .gitkeep
| |-- .htaccess
| |-- index.php
| `-- assets/
| |-- css/
| | |-- .gitkeep
| | `-- app.css
| |-- images/
| | `-- .gitkeep
| `-- js/
| |-- .gitkeep
| `-- app.js
|-- src/
| |-- .gitkeep
| |-- App/
| | |-- .gitkeep
| | |-- App.php
| | |-- Assets.php
| | |-- Config.php
| | |-- Database.php
| | |-- ModuleManager.php
| | `-- functions.php
| `-- Repository/
| `-- .gitkeep
`-- tools/
`-- .gitkeep
```
## Pflichtordner
Diese Ordner muessen als Basis immer vorhanden sein, weil sie entweder vom Projektaufbau oder vom Deployment vorausgesetzt werden:
- `api/`
- `config/`
- `data/`
- `debug/`
- `modules/`
- `partials/`
- `public/`
- `src/`
- `tools/`
Diese Liste entspricht der Deploy-Basis aus `.gitlab-ci.yml` plus den notwendigen Unterordnern fuer die Anwendung.
## Regel fuer leere Ordner
Wenn ein notwendiger Ordner anfangs noch keine echten Dateien enthaelt, muss er eine leere Datei mit dem Namen `.gitkeep` enthalten. Das gilt insbesondere fuer:
- `api/`
- `data/`
- `debug/`
- `modules/`
- `tools/`
- `public/assets/images/`
- `src/Repository/`
- weitere leere Unterordner, die im Template bereits vorgesehen sind
Damit bleiben die Verzeichnisse versionierbar und werden beim Kopieren und Deployment nicht versehentlich ausgelassen.
## Rollen der wichtigsten Verzeichnisse
### `public/`
`public/` ist der Webroot. Hier liegen:
- `index.php` als zentraler Router
- globale Assets unter `public/assets/`
- Webserver-Dateien wie `.htaccess`
### `src/`
`src/` enthaelt den PHP-Kern der Anwendung.
- `src/App/` fuer App-Klassen, Bootstrap-nahe Logik, Config, Assets, Datenbank, Request, Session und Modulverwaltung
- `src/Repository/` fuer Datenzugriffslogik
### `partials/`
`partials/` enthaelt globale Templates.
- `partials/landingpages/` fuer globale, direkt routbare Seiten
- `partials/structure/` fuer das globale Layout
### `modules/`
`modules/` enthaelt fachlich getrennte Erweiterungen. Jedes Modul bleibt in seinem eigenen Ordner und kapselt Seiten, Assets, Partials und optionale Bootstrap-Logik.
### `api/`
`api/` ist fuer API-Funktionen vorgesehen, falls das Projekt eigene API-Endpunkte anbieten soll. Wenn ein Projekt keine API bereitstellt, kann der Ordner leer bleiben, soll aber als Teil der Basisstruktur dennoch vorhanden sein.
### `config/`
`config/` enthaelt den Bootstrap der Konfiguration sowie die umgebungsspezifischen Quellverzeichnisse `staging` und `prod`.
### `tools/`
`tools/` ist fuer CLI-Skripte, Worker und Hilfsprogramme vorgesehen.
## Routing- und Renderstruktur
### `public/index.php`
`public/index.php` ist der einzige Web-Einstiegspunkt und uebernimmt:
- Laden von `config/fileload.php`
- Normalisierung des Request-Pfads
- Pruefung optionaler Authentifizierung oder Schutzregeln
- Routing auf globale Seiten unter `partials/landingpages/`
- Routing auf Modulseiten unter `modules/<modul>/pages/`
- 404-Behandlung
- Rendern des Inhalts innerhalb des globalen Layouts
### Globale Seiten
Globale Seiten liegen unter `partials/landingpages/`. Das Routing ist dateibasiert, also ohne externen Framework-Router.
Beispiele:
- `/` -> `partials/landingpages/index.php`
- `/users` -> `partials/landingpages/users/index.php`
### Layout
Die globale HTML-Struktur liegt unter `partials/structure/`.
- `layout_start.php` oeffnet das Seitenlayout
- `layout_end.php` schliesst es
### Module
Modulrouten folgen dem Schema:
```text
/module/<modulname>
/module/<modulname>/<seite>
```
Diese Routen verweisen auf Dateien unter:
```text
modules/<modulname>/pages/
```
## Modulstruktur fuer neue Projekte
Wenn ein neues Projekt Module verwendet, sollte jedes Modul nach demselben Muster aufgebaut sein:
```text
modules/<modulname>/
|-- assets/
| `-- .gitkeep
|-- pages/
| |-- .gitkeep
| `-- index.php
|-- partials/
| `-- .gitkeep
|-- bootstrap.php
`-- module.json
```
Regeln:
- modulspezifisches CSS und JavaScript bleibt unter `modules/<modulname>/assets/`
- globale Assets gehoeren nicht in Modulordner
- Modulcode gehoert nicht nach `public/assets/`
- Seiten eines Moduls liegen unter `pages/`
- wiederverwendbare Modul-Templates liegen unter `partials/`
## Asset-Struktur
### Globale Assets
Projektweite Dateien liegen unter:
- `public/assets/css/`
- `public/assets/js/`
- `public/assets/images/`
### Modul-Assets
Modulbezogene Dateien liegen unter:
- `modules/<modulname>/assets/`
Neue Projekte sollen diese Trennung konsequent beibehalten.
## Config-Aufteilung mit `staging` und `prod`
Dieser Teil ist fuer neue Projekte verpflichtend.
### Quellverzeichnisse im Repository
Im Repository liegen die umgebungsspezifischen Config-Quellen unter:
```text
config/staging/
config/prod/
```
Darin liegen typischerweise:
- `domaindata.php`
- `settings.php`
- `db_settings_basic.php`
### Laufzeitlogik
Die Anwendung selbst laedt zur Laufzeit nicht direkt aus `config/staging/` oder `config/prod/`, sondern aus dem Root von `config/`, also z. B.:
- `config/settings.php`
- `config/domaindata.php`
- `config/db_settings_basic.php`
`config/fileload.php` erwartet genau diese Root-Dateien.
### Deployment-Regel
Beim Deployment wird die passende Umgebung in das aktive `config/`-Root kopiert:
1. allgemeine Root-Dateien aus `config/` werden bereitgestellt
2. je nach Branch wird die Umgebungsvariante darueberkopiert
3. `develop` verwendet `config/staging/`
4. `main` verwendet `config/prod/`
5. im Zielsystem gelten die kopierten Dateien danach so, als waeren sie direkt normale Root-Configs
Neue Projekte muessen exakt dieses Prinzip uebernehmen.
## Domain-Pflicht fuer neue Projekterstellungen
Neue Projekte duerfen nur erstellt werden, wenn beide Domains vorliegen:
- Live-Domain
- Staging-Domain
Diese Domains muessen in den umgebungsspezifischen Config-Dateien verwendet und automatisch eingetragen werden, insbesondere in:
- `config/prod/domaindata.php`
- `config/prod/settings.php`
- `config/staging/domaindata.php`
- `config/staging/settings.php`
- `.gitlab-ci.yml`, falls dort Domainreferenzen oder Umgebungs-URLs hinterlegt sind
## Verbindliche Erstellungsregel
Wenn bei der Aufgabenstellung fuer ein neues Projekt keine Domains angegeben werden, muss vor der Projekterstellung explizit nach beiden Werten gefragt werden.
Die Erstellung ist in diesem Fall zu blockieren.
Sie darf erst fortgesetzt werden, wenn beide Angaben vorhanden sind:
1. Live-Domain
2. Staging-Domain
Fehlt mindestens eine der beiden Angaben, muss die Erstellung unterbunden werden mit einem klaren Hinweis, dass die Domains fehlen.
## Reset-Regel fuer neue Projekterstellungen
Vor der eigentlichen Erstellung eines neuen Projekts muessen alle bestehenden Dateien und Ordner im Repository entfernt werden, mit genau einer Ausnahme:
- `.gitlab-ci.yml`
Die bestehende `.gitlab-ci.yml` bleibt erhalten, weil sie die Deploy-Basis vorgibt. Sie muss jedoch im Zuge der neuen Projekterstellung geprueft und angepasst werden, wenn darin Domainreferenzen, Umgebungs-URLs oder projektspezifische Zielpfade enthalten sind.
Fuer neue Projekterstellungen gilt deshalb verbindlich:
1. vorhandene Projektdateien und Projektordner loeschen
2. `.gitlab-ci.yml` behalten
3. `.gitlab-ci.yml` auf alte Domain- oder Projektreferenzen pruefen
4. vorhandene Domainreferenzen in `.gitlab-ci.yml` auf die neue Live- und Staging-Domain anpassen
5. danach erst die neue Basisstruktur und die neuen Basisdateien erstellen
## Mindestinhalt der Config-Dateien
Die folgenden Dateien koennen als Basis aus diesem Projekttyp uebernommen werden und muessen pro neuem Projekt angepasst werden:
- `config/fileload.php`
- `config/config.php`
- `config/base_db.php`
- `config/prod/domaindata.php`
- `config/prod/settings.php`
- `config/staging/domaindata.php`
- `config/staging/settings.php`
Dabei gilt:
- die allgemeine Config-Logik kann uebernommen werden
- domainspezifische Werte muessen pro Projekt ersetzt werden
- staging und prod muessen immer unterschiedliche Zielwerte bekommen, sofern nicht ausdruecklich anders gefordert
## Basisdateien fuer neue Projekte
Neben der Ordnerstruktur werden fuer neue Projekte auch Basisdateien benoetigt, insbesondere im Config-Bereich. Die konkreten Inhalte sind in einer separaten Datei beschrieben:
- `BASE_FILES.md`
Diese Datei ist dafuer gedacht, nach dem Anlegen eines neuen GitLab-Projekts zusammen mit `GENERAL.md` in das neue Repository kopiert zu werden, damit die Erstellung der Grundstruktur und der Konfigurationsdateien direkt auf einer klaren Vorlage basiert.
## Kurzfassung fuer neue Projekte
Neue Projekte auf dieser Basis verwenden:
- einen zentralen Router in `public/index.php`
- einen zentralen Bootstrap in `config/fileload.php`
- globale Seiten in `partials/landingpages/`
- globale Layout-Dateien in `partials/structure/`
- optionale Module in `modules/`
- globale Assets in `public/assets/`
- modulspezifische Assets in `modules/<modulname>/assets/`
- eine Deploy-gesteuerte Config mit `config/staging/` und `config/prod/`
Leere Pflichtordner erhalten immer `.gitkeep`. Eine neue Projekterstellung ist nur zulaessig, wenn sowohl Live- als auch Staging-Domain vorab angegeben wurden.