Finanzmanager/src/View.php
fds2610-bot be3ee6400e Detailseite eines Wertpapiers
Der Name in Bestandsübersicht, Depotbuchungen und Stammdaten führt jetzt auf
/wertpapiere/papier/{id}: Kennzahlen über die ganze Historie, Stammdaten und
Kurs, Bestand je Depot, Wertentwicklung und die Buchungen eines Zeitraums.

Depot::bestand() und Depot::entwicklung() nehmen dafür eine Wertpapiernummer
entgegen – die Detailseite rechnet nicht selbst, sondern bekommt dieselben
Zahlen wie die Übersicht. Neu sind Wertpapier::kurseckwerte() und
Depotbuchung::datumsgrenzen().

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 15:08:01 +02:00

141 lines
4.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
namespace Finanzmanager;
class View
{
private string $viewDir;
private array $flash = [];
public function __construct()
{
$this->viewDir = __DIR__ . '/Views';
Auth::startSession();
if (isset($_SESSION['flash'])) {
$this->flash = $_SESSION['flash'];
unset($_SESSION['flash']);
}
}
public function render(string $template, array $daten = []): void
{
$daten['flash'] = $this->flash;
$daten['aktuellerPfad'] = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
extract($daten, EXTR_SKIP);
include $this->viewDir . '/' . $template;
}
public static function redirect(string $pfad, string $meldung = '', string $typ = 'erfolg'): void
{
Auth::startSession();
if ($meldung !== '') {
$_SESSION['flash'][] = ['typ' => $typ, 'meldung' => $meldung];
}
header('Location: ' . $pfad);
exit;
}
public static function h(mixed $wert): string
{
return htmlspecialchars((string)$wert, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
/**
* Beträge im deutschen Format. Das Leerzeichen vor dem Euro-Zeichen ist
* geschützt, sonst rutscht das Zeichen in schmalen Tabellenspalten allein
* in die nächste Zeile.
*/
public static function betrag(mixed $wert, bool $mitWaehrung = true): string
{
$text = number_format((float)$wert, 2, ',', '.');
return $mitWaehrung ? $text . "\u{00A0}€" : $text;
}
/**
* Stückzahlen. Fonds werden in Bruchteilen geführt, Aktien in ganzen
* Stücken – dieselbe Spalte trägt beides, deshalb sechs Nachkommastellen
* ohne die Nullen, die niemand liest: „12“ statt „12,000000“.
*/
public static function stueck(mixed $wert): string
{
return rtrim(rtrim(number_format((float)$wert, 6, ',', '.'), '0'), ',');
}
/**
* Monatsnamen auf Deutsch. Nicht über date('F') oder IntlDateFormatter –
* date() ist immer englisch und intl ist keine Standarderweiterung. Der
* Budgetplaner und die Auswertungen greifen später ebenfalls hierauf zu.
*/
public const MONATE = [
1 => 'Januar', 2 => 'Februar', 3 => 'März', 4 => 'April',
5 => 'Mai', 6 => 'Juni', 7 => 'Juli', 8 => 'August',
9 => 'September', 10 => 'Oktober', 11 => 'November', 12 => 'Dezember',
];
/** Kurzform für schmale Spalten (zwölf Monatsspalten im Budgetplaner). */
public const MONATE_KURZ = [
1 => 'Jan', 2 => 'Feb', 3 => 'Mär', 4 => 'Apr',
5 => 'Mai', 6 => 'Jun', 7 => 'Jul', 8 => 'Aug',
9 => 'Sep', 10 => 'Okt', 11 => 'Nov', 12 => 'Dez',
];
public static function monat(int $monat, bool $kurz = false): string
{
$namen = $kurz ? self::MONATE_KURZ : self::MONATE;
return $namen[$monat] ?? (string)$monat;
}
/** Wochentagskürzel, Montag zuerst – wie MONATE nicht über date() oder intl. */
public const WOCHENTAGE = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'];
public static function wochentag(?string $datum): string
{
if (!$datum) {
return '';
}
$zeit = strtotime(substr($datum, 0, 10));
if ($zeit === false) {
return '';
}
// date('N') zählt Montag als 1.
return self::WOCHENTAGE[(int)date('N', $zeit) - 1] ?? '';
}
public static function datum(?string $datum): string
{
if (!$datum) {
return '–';
}
$d = \DateTime::createFromFormat('Y-m-d', substr($datum, 0, 10));
return $d ? $d->format('d.m.Y') : $datum;
}
/** CSS-Klasse für Beträge: negative Werte werden rot dargestellt. */
public static function betragKlasse(mixed $wert): string
{
return (float)$wert < 0 ? 'betrag negativ' : 'betrag';
}
/**
* Farbschema für das data-thema-Attribut: 'hell', 'dunkel' oder '' für die
* Systemvorgabe. Fällt auf die Systemvorgabe zurück, wenn die Einstellung
* nicht lesbar ist – die Fehlerseite muss auch ohne Datenbank darstellbar
* bleiben.
*/
public static function thema(): string
{
try {
$thema = \Finanzmanager\Models\Einstellung::get('darstellung_thema', 'system');
} catch (\Throwable) {
return '';
}
return in_array($thema, ['hell', 'dunkel'], true) ? $thema : '';
}
}