194 lines
7.1 KiB
PHP
194 lines
7.1 KiB
PHP
<?php
|
|
|
|
namespace EIS\Component\EIS\Administrator\Helper;
|
|
|
|
\defined('_JEXEC') or die;
|
|
|
|
use Joomla\CMS\Factory;
|
|
use Joomla\CMS\Language\Text;
|
|
use Joomla\Database\DatabaseDriver;
|
|
|
|
class TreeHelper
|
|
{
|
|
/** Lädt #__eis_documents, gruppiert nach parent_id und sortiert */
|
|
public static function getItems(): array
|
|
{
|
|
/** @var DatabaseDriver $db */
|
|
$db = Factory::getDbo();
|
|
|
|
$query = $db->getQuery(true)
|
|
->select('*')
|
|
->from($db->quoteName('#__eis_documents'))
|
|
->order($db->quoteName('ordering') . ' ASC');
|
|
|
|
$rows = $db->setQuery($query)->loadAssocList();
|
|
|
|
$grouped = [];
|
|
foreach ($rows as $row) {
|
|
$pid = $row['parent_id'] === null ? null : (int) $row['parent_id'];
|
|
$grouped[$pid][] = $row;
|
|
}
|
|
|
|
// alphabetisch nach name
|
|
foreach ($grouped as &$group) {
|
|
usort($group, static fn($a, $b) => strcasecmp((string)$a['name'], (string)$b['name']));
|
|
}
|
|
|
|
return $grouped;
|
|
}
|
|
|
|
/**
|
|
* Kombiniert: Virtueller Ordner "Neue Dokumente" (falls $newIds vorhanden) + normaler Baum
|
|
*/
|
|
public static function renderTreeWithNew(array $items, array $newIds = []): string
|
|
{
|
|
$html = '';
|
|
|
|
// 1) Virtueller Ordner "Neue Dokumente"
|
|
$newFiles = self::collectFilesByIds($items, $newIds);
|
|
if (!empty($newFiles)) {
|
|
$label = Text::_('COM_EIS_VIRTUAL_NEW') ?: 'Neue Dokumente';
|
|
|
|
$html .= '<ul class="pdf-tree">';
|
|
$html .= '<li class="folder" data-id="new" data-title="' . htmlspecialchars($label, ENT_QUOTES, 'UTF-8') . '" data-name="' . htmlspecialchars($label, ENT_QUOTES, 'UTF-8') . '" data-count="' . count($newFiles) . '">';
|
|
$html .= '<span class="toggle" role="button" aria-label="Ordner umschalten" tabindex="0">▼</span> ';
|
|
$html .= '<span class="folder-label">🆕 ' . htmlspecialchars($label, ENT_QUOTES, 'UTF-8') . ' <small class="count">(' . (int) count($newFiles) . ')</small></span>';
|
|
|
|
// Kinder sichtbar
|
|
$html .= '<ul style="display:block">';
|
|
foreach ($newFiles as $row) {
|
|
$html .= self::renderSingleFileLi($row);
|
|
}
|
|
$html .= '</ul>';
|
|
|
|
$html .= '</li>';
|
|
$html .= '</ul>';
|
|
}
|
|
|
|
// 2) Normaler Baum
|
|
$html .= self::renderTree($items, null);
|
|
|
|
return $html;
|
|
}
|
|
|
|
/** Baum rendern (nutzt title als alternativen Anzeigenamen) */
|
|
public static function renderTree(array $items, ?int $parentId = null): string
|
|
{
|
|
if (!isset($items[$parentId])) {
|
|
return '';
|
|
}
|
|
|
|
$html = '<ul class="pdf-tree">';
|
|
|
|
foreach ($items[$parentId] as $item) {
|
|
$isFolder = !empty($item['is_folder']);
|
|
$rawName = (string)($item['title'] ?? '') !== '' ? (string)$item['title'] : (string)$item['name'];
|
|
$display = preg_replace('/\.pdf$/i', '', $rawName);
|
|
$display = htmlspecialchars((string)$display, ENT_QUOTES, 'UTF-8');
|
|
$id = (int)$item['id'];
|
|
|
|
if ($isFolder) {
|
|
$fileCount = self::countFilesRecursive($items, $id);
|
|
|
|
$html .= '<li class="folder"'
|
|
. ' data-id="' . $id . '"'
|
|
. ' data-title="' . htmlspecialchars((string)($item['title'] ?? ''), ENT_QUOTES, 'UTF-8') . '"'
|
|
. ' data-name="' . htmlspecialchars((string)$item['name'], ENT_QUOTES, 'UTF-8') . '"'
|
|
. ' data-count="' . (int)$fileCount . '"'
|
|
. '>'
|
|
. '<span class="toggle" role="button" aria-label="Ordner umschalten" tabindex="0">▶</span> '
|
|
. '<span class="folder-label">📁 ' . $display . ' <small class="count">(' . (int)$fileCount . ')</small></span>'
|
|
. self::renderTree($items, $id)
|
|
. '</li>';
|
|
} else {
|
|
$html .= self::renderSingleFileLi($item, $display);
|
|
}
|
|
}
|
|
|
|
$html .= '</ul>';
|
|
return $html;
|
|
}
|
|
|
|
/** Einzelnes <li> für Datei (wird auch vom virtuellen Ordner genutzt) */
|
|
private static function renderSingleFileLi(array $item, ?string $displayAlreadyEscaped = null): string
|
|
{
|
|
$rawName = (string)($item['title'] ?? '') !== '' ? (string)$item['title'] : (string)$item['name'];
|
|
$display = $displayAlreadyEscaped ?? htmlspecialchars(preg_replace('/\.pdf$/i', '', $rawName), ENT_QUOTES, 'UTF-8');
|
|
$id = (int)$item['id'];
|
|
|
|
// Dateigröße ermitteln (optional)
|
|
$sizeStr = '';
|
|
$sizeBytes = '';
|
|
if (!empty($item['path']) && is_file((string)$item['path'])) {
|
|
$bytes = @filesize((string)$item['path']); // @ unterdrückt Warnungen bei Zugriffsproblemen
|
|
if ($bytes !== false) {
|
|
$sizeBytes = (string)(int)$bytes;
|
|
$sizeStr = self::formatFileSize((int)$bytes);
|
|
}
|
|
}
|
|
|
|
$html = '<li class="file"'
|
|
. ' data-id="' . $id . '"'
|
|
. ' data-title="' . htmlspecialchars((string)($item['title'] ?? ''), ENT_QUOTES, 'UTF-8') . '"'
|
|
. ' data-name="' . htmlspecialchars((string)$item['name'], ENT_QUOTES, 'UTF-8') . '"'
|
|
. ' data-size="' . htmlspecialchars($sizeStr, ENT_QUOTES, 'UTF-8') . '"'
|
|
. ' data-bytes="' . htmlspecialchars($sizeBytes, ENT_QUOTES, 'UTF-8') . '"'
|
|
. '>'
|
|
. '<span class="file-label">📄 ' . $display
|
|
. ($sizeStr !== '' ? ' <small class="meta">(' . $sizeStr . ')</small>' : '')
|
|
. '</span>'
|
|
. '</li>';
|
|
|
|
return $html;
|
|
}
|
|
|
|
/** Dateien zu gegebenen IDs einsammeln (nur is_folder = 0) */
|
|
private static function collectFilesByIds(array $items, array $ids): array
|
|
{
|
|
if (empty($ids)) {
|
|
return [];
|
|
}
|
|
$ids = array_map('intval', $ids);
|
|
|
|
// Flat-Index aller Rows
|
|
$idx = [];
|
|
foreach ($items as $group) {
|
|
foreach ($group as $row) {
|
|
$idx[(int)$row['id']] = $row;
|
|
}
|
|
}
|
|
|
|
$out = [];
|
|
foreach ($ids as $id) {
|
|
if (isset($idx[$id]) && empty($idx[$id]['is_folder'])) {
|
|
$out[] = $idx[$id];
|
|
}
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
private static function countFilesRecursive(array $items, int $parentId): int
|
|
{
|
|
$count = 0;
|
|
if (!isset($items[$parentId])) {
|
|
return 0;
|
|
}
|
|
foreach ($items[$parentId] as $item) {
|
|
if (!empty($item['is_folder'])) {
|
|
$count += self::countFilesRecursive($items, (int)$item['id']);
|
|
} else {
|
|
$count++;
|
|
}
|
|
}
|
|
return $count;
|
|
}
|
|
|
|
private static function formatFileSize(int $bytes): string
|
|
{
|
|
if ($bytes >= 1073741824) return number_format($bytes / 1073741824, 2) . ' GB';
|
|
if ($bytes >= 1048576) return number_format($bytes / 1048576, 1) . ' MB';
|
|
if ($bytes >= 1024) return number_format($bytes / 1024, 0) . ' KB';
|
|
return $bytes . ' B';
|
|
}
|
|
}
|