# pnk

> Ét spørgsmål om dagen. Mange svar. — Mindre i. Mere vi.

Phase 1 MVP: monolitisk PHP 8.3 + MySQL 8 platform med forside, lokal email/password auth, svar + likes, REST API og adminpanel til spørgsmålshåndtering.

Phase 2 tilføjer: kommentarer på svar (med 2-niveau threading), moderation-kø (de første 3 kommentarer fra nye brugere kræver godkendelse), emoji-reactions på dagens spørgsmål (6 emojis), arkiv over tidligere spørgsmål, en `random`-knap (foretrækker ikke-besvarede for logget-ind brugere) og et fy-ord-filter med admin-CRUD: hvert ord kan markere indhold (`flag`), tvinge til `pending` (auto_pending) eller afvise direkte (auto_reject). Filteret kører på både svar og kommentarer ved oprettelse (case-insensitive substring), og matchede ord vises i moderation-køen.

## Krav
- PHP 8.3 (med ext-pdo_mysql, ext-fileinfo)
- MySQL 8+
- Apache med `mod_rewrite` (eller tilsvarende rewrite-config til nginx)
- Composer

## Installation

```bash
# 1. Hent dependencies
composer install

# 2. Konfigurér
cp config/config.example.php config/config.php
# Tilret database, app.url og app.debug i config/config.php

# 3. Opret databasen (manuelt i MySQL)
mysql -uroot -p -e "CREATE DATABASE pnk CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

# 4. Kør migrations
php bin/migrate.php

# 5. Opret owner-bruger
php bin/seed.php owner din@email.dk SikkertKodeord123 "Dit Navn"

# 6. (valgfrit) Indsæt demo-spørgsmål
php bin/seed.php demo
```

Pege Apache DocumentRoot mod `www/` og sørg for at `AllowOverride All` er sat så `.htaccess` virker. `www/uploads/questions/` skal være skrivbar af webserveren.

### Eksempel Apache vhost

```apache
<VirtualHost *:80>
    ServerName pnk.local
    DocumentRoot /var/www/pnk/pnk/www
    <Directory /var/www/pnk/pnk/www>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
```

### Eksempel nginx (hvis I vælger nginx)

```nginx
server {
    listen 80;
    server_name pnk.local;
    root /var/www/pnk/pnk/www;
    index index.php;

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}
```

## Struktur

```
app/
  Core/         # Bootstrap, Router, Request, Response, Database, View, Auth, Csrf, Validator, Flash, Config
  Controllers/  # Web + Admin/* + Api/*
  Middleware/   # AuthMiddleware, AdminMiddleware, CsrfMiddleware
  Repositories/ # User, Question, Answer
  Services/     # AuthService, AnswerService, UploadService
  Views/        # PHP-templates
config/         # config.php (gitignored), config.example.php
database/migrations/  # SQL-migrations, eksekveret af bin/migrate.php
www/            # Apache DocumentRoot — index.php + assets + .htaccess
storage/        # uploads/ + logs/ (skrivbar)
bin/            # migrate.php, seed.php
```

## Routes (Phase 1)

**Web**
- `GET /` — forside med dagens spørgsmål + 5 offentlige svar
- `GET /arkiv` — tidligere publicerede spørgsmål (paginerede, 20/side)
- `GET /random` — redirect til et tilfældigt publiceret spørgsmål
- `GET /q/{uuid}` — spørgsmålsside med fuld svarliste
- `POST /q/{uuid}/answer` — indsend svar (auth)
- `POST /answers/{uuid}/like` — toggle like (auth)
- `POST /answers/{uuid}/comments` — skriv kommentar; valgfri `parent_comment_id` for tråd-svar (auth)
- `POST /q/{uuid}/react` — set/skift/fjern reaction (auth, body: `emoji`)
- `GET/POST /login`, `GET/POST /register`, `POST /logout`

**Admin** (kræver `admin` eller `owner` rolle)
- `GET /admin` — dashboard
- `GET /admin/questions` — liste
- `GET /admin/questions/create`, `POST /admin/questions`
- `GET /admin/questions/{uuid}/edit`, `PUT /admin/questions/{uuid}`
- `POST /admin/questions/{uuid}/delete`
- `GET /admin/moderation` — kø af pending svar + kommentarer (viser matchede fy-ord)
- `POST /admin/comments/{uuid}/approve|reject|delete`
- `POST /admin/answers/{uuid}/approve|reject|delete`
- `GET /admin/blocked-terms` — fy-ord CRUD
- `GET /admin/blocked-terms/create`, `POST /admin/blocked-terms`
- `GET /admin/blocked-terms/{id}/edit`, `PUT /admin/blocked-terms/{id}`
- `POST /admin/blocked-terms/{id}/delete`

**API v1**
- `GET /api/v1/today` — dagens spørgsmål + 5 svar (offentlig)
- `GET /api/v1/archive?page=1&per_page=20` — paginerede tidligere spørgsmål
- `GET /api/v1/random` — ét tilfældigt spørgsmål
- `GET /api/v1/questions/{uuid}/answers?sort=newest|likes&page=1` — paginerede svar
- `GET /api/v1/me` — logged-in user
- `POST /api/v1/logout`

## Verifikation

```bash
# Vis dagens spørgsmål via API
curl http://pnk.local/api/v1/today | jq

# Tjek forside
curl -I http://pnk.local/
```

Browse `http://pnk.local/`, opret en konto, send et svar, like et andet svar. Login som owner → `/admin` → opret nyt spørgsmål, planlæg dato eller publicér direkte.

## Hvad er IKKE inkluderet i Phase 1

Forberedt i database, men ikke aktiv UI/logik:
- Reputation (felter findes)
- Reports
- Social login providers (Google/Apple/Facebook/Discord)
- AI question suggestions
- Content creator videolinks
- Push tokens, purchases
- Fy-ord/blocked terms-filter

Disse implementeres i senere faser.

## Sikkerhed

- PDO med prepared statements overalt
- CSRF-tokens på alle POST/PUT/DELETE web forms (`Csrf::field()`)
- Output escaping via `View::e()`
- Bcrypt password hashing
- Upload validering: MIME-tjek (finfo), max-størrelse, dimensioner, UUID-filnavn
- Admin/auth middleware på beskyttede routes
- Session cookie httponly + samesite=Lax (sæt `cookie_secure=true` på HTTPS i config)
