erste Lauffähige Fassung

This commit is contained in:
Thomas Spohr
2025-07-29 10:33:26 +02:00
parent af2ebf4ab6
commit a481866b66
26 changed files with 500 additions and 76619 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -1,4 +0,0 @@
# EIS
Joomla-Modul für die Ansicht von PDF's
Das kommt alles noch

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +0,0 @@
#pdfexplorer {
padding: 1em;
background: #f8f9fa;
border-radius: 8px;
min-height: 50px;
font-family: sans-serif;
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

58353
assets/js/pdf.worker.js vendored

File diff suppressed because one or more lines are too long

36
com_eis/eis.xml Normal file
View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<extension type="component" method="install">
<!-- Database table for PDF entries -->
<install>
<sql>
<file driver="mysql" charset="utf8mb4">sql/install/mysql/install.mysql.sql</file>
</sql>
</install>
<name>com_eis</name>
<creationDate>2025-07-23</creationDate>
<author>Thomas Spohr powert by OpenAI</author>
<version>1.0.0</version>
<description>EIS Minimal-Komponente</description>
<namespace path="src">EIS\Component\EIS</namespace>
<administration>
<menu img="class:eis">COM_EIS_MENU</menu>
<submenu>
<menu link="option=com_eis&amp;view=main" img="class:eis-main" alt="EIS/Main">
COM_EIS_MAIN</menu>
</submenu>
<files client="administrator">
<folder>sql</folder>
<folder>src</folder>
<folder>tmpl</folder>
<folder>language</folder>
<folder>services</folder>
</files>
<languages folder="language/en-GB">
<language tag="en-GB">en-GB.com_eis.ini</language>
<language tag="en-GB">en-GB.com_eis.sys.ini</language>
</languages>
</administration>
</extension>

View File

@@ -0,0 +1,8 @@
COM_EIS_DOCUMENT_PATH="Dokumentenpfad"
COM_EIS_DOCUMENT_PATH_LABEL="Pfad zu den PDF-Dokumenten"
COM_EIS_SCAN_DOCUMENTS="Dokumente einlesen"
COM_EIS_MAIN="EIS Hauptansicht"
COM_EIS_MENU="EIS"
COM_EIS_SETTINGS="Einstellungen"
COM_EIS_MAINTENANCE="Wartung"

View File

@@ -0,0 +1 @@
COM_EIS="EIS Komponente"

View File

@@ -0,0 +1,30 @@
<?php
namespace EIS\Component\EIS;
\defined('_JEXEC') or die;
use Joomla\CMS\Extension\Service\Provider\ComponentDispatcherFactory;
use Joomla\CMS\Extension\Service\Provider\MVCFactory;
use Joomla\CMS\Extension\Service\Provider\RouterFactory;
use Joomla\CMS\Extension\ComponentInterface;
use Joomla\CMS\Extension\MVCComponent;
use Joomla\CMS\Dispatcher\ComponentDispatcherFactoryInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
return new class implements ServiceProviderInterface
{
public function register(Container $container): void
{
$container->registerServiceProvider(new ComponentDispatcherFactory('\\EIS\\Component\\EIS'));
$container->registerServiceProvider(new MVCFactory('\\EIS\\Component\\EIS'));
$container->registerServiceProvider(new RouterFactory('\\EIS\\Component\\EIS'));
$container->set(
ComponentInterface::class,
static fn(Container $c) => new MVCComponent(
$c->get(ComponentDispatcherFactoryInterface::class)
)
);
}
};

View File

