Mit neuen Manfest
This commit is contained in:
BIN
com_eis/.DS_Store
vendored
BIN
com_eis/.DS_Store
vendored
Binary file not shown.
Binary file not shown.
BIN
com_eis/administrator/.DS_Store
vendored
BIN
com_eis/administrator/.DS_Store
vendored
Binary file not shown.
BIN
com_eis/administrator/language/.DS_Store
vendored
BIN
com_eis/administrator/language/.DS_Store
vendored
Binary file not shown.
@@ -1,9 +1,44 @@
|
|||||||
|
; Joomla Backend – UI-Texte
|
||||||
|
|
||||||
COM_EIS_DOCUMENT_PATH="Dokumentenpfad"
|
; Allgemein
|
||||||
COM_EIS_DOCUMENT_PATH_LABEL="Pfad zu den PDF-Dokumenten"
|
COM_EIS_TITLE="EIS"
|
||||||
|
COM_EIS_SUBTITLE="Dokumentenverwaltung"
|
||||||
|
COM_EIS_BACK="Zurück"
|
||||||
|
COM_EIS_SAVE="Speichern"
|
||||||
|
COM_EIS_CANCEL="Abbrechen"
|
||||||
|
COM_EIS_APPLY="Anwenden"
|
||||||
|
COM_EIS_CLOSE="Schließen"
|
||||||
|
|
||||||
|
; Main View (Baum & Scan)
|
||||||
|
COM_EIS_PDF_TREE="PDF-Baum"
|
||||||
COM_EIS_SCAN_DOCUMENTS="Dokumente einlesen"
|
COM_EIS_SCAN_DOCUMENTS="Dokumente einlesen"
|
||||||
COM_EIS_MAIN="EIS Hauptansicht"
|
COM_EIS_DOCUMENT_PATH="Dokumenten-Pfad"
|
||||||
COM_EIS_MENU="EIS"
|
COM_EIS_NO_DOCUMENTS_FOUND="Noch keine Dokumente in der Datenbank. Bitte zuerst „Dokumente einlesen“ ausführen."
|
||||||
COM_EIS_CONFIG="Einstellungen"
|
COM_EIS_EXPAND_ALL="Ausklappen"
|
||||||
COM_EIS_MAINTENANCE="Wartung"
|
COM_EIS_COLLAPSE_ALL="Einklappen"
|
||||||
COM_EIS_PDF_TREE="Verzeichnisbaum"
|
COM_EIS_PREVIEW_OPEN_NEWTAB="Im neuen Tab öffnen"
|
||||||
|
COM_EIS_PREVIEW_TITLE="PDF-Vorschau"
|
||||||
|
COM_EIS_FILESIZE="Dateigröße"
|
||||||
|
COM_EIS_VIRTUAL_NEW="Neue Dokumente"
|
||||||
|
|
||||||
|
; Config View (Einstellungen)
|
||||||
|
COM_EIS_SETTINGS_TITLE="Einstellungen"
|
||||||
|
COM_EIS_FIELDSET_GENERAL="Allgemein"
|
||||||
|
COM_EIS_FIELD_DOCUMENT_ROOT_LABEL="Basis-Verzeichnis für PDFs"
|
||||||
|
COM_EIS_FIELD_DOCUMENT_ROOT_DESC="Absoluter Serverpfad, in dem die PDF-Dateien liegen (z. B. /var/www/pdf)."
|
||||||
|
|
||||||
|
; Meldungen
|
||||||
|
COM_EIS_MSG_SAVED_SUCCESS="Einstellungen wurden gespeichert."
|
||||||
|
COM_EIS_MSG_SAVED_ERROR="Einstellungen konnten nicht gespeichert werden."
|
||||||
|
COM_EIS_MSG_SCAN_STARTED="Einlesen gestartet."
|
||||||
|
COM_EIS_MSG_SCAN_DONE="Einlesen abgeschlossen."
|
||||||
|
COM_EIS_MSG_INVALID_PATH="Der angegebene Pfad ist ungültig oder nicht lesbar."
|
||||||
|
|
||||||
|
; Toolbar/Buttons (falls eigene Toolbars)
|
||||||
|
COM_EIS_TOOLBAR_SAVE="Speichern"
|
||||||
|
COM_EIS_TOOLBAR_APPLY="Übernehmen"
|
||||||
|
COM_EIS_TOOLBAR_CLOSE="Schließen"
|
||||||
|
|
||||||
|
COM_EIS_MSG_PATH_NOT_EXISTS="Hinweis: Das Verzeichnis „%s“ existiert nicht."
|
||||||
|
COM_EIS_MSG_PATH_NOT_READABLE="Hinweis: Das Verzeichnis „%s“ ist nicht lesbar."
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1,6 @@
|
|||||||
COM_EIS="EIS Komponente"
|
; Joomla Backend – Systemtexte (Menü, Erweiterungsname, Kurzbeschreibung)
|
||||||
|
COM_EIS="EIS"
|
||||||
|
COM_EIS_MENU="EIS"
|
||||||
|
COM_EIS_MAIN="EIS-Dokumente"
|
||||||
|
COM_EIS_CONFIG="Einstellungen"
|
||||||
|
COM_EIS_XML_DESCRIPTION="EIS Komponente zum Verwalten und Anzeigen von PDFs."
|
||||||
|
|||||||
@@ -1,9 +1,32 @@
|
|||||||
|
COM_EIS_TITLE="EIS"
|
||||||
|
COM_EIS_SUBTITLE="Document Management"
|
||||||
|
COM_EIS_BACK="Back"
|
||||||
|
COM_EIS_SAVE="Save"
|
||||||
|
COM_EIS_CANCEL="Cancel"
|
||||||
|
COM_EIS_APPLY="Apply"
|
||||||
|
COM_EIS_CLOSE="Close"
|
||||||
|
|
||||||
COM_EIS_DOCUMENT_PATH="Dokumentenpfad"
|
COM_EIS_PDF_TREE="PDF Tree"
|
||||||
COM_EIS_DOCUMENT_PATH_LABEL="Pfad zu den PDF-Dokumenten"
|
COM_EIS_SCAN_DOCUMENTS="Scan Documents"
|
||||||
COM_EIS_SCAN_DOCUMENTS="Dokumente einlesen"
|
COM_EIS_DOCUMENT_PATH="Document Path"
|
||||||
COM_EIS_MAIN="EIS Hauptansicht"
|
COM_EIS_NO_DOCUMENTS_FOUND="No documents in the database yet. Please run “Scan Documents” first."
|
||||||
COM_EIS_MENU="EIS"
|
COM_EIS_EXPAND_ALL="Expand All"
|
||||||
COM_EIS_CONFIG="Einstellungen"
|
COM_EIS_COLLAPSE_ALL="Collapse All"
|
||||||
COM_EIS_MAINTENANCE="Wartung"
|
COM_EIS_PREVIEW_OPEN_NEWTAB="Open in new tab"
|
||||||
COM_EIS_PDF_TREE="Verzeichnisbaum"
|
COM_EIS_PREVIEW_TITLE="PDF Preview"
|
||||||
|
COM_EIS_FILESIZE="File size"
|
||||||
|
|
||||||
|
COM_EIS_SETTINGS_TITLE="Settings"
|
||||||
|
COM_EIS_FIELDSET_GENERAL="General"
|
||||||
|
COM_EIS_FIELD_DOCUMENT_ROOT_LABEL="Base directory for PDFs"
|
||||||
|
COM_EIS_FIELD_DOCUMENT_ROOT_DESC="Absolute server path containing the PDF files (e.g. /var/www/pdf)."
|
||||||
|
|
||||||
|
COM_EIS_MSG_SAVED_SUCCESS="Settings saved."
|
||||||
|
COM_EIS_MSG_SAVED_ERROR="Settings could not be saved."
|
||||||
|
COM_EIS_MSG_SCAN_STARTED="Scan started."
|
||||||
|
COM_EIS_MSG_SCAN_DONE="Scan finished."
|
||||||
|
COM_EIS_MSG_INVALID_PATH="The specified path is invalid or not readable."
|
||||||
|
|
||||||
|
COM_EIS_TOOLBAR_SAVE="Save"
|
||||||
|
COM_EIS_TOOLBAR_APPLY="Apply"
|
||||||
|
COM_EIS_TOOLBAR_CLOSE="Close"
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
COM_EIS="EIS Komponente"
|
COM_EIS="EIS"
|
||||||
|
COM_EIS_MENU="EIS"
|
||||||
|
COM_EIS_MAIN="EIS Documents"
|
||||||
|
COM_EIS_CONFIG="Settings"
|
||||||
|
COM_EIS_XML_DESCRIPTION="EIS component for managing and viewing PDFs."
|
||||||
|
|||||||
@@ -1,18 +1,33 @@
|
|||||||
|
-- Documents
|
||||||
CREATE TABLE IF NOT EXISTS `#__eis_documents` (
|
CREATE TABLE IF NOT EXISTS `#__eis_documents` (
|
||||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
`name` VARCHAR(255) NOT NULL,
|
`name` VARCHAR(255) NOT NULL,
|
||||||
`path` TEXT NOT NULL,
|
`path` TEXT NOT NULL,
|
||||||
`parent_id` INT UNSIGNED DEFAULT NULL,
|
`parent_id` INT UNSIGNED DEFAULT NULL,
|
||||||
`is_folder` TINYINT(1) DEFAULT 0,
|
`is_folder` TINYINT(1) NOT NULL DEFAULT 0,
|
||||||
`title` VARCHAR(255) DEFAULT NULL,
|
`title` VARCHAR(255) DEFAULT NULL,
|
||||||
`description` TEXT DEFAULT NULL,
|
`description` TEXT DEFAULT NULL,
|
||||||
`ordering` INT DEFAULT 0,
|
`ordering` INT NOT NULL DEFAULT 0,
|
||||||
PRIMARY KEY (`id`)
|
`created` DATETIME DEFAULT NULL,
|
||||||
|
`modified` DATETIME DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_eis_docs_parent` (`parent_id`),
|
||||||
|
KEY `idx_eis_docs_ordering` (`ordering`),
|
||||||
|
KEY `idx_eis_docs_name` (`name`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- Settings (Key/Value)
|
||||||
CREATE TABLE IF NOT EXISTS `#__eis_settings` (
|
CREATE TABLE IF NOT EXISTS `#__eis_settings` (
|
||||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
`pdf_path` TEXT NOT NULL,
|
`param` VARCHAR(191) NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
`value` TEXT NULL,
|
||||||
|
`created` DATETIME DEFAULT NULL,
|
||||||
|
`modified` DATETIME DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `uniq_param` (`param`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
-- Standardwert für den PDF-Pfad (leer = noch nicht gesetzt)
|
||||||
|
|
||||||
|
INSERT IGNORE INTO `#__eis_settings` (`param`, `value`, `created`, `modified`)
|
||||||
|
VALUES ('document_root', '/var/www/pdf', NOW(), NOW());
|
||||||
BIN
com_eis/administrator/src/.DS_Store
vendored
BIN
com_eis/administrator/src/.DS_Store
vendored
Binary file not shown.
@@ -4,43 +4,55 @@ namespace EIS\Component\EIS\Administrator\Controller;
|
|||||||
\defined('_JEXEC') or die;
|
\defined('_JEXEC') or die;
|
||||||
|
|
||||||
use Joomla\CMS\Factory;
|
use Joomla\CMS\Factory;
|
||||||
|
use Joomla\CMS\Language\Text;
|
||||||
use Joomla\CMS\MVC\Controller\BaseController;
|
use Joomla\CMS\MVC\Controller\BaseController;
|
||||||
use Joomla\CMS\Router\Route;
|
use Joomla\CMS\Router\Route;
|
||||||
|
use Joomla\CMS\Session\Session;
|
||||||
|
use EIS\Component\EIS\Administrator\Helper\SettingsHelper;
|
||||||
|
|
||||||
class ConfigController extends BaseController
|
class ConfigController extends BaseController
|
||||||
{
|
{
|
||||||
public function save(): void
|
public function save(): void
|
||||||
{
|
{
|
||||||
$app = Factory::getApplication();
|
// CSRF
|
||||||
$input = $app->getInput();
|
if (!Session::checkToken('post')) {
|
||||||
$db = Factory::getDbo();
|
throw new \RuntimeException(Text::_('JINVALID_TOKEN'), 403);
|
||||||
|
|
||||||
// Eingabe
|
|
||||||
$pdfPath = $input->getString('pdf_path', '');
|
|
||||||
|
|
||||||
// Existiert ein Eintrag?
|
|
||||||
$query = $db->getQuery(true)
|
|
||||||
->select('COUNT(*)')
|
|
||||||
->from($db->quoteName('#__eis_settings'));
|
|
||||||
$db->setQuery($query);
|
|
||||||
$exists = (int) $db->loadResult() > 0;
|
|
||||||
|
|
||||||
if ($exists) {
|
|
||||||
// Update
|
|
||||||
$query = $db->getQuery(true)
|
|
||||||
->update($db->quoteName('#__eis_settings'))
|
|
||||||
->set($db->quoteName('pdf_path') . ' = ' . $db->quote($pdfPath));
|
|
||||||
} else {
|
|
||||||
// Insert
|
|
||||||
$query = $db->getQuery(true)
|
|
||||||
->insert($db->quoteName('#__eis_settings'))
|
|
||||||
->columns([$db->quoteName('pdf_path')])
|
|
||||||
->values($db->quote($pdfPath));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$db->setQuery($query)->execute();
|
$app = Factory::getApplication();
|
||||||
|
$input = $app->getInput();
|
||||||
|
|
||||||
$app->enqueueMessage('Pfad gespeichert: ' . $pdfPath, 'message');
|
// Feldname aus dem Config-Template
|
||||||
|
$path = (string) $input->post->get('document_root', '', 'string');
|
||||||
|
$path = trim($path);
|
||||||
|
|
||||||
|
// Minimal-Validierung & Normalisierung
|
||||||
|
// (Hier kein striktes is_readable(), damit man den Pfad auch erst konfigurieren kann,
|
||||||
|
// wenn das Verzeichnis später angelegt/umgehängt wird. Warnen ist aber hilfreich.)
|
||||||
|
if ($path === '') {
|
||||||
|
$app->enqueueMessage(Text::_('COM_EIS_MSG_INVALID_PATH') ?: 'Bitte einen gültigen Pfad angeben.', 'warning');
|
||||||
|
$this->setRedirect(Route::_('index.php?option=com_eis&view=config', false));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Doppelte Slashes und trailing Slash bereinigen
|
||||||
|
$path = preg_replace('#/+#', '/', $path);
|
||||||
|
// Lass den Root-Slash stehen, entferne sonst trailing Slash
|
||||||
|
if ($path !== '/' && str_ends_with($path, '/')) {
|
||||||
|
$path = rtrim($path, '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional: Hinweise zur Existenz/Lesbarkeit (nur Hinweis, kein Hard-Error)
|
||||||
|
if (!is_dir($path)) {
|
||||||
|
$app->enqueueMessage(Text::sprintf('COM_EIS_MSG_PATH_NOT_EXISTS', $path) ?: "Hinweis: Verzeichnis existiert nicht: {$path}", 'notice');
|
||||||
|
} elseif (!is_readable($path)) {
|
||||||
|
$app->enqueueMessage(Text::sprintf('COM_EIS_MSG_PATH_NOT_READABLE', $path) ?: "Hinweis: Verzeichnis nicht lesbar: {$path}", 'notice');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Persistieren
|
||||||
|
SettingsHelper::setSetting('document_root', $path);
|
||||||
|
|
||||||
|
$app->enqueueMessage(Text::_('COM_EIS_MSG_SAVED_SUCCESS') ?: 'Einstellungen wurden gespeichert.', 'message');
|
||||||
$this->setRedirect(Route::_('index.php?option=com_eis&view=config', false));
|
$this->setRedirect(Route::_('index.php?option=com_eis&view=config', false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,12 @@ namespace EIS\Component\EIS\Administrator\Controller;
|
|||||||
\defined('_JEXEC') or die;
|
\defined('_JEXEC') or die;
|
||||||
|
|
||||||
use Joomla\CMS\Factory;
|
use Joomla\CMS\Factory;
|
||||||
|
use Joomla\CMS\Language\Text;
|
||||||
use Joomla\CMS\MVC\Controller\BaseController;
|
use Joomla\CMS\MVC\Controller\BaseController;
|
||||||
|
use Joomla\CMS\Router\Route;
|
||||||
|
use Joomla\CMS\Session\Session;
|
||||||
use Joomla\Database\DatabaseDriver;
|
use Joomla\Database\DatabaseDriver;
|
||||||
|
use EIS\Component\EIS\Administrator\Helper\SettingsHelper;
|
||||||
|
|
||||||
class DisplayController extends BaseController
|
class DisplayController extends BaseController
|
||||||
{
|
{
|
||||||
@@ -17,36 +21,39 @@ class DisplayController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function scan(): void
|
public function scan(): void
|
||||||
{
|
{
|
||||||
|
// CSRF prüfen (Form hat Token)
|
||||||
|
if (!Session::checkToken('post')) {
|
||||||
|
throw new \RuntimeException(Text::_('JINVALID_TOKEN'), 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$app = Factory::getApplication();
|
||||||
|
/** @var DatabaseDriver $db */
|
||||||
$db = Factory::getDbo();
|
$db = Factory::getDbo();
|
||||||
|
|
||||||
// Pfad aus Tabelle laden
|
// Pfad aus Settings laden (Key/Value); Default /var/www/pdf
|
||||||
$query = $db->getQuery(true)
|
$path = SettingsHelper::getSetting('document_root', '/var/www/pdf');
|
||||||
->select($db->quoteName('pdf_path'))
|
|
||||||
->from($db->quoteName('#__eis_settings'))
|
|
||||||
->order('id ASC')
|
|
||||||
->setLimit(1);
|
|
||||||
|
|
||||||
$db->setQuery($query);
|
|
||||||
$path = $db->loadResult();
|
|
||||||
|
|
||||||
if (!$path || !is_dir($path)) {
|
if (!$path || !is_dir($path)) {
|
||||||
Factory::getApplication()->enqueueMessage('Pfad ungültig oder nicht gesetzt: ' . $path, 'error');
|
$app->enqueueMessage(Text::sprintf('COM_EIS_MSG_PATH_NOT_EXISTS', $path) ?: ('Pfad ungültig oder nicht gesetzt: ' . $path), 'error');
|
||||||
$this->setRedirect('index.php?option=com_eis&view=main');
|
$this->setRedirect(Route::_('index.php?option=com_eis&view=main', false));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verzeichnis rekursiv scannen
|
// Verzeichnis rekursiv scannen
|
||||||
$data = $this->scanFolder($path);
|
$data = $this->scanFolder($path);
|
||||||
|
|
||||||
// Alte Einträge löschen
|
// Alte Einträge löschen (Hinweis: Dann sind ALLE eingefügten „neu“)
|
||||||
$db->truncateTable('#__eis_documents');
|
$db->truncateTable('#__eis_documents');
|
||||||
|
|
||||||
// In Datenbank speichern
|
// In Datenbank speichern und neue IDs sammeln
|
||||||
$this->saveToDb($data, null, $db);
|
$newIds = $this->saveToDb($data, null, $db);
|
||||||
|
|
||||||
|
// Neue IDs im UserState für die View -> virtueller Ordner "Neue Dokumente"
|
||||||
|
$app->setUserState('com_eis.new_ids', $newIds);
|
||||||
|
|
||||||
// Erfolgsmeldung
|
// Erfolgsmeldung
|
||||||
Factory::getApplication()->enqueueMessage('PDF-Struktur erfolgreich gespeichert.', 'message');
|
$app->enqueueMessage(Text::_('COM_EIS_MSG_SCAN_DONE') ?: 'PDF-Struktur erfolgreich gespeichert.', 'message');
|
||||||
$this->setRedirect('index.php?option=com_eis&view=main');
|
$this->setRedirect(Route::_('index.php?option=com_eis&view=main', false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,7 +66,12 @@ class DisplayController extends BaseController
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (scandir($dir) as $file) {
|
$entries = @scandir($dir);
|
||||||
|
if ($entries === false) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($entries as $file) {
|
||||||
if ($file === '.' || $file === '..') {
|
if ($file === '.' || $file === '..') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -78,18 +90,26 @@ class DisplayController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Alphabetisch stabil sortieren (Ordner/Dateien je Ebene)
|
||||||
|
usort($result, static function ($a, $b) {
|
||||||
|
return strcasecmp((string)$a['name'], (string)$b['name']);
|
||||||
|
});
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Struktur rekursiv in die Datenbank schreiben
|
* Struktur rekursiv in die Datenbank schreiben
|
||||||
|
* @return int[] Insert-IDs aller neu eingefügten Dateien (für „Neue Dokumente“)
|
||||||
*/
|
*/
|
||||||
private function saveToDb(array $items, ?int $parentId, DatabaseDriver $db): void
|
private function saveToDb(array $items, ?int $parentId, DatabaseDriver $db): array
|
||||||
{
|
{
|
||||||
|
$insertedFileIds = [];
|
||||||
|
|
||||||
foreach ($items as $item) {
|
foreach ($items as $item) {
|
||||||
$name = $db->quote($item['name']);
|
$name = $db->quote($item['name']);
|
||||||
$path = $db->quote($item['path'] ?? ''); // Leerer String statt NULL
|
$path = $db->quote($item['path'] ?? ''); // leer statt NULL
|
||||||
$parent = $parentId !== null ? (int) $parentId : 'NULL';
|
$parent = $parentId !== null ? (int)$parentId : 'NULL';
|
||||||
$isFolder = isset($item['children']) ? 1 : 0;
|
$isFolder = isset($item['children']) ? 1 : 0;
|
||||||
|
|
||||||
$query = $db->getQuery(true)
|
$query = $db->getQuery(true)
|
||||||
@@ -97,45 +117,55 @@ class DisplayController extends BaseController
|
|||||||
->columns(['name', 'path', 'parent_id', 'is_folder'])
|
->columns(['name', 'path', 'parent_id', 'is_folder'])
|
||||||
->values("$name, $path, $parent, $isFolder");
|
->values("$name, $path, $parent, $isFolder");
|
||||||
|
|
||||||
$db->setQuery($query);
|
$db->setQuery($query)->execute();
|
||||||
$db->execute();
|
|
||||||
|
|
||||||
$insertedId = $db->insertid();
|
$insertedId = (int)$db->insertid();
|
||||||
|
|
||||||
if ($isFolder && !empty($item['children'])) {
|
if ($isFolder && !empty($item['children'])) {
|
||||||
$this->saveToDb($item['children'], $insertedId, $db);
|
// Kinder speichern
|
||||||
|
$childIds = $this->saveToDb($item['children'], $insertedId, $db);
|
||||||
|
// Nur Datei-IDs sammeln
|
||||||
|
$insertedFileIds = array_merge($insertedFileIds, $childIds);
|
||||||
|
} else {
|
||||||
|
// Datei -> ID merken
|
||||||
|
$insertedFileIds[] = $insertedId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $insertedFileIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function rename(): void
|
public function rename(): void
|
||||||
{
|
{
|
||||||
// CSRF prüfen
|
// CSRF prüfen
|
||||||
\Joomla\CMS\Session\Session::checkToken() or jexit(\JText::_('JINVALID_TOKEN'));
|
if (!Session::checkToken('post')) {
|
||||||
|
throw new \RuntimeException(Text::_('JINVALID_TOKEN'), 403);
|
||||||
|
}
|
||||||
|
|
||||||
$app = \Joomla\CMS\Factory::getApplication();
|
$app = Factory::getApplication();
|
||||||
$id = (int) $app->input->get('id');
|
$id = (int) $app->input->post->get('id', 0);
|
||||||
$title = trim((string) $app->input->get('title', '', 'STRING'));
|
$title = trim((string) $app->input->post->get('title', '', 'string'));
|
||||||
|
|
||||||
if ($id <= 0) {
|
if ($id <= 0) {
|
||||||
$app->enqueueMessage('Ungültige ID', 'error');
|
$app->enqueueMessage(Text::_('JERROR_AN_ERROR_HAS_OCCURRED') ?: 'Ungültige ID', 'error');
|
||||||
$this->setRedirect('index.php?option=com_eis&view=main');
|
$this->setRedirect(Route::_('index.php?option=com_eis&view=main', false));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var \Joomla\Database\DatabaseDriver $db */
|
/** @var DatabaseDriver $db */
|
||||||
$db = \Joomla\CMS\Factory::getDbo();
|
$db = Factory::getDbo();
|
||||||
$query = $db->getQuery(true)
|
$query = $db->getQuery(true)
|
||||||
->update($db->quoteName('#__eis_documents'))
|
->update($db->quoteName('#__eis_documents'))
|
||||||
->set($db->quoteName('title') . ' = ' . ($title === '' ? 'NULL' : $db->quote($title)))
|
->set($db->quoteName('title') . ' = ' . ($title === '' ? 'NULL' : $db->quote($title)))
|
||||||
->where($db->quoteName('id') . ' = ' . (int) $id);
|
->where($db->quoteName('id') . ' = ' . (int)$id);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$db->setQuery($query)->execute();
|
$db->setQuery($query)->execute();
|
||||||
$app->enqueueMessage('Anzeigename gespeichert', 'message');
|
$app->enqueueMessage(Text::_('COM_EIS_MSG_SAVED_SUCCESS') ?: 'Anzeigename gespeichert', 'message');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
$app->enqueueMessage('Fehler beim Speichern: ' . $e->getMessage(), 'error');
|
$app->enqueueMessage((Text::_('COM_EIS_MSG_SAVED_ERROR') ?: 'Fehler beim Speichern: ') . $e->getMessage(), 'error');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->setRedirect('index.php?option=com_eis&view=main');
|
$this->setRedirect(Route::_('index.php?option=com_eis&view=main', false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
45
com_eis/administrator/src/Helper/SettingsHelper.php
Normal file
45
com_eis/administrator/src/Helper/SettingsHelper.php
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
namespace EIS\Component\EIS\Administrator\Helper;
|
||||||
|
|
||||||
|
\defined('_JEXEC') or die;
|
||||||
|
|
||||||
|
use Joomla\CMS\Factory;
|
||||||
|
|
||||||
|
final class SettingsHelper
|
||||||
|
{
|
||||||
|
public static function getSetting(string $param, $default = '')
|
||||||
|
{
|
||||||
|
$db = Factory::getDbo();
|
||||||
|
$q = $db->getQuery(true)
|
||||||
|
->select($db->quoteName('value'))
|
||||||
|
->from($db->quoteName('#__eis_settings'))
|
||||||
|
->where($db->quoteName('param') . ' = ' . $db->quote($param));
|
||||||
|
$db->setQuery($q);
|
||||||
|
$val = $db->loadResult();
|
||||||
|
|
||||||
|
return ($val !== null && $val !== '') ? $val : $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function setSetting(string $param, $value): void
|
||||||
|
{
|
||||||
|
$db = Factory::getDbo();
|
||||||
|
|
||||||
|
// Basis-INSERT per Query-Builder zusammenstellen …
|
||||||
|
$qb = $db->getQuery(true)
|
||||||
|
->insert($db->quoteName('#__eis_settings'))
|
||||||
|
->columns([$db->quoteName('param'), $db->quoteName('value'), $db->quoteName('modified')])
|
||||||
|
->values(
|
||||||
|
$db->quote($param) . ', ' .
|
||||||
|
$db->quote((string) $value) . ', ' .
|
||||||
|
$db->quote(date('Y-m-d H:i:s'))
|
||||||
|
);
|
||||||
|
|
||||||
|
// … und dann als String um "ON DUPLICATE KEY UPDATE" erweitern.
|
||||||
|
$sql = (string) $qb
|
||||||
|
. ' ON DUPLICATE KEY UPDATE '
|
||||||
|
. $db->quoteName('value') . ' = VALUES(' . $db->quoteName('value') . '), '
|
||||||
|
. $db->quoteName('modified') . ' = VALUES(' . $db->quoteName('modified') . ')';
|
||||||
|
|
||||||
|
$db->setQuery($sql)->execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ namespace EIS\Component\EIS\Administrator\Helper;
|
|||||||
\defined('_JEXEC') or die;
|
\defined('_JEXEC') or die;
|
||||||
|
|
||||||
use Joomla\CMS\Factory;
|
use Joomla\CMS\Factory;
|
||||||
|
use Joomla\CMS\Language\Text;
|
||||||
use Joomla\Database\DatabaseDriver;
|
use Joomla\Database\DatabaseDriver;
|
||||||
|
|
||||||
class TreeHelper
|
class TreeHelper
|
||||||
@@ -30,12 +31,46 @@ class TreeHelper
|
|||||||
|
|
||||||
// alphabetisch nach name
|
// alphabetisch nach name
|
||||||
foreach ($grouped as &$group) {
|
foreach ($grouped as &$group) {
|
||||||
usort($group, fn($a, $b) => strcasecmp($a['name'], $b['name']));
|
usort($group, static fn($a, $b) => strcasecmp((string)$a['name'], (string)$b['name']));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $grouped;
|
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) */
|
/** Baum rendern (nutzt title als alternativen Anzeigenamen) */
|
||||||
public static function renderTree(array $items, ?int $parentId = null): string
|
public static function renderTree(array $items, ?int $parentId = null): string
|
||||||
{
|
{
|
||||||
@@ -46,11 +81,12 @@ class TreeHelper
|
|||||||
$html = '<ul class="pdf-tree">';
|
$html = '<ul class="pdf-tree">';
|
||||||
|
|
||||||
foreach ($items[$parentId] as $item) {
|
foreach ($items[$parentId] as $item) {
|
||||||
$isFolder = (bool) $item['is_folder'];
|
$isFolder = !empty($item['is_folder']);
|
||||||
$rawName = $item['title'] ?: $item['name'];
|
$rawName = (string)($item['title'] ?? '') !== '' ? (string)$item['title'] : (string)$item['name'];
|
||||||
$display = preg_replace('/\.pdf$/i', '', (string) $rawName);
|
$display = preg_replace('/\.pdf$/i', '', $rawName);
|
||||||
$display = htmlspecialchars($display, ENT_QUOTES, 'UTF-8');
|
$display = htmlspecialchars((string)$display, ENT_QUOTES, 'UTF-8');
|
||||||
$id = (int) $item['id'];
|
$id = (int)$item['id'];
|
||||||
|
|
||||||
if ($isFolder) {
|
if ($isFolder) {
|
||||||
$fileCount = self::countFilesRecursive($items, $id);
|
$fileCount = self::countFilesRecursive($items, $id);
|
||||||
|
|
||||||
@@ -58,27 +94,14 @@ class TreeHelper
|
|||||||
. ' data-id="' . $id . '"'
|
. ' data-id="' . $id . '"'
|
||||||
. ' data-title="' . htmlspecialchars((string)($item['title'] ?? ''), ENT_QUOTES, 'UTF-8') . '"'
|
. ' data-title="' . htmlspecialchars((string)($item['title'] ?? ''), ENT_QUOTES, 'UTF-8') . '"'
|
||||||
. ' data-name="' . htmlspecialchars((string)$item['name'], ENT_QUOTES, 'UTF-8') . '"'
|
. ' data-name="' . htmlspecialchars((string)$item['name'], ENT_QUOTES, 'UTF-8') . '"'
|
||||||
. '>';
|
. ' data-count="' . (int)$fileCount . '"'
|
||||||
$html .= '<span class="toggle" role="button" aria-label="Ordner umschalten" tabindex="0">▶</span> ';
|
. '>'
|
||||||
$html .= '<span class="folder-label">📁 ' . $display . ' <small class="count">(' . (int)$fileCount . ')</small></span>';
|
. '<span class="toggle" role="button" aria-label="Ordner umschalten" tabindex="0">▶</span> '
|
||||||
$html .= self::renderTree($items, $id);
|
. '<span class="folder-label">📁 ' . $display . ' <small class="count">(' . (int)$fileCount . ')</small></span>'
|
||||||
$html .= '</li>';
|
. self::renderTree($items, $id)
|
||||||
|
. '</li>';
|
||||||
} else {
|
} else {
|
||||||
$sizeStr = '';
|
$html .= self::renderSingleFileLi($item, $display);
|
||||||
if (!empty($item['path']) && is_file($item['path'])) {
|
|
||||||
$size = @filesize($item['path']);
|
|
||||||
if ($size !== false) {
|
|
||||||
$sizeStr = ' <small class="meta">(' . self::formatFileSize((int) $size) . ')</small>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$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') . '"'
|
|
||||||
. '>';
|
|
||||||
$html .= '<span class="file-label">📄 ' . $display . $sizeStr . '</span>';
|
|
||||||
$html .= '</li>';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +109,64 @@ class TreeHelper
|
|||||||
return $html;
|
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
|
private static function countFilesRecursive(array $items, int $parentId): int
|
||||||
{
|
{
|
||||||
$count = 0;
|
$count = 0;
|
||||||
@@ -93,7 +174,7 @@ class TreeHelper
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
foreach ($items[$parentId] as $item) {
|
foreach ($items[$parentId] as $item) {
|
||||||
if ((bool) $item['is_folder']) {
|
if (!empty($item['is_folder'])) {
|
||||||
$count += self::countFilesRecursive($items, (int)$item['id']);
|
$count += self::countFilesRecursive($items, (int)$item['id']);
|
||||||
} else {
|
} else {
|
||||||
$count++;
|
$count++;
|
||||||
|
|||||||
@@ -4,29 +4,20 @@ namespace EIS\Component\EIS\Administrator\View\Config;
|
|||||||
\defined('_JEXEC') or die;
|
\defined('_JEXEC') or die;
|
||||||
|
|
||||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||||
use Joomla\CMS\Factory;
|
use EIS\Component\EIS\Administrator\Helper\SettingsHelper;
|
||||||
|
|
||||||
class HtmlView extends BaseHtmlView
|
class HtmlView extends BaseHtmlView
|
||||||
{
|
{
|
||||||
protected $form;
|
protected $pdfPath = '';
|
||||||
protected $item;
|
|
||||||
|
|
||||||
public function display($tpl = null): void
|
public function display($tpl = null): void
|
||||||
{
|
{
|
||||||
$db = Factory::getDbo();
|
$this->pdfPath = SettingsHelper::getSetting('document_root', '/var/www/pdf');
|
||||||
$query = $db->getQuery(true)
|
|
||||||
->select('*')
|
|
||||||
->from($db->quoteName('#__eis_settings'))
|
|
||||||
->setLimit(1);
|
|
||||||
|
|
||||||
$db->setQuery($query);
|
|
||||||
$this->item = $db->loadAssoc();
|
|
||||||
|
|
||||||
parent::display($tpl);
|
parent::display($tpl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getItem()
|
public function getPdfPath(): string
|
||||||
{
|
{
|
||||||
return $this->item;
|
return (string)$this->pdfPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,41 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace EIS\Component\EIS\Administrator\View\Main;
|
namespace EIS\Component\EIS\Administrator\View\Main;
|
||||||
|
|
||||||
\defined('_JEXEC') or die;
|
\defined('_JEXEC') or die;
|
||||||
|
|
||||||
|
use Joomla\CMS\Factory;
|
||||||
|
use Joomla\CMS\Language\Text;
|
||||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||||
use EIS\Component\EIS\Administrator\Helper\TreeHelper;
|
use EIS\Component\EIS\Administrator\Helper\TreeHelper;
|
||||||
|
|
||||||
class HtmlView extends BaseHtmlView
|
class HtmlView extends BaseHtmlView
|
||||||
{
|
{
|
||||||
|
/** @var string HTML des Baums (inkl. virtuellem Ordner „Neue Dokumente“, falls vorhanden) */
|
||||||
|
protected $treeHtml = '';
|
||||||
|
|
||||||
public function display($tpl = null): void
|
public function display($tpl = null): void
|
||||||
{
|
{
|
||||||
// Baumdaten laden und fürs Template bereitstellen
|
$app = Factory::getApplication();
|
||||||
$items = TreeHelper::getItems();
|
|
||||||
$this->treeHtml = TreeHelper::renderTree($items);
|
|
||||||
|
|
||||||
|
// Daten für den Baum holen
|
||||||
|
$items = TreeHelper::getItems();
|
||||||
|
|
||||||
|
// Neu hinzugekommene IDs aus dem letzten Scan (können leer sein)
|
||||||
|
$newIds = (array) $app->getUserState('com_eis.new_ids', []);
|
||||||
|
|
||||||
|
// Baum rendern (virtueller Ordner „Neue Dokumente“ + normaler Baum)
|
||||||
|
$this->treeHtml = TreeHelper::renderTreeWithNew($items, $newIds);
|
||||||
|
|
||||||
|
// Template rendern
|
||||||
parent::display($tpl);
|
parent::display($tpl);
|
||||||
|
|
||||||
|
// Optional: nur einmal anzeigen -> State leeren
|
||||||
|
$app->setUserState('com_eis.new_ids', []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Ermöglicht im Template: $this->treeHtml */
|
||||||
|
public function getTreeHtml(): string
|
||||||
|
{
|
||||||
|
return (string) $this->treeHtml;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
com_eis/administrator/tmpl/.DS_Store
vendored
BIN
com_eis/administrator/tmpl/.DS_Store
vendored
Binary file not shown.
@@ -1,38 +1,72 @@
|
|||||||
<?php defined('_JEXEC') or die;
|
<?php
|
||||||
|
\defined('_JEXEC') or die;
|
||||||
|
|
||||||
use Joomla\CMS\Language\Text;
|
use Joomla\CMS\Language\Text;
|
||||||
use Joomla\CMS\Router\Route;
|
use Joomla\CMS\Router\Route;
|
||||||
use Joomla\CMS\HTML\HTMLHelper;
|
use Joomla\CMS\HTML\HTMLHelper;
|
||||||
use Joomla\CMS\Session\Session;
|
|
||||||
|
|
||||||
$item = $this->getItem();
|
// Wert aus der View (HtmlView::getPdfPath()), Fallback leer
|
||||||
$pdfPath = $item['pdf_path'] ?? '';
|
$pdfPath = method_exists($this, 'getPdfPath') ? (string) $this->getPdfPath() : '';
|
||||||
?>
|
?>
|
||||||
|
<h2 class="mb-3">
|
||||||
|
<?php echo Text::_('COM_EIS_SETTINGS_TITLE') ?: 'Einstellungen'; ?>
|
||||||
|
</h2>
|
||||||
|
|
||||||
<h2><?php echo Text::_('COM_EIS_CONFIG_TITLE'); ?></h2>
|
<form action="<?php echo Route::_('index.php?option=com_eis&task=config.save'); ?>"
|
||||||
|
method="post"
|
||||||
<form action="<?php echo Route::_('index.php?option=com_eis&task=config.save'); ?>" method="post" name="adminForm" id="adminForm">
|
name="adminForm"
|
||||||
|
id="adminForm"
|
||||||
|
novalidate>
|
||||||
<div class="form-horizontal">
|
<div class="form-horizontal">
|
||||||
<fieldset class="adminform">
|
<fieldset class="adminform">
|
||||||
<legend><?php echo Text::_('COM_EIS_FIELDSET_SETTINGS'); ?></legend>
|
<legend><?php echo Text::_('COM_EIS_FIELDSET_GENERAL') ?: 'Allgemein'; ?></legend>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="pdf_path">
|
<label class="control-label" for="document_root">
|
||||||
<?php echo Text::_('COM_EIS_FIELD_PDF_PATH'); ?>
|
<?php echo Text::_('COM_EIS_FIELD_DOCUMENT_ROOT_LABEL') ?: 'Basis-Verzeichnis für PDFs'; ?>
|
||||||
</label>
|
</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" name="pdf_path" id="pdf_path" value="<?php echo htmlspecialchars($pdfPath, ENT_QUOTES); ?>" size="60" />
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
name="document_root"
|
||||||
|
id="document_root"
|
||||||
|
value="<?php echo htmlspecialchars($pdfPath, ENT_QUOTES, 'UTF-8'); ?>"
|
||||||
|
placeholder="/var/www/pdf"
|
||||||
|
size="60"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<p class="help-block" style="margin-top:.35rem;">
|
||||||
|
<?php echo Text::_('COM_EIS_FIELD_DOCUMENT_ROOT_DESC')
|
||||||
|
?: 'Absoluter Serverpfad, in dem die PDF-Dateien liegen (z. B. /var/www/pdf).'; ?>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="mt-2">
|
||||||
<button type="submit" class="btn btn-primary">
|
<button type="submit" class="btn btn-primary">
|
||||||
<?php echo Text::_('JSAVE'); ?>
|
<?php echo Text::_('JSAVE') ?: 'Speichern'; ?>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php echo HTMLHelper::_('form.token'); ?>
|
<?php echo HTMLHelper::_('form.token'); ?>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
const form = document.getElementById('adminForm');
|
||||||
|
if (!form) return;
|
||||||
|
|
||||||
|
form.addEventListener('submit', function (e) {
|
||||||
|
const input = document.getElementById('document_root');
|
||||||
|
if (!input || !input.value.trim()) {
|
||||||
|
e.preventDefault();
|
||||||
|
alert('<?php echo Text::_('COM_EIS_MSG_INVALID_PATH') ?: 'Bitte einen gültigen Pfad angeben.'; ?>');
|
||||||
|
input?.focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -4,114 +4,58 @@
|
|||||||
use Joomla\CMS\HTML\HTMLHelper;
|
use Joomla\CMS\HTML\HTMLHelper;
|
||||||
use Joomla\CMS\Router\Route;
|
use Joomla\CMS\Router\Route;
|
||||||
use Joomla\CMS\Language\Text;
|
use Joomla\CMS\Language\Text;
|
||||||
|
|
||||||
|
$hasTree = !empty($this->treeHtml);
|
||||||
?>
|
?>
|
||||||
|
<style>
|
||||||
|
/* Layout */
|
||||||
|
.eis-flex{display:flex;gap:1rem;align-items:flex-start}
|
||||||
|
.eis-tree-wrap{flex:1 1 auto;background:#f9f9f9;border:1px solid #ddd;border-radius:6px;padding:1em}
|
||||||
|
.eis-edit{flex:0 0 360px;background:#fff;border:1px solid #ddd;border-radius:6px;padding:1em}
|
||||||
|
.eis-edit h4{margin:.2rem 0 1rem}
|
||||||
|
|
||||||
|
/* Baum */
|
||||||
|
.pdf-tree{list-style:none;margin:0;padding:0}
|
||||||
|
.pdf-tree ul{list-style:none;margin-left:1.25em;padding:0;display:none}
|
||||||
|
.pdf-tree li{margin:.35em 0}
|
||||||
|
.folder>.toggle{cursor:pointer;width:1.25em;display:inline-block;user-select:none}
|
||||||
|
.folder>.folder-label,.file>.file-label{cursor:pointer;user-select:none}
|
||||||
|
.pdf-tree .meta{color:#666}
|
||||||
|
.pdf-tree .count{color:#999}
|
||||||
|
.pdf-tree .is-selected{background:rgba(0,0,0,.06);border-radius:3px}
|
||||||
|
|
||||||
|
/* Steuerleiste */
|
||||||
|
.controls{margin-bottom:.75em}
|
||||||
|
.controls button{margin-right:.5em}
|
||||||
|
|
||||||
|
/* Form */
|
||||||
|
.control-group{margin-bottom:.6rem}
|
||||||
|
.form-help{color:#666;font-size:.9em}
|
||||||
|
</style>
|
||||||
|
|
||||||
<!-- Scan-Formular -->
|
<!-- Scan-Formular -->
|
||||||
<form action="<?php echo Route::_('index.php?option=com_eis&task=display.scan'); ?>" method="post" name="adminForm" id="adminForm">
|
<form action="<?php echo Route::_('index.php?option=com_eis&task=display.scan'); ?>" method="post" id="eis-scan-form">
|
||||||
<div class="form-horizontal">
|
|
||||||
<fieldset class="adminform">
|
<fieldset class="adminform">
|
||||||
<legend><?php echo Text::_('COM_EIS_DOCUMENT_PATH'); ?></legend>
|
<legend><?php echo Text::_('COM_EIS_DOCUMENT_PATH'); ?></legend>
|
||||||
<!-- Optional: Hier später Pfad aus Einstellungen anzeigen -->
|
<div class="form-help"><?php echo Text::_('COM_EIS_SETTINGS_TITLE'); ?> · <?php echo Text::_('COM_EIS_FIELD_DOCUMENT_ROOT_LABEL'); ?></div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<button class="btn btn-primary" type="submit">
|
<button class="btn btn-primary" type="submit">
|
||||||
<?php echo Text::_('COM_EIS_SCAN_DOCUMENTS'); ?>
|
<?php echo Text::_('COM_EIS_SCAN_DOCUMENTS'); ?>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<?php echo HTMLHelper::_('form.token'); ?>
|
<?php echo HTMLHelper::_('form.token'); ?>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<?php $hasTree = !empty($this->treeHtml); ?>
|
|
||||||
|
|
||||||
<?php if (!$hasTree): ?>
|
<?php if (!$hasTree): ?>
|
||||||
<p class="text-muted">
|
<p class="text-muted">
|
||||||
<?php echo Text::_('COM_EIS_NO_DOCUMENTS_FOUND') ?: 'Noch keine Dokumente in der Datenbank. Bitte zuerst „Dokumente einlesen“ ausführen.'; ?>
|
<?php echo Text::_('COM_EIS_NO_DOCUMENTS_FOUND'); ?>
|
||||||
</p>
|
</p>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
|
|
||||||
<style>
|
<h3 class="mt-3"><?php echo Text::_('COM_EIS_PDF_TREE'); ?></h3>
|
||||||
/* Layout */
|
|
||||||
.eis-flex {
|
|
||||||
display: flex;
|
|
||||||
gap: 1rem;
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.eis-tree-wrap {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
background: #f9f9f9;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
border-radius: 6px;
|
|
||||||
padding: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.eis-edit {
|
|
||||||
flex: 0 0 360px;
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
border-radius: 6px;
|
|
||||||
padding: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.eis-edit h4 {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Baum */
|
|
||||||
.pdf-tree {
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pdf-tree ul {
|
|
||||||
list-style: none;
|
|
||||||
margin-left: 1.5em;
|
|
||||||
padding: 0;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unterebenen eingeklappt */
|
|
||||||
.pdf-tree li {
|
|
||||||
margin: .3em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.folder>.toggle {
|
|
||||||
cursor: pointer;
|
|
||||||
width: 1em;
|
|
||||||
display: inline-block;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.folder>.folder-label,
|
|
||||||
.file>.file-label {
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pdf-tree .meta {
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pdf-tree .count {
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Steuerleiste */
|
|
||||||
.controls {
|
|
||||||
margin-bottom: .75em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.controls button {
|
|
||||||
margin-right: .5em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<h3 class="mt-3"><?php echo Text::_('COM_EIS_PDF_TREE') ?: 'PDF-Baum'; ?></h3>
|
|
||||||
|
|
||||||
<div class="eis-flex">
|
<div class="eis-flex">
|
||||||
|
|
||||||
@@ -119,14 +63,14 @@ use Joomla\CMS\Language\Text;
|
|||||||
<div class="eis-tree-wrap">
|
<div class="eis-tree-wrap">
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<button id="eis-expand-all" type="button" class="btn btn-sm btn-secondary">
|
<button id="eis-expand-all" type="button" class="btn btn-sm btn-secondary">
|
||||||
<?php echo Text::_('JGLOBAL_EXPAND_ALL') ?: 'Ausklappen'; ?>
|
<?php echo Text::_('COM_EIS_EXPAND_ALL'); ?>
|
||||||
</button>
|
</button>
|
||||||
<button id="eis-collapse-all" type="button" class="btn btn-sm btn-secondary">
|
<button id="eis-collapse-all" type="button" class="btn btn-sm btn-secondary">
|
||||||
<?php echo Text::_('JGLOBAL_COLLAPSE_ALL') ?: 'Einklappen'; ?>
|
<?php echo Text::_('COM_EIS_COLLAPSE_ALL'); ?>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tree">
|
<div class="tree" id="eis-tree" role="tree" aria-label="<?php echo Text::_('COM_EIS_PDF_TREE'); ?>">
|
||||||
<?php echo $this->treeHtml; ?>
|
<?php echo $this->treeHtml; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -134,24 +78,27 @@ use Joomla\CMS\Language\Text;
|
|||||||
<!-- Rechte Seite: Inline-Bearbeitungsformular -->
|
<!-- Rechte Seite: Inline-Bearbeitungsformular -->
|
||||||
<div class="eis-edit">
|
<div class="eis-edit">
|
||||||
<h4><?php echo Text::_('COM_EIS_EDIT_TITLE') ?: 'Anzeigename bearbeiten'; ?></h4>
|
<h4><?php echo Text::_('COM_EIS_EDIT_TITLE') ?: 'Anzeigename bearbeiten'; ?></h4>
|
||||||
<form action="<?php echo Route::_('index.php?option=com_eis&task=display.rename'); ?>" method="post" id="eis-rename-form">
|
|
||||||
|
<form action="<?php echo Route::_('index.php?option=com_eis&task=display.rename'); ?>" method="post" id="eis-rename-form" novalidate>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label for="eis-current-name"><?php echo Text::_('COM_EIS_FIELD_NAME') ?: 'Originalname'; ?></label>
|
<label for="eis-current-name"><?php echo Text::_('COM_EIS_FIELD_NAME') ?: 'Originalname'; ?></label>
|
||||||
<input type="text" id="eis-current-name" class="form-control" value="" readonly>
|
<input type="text" id="eis-current-name" class="form-control" value="" readonly>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group" style="margin-top:.5rem;">
|
<div class="control-group">
|
||||||
<label for="eis-title"><?php echo Text::_('COM_EIS_FIELD_TITLE') ?: 'Anzeigename (optional)'; ?></label>
|
<label for="eis-title"><?php echo Text::_('COM_EIS_FIELD_TITLE') ?: 'Anzeigename (optional)'; ?></label>
|
||||||
<input type="text" name="title" id="eis-title" class="form-control" value="" placeholder="<?php echo Text::_('COM_EIS_PLACEHOLDER_TITLE') ?: 'Leer lassen = automatisch aus Dateiname'; ?>">
|
<input type="text" name="title" id="eis-title" class="form-control" value=""
|
||||||
|
placeholder="<?php echo Text::_('COM_EIS_PLACEHOLDER_TITLE') ?: 'Leer lassen = automatisch aus Dateiname'; ?>">
|
||||||
|
<div class="form-help"><?php echo Text::_('COM_EIS_FILESIZE'); ?>: <span id="eis-filesize">–</span></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="hidden" name="id" id="eis-id" value="">
|
<input type="hidden" name="id" id="eis-id" value="">
|
||||||
|
|
||||||
<div style="margin-top:.75rem;">
|
<div class="mt-2">
|
||||||
<button type="submit" class="btn btn-success">
|
<button type="submit" class="btn btn-success" id="eis-save" disabled>
|
||||||
<?php echo Text::_('JSAVE') ?: 'Speichern'; ?>
|
<?php echo Text::_('JSAVE'); ?>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" id="eis-clear-title" class="btn btn-light">
|
<button type="button" id="eis-clear-title" class="btn btn-light" disabled>
|
||||||
<?php echo Text::_('JDEFAULT') ?: 'Zurücksetzen'; ?>
|
<?php echo Text::_('JDEFAULT') ?: 'Zurücksetzen'; ?>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -162,64 +109,76 @@ use Joomla\CMS\Language\Text;
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
const wrap = document.querySelector('.eis-tree-wrap');
|
const tree = document.getElementById('eis-tree');
|
||||||
const form = document.getElementById('eis-rename-form');
|
const form = document.getElementById('eis-rename-form');
|
||||||
const idField = document.getElementById('eis-id');
|
const idFld = document.getElementById('eis-id');
|
||||||
const nameField = document.getElementById('eis-current-name');
|
const nameFld = document.getElementById('eis-current-name');
|
||||||
const titleField = document.getElementById('eis-title');
|
const titleFld= document.getElementById('eis-title');
|
||||||
const clearBtn = document.getElementById('eis-clear-title');
|
const sizeOut = document.getElementById('eis-filesize');
|
||||||
|
const btnSave = document.getElementById('eis-save');
|
||||||
|
const btnClr = document.getElementById('eis-clear-title');
|
||||||
|
|
||||||
if (!wrap || !form) return;
|
if (!tree || !form) return;
|
||||||
|
|
||||||
// Einzelnes Toggle: Caret ODER Label
|
let lastSelected;
|
||||||
wrap.addEventListener('click', (e) => {
|
|
||||||
|
// Toggle (Caret) & Auswahl
|
||||||
|
tree.addEventListener('click', (e) => {
|
||||||
const t = e.target;
|
const t = e.target;
|
||||||
|
|
||||||
// Toggle (Caret oder Label für Ordner)
|
// Ein-/Ausklappen
|
||||||
if (t.classList.contains('toggle') || t.classList.contains('folder-label')) {
|
if (t.classList.contains('toggle') || t.classList.contains('folder-label')) {
|
||||||
const li = t.closest('li.folder');
|
const li = t.closest('li.folder');
|
||||||
if (li) {
|
if (li) {
|
||||||
// direkte Kind-UL finden
|
const childUl = li.querySelector(':scope > ul');
|
||||||
let childUl = null;
|
|
||||||
for (const el of li.children) {
|
|
||||||
if (el.tagName === 'UL') {
|
|
||||||
childUl = el;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (childUl) {
|
if (childUl) {
|
||||||
const open = childUl.style.display === 'block';
|
const open = childUl.style.display === 'block';
|
||||||
childUl.style.display = open ? 'none' : 'block';
|
childUl.style.display = open ? 'none' : 'block';
|
||||||
const caret = li.querySelector(':scope > .toggle') || li.querySelector('.toggle');
|
const caret = li.querySelector(':scope > .toggle');
|
||||||
if (caret) caret.textContent = open ? '▶' : '▼';
|
if (caret) caret.textContent = open ? '▶' : '▼';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auswahl fürs Bearbeiten: Klick auf Ordner- oder Datei-Label
|
// Auswahl für Bearbeitung (Ordner- oder Datei-Label)
|
||||||
if (t.classList.contains('folder-label') || t.classList.contains('file-label')) {
|
if (t.classList.contains('folder-label') || t.classList.contains('file-label')) {
|
||||||
const li = t.closest('li');
|
const li = t.closest('li');
|
||||||
if (!li) return;
|
if (!li) return;
|
||||||
|
|
||||||
|
// Visuelles Highlight
|
||||||
|
if (lastSelected) lastSelected.classList.remove('is-selected');
|
||||||
|
t.classList.add('is-selected');
|
||||||
|
lastSelected = t;
|
||||||
|
|
||||||
|
// Daten aus data-Attributen (TreeHelper muss sie setzen)
|
||||||
const id = li.getAttribute('data-id') || '';
|
const id = li.getAttribute('data-id') || '';
|
||||||
const title = li.getAttribute('data-title') || '';
|
const title = li.getAttribute('data-title') || '';
|
||||||
const name = li.getAttribute('data-name') || '';
|
const name = li.getAttribute('data-name') || '';
|
||||||
|
const size = li.getAttribute('data-size') || ''; // optional
|
||||||
|
|
||||||
idField.value = id;
|
|
||||||
nameField.value = name;
|
idFld.value = id;
|
||||||
titleField.value = title;
|
nameFld.value = name;
|
||||||
titleField.focus();
|
titleFld.value= title;
|
||||||
|
sizeOut.textContent = size || '–';
|
||||||
|
|
||||||
|
// Buttons ermöglichen
|
||||||
|
btnSave.disabled = !id;
|
||||||
|
btnClr.disabled = !id;
|
||||||
|
|
||||||
|
// Fokus ins Titel-Feld
|
||||||
|
titleFld.focus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// "Zurücksetzen" = Anzeigename löschen (fällt auf Dateiname zurück)
|
// „Zurücksetzen“ = Titel leeren
|
||||||
clearBtn?.addEventListener('click', () => {
|
btnClr?.addEventListener('click', () => {
|
||||||
titleField.value = '';
|
titleFld.value = '';
|
||||||
titleField.focus();
|
titleFld.focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Global: Alle aus-/einklappen
|
// Global: Aus-/Einklappen
|
||||||
document.getElementById('eis-expand-all')?.addEventListener('click', () => {
|
document.getElementById('eis-expand-all')?.addEventListener('click', () => {
|
||||||
document.querySelectorAll('.pdf-tree ul').forEach(ul => ul.style.display = 'block');
|
document.querySelectorAll('.pdf-tree ul').forEach(ul => ul.style.display = 'block');
|
||||||
document.querySelectorAll('.pdf-tree .toggle').forEach(t => t.textContent = '▼');
|
document.querySelectorAll('.pdf-tree .toggle').forEach(t => t.textContent = '▼');
|
||||||
|
|||||||
Reference in New Issue
Block a user