diff --git a/www/pages/systemhealth.php b/www/pages/systemhealth.php index 5e41a0b1..a685b840 100644 --- a/www/pages/systemhealth.php +++ b/www/pages/systemhealth.php @@ -1,1009 +1,1012 @@ -app = $app; - try { - if(!empty($this->app->Container)) { - $this->gateway = $this->app->Container->get('SystemHealthGateway'); - $this->service = $this->app->Container->get('SystemHealthService'); - } - } - catch(Exception $e) { - - } - if($intern) { - return; - } - $this->app->ActionHandlerInit($this); - - $this->app->ActionHandler('list','SystemhealthList'); - - $this->app->DefaultActionHandler('list'); - - $this->app->ActionHandlerListen($app); - } - - public function SystemhealthMenu() - { - $this->app->erp->MenuEintrag('index.php?module=systemhealth&action=list','Übersicht'); - } - - /** - * @return array - */ - public function getMemory() - { - try { - return $this->service->getMemoryUsage(); - } - catch (Exception $e) { - return []; - } - } - - /** - * @param string $catgoryId - * @param int $nr - * @param string $target - * - * @return bool - */ - public function drawCategory($catgoryId, $nr, $target = 'TAB1') { - if(empty($this->gateway)) { - return false; - } - $category = $this->gateway->getCategoryById($catgoryId); - if(empty($category)) { - return false; - } - if($nr % 2 === 0) { - $this->app->Tpl->Add($target, '
-
'); - } - $this->app->Tpl->Set('CATEGORYTITLE', !empty($category['description'])?$category['description']:$category['name']); - $systemHealthEntries = $this->gateway->getEntriesByCategoryId($catgoryId); - $notifications = $this->gateway->getItemNoticiationsByUserId($this->app->User->GetID(), $catgoryId); - $this->app->Tpl->Set('ENTRIES',''); - $icons = [ - '' => 'unbekannt', - 'ok' => 'OK', - 'warning' => 'Warnung', - 'error' => 'Fehler', - ]; - foreach($systemHealthEntries as $systemHealthEntry) { - $this->app->Tpl->Add( - 'ENTRIES', - ' - '.$systemHealthEntry['description'].': - '.$icons[strtolower($systemHealthEntry['status'])].' - '.$systemHealthEntry['message'].' - !'. - (empty($systemHealthEntry['resetable'])?'': - 'Meldung zurücksetzen ' - ).' - - ' - ); - } - - $this->app->Tpl->Parse($target, 'systemhealth_fieldset.tpl'); - if($nr % 2 === 1) { - $this->app->Tpl->Add($target, '
'); - } - - return true; - } - - public function SystemhealthList() - { - $cmd = $this->app->Secure->GetGET('cmd'); - if($cmd === 'reset') { - $id = $this->app->Secure->GetPOST('id'); - - try { - $this->service->resetStatus($id); - $status = 1; - } - catch(Exception $e) { - $status = 0; - } - header('Content-Type: application/json'); - echo json_encode(['status' => $status]); - $this->app->ExitXentral(); - } - - if($this->app->Secure->GetPOST('reset')) { - $this->app->DB->Update( - sprintf( - "UPDATE systemhealth SET status = '', message = '', last_reset = NOW() WHERE status <> '' OR message <> ''" - ) - ); - $this->fillEntries(); - $this->app->Location->execute('index.php?module=systemhealth&action=list'); - } - - if($cmd === 'changenotification') { - $value = $this->app->Secure->GetPOST('value'); - $systemhealthId = $this->app->Secure->GetPOST('id'); - try{ - $status = 1; - if(empty($value)){ - $this->service->deleteSystemHealthItemNotificationSetting($systemhealthId, $this->app->User->GetID()); - } - else { - $this->service->createSystemHealthItemNotificationSetting($systemhealthId, $this->app->User->GetID()); - } - } - catch(Exception $e) { - $status = 0; - } - header('Content-Type: application/json'); - echo json_encode( - [ - 'status' => $status,'value' => $value,'id' => $systemhealthId - ] - ); - $this->app->ExitXentral(); - } - - $this->SystemhealthMenu(); - - $this->app->erp->Headlines('System-Meldungen'); - - $this->loadFreeDisc(); - $data = $this->getHealthData(); - if(empty($data)) { - $this->Install(); - } - $categories = $this->gateway->getCategories(); - $nr = 0; - foreach($categories as $category) { - if($this->drawCategory($category['id'], $nr)) { - $nr++; - } - } - if($nr % 2 === 0) { - $this->app->Tpl->Add('TAB1',''); - } - else{ - $this->app->Tpl->Set('CATEGORYTITLE',''); - $this->app->Tpl->Set('ENTRIES',''); - $this->app->Tpl->Parse('TAB1','systemhealth_fieldset.tpl'); - } - $this->app->erp->checkActiveCronjob('systemhealth'); - $this->app->Tpl->Parse('PAGE', 'systemhealth_list.tpl'); - } - - public function Install() - { - $this->app->erp->CheckTable('systemhealth'); - $this->app->erp->CheckColumn('systemhealth_category_id','INT(11)','systemhealth','DEFAULT 0 NOT NULL'); - $this->app->erp->CheckColumn('name','VARCHAR(64)','systemhealth',"DEFAULT '' NOT NULL"); - $this->app->erp->CheckColumn('description','VARCHAR(64)','systemhealth',"DEFAULT '' NOT NULL"); - $this->app->erp->CheckColumn('status','VARCHAR(64)','systemhealth',"DEFAULT '' NOT NULL"); - $this->app->erp->CheckColumn('message','VARCHAR(255)','systemhealth',"DEFAULT '' NOT NULL"); - $this->app->erp->CheckColumn('created_at','TIMESTAMP','systemhealth','DEFAULT CURRENT_TIMESTAMP NOT NULL'); - $this->app->erp->CheckColumn('lastupdate','TIMESTAMP','systemhealth', 'NULL DEFAULT NULL'); - $this->app->erp->CheckColumn('resetable','TINYINT(1)','systemhealth', 'DEFAULT 0 NOT NULL'); - $this->app->erp->CheckColumn('last_reset','TIMESTAMP','systemhealth', 'NULL DEFAULT NULL'); - $this->app->erp->CheckIndex('systemhealth', 'systemhealth_category_id'); - $this->app->erp->CheckIndex('systemhealth', 'name'); - - $this->app->erp->CheckTable('systemhealth_category'); - $this->app->erp->CheckColumn('name','VARCHAR(64)','systemhealth_category',"DEFAULT '' NOT NULL"); - $this->app->erp->CheckColumn('description','TEXT','systemhealth_category'); - $this->app->erp->CheckColumn('created_at','TIMESTAMP','systemhealth_category'); - $this->app->erp->CheckIndex('systemhealth_category', 'name'); - - $this->app->erp->CheckTable('systemhealth_custom_error_lvl'); - $this->app->erp->CheckColumn('systemhealth_id','INT(11)','systemhealth_custom_error_lvl','DEFAULT 0 NOT NULL'); - $this->app->erp->CheckColumn('status','VARCHAR(64)','systemhealth_custom_error_lvl',"DEFAULT '' NOT NULL"); - $this->app->erp->CheckIndex('systemhealth_custom_error_lvl', 'systemhealth_id'); - - $this->app->erp->CheckTable('systemhealth_notification'); - $this->app->erp->CheckColumn('status','VARCHAR(64)','systemhealth_notification',"DEFAULT '' NOT NULL"); - $this->app->erp->CheckColumn('email','VARCHAR(255)','systemhealth_notification',"DEFAULT '' NOT NULL"); - - $this->app->erp->CheckTable('systemhealth_notification_item'); - $this->app->erp->CheckColumn('systemhealth_id','INT(11)','systemhealth_notification_item','DEFAULT 0 NOT NULL'); - $this->app->erp->CheckColumn('user_id','INT(11)','systemhealth_notification_item','DEFAULT 0 NOT NULL'); - $this->app->erp->CheckColumn('status','VARCHAR(64)','systemhealth_notification_item',"DEFAULT '' NOT NULL"); - $this->app->erp->CheckColumn('email','VARCHAR(255)','systemhealth_notification_item',"DEFAULT '' NOT NULL"); - $this->app->erp->CheckIndex('systemhealth_notification_item', 'systemhealth_id'); - - $this->app->erp->CheckTable('systemhealth_event'); - $this->app->erp->CheckColumn('systemhealth_id','INT(11)','systemhealth_event','DEFAULT 0 NOT NULL'); - $this->app->erp->CheckColumn('created_at','TIMESTAMP','systemhealth_event','DEFAULT CURRENT_TIMESTAMP NOT NULL'); - $this->app->erp->CheckColumn('doctype','VARCHAR(64)','systemhealth_event',"DEFAULT '' NOT NULL"); - $this->app->erp->CheckColumn('doctype_id','INT(11)','systemhealth_event','DEFAULT 0 NOT NULL'); - $this->app->erp->CheckColumn('status','VARCHAR(64)','systemhealth_event',"DEFAULT '' NOT NULL"); - $this->app->erp->CheckColumn('message','VARCHAR(255)','systemhealth_event',"DEFAULT '' NOT NULL"); - $this->app->erp->CheckIndex('systemhealth_event', 'systemhealth_id'); - $this->app->erp->CheckIndex('systemhealth_event', 'created_at'); - - $this->app->erp->CheckProzessstarter('SystemHealth', 'periodisch', '1440', '', 'cronjob', 'systemhealth', 1); - $this->app->erp->RegisterHook('eproosystem_iconboxes_start','systemhealth','SystemHealthIconBoxedStart'); - - $this->checkEntries(); - $this->fillEntries(); - - $userDataEntry = $this->app->DB->Select( - "SELECT COUNT(sh.id) AS `total` FROM `systemhealth` AS `sh` - WHERE sh.name = 'userdata_writeable' - AND MD5('Schreibrechte in Userdata') != MD5(sh.description) LIMIT 1" - ); - if($userDataEntry > 0){ - $this->app->DB->Update( - "UPDATE `systemhealth` SET `description` = 'Schreibrechte in Userdata' WHERE `name` = 'userdata_writeable'"); - } - } - - /** - * @param string $categoryName - * @param string $systemHealthName - * @param string $status - * @param string $doctype - * @param int $doctypeId - * @param string $message - */ - public function createEvent($categoryName, $systemHealthName, $status, $doctype, $doctypeId, $message = '') - { - try { - $category = $this->gateway->getCategoryByName($categoryName); - if(empty($category)) { - return; - } - $systemHealth = $this->gateway->getByName($category['id'], $systemHealthName); - if(empty($systemHealth)) { - return; - } - $this->service->createEvent($systemHealth['id'], $status, $doctype, $doctypeId, $message); - } - catch(Exception $e) { - - } - } - - /** - * @param int $boxCount - */ - public function SystemHealthIconBoxedStart(&$boxCount) - { - if(empty($this->gateway) || !$this->app->erp->RechteVorhanden('systemhealth', 'list')) { - return; - } - - $boxCount++; - $counter = ''; - $status = $this->gateway->getStatusCount(); - $errorClass = ''; - $isWarning = !empty($status['warning']); - if(!empty($status['error'])) { - $errorClass = ' countererror'; - $counter = $status['error']; - if($isWarning) { - $counter .= '/'.$status['warning']; - } - } - elseif($isWarning) { - $counter = $status['warning']; - $errorClass = ' counterwarning'; - } - - $this->app->Tpl->Add( - 'ICONBOXESHOOK1', - '
  • - - - '.$counter.' - - - - - - - - - - - - -
  • ' - ); - } - - public function checkEntries() - { - if(empty($this->gateway) || empty($this->service)) { - return; - } - $this->app->DB->Update( - "UPDATE systemhealth SET description = 'DB-Version ab 20.2' WHERE description = 'DB-Version ab 20.1'" - ); - $categories = $this->getDefaultCategories(); - foreach($this->getValues() as $category => $names) { - $categoryRow = $this->gateway->getCategoryByName($category); - if(empty($categoryRow)) { - try { - $categoryId = $this->service->createCategory($category, $categories[$category]); - } - catch(Exception $e) { - continue; - } - } - else { - $categoryId = $categoryRow['id']; - } - foreach($names as $name => $description) { - $resetAble = false; - if(is_array($description)) { - $resetAble = !empty($description[1]); - $description = reset($description); - } - $systemHealth = $this->gateway->getByName($categoryId, $name); - if(empty($systemHealth)) { - $this->service->create($categoryId, $name, $description, '', $resetAble); - } - elseif($resetAble && empty($systemHealth['resetable'])) { - $this->service->update($systemHealth['id'], $description, $systemHealth['status'], $resetAble); - } - } - } - } - - /** - * @param string $categoryKey - * @param string $categoryTitle - * @param string $entryKey - * @param string $entryTitle - * @param string $status - * @param string $message - * @param bool $resetAble - */ - public function createEntryWithCategoryIfError( - $categoryKey, $categoryTitle, $entryKey, $entryTitle, $status, $message = '', $resetAble = false - ) - { - if(empty($categoryKey) || empty($entryKey) || empty($status)) { - return; - } - try { - $category = $this->gateway->getCategoryByName($categoryKey); - if($status === 'error' || $status === 'warning'){ - if(empty($category)) { - $this->service->createCategory($categoryKey, $categoryTitle); - } - $this->createEntryIfError($categoryKey, $entryKey, $entryTitle, $status, $message, $resetAble); - } - else { - if(empty($category)) { - return; - } - $this->createEntryIfError($categoryKey, $entryKey, $entryTitle, $status, $message, $resetAble); - } - } - catch (Exception $e) { - - } - } - - /** - * @param string $categoryKey - * @param string $entryKey - * @param string $entryTitle - * @param string $status - * @param string $message - * @param bool $resetable - */ - public function createEntryIfError($categoryKey, $entryKey, $entryTitle, $status, $message = '', $resetable = false) - { - try { - if($status === 'error' || $status === 'warning'){ - $category = $this->gateway->getCategoryByName($categoryKey); - $systemHealth = $this->gateway->getByName($category['id'], $entryKey); - if(empty($systemHealth)){ - $this->service->create($category['id'], $entryKey, $entryTitle, '', $resetable); - } - $this->changeStatus( - $categoryKey, $entryKey, $status, $message - ); - return; - } - if($status === 'ok'){ - $category = $this->gateway->getCategoryByName($categoryKey); - $systemHealth = $this->gateway->getByName($category['id'], $entryKey); - if(!empty($systemHealth)){ - $this->changeStatus( - $categoryKey, $entryKey, 'ok', '' - ); - } - } - } - catch(Exception $e) { - - } - } - - public function fillEntries() - { - $phpVersion = substr(PHP_VERSION,0,3); - if($phpVersion < 7.2) { - $status = 'warning'; - $phpVersion = 'Ab Xentral 20.2 benötigen Sie mind. PHP 7.2 (aktuell '.$phpVersion - .'). Hilfe'; - } - else { - $status = 'ok'; - } - $this->changeStatus('server', 'php_version', $status, $phpVersion); - - $dbType = ''; - if(method_exists($this->app->DB, 'GetVersionArr')) { - list($dbType, $dbVersion) = $this->app->DB->GetVersionArr(); - if($dbType === 'mysql') { - $status = 'warning'; - if($dbVersion >= 5.7) { - $status = 'ok'; - } - $mysqlVersion = 'MySQL '.$dbVersion; - } - elseif($dbType === 'mariadb') { - $status = 'warning'; - if($dbVersion >= 10.2) { - $status = 'ok'; - } - $mysqlVersion = 'MariaDB '.$dbVersion; - } - else { - $dbType = ''; - } - } - if(empty($dbType)) { - $mysqlVersion = $this->app->DB->GetVersion(); - $mysqlVersion = $mysqlVersion[0] . '.' . $mysqlVersion[1]; - $status = 'warning'; - if($mysqlVersion >= 5.5){ - $status = 'ok'; - } - } - //@todo select version() >= 10.2 mariadb + update.php prüfung - $this->changeStatus('database', 'db_version', $status, $mysqlVersion); - if($status === 'warning') { - $mysqlVersion = 'Ab Xentral 20.2 benötigen Sie mind. MySQL 5.7 / MariaDb 10.2 (aktuell '.$mysqlVersion - .'). Hilfe'; - } - $this->changeStatus('database', 'db_version_min', $status, $mysqlVersion); - - $system_cronjob_memory_limit = (string)$this->app->erp->GetKonfiguration('system_cronjob_memory_limit'); - if($system_cronjob_memory_limit === '-1' || $system_cronjob_memory_limit === '0') - { - $this->changeStatus('cronjobs','max_memory','ok','OK (unbegrenzt)'); - } - elseif(!empty($system_cronjob_memory_limit)) { - if($system_cronjob_memory_limit <= 64 * 1024 * 1024) { - $this->changeStatus('cronjobs','max_memory','warning','Es werden mindestens 256 MB empfohlen (' - .round($system_cronjob_memory_limit / 1024 / 1024) .' MB eingestellt)'); - } - elseif($system_cronjob_memory_limit < 256 * 1024 * 1024) { - $this->changeStatus('cronjobs','max_memory','warning','Es werden mindestens 256 MB empfohlen (' - .round($system_cronjob_memory_limit / 1024 / 1024) .' MB eingestellt)'); - } - else { - $this->changeStatus('cronjobs','max_memory','ok','OK ('.round($system_cronjob_memory_limit / 1024 / 1024) .' MB)'); - } - } - $system_cronjob_max_execution_time = (string)$this->app->erp->GetKonfiguration('system_cronjob_max_execution_time'); - if($system_cronjob_max_execution_time === '0') { - $this->changeStatus('cronjobs','max_execution_time','ok','unbegrenzt'); - } - elseif(!empty($system_cronjob_max_execution_time)) { - if($system_cronjob_max_execution_time < 30) { - $this->changeStatus('cronjobs','max_execution_time','warning','< 30 Sekunden ('.$system_cronjob_max_execution_time.' Sekunden)'); - } - elseif($system_cronjob_max_execution_time < 300){ - $this->changeStatus('cronjobs','max_execution_time','warning','< 300 Sekunden ('.$system_cronjob_max_execution_time.' Sekunden)'); - } - else { - $this->changeStatus('cronjobs','max_execution_time','ok','OK ('.$system_cronjob_max_execution_time.' Sekunden)'); - } - } - - $hintergrund=$this->app->erp->Firmendaten('hintergrund'); - $hintergrund_size = 0; - switch($hintergrund) { - case 'briefpapier': - $hintergrund_size = strlen($this->app->erp->getSettingsFile('briefpapier')); - break; - case 'logo': - $hintergrund_size = strlen($this->app->erp->getSettingsFile('logo')); - break; - } - - if($hintergrund_size / 1000 > 100){ - $this->changeStatus( - 'settings', - 'letterhead', - 'warning', - 'Die Dateigröße von ca. '.round($hintergrund_size / 1000). - ' KB vom ' . ucfirst($hintergrund) . ' ist zu groß. Das ' . ucfirst($hintergrund) . - ' sollte unter 100 KB sein'); - } - else { - $this->changeStatus('settings','letterhead','ok','OK'); - } - - $this->loadFreeDisc(); - if((string)1.1 === '1,1') { - $category = $this->gateway->getCategoryByName('server'); - $name = 'locale_lc_numeric'; - $description = 'Decimaltrennzeichen Einstellung'; - $systemHealth = $this->gateway->getByName($category['id'], $name); - if(empty($systemHealth)) { - $this->service->create($category['id'], $name, $description, '', false); - } - $this->changeStatus( - 'server',$name,'error','Die lokale Decimal Trennzeicheneinstellung ist fehlerhaft' - ); - } - else { - $category = $this->gateway->getCategoryByName('server'); - $name = 'locale_lc_numeric'; - $systemHealth = $this->gateway->getByName($category['id'], $name); - if(!empty($systemHealth)) { - $this->changeStatus( - 'server',$name,'ok','' - ); - } - } - if(!function_exists('imap_open')) { - $category = $this->gateway->getCategoryByName('server'); - $name = 'imap_plugin'; - $description = 'IMAP Plugin'; - $systemHealth = $this->gateway->getByName($category['id'], $name); - if(empty($systemHealth)) { - $this->service->create($category['id'], $name, $description, '', false); - } - $this->changeStatus( - 'server',$name,'error','IMAP ist nicht installiert' - ); - } - else { - $category = $this->gateway->getCategoryByName('server'); - $name = 'imap_plugin'; - $systemHealth = $this->gateway->getByName($category['id'], $name); - if(!empty($systemHealth)) { - $this->changeStatus( - 'server',$name,'ok','' - ); - } - } - $this->app->erp->RunHook('systemhealth_fill_entries'); - } - - public function loadFreeDisc(): void - { - $free = $this->getDiskFree(); - if($free === false) { - $this->changeStatus('server', 'disk_space', 'warning', 'Der freie Speicherplatz konnte nicht ermittelt werden'); - } - else{ - $free /= 1024 * 1024; - $userdataSize = (int)$this->app->erp->GetKonfiguration('userdatasize'); - $dbSize = $this->getDbSize(); - if(is_array($dbSize)) { - $dbSize = $dbSize['all']; - } - $minFree = (int)($dbSize / 1024) + $userdataSize + 512; - if($minFree < 2048) { - $minFree = 2048; - } - if($free < 512) { - $this->changeStatus('server', 'disk_space', 'error', 'Es sind nur ' . round($free) . ' MB Speicherplatz frei'); - } - elseif($free < $minFree) { - $this->changeStatus('server', 'disk_space', 'warning', 'Es sind nur ' . round($free) . ' MB Speicherplatz frei'); - } - else { - $this->changeStatus('server', 'disk_space', 'ok', 'Es sind ' . round($free) . ' MB Speicherplatz frei'); - } - } - } - - /** - * @param string $category - * @param string $name - * @param string $status - * @param string $message - */ - public function changeStatus($category, $name, $status, $message) - { - if(empty($this->gateway) || empty($this->service)) { - return; - } - try { - $categoryRow = $this->gateway->getCategoryByName($category); - if(empty($categoryRow)) { - return; - } - $categoryId = $categoryRow['id']; - - $systemHealth = $this->gateway->getByName($categoryId, $name); - if(empty($systemHealth)) { - return; - } - - $this->service->setStatus($systemHealth['id'], $status, $message); - } - catch(Exception $e) { - - } - } - - /** - * @return array - */ - public function getDefaultCategories() - { - return [ - 'masterdata' => 'Stammdaten', - 'bestbeforebatchsn' => 'MHD / Chargen / Seriennummern', - 'server' => 'Server', - 'settings' => 'Einstellungen', - 'cronjobs' => 'Prozessstarter', - 'database' => 'Datenbank', - 'shopexport' => 'Onlineshops', - ]; - } - - /** - * @return array - */ - public function getValues() - { - return [ - 'masterdata' => [ - 'double_articlenumber' => ['Artikelnummern', true], - 'double_suppliernumber' => ['Lieferantennummern', true], - 'double_customernumber' => ['Kundennummern', true], - 'empty_articlenumber' => ['Leere Artikelnummern', true], - 'double_invoice' => ['Rechnungsnummern', true], - 'double_return_order' => ['Gutschriftsnummern', true], - ], - 'bestbeforebatchsn' => [ - 'sn' => ['Seriennummern', true], - 'batch' => ['Chargen-Schiefstand', true], - 'bestbefore' => ['MHD-Schiefstand', true], - 'expiredbestbefore' => ['abgelaufene MHD', true], - ], - 'server' => [ - 'php_version' => 'PHP-Version', - 'extension_zip' => 'Zip Extension', - 'disk_space' => 'Speicherplatz', - 'max_upload' => 'Upload-Kapazität', - 'max_execution_time' => 'Scriptlauftzeit', - 'userdata_writeable' => 'Schreibrechte in Userdata', - 'ioncube' => 'Lizenz', - 'tls1-2' => 'TLS v1.2', - ], - 'settings' => [ - 'company_settings' => 'Firmendaten', - 'letterhead' => 'Briefpapier', - ], - 'cronjobs' => [ - 'lastrunning' => 'Aktivität', - 'frequently' => 'Häufigkeit', - 'max_memory' => 'Speicher', - 'out_of_memory' => ['Speicherüberlauf', true], - 'max_execution_time' => 'Laufzeit', - 'errors' => ['Fehler', true] - ], - 'database' => [ - 'db_version' => 'DB-Version', - 'db_version_min' => 'DB-Version ab 20.2', - 'sql_errors' => ['SQL-Fehler', true], - 'sql_integrity' => ['Datenintegrität', true], - ], - 'shopexport' => [ - 'auth' => ['Authentifizierung', true], - ], - ]; - } - - /** - * @return array - */ - public function getTableSizes() - { - try{ - return $this->service->getTableSizes($this->app->Conf->WFdbname); - } - catch(Exception $e) { - return []; - } - } - - /** - * @return array - */ - public function getLogTables() - { - return [ - 'shopexport_log', - 'logfile', - 'protokoll', - 'logfile', - 'cronjob_log', - 'cronjob_starter_running', - 'uebertragungen_monitor', - 'adapterbox_request_log', - 'versandzentrum_log', - ]; - } - - /** - * @var bool $splittedLogs - * - * @return int|array - */ - public function getDbSize($splittedLogs = false) - { - if($splittedLogs) { - try { - $dbSize = $this->service->getTableSizes($this->app->Conf->WFdbname); - if(empty($dbSize)) { - return 0; - } - $ret = ['all' => 0., 'log' => 0.]; - $logTables = $this->getLogTables(); - foreach($dbSize as $table => $size) { - $ret['all'] += (float)$size; - if(in_array($table, $logTables,true)) { - $ret['log'] += (float)$size; - } - } - - return $ret; - } - catch(Exception $e) { - return 0; - } - } - - try { - return $this->service->getDbSize($this->app->Conf->WFdbname); - } - catch(Exception $e) { - return 0; - } - } - - /** - * @return array - */ - public function getSystemLoad() - { - try { - return $this->service->getSystemLoad(); - } - catch(Exception $e) { - return [null, null, null, null, null]; - } - } - - /** - * @param float|int $tresholdAct - * @param float|int $treshold5Min - * - * @return bool - */ - public function isSystemLoadHigh($tresholdAct = 5.0, $treshold5Min = 5.0) - { - $systemLoad = $this->getSystemLoad(); - $loadAct = empty($systemLoad['act'])?0:$systemLoad['act']; - $load5min = empty($systemLoad['5min'])?0:$systemLoad['5min']; - - return $loadAct > $tresholdAct || $load5min > $treshold5Min; - } - - /** - * @param string $dir - * - * @return false|float - */ - public function getDiskFree($dir = '') - { - try{ - return $this->service->getDiskFree($dir); - } - catch(Exception $e) { - return false; - } - } - - /** - * @param string|array $type - * - * @return int|array - */ - public function getUserdataSpace($type = '') - { - $dir = $this->app->Conf->WFuserdata; - if(is_array($type)) { - $ret = []; - $excludes = []; - $sum = 0; - foreach($type as $key => $typeString) { - if(empty(trim($typeString))) { - unset($type[$key]); - continue; - } - try { - $ret[$typeString] = $this->service->getUsedSpace($this->app->Conf->WFuserdata.'/'.$typeString, []); - $sum += $ret[$typeString]; - } - catch (Exception $e) { - $ret[$typeString] = 0; - } - $excludes[] = './'.$typeString; - } - try { - $ret['sum'] = $sum + $this->service->getUsedSpace($this->app->Conf->WFuserdata, $excludes); - } - catch(Exception $e) { - $ret['sum'] = $sum; - } - - return $ret; - } - $exclude = []; - switch($type) { - case 'userdatawithoutdmspdfarchiv': - $dir = $this->app->Conf->WFuserdata; - $exclude = ['./pdfarchiv', './dms']; - break; - case 'dms': - $dir = $this->app->Conf->WFuserdata.'/dms'; - break; - case 'pdfarchiv': - $dir = $this->app->Conf->WFuserdata.'/pdfarchiv'; - break; - default: - if(strpos($type, '.') !== false && is_dir($this->app->Conf->WFuserdata.'/'.$type)) { - $dir = $this->app->Conf->WFuserdata.'/'.$type; - } - break; - } - try { - return $this->service->getUsedSpace($dir, $exclude); - } - catch (Exception $e) { - return 0; - } - } - - /** - * @return int[] - */ - public function getUserDataSpaces() - { - return $this->getUserdataSpace( - [ - 'dms', - 'pdfarchiv', - 'pdfmirror', - 'tmp', - 'wiki', - 'emailbackup', - 'uebertragung', - ] - ); - } - - /** - * @var string $dir - * - * @return array - */ - public function getPartions($dir = '') - { - try{ - return $this->service->getPartions($dir); - } - catch (Exception $e) { - - } - - return []; - } - - public function doCronjob() - { - $userDataSpaces = $this->getUserDataSpaces(); - foreach($userDataSpaces as $userDataDir => $userDataSpace) { - if($userDataDir === 'sum') { - $this->app->erp->SetKonfigurationValue('userdatasize', (int)ceil($userDataSpace / 1024)); - } - else { - $this->app->erp->SetKonfigurationValue('userdata'.$userDataDir.'size', (int)ceil($userDataSpace / 1024)); - } - } - try{ - $backupSize = (int)$this->service->getUsedSpace(dirname(__DIR__,2).'/backup'); - } - catch (Exception $e) { - $backupSize = 0; - } - $this->app->erp->SetKonfigurationValue('backupsize', (int)ceil($backupSize / 1024)); - $dbSize = $this->getDbSize(true); - $dbSizeLog = 0; - if(is_array($dbSize)) { - if(!empty($dbSize['log'])) { - $dbSizeLog = $dbSize['log']; - } - $dbSize = $dbSize['all']; - } - - $this->app->erp->SetKonfigurationValue('databasesize', (int)ceil($dbSize / 1024)); - $this->app->erp->SetKonfigurationValue('databasesizelog', (int)ceil($dbSizeLog / 1024)); - $this->app->erp->SetKonfigurationValue('diskfree', (int)floor($this->getDiskFree() / 1024 / 1024)); - $this->app->erp->SetKonfigurationValue('lastsizeupdate', date('Y-m-d H:i:s')); - - $partitions = $this->getPartions(dirname(__DIR__, 2)); - if(!empty($partitions)) { - $this->app->erp->SetKonfigurationValue('partitiontotal', (int)($partitions['total'] / 1024)); - $this->app->erp->SetKonfigurationValue('partitionused', (int)($partitions['used'] / 1024)); - $this->app->erp->SetKonfigurationValue('partitionfree', (int)($partitions['free'] / 1024)); - } - - $this->fillEntries(); - $this->app->erp->RunHook('systemhealth_cronjob'); - } - - /** - * @return array - */ - public function getHealthData() - { - $ret = []; - $healthData = $this->app->DB->SelectArr('SELECT * FROM `systemhealth` ORDER BY `id`'); - foreach($healthData as $healthRow) { - $ret[$healthRow['category']][$healthRow['name']] = $healthRow; - } - - return $ret; - } -} +app = $app; + try { + if(!empty($this->app->Container)) { + $this->gateway = $this->app->Container->get('SystemHealthGateway'); + $this->service = $this->app->Container->get('SystemHealthService'); + } + } + catch(Exception $e) { + + } + if($intern) { + return; + } + $this->app->ActionHandlerInit($this); + + $this->app->ActionHandler('list','SystemhealthList'); + + $this->app->DefaultActionHandler('list'); + + $this->app->ActionHandlerListen($app); + } + + public function SystemhealthMenu() + { + $this->app->erp->MenuEintrag('index.php?module=systemhealth&action=list','Übersicht'); + } + + /** + * @return array + */ + public function getMemory() + { + try { + return $this->service->getMemoryUsage(); + } + catch (Exception $e) { + return []; + } + } + + /** + * @param string $catgoryId + * @param int $nr + * @param string $target + * + * @return bool + */ + public function drawCategory($catgoryId, $nr, $target = 'TAB1') { + if(empty($this->gateway)) { + return false; + } + $category = $this->gateway->getCategoryById($catgoryId); + if(empty($category)) { + return false; + } + if($nr % 2 === 0) { + $this->app->Tpl->Add($target, '
    +
    '); + } + $this->app->Tpl->Set('CATEGORYTITLE', !empty($category['description'])?$category['description']:$category['name']); + $systemHealthEntries = $this->gateway->getEntriesByCategoryId($catgoryId); + $notifications = $this->gateway->getItemNoticiationsByUserId($this->app->User->GetID(), $catgoryId); + $this->app->Tpl->Set('ENTRIES',''); + $icons = [ + '' => 'unbekannt', + 'ok' => 'OK', + 'warning' => 'Warnung', + 'error' => 'Fehler', + ]; + foreach($systemHealthEntries as $systemHealthEntry) { + $this->app->Tpl->Add( + 'ENTRIES', + ' + '.$systemHealthEntry['description'].': + '.$icons[strtolower($systemHealthEntry['status'])].' + '.$systemHealthEntry['message'].' + !'. + (empty($systemHealthEntry['resetable'])?'': + 'Meldung zurücksetzen ' + ).' + + ' + ); + } + + $this->app->Tpl->Parse($target, 'systemhealth_fieldset.tpl'); + if($nr % 2 === 1) { + $this->app->Tpl->Add($target, '
    '); + } + + return true; + } + + public function SystemhealthList() + { + $cmd = $this->app->Secure->GetGET('cmd'); + if($cmd === 'reset') { + $id = $this->app->Secure->GetPOST('id'); + try { + $this->service->resetStatus($id); + $status = 1; + } + catch(Exception $e) { + $status = 0; + } + $this->fillEntries(); + header('Content-Type: application/json'); + echo json_encode(['status' => $status]); + $this->app->ExitXentral(); + } + + if($this->app->Secure->GetPOST('reset')) { + $this->app->DB->Update( + sprintf( + "UPDATE systemhealth SET status = '', message = '', last_reset = NOW() WHERE status <> '' OR message <> ''" + ) + ); + $this->fillEntries(); + $this->app->Location->execute('index.php?module=systemhealth&action=list'); + } + + if($cmd === 'changenotification') { + $value = $this->app->Secure->GetPOST('value'); + $systemhealthId = $this->app->Secure->GetPOST('id'); + try{ + $status = 1; + if(empty($value)){ + $this->service->deleteSystemHealthItemNotificationSetting($systemhealthId, $this->app->User->GetID()); + } + else { + $this->service->createSystemHealthItemNotificationSetting($systemhealthId, $this->app->User->GetID()); + } + } + catch(Exception $e) { + $status = 0; + } + header('Content-Type: application/json'); + echo json_encode( + [ + 'status' => $status,'value' => $value,'id' => $systemhealthId + ] + ); + $this->app->ExitXentral(); + } + + $this->SystemhealthMenu(); + + $this->app->erp->Headlines('System-Meldungen'); + + $this->loadFreeDisc(); + $data = $this->getHealthData(); + if(empty($data)) { + $this->Install(); + } + $categories = $this->gateway->getCategories(); + $nr = 0; + foreach($categories as $category) { + if($this->drawCategory($category['id'], $nr)) { + $nr++; + } + } + if($nr % 2 === 0) { + $this->app->Tpl->Add('TAB1',''); + } + else{ + $this->app->Tpl->Set('CATEGORYTITLE',''); + $this->app->Tpl->Set('ENTRIES',''); + $this->app->Tpl->Parse('TAB1','systemhealth_fieldset.tpl'); + } + $this->app->erp->checkActiveCronjob('systemhealth'); + $this->app->Tpl->Parse('PAGE', 'systemhealth_list.tpl'); + } + + public function Install() + { + $this->app->erp->CheckTable('systemhealth'); + $this->app->erp->CheckColumn('systemhealth_category_id','INT(11)','systemhealth','DEFAULT 0 NOT NULL'); + $this->app->erp->CheckColumn('name','VARCHAR(64)','systemhealth',"DEFAULT '' NOT NULL"); + $this->app->erp->CheckColumn('description','VARCHAR(64)','systemhealth',"DEFAULT '' NOT NULL"); + $this->app->erp->CheckColumn('status','VARCHAR(64)','systemhealth',"DEFAULT '' NOT NULL"); + $this->app->erp->CheckColumn('message','VARCHAR(255)','systemhealth',"DEFAULT '' NOT NULL"); + $this->app->erp->CheckColumn('created_at','TIMESTAMP','systemhealth','DEFAULT CURRENT_TIMESTAMP NOT NULL'); + $this->app->erp->CheckColumn('lastupdate','TIMESTAMP','systemhealth', 'NULL DEFAULT NULL'); + $this->app->erp->CheckColumn('resetable','TINYINT(1)','systemhealth', 'DEFAULT 0 NOT NULL'); + $this->app->erp->CheckColumn('last_reset','TIMESTAMP','systemhealth', 'NULL DEFAULT NULL'); + $this->app->erp->CheckIndex('systemhealth', 'systemhealth_category_id'); + $this->app->erp->CheckIndex('systemhealth', 'name'); + + $this->app->erp->CheckTable('systemhealth_category'); + $this->app->erp->CheckColumn('name','VARCHAR(64)','systemhealth_category',"DEFAULT '' NOT NULL"); + $this->app->erp->CheckColumn('description','TEXT','systemhealth_category'); + $this->app->erp->CheckColumn('created_at','TIMESTAMP','systemhealth_category'); + $this->app->erp->CheckIndex('systemhealth_category', 'name'); + + $this->app->erp->CheckTable('systemhealth_custom_error_lvl'); + $this->app->erp->CheckColumn('systemhealth_id','INT(11)','systemhealth_custom_error_lvl','DEFAULT 0 NOT NULL'); + $this->app->erp->CheckColumn('status','VARCHAR(64)','systemhealth_custom_error_lvl',"DEFAULT '' NOT NULL"); + $this->app->erp->CheckIndex('systemhealth_custom_error_lvl', 'systemhealth_id'); + + $this->app->erp->CheckTable('systemhealth_notification'); + $this->app->erp->CheckColumn('status','VARCHAR(64)','systemhealth_notification',"DEFAULT '' NOT NULL"); + $this->app->erp->CheckColumn('email','VARCHAR(255)','systemhealth_notification',"DEFAULT '' NOT NULL"); + + $this->app->erp->CheckTable('systemhealth_notification_item'); + $this->app->erp->CheckColumn('systemhealth_id','INT(11)','systemhealth_notification_item','DEFAULT 0 NOT NULL'); + $this->app->erp->CheckColumn('user_id','INT(11)','systemhealth_notification_item','DEFAULT 0 NOT NULL'); + $this->app->erp->CheckColumn('status','VARCHAR(64)','systemhealth_notification_item',"DEFAULT '' NOT NULL"); + $this->app->erp->CheckColumn('email','VARCHAR(255)','systemhealth_notification_item',"DEFAULT '' NOT NULL"); + $this->app->erp->CheckIndex('systemhealth_notification_item', 'systemhealth_id'); + + $this->app->erp->CheckTable('systemhealth_event'); + $this->app->erp->CheckColumn('systemhealth_id','INT(11)','systemhealth_event','DEFAULT 0 NOT NULL'); + $this->app->erp->CheckColumn('created_at','TIMESTAMP','systemhealth_event','DEFAULT CURRENT_TIMESTAMP NOT NULL'); + $this->app->erp->CheckColumn('doctype','VARCHAR(64)','systemhealth_event',"DEFAULT '' NOT NULL"); + $this->app->erp->CheckColumn('doctype_id','INT(11)','systemhealth_event','DEFAULT 0 NOT NULL'); + $this->app->erp->CheckColumn('status','VARCHAR(64)','systemhealth_event',"DEFAULT '' NOT NULL"); + $this->app->erp->CheckColumn('message','VARCHAR(255)','systemhealth_event',"DEFAULT '' NOT NULL"); + $this->app->erp->CheckIndex('systemhealth_event', 'systemhealth_id'); + $this->app->erp->CheckIndex('systemhealth_event', 'created_at'); + + $this->app->erp->CheckProzessstarter('SystemHealth', 'periodisch', '1440', '', 'cronjob', 'systemhealth', 1); + $this->app->erp->RegisterHook('eproosystem_iconboxes_start','systemhealth','SystemHealthIconBoxedStart'); + + $this->checkEntries(); + $this->fillEntries(); + + $userDataEntry = $this->app->DB->Select( + "SELECT COUNT(sh.id) AS `total` FROM `systemhealth` AS `sh` + WHERE sh.name = 'userdata_writeable' + AND MD5('Schreibrechte in Userdata') != MD5(sh.description) LIMIT 1" + ); + if($userDataEntry > 0){ + $this->app->DB->Update( + "UPDATE `systemhealth` SET `description` = 'Schreibrechte in Userdata' WHERE `name` = 'userdata_writeable'"); + } + } + + /** + * @param string $categoryName + * @param string $systemHealthName + * @param string $status + * @param string $doctype + * @param int $doctypeId + * @param string $message + */ + public function createEvent($categoryName, $systemHealthName, $status, $doctype, $doctypeId, $message = '') + { + try { + $category = $this->gateway->getCategoryByName($categoryName); + if(empty($category)) { + return; + } + $systemHealth = $this->gateway->getByName($category['id'], $systemHealthName); + if(empty($systemHealth)) { + return; + } + $this->service->createEvent($systemHealth['id'], $status, $doctype, $doctypeId, $message); + } + catch(Exception $e) { + + } + } + + /** + * @param int $boxCount + */ + public function SystemHealthIconBoxedStart(&$boxCount) + { + if(empty($this->gateway) || !$this->app->erp->RechteVorhanden('systemhealth', 'list')) { + return; + } + + $boxCount++; + $counter = ''; + $status = $this->gateway->getStatusCount(); + $errorClass = ''; + $isWarning = !empty($status['warning']); + if(!empty($status['error'])) { + $errorClass = ' countererror'; + $counter = $status['error']; + if($isWarning) { + $counter .= '/'.$status['warning']; + } + } + elseif($isWarning) { + $counter = $status['warning']; + $errorClass = ' counterwarning'; + } + + $this->app->Tpl->Add( + 'ICONBOXESHOOK1', + '
  • + + + '.$counter.' + + + + + + + + + + + + +
  • ' + ); + } + + public function checkEntries() + { + if(empty($this->gateway) || empty($this->service)) { + return; + } + $this->app->DB->Update( + "UPDATE systemhealth SET description = 'DB-Version ab 20.2' WHERE description = 'DB-Version ab 20.1'" + ); + $categories = $this->getDefaultCategories(); + foreach($this->getValues() as $category => $names) { + $categoryRow = $this->gateway->getCategoryByName($category); + if(empty($categoryRow)) { + try { + $categoryId = $this->service->createCategory($category, $categories[$category]); + } + catch(Exception $e) { + continue; + } + } + else { + $categoryId = $categoryRow['id']; + } + foreach($names as $name => $description) { + $resetAble = false; + if(is_array($description)) { + $resetAble = !empty($description[1]); + $description = reset($description); + } + $systemHealth = $this->gateway->getByName($categoryId, $name); + if(empty($systemHealth)) { + $this->service->create($categoryId, $name, $description, '', $resetAble); + } + elseif($resetAble && empty($systemHealth['resetable'])) { + $this->service->update($systemHealth['id'], $description, $systemHealth['status'], $resetAble); + } + } + } + } + + /** + * @param string $categoryKey + * @param string $categoryTitle + * @param string $entryKey + * @param string $entryTitle + * @param string $status + * @param string $message + * @param bool $resetAble + */ + public function createEntryWithCategoryIfError( + $categoryKey, $categoryTitle, $entryKey, $entryTitle, $status, $message = '', $resetAble = false + ) + { + if(empty($categoryKey) || empty($entryKey) || empty($status)) { + return; + } + try { + $category = $this->gateway->getCategoryByName($categoryKey); + if($status === 'error' || $status === 'warning'){ + if(empty($category)) { + $this->service->createCategory($categoryKey, $categoryTitle); + } + $this->createEntryIfError($categoryKey, $entryKey, $entryTitle, $status, $message, $resetAble); + } + else { + if(empty($category)) { + return; + } + $this->createEntryIfError($categoryKey, $entryKey, $entryTitle, $status, $message, $resetAble); + } + } + catch (Exception $e) { + + } + } + + /** + * @param string $categoryKey + * @param string $entryKey + * @param string $entryTitle + * @param string $status + * @param string $message + * @param bool $resetable + */ + public function createEntryIfError($categoryKey, $entryKey, $entryTitle, $status, $message = '', $resetable = false) + { + try { + if($status === 'error' || $status === 'warning'){ + $category = $this->gateway->getCategoryByName($categoryKey); + $systemHealth = $this->gateway->getByName($category['id'], $entryKey); + if(empty($systemHealth)){ + $this->service->create($category['id'], $entryKey, $entryTitle, '', $resetable); + } + $this->changeStatus( + $categoryKey, $entryKey, $status, $message + ); + return; + } + if($status === 'ok'){ + $category = $this->gateway->getCategoryByName($categoryKey); + $systemHealth = $this->gateway->getByName($category['id'], $entryKey); + if(!empty($systemHealth)){ + $this->changeStatus( + $categoryKey, $entryKey, 'ok', '' + ); + } + } + } + catch(Exception $e) { + + } + } + + public function fillEntries() + { + $phpVersion = substr(PHP_VERSION,0,3); + if($phpVersion < 8) { + $status = 'warning'; + $phpVersion = 'OpenXE benötigt mind. PHP 8 (aktuell '.$phpVersion + .'). Hilfe'; + } + else { + $status = 'ok'; + } + $this->changeStatus('server', 'php_version', $status, $phpVersion); + + $dbType = ''; + if(method_exists($this->app->DB, 'GetVersionArr')) { + list($dbType, $dbVersion) = $this->app->DB->GetVersionArr(); + if($dbType === 'mysql') { + $status = 'warning'; + if($dbVersion >= 5.7) { + $status = 'ok'; + } + $mysqlVersion = 'MySQL '.$dbVersion; + } + elseif($dbType === 'mariadb') { + $status = 'warning'; + + $dbVersionArr = explode('.',$dbVersion); + + if($dbVersionArr[0] >= 10 && !($dbVersionArr[1] < 2)) { + $status = 'ok'; + } + $mysqlVersion = 'MariaDB '.$dbVersion; + } + else { + $dbType = ''; + } + } + if(empty($dbType)) { + $mysqlVersion = $this->app->DB->GetVersion(); + $mysqlVersion = $mysqlVersion[0] . '.' . $mysqlVersion[1]; + $status = 'warning'; + if($mysqlVersion >= 5.5){ + $status = 'ok'; + } + } + //@todo select version() >= 10.2 mariadb + update.php prüfung + $this->changeStatus('database', 'db_version', $status, $mysqlVersion); + if($status === 'warning') { + $mysqlVersion = 'OpenXE benötigt mind. MySQL 5.7 / MariaDb 10.2 (aktuell '.$mysqlVersion + .'). Hilfe'; + } + $this->changeStatus('database', 'db_version_min', $status, $mysqlVersion); + + $system_cronjob_memory_limit = (string)$this->app->erp->GetKonfiguration('system_cronjob_memory_limit'); + if($system_cronjob_memory_limit === '-1' || $system_cronjob_memory_limit === '0') + { + $this->changeStatus('cronjobs','max_memory','ok','OK (unbegrenzt)'); + } + elseif(!empty($system_cronjob_memory_limit)) { + if($system_cronjob_memory_limit <= 64 * 1024 * 1024) { + $this->changeStatus('cronjobs','max_memory','warning','Es werden mindestens 256 MB empfohlen (' + .round($system_cronjob_memory_limit / 1024 / 1024) .' MB eingestellt)'); + } + elseif($system_cronjob_memory_limit < 256 * 1024 * 1024) { + $this->changeStatus('cronjobs','max_memory','warning','Es werden mindestens 256 MB empfohlen (' + .round($system_cronjob_memory_limit / 1024 / 1024) .' MB eingestellt)'); + } + else { + $this->changeStatus('cronjobs','max_memory','ok','OK ('.round($system_cronjob_memory_limit / 1024 / 1024) .' MB)'); + } + } + $system_cronjob_max_execution_time = (string)$this->app->erp->GetKonfiguration('system_cronjob_max_execution_time'); + if($system_cronjob_max_execution_time === '0') { + $this->changeStatus('cronjobs','max_execution_time','ok','unbegrenzt'); + } + elseif(!empty($system_cronjob_max_execution_time)) { + if($system_cronjob_max_execution_time < 30) { + $this->changeStatus('cronjobs','max_execution_time','warning','< 30 Sekunden ('.$system_cronjob_max_execution_time.' Sekunden)'); + } + elseif($system_cronjob_max_execution_time < 300){ + $this->changeStatus('cronjobs','max_execution_time','warning','< 300 Sekunden ('.$system_cronjob_max_execution_time.' Sekunden)'); + } + else { + $this->changeStatus('cronjobs','max_execution_time','ok','OK ('.$system_cronjob_max_execution_time.' Sekunden)'); + } + } + + $hintergrund=$this->app->erp->Firmendaten('hintergrund'); + $hintergrund_size = 0; + switch($hintergrund) { + case 'briefpapier': + $hintergrund_size = strlen($this->app->erp->getSettingsFile('briefpapier')); + break; + case 'logo': + $hintergrund_size = strlen($this->app->erp->getSettingsFile('logo')); + break; + } + + if($hintergrund_size / 1000 > 100){ + $this->changeStatus( + 'settings', + 'letterhead', + 'warning', + 'Die Dateigröße von ca. '.round($hintergrund_size / 1000). + ' KB vom ' . ucfirst($hintergrund) . ' ist zu groß. Das ' . ucfirst($hintergrund) . + ' sollte unter 100 KB sein'); + } + else { + $this->changeStatus('settings','letterhead','ok','OK'); + } + + $this->loadFreeDisc(); + if((string)1.1 === '1,1') { + $category = $this->gateway->getCategoryByName('server'); + $name = 'locale_lc_numeric'; + $description = 'Decimaltrennzeichen Einstellung'; + $systemHealth = $this->gateway->getByName($category['id'], $name); + if(empty($systemHealth)) { + $this->service->create($category['id'], $name, $description, '', false); + } + $this->changeStatus( + 'server',$name,'error','Die lokale Decimal Trennzeicheneinstellung ist fehlerhaft' + ); + } + else { + $category = $this->gateway->getCategoryByName('server'); + $name = 'locale_lc_numeric'; + $systemHealth = $this->gateway->getByName($category['id'], $name); + if(!empty($systemHealth)) { + $this->changeStatus( + 'server',$name,'ok','' + ); + } + } + if(!function_exists('imap_open')) { + $category = $this->gateway->getCategoryByName('server'); + $name = 'imap_plugin'; + $description = 'IMAP Plugin'; + $systemHealth = $this->gateway->getByName($category['id'], $name); + if(empty($systemHealth)) { + $this->service->create($category['id'], $name, $description, '', false); + } + $this->changeStatus( + 'server',$name,'error','IMAP ist nicht installiert' + ); + } + else { + $category = $this->gateway->getCategoryByName('server'); + $name = 'imap_plugin'; + $systemHealth = $this->gateway->getByName($category['id'], $name); + if(!empty($systemHealth)) { + $this->changeStatus( + 'server',$name,'ok','' + ); + } + } + $this->app->erp->RunHook('systemhealth_fill_entries'); + } + + public function loadFreeDisc(): void + { + $free = $this->getDiskFree(); + if($free === false) { + $this->changeStatus('server', 'disk_space', 'warning', 'Der freie Speicherplatz konnte nicht ermittelt werden'); + } + else{ + $free /= 1024 * 1024; + $userdataSize = (int)$this->app->erp->GetKonfiguration('userdatasize'); + $dbSize = $this->getDbSize(); + if(is_array($dbSize)) { + $dbSize = $dbSize['all']; + } + $minFree = (int)($dbSize / 1024) + $userdataSize + 512; + if($minFree < 2048) { + $minFree = 2048; + } + if($free < 512) { + $this->changeStatus('server', 'disk_space', 'error', 'Es sind nur ' . round($free) . ' MB Speicherplatz frei'); + } + elseif($free < $minFree) { + $this->changeStatus('server', 'disk_space', 'warning', 'Es sind nur ' . round($free) . ' MB Speicherplatz frei'); + } + else { + $this->changeStatus('server', 'disk_space', 'ok', 'Es sind ' . round($free) . ' MB Speicherplatz frei'); + } + } + } + + /** + * @param string $category + * @param string $name + * @param string $status + * @param string $message + */ + public function changeStatus($category, $name, $status, $message) + { + if(empty($this->gateway) || empty($this->service)) { + return; + } + try { + $categoryRow = $this->gateway->getCategoryByName($category); + if(empty($categoryRow)) { + return; + } + $categoryId = $categoryRow['id']; + + $systemHealth = $this->gateway->getByName($categoryId, $name); + if(empty($systemHealth)) { + return; + } + + $this->service->setStatus($systemHealth['id'], $status, $message); + } + catch(Exception $e) { + + } + } + + /** + * @return array + */ + public function getDefaultCategories() + { + return [ + 'masterdata' => 'Stammdaten', + 'bestbeforebatchsn' => 'MHD / Chargen / Seriennummern', + 'server' => 'Server', + 'settings' => 'Einstellungen', + 'cronjobs' => 'Prozessstarter', + 'database' => 'Datenbank', + 'shopexport' => 'Onlineshops', + ]; + } + + /** + * @return array + */ + public function getValues() + { + return [ + 'masterdata' => [ + 'double_articlenumber' => ['Artikelnummern', true], + 'double_suppliernumber' => ['Lieferantennummern', true], + 'double_customernumber' => ['Kundennummern', true], + 'empty_articlenumber' => ['Leere Artikelnummern', true], + 'double_invoice' => ['Rechnungsnummern', true], + 'double_return_order' => ['Gutschriftsnummern', true], + ], + 'bestbeforebatchsn' => [ + 'sn' => ['Seriennummern', true], + 'batch' => ['Chargen-Schiefstand', true], + 'bestbefore' => ['MHD-Schiefstand', true], + 'expiredbestbefore' => ['abgelaufene MHD', true], + ], + 'server' => [ + 'php_version' => 'PHP-Version', + 'extension_zip' => 'Zip Extension', + 'disk_space' => 'Speicherplatz', + 'max_upload' => 'Upload-Kapazität', + 'max_execution_time' => 'Scriptlauftzeit', + 'userdata_writeable' => 'Schreibrechte in Userdata', + 'ioncube' => 'Lizenz', + 'tls1-2' => 'TLS v1.2', + ], + 'settings' => [ + 'company_settings' => 'Firmendaten', + 'letterhead' => 'Briefpapier', + ], + 'cronjobs' => [ + 'lastrunning' => 'Aktivität', + 'frequently' => 'Häufigkeit', + 'max_memory' => 'Speicher', + 'out_of_memory' => ['Speicherüberlauf', true], + 'max_execution_time' => 'Laufzeit', + 'errors' => ['Fehler', true] + ], + 'database' => [ + 'db_version' => 'DB-Version', + 'db_version_min' => 'DB-Version ab 20.2', + 'sql_errors' => ['SQL-Fehler', true], + 'sql_integrity' => ['Datenintegrität', true], + ], + 'shopexport' => [ + 'auth' => ['Authentifizierung', true], + ], + ]; + } + + /** + * @return array + */ + public function getTableSizes() + { + try{ + return $this->service->getTableSizes($this->app->Conf->WFdbname); + } + catch(Exception $e) { + return []; + } + } + + /** + * @return array + */ + public function getLogTables() + { + return [ + 'shopexport_log', + 'logfile', + 'protokoll', + 'logfile', + 'cronjob_log', + 'cronjob_starter_running', + 'uebertragungen_monitor', + 'adapterbox_request_log', + 'versandzentrum_log', + ]; + } + + /** + * @var bool $splittedLogs + * + * @return int|array + */ + public function getDbSize($splittedLogs = false) + { + if($splittedLogs) { + try { + $dbSize = $this->service->getTableSizes($this->app->Conf->WFdbname); + if(empty($dbSize)) { + return 0; + } + $ret = ['all' => 0., 'log' => 0.]; + $logTables = $this->getLogTables(); + foreach($dbSize as $table => $size) { + $ret['all'] += (float)$size; + if(in_array($table, $logTables,true)) { + $ret['log'] += (float)$size; + } + } + + return $ret; + } + catch(Exception $e) { + return 0; + } + } + + try { + return $this->service->getDbSize($this->app->Conf->WFdbname); + } + catch(Exception $e) { + return 0; + } + } + + /** + * @return array + */ + public function getSystemLoad() + { + try { + return $this->service->getSystemLoad(); + } + catch(Exception $e) { + return [null, null, null, null, null]; + } + } + + /** + * @param float|int $tresholdAct + * @param float|int $treshold5Min + * + * @return bool + */ + public function isSystemLoadHigh($tresholdAct = 5.0, $treshold5Min = 5.0) + { + $systemLoad = $this->getSystemLoad(); + $loadAct = empty($systemLoad['act'])?0:$systemLoad['act']; + $load5min = empty($systemLoad['5min'])?0:$systemLoad['5min']; + + return $loadAct > $tresholdAct || $load5min > $treshold5Min; + } + + /** + * @param string $dir + * + * @return false|float + */ + public function getDiskFree($dir = '') + { + try{ + return $this->service->getDiskFree($dir); + } + catch(Exception $e) { + return false; + } + } + + /** + * @param string|array $type + * + * @return int|array + */ + public function getUserdataSpace($type = '') + { + $dir = $this->app->Conf->WFuserdata; + if(is_array($type)) { + $ret = []; + $excludes = []; + $sum = 0; + foreach($type as $key => $typeString) { + if(empty(trim($typeString))) { + unset($type[$key]); + continue; + } + try { + $ret[$typeString] = $this->service->getUsedSpace($this->app->Conf->WFuserdata.'/'.$typeString, []); + $sum += $ret[$typeString]; + } + catch (Exception $e) { + $ret[$typeString] = 0; + } + $excludes[] = './'.$typeString; + } + try { + $ret['sum'] = $sum + $this->service->getUsedSpace($this->app->Conf->WFuserdata, $excludes); + } + catch(Exception $e) { + $ret['sum'] = $sum; + } + + return $ret; + } + $exclude = []; + switch($type) { + case 'userdatawithoutdmspdfarchiv': + $dir = $this->app->Conf->WFuserdata; + $exclude = ['./pdfarchiv', './dms']; + break; + case 'dms': + $dir = $this->app->Conf->WFuserdata.'/dms'; + break; + case 'pdfarchiv': + $dir = $this->app->Conf->WFuserdata.'/pdfarchiv'; + break; + default: + if(strpos($type, '.') !== false && is_dir($this->app->Conf->WFuserdata.'/'.$type)) { + $dir = $this->app->Conf->WFuserdata.'/'.$type; + } + break; + } + try { + return $this->service->getUsedSpace($dir, $exclude); + } + catch (Exception $e) { + return 0; + } + } + + /** + * @return int[] + */ + public function getUserDataSpaces() + { + return $this->getUserdataSpace( + [ + 'dms', + 'pdfarchiv', + 'pdfmirror', + 'tmp', + 'wiki', + 'emailbackup', + 'uebertragung', + ] + ); + } + + /** + * @var string $dir + * + * @return array + */ + public function getPartions($dir = '') + { + try{ + return $this->service->getPartions($dir); + } + catch (Exception $e) { + + } + + return []; + } + + public function doCronjob() + { + $userDataSpaces = $this->getUserDataSpaces(); + foreach($userDataSpaces as $userDataDir => $userDataSpace) { + if($userDataDir === 'sum') { + $this->app->erp->SetKonfigurationValue('userdatasize', (int)ceil($userDataSpace / 1024)); + } + else { + $this->app->erp->SetKonfigurationValue('userdata'.$userDataDir.'size', (int)ceil($userDataSpace / 1024)); + } + } + try{ + $backupSize = (int)$this->service->getUsedSpace(dirname(__DIR__,2).'/backup'); + } + catch (Exception $e) { + $backupSize = 0; + } + $this->app->erp->SetKonfigurationValue('backupsize', (int)ceil($backupSize / 1024)); + $dbSize = $this->getDbSize(true); + $dbSizeLog = 0; + if(is_array($dbSize)) { + if(!empty($dbSize['log'])) { + $dbSizeLog = $dbSize['log']; + } + $dbSize = $dbSize['all']; + } + + $this->app->erp->SetKonfigurationValue('databasesize', (int)ceil($dbSize / 1024)); + $this->app->erp->SetKonfigurationValue('databasesizelog', (int)ceil($dbSizeLog / 1024)); + $this->app->erp->SetKonfigurationValue('diskfree', (int)floor($this->getDiskFree() / 1024 / 1024)); + $this->app->erp->SetKonfigurationValue('lastsizeupdate', date('Y-m-d H:i:s')); + + $partitions = $this->getPartions(dirname(__DIR__, 2)); + if(!empty($partitions)) { + $this->app->erp->SetKonfigurationValue('partitiontotal', (int)($partitions['total'] / 1024)); + $this->app->erp->SetKonfigurationValue('partitionused', (int)($partitions['used'] / 1024)); + $this->app->erp->SetKonfigurationValue('partitionfree', (int)($partitions['free'] / 1024)); + } + + $this->fillEntries(); + $this->app->erp->RunHook('systemhealth_cronjob'); + } + + /** + * @return array + */ + public function getHealthData() + { + $ret = []; + $healthData = $this->app->DB->SelectArr('SELECT * FROM `systemhealth` ORDER BY `id`'); + foreach($healthData as $healthRow) { + $ret[$healthRow['category']][$healthRow['name']] = $healthRow; + } + + return $ret; + } +}