💾 Downloads
Download-Ordner können einfach über TVs integriert werden.
<?php
# V 2025-12-22 (mit absolut URLs) - minimal modernisiert
# Parameter
$strSORT = $modx->getOption('SORT', $scriptProperties, 'asc'); # asc oder desc
$dir = trim($modx->getOption('dir', $scriptProperties, ""), '/');
$style = $modx->getOption('style', $scriptProperties, 'legacy'); # legacy oder bs5
# Pfade vorbereiten
$fsDir = MODX_BASE_PATH . $dir; # Dateisystem-Pfad
$urlDir = rtrim(MODX_BASE_URL, '/') . '/' . $dir; # URL-Pfad (immer mit führendem /)
# erlaubte Extensions (kleingeschrieben, ohne Punkt)
$allowedExt = [
'pdf','ics','deb','zip','gif','png','jpg','jpeg','xz','zst','gz'
];
if (is_dir($fsDir)) {
$open_dir = opendir($fsDir);
$output = array(); // legacy
$files = array(); // bs5
while ($file = readdir($open_dir)) {
if ($file != "." && $file != "..") {
# Extension sauber prüfen (case-insensitive)
$ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
if (!in_array($ext, $allowedExt, true)) {
continue;
}
# Dateigröße aus dem Dateisystem
$size = ceil(filesize($fsDir . "/" . $file) / 1024);
# HTML-sicher ausgeben
$fileEsc = htmlspecialchars($file, ENT_QUOTES, 'UTF-8');
if ($style === 'bs5') {
# Bootstrap-Variante
$files[$file] = array(
'file' => $file,
'fileEsc' => $fileEsc,
'size' => $size,
'ext' => $ext,
);
} else {
# Legacy-Ausgabe
$o = "<ul style=\"list-style-type:square;\">";
$o .= "<li><a href=\"{$urlDir}/{$file}\" target=\"_blank\" rel=\"noopener noreferrer\"> {$fileEsc}</a>";
$o .= " [" . $size . " KB]</li>";
$o .= "</ul>";
$output[$file] = $o;
}
}
}
closedir($open_dir);
# Bootstrap-Ausgabe
if ($style === 'bs5') {
if ($strSORT == "asc") {
ksort($files);
} else {
krsort($files);
}
$html = array();
$html[] = '<div class="download card file-list-card my-4">';
$html[] = ' <div class="card-header py-2">Downloads</div>';
$html[] = ' <ul class="list-group list-group-flush small mb-0">';
foreach ($files as $fileName => $data) {
$file = $data['file'];
$fileEsc = $data['fileEsc'];
$size = $data['size'];
$ext = $data['ext'];
# Icon minimal nach Typ (fallback: generic file)
$icon = 'bi bi-file-earmark me-2';
if ($ext === 'pdf') {
$icon = 'bi bi-file-earmark-pdf me-2';
} elseif ($ext === 'zip' || $ext === 'gz' || $ext === 'xz' || $ext === 'zst') {
$icon = 'bi bi-file-earmark-zip me-2';
} elseif ($ext === 'png' || $ext === 'jpg' || $ext === 'jpeg' || $ext === 'gif') {
$icon = 'bi bi-file-earmark-image me-2';
} elseif ($ext === 'ics') {
$icon = 'bi bi-calendar-event me-2';
}
$html[] = ' <li class="list-group-item d-flex justify-content-between align-items-center">';
$html[] = ' <a href="' . $urlDir . '/' . rawurlencode($file) . '" target="_blank" rel="noopener noreferrer" class="file-link text-decoration-none">';
$html[] = ' <i class="' . $icon . '"></i> ' . $fileEsc;
$html[] = ' </a>';
$html[] = ' <span class="badge bg-secondary">' . $size . ' KB</span>';
$html[] = ' </li>';
}
$html[] = ' </ul>';
$html[] = '</div>';
return implode("\n", $html);
} else {
if ($strSORT == "asc") {
ksort($output);
} else {
krsort($output);
}
return implode('', $output);
}
}
return "Das Verzeichnis \"" . htmlspecialchars($dir, ENT_QUOTES, 'UTF-8') . "\" existiert nicht!";
<style>
.download.card.file-list-card {
max-width: 520px;
margin: 2rem 0;
box-shadow: 0 4px 12px rgba(0,0,0,0.10);
}
.file-list-card .card-header {
background-color: #f8f9fa;
font-weight: 600;
font-size: 0.95rem;
}
.file-list-card .list-group-item {
padding: 0.35rem 0.75rem;
}
.file-list-card .file-link {
display: inline-flex;
align-items: center;
}
.file-list-card .file-link:hover {
text-decoration: underline;
}
.file-list-card .badge {
font-size: 0.75rem;
font-weight: 400;
}
</style>
