Compare commits
20 Commits
74a91e4e76
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd88be717e | ||
|
|
c744863094 | ||
|
|
530ff9f3a0 | ||
|
|
31af9b27e7 | ||
|
|
103fea5c48 | ||
|
|
dda6869030 | ||
|
|
bcc180fa6f | ||
|
|
87666dde70 | ||
|
|
fc1de065c9 | ||
|
|
381b203e85 | ||
|
|
7396cf9f51 | ||
|
|
bd7e720c47 | ||
|
|
33fa9c8f94 | ||
|
|
266fd69afb | ||
|
|
9c9d422380 | ||
|
|
a481866b66 | ||
|
|
af2ebf4ab6 | ||
|
|
519f9e16b3 | ||
|
|
8d6318bc29 | ||
|
|
a879392973 |
1
EIS
1
EIS
Submodule EIS deleted from 613600f6fc
@@ -1,4 +0,0 @@
|
||||
# EIS
|
||||
|
||||
Joomla-Modul für die Ansicht von PDF's
|
||||
Das kommt alles noch
|
||||
48
com_eis/administrator/language/de-DE/de-DE.com_eis.ini
Normal file
48
com_eis/administrator/language/de-DE/de-DE.com_eis.ini
Normal file
@@ -0,0 +1,48 @@
|
||||
; Joomla Backend – UI-Texte
|
||||
|
||||
; Allgemein
|
||||
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_DOCUMENT_PATH="Dokumenten-Pfad"
|
||||
COM_EIS_NO_DOCUMENTS_FOUND="Noch keine Dokumente in der Datenbank. Bitte zuerst „Dokumente einlesen“ ausführen."
|
||||
COM_EIS_EXPAND_ALL="Ausklappen"
|
||||
COM_EIS_COLLAPSE_ALL="Einklappen"
|
||||
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."
|
||||
|
||||
COM_EIS_ACCESS_TITLE="Zugriff (Top-Level-Ordner)"
|
||||
COM_EIS_FIELD_VIEWLEVEL="Zugriffsebene"
|
||||
COM_EIS_ACCESS_HELP="Nur für Ordner der ersten Ebene. Unterordner und Dateien erben die Einstellung."
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
; 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."
|
||||
32
com_eis/administrator/language/en-GB/en-GB.com_eis.ini
Normal file
32
com_eis/administrator/language/en-GB/en-GB.com_eis.ini
Normal file
@@ -0,0 +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_PDF_TREE="PDF Tree"
|
||||
COM_EIS_SCAN_DOCUMENTS="Scan Documents"
|
||||
COM_EIS_DOCUMENT_PATH="Document Path"
|
||||
COM_EIS_NO_DOCUMENTS_FOUND="No documents in the database yet. Please run “Scan Documents” first."
|
||||
COM_EIS_EXPAND_ALL="Expand All"
|
||||
COM_EIS_COLLAPSE_ALL="Collapse All"
|
||||
COM_EIS_PREVIEW_OPEN_NEWTAB="Open in new tab"
|
||||
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"
|
||||
@@ -0,0 +1,5 @@
|
||||
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."
|
||||
40
com_eis/administrator/services/provider.php
Normal file
40
com_eis/administrator/services/provider.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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;
|
||||
use EIS\Component\EIS\Site\Controller\DownloadController;
|
||||
|
||||
return new class implements ServiceProviderInterface
|
||||
{
|
||||
public function register(Container $container): void
|
||||
{
|
||||
// MVC-Basisregistrierung
|
||||
$container->registerServiceProvider(new ComponentDispatcherFactory('\\EIS\\Component\\EIS'));
|
||||
$container->registerServiceProvider(new MVCFactory('\\EIS\\Component\\EIS'));
|
||||
$container->registerServiceProvider(new RouterFactory('\\EIS\\Component\\EIS'));
|
||||
|
||||
// Optional: DownloadController explizit registrieren (kann auch weggelassen werden)
|
||||
$container->set(
|
||||
DownloadController::class,
|
||||
fn(Container $c) => new DownloadController()
|
||||
);
|
||||
|
||||
// Komponentenschnittstelle
|
||||
$container->set(
|
||||
ComponentInterface::class,
|
||||
static fn(Container $c) => new MVCComponent(
|
||||
$c->get(ComponentDispatcherFactoryInterface::class)
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
43
com_eis/administrator/sql/install.mysql.utf8.sql
Normal file
43
com_eis/administrator/sql/install.mysql.utf8.sql
Normal file
@@ -0,0 +1,43 @@
|
||||
-- Documents
|
||||
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) NOT NULL DEFAULT 0,
|
||||
`title` VARCHAR(255) DEFAULT NULL,
|
||||
`description` TEXT DEFAULT NULL,
|
||||
`ordering` INT NOT NULL DEFAULT 0,
|
||||
`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;
|
||||
|
||||
-- Settings (Key/Value)
|
||||
CREATE TABLE IF NOT EXISTS `#__eis_settings` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`param` VARCHAR(191) NOT NULL,
|
||||
`value` TEXT NULL,
|
||||
`created` DATETIME DEFAULT NULL,
|
||||
`modified` DATETIME DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uniq_param` (`param`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__eis_folder_access` (
|
||||
`folder_id` INT UNSIGNED NOT NULL,
|
||||
`viewlevel_id` INT UNSIGNED NOT NULL,
|
||||
`modified` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`folder_id`),
|
||||
KEY `idx_viewlevel` (`viewlevel_id`)
|
||||
) 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());
|
||||
2
com_eis/administrator/sql/uninstall.mysql.utf8.sql
Normal file
2
com_eis/administrator/sql/uninstall.mysql.utf8.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
DROP TABLE IF EXISTS `#__eis_settings`;
|
||||
DROP TABLE IF EXISTS `#__eis_documents`;
|
||||
70
com_eis/administrator/sql/updates/1.1.2.sql
Normal file
70
com_eis/administrator/sql/updates/1.1.2.sql
Normal file
@@ -0,0 +1,70 @@
|
||||
-- UTF-8, kein BOM
|
||||
-- EIS – Schema-Update 1.1.1
|
||||
-- Ziel: fehlende Tabellen anlegen, fehlende Spalten/Indizes ergänzen.
|
||||
|
||||
-- ==========================================================
|
||||
-- 1) Einstellungen (neu in 1.1.1)
|
||||
-- ==========================================================
|
||||
CREATE TABLE IF NOT EXISTS `#__eis_settings` (
|
||||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`param` VARCHAR(191) NOT NULL,
|
||||
`value` TEXT NULL,
|
||||
`created` DATETIME NULL DEFAULT NULL,
|
||||
`modified` DATETIME NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uniq_param` (`param`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
INSERT IGNORE INTO `#__eis_settings` (`param`, `value`, `created`, `modified`)
|
||||
VALUES ('document_root', '', NOW(), NOW());
|
||||
|
||||
-- ==========================================================
|
||||
-- 2) Dokumente (Bestand absichern)
|
||||
-- Falls ältere Installationen die Tabelle nicht haben.
|
||||
-- ==========================================================
|
||||
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) NOT NULL DEFAULT 0,
|
||||
`title` VARCHAR(255) DEFAULT NULL,
|
||||
`description` TEXT DEFAULT NULL,
|
||||
`ordering` INT NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `#__eis_folder_access` (
|
||||
`folder_id` INT UNSIGNED NOT NULL,
|
||||
`viewlevel_id` INT UNSIGNED NOT NULL,
|
||||
`modified` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`folder_id`),
|
||||
KEY `idx_viewlevel` (`viewlevel_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
|
||||
-- Falls es Altbestände ohne neue Spalten gab, Spalten idempotent ergänzen
|
||||
ALTER TABLE `#__eis_documents`
|
||||
ADD COLUMN IF NOT EXISTS `title` VARCHAR(255) DEFAULT NULL,
|
||||
ADD COLUMN IF NOT EXISTS `description` TEXT DEFAULT NULL,
|
||||
ADD COLUMN IF NOT EXISTS `ordering` INT NOT NULL DEFAULT 0,
|
||||
MODIFY COLUMN `is_folder` TINYINT(1) NOT NULL DEFAULT 0;
|
||||
|
||||
-- Nützliche Indizes (idempotent)
|
||||
CREATE INDEX IF NOT EXISTS `idx_eis_docs_parent` ON `#__eis_documents` (`parent_id`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_eis_docs_ordering` ON `#__eis_documents` (`ordering`);
|
||||
CREATE INDEX IF NOT EXISTS `idx_eis_docs_name` ON `#__eis_documents` (`name`);
|
||||
|
||||
-- Optional: Selbst-Referenz als FK (nur wenn du ON DELETE CASCADE willst)
|
||||
-- Achtung: MySQL verlangt gleiche Kollation/Engine; Namen idempotent prüfen:
|
||||
-- (MySQL kennt kein "ADD CONSTRAINT IF NOT EXISTS", daher defensiv erst droppen)
|
||||
-- SET @fk_exists := (
|
||||
-- SELECT COUNT(*)
|
||||
-- FROM information_schema.REFERENTIAL_CONSTRAINTS
|
||||
-- WHERE CONSTRAINT_SCHEMA = DATABASE()
|
||||
-- AND CONSTRAINT_NAME = 'fk_eis_docs_parent'
|
||||
-- );
|
||||
-- SET @sql := IF(@fk_exists = 0,
|
||||
-- 'ALTER TABLE `#__eis_documents` ADD CONSTRAINT `fk_eis_docs_parent` FOREIGN KEY (`parent_id`) REFERENCES `#__eis_documents`(`id`) ON DELETE CASCADE;',
|
||||
-- 'SELECT 1');
|
||||
-- PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
58
com_eis/administrator/src/Controller/ConfigController.php
Normal file
58
com_eis/administrator/src/Controller/ConfigController.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
namespace EIS\Component\EIS\Administrator\Controller;
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Session\Session;
|
||||
use EIS\Component\EIS\Administrator\Helper\SettingsHelper;
|
||||
|
||||
class ConfigController extends BaseController
|
||||
{
|
||||
public function save(): void
|
||||
{
|
||||
// CSRF
|
||||
if (!Session::checkToken('post')) {
|
||||
throw new \RuntimeException(Text::_('JINVALID_TOKEN'), 403);
|
||||
}
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$input = $app->getInput();
|
||||
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
218
com_eis/administrator/src/Controller/DisplayController.php
Normal file
218
com_eis/administrator/src/Controller/DisplayController.php
Normal file
@@ -0,0 +1,218 @@
|
||||
<?php
|
||||
|
||||
namespace EIS\Component\EIS\Administrator\Controller;
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Session\Session;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use EIS\Component\EIS\Administrator\Helper\SettingsHelper;
|
||||
use EIS\Component\EIS\Administrator\Service\DocumentScanner;
|
||||
|
||||
class DisplayController extends BaseController
|
||||
{
|
||||
protected $default_view = 'main';
|
||||
|
||||
/**
|
||||
* Button-Aktion: PDF-Verzeichnis scannen und in Datenbank speichern
|
||||
*/
|
||||
|
||||
public function scan(): void
|
||||
{
|
||||
// CSRF prüfen (Form hat Token)
|
||||
if (!Session::checkToken('post')) {
|
||||
throw new \RuntimeException(Text::_('JINVALID_TOKEN'), 403);
|
||||
}
|
||||
|
||||
$app = Factory::getApplication();
|
||||
|
||||
try {
|
||||
$newIds = DocumentScanner::run();
|
||||
|
||||
// Wie bisher: New IDs für die View (virtueller Ordner "Neue Dokumente")
|
||||
$app->setUserState('com_eis.new_ids', $newIds);
|
||||
|
||||
$app->enqueueMessage(Text::_('COM_EIS_MSG_SCAN_DONE') ?: 'PDF-Struktur erfolgreich gespeichert.', 'message');
|
||||
} catch (\Throwable $e) {
|
||||
$app->enqueueMessage($e->getMessage(), 'error');
|
||||
}
|
||||
|
||||
$this->setRedirect(Route::_('index.php?option=com_eis&view=main', false));
|
||||
}
|
||||
/**
|
||||
* Rekursive Verzeichnisanalyse
|
||||
*/
|
||||
private function scanFolder(string $dir): array
|
||||
{
|
||||
$result = [];
|
||||
if (!is_dir($dir)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$entries = @scandir($dir);
|
||||
if ($entries === false) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
foreach ($entries as $file) {
|
||||
if ($file === '.' || $file === '..') {
|
||||
continue;
|
||||
}
|
||||
$fullPath = $dir . DIRECTORY_SEPARATOR . $file;
|
||||
|
||||
if (is_dir($fullPath)) {
|
||||
$result[] = [
|
||||
'name' => $file,
|
||||
'children' => $this->scanFolder($fullPath)
|
||||
];
|
||||
} elseif (is_file($fullPath) && strtolower(pathinfo($file, PATHINFO_EXTENSION)) === 'pdf') {
|
||||
$result[] = [
|
||||
'name' => $file,
|
||||
'path' => $fullPath
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Alphabetisch stabil sortieren
|
||||
usort($result, static function ($a, $b) {
|
||||
return strcasecmp((string)$a['name'], (string)$b['name']);
|
||||
});
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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): array
|
||||
{
|
||||
$insertedFileIds = [];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$name = $db->quote($item['name']);
|
||||
$path = $db->quote($item['path'] ?? ''); // leer statt NULL
|
||||
$parent = $parentId !== null ? (int)$parentId : 'NULL';
|
||||
$isFolder = isset($item['children']) ? 1 : 0;
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->insert($db->quoteName('#__eis_documents'))
|
||||
->columns(['name', 'path', 'parent_id', 'is_folder'])
|
||||
->values("$name, $path, $parent, $isFolder");
|
||||
|
||||
$db->setQuery($query)->execute();
|
||||
|
||||
$insertedId = (int)$db->insertid();
|
||||
|
||||
if ($isFolder && !empty($item['children'])) {
|
||||
// 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
|
||||
{
|
||||
// CSRF prüfen
|
||||
if (!Session::checkToken('post')) {
|
||||
throw new \RuntimeException(Text::_('JINVALID_TOKEN'), 403);
|
||||
}
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$id = (int) $app->input->post->get('id', 0);
|
||||
$title = trim((string) $app->input->post->get('title', '', 'string'));
|
||||
|
||||
if ($id <= 0) {
|
||||
$app->enqueueMessage(Text::_('JERROR_AN_ERROR_HAS_OCCURRED') ?: 'Ungültige ID', 'error');
|
||||
$this->setRedirect(Route::_('index.php?option=com_eis&view=main', false));
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var DatabaseDriver $db */
|
||||
$db = Factory::getDbo();
|
||||
$query = $db->getQuery(true)
|
||||
->update($db->quoteName('#__eis_documents'))
|
||||
->set($db->quoteName('title') . ' = ' . ($title === '' ? 'NULL' : $db->quote($title)))
|
||||
->set($db->quoteName('modified') . ' = ' . $db->quote(\Joomla\CMS\Factory::getDate()->toSql()))
|
||||
->where($db->quoteName('id') . ' = ' . (int)$id);
|
||||
|
||||
try {
|
||||
$db->setQuery($query)->execute();
|
||||
$app->enqueueMessage(Text::_('COM_EIS_MSG_SAVED_SUCCESS') ?: 'Anzeigename gespeichert', 'message');
|
||||
} catch (\Throwable $e) {
|
||||
$app->enqueueMessage((Text::_('COM_EIS_MSG_SAVED_ERROR') ?: 'Fehler beim Speichern: ') . $e->getMessage(), 'error');
|
||||
}
|
||||
|
||||
$this->setRedirect(Route::_('index.php?option=com_eis&view=main', false));
|
||||
}
|
||||
|
||||
public function saveAccess(): void
|
||||
{
|
||||
if (!\Joomla\CMS\Session\Session::checkToken('post')) {
|
||||
throw new \RuntimeException(\JText::_('JINVALID_TOKEN'), 403);
|
||||
}
|
||||
|
||||
$app = \Joomla\CMS\Factory::getApplication();
|
||||
$db = \Joomla\CMS\Factory::getDbo();
|
||||
|
||||
$folderId = (int) $app->input->post->get('folder_id', 0);
|
||||
$viewlevelId = (int) $app->input->post->get('viewlevel_id', 0);
|
||||
|
||||
// Validierung: folderId muss Top-Level-Ordner sein
|
||||
if ($folderId <= 0) {
|
||||
$app->enqueueMessage('Ungültiger Ordner.', 'error');
|
||||
$this->setRedirect(\Joomla\CMS\Router\Route::_('index.php?option=com_eis&view=main', false));
|
||||
return;
|
||||
}
|
||||
|
||||
// prüfen, ob Top-Level-Ordner
|
||||
$q = $db->getQuery(true)
|
||||
->select($db->quoteName(['id','is_folder','parent_id']))
|
||||
->from($db->quoteName('#__eis_documents'))
|
||||
->where($db->quoteName('id') . ' = ' . (int)$folderId);
|
||||
$db->setQuery($q);
|
||||
$row = $db->loadAssoc();
|
||||
|
||||
if (!$row || (int)$row['is_folder'] !== 1 || $row['parent_id'] !== null) {
|
||||
$app->enqueueMessage('Nur Top-Level-Ordner können berechtigt werden.', 'warning');
|
||||
$this->setRedirect(\Joomla\CMS\Router\Route::_('index.php?option=com_eis&view=main', false));
|
||||
return;
|
||||
}
|
||||
|
||||
// Viewlevel validieren
|
||||
if ($viewlevelId <= 0) {
|
||||
// löschen (öffentlich)
|
||||
$db->setQuery(
|
||||
$db->getQuery(true)
|
||||
->delete($db->quoteName('#__eis_folder_access'))
|
||||
->where($db->quoteName('folder_id') . ' = ' . (int)$folderId)
|
||||
)->execute();
|
||||
|
||||
$app->enqueueMessage('Berechtigung entfernt (öffentlich).', 'message');
|
||||
$this->setRedirect(\Joomla\CMS\Router\Route::_('index.php?option=com_eis&view=main', false));
|
||||
return;
|
||||
}
|
||||
|
||||
// upsert
|
||||
$sql = 'INSERT INTO ' . $db->quoteName('#__eis_folder_access')
|
||||
. ' (' . $db->quoteName('folder_id') . ', ' . $db->quoteName('viewlevel_id') . ') VALUES ('
|
||||
. (int)$folderId . ', ' . (int)$viewlevelId . ')'
|
||||
. ' ON DUPLICATE KEY UPDATE ' . $db->quoteName('viewlevel_id') . ' = VALUES(' . $db->quoteName('viewlevel_id') . ')';
|
||||
$db->setQuery($sql)->execute();
|
||||
|
||||
$app->enqueueMessage('Berechtigung gespeichert.', 'message');
|
||||
$this->setRedirect(\Joomla\CMS\Router\Route::_('index.php?option=com_eis&view=main', false));
|
||||
}
|
||||
|
||||
}
|
||||
10
com_eis/administrator/src/Extension/EISComponent.php
Normal file
10
com_eis/administrator/src/Extension/EISComponent.php
Normal 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
|
||||
{
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
193
com_eis/administrator/src/Helper/TreeHelper.php
Normal file
193
com_eis/administrator/src/Helper/TreeHelper.php
Normal file
@@ -0,0 +1,193 @@
|
||||
<?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';
|
||||
}
|
||||
}
|
||||
107
com_eis/administrator/src/Service/DocumentScanner.php
Normal file
107
com_eis/administrator/src/Service/DocumentScanner.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
namespace EIS\Component\EIS\Administrator\Service;
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use EIS\Component\EIS\Administrator\Helper\SettingsHelper;
|
||||
|
||||
class DocumentScanner
|
||||
{
|
||||
/**
|
||||
* Führt den Scan aus.
|
||||
* @return int[] IDs der eingefügten Dateien
|
||||
*/
|
||||
public static function run(?string $path = null, ?DatabaseDriver $db = null): array
|
||||
{
|
||||
$db = $db ?: Factory::getDbo();
|
||||
$app = Factory::getApplication();
|
||||
|
||||
// Pfad laden, wenn nicht übergeben
|
||||
$path = $path ?: SettingsHelper::getSetting('document_root', '/var/www/pdf');
|
||||
|
||||
if (!$path || !is_dir($path)) {
|
||||
// Kein enqueueMessage, damit es auch im Task sauber läuft
|
||||
throw new \RuntimeException('Pfad ungültig oder nicht gesetzt: ' . (string)$path);
|
||||
}
|
||||
|
||||
$data = self::scanFolder($path);
|
||||
|
||||
// Achtung: du löscht aktuell immer alles -> danach ist alles "neu"
|
||||
$db->truncateTable('#__eis_documents');
|
||||
|
||||
$newIds = self::saveToDb($data, null, $db);
|
||||
|
||||
// Dauerhaft speichern (Frontend-Modul nutzt das ja schon)
|
||||
SettingsHelper::setSetting('last_new_ids', json_encode($newIds, JSON_UNESCAPED_SLASHES));
|
||||
SettingsHelper::setSetting('last_scan_at', date('Y-m-d H:i:s'));
|
||||
|
||||
return $newIds;
|
||||
}
|
||||
|
||||
private static function scanFolder(string $dir): array
|
||||
{
|
||||
$result = [];
|
||||
if (!is_dir($dir)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$entries = @scandir($dir);
|
||||
if ($entries === false) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
foreach ($entries as $file) {
|
||||
if ($file === '.' || $file === '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fullPath = $dir . DIRECTORY_SEPARATOR . $file;
|
||||
|
||||
if (is_dir($fullPath)) {
|
||||
$result[] = [
|
||||
'name' => $file,
|
||||
'children' => self::scanFolder($fullPath)
|
||||
];
|
||||
} elseif (is_file($fullPath) && strtolower(pathinfo($file, PATHINFO_EXTENSION)) === 'pdf') {
|
||||
$result[] = [
|
||||
'name' => $file,
|
||||
'path' => $fullPath
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
usort($result, static fn($a, $b) => strcasecmp((string)$a['name'], (string)$b['name']));
|
||||
return $result;
|
||||
}
|
||||
|
||||
private static function saveToDb(array $items, ?int $parentId, DatabaseDriver $db): array
|
||||
{
|
||||
$insertedFileIds = [];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$name = $db->quote($item['name']);
|
||||
$path = $db->quote($item['path'] ?? '');
|
||||
$parent = $parentId !== null ? (int)$parentId : 'NULL';
|
||||
$isFolder = isset($item['children']) ? 1 : 0;
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->insert($db->quoteName('#__eis_documents'))
|
||||
->columns(['name', 'path', 'parent_id', 'is_folder'])
|
||||
->values("$name, $path, $parent, $isFolder");
|
||||
|
||||
$db->setQuery($query)->execute();
|
||||
$insertedId = (int) $db->insertid();
|
||||
|
||||
if ($isFolder && !empty($item['children'])) {
|
||||
$childIds = self::saveToDb($item['children'], $insertedId, $db);
|
||||
$insertedFileIds = array_merge($insertedFileIds, $childIds);
|
||||
} else {
|
||||
$insertedFileIds[] = $insertedId;
|
||||
}
|
||||
}
|
||||
|
||||
return $insertedFileIds;
|
||||
}
|
||||
}
|
||||
23
com_eis/administrator/src/View/Config/HtmlView.php
Normal file
23
com_eis/administrator/src/View/Config/HtmlView.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
namespace EIS\Component\EIS\Administrator\View\Config;
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use EIS\Component\EIS\Administrator\Helper\SettingsHelper;
|
||||
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
protected $pdfPath = '';
|
||||
|
||||
public function display($tpl = null): void
|
||||
{
|
||||
$this->pdfPath = SettingsHelper::getSetting('document_root', '/var/www/pdf');
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
public function getPdfPath(): string
|
||||
{
|
||||
return (string)$this->pdfPath;
|
||||
}
|
||||
}
|
||||
117
com_eis/administrator/src/View/Main/HtmlView.php
Normal file
117
com_eis/administrator/src/View/Main/HtmlView.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
namespace EIS\Component\EIS\Administrator\View\Main;
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use EIS\Component\EIS\Administrator\Helper\TreeHelper;
|
||||
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/** HTML des Baums (inkl. virtuellem Ordner „Neue Dokumente“, falls vorhanden) */
|
||||
protected string $treeHtml = '';
|
||||
|
||||
/** Liste aller Viewlevels: [ ['id'=>int, 'title'=>string], ... ] */
|
||||
protected array $viewLevels = [];
|
||||
|
||||
/**
|
||||
* Map der gesetzten ACLs für Top-Level-Ordner:
|
||||
* [ folder_id (int) => viewlevel_id (int), ... ]
|
||||
*/
|
||||
protected array $folderAccess = [];
|
||||
|
||||
public function display($tpl = null): void
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
/** @var DatabaseDriver $db */
|
||||
$db = Factory::getDbo();
|
||||
|
||||
// 1) Baum-Daten
|
||||
$items = TreeHelper::getItems();
|
||||
|
||||
// neu hinzugekommene IDs aus letztem Scan (können leer sein)
|
||||
$newIds = (array) $app->getUserState('com_eis.new_ids', []);
|
||||
|
||||
// Baum rendern (virtueller Ordner „Neue Dokumente“ + regulärer Baum)
|
||||
$this->treeHtml = TreeHelper::renderTreeWithNew($items, $newIds);
|
||||
|
||||
// 2) Viewlevels laden
|
||||
$this->viewLevels = $this->loadViewLevels($db);
|
||||
|
||||
// 3) gesetzte ACLs für Top-Level-Ordner laden
|
||||
$this->folderAccess = $this->loadFolderAccess($db);
|
||||
|
||||
// Template ausgeben
|
||||
parent::display($tpl);
|
||||
|
||||
// „Neue Dokumente“ einmalig zeigen → State leeren
|
||||
$app->setUserState('com_eis.new_ids', []);
|
||||
}
|
||||
|
||||
/** Für Template: HTML des Baums */
|
||||
public function getTreeHtml(): string
|
||||
{
|
||||
return $this->treeHtml;
|
||||
}
|
||||
|
||||
/** Für Template: Liste der Viewlevels */
|
||||
public function getViewLevels(): array
|
||||
{
|
||||
return $this->viewLevels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Für Template/JS: Map folder_id => viewlevel_id (nur Top-Level-Ordner)
|
||||
* Beispiel: [ 12 => 3, 15 => 5 ]
|
||||
*/
|
||||
public function getFolderAccess(): array
|
||||
{
|
||||
return $this->folderAccess;
|
||||
}
|
||||
|
||||
/** Lädt alle Viewlevels sortiert nach Titel */
|
||||
private function loadViewLevels(DatabaseDriver $db): array
|
||||
{
|
||||
$q = $db->getQuery(true)
|
||||
->select($db->quoteName(['id', 'title']))
|
||||
->from($db->quoteName('#__viewlevels'))
|
||||
->order($db->quoteName('title') . ' ASC');
|
||||
|
||||
$db->setQuery($q);
|
||||
$rows = (array) $db->loadAssocList();
|
||||
|
||||
// Safety: Normalisieren der Typen
|
||||
foreach ($rows as &$r) {
|
||||
$r['id'] = (int) ($r['id'] ?? 0);
|
||||
$r['title'] = (string) ($r['title'] ?? '');
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt ACL-Zuweisungen aus #__eis_folder_access.
|
||||
* Es werden nur Top-Level-Ordner-IDs erwartet (per Controller validiert).
|
||||
*/
|
||||
private function loadFolderAccess(DatabaseDriver $db): array
|
||||
{
|
||||
$q = $db->getQuery(true)
|
||||
->select($db->quoteName(['folder_id', 'viewlevel_id']))
|
||||
->from($db->quoteName('#__eis_folder_access'));
|
||||
|
||||
$db->setQuery($q);
|
||||
$rows = (array) $db->loadAssocList();
|
||||
|
||||
$map = [];
|
||||
foreach ($rows as $r) {
|
||||
$fid = (int) ($r['folder_id'] ?? 0);
|
||||
$vid = (int) ($r['viewlevel_id'] ?? 0);
|
||||
if ($fid > 0 && $vid > 0) {
|
||||
$map[$fid] = $vid;
|
||||
}
|
||||
}
|
||||
return $map;
|
||||
}
|
||||
}
|
||||
72
com_eis/administrator/tmpl/config/default.php
Normal file
72
com_eis/administrator/tmpl/config/default.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
|
||||
// Wert aus der View (HtmlView::getPdfPath()), Fallback leer
|
||||
$pdfPath = method_exists($this, 'getPdfPath') ? (string) $this->getPdfPath() : '';
|
||||
?>
|
||||
<h2 class="mb-3">
|
||||
<?php echo Text::_('COM_EIS_SETTINGS_TITLE') ?: 'Einstellungen'; ?>
|
||||
</h2>
|
||||
|
||||
<form action="<?php echo Route::_('index.php?option=com_eis&task=config.save'); ?>"
|
||||
method="post"
|
||||
name="adminForm"
|
||||
id="adminForm"
|
||||
novalidate>
|
||||
<div class="form-horizontal">
|
||||
<fieldset class="adminform">
|
||||
<legend><?php echo Text::_('COM_EIS_FIELDSET_GENERAL') ?: 'Allgemein'; ?></legend>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="document_root">
|
||||
<?php echo Text::_('COM_EIS_FIELD_DOCUMENT_ROOT_LABEL') ?: 'Basis-Verzeichnis für PDFs'; ?>
|
||||
</label>
|
||||
<div class="controls">
|
||||
<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>
|
||||
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div class="mt-2">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<?php echo Text::_('JSAVE') ?: 'Speichern'; ?>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</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>
|
||||
263
com_eis/administrator/tmpl/main/default.php
Normal file
263
com_eis/administrator/tmpl/main/default.php
Normal file
@@ -0,0 +1,263 @@
|
||||
<?php
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
$hasTree = !empty($this->treeHtml);
|
||||
|
||||
// ACL-Daten aus der View (für Vorbelegung im Formular)
|
||||
$viewLevels = method_exists($this, 'getViewLevels') ? (array) $this->getViewLevels() : [];
|
||||
$aclMap = method_exists($this, 'getFolderAccess') ? (array) $this->getFolderAccess() : [];
|
||||
?>
|
||||
<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 -->
|
||||
<form action="<?php echo Route::_('index.php?option=com_eis&task=display.scan'); ?>" method="post" id="eis-scan-form">
|
||||
<fieldset class="adminform">
|
||||
<legend><?php echo Text::_('COM_EIS_DOCUMENT_PATH'); ?></legend>
|
||||
<div class="form-help"><?php echo Text::_('COM_EIS_SETTINGS_TITLE'); ?> · <?php echo Text::_('COM_EIS_FIELD_DOCUMENT_ROOT_LABEL'); ?></div>
|
||||
</fieldset>
|
||||
<div class="mt-2">
|
||||
<button class="btn btn-primary" type="submit">
|
||||
<?php echo Text::_('COM_EIS_SCAN_DOCUMENTS'); ?>
|
||||
</button>
|
||||
</div>
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
|
||||
<?php if (!$hasTree): ?>
|
||||
<p class="text-muted">
|
||||
<?php echo Text::_('COM_EIS_NO_DOCUMENTS_FOUND'); ?>
|
||||
</p>
|
||||
<?php else: ?>
|
||||
|
||||
<h3 class="mt-3"><?php echo Text::_('COM_EIS_PDF_TREE'); ?></h3>
|
||||
|
||||
<div class="eis-flex">
|
||||
|
||||
<!-- Linke Seite: Baum -->
|
||||
<div class="eis-tree-wrap">
|
||||
<div class="controls">
|
||||
<button id="eis-expand-all" type="button" class="btn btn-sm btn-secondary">
|
||||
<?php echo Text::_('COM_EIS_EXPAND_ALL'); ?>
|
||||
</button>
|
||||
<button id="eis-collapse-all" type="button" class="btn btn-sm btn-secondary">
|
||||
<?php echo Text::_('COM_EIS_COLLAPSE_ALL'); ?>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="tree" id="eis-tree" role="tree" aria-label="<?php echo Text::_('COM_EIS_PDF_TREE'); ?>">
|
||||
<?php echo $this->treeHtml; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Rechte Seite: Inline-Bearbeitung + ACL -->
|
||||
<div class="eis-edit">
|
||||
<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" novalidate>
|
||||
<div class="control-group">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<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'; ?>">
|
||||
<div class="form-help"><?php echo Text::_('COM_EIS_FILESIZE'); ?>: <span id="eis-filesize">–</span></div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="id" id="eis-id" value="">
|
||||
|
||||
<div class="mt-2">
|
||||
<button type="submit" class="btn btn-success" id="eis-save" disabled>
|
||||
<?php echo Text::_('JSAVE'); ?>
|
||||
</button>
|
||||
<button type="button" id="eis-clear-title" class="btn btn-light" disabled>
|
||||
<?php echo Text::_('JDEFAULT') ?: 'Zurücksetzen'; ?>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</form>
|
||||
|
||||
<!-- ===== ACL: Zugriff (Top-Level-Ordner) ===== -->
|
||||
<hr style="margin:1rem 0">
|
||||
|
||||
<h4><?php echo Text::_('COM_EIS_ACCESS_TITLE') ?: 'Zugriff (Top-Level-Ordner)'; ?></h4>
|
||||
|
||||
<form action="<?php echo Route::_('index.php?option=com_eis&task=display.saveAccess'); ?>"
|
||||
method="post" id="eis-access-form">
|
||||
<div class="control-group">
|
||||
<label for="eis-folder-viewlevel">
|
||||
<?php echo Text::_('COM_EIS_FIELD_VIEWLEVEL') ?: 'Zugriffsebene'; ?>
|
||||
</label>
|
||||
<select name="viewlevel_id" id="eis-folder-viewlevel" class="form-control">
|
||||
<option value="0">(Öffentlich)</option>
|
||||
<?php foreach ($viewLevels as $vl): ?>
|
||||
<option value="<?php echo (int)$vl['id']; ?>">
|
||||
<?php echo htmlspecialchars($vl['title'], ENT_QUOTES, 'UTF-8'); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="form-help">
|
||||
<?php echo Text::_('COM_EIS_ACCESS_HELP') ?: 'Nur für Ordner der ersten Ebene. Unterordner und Dateien erben die Einstellung.'; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="folder_id" id="eis-folder-id" value="">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
|
||||
<div class="mt-2">
|
||||
<button type="submit" class="btn btn-secondary" id="eis-access-save" disabled>
|
||||
<?php echo Text::_('JSAVE'); ?>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<!-- ===== /ACL ===== -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
const tree = document.getElementById('eis-tree');
|
||||
const form = document.getElementById('eis-rename-form');
|
||||
const idFld = document.getElementById('eis-id');
|
||||
const nameFld = document.getElementById('eis-current-name');
|
||||
const titleFld= document.getElementById('eis-title');
|
||||
const sizeOut = document.getElementById('eis-filesize');
|
||||
const btnSave = document.getElementById('eis-save');
|
||||
const btnClr = document.getElementById('eis-clear-title');
|
||||
|
||||
// ACL-Form Elemente
|
||||
const aclForm = document.getElementById('eis-access-form');
|
||||
const aclFolderId = document.getElementById('eis-folder-id');
|
||||
const aclSelect = document.getElementById('eis-folder-viewlevel');
|
||||
const aclBtn = document.getElementById('eis-access-save');
|
||||
|
||||
// PHP-Map folder_id => viewlevel_id an JS übergeben
|
||||
const ACL_MAP = <?php echo json_encode($aclMap, JSON_UNESCAPED_SLASHES); ?>;
|
||||
|
||||
if (!tree) return;
|
||||
|
||||
let lastSelected;
|
||||
|
||||
// Helper: prüfen, ob li.folder Top-Level ist
|
||||
function isTopLevelFolder(li){
|
||||
if (!li) return false;
|
||||
const parentLi = li.parentElement ? li.parentElement.closest('li.folder') : null;
|
||||
return !parentLi; // kein übergeordneter <li.folder>
|
||||
}
|
||||
|
||||
// Toggle (Caret) & Auswahl
|
||||
tree.addEventListener('click', (e) => {
|
||||
const t = e.target;
|
||||
|
||||
// Ein-/Ausklappen
|
||||
if (t.classList.contains('toggle') || t.classList.contains('folder-label')) {
|
||||
const li = t.closest('li.folder');
|
||||
if (li) {
|
||||
const childUl = li.querySelector(':scope > ul');
|
||||
if (childUl) {
|
||||
const open = childUl.style.display === 'block';
|
||||
childUl.style.display = open ? 'none' : 'block';
|
||||
const caret = li.querySelector(':scope > .toggle');
|
||||
if (caret) caret.textContent = open ? '▶' : '▼';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Auswahl für Bearbeitung (Ordner- oder Datei-Label)
|
||||
if (t.classList.contains('folder-label') || t.classList.contains('file-label')) {
|
||||
const li = t.closest('li');
|
||||
if (!li) return;
|
||||
|
||||
// Visuelles Highlight
|
||||
if (lastSelected) lastSelected.classList.remove('is-selected');
|
||||
t.classList.add('is-selected');
|
||||
lastSelected = t;
|
||||
|
||||
// Daten aus data-Attributen
|
||||
const id = li.getAttribute('data-id') || '';
|
||||
const title = li.getAttribute('data-title') || '';
|
||||
const name = li.getAttribute('data-name') || '';
|
||||
const size = li.getAttribute('data-size') || ''; // optional
|
||||
|
||||
idFld.value = id;
|
||||
nameFld.value = name;
|
||||
titleFld.value= title;
|
||||
sizeOut.textContent = size || '–';
|
||||
|
||||
btnSave.disabled = !id;
|
||||
btnClr.disabled = !id;
|
||||
|
||||
// ACL-Form: nur bei Top-Level-Ordner aktivieren und vorbelegen
|
||||
if (li.classList.contains('folder') && isTopLevelFolder(li)) {
|
||||
aclFolderId.value = id || '';
|
||||
aclBtn.disabled = !aclFolderId.value;
|
||||
// vorwählen
|
||||
const current = (id && ACL_MAP[id]) ? String(ACL_MAP[id]) : '0';
|
||||
if (aclSelect) {
|
||||
for (const opt of aclSelect.options) {
|
||||
opt.selected = (opt.value === current);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// kein Top-Level -> ACL-Form deaktivieren
|
||||
aclFolderId.value = '';
|
||||
aclBtn.disabled = true;
|
||||
}
|
||||
|
||||
// Fokus ins Titel-Feld
|
||||
titleFld.focus();
|
||||
}
|
||||
});
|
||||
|
||||
// „Zurücksetzen“ = Titel leeren
|
||||
btnClr?.addEventListener('click', () => {
|
||||
titleFld.value = '';
|
||||
titleFld.focus();
|
||||
});
|
||||
|
||||
// Global: Aus-/Einklappen
|
||||
document.getElementById('eis-expand-all')?.addEventListener('click', () => {
|
||||
document.querySelectorAll('.pdf-tree ul').forEach(ul => ul.style.display = 'block');
|
||||
document.querySelectorAll('.pdf-tree .toggle').forEach(t => t.textContent = '▼');
|
||||
});
|
||||
document.getElementById('eis-collapse-all')?.addEventListener('click', () => {
|
||||
document.querySelectorAll('.pdf-tree ul').forEach(ul => ul.style.display = 'none');
|
||||
document.querySelectorAll('.pdf-tree .toggle').forEach(t => t.textContent = '▶');
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
<?php endif; ?>
|
||||
52
com_eis/eis.xml
Normal file
52
com_eis/eis.xml
Normal file
@@ -0,0 +1,52 @@
|
||||
<extension type="component" method="upgrade">
|
||||
<name>com_eis</name>
|
||||
<version>1.1.3</version>
|
||||
<namespace path="src">EIS\Component\EIS</namespace>
|
||||
|
||||
<files folder="site">
|
||||
<folder>src</folder>
|
||||
</files>
|
||||
|
||||
<administration>
|
||||
<menu>COM_EIS_MENU</menu>
|
||||
<submenu>
|
||||
<menu link="option=com_eis&view=main">COM_EIS_MAIN</menu>
|
||||
<menu link="option=com_eis&view=config">COM_EIS_CONFIG</menu>
|
||||
</submenu>
|
||||
<files folder="administrator">
|
||||
<folder>src</folder>
|
||||
<folder>tmpl</folder>
|
||||
<folder>sql</folder>
|
||||
<folder>language</folder>
|
||||
<folder>services</folder>
|
||||
</files>
|
||||
<languages folder="administrator/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>
|
||||
<languages folder="administrator/language/de-DE">
|
||||
<language tag="de-DE">de-DE.com_eis.ini</language>
|
||||
<language tag="de-DE">de-DE.com_eis.sys.ini</language>
|
||||
</languages>
|
||||
</administration>
|
||||
|
||||
|
||||
<install>
|
||||
<sql>
|
||||
<file driver="mysql" charset="utf8">sql/install.mysql.utf8.sql</file>
|
||||
</sql>
|
||||
</install>
|
||||
<uninstall>
|
||||
<sql>
|
||||
<file driver="mysql" charset="utf8">sql/uninstall.mysql.utf8.sql</file>
|
||||
</sql>
|
||||
</uninstall>
|
||||
<schemas>
|
||||
<schemapath type="mysql">sql/updates/mysql</schemapath>
|
||||
</schemas>
|
||||
|
||||
|
||||
<media folder="media" destination="com_eis">
|
||||
<folder>pdfjs</folder>
|
||||
</media>
|
||||
</extension>
|
||||
BIN
com_eis/eis.zip
Normal file
BIN
com_eis/eis.zip
Normal file
Binary file not shown.
23371
com_eis/media/pdfjs/build/pdf.mjs
Normal file
23371
com_eis/media/pdfjs/build/pdf.mjs
Normal file
File diff suppressed because it is too large
Load Diff
1
com_eis/media/pdfjs/build/pdf.mjs.map
Normal file
1
com_eis/media/pdfjs/build/pdf.mjs.map
Normal file
File diff suppressed because one or more lines are too long
218
com_eis/media/pdfjs/build/pdf.sandbox.mjs
Normal file
218
com_eis/media/pdfjs/build/pdf.sandbox.mjs
Normal file
File diff suppressed because one or more lines are too long
1
com_eis/media/pdfjs/build/pdf.sandbox.mjs.map
Normal file
1
com_eis/media/pdfjs/build/pdf.sandbox.mjs.map
Normal file
File diff suppressed because one or more lines are too long
58148
com_eis/media/pdfjs/build/pdf.worker.mjs
Normal file
58148
com_eis/media/pdfjs/build/pdf.worker.mjs
Normal file
File diff suppressed because one or more lines are too long
1
com_eis/media/pdfjs/build/pdf.worker.mjs.map
Normal file
1
com_eis/media/pdfjs/build/pdf.worker.mjs.map
Normal file
File diff suppressed because one or more lines are too long
BIN
com_eis/media/pdfjs/web/cmaps/78-EUC-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/78-EUC-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/78-EUC-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/78-EUC-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/78-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/78-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/78-RKSJ-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/78-RKSJ-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/78-RKSJ-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/78-RKSJ-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/78-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/78-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/78ms-RKSJ-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/78ms-RKSJ-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/78ms-RKSJ-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/78ms-RKSJ-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/83pv-RKSJ-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/83pv-RKSJ-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/90ms-RKSJ-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/90ms-RKSJ-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/90ms-RKSJ-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/90ms-RKSJ-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/90msp-RKSJ-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/90msp-RKSJ-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/90msp-RKSJ-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/90msp-RKSJ-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/90pv-RKSJ-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/90pv-RKSJ-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/90pv-RKSJ-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/90pv-RKSJ-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Add-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Add-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Add-RKSJ-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Add-RKSJ-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Add-RKSJ-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Add-RKSJ-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Add-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Add-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-0.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-0.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-1.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-1.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-2.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-2.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-3.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-3.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-4.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-4.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-5.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-5.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-6.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-6.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-UCS2.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-CNS1-UCS2.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-GB1-0.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-GB1-0.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-GB1-1.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-GB1-1.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-GB1-2.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-GB1-2.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-GB1-3.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-GB1-3.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-GB1-4.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-GB1-4.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-GB1-5.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-GB1-5.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-GB1-UCS2.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-GB1-UCS2.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-0.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-0.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-1.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-1.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-2.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-2.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-3.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-3.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-4.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-4.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-5.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-5.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-6.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-6.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-UCS2.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Japan1-UCS2.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Korea1-0.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Korea1-0.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Korea1-1.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Korea1-1.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Korea1-2.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Korea1-2.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Korea1-UCS2.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Adobe-Korea1-UCS2.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/B5-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/B5-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/B5-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/B5-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/B5pc-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/B5pc-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/B5pc-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/B5pc-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/CNS-EUC-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/CNS-EUC-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/CNS-EUC-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/CNS-EUC-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/CNS1-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/CNS1-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/CNS1-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/CNS1-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/CNS2-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/CNS2-H.bcmap
Normal file
Binary file not shown.
3
com_eis/media/pdfjs/web/cmaps/CNS2-V.bcmap
Normal file
3
com_eis/media/pdfjs/web/cmaps/CNS2-V.bcmap
Normal file
@@ -0,0 +1,3 @@
|
||||
àRCopyright 1990-2009 Adobe Systems Incorporated.
|
||||
All rights reserved.
|
||||
See ./LICENSEáCNS2-H
|
||||
BIN
com_eis/media/pdfjs/web/cmaps/ETHK-B5-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/ETHK-B5-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/ETHK-B5-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/ETHK-B5-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/ETen-B5-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/ETen-B5-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/ETen-B5-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/ETen-B5-V.bcmap
Normal file
Binary file not shown.
3
com_eis/media/pdfjs/web/cmaps/ETenms-B5-H.bcmap
Normal file
3
com_eis/media/pdfjs/web/cmaps/ETenms-B5-H.bcmap
Normal file
@@ -0,0 +1,3 @@
|
||||
àRCopyright 1990-2009 Adobe Systems Incorporated.
|
||||
All rights reserved.
|
||||
See ./LICENSEá ETen-B5-H` ^
|
||||
BIN
com_eis/media/pdfjs/web/cmaps/ETenms-B5-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/ETenms-B5-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/EUC-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/EUC-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/EUC-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/EUC-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Ext-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Ext-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Ext-RKSJ-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Ext-RKSJ-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Ext-RKSJ-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Ext-RKSJ-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/Ext-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/Ext-V.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/GB-EUC-H.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/GB-EUC-H.bcmap
Normal file
Binary file not shown.
BIN
com_eis/media/pdfjs/web/cmaps/GB-EUC-V.bcmap
Normal file
BIN
com_eis/media/pdfjs/web/cmaps/GB-EUC-V.bcmap
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user