@@ -0,0 +1,8 @@
CREATE TABLE IF NOT EXISTS `#__eis_documents` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`path` TEXT NOT NULL,
`parent_id` INT UNSIGNED DEFAULT NULL,
`is_folder` TINYINT(1) DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@@ -0,0 +1,82 @@
<?php
namespace EIS\Component\EIS\Administrator\Controller;
\defined('_JEXEC') or die;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\Factory;
class DisplayController extends BaseController
{
protected $default_view = 'main';
/**
* Endpoint to generate JSON of PDF directory tree
*/
public function scan(): void
{
$input = Factory::getApplication()->input;
// Default to PDF folder if no path provided
$defaultPath = JPATH_ROOT . DIRECTORY_SEPARATOR . 'pdf';
$path = $input->getString('path', $defaultPath);
$data = $this->scanFolder($path);
// Encode JSON
$json = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
// Determine output file path
$outputFile = JPATH_ROOT . DIRECTORY_SEPARATOR . 'media' . DIRECTORY_SEPARATOR . 'com_eis' . DIRECTORY_SEPARATOR . 'documents.json';
// Ensure directory exists
$dir = dirname($outputFile);
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
}
// Write JSON to file
file_put_contents($outputFile, $json);
// Provide feedback and redirect
Factory::getApplication()
->enqueueMessage('JSON file saved to ' . $outputFile, 'message');
// Ausgabe auch im Bachkend
Factory::getApplication()->setUserState('com_eis.pdfdata', $data);
$this->setRedirect('index.php?option=com_eis&view=main');
}
/**
* Recursively scans a directory and returns an array structure
* with names and absolute paths for PDF files.
*
* @param string $dir Absolute filesystem path
* @return array Structure: [ ['name'=>'FolderName','children'=>[...] ], ['name'=>'file.pdf','path'=>'/abs/path/file.pdf'] ]
*/
private function scanFolder(string $dir): array
{
$result = [];
if (!is_dir($dir)) {
return $result;
}
foreach (scandir($dir) as $file) {
if ($file === '.' || $file === '..') {
continue;
}
$fullPath = $dir . DIRECTORY_SEPARATOR . $file;
if (is_dir($fullPath)) {
// Directory: include name and children
$result[] = [
'name' => $file,
'children' => $this->scanFolder($fullPath)
];
} elseif (is_file($fullPath) && strtolower(pathinfo($file, PATHINFO_EXTENSION)) === 'pdf') {
// File: include name and absolute path
$result[] = [
'name' => $file,
'path' => $fullPath
];
}
}
return $result;
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace EIS\Component\EIS\Administrator\Extension;
\defined('_JEXEC') or die;
use Joomla\CMS\Extension\MVCComponent;
final class EISComponent extends MVCComponent
{
}

View File

@@ -0,0 +1,16 @@
<?php
namespace EIS\Component\EIS\Administrator\View\Main;
\defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
class HtmlView extends BaseHtmlView
{
public function display($tpl = null): void
{
echo "<h2>Willkommen bei EIS</h2>";
$this->data = Factory::getApplication()->getUserState('com_eis.pdfdata');
parent::display($tpl);
}
}

View File

@@ -0,0 +1,48 @@
<?php
\defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Session\Session;
?>
<form action="<?php echo Route::_('index.php?option=com_eis&task=display.scan'); ?>" method="post" name="adminForm" id="adminForm">
<div class="form-horizontal">
<fieldset class="adminform">
<legend><?php echo Text::_('COM_EIS_DOCUMENT_PATH'); ?></legend>
<div class="control-group">
<label class="control-label" for="docpath"><?php echo Text::_('COM_EIS_DOCUMENT_PATH_LABEL'); ?></label>
<div class="controls">
<input type="text" name="docpath" id="docpath" size="60" value="/var/www/vhosts/ts-it24.net/stbv.ts-it24.net/pdf/" />
</div>
</div>
</fieldset>
<div>
<button class="btn btn-primary" type="submit"><?php echo Text::_('COM_EIS_SCAN_DOCUMENTS'); ?></button>
</div>
</div>
<?php echo HTMLHelper::_('form.token'); ?>
</form>
<?php if (!empty($this->data)) : ?>
<hr>
<h3><?php echo Text::_('COM_EIS_PDF_TREE'); ?></h3>
<ul>
<?php echo renderTree($this->data); ?>
</ul>
<?php endif; ?>
<?php
function renderTree($items)
{
$html = '';
foreach ($items as $item) {
if (isset($item['children'])) {
$html .= '<li><strong>' . htmlspecialchars($item['name']) . '</strong><ul>' . renderTree($item['children']) . '</ul></li>';
} else {
$html .= '<li>' . htmlspecialchars($item['name']) . '</li>';
}
}
return $html;
}
?>

View File

@@ -1,9 +0,0 @@
<?php
// Keine direkten Zugriffe erlauben
defined('_JEXEC') or die;
// Placeholder für spätere Helper-Funktionen
class ModPdfexplorerHelper
{
// Hier kommen später Funktionen rein (z.B. für Rechte, Verzeichnis-Scan, etc.)
}

99
mod_pdf_tree/helper.php Normal file
View File

@@ -0,0 +1,99 @@
<?php
// Direktzugriff verhindern
defined('_JEXEC') or die;
// Hilfsklasse zur URI-Verarbeitung einbinden
use Joomla\CMS\Uri\Uri;
/**
* Modul-Hilfsklasse: Baumstruktur aus JSON-Datei aufbereiten
*/
class ModEisAnzeigeHelper
{
/**
* JSON-Datei einlesen und als Array zurückgeben
* @param string $jsonPath Pfad relativ zum Joomla-Root
* @return array Strukturierte Baumdaten oder leeres Array
*/
public static function getItems(string $jsonPath): array
{
$file = JPATH_ROOT . DIRECTORY_SEPARATOR . ltrim($jsonPath, '/');
if (!file_exists($file)) {
return [];
}
$json = file_get_contents($file);
$data = json_decode($json, true);
if (json_last_error() !== JSON_ERROR_NONE || !is_array($data)) {
return [];
}
return $data;
}
/**
* Baumstruktur als HTML generieren (rekursiv)
* @param array $items Eingelesene JSON-Daten
* @return string HTML-Ausgabe
*/
public static function renderTree(array $items): string
{
$html = '<ul class="pdf-tree">';
foreach ($items as $node) {
$name = htmlspecialchars($node['name'], ENT_QUOTES, 'UTF-8');
// Ordner: hat Kinder
if (isset($node['children']) && is_array($node['children'])) {
$count = self::countFiles($node['children']);
$html .= '<li class="folder">'
. '<span class="toggle">▶</span>'
. '<span class="folder-icon"></span>'
. '<span class="folder-name">'
. $name . ' (' . $count . ')'
. '</span>';
// Rekursiver Aufruf
$html .= self::renderTree($node['children']);
$html .= '</li>';
} else {
// Datei
$path = $node['path'] ?? '';
$relative = str_replace(JPATH_ROOT, '', $path);
$url = Uri::root(true) . '/' . ltrim(str_replace(DIRECTORY_SEPARATOR, '/', $relative), '/');
$html .= '<li class="file">'
. '<span class="file-icon"></span>'
. '<a href="' . $url . '" class="file-link" download>'
. $name . '</a>'
. '</li>';
}
}
$html .= '</ul>';
return $html;
}
/**
* Dateien im aktuellen Knotenbaum zählen
* @param array $items Unterknoten
* @return int Anzahl Dateien
*/
private static function countFiles(array $items): int
{
$count = 0;
foreach ($items as $node) {
if (isset($node['children']) && is_array($node['children'])) {
$count += self::countFiles($node['children']);
} else {
$count++;
}
}
return $count;
}
}

View File

@@ -0,0 +1,20 @@
<?php
// Prevent direct access
defined('_JEXEC') or die;
// Include the helper class
require_once __DIR__ . '/helper.php';
// Retrieve JSON path and access params
$jsonPath = $params->get('json_path', 'media/com_eis/documents.json');
$confidentialLevel = $params->get('confidential_level');
$privateUserId = $params->get('private_user');
// Load and parse JSON document tree
$items = ModEisAnzeigeHelper::getItems($jsonPath);
// TODO: Apply access filtering
// $items = ModEisAnzeigeHelper::filterByAccess($items, $confidentialLevel, $privateUserId);
// Render module layout
require JModuleHelper::getLayoutPath('mod_eis_anzeige', $params->get('layout', 'default'));

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="5.0" client="site" method="upgrade">
<name>EIS-Anzeige</name>
<author>Ich</author>
<version>1.0.1</version>
<description>Anzeige des PDF-Baums mit Dokumentenzählung und Expand/Collapse-All</description>
<files>
<filename module="mod_eis_anzeige">mod_eis_anzeige.php</filename>
<filename>helper.php</filename>
<folder>tmpl</folder>
</files>
<config>
<fields name="params">
<fieldset name="basic">
<field name="json_path" type="text"
default="media/com_eis/documents.json"
label="JSON Path"
description="Pfad zur JSON-Datei relativ zum Joomla Root" />
<field name="confidential_level" type="viewlevels"
label="Confidential Access Level"
description="View level for confidential documents" />
<field name="private_user" type="user"
label="Private Document Owner"
description="User who can view private documents" />
</fieldset>
</fields>
</config>
</extension>

View File

@@ -0,0 +1,114 @@
<?php defined('_JEXEC') or die; ?>
<!-- Styles für Struktur, Vorschau und Icons -->
<style>
/* Baum und Vorschau nebeneinander */
.pdf-tree-wrapper { display: flex; }
.pdf-tree-container { flex: 1; }
/* Verzeichnisliste zurücksetzen */
.pdf-tree, .pdf-tree ul {
list-style: none;
margin: 0;
padding: 0;
}
.pdf-tree li { margin: 0.3em 0; }
/* Ordner-Icons & Pfeile */
.folder > .toggle { cursor: pointer; display: inline-block; width: 1em; }
.folder-icon::before { content: "📁"; margin-right: 4px; }
/* Datei-Icon */
.file-icon::before { content: "📄"; margin-right: 4px; }
/* Standard: Unterverzeichnisse einklappen */
.pdf-tree ul {
display: none;
margin-left: 1.5em;
}
/* Vorschaufenster rechts */
#pdf-preview {
flex: 1;
margin-left: 1em;
border: 1px solid #ccc;
background: #fff;
display: none;
}
#pdf-preview iframe {
width: 100%;
height: 100%;
border: none;
}
/* Buttons oben */
.expand-collapse { margin-bottom: 0.5em; }
.expand-collapse button { margin-right: 0.5em; }
</style>
<!-- Steuerbuttons oben -->
<div class="expand-collapse">
<button id="expand-all">Expand All</button>
<button id="collapse-all">Collapse All</button>
</div>
<div class="pdf-tree-wrapper">
<!-- Links: Verzeichnisbaum -->
<div class="pdf-tree-container">
<?php echo ModEisAnzeigeHelper::renderTree($items); ?>
</div>
<!-- Rechts: Vorschau-Bereich -->
<div id="pdf-preview"></div>
</div>
<!-- Interaktivität: Vorschau, Toggle, Buttons -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// (1) Verzeichnisse auf-/zuklappen per Klick
document.querySelectorAll('.pdf-tree .toggle').forEach(function(toggle) {
toggle.addEventListener('click', function() {
var li = this.parentNode;
var ul = li.querySelector('ul');
if (!ul) return;
if (ul.style.display === 'block') {
ul.style.display = 'none'; this.textContent = '▶';
} else {
ul.style.display = 'block'; this.textContent = '▼';
}
});
});
// (2) Alle ausklappen
document.getElementById('expand-all').addEventListener('click', function() {
document.querySelectorAll('.pdf-tree ul').forEach(function(ul) {
ul.style.display = 'block';
});
document.querySelectorAll('.pdf-tree .toggle').forEach(function(toggle) {
toggle.textContent = '▼';
});
});
// (3) Alle einklappen
document.getElementById('collapse-all').addEventListener('click', function() {
document.querySelectorAll('.pdf-tree ul').forEach(function(ul) {
ul.style.display = 'none';
});
document.querySelectorAll('.pdf-tree .toggle').forEach(function(toggle) {
toggle.textContent = '▶';
});
});
// (4) Vorschau anzeigen beim Klick
var preview = document.getElementById('pdf-preview');
document.querySelectorAll('.pdf-tree .file-link').forEach(function(link) {
link.addEventListener('click', function(e) {
e.preventDefault();
preview.style.display = 'block';
preview.innerHTML = '<iframe src="' + this.href + '"></iframe>';
});
});
});
</script>

