FilesDir = '';
}
static function GetModelDesc(): ModelDesc
{
$Desc = new ModelDesc('File');
$Desc->AddString('Name');
$Desc->AddInteger('Size');
$Desc->AddReference('Directory', FileDirectory::GetClassName(), true);
$Desc->AddDateTime('Time');
$Desc->AddString('Hash');
$Desc->AddBoolean('Generate');
return $Desc;
}
function Delete($Id): void
{
$DbResult = $this->Database->select('File', 'Name', 'Id='.$Id);
if ($DbResult->num_rows > 0)
{
$DbRow = $DbResult->fetch_assoc();
$this->Database->delete('File', 'Id='.$Id);
unlink($this->FilesDir.'/'.$Id.'_'.$DbRow['Name']);
}
}
function CreateFromUpload(string $Name): string
{
// Submited form with file input have to be enctype="multipart/form-data"
$Result = 0;
if (array_key_exists($Name, $_FILES) and ($_FILES[$Name]['name'] != ''))
{
if (file_exists($_FILES[$Name]['tmp_name']))
{
$FileName = substr($_FILES[$Name]['name'], strrpos($_FILES[$Name]['name'], '/'));
$this->Database->query('INSERT INTO File (`Name`, `Size`) VALUES ("'.$FileName.'", '.filesize($_FILES[$Name]['tmp_name']).')');
$InsertId = $this->Database->insert_id;
if (move_uploaded_file($_FILES[$Name]['tmp_name'], $this->FilesDir.'/'.$InsertId.'_'.$FileName)) $Result = $InsertId;
}
}
return $Result;
}
function DetectMimeType(string $FileName): string
{
$MimeTypes = GetMimeTypes();
$MimeType = pathinfo($FileName, PATHINFO_EXTENSION);
$Result = $MimeTypes[$MimeType][0];
return $Result;
}
function DownloadHash(string $Hash): void
{
$this->Download('Hash="'.addslashes($Hash).'"');
}
function DownloadId(string $Id): void
{
if (!ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('File', 'DownloadById'))
echo('Nemáte oprávnění');
$this->Download('Id='.addslashes($Id));
}
function Download(string $Where): void
{
$DbResult = $this->Database->select('File', '*', $Where);
if ($DbResult->num_rows > 0)
{
$DbRow = $DbResult->fetch_assoc();
if ($DbRow['Directory'] != '') $FileName = $this->GetDir($DbRow['Directory']);
else $FileName = $this->FilesDir;
$FileName .= $DbRow['Name'];
if (file_exists($FileName))
{
Header('Content-Type: '.$this->DetectMimeType($FileName));
Header('Content-Disposition: inline; filename="'.$DbRow['Name'].'"');
echo(file_get_contents($FileName));
} else echo('Soubor nenalezen!');
} else echo('Soubor nenalezen!');
}
function GetDir(string $Id): string
{
$DbResult = $this->Database->select('FileDirectory', '*', 'Id='.$Id);
$DbRow = $DbResult->fetch_assoc();
if ($DbRow['Parent'] != '') $Result = $this->GetDir($DbRow['Parent']);
else $Result = $this->FilesDir;
$Result .= $DbRow['Name'].'/';
return $Result;
}
function GetFullPath(string $Id): string
{
$DbResult = $this->Database->select('File', '*', 'Id='.addslashes($Id));
if ($DbResult->num_rows > 0)
{
$DbRow = $DbResult->fetch_assoc();
if ($DbRow['Directory'] != '') $FileName = $this->GetDir($DbRow['Directory']);
else $FileName = $this->FilesDir;
$FileName .= $DbRow['Name'];
return $FileName;
} else echo('Soubor nenalezen!');
}
}
class PageFile extends Page
{
function Show(): string
{
if (array_key_exists('h', $_GET))
{
$Hash = $_GET['h'];
$this->RawPage = true;
ModuleFile::Cast($this->System->GetModule('File'))->File->DownloadHash($Hash);
return '';
}
else if (array_key_exists('i', $_GET) and is_numeric($_GET['i']))
{
$Id = $_GET['i'] * 1;
$this->RawPage = true;
ModuleFile::Cast($this->System->GetModule('File'))->File->DownloadId($Id);
}
else return $this->SystemMessage('Chyba', 'Nezadáno id souboru');
return '';
}
}
class FileDirectory extends Model
{
static function GetModelDesc(): ModelDesc
{
$Desc = new ModelDesc('FileDirectory');
$Desc->AddString('Name');
$Desc->AddReference('Parent', FileDirectory::GetClassName(), true);
return $Desc;
}
}
class PageFileCheck extends Page
{
function __construct(System $System)
{
parent::__construct($System);
$this->Title = 'File check';
$this->ParentClass = 'PagePortal';
}
function GetAbsolutePath(string $Path): string
{
$Path = trim($Path);
$IsRoot = substr($Path, 0, 1) == '/';
$Path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $Path);
$Parts = array_filter(explode(DIRECTORY_SEPARATOR, $Path), 'strlen');
$Absolutes = array();
foreach ($Parts as $Part)
{
if ('.' == $Part) continue;
if ('..' == $Part)
{
array_pop($Absolutes);
} else
{
$Absolutes[] = $Part;
}
}
$Path = implode(DIRECTORY_SEPARATOR, $Absolutes);
if ($IsRoot) $Path = DIRECTORY_SEPARATOR.$Path;
return $Path;
}
function Show(): string
{
$Output = 'Missing files:
';
if (!ModuleUser::Cast($this->System->GetModule('User'))->User->CheckPermission('File', 'Check'))
return 'Nemáte oprávnění';
$DbResult = $this->Database->select('File', 'Id');
while ($DbRow = $DbResult->fetch_assoc())
{
$Id = $DbRow['Id'];
$FileName = $this->GetAbsolutePath(ModuleFile::Cast($this->System->GetModule('File'))->File->GetFullPath($Id));
if (!file_exists($FileName))
$Output .= ''.$FileName.'
';
}
return $Output;
}
}
class ModuleFile extends Module
{
public File $File;
function __construct(System $System)
{
parent::__construct($System);
$this->Name = 'File';
$this->Version = '1.0';
$this->Creator = 'Chronos';
$this->License = 'GNU/GPLv3';
$this->Description = 'Base module for file management';
$this->Dependencies = array(ModuleUser::GetName());
$this->Models = array(FileDirectory::GetClassName(), File::GetClassName());
$this->File = new File($this->System);
}
function DoStart(): void
{
global $Config;
$this->System->RegisterPage(['file'], 'PageFile');
$this->System->RegisterPage(['file-check'], 'PageFileCheck');
$this->File->FilesDir = dirname(__FILE__).'/../../'.$Config['Web']['UploadFileFolder'];
$this->System->FormManager->RegisterClass('File', array(
'Title' => 'Soubor',
'Table' => 'File',
'Items' => array(
'Name' => array('Type' => 'String', 'Caption' => 'Jméno', 'Default' => ''),
'Directory' => array('Type' => 'TDirectory', 'Caption' => 'Adresář', 'Default' => '', 'Null' => true),
'Size' => array('Type' => 'Integer', 'Caption' => 'Velikost', 'Default' => ''),
'Time' => array('Type' => 'DateTime', 'Caption' => 'Čas vytvoření', 'Default' => ''),
'Hash' => array('Type' => 'String', 'Caption' => 'Haš', 'Default' => ''),
'Invoices' => array('Type' => 'TFinanceInvoiceListFile', 'Caption' => 'Faktury', 'Default' => ''),
'Operations' => array('Type' => 'TFinanceOperationListFile', 'Caption' => 'Operace', 'Default' => ''),
'Contracts' => array('Type' => 'TContractListFile', 'Caption' => 'Smlouvy', 'Default' => ''),
'StockMoves' => array('Type' => 'TStockMoveListFile', 'Caption' => 'Skladové pohyby', 'Default' => ''),
),
'ItemActions' => array(
array('Caption' => 'Stáhnout', 'URL' => '/file?i=#RowId'),
),
'Actions' => array(
array('Caption' => 'Kontrola souborů', 'URL' => '/file-check'),
),
));
$this->System->FormManager->RegisterClass('FileDirectory', array(
'Title' => 'Adresář souborů',
'Table' => 'FileDirectory',
'Items' => array(
'Name' => array('Type' => 'String', 'Caption' => 'Jméno', 'Default' => ''),
'Parent' => array('Type' => 'TDirectory', 'Caption' => 'Nadřazený adresář', 'Default' => '', 'Null' => true),
'Files' => array('Type' => 'TFileList', 'Caption' => 'Soubory', 'Default' => ''),
'Subdirectories' => array('Type' => 'TDirectoryList', 'Caption' => 'Podadresáře', 'Default' => ''),
),
));
$this->System->FormManager->RegisterFormType('TDirectory', array(
'Type' => 'Reference',
'Table' => 'FileDirectory',
'Id' => 'Id',
'Name' => 'Name',
'Filter' => '1',
));
$this->System->FormManager->RegisterFormType('TFile', array(
'Type' => 'Reference',
'Table' => 'File',
'Id' => 'Id',
'Name' => 'Name',
'Filter' => '1',
));
$this->System->FormManager->RegisterFormType('TFileList', array(
'Type' => 'ManyToOne',
'Table' => 'File',
'Id' => 'Id',
'Ref' => 'Directory',
'Filter' => '1',
));
$this->System->FormManager->RegisterFormType('TDirectoryList', array(
'Type' => 'ManyToOne',
'Table' => 'FileDirectory',
'Id' => 'Id',
'Ref' => 'Parent',
'Filter' => '1',
));
$this->System->FormManager->RegisterFormType('TFinanceInvoiceListFile', array(
'Type' => 'ManyToOne',
'Table' => 'FinanceInvoice',
'Id' => 'Id',
'Ref' => 'File',
'Filter' => '1',
));
$this->System->FormManager->RegisterFormType('TFinanceOperationListFile', array(
'Type' => 'ManyToOne',
'Table' => 'FinanceOperation',
'Id' => 'Id',
'Ref' => 'File',
'Filter' => '1',
));
$this->System->FormManager->RegisterFormType('TContractListFile', array(
'Type' => 'ManyToOne',
'Table' => 'Contract',
'Id' => 'Id',
'Ref' => 'File',
'Filter' => '1',
));
$this->System->FormManager->RegisterFormType('TStockMoveListFile', array(
'Type' => 'ManyToOne',
'Table' => 'StockMove',
'Id' => 'Id',
'Ref' => 'File',
'Filter' => '1',
));
}
static function Cast(Module $Module): ModuleFile
{
if ($Module instanceof ModuleFile)
{
return $Module;
}
throw new Exception('Expected ModuleFile type but got '.gettype($Module));
}
}