site = $site->load(['server', 'certificate', 'crons']); } public function setTab(string $t): void { $this->tab = $t; } public function setActiveFile(string $path): void { $this->activeFile = $path; } public function setLog(string $type): void { $this->currentLog = $type; } public function toggleMaintenance(): void { $this->site->maintenance_mode = ! $this->site->maintenance_mode; $this->site->save(); } public function toggleCache(): void { $this->site->cache_enabled = ! $this->site->cache_enabled; $this->site->save(); } public function toggleCdn(): void { $this->site->cdn_enabled = ! $this->site->cdn_enabled; $this->site->save(); } /* File tree (nested) — verbatim from templates/akutell/sitedetails.js */ public function getFileTreeProperty(): array { return [ [ 'name' => 'htdocs', 'type' => 'dir', 'open' => true, 'children' => [ ['name' => 'wp-admin', 'type' => 'dir', 'children' => []], [ 'name' => 'wp-content', 'type' => 'dir', 'open' => true, 'children' => [ [ 'name' => 'themes', 'type' => 'dir', 'open' => true, 'children' => [ [ 'name' => 'storefront-child', 'type' => 'dir', 'open' => true, 'children' => [ ['name' => 'functions.php', 'type' => 'file', 'lang' => 'PHP', 'path' => 'htdocs/wp-content/themes/storefront-child/functions.php'], ['name' => 'style.css', 'type' => 'file', 'lang' => 'CSS', 'path' => 'htdocs/wp-content/themes/storefront-child/style.css'], ], ], ], ], ['name' => 'plugins', 'type' => 'dir', 'children' => []], ['name' => 'uploads', 'type' => 'dir', 'children' => []], ], ], ['name' => 'wp-includes', 'type' => 'dir', 'children' => []], ['name' => '.htaccess', 'type' => 'file', 'lang' => 'APACHE', 'path' => 'htdocs/.htaccess'], ['name' => 'index.php', 'type' => 'file', 'lang' => 'PHP', 'path' => 'htdocs/index.php'], ['name' => 'robots.txt', 'type' => 'file', 'lang' => 'TEXT', 'path' => 'htdocs/robots.txt'], ['name' => 'wp-config.php','type' => 'file', 'lang' => 'PHP', 'path' => 'htdocs/wp-config.php'], ], ], ['name' => 'php.ini', 'type' => 'file', 'lang' => 'INI', 'path' => 'php.ini'], [ 'name' => 'logs', 'type' => 'dir', 'open' => true, 'children' => [ ['name' => 'access.log', 'type' => 'file', 'lang' => 'LOG', 'path' => 'logs/access.log'], ['name' => 'error.log', 'type' => 'file', 'lang' => 'LOG', 'path' => 'logs/error.log'], ], ], ]; } /* fileContents from sitedetails.js verbatim */ public function getFileContentsProperty(): array { return [ 'htdocs/wp-config.php' => <<<'PHP' <<<'TXT' # BEGIN WordPress RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] # END WordPress Header set X-Content-Type-Options nosniff Header set X-Frame-Options SAMEORIGIN Header set Referrer-Policy strict-origin-when-cross-origin TXT, 'htdocs/robots.txt' => <<<'TXT' User-agent: * Disallow: /wp-admin/ Disallow: /warenkorb/ Disallow: /checkout/ Allow: /wp-admin/admin-ajax.php Sitemap: https://shop.bergmann-coffee.com/sitemap_index.xml TXT, 'htdocs/index.php' => <<<'PHP' <<<'PHP' array_merge($s, ['interval' => 60])); PHP, 'htdocs/wp-content/themes/storefront-child/style.css' => <<<'CSS' /* Theme Name: Storefront Child — Bergmann Template: storefront */ :root { --brand: #15a06a; --brand-dark: #0d6c4a; } .button.alt { background: var(--brand); border-color: var(--brand); } .button.alt:hover { background: var(--brand-dark); } CSS, 'php.ini' => <<<'INI' ; bergmann-coffee · php-fpm pool memory_limit = 256M max_execution_time = 60 max_input_time = 60 upload_max_filesize = 64M post_max_size = 64M date.timezone = Europe/Berlin opcache.enable = 1 opcache.memory_consumption = 256 opcache.max_accelerated_files = 20000 opcache.validate_timestamps = 0 INI, 'logs/access.log' => <<<'LOG' 192.0.2.41 - - [12/Mai/2026:09:12:04 +0200] "GET /shop/ HTTP/2.0" 200 18421 203.0.113.7 - - [12/Mai/2026:09:12:05 +0200] "GET /wp-json/wc/store/cart HTTP/2.0" 200 842 192.0.2.41 - - [12/Mai/2026:09:12:09 +0200] "POST /?wc-ajax=add_to_cart HTTP/2.0" 200 311 LOG, 'logs/error.log' => "[error] PHP Notice: Undefined index 'shipping_zone' in cart.php:88\n[error] Uncaught TypeError: count(): Argument must be array in class-wc-cart.php:412\n", ]; } /* Log entries per type (xterm renders these client-side) */ public function getLogDataProperty(): array { return [ 'access' => [ ['09:12:04', 'INFO', '192.0.2.41 "GET /shop/" 200 18421 — 142ms'], ['09:12:05', 'INFO', '203.0.113.7 "GET /wp-json/wc/store/cart" 200 842 — 38ms'], ['09:12:09', 'INFO', '192.0.2.41 "POST /?wc-ajax=add_to_cart" 200 311 — 96ms'], ['09:12:14', 'INFO', '198.51.100.2 "GET /produkt/espresso-blend/" 200 21044 — 158ms'], ['09:12:21', 'WARN', '45.155.* "GET /wp-login.php" 403 — rate-limit'], ['09:12:33', 'INFO', '192.0.2.88 "GET /warenkorb/" 200 9920 — 71ms'], ['09:12:40', 'INFO', 'Googlebot "GET /sitemap_index.xml" 200 4210 — 22ms'], ['09:12:48', 'INFO', '192.0.2.41 "POST /checkout/" 302 0 — 210ms'], ], 'error' => [ ['09:05:11', 'WARN', 'PHP Notice: Undefined index "shipping_zone" in cart.php:88'], ['09:07:42', 'ERROR', 'Uncaught TypeError: count(): Argument must be array — class-wc-cart.php:412'], ['09:09:03', 'INFO', 'Cache geleert: object-cache (redis) — 18421 keys'], ['08:58:19', 'WARN', 'Slow query (2,1s): wp_bg_postmeta — SELECT meta_value …'], ], 'php' => [ ['09:00:01', 'OK', 'php-fpm pool "bergmann" reloaded — 8 worker'], ['09:03:55', 'INFO', 'OPcache: 4218 scripts cached, 99.2% hit rate'], ['09:08:12', 'WARN', 'Worker 3: memory peak 214M / 256M'], ['09:11:40', 'INFO', 'request /checkout/ — 210ms, mem 41M'], ], 'wp' => [ ['09:01:00', 'DEBUG', 'WC_Cart::calculate_totals() — 12 items'], ['09:04:22', 'DEBUG', 'do_action("woocommerce_payment_complete", 48211)'], ['09:06:30', 'WARN', 'Plugin "Smart Coupons" deprecated hook: woocommerce_add_to_cart'], ['09:10:05', 'DEBUG', 'wp_mail() → kunde@example.com — Bestellbestätigung #48211'], ], ]; } public function getCurrentFileContentProperty(): string { return $this->fileContents[$this->activeFile] ?? ''; } }; ?> @php /** Recursive file tree renderer. */ if (! function_exists('clu_render_tree')) { function clu_render_tree(array $items, string $activeFile): string { $out = ''; foreach ($items as $node) { $isDir = ($node['type'] ?? '') === 'dir'; $isOpen = $node['open'] ?? false; $isActive = ! $isDir && ($node['path'] ?? null) === $activeFile; $rowClass = 'clu-tree-item' . ($isDir ? ' dir' : '') . ($isOpen ? ' open' : '') . ($isActive ? ' active' : ''); $click = $isDir ? '' : 'wire:click="setActiveFile(\''.addslashes($node['path']).'\')" wire:navigate.hover'; $ico = $isDir ? '' : ''; $chev = $isDir ? '' : ''; $out .= '
'.$chev.$ico.''.htmlspecialchars($node['name']).'
'; if ($isDir && ! empty($node['children'])) { $hidden = $isOpen ? '' : ' collapsed'; $out .= '
'.clu_render_tree($node['children'], $activeFile).'
'; } } return $out; } } @endphp
{{-- ── Topbar ── --}}
{{ mb_strtoupper(mb_substr($site->domain, 0, 1)) }}

{{ $site->domain }}

{{ $site->server->name }} · wp {{ $site->wp_version }} · php {{ $site->php_version }} · ssl ✓
online
Besuchen
{{-- ── Tab bar ── --}}
@foreach (['overview' => ['Übersicht', ''], 'wp' => ['WordPress', ''], 'php' => ['PHP / ini', ''], 'files' => ['Datei-Manager', ''], 'cron' => ['Cronjobs', ''], 'logs' => ['Logs', '']] as $key => [$label, $svg]) @endforeach
{{-- ────── OVERVIEW ────── --}} @if ($tab === 'overview')
Besucher / 24h
{{ number_format($site->visitors_24h, 0, ',', '.') }}
↑ 9.2% vs. gestern
Speicher
14.2/40 GB
36% genutzt
PageSpeed
{{ $site->pagespeed_score }}/100
Core Web Vitals OK
Updates
{{ $site->updates_pending }}
{{ $site->updates_pending > 0 ? 'verfügbar' : 'aktuell' }}

Installation

Domain{{ $site->domain }}
Server{{ $site->server->name }} · {{ $site->server->region }}
WordPress{{ $site->wp_version }}
PHP{{ $site->php_version }}
SSLLet's Encrypt
DB-Größe412 MB
Letztes Deployvor 4h

Schnellaktionen

@endif {{-- ────── FILES ────── --}} @if ($tab === 'files')

Datei-Manager

/var/www/bergmann
{!! clu_render_tree($this->fileTree, $activeFile) !!}
{{ implode(' / ', array_slice(explode('/', $activeFile), 0, -1)) }} / {{ basename($activeFile) }}
{{ strtoupper(pathinfo($activeFile, PATHINFO_EXTENSION)) ?: 'TEXT' }}
@php $lines = max(1, substr_count($this->currentFileContent, "\n") + 1); @endphp
@for ($i = 1; $i <= $lines; $i++)
{{ $i }}
@endfor
✓ geladen · {{ $lines }} Zeilen
@endif {{-- ────── CRON ────── --}} @if ($tab === 'cron')

Cronjobs

Geplante Aufgaben {{ $site->crons->count() }}

@forelse ($site->crons as $c) @empty @endforelse
NameZeitplanBefehlLetzter LaufStatus
{{ $c->name }} {{ $c->expression }} {{ $c->command }} {{ $c->last_run_at?->diffForHumans() ?? '—' }} @if ($c->status === 'ok')ok @elseif ($c->status === 'failing')failing @elsepaused@endif
Noch keine Cronjobs.
@endif {{-- ────── LOGS (xterm.js) ────── --}} @if ($tab === 'logs')

Logs · {{ $currentLog }}.log

@foreach (['access', 'error', 'php', 'wp'] as $log) @endforeach
@push('scripts') @endpush
@endif {{-- ────── WP + PHP (kompakte Hardcoded-Konfig nach Template) ────── --}} @if ($tab === 'wp')

wp-config.php

WordPress core
@foreach (['Tabellen-Präfix' => 'wp_bg_', 'WP_MEMORY_LIMIT' => '256M', 'AUTOSAVE_INTERVAL' => '60', 'WP_POST_REVISIONS' => '10', 'WP_DEBUG_LOG' => '/var/www/bergmann/logs/wp-debug.log', 'WP_HOME' => 'https://shop.bergmann-coffee.com'] as $label => $val)
@endforeach
@foreach (['WP_DEBUG' => false, 'WP_CACHE' => true, 'DISALLOW_FILE_EDIT' => true, 'FORCE_SSL_ADMIN' => true, 'AUTOMATIC_UPDATER_DISABLED' => false] as $k => $v) @endforeach

Datenbank

@foreach (['DB_NAME' => 'bergmann_prod', 'DB_USER' => 'bergmann_wp', 'DB_HOST' => '127.0.0.1:3306', 'DB_CHARSET' => 'utf8mb4'] as $k => $v)
@endforeach

Security Keys

AUTH_KEYenv
SECURE_AUTH_KEYenv
Rotationvor 11 Wochen
@endif @if ($tab === 'php')

php.ini · PHP {{ $site->php_version }}

@foreach (['memory_limit' => '256M', 'max_execution_time' => '60', 'max_input_time' => '60', 'upload_max_filesize' => '64M', 'post_max_size' => '64M', 'date.timezone' => 'Europe/Berlin', 'opcache.memory_consumption' => '256', 'opcache.max_accelerated_files' => '20000'] as $k => $v)
@endforeach
@foreach (['display_errors' => false, 'opcache.enable' => true, 'log_errors' => true, 'allow_url_fopen' => false] as $k => $v) @endforeach

OPcache

Hit-Rate99.2%
Scripts4 218
Memory187 / 256 MB

Aktive Erweiterungen

@foreach (['curl', 'gd', 'imagick', 'mbstring', 'mysqli', 'opcache', 'redis', 'xml', 'zip', 'intl', 'json', 'soap', 'sodium', 'exif', 'fileinfo', 'iconv'] as $ext){{ $ext }}@endforeach
@endif