View File

@@ -1,24 +0,0 @@
<?php
// Keine direkten Zugriffe erlauben
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Helper\ModuleHelper;
// Hole die Applikation
$app = Factory::getApplication();
// Web Asset Manager holen (Joomla 4/5)
$wa = $app->getDocument()->getWebAssetManager();
// Assets einbinden
$wa->registerAndUseScript('pdfexplorer.pdfjs', 'modules/mod_pdfexplorer/assets/js/pdf.js', [], [], []);
$wa->registerAndUseScript('pdfexplorer.pdfworker', 'modules/mod_pdfexplorer/assets/js/pdf.worker.js', [], [], []);
$wa->registerAndUseScript('pdfexplorer.jstree', 'modules/mod_pdfexplorer/assets/js/jstree.min.js', [], [], []);
$wa->registerAndUseStyle('pdfexplorer.jstree', 'modules/mod_pdfexplorer/assets/css/jstree.min.css', [], []);
$wa->registerAndUseStyle('pdfexplorer.custom', 'modules/mod_pdfexplorer/assets/css/pdfexplorer.css', [], []);
// Übergib Parameter ins Template
require ModuleHelper::getLayoutPath('mod_pdfexplorer', $params->get('layout', 'default'));

View File

@@ -1,48 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="4.0" client="site" method="upgrade">
<name>PDF-Explorer</name>
<creationDate>16.07.2025</creationDate>
<author>TS-IT24</author>
<authorEmail>service@ts-it24.de</authorEmail>
<authorUrl>www.ts-it24.de</authorUrl>
<copyright>Thomas Spohr</copyright>
<version>1.0.0</version>
<description>Modul für die spätere Darstellung eines PDF-Explorers mit Vorschau</description>
<files>
<filename module="mod_pdfexplorer">mod_pdfexplorer.php</filename>
<filename>helper.php</filename>
<folder>tmpl</folder>
<folder>assets</folder>
<filename>README.md</filename>
</files>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="pdf_path"
type="text"
label="Pfad zum PDF-Verzeichnis"
description="Absoluter Serverpfad (außerhalb des DocumentRoot)"
/>
<field
name="usergroups"
type="usergrouplist"
label="Erlaubte Benutzergruppen"
description="Wähle die Benutzergruppen, die Zugriff auf den PDF-Explorer haben sollen."
multiple="true"
/>
<field
name="preview_option"
type="list"
label="Vorschau-Option"
description="Wie sollen PDFs im Frontend angezeigt werden?"
default="both"
>
<option value="thumbnail">Nur Thumbnail</option>
<option value="viewer">Nur PDF-Viewer</option>
<option value="both">Thumbnail + PDF-Viewer</option>
</field>
</fieldset>
</fields>
</config>
</extension>

Binary file not shown.

View File

@@ -1,3 +0,0 @@
<?php
echo phpinfo();
?>

View File

@@ -1,21 +0,0 @@
<?php
defined('_JEXEC') or die;
?>
<div id="pdfexplorer">
<h2>Hello World PDF-Explorer Dummy-Modul</h2>
<p>Modul-Parameter:</p>
<ul>
<li><strong>PDF-Pfad:</strong> <?php echo htmlspecialchars($params->get('pdf_path', '')); ?></li>
<li><strong>Erlaubte Gruppen:</strong>
<?php
$groups = $params->get('usergroups', []);
if (is_array($groups) && count($groups)) {
echo implode(', ', $groups);
} else {
echo 'Keine ausgewählt';
}
?>
</li>
<li><strong>Vorschau-Option:</strong> <?php echo htmlspecialchars($params->get('preview_option', '')); ?></li>
</ul>
</div>