From 6082308e2053142d5ddb3373b1ca31c302ee5297 Mon Sep 17 00:00:00 2001 From: Molkobain Date: Wed, 8 Jan 2020 11:40:35 +0100 Subject: [PATCH] Add combodo-db-tools/1.0.7 module as a default module --- data/.htaccess | 13 - data/index.php | 2 - data/web.config | 8 - .../cs.dict.combodo-db-tools.php | 83 +++ .../da.dict.combodo-db-tools.php | 83 +++ .../datamodel.combodo-db-tools.xml | 15 + .../db_analyzer.class.inc.php | 355 +++++++++++ datamodels/2.x/combodo-db-tools/dbtools.php | 602 ++++++++++++++++++ .../de.dict.combodo-db-tools.php | 82 +++ datamodels/2.x/combodo-db-tools/default.css | 36 ++ datamodels/2.x/combodo-db-tools/default.scss | 48 ++ .../en.dict.combodo-db-tools.php | 84 +++ .../es_cr.dict.combodo-db-tools.php | 83 +++ .../fr.dict.combodo-db-tools.php | 82 +++ .../hu.dict.combodo-db-tools.php | 83 +++ .../it.dict.combodo-db-tools.php | 83 +++ .../ja.dict.combodo-db-tools.php | 83 +++ .../module.combodo-db-tools.php | 57 ++ .../nl.dict.combodo-db-tools.php | 83 +++ .../pt_br.dict.combodo-db-tools.php | 83 +++ .../ru.dict.combodo-db-tools.php | 83 +++ .../tr.dict.combodo-db-tools.php | 83 +++ .../zh_cn.dict.combodo-db-tools.php | 83 +++ 23 files changed, 2274 insertions(+), 23 deletions(-) delete mode 100644 data/.htaccess delete mode 100644 data/index.php delete mode 100644 data/web.config create mode 100644 datamodels/2.x/combodo-db-tools/cs.dict.combodo-db-tools.php create mode 100644 datamodels/2.x/combodo-db-tools/da.dict.combodo-db-tools.php create mode 100644 datamodels/2.x/combodo-db-tools/datamodel.combodo-db-tools.xml create mode 100644 datamodels/2.x/combodo-db-tools/db_analyzer.class.inc.php create mode 100644 datamodels/2.x/combodo-db-tools/dbtools.php create mode 100644 datamodels/2.x/combodo-db-tools/de.dict.combodo-db-tools.php create mode 100644 datamodels/2.x/combodo-db-tools/default.css create mode 100644 datamodels/2.x/combodo-db-tools/default.scss create mode 100644 datamodels/2.x/combodo-db-tools/en.dict.combodo-db-tools.php create mode 100644 datamodels/2.x/combodo-db-tools/es_cr.dict.combodo-db-tools.php create mode 100644 datamodels/2.x/combodo-db-tools/fr.dict.combodo-db-tools.php create mode 100644 datamodels/2.x/combodo-db-tools/hu.dict.combodo-db-tools.php create mode 100644 datamodels/2.x/combodo-db-tools/it.dict.combodo-db-tools.php create mode 100644 datamodels/2.x/combodo-db-tools/ja.dict.combodo-db-tools.php create mode 100644 datamodels/2.x/combodo-db-tools/module.combodo-db-tools.php create mode 100644 datamodels/2.x/combodo-db-tools/nl.dict.combodo-db-tools.php create mode 100644 datamodels/2.x/combodo-db-tools/pt_br.dict.combodo-db-tools.php create mode 100644 datamodels/2.x/combodo-db-tools/ru.dict.combodo-db-tools.php create mode 100644 datamodels/2.x/combodo-db-tools/tr.dict.combodo-db-tools.php create mode 100644 datamodels/2.x/combodo-db-tools/zh_cn.dict.combodo-db-tools.php diff --git a/data/.htaccess b/data/.htaccess deleted file mode 100644 index 782472c78..000000000 --- a/data/.htaccess +++ /dev/null @@ -1,13 +0,0 @@ -# Apache 2.4 - -Require all denied - - -# Apache 2.2 - -deny from all -Satisfy All - - -# Apache 2.2 and 2.4 -IndexIgnore * diff --git a/data/index.php b/data/index.php deleted file mode 100644 index 112807643..000000000 --- a/data/index.php +++ /dev/null @@ -1,2 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/datamodels/2.x/combodo-db-tools/cs.dict.combodo-db-tools.php b/datamodels/2.x/combodo-db-tools/cs.dict.combodo-db-tools.php new file mode 100644 index 000000000..3ac616cee --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/cs.dict.combodo-db-tools.php @@ -0,0 +1,83 @@ + 'DB Tools~~', + 'DBTools:Class' => 'Class~~', + 'DBTools:Title' => 'Database Maintenance Tools~~', + 'DBTools:ErrorsFound' => 'Errors Found~~', + 'DBTools:Error' => 'Error~~', + 'DBTools:Count' => 'Count~~', + 'DBTools:SQLquery' => 'SQL query~~', + 'DBTools:FixitSQLquery' => 'SQL query To Fix it (indication)~~', + 'DBTools:SQLresult' => 'SQL result~~', + 'DBTools:NoError' => 'The database is OK~~', + 'DBTools:HideIds' => 'Error List~~', + 'DBTools:ShowIds' => 'Detailed view~~', + 'DBTools:ShowReport' => 'Report~~', + 'DBTools:IntegrityCheck' => 'Integrity check~~', + 'DBTools:FetchCheck' => 'Fetch Check (long)~~', + + 'DBTools:Analyze' => 'Analyze~~', + 'DBTools:Details' => 'Show Details~~', + 'DBTools:ShowAll' => 'Show All Errors~~', + + 'DBTools:Inconsistencies' => 'Database inconsistencies~~', + + 'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~', + 'DBAnalyzer-Integrity-InvalidExtKey' => 'Invalid external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~', + 'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted~~', +)); + +// Database Info +Dict::Add('CS CZ', 'Czech', 'Čeština', array( + 'DBTools:DatabaseInfo' => 'Database Information~~', + 'DBTools:Base' => 'Base~~', + 'DBTools:Size' => 'Size~~', +)); + +// Lost attachments +Dict::Add('CS CZ', 'Czech', 'Čeština', array( + 'DBTools:LostAttachments' => 'Lost attachments~~', + 'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~', + + 'DBTools:LostAttachments:Button:Analyze' => 'Analyze~~', + 'DBTools:LostAttachments:Button:Restore' => 'Restore~~', + 'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~', + 'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~', + + 'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~', + + 'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Great! Every thing seems to be at the right place.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Some attachments (%1$d) seem to be misplaced. Take a look at the following list and check the ones you would like to move.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Filename~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Current location~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Move to...~~', + + 'DBTools:LostAttachments:Step:RestoreResults' => 'Restore results:~~', + 'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d attachments were restored.~~', + + 'DBTools:LostAttachments:StoredAsInlineImage' => 'Stored as inline image~~', + 'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~' +)); diff --git a/datamodels/2.x/combodo-db-tools/da.dict.combodo-db-tools.php b/datamodels/2.x/combodo-db-tools/da.dict.combodo-db-tools.php new file mode 100644 index 000000000..6d72d7bcf --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/da.dict.combodo-db-tools.php @@ -0,0 +1,83 @@ + 'DB Tools~~', + 'DBTools:Class' => 'Class~~', + 'DBTools:Title' => 'Database Maintenance Tools~~', + 'DBTools:ErrorsFound' => 'Errors Found~~', + 'DBTools:Error' => 'Error~~', + 'DBTools:Count' => 'Count~~', + 'DBTools:SQLquery' => 'SQL query~~', + 'DBTools:FixitSQLquery' => 'SQL query To Fix it (indication)~~', + 'DBTools:SQLresult' => 'SQL result~~', + 'DBTools:NoError' => 'The database is OK~~', + 'DBTools:HideIds' => 'Error List~~', + 'DBTools:ShowIds' => 'Detailed view~~', + 'DBTools:ShowReport' => 'Report~~', + 'DBTools:IntegrityCheck' => 'Integrity check~~', + 'DBTools:FetchCheck' => 'Fetch Check (long)~~', + + 'DBTools:Analyze' => 'Analyze~~', + 'DBTools:Details' => 'Show Details~~', + 'DBTools:ShowAll' => 'Show All Errors~~', + + 'DBTools:Inconsistencies' => 'Database inconsistencies~~', + + 'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~', + 'DBAnalyzer-Integrity-InvalidExtKey' => 'Invalid external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~', + 'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted~~', +)); + +// Database Info +Dict::Add('DA DA', 'Danish', 'Dansk', array( + 'DBTools:DatabaseInfo' => 'Database Information~~', + 'DBTools:Base' => 'Base~~', + 'DBTools:Size' => 'Size~~', +)); + +// Lost attachments +Dict::Add('DA DA', 'Danish', 'Dansk', array( + 'DBTools:LostAttachments' => 'Lost attachments~~', + 'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~', + + 'DBTools:LostAttachments:Button:Analyze' => 'Analyze~~', + 'DBTools:LostAttachments:Button:Restore' => 'Restore~~', + 'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~', + 'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~', + + 'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~', + + 'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Great! Every thing seems to be at the right place.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Some attachments (%1$d) seem to be misplaced. Take a look at the following list and check the ones you would like to move.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Filename~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Current location~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Move to...~~', + + 'DBTools:LostAttachments:Step:RestoreResults' => 'Restore results:~~', + 'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d attachments were restored.~~', + + 'DBTools:LostAttachments:StoredAsInlineImage' => 'Stored as inline image~~', + 'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~' +)); diff --git a/datamodels/2.x/combodo-db-tools/datamodel.combodo-db-tools.xml b/datamodels/2.x/combodo-db-tools/datamodel.combodo-db-tools.xml new file mode 100644 index 000000000..ab5e9b324 --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/datamodel.combodo-db-tools.xml @@ -0,0 +1,15 @@ + + + + + 80 + 1 + + + 15 + AdminTools + $pages/exec.php?exec_module=combodo-db-tools&exec_page=dbtools.php&c[menu]=DBToolsMenu + 1 + + + diff --git a/datamodels/2.x/combodo-db-tools/db_analyzer.class.inc.php b/datamodels/2.x/combodo-db-tools/db_analyzer.class.inc.php new file mode 100644 index 000000000..3445a7787 --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/db_analyzer.class.inc.php @@ -0,0 +1,355 @@ +iTimeLimitPerOperation = $iTimeLimitPerOperation; + } + + /** + * @param $sSelWrongRecs + * @param $sFixitRequest + * @param $sErrorDesc + * @param $sClass + * @param $aErrorsAndFixes + * + * @throws \MySQLException + */ + private function ExecQuery($sSelWrongRecs, $sFixitRequest, $sErrorDesc, $sClass, &$aErrorsAndFixes, $aValueNames = array()) + { + if (!is_null($this->iTimeLimitPerOperation)) + { + set_time_limit($this->iTimeLimitPerOperation); + } + + $aWrongRecords = CMDBSource::QueryToArray($sSelWrongRecs); + if (count($aWrongRecords) > 0) + { + foreach($aWrongRecords as $aRes) + { + if (!isset($aErrorsAndFixes[$sClass][$sErrorDesc])) + { + $aErrorsAndFixes[$sClass][$sErrorDesc] = array( + 'count' => 1, + 'query' => $sSelWrongRecs, + ); + if (!empty($sFixitRequest)) + { + $aErrorsAndFixes[$sClass][$sErrorDesc]['fixit'] = array($sFixitRequest); + } + } + else + { + $aErrorsAndFixes[$sClass][$sErrorDesc]['count'] += 1; + } + if (empty($aValueNames)) + { + $aValues = array('id' => $aRes['id']); + } + else + { + $aValues = array(); + foreach ($aValueNames as $sValueName) + { + $aValues[$sValueName] = $aRes[$sValueName]; + } + } + + if (isset($aRes['value'])) + { + $value = $aRes['value']; + $aValues['value'] = $value; + if (!isset($aErrorsAndFixes[$sClass][$sErrorDesc]['values'][$value])) + { + $aErrorsAndFixes[$sClass][$sErrorDesc]['values'][$value] = 1; + } + else + { + $aErrorsAndFixes[$sClass][$sErrorDesc]['values'][$value] += 1; + } + } + $aErrorsAndFixes[$sClass][$sErrorDesc]['res'][] = $aValues; + } + } + } + + /** + * @param $aClassSelection + * @param $iShowId + * @return array + * @throws CoreException + * @throws DictExceptionMissingString + * @throws MySQLException + * @throws Exception + */ + public function CheckIntegrity($aClassSelection, $iShowId) + { + // Getting and setting time limit are not symetric: + // www.php.net/manual/fr/function.set-time-limit.php#72305 + $iPreviousTimeLimit = ini_get('max_execution_time'); + + $aErrorsAndFixes = array(); + + if (empty($aClassSelection)) + { + $aClassSelection = MetaModel::GetClasses(); + } + else + { + $aClasses = $aClassSelection; + foreach($aClasses as $sClass) + { + $aExpectedClasses = MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL); + $aClassSelection = array_merge($aClassSelection, $aExpectedClasses); + } + $aClassSelection = array_unique($aClassSelection); + } + + foreach($aClassSelection as $sClass) + { + // Check uniqueness rules + if (method_exists('MetaModel', 'GetUniquenessRules')) + { + $aUniquenessRules = MetaModel::GetUniquenessRules($sClass); + foreach ($aUniquenessRules as $sUniquenessRuleId => $aUniquenessRuleProperties) + { + if ($aUniquenessRuleProperties['disabled'] === true) + { + continue; + } + $this->CheckUniquenessRule($sClass, $sUniquenessRuleId, $aUniquenessRuleProperties, $aErrorsAndFixes); + } + } + + if (!MetaModel::HasTable($sClass)) + { + continue; + } + $sRootClass = MetaModel::GetRootClass($sClass); + $sTable = MetaModel::DBGetTable($sClass); + $sKeyField = MetaModel::DBGetKey($sClass); + + + if (!MetaModel::IsStandaloneClass($sClass)) + { + if (!MetaModel::IsRootClass($sClass)) + { + $sRootTable = MetaModel::DBGetTable($sRootClass); + $sRootKey = MetaModel::DBGetKey($sRootClass); + $sFinalClassField = MetaModel::DBGetClassField($sRootClass); + + $aExpectedClasses = MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL); + $sExpectedClasses = implode(",", CMDBSource::Quote($aExpectedClasses, true)); + + // Check that any record found here has its counterpart in the root table + // + $sSelect = "SELECT DISTINCT `$sTable`.`$sKeyField` AS id"; + $sDelete = "DELETE `$sTable`"; + $sFilter = "FROM `$sTable` LEFT JOIN `$sRootTable` ON `$sTable`.`$sKeyField` = `$sRootTable`.`$sRootKey` WHERE `$sRootTable`.`$sRootKey` IS NULL"; + $sSelWrongRecs = "$sSelect $sFilter"; + $sFixitRequest = "$sDelete $sFilter"; + $this->ExecQuery($sSelWrongRecs, $sFixitRequest, Dict::Format('DBAnalyzer-Integrity-OrphanRecord', $sTable, $sRootTable), $sClass, $aErrorsAndFixes); + + // Check that any record found in the root table and referring to a child class + // has its counterpart here (detect orphan nodes -root or in the middle of the hierarchy) + // + $sSelect = "SELECT DISTINCT `$sRootTable`.`$sRootKey` AS id"; + $sDelete = "DELETE `$sRootTable`"; + $sFilter = "FROM `$sRootTable` LEFT JOIN `$sTable` ON `$sRootTable`.`$sRootKey` = `$sTable`.`$sKeyField` WHERE `$sTable`.`$sKeyField` IS NULL AND `$sRootTable`.`$sFinalClassField` IN ($sExpectedClasses)"; + $sSelWrongRecs = "$sSelect $sFilter"; + $sFixitRequest = "$sDelete $sFilter"; + $this->ExecQuery($sSelWrongRecs, $sFixitRequest, Dict::Format('DBAnalyzer-Integrity-OrphanRecord', $sRootTable, $sTable), $sRootClass, $aErrorsAndFixes); + } + } + + foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) + { + // Skip this attribute if not defined in this table + if (!MetaModel::IsAttributeOrigin($sClass, $sAttCode)) + { + continue; + } + + if ($oAttDef->IsExternalKey()) + { + // Check that any external field is pointing to an existing object + // + $sRemoteClass = $oAttDef->GetTargetClass(); + $sRemoteTable = MetaModel::DBGetTable($sRemoteClass); + $sRemoteKey = MetaModel::DBGetKey($sRemoteClass); + + $aCols = $oAttDef->GetSQLExpressions(); // Workaround a PHP bug: sometimes issuing a Notice if invoking current(somefunc()) + $sExtKeyField = current($aCols); // get the first column for an external key + + // Note: a class/table may have an external key on itself + $sSelect = "SELECT DISTINCT `$sTable`.`$sKeyField` AS id, `$sTable`.`$sExtKeyField` AS value"; + $sFilter = "FROM `$sTable` LEFT JOIN `$sRemoteTable` AS `{$sRemoteTable}_1` ON `$sTable`.`$sExtKeyField` = `{$sRemoteTable}_1`.`$sRemoteKey`"; + + $sFilter = $sFilter." WHERE `{$sRemoteTable}_1`.`$sRemoteKey` IS NULL"; + // Exclude the records pointing to 0/null from the errors (separate test below) + $sFilter .= " AND `$sTable`.`$sExtKeyField` IS NOT NULL"; + $sFilter .= " AND `$sTable`.`$sExtKeyField` != 0"; + + $sSelWrongRecs = "$sSelect $sFilter"; + + $sErrorDesc = Dict::Format('DBAnalyzer-Integrity-InvalidExtKey', $sAttCode, $sTable, $sExtKeyField); + $this->ExecQuery($sSelWrongRecs, '', $sErrorDesc, $sClass, $aErrorsAndFixes); + // Fix it request needs the values of the enum to generate the requests + if (isset($aErrorsAndFixes[$sClass][$sErrorDesc]['values'])) + { + $aFixit = array(); + $aFixit[] = "-- Remove inconsistant entries:"; + $sIds = implode(', ', array_keys($aErrorsAndFixes[$sClass][$sErrorDesc]['values'])); + $aFixit[] = "DELETE `$sTable` FROM `$sTable` WHERE `$sTable`.`$sExtKeyField` IN ($sIds)"; + $aFixit[] = ""; + $aFixit[] = "-- Or fix inconsistant values: Replace XXX with the appropriate value"; + foreach (array_keys($aErrorsAndFixes[$sClass][$sErrorDesc]['values']) as $sKey) + { + $aFixit[] = "UPDATE `$sTable` SET `$sTable`.`$sExtKeyField` = XXX WHERE `$sTable`.`$sExtKeyField` = '$sKey'"; + } + $aErrorsAndFixes[$sClass][$sErrorDesc]['fixit'] = $aFixit; + } + + if (!$oAttDef->IsNullAllowed()) + { + $sSelect = "SELECT DISTINCT `$sTable`.`$sKeyField` AS id"; + $sDelete = "DELETE `$sTable`"; + $sFilter = "FROM `$sTable` WHERE `$sTable`.`$sExtKeyField` IS NULL OR `$sTable`.`$sExtKeyField` = 0"; + $sSelWrongRecs = "$sSelect $sFilter"; + $sFixitRequest = "$sDelete $sFilter"; + $sErrorDesc = Dict::Format('DBAnalyzer-Integrity-MissingExtKey', $sAttCode, $sTable, $sExtKeyField); + $this->ExecQuery($sSelWrongRecs, $sFixitRequest, $sErrorDesc, $sClass, $aErrorsAndFixes); + if (isset($aErrorsAndFixes[$sClass][$sErrorDesc]['count']) && ($aErrorsAndFixes[$sClass][$sErrorDesc]['count'] > 0)) + { + $aFixit = $aErrorsAndFixes[$sClass][$sErrorDesc]['fixit']; + $aFixit[] = "-- Alternate fix"; + $aFixit[] = "-- Replace XXX with the appropriate value"; + $aFixit[] = "UPDATE `$sTable` SET `$sTable`.`$sExtKeyField` = XXX WHERE `$sTable`.`$sExtKeyField` IS NULL OR `$sTable`.`$sExtKeyField` = 0"; + $aErrorsAndFixes[$sClass][$sErrorDesc]['fixit'] = $aFixit; + } + } + } + elseif ($oAttDef->IsDirectField() && !($oAttDef instanceof AttributeTagSet)) + { + // Check that the values fit the allowed values + // + $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode); + if (!is_null($aAllowedValues) && count($aAllowedValues) > 0) + { + $sExpectedValues = implode(",", CMDBSource::Quote(array_keys($aAllowedValues), true)); + + $aCols = $oAttDef->GetSQLExpressions(); // Workaround a PHP bug: sometimes issuing a Notice if invoking current(somefunc()) + $sMyAttributeField = current($aCols); // get the first column for the moment + $sSelWrongRecs = "SELECT DISTINCT `$sTable`.`$sKeyField` AS id, `$sTable`.`$sMyAttributeField` AS value FROM `$sTable` WHERE `$sTable`.`$sMyAttributeField` NOT IN ($sExpectedValues)"; + $sErrorDesc = Dict::Format('DBAnalyzer-Integrity-InvalidValue', $sAttCode, $sTable, $sMyAttributeField); + $this->ExecQuery($sSelWrongRecs, '', $sErrorDesc, $sClass, $aErrorsAndFixes); + // Fix it request needs the values of the enum to generate the requests + if (isset($aErrorsAndFixes[$sClass][$sErrorDesc]['values'])) + { + if (isset($aErrorsAndFixes[$sClass][$sErrorDesc]['fixit'])) + { + $aFixit = $aErrorsAndFixes[$sClass][$sErrorDesc]['fixit']; + } + else + { + $aFixit = array("-- Replace 'XXX' with the appropriate value"); + } + foreach (array_keys($aErrorsAndFixes[$sClass][$sErrorDesc]['values']) as $sKey) + { + $aFixit[] = "UPDATE `$sTable` SET `$sTable`.`$sMyAttributeField` = 'XXX' WHERE `$sTable`.`$sMyAttributeField` = '$sKey'"; + } + $aErrorsAndFixes[$sClass][$sErrorDesc]['fixit'] = $aFixit; + } + } + } + } + } + + // Check user accounts without profile + $sUserTable = MetaModel::DBGetTable('User'); + $sLinkTable = MetaModel::DBGetTable('URP_UserProfile'); + $sSelect = "SELECT DISTINCT u.id AS id, u.`login` AS value"; + $sFilter = "FROM `$sUserTable` AS u LEFT JOIN `$sLinkTable` AS l ON l.userid = u.id WHERE l.id IS NULL"; + $sSelWrongRecs = "$sSelect $sFilter"; + $sFixit = "-- Remove the corresponding user(s)"; + $this->ExecQuery($sSelWrongRecs, $sFixit, Dict::S('DBAnalyzer-Integrity-UsersWithoutProfile'), 'User', $aErrorsAndFixes); + + if (!is_null($this->iTimeLimitPerOperation)) + { + set_time_limit($iPreviousTimeLimit); + } + return $aErrorsAndFixes; + } + + private function CheckUniquenessRule($sClass, $sUniquenessRuleId, $aUniquenessRuleProperties, &$aErrorsAndFixes) + { + $sOqlUniquenessQuery = "SELECT $sClass"; + if (!(empty($sUniquenessFilter = $aUniquenessRuleProperties['filter']))) + { + $sOqlUniquenessQuery .= ' WHERE '.$sUniquenessFilter; + } + $oUniquenessQuery = DBObjectSearch::FromOQL($sOqlUniquenessQuery); + + $aValueNames = array(); + $aGroupByExpr = array(); + foreach ($aUniquenessRuleProperties['attributes'] as $sAttributeCode) + { + $oExpr = Expression::FromOQL("$sClass.$sAttributeCode"); + $aGroupByExpr[$sAttributeCode] = $oExpr; + $aValueNames[] = $sAttributeCode; + } + + $aSelectExpr = array(); + + $sSQLUniquenessQuery = $oUniquenessQuery->MakeGroupByQuery(array(), $aGroupByExpr, false, $aSelectExpr); + + $sSQLUniquenessQuery .= ' having count(*) > 1'; + + $sErrorDesc = $this->GetUniquenessRuleMessage($sClass, $sUniquenessRuleId); + + $this->ExecQuery($sSQLUniquenessQuery, '', $sErrorDesc, $sClass, $aErrorsAndFixes, $aValueNames); + if (isset($aErrorsAndFixes[$sClass][$sErrorDesc]['res'])) + { + $aFixit = array("-- In order to get the duplicates, run the following queries:"); + foreach ($aErrorsAndFixes[$sClass][$sErrorDesc]['res'] as $aValues) + { + $oFixSearch = new DBObjectSearch($sClass); + foreach ($aValues as $sAttCode => $sValue) + { + $oFixSearch->AddCondition($sAttCode, $sValue, '='); + } + $aFixit[] = $oFixSearch->MakeSelectQuery().';'; + $aFixit[] = ""; + } + $aErrorsAndFixes[$sClass][$sErrorDesc]['fixit'] = $aFixit; + } + + return; + } + + private function GetUniquenessRuleMessage($sCurrentClass, $sUniquenessRuleId) + { + // we could add also a specific message if user is admin ("dict key is missing") + return Dict::Format('Core:UniquenessDefaultError', $sUniquenessRuleId); + } +} diff --git a/datamodels/2.x/combodo-db-tools/dbtools.php b/datamodels/2.x/combodo-db-tools/dbtools.php new file mode 100644 index 000000000..32e22353e --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/dbtools.php @@ -0,0 +1,602 @@ +SetCurrentTab(Dict::S('DBTools:Inconsistencies')); + + $bRunAnalysis = intval(utils::ReadParam('run_analysis', '0')); + if ($bRunAnalysis) + { + $oDBAnalyzer = new DatabaseAnalyzer(); + $aResults = $oDBAnalyzer->CheckIntegrity($aClassSelection, $iShowId); + if (empty($aResults)) + { + $oP->p('
'.Dict::S('DBTools:NoError').'
'); + } + } + + $oP->add('
'); + $oP->add("
"); + $oP->add(""); + + $oP->add("\n"); + + $oP->add("
"); + $sChecked = ($iShowId == 0) ? 'checked' : ''; + $oP->add("'); + $oP->add(""); + $sChecked = ($iShowId == 1) ? 'checked' : ''; + $oP->add("'); + $oP->add(""); + $sChecked = ($iShowId == 3) ? 'checked' : ''; + $oP->add("'); + $oP->add("

\n"); + + $oP->add("\n"); + $oP->add(''); + $oP->add(''); + $oP->add(''); + $oP->add(''); + $oP->add(''); + $oP->add($oAppContext->GetForForm()); + $oP->add("
\n"); + $oP->add('
'); + + + if (!empty($sErrorLabelSelection) || !empty($sClassSelection)) + { + $oP->add("
"); + $oP->add("
"); + $oP->add(''); + $oP->add(''); + $oP->add(''); + $oP->add(''); + $oP->add(''); + $oP->add("\n"); + $oP->add("
\n"); + } + + if (!empty($aResults)) + { + + if ($iShowId == 3) + { + DisplayInconsistenciesReport($aResults); + } + + $oP->p(Dict::S('DBTools:ErrorsFound')); + + $oP->add(''); + $bTable = true; + foreach($aResults as $sClass => $aErrorList) + { + foreach($aErrorList as $sErrorLabel => $aError) + { + if (!empty($sErrorLabelSelection) && ($sErrorLabel != $sErrorLabelSelection)) + { + continue; + } + + if (!$bTable) + { + $oP->add('
'); + $oP->add('
'.Dict::S('DBTools:Class').''.Dict::S('DBTools:Count').''.Dict::S('DBTools:Error').'
'); + $bTable = true; + } + + $oP->add(''); + + + $oP->add(''); + $iCount = $aError['count']; + $oP->add(''); + $oP->add(''); + $oP->add(''); + + if ($iShowId > 0) + { + $oP->add('
ClassCountError
'.MetaModel::GetName($sClass).' ('.$sClass.')'.$iCount.''.$sErrorLabel.'
'); + $bTable = false; + $oP->p(Dict::S('DBTools:SQLquery')); + $sQuery = $aError['query']; + $oP->add('
'); + $oP->add(''.$sQuery.''); + $oP->add('
'); + + if (isset($aError['fixit'])) + { + $oP->p(Dict::S('DBTools:FixitSQLquery')); + $aQueries = $aError['fixit']; + $oP->add('
'); + foreach($aQueries as $sFixQuery) + { + $oP->add('
'.$sFixQuery.'
'); + } + $oP->add('
'); + } + + $oP->p(Dict::S('DBTools:SQLresult')); + $sQueryResult = ''; + $iCount = count($aError['res']); + $iMaxCount = MAX_RESULTS; + foreach($aError['res'] as $aRes) + { + $iMaxCount--; + if ($iMaxCount < 0) + { + $sQueryResult .= 'Displayed '.MAX_RESULTS."/$iCount results.
"; + break; + } + foreach($aRes as $sKey => $sValue) + { + $sQueryResult .= "'$sKey'='$sValue' "; + } + $sQueryResult .= '
'; + } + $oP->add('
'); + $oP->add(''.$sQueryResult.''); + $oP->add('
'); + } + } + } + $oP->add(''); + } + return $oP; +} + +/** + * @param $aResults + * + * @return mixed + * @throws CoreException + * @throws DictExceptionMissingString + */ +function DisplayInconsistenciesReport($aResults) +{ + $sDBToolsFolder = str_replace("\\", '/', APPROOT.'log/'); + $sReportFile = 'dbtools-report-'.date('Y-m-d-H-i-s'); + + $fReport = fopen($sDBToolsFolder.$sReportFile.'.txt', 'w'); + fwrite($fReport, 'Database Maintenance tools: '.date('Y-m-d H:i:s')."\r\n"); + foreach($aResults as $sClass => $aErrorList) + { + fwrite($fReport, ''); + foreach($aErrorList as $sErrorLabel => $aError) + { + fwrite($fReport, "\r\n----------\r\n"); + fwrite($fReport, 'Class: '.MetaModel::GetName($sClass).' ('.$sClass.")\r\n"); + $iCount = $aError['count']; + fwrite($fReport, 'Count: '.$iCount."\r\n"); + fwrite($fReport, 'Error: '.$sErrorLabel."\r\n"); + $sQuery = $aError['query']; + fwrite($fReport, 'Query: '.$sQuery."\r\n"); + + if (isset($aError['fixit'])) + { + fwrite($fReport, "\r\nFix it (indication):\r\n\r\n"); + $aFixitQueries = $aError['fixit']; + foreach($aFixitQueries as $sFixitQuery) + { + fwrite($fReport, "$sFixitQuery\r\n"); + } + fwrite($fReport, "\r\n"); + } + + $sQueryResult = ''; + $aIdList = array(); + foreach($aError['res'] as $aRes) + { + foreach($aRes as $sKey => $sValue) + { + $sQueryResult .= "'$sKey'='$sValue' "; + if ($sKey == 'id') + { + $aIdList[] = $sValue; + } + } + $sQueryResult .= "\r\n"; + + } + fwrite($fReport, "Result: \r\n".$sQueryResult); + $sIdList = '('.implode(',', $aIdList).')'; + fwrite($fReport, 'Ids: '.$sIdList."\r\n"); + } + } + fclose($fReport); + + $oArchive = new ZipArchive(); + $oArchive->open($sDBToolsFolder.$sReportFile.'.zip', ZipArchive::CREATE); + $oArchive->addFile($sDBToolsFolder.$sReportFile.'.txt', $sReportFile.'.txt'); + $oArchive->close(); + unlink($sDBToolsFolder.$sReportFile.'.txt'); + $sReportFile = $sDBToolsFolder.$sReportFile.'.zip'; + + + header('Content-Description: File Transfer'); + header('Content-Type: multipart/x-zip'); + header('Content-Disposition: inline; filename="'.basename($sReportFile).'"'); + header('Expires: 0'); + header('Cache-Control: must-revalidate'); + header('Pragma: public'); + header('Content-Length: '.filesize($sReportFile)); + readfile($sReportFile); + unlink($sReportFile); + exit(0); +} + +/** + * @return float + * @throws MySQLException + * @throws MySQLHasGoneAwayException + */ +function GetDatabaseSize() +{ + $sShema = CMDBSource::DBName(); + + $sReq = <<fetch_assoc(); + $sSize = $aRow['sz']; + return $sSize; + } + + return 0; +} + +/** + * @param iTopWebPage $oP + * @param ApplicationContext $oAppContext + * + * @return \iTopWebPage + * @throws \MySQLException + * @throws \MySQLHasGoneAwayException + */ +function DisplayDatabaseInfo(iTopWebPage &$oP, ApplicationContext &$oAppContext) +{ + // Build HTML + $oP->SetCurrentTab(Dict::S('DBTools:DatabaseInfo')); + + $oP->add('
'); + $oP->add(''); + + $oP->add(''); + $oP->add(''); + $oP->add(''); + $oP->add(''); + $oP->add('
'.Dict::S('DBTools:Base').''.Dict::S('DBTools:Size').'
'); + $oP->add(CMDBSource::DBName()); + $oP->add(''); + $fSize = GetDatabaseSize(); + $oP->add("$fSize MB"); + $oP->add('
'); + + $oP->add('
'); + + return $oP; +} + +/** + * @param iTopWebPage $oP + * @param ApplicationContext $oAppContext + * + * @return \iTopWebPage + * @throws CoreException + * @throws MySQLException + * @throws \Exception + */ +function DisplayLostAttachments(iTopWebPage &$oP, ApplicationContext &$oAppContext) +{ + // Retrieve parameters + $sStepName = utils::ReadParam('step_name'); + $aRecordsToClean = utils::ReadParam('dbt-cbx', array(), false, 'raw_data'); + + $iRestoredItemsCount = 0; + $iRecordsToCleanCount = count($aRecordsToClean); + $aErrorsReport = array(); + + $bDoAnalyze = in_array($sStepName, array('analyze', 'restore')); + $bDoRestore = in_array($sStepName, array('restore')); + + // Build HTML + $oP->SetCurrentTab(Dict::S('DBTools:LostAttachments')); + + $oP->add('
'); + $oP->add('
'); + + $oP->add('
'.Dict::S('DBTools:LostAttachments:Disclaimer').'
'); + $oP->add('
'); + $oP->add('
'); + $oP->add(''); + $oP->add(''); + + // Step 1: Analyze DB + $oP->add('

1.'.Dict::S('DBTools:LostAttachments:Step:Analyze').'

'); + + // Step 2: Display results + if($bDoAnalyze) + { + // Check if we have to restore some items first + if($bDoRestore) + { + foreach($aRecordsToClean as $sRecordToClean) + { + utils::PushArchiveMode(false); // For iTop < 2.5, the application can be wrongly set to archive mode true when it fails from retrieving an object. See r5340. + try + { + // Retrieve attachment + $aLocationParts = explode('::', $sRecordToClean); + /** @var \DBObject $oOriginObject */ + $oOriginObject = MetaModel::GetObject($aLocationParts[0], $aLocationParts[1], true, true); + /** @var \ormDocument $oOrmDocument */ + $oOrmDocument = $oOriginObject->Get('contents'); + + // Retrieve target object + $sTargetClass = $oOriginObject->Get('item_class'); + $sTargetId = $oOriginObject->Get('item_id'); + /** @var \DBObject $oTargetObject */ + $oTargetObject = MetaModel::GetObject($sTargetClass, $sTargetId, true, true); + + // Put it on the target object + /** @var \Attachment $oAttachment */ + $oAttachment = MetaModel::NewObject('Attachment'); + $oAttachment->Set('item_class', $sTargetClass); + $oAttachment->Set('item_id', $sTargetId); + $oAttachment->Set('item_org_id', $oTargetObject->Get('org_id')); + $oAttachment->Set('contents', $oOrmDocument); + $oAttachment->DBInsert(); + + // Put history entry + $sHistoryEntry = Dict::Format('DBTools:LostAttachments:History', $oOrmDocument->GetFileName()); + CMDBObject::SetTrackInfo(UserRights::GetUserFriendlyName()); + $oChangeOp = MetaModel::NewObject('CMDBChangeOpPlugin'); + /** @var \Change $oChange */ + $oChange = CMDBObject::GetCurrentChange(); + $oChangeOp->Set('change', $oChange->GetKey()); + $oChangeOp->Set('objclass', $sTargetClass); + $oChangeOp->Set('objkey', $sTargetId); + $oChangeOp->Set('description', $sHistoryEntry); + $oChangeOp->DBInsert(); + + // Remove origin object (should only be done for InlineImage) + $oOriginObject->DBDelete(); + + $iRestoredItemsCount++; + } + catch(Exception $e) + { + $aErrorsReport[] = 'Could not restore attachment from '.$sRecordToClean.', cause: '.$e->getMessage(); + } + utils::PopArchiveMode(); + } + } + + // Search attachments stored as inline images + $sInlineImageDBTable = MetaModel::DBGetTable('InlineImage'); + $sSelWrongRecs = 'SELECT id, secret, "InlineImage" AS current_class, id AS current_id, item_class AS target_class, item_id AS target_id, contents_filename AS filename FROM '.$sInlineImageDBTable.' WHERE contents_mimetype NOT LIKE "image/%"'; + $aWrongRecords = CMDBSource::QueryToArray($sSelWrongRecs); + + $oP->add('
'); + $oP->add('

2.'.Dict::S('DBTools:LostAttachments:Step:AnalyzeResults').'

'); + + if(empty($aWrongRecords)) + { + $oP->add('
'.Dict::S('DBTools:LostAttachments:Step:AnalyzeResults:None').'
'); + } + else + { + $oP->add('
'.Dict::Format('DBTools:LostAttachments:Step:AnalyzeResults:Some', count($aWrongRecords)).'
'); + + // Display errors as table + $oP->add(''); + $oP->add(''); + + foreach($aWrongRecords as $iIndex => $aWrongRecord) + { + + $sCurrentClass = $aWrongRecord['current_class']; + $sCurrentId = $aWrongRecord['current_id']; + $sRecordToClean = Dict::S('DBTools:LostAttachments:StoredAsInlineImage'); + + $sTargetClass = $aWrongRecord['target_class']; + $sTargetId = $aWrongRecord['target_id']; + $sTargetLocation = ''.$sTargetClass.'::'.$sTargetId.''; + + $sFilename = ''.$aWrongRecord['filename'].''; + + $sRowClass = ($iIndex % 2 === 0) ? 'odd' : 'even'; // (Starts at 0, not 1) + $oP->add(''); + } + + $oP->add('
'.Dict::S('DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename').''.Dict::S('DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation').''.Dict::S('DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation').'
'.$sFilename.''.$sRecordToClean.''.$sTargetLocation.'
'); + $oP->add('
'); + + // JS to handle checkboxes and button + $oP->add_ready_script( +<< 0 ) + { + $('.dbt-lostattachments .dbt-toggler-cbx').prop('checked', false); + } + }); +EOF + ); + } + + $oP->add('
'); + } + + // Step 3: Restore results + if($bDoRestore) + { + $oP->add('
'); + $oP->add('

3.'.Dict::S('DBTools:LostAttachments:Step:RestoreResults').'

'); + + $oP->add('
'.Dict::Format('DBTools:LostAttachments:Step:RestoreResults:Results', $iRestoredItemsCount, $iRecordsToCleanCount).'
'); + + if(!empty($aErrorsReport)) + { + foreach($aErrorsReport as $sErrorReport) + { + $oP->add('
'.$sErrorReport.'
'); + } + } + + $oP->add('
'); + } + + $oP->add($oAppContext->GetForForm()); + $oP->add('
'); + $oP->add('
'); + + $oP->add('
'); + $oP->add('
'); + + // Buttons disabling on click + $sConfirmText = Dict::S('DBTools:LostAttachments:Button:Restore:Confirm'); + $sButtonBusyText = Dict::S('DBTools:LostAttachments:Button:Busy'); + $oP->add_ready_script( +<<add_saas('env-'.utils::GetCurrentEnvironment().'/combodo-db-tools/default.scss'); + + $oP->add( +<< +

$sPageTitle

+ +EOF + ); + $oP->AddTabContainer('db-tools'); + $oP->SetCurrentTabContainer('db-tools'); + + // Database Info + $oP = DisplayDatabaseInfo($oP, $oAppContext); + + // DB Inconsistences + $oP = DisplayDBInconsistencies($oP, $oAppContext); + + // Lost attachments + $oP = DisplayLostAttachments($oP, $oAppContext); +} +catch (Exception $e) +{ + $oP->p(''.$e->getMessage().''); +} + +if (isset($oP)) +{ + $oP->output(); +} diff --git a/datamodels/2.x/combodo-db-tools/de.dict.combodo-db-tools.php b/datamodels/2.x/combodo-db-tools/de.dict.combodo-db-tools.php new file mode 100644 index 000000000..6250d685d --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/de.dict.combodo-db-tools.php @@ -0,0 +1,82 @@ + 'DB Tools', + 'DBTools:Class' => 'Klasse', + 'DBTools:Title' => 'Datenbank-Pflege-Tools', + 'DBTools:ErrorsFound' => 'Fehler gefunden', + 'DBTools:Error' => 'Fehler', + 'DBTools:Count' => 'Anzahl', + 'DBTools:SQLquery' => 'SQL Query', + 'DBTools:FixitSQLquery' => 'SQL query To Fix it (indication)~~', + 'DBTools:SQLresult' => 'SQL Ergebnis', + 'DBTools:NoError' => 'Die Datenbank ist OK', + 'DBTools:HideIds' => 'Fehler', + 'DBTools:ShowIds' => 'Fehler und Werte', + 'DBTools:ShowReport' => 'Report', + 'DBTools:IntegrityCheck' => 'Integritätscheck', + 'DBTools:FetchCheck' => 'Fetch Check (dauert länger)', + + 'DBTools:Analyze' => 'Analysiere', + 'DBTools:Details' => 'Details anzeigen', + 'DBTools:ShowAll' => 'Alle Fehler anzeigen', + + 'DBTools:Inconsistencies' => 'Datenbank-Inkonsistenzen', + + 'DBAnalyzer-Integrity-OrphanRecord' => 'Verwaister Eintrag in `%1$s`, er sollte eine Entsprechung in Tabelle `%2$s` haben', + 'DBAnalyzer-Integrity-InvalidExtKey' => 'Ungültiger Externer Key %1$s (Spalte: `%2$s.%3$s`)', + 'DBAnalyzer-Integrity-MissingExtKey' => 'Fehlender Externer Key %1$s (Spalte: `%2$s.%3$s`)', + 'DBAnalyzer-Integrity-InvalidValue' => 'Ungültiger Wert für %1$s (Spalte: `%2$s.%3$s`)', + 'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Manche Benutzerkonten haben keinerlei zugewiesenes Profi', + 'DBAnalyzer-Fetch-Count-Error' => 'Fetch-Count-Fehler in `%1$s`, %2$d Einträge geholt (fetched) / %3$d gezählt', +)); + +// Database Info +Dict::Add('DE DE', 'German', 'Deutsch', array( + 'DBTools:DatabaseInfo' => 'Datenbank-Information', + 'DBTools:Base' => 'Datenbank', + 'DBTools:Size' => 'Größe', +)); + +// Lost attachments +Dict::Add('DE DE', 'German', 'Deutsch', array( + 'DBTools:LostAttachments' => 'Verlorene Attachments', + 'DBTools:LostAttachments:Disclaimer' => 'Hier können Sie Ihre Datenbank nach verlorenen oder falsch platzierten Attachments durchsuchen. Dies ist kein Recovery-Tool - es stellt keine gelöschten Daten wieder her.', + + 'DBTools:LostAttachments:Button:Analyze' => 'Analysieren', + 'DBTools:LostAttachments:Button:Restore' => 'Wiederherstellen', + 'DBTools:LostAttachments:Button:Restore:Confirm' => 'Diese Aktion kann nicht rückgängig gemacht werden, bitte bestätigen Sie dass Sie die ausgewählten Dateien wiederherstellen möchten.', + 'DBTools:LostAttachments:Button:Busy' => 'Bitte warten...', + + 'DBTools:LostAttachments:Step:Analyze' => 'Suche zunächst nach verlorenen / falsch platzierten Attachments, mittels einer Analyse der Datenbank', + + 'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyseergebnisse:', + 'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Toll! Alles scheint am richtigen Ort zu sein.', + 'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Manche Attachments scheinen am falschen Ort zu sein. Werfen Sie einen Blick auf die folgende Liste und wählen Sie diejenigen aus, die Sie gerne verschieben möchten.', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Dateiname', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Derzeitiger Ort', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Verschieben nach...', + + 'DBTools:LostAttachments:Step:RestoreResults' => 'Restore-Ergebnisse:', + 'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d Attachments wurden wiederhergestellt.', + + 'DBTools:LostAttachments:StoredAsInlineImage' => 'Als Inline-Bild gespeichert', + 'DBTools:LostAttachments:History' => 'Attachment "%1$s" mit DB-Tools wiederhergestellt' +)); diff --git a/datamodels/2.x/combodo-db-tools/default.css b/datamodels/2.x/combodo-db-tools/default.css new file mode 100644 index 000000000..3b2092342 --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/default.css @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2013-2020 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + */ + +.db-tools-tab-content .dbt-lostattachments .dbt-steps .dbt-step { + margin-top: 30px; + /* This is to avoid long exception message on restore errors */ +} +.db-tools-tab-content .dbt-lostattachments .dbt-steps .dbt-step .dbt-step-description { + padding: 0; + margin: 0px 0px 5px 0px; +} +.db-tools-tab-content .dbt-lostattachments .dbt-steps .dbt-step .dbt-step-number { + margin-right: 0.3em; +} +.db-tools-tab-content .dbt-lostattachments .dbt-steps .dbt-step .listResults tr > *:first-child { + text-align: center; +} +.db-tools-tab-content .dbt-lostattachments .dbt-steps .dbt-step .message_error { + max-height: 150px; + overflow-y: auto; +} diff --git a/datamodels/2.x/combodo-db-tools/default.scss b/datamodels/2.x/combodo-db-tools/default.scss new file mode 100644 index 000000000..aaf1ac052 --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/default.scss @@ -0,0 +1,48 @@ +/*! + * Copyright (C) 2013-2020 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + */ + +.db-tools-tab-content{ + .dbt-lostattachments{ + .dbt-steps{ + .dbt-step{ + margin-top: 30px; + + .dbt-step-description{ + padding: 0; + margin: 0px 0px 5px 0px; + } + + .dbt-step-number{ + margin-right: 0.3em; + } + + .listResults{ + tr>*:first-child{ + text-align: center; + } + } + + /* This is to avoid long exception message on restore errors */ + .message_error{ + max-height: 150px; + overflow-y: auto; + } + } + } + } +} \ No newline at end of file diff --git a/datamodels/2.x/combodo-db-tools/en.dict.combodo-db-tools.php b/datamodels/2.x/combodo-db-tools/en.dict.combodo-db-tools.php new file mode 100644 index 000000000..50c1ce949 --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/en.dict.combodo-db-tools.php @@ -0,0 +1,84 @@ + 'DB Tools', + 'DBTools:Class' => 'Class', + 'DBTools:Title' => 'Database Maintenance Tools', + 'DBTools:ErrorsFound' => 'Errors Found', + 'DBTools:Error' => 'Error', + 'DBTools:Count' => 'Count', + 'DBTools:SQLquery' => 'SQL query', + 'DBTools:FixitSQLquery' => 'SQL query To Fix it (indication)', + 'DBTools:SQLresult' => 'SQL result', + 'DBTools:NoError' => 'The database is OK', + 'DBTools:HideIds' => 'Error List', + 'DBTools:ShowIds' => 'Detailed view', + 'DBTools:ShowReport' => 'Report', + 'DBTools:IntegrityCheck' => 'Integrity check', + 'DBTools:FetchCheck' => 'Fetch Check (long)', + + 'DBTools:Analyze' => 'Analyze', + 'DBTools:Details' => 'Show Details', + 'DBTools:ShowAll' => 'Show All Errors', + + 'DBTools:Inconsistencies' => 'Database inconsistencies', + + 'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`', + 'DBAnalyzer-Integrity-InvalidExtKey' => 'Invalid external key %1$s (column: `%2$s.%3$s`)', + 'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)', + 'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)', + 'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all', + 'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted', +)); + +// Database Info +Dict::Add('EN US', 'English', 'English', array( + 'DBTools:DatabaseInfo' => 'Database Information', + 'DBTools:Base' => 'Base', + 'DBTools:Size' => 'Size', +)); + +// Lost attachments +Dict::Add('EN US', 'English', 'English', array( + 'DBTools:LostAttachments' => 'Lost attachments', + 'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.', + + 'DBTools:LostAttachments:Button:Analyze' => 'Analyze', + 'DBTools:LostAttachments:Button:Restore' => 'Restore', + 'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.', + 'DBTools:LostAttachments:Button:Busy' => 'Please wait...', + + 'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.', + + 'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:', + 'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Great! Every thing seems to be at the right place.', + 'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Some attachments (%1$d) seem to be misplaced. Take a look at the following list and check the ones you would like to move.', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Filename', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Current location', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Move to...', + + 'DBTools:LostAttachments:Step:RestoreResults' => 'Restore results:', + 'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d attachments were restored.', + + 'DBTools:LostAttachments:StoredAsInlineImage' => 'Stored as inline image', + 'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools' +)); diff --git a/datamodels/2.x/combodo-db-tools/es_cr.dict.combodo-db-tools.php b/datamodels/2.x/combodo-db-tools/es_cr.dict.combodo-db-tools.php new file mode 100644 index 000000000..5bfc06462 --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/es_cr.dict.combodo-db-tools.php @@ -0,0 +1,83 @@ + 'DB Tools~~', + 'DBTools:Class' => 'Class~~', + 'DBTools:Title' => 'Database Maintenance Tools~~', + 'DBTools:ErrorsFound' => 'Errors Found~~', + 'DBTools:Error' => 'Error~~', + 'DBTools:Count' => 'Count~~', + 'DBTools:SQLquery' => 'SQL query~~', + 'DBTools:FixitSQLquery' => 'SQL query To Fix it (indication)~~', + 'DBTools:SQLresult' => 'SQL result~~', + 'DBTools:NoError' => 'The database is OK~~', + 'DBTools:HideIds' => 'Error List~~', + 'DBTools:ShowIds' => 'Detailed view~~', + 'DBTools:ShowReport' => 'Report~~', + 'DBTools:IntegrityCheck' => 'Integrity check~~', + 'DBTools:FetchCheck' => 'Fetch Check (long)~~', + + 'DBTools:Analyze' => 'Analyze~~', + 'DBTools:Details' => 'Show Details~~', + 'DBTools:ShowAll' => 'Show All Errors~~', + + 'DBTools:Inconsistencies' => 'Database inconsistencies~~', + + 'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~', + 'DBAnalyzer-Integrity-InvalidExtKey' => 'Invalid external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~', + 'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted~~', +)); + +// Database Info +Dict::Add('ES CR', 'Spanish', 'Español, Castellaño', array( + 'DBTools:DatabaseInfo' => 'Database Information~~', + 'DBTools:Base' => 'Base~~', + 'DBTools:Size' => 'Size~~', +)); + +// Lost attachments +Dict::Add('ES CR', 'Spanish', 'Español, Castellaño', array( + 'DBTools:LostAttachments' => 'Lost attachments~~', + 'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~', + + 'DBTools:LostAttachments:Button:Analyze' => 'Analyze~~', + 'DBTools:LostAttachments:Button:Restore' => 'Restore~~', + 'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~', + 'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~', + + 'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~', + + 'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Great! Every thing seems to be at the right place.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Some attachments (%1$d) seem to be misplaced. Take a look at the following list and check the ones you would like to move.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Filename~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Current location~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Move to...~~', + + 'DBTools:LostAttachments:Step:RestoreResults' => 'Restore results:~~', + 'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d attachments were restored.~~', + + 'DBTools:LostAttachments:StoredAsInlineImage' => 'Stored as inline image~~', + 'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~' +)); diff --git a/datamodels/2.x/combodo-db-tools/fr.dict.combodo-db-tools.php b/datamodels/2.x/combodo-db-tools/fr.dict.combodo-db-tools.php new file mode 100644 index 000000000..fa1f5d351 --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/fr.dict.combodo-db-tools.php @@ -0,0 +1,82 @@ + 'Outils BDD', + 'DBTools:Class' => 'Classe', + 'DBTools:Title' => 'Outils maintenance base de données', + 'DBTools:ErrorsFound' => 'Erreurs trouvées', + 'DBTools:Error' => 'Erreur', + 'DBTools:Count' => 'Nombre', + 'DBTools:SQLquery' => 'Requête SQL', + 'DBTools:FixitSQLquery' => 'Requête SQL pour nettoyer la base (indication)', + 'DBTools:SQLresult' => 'Résultat SQL', + 'DBTools:NoError' => 'La base de données est OK', + 'DBTools:HideIds' => 'Erreurs', + 'DBTools:ShowIds' => 'Détails des erreurs', + 'DBTools:ShowReport' => 'Rapport', + 'DBTools:IntegrityCheck' => 'Contrôle d\'intégrité', + 'DBTools:FetchCheck' => 'Contrôle de récupération (long)', + + 'DBTools:Analyze' => 'Analyser', + 'DBTools:Details' => 'Afficher détails', + 'DBTools:ShowAll' => 'Afficher toutes les erreurs', + + 'DBTools:Inconsistencies' => 'Incohérences de base de données', + + 'DBAnalyzer-Integrity-OrphanRecord' => 'Enregistrement orphelin dans `%1$s`, il devrait avoir son équivalent dans la tableit `%2$s`', + 'DBAnalyzer-Integrity-InvalidExtKey' => 'Clef externe invalide %1$s (colonne: `%2$s.%3$s`)', + 'DBAnalyzer-Integrity-MissingExtKey' => 'Clef externe manquante %1$s (colonne: `%2$s.%3$s`)', + 'DBAnalyzer-Integrity-InvalidValue' => 'Valeur invalide pour %1$s (colonne: `%2$s.%3$s`)', + 'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Certains comptes utilisateurs n\'ont aucun profile', + 'DBAnalyzer-Fetch-Count-Error' => 'Erreur de récupération dans `%1$s`, %2$d enregistrements récupérés / %3$d comptés', +)); + +// Database Info +Dict::Add('FR FR', 'French', 'Français', array( + 'DBTools:DatabaseInfo' => 'Information Base de Données', + 'DBTools:Base' => 'Base', + 'DBTools:Size' => 'Taille', +)); + +// Lost attachments +Dict::Add('FR FR', 'French', 'Français', array( + 'DBTools:LostAttachments' => 'Pièces jointes perdues', + 'DBTools:LostAttachments:Disclaimer' => 'Ici vous pouvez retrouver des pièces jointes perdues ou égarées dans votre base de données. Ceci n\'est PAS un outil de récupération des données, il ne récupère pas les données effacées.', + + 'DBTools:LostAttachments:Button:Analyze' => 'Analyser', + 'DBTools:LostAttachments:Button:Restore' => 'Restaurer', + 'DBTools:LostAttachments:Button:Restore:Confirm' => 'Cet action ne peut être annuler, veuillez confirmer que vous voulez restaurer les fichiers sélectionnés.', + 'DBTools:LostAttachments:Button:Busy' => 'Patientez ...', + + 'DBTools:LostAttachments:Step:Analyze' => 'Tout d\'abord, scannez la base de données à la recherche de pièces jointes perdues/égarées.', + + 'DBTools:LostAttachments:Step:AnalyzeResults' => 'Résultat de l\'analyse :', + 'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Parfait ! Il semble que tout soit en ordre.', + 'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Certaines pièces jointes (%1$d) semblent être au mauvais endroit. Examinez la liste suivante et cochez celles que vous souhaitez déplacer.', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Nom de fichier', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Emplacement actuel', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Déplacer vers ...', + + 'DBTools:LostAttachments:Step:RestoreResults' => 'Résultats de la restauration :', + 'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d pièces jointes ont été restaurées.', + + 'DBTools:LostAttachments:StoredAsInlineImage' => 'Stockée comme "InlineImage"', + 'DBTools:LostAttachments:History' => 'Pièce jointe "%1$s" restaurée avec l\'outil de BDD' +)); diff --git a/datamodels/2.x/combodo-db-tools/hu.dict.combodo-db-tools.php b/datamodels/2.x/combodo-db-tools/hu.dict.combodo-db-tools.php new file mode 100644 index 000000000..0abaf7b16 --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/hu.dict.combodo-db-tools.php @@ -0,0 +1,83 @@ + 'DB Tools~~', + 'DBTools:Class' => 'Class~~', + 'DBTools:Title' => 'Database Maintenance Tools~~', + 'DBTools:ErrorsFound' => 'Errors Found~~', + 'DBTools:Error' => 'Error~~', + 'DBTools:Count' => 'Count~~', + 'DBTools:SQLquery' => 'SQL query~~', + 'DBTools:FixitSQLquery' => 'SQL query To Fix it (indication)~~', + 'DBTools:SQLresult' => 'SQL result~~', + 'DBTools:NoError' => 'The database is OK~~', + 'DBTools:HideIds' => 'Error List~~', + 'DBTools:ShowIds' => 'Detailed view~~', + 'DBTools:ShowReport' => 'Report~~', + 'DBTools:IntegrityCheck' => 'Integrity check~~', + 'DBTools:FetchCheck' => 'Fetch Check (long)~~', + + 'DBTools:Analyze' => 'Analyze~~', + 'DBTools:Details' => 'Show Details~~', + 'DBTools:ShowAll' => 'Show All Errors~~', + + 'DBTools:Inconsistencies' => 'Database inconsistencies~~', + + 'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~', + 'DBAnalyzer-Integrity-InvalidExtKey' => 'Invalid external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~', + 'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted~~', +)); + +// Database Info +Dict::Add('HU HU', 'Hungarian', 'Magyar', array( + 'DBTools:DatabaseInfo' => 'Database Information~~', + 'DBTools:Base' => 'Base~~', + 'DBTools:Size' => 'Size~~', +)); + +// Lost attachments +Dict::Add('HU HU', 'Hungarian', 'Magyar', array( + 'DBTools:LostAttachments' => 'Lost attachments~~', + 'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~', + + 'DBTools:LostAttachments:Button:Analyze' => 'Analyze~~', + 'DBTools:LostAttachments:Button:Restore' => 'Restore~~', + 'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~', + 'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~', + + 'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~', + + 'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Great! Every thing seems to be at the right place.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Some attachments (%1$d) seem to be misplaced. Take a look at the following list and check the ones you would like to move.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Filename~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Current location~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Move to...~~', + + 'DBTools:LostAttachments:Step:RestoreResults' => 'Restore results:~~', + 'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d attachments were restored.~~', + + 'DBTools:LostAttachments:StoredAsInlineImage' => 'Stored as inline image~~', + 'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~' +)); diff --git a/datamodels/2.x/combodo-db-tools/it.dict.combodo-db-tools.php b/datamodels/2.x/combodo-db-tools/it.dict.combodo-db-tools.php new file mode 100644 index 000000000..f5b63b4fa --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/it.dict.combodo-db-tools.php @@ -0,0 +1,83 @@ + 'DB Tools~~', + 'DBTools:Class' => 'Class~~', + 'DBTools:Title' => 'Database Maintenance Tools~~', + 'DBTools:ErrorsFound' => 'Errors Found~~', + 'DBTools:Error' => 'Error~~', + 'DBTools:Count' => 'Count~~', + 'DBTools:SQLquery' => 'SQL query~~', + 'DBTools:FixitSQLquery' => 'SQL query To Fix it (indication)~~', + 'DBTools:SQLresult' => 'SQL result~~', + 'DBTools:NoError' => 'The database is OK~~', + 'DBTools:HideIds' => 'Error List~~', + 'DBTools:ShowIds' => 'Detailed view~~', + 'DBTools:ShowReport' => 'Report~~', + 'DBTools:IntegrityCheck' => 'Integrity check~~', + 'DBTools:FetchCheck' => 'Fetch Check (long)~~', + + 'DBTools:Analyze' => 'Analyze~~', + 'DBTools:Details' => 'Show Details~~', + 'DBTools:ShowAll' => 'Show All Errors~~', + + 'DBTools:Inconsistencies' => 'Database inconsistencies~~', + + 'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~', + 'DBAnalyzer-Integrity-InvalidExtKey' => 'Invalid external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~', + 'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted~~', +)); + +// Database Info +Dict::Add('IT IT', 'Italian', 'Italiano', array( + 'DBTools:DatabaseInfo' => 'Database Information~~', + 'DBTools:Base' => 'Base~~', + 'DBTools:Size' => 'Size~~', +)); + +// Lost attachments +Dict::Add('IT IT', 'Italian', 'Italiano', array( + 'DBTools:LostAttachments' => 'Lost attachments~~', + 'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~', + + 'DBTools:LostAttachments:Button:Analyze' => 'Analyze~~', + 'DBTools:LostAttachments:Button:Restore' => 'Restore~~', + 'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~', + 'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~', + + 'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~', + + 'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Great! Every thing seems to be at the right place.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Some attachments (%1$d) seem to be misplaced. Take a look at the following list and check the ones you would like to move.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Filename~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Current location~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Move to...~~', + + 'DBTools:LostAttachments:Step:RestoreResults' => 'Restore results:~~', + 'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d attachments were restored.~~', + + 'DBTools:LostAttachments:StoredAsInlineImage' => 'Stored as inline image~~', + 'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~' +)); diff --git a/datamodels/2.x/combodo-db-tools/ja.dict.combodo-db-tools.php b/datamodels/2.x/combodo-db-tools/ja.dict.combodo-db-tools.php new file mode 100644 index 000000000..4e5386823 --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/ja.dict.combodo-db-tools.php @@ -0,0 +1,83 @@ + 'DB Tools~~', + 'DBTools:Class' => 'Class~~', + 'DBTools:Title' => 'Database Maintenance Tools~~', + 'DBTools:ErrorsFound' => 'Errors Found~~', + 'DBTools:Error' => 'Error~~', + 'DBTools:Count' => 'Count~~', + 'DBTools:SQLquery' => 'SQL query~~', + 'DBTools:FixitSQLquery' => 'SQL query To Fix it (indication)~~', + 'DBTools:SQLresult' => 'SQL result~~', + 'DBTools:NoError' => 'The database is OK~~', + 'DBTools:HideIds' => 'Error List~~', + 'DBTools:ShowIds' => 'Detailed view~~', + 'DBTools:ShowReport' => 'Report~~', + 'DBTools:IntegrityCheck' => 'Integrity check~~', + 'DBTools:FetchCheck' => 'Fetch Check (long)~~', + + 'DBTools:Analyze' => 'Analyze~~', + 'DBTools:Details' => 'Show Details~~', + 'DBTools:ShowAll' => 'Show All Errors~~', + + 'DBTools:Inconsistencies' => 'Database inconsistencies~~', + + 'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~', + 'DBAnalyzer-Integrity-InvalidExtKey' => 'Invalid external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~', + 'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted~~', +)); + +// Database Info +Dict::Add('JA JP', 'Japanese', '日本語', array( + 'DBTools:DatabaseInfo' => 'Database Information~~', + 'DBTools:Base' => 'Base~~', + 'DBTools:Size' => 'Size~~', +)); + +// Lost attachments +Dict::Add('JA JP', 'Japanese', '日本語', array( + 'DBTools:LostAttachments' => 'Lost attachments~~', + 'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~', + + 'DBTools:LostAttachments:Button:Analyze' => 'Analyze~~', + 'DBTools:LostAttachments:Button:Restore' => 'Restore~~', + 'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~', + 'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~', + + 'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~', + + 'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Great! Every thing seems to be at the right place.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Some attachments (%1$d) seem to be misplaced. Take a look at the following list and check the ones you would like to move.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Filename~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Current location~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Move to...~~', + + 'DBTools:LostAttachments:Step:RestoreResults' => 'Restore results:~~', + 'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d attachments were restored.~~', + + 'DBTools:LostAttachments:StoredAsInlineImage' => 'Stored as inline image~~', + 'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~' +)); diff --git a/datamodels/2.x/combodo-db-tools/module.combodo-db-tools.php b/datamodels/2.x/combodo-db-tools/module.combodo-db-tools.php new file mode 100644 index 000000000..b56397756 --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/module.combodo-db-tools.php @@ -0,0 +1,57 @@ + 'Database maintenance tools', + 'category' => 'business', + + // Setup + // + 'dependencies' => array(), + 'mandatory' => true, + 'visible' => false, + + // Components + // + 'datamodel' => array( + 'model.combodo-db-tools.php', + ), + 'webservice' => array(), + 'data.struct' => array(), + 'data.sample' => array(), + + // Documentation + // + 'doc.manual_setup' => '', // hyperlink to manual setup documentation, if any + 'doc.more_information' => '', // hyperlink to more information, if any + + // Default settings + // + 'settings' => array(), + ) +); diff --git a/datamodels/2.x/combodo-db-tools/nl.dict.combodo-db-tools.php b/datamodels/2.x/combodo-db-tools/nl.dict.combodo-db-tools.php new file mode 100644 index 000000000..0864a774c --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/nl.dict.combodo-db-tools.php @@ -0,0 +1,83 @@ + 'DB Tools~~', + 'DBTools:Class' => 'Class~~', + 'DBTools:Title' => 'Database Maintenance Tools~~', + 'DBTools:ErrorsFound' => 'Errors Found~~', + 'DBTools:Error' => 'Error~~', + 'DBTools:Count' => 'Count~~', + 'DBTools:SQLquery' => 'SQL query~~', + 'DBTools:FixitSQLquery' => 'SQL query To Fix it (indication)~~', + 'DBTools:SQLresult' => 'SQL result~~', + 'DBTools:NoError' => 'The database is OK~~', + 'DBTools:HideIds' => 'Error List~~', + 'DBTools:ShowIds' => 'Detailed view~~', + 'DBTools:ShowReport' => 'Report~~', + 'DBTools:IntegrityCheck' => 'Integrity check~~', + 'DBTools:FetchCheck' => 'Fetch Check (long)~~', + + 'DBTools:Analyze' => 'Analyze~~', + 'DBTools:Details' => 'Show Details~~', + 'DBTools:ShowAll' => 'Show All Errors~~', + + 'DBTools:Inconsistencies' => 'Database inconsistencies~~', + + 'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~', + 'DBAnalyzer-Integrity-InvalidExtKey' => 'Invalid external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~', + 'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted~~', +)); + +// Database Info +Dict::Add('NL NL', 'Dutch', 'Nederlands', array( + 'DBTools:DatabaseInfo' => 'Database Information~~', + 'DBTools:Base' => 'Base~~', + 'DBTools:Size' => 'Size~~', +)); + +// Lost attachments +Dict::Add('NL NL', 'Dutch', 'Nederlands', array( + 'DBTools:LostAttachments' => 'Lost attachments~~', + 'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~', + + 'DBTools:LostAttachments:Button:Analyze' => 'Analyze~~', + 'DBTools:LostAttachments:Button:Restore' => 'Restore~~', + 'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~', + 'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~', + + 'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~', + + 'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Great! Every thing seems to be at the right place.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Some attachments (%1$d) seem to be misplaced. Take a look at the following list and check the ones you would like to move.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Filename~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Current location~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Move to...~~', + + 'DBTools:LostAttachments:Step:RestoreResults' => 'Restore results:~~', + 'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d attachments were restored.~~', + + 'DBTools:LostAttachments:StoredAsInlineImage' => 'Stored as inline image~~', + 'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~' +)); diff --git a/datamodels/2.x/combodo-db-tools/pt_br.dict.combodo-db-tools.php b/datamodels/2.x/combodo-db-tools/pt_br.dict.combodo-db-tools.php new file mode 100644 index 000000000..3dcb19670 --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/pt_br.dict.combodo-db-tools.php @@ -0,0 +1,83 @@ + 'DB Tools~~', + 'DBTools:Class' => 'Class~~', + 'DBTools:Title' => 'Database Maintenance Tools~~', + 'DBTools:ErrorsFound' => 'Errors Found~~', + 'DBTools:Error' => 'Error~~', + 'DBTools:Count' => 'Count~~', + 'DBTools:SQLquery' => 'SQL query~~', + 'DBTools:FixitSQLquery' => 'SQL query To Fix it (indication)~~', + 'DBTools:SQLresult' => 'SQL result~~', + 'DBTools:NoError' => 'The database is OK~~', + 'DBTools:HideIds' => 'Error List~~', + 'DBTools:ShowIds' => 'Detailed view~~', + 'DBTools:ShowReport' => 'Report~~', + 'DBTools:IntegrityCheck' => 'Integrity check~~', + 'DBTools:FetchCheck' => 'Fetch Check (long)~~', + + 'DBTools:Analyze' => 'Analyze~~', + 'DBTools:Details' => 'Show Details~~', + 'DBTools:ShowAll' => 'Show All Errors~~', + + 'DBTools:Inconsistencies' => 'Database inconsistencies~~', + + 'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~', + 'DBAnalyzer-Integrity-InvalidExtKey' => 'Invalid external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~', + 'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted~~', +)); + +// Database Info +Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( + 'DBTools:DatabaseInfo' => 'Database Information~~', + 'DBTools:Base' => 'Base~~', + 'DBTools:Size' => 'Size~~', +)); + +// Lost attachments +Dict::Add('PT BR', 'Brazilian', 'Brazilian', array( + 'DBTools:LostAttachments' => 'Lost attachments~~', + 'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~', + + 'DBTools:LostAttachments:Button:Analyze' => 'Analyze~~', + 'DBTools:LostAttachments:Button:Restore' => 'Restore~~', + 'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~', + 'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~', + + 'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~', + + 'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Great! Every thing seems to be at the right place.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Some attachments (%1$d) seem to be misplaced. Take a look at the following list and check the ones you would like to move.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Filename~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Current location~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Move to...~~', + + 'DBTools:LostAttachments:Step:RestoreResults' => 'Restore results:~~', + 'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d attachments were restored.~~', + + 'DBTools:LostAttachments:StoredAsInlineImage' => 'Stored as inline image~~', + 'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~' +)); diff --git a/datamodels/2.x/combodo-db-tools/ru.dict.combodo-db-tools.php b/datamodels/2.x/combodo-db-tools/ru.dict.combodo-db-tools.php new file mode 100644 index 000000000..f7409a4ac --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/ru.dict.combodo-db-tools.php @@ -0,0 +1,83 @@ + 'DB Tools~~', + 'DBTools:Class' => 'Class~~', + 'DBTools:Title' => 'Database Maintenance Tools~~', + 'DBTools:ErrorsFound' => 'Errors Found~~', + 'DBTools:Error' => 'Error~~', + 'DBTools:Count' => 'Count~~', + 'DBTools:SQLquery' => 'SQL query~~', + 'DBTools:FixitSQLquery' => 'SQL query To Fix it (indication)~~', + 'DBTools:SQLresult' => 'SQL result~~', + 'DBTools:NoError' => 'The database is OK~~', + 'DBTools:HideIds' => 'Error List~~', + 'DBTools:ShowIds' => 'Detailed view~~', + 'DBTools:ShowReport' => 'Report~~', + 'DBTools:IntegrityCheck' => 'Integrity check~~', + 'DBTools:FetchCheck' => 'Fetch Check (long)~~', + + 'DBTools:Analyze' => 'Analyze~~', + 'DBTools:Details' => 'Show Details~~', + 'DBTools:ShowAll' => 'Show All Errors~~', + + 'DBTools:Inconsistencies' => 'Database inconsistencies~~', + + 'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~', + 'DBAnalyzer-Integrity-InvalidExtKey' => 'Invalid external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~', + 'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted~~', +)); + +// Database Info +Dict::Add('RU RU', 'Russian', 'Русский', array( + 'DBTools:DatabaseInfo' => 'Database Information~~', + 'DBTools:Base' => 'Base~~', + 'DBTools:Size' => 'Size~~', +)); + +// Lost attachments +Dict::Add('RU RU', 'Russian', 'Русский', array( + 'DBTools:LostAttachments' => 'Lost attachments~~', + 'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~', + + 'DBTools:LostAttachments:Button:Analyze' => 'Analyze~~', + 'DBTools:LostAttachments:Button:Restore' => 'Restore~~', + 'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~', + 'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~', + + 'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~', + + 'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Great! Every thing seems to be at the right place.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Some attachments (%1$d) seem to be misplaced. Take a look at the following list and check the ones you would like to move.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Filename~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Current location~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Move to...~~', + + 'DBTools:LostAttachments:Step:RestoreResults' => 'Restore results:~~', + 'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d attachments were restored.~~', + + 'DBTools:LostAttachments:StoredAsInlineImage' => 'Stored as inline image~~', + 'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~' +)); diff --git a/datamodels/2.x/combodo-db-tools/tr.dict.combodo-db-tools.php b/datamodels/2.x/combodo-db-tools/tr.dict.combodo-db-tools.php new file mode 100644 index 000000000..bb0557dd8 --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/tr.dict.combodo-db-tools.php @@ -0,0 +1,83 @@ + 'DB Tools~~', + 'DBTools:Class' => 'Class~~', + 'DBTools:Title' => 'Database Maintenance Tools~~', + 'DBTools:ErrorsFound' => 'Errors Found~~', + 'DBTools:Error' => 'Error~~', + 'DBTools:Count' => 'Count~~', + 'DBTools:SQLquery' => 'SQL query~~', + 'DBTools:FixitSQLquery' => 'SQL query To Fix it (indication)~~', + 'DBTools:SQLresult' => 'SQL result~~', + 'DBTools:NoError' => 'The database is OK~~', + 'DBTools:HideIds' => 'Error List~~', + 'DBTools:ShowIds' => 'Detailed view~~', + 'DBTools:ShowReport' => 'Report~~', + 'DBTools:IntegrityCheck' => 'Integrity check~~', + 'DBTools:FetchCheck' => 'Fetch Check (long)~~', + + 'DBTools:Analyze' => 'Analyze~~', + 'DBTools:Details' => 'Show Details~~', + 'DBTools:ShowAll' => 'Show All Errors~~', + + 'DBTools:Inconsistencies' => 'Database inconsistencies~~', + + 'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~', + 'DBAnalyzer-Integrity-InvalidExtKey' => 'Invalid external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~', + 'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted~~', +)); + +// Database Info +Dict::Add('TR TR', 'Turkish', 'Türkçe', array( + 'DBTools:DatabaseInfo' => 'Database Information~~', + 'DBTools:Base' => 'Base~~', + 'DBTools:Size' => 'Size~~', +)); + +// Lost attachments +Dict::Add('TR TR', 'Turkish', 'Türkçe', array( + 'DBTools:LostAttachments' => 'Lost attachments~~', + 'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~', + + 'DBTools:LostAttachments:Button:Analyze' => 'Analyze~~', + 'DBTools:LostAttachments:Button:Restore' => 'Restore~~', + 'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~', + 'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~', + + 'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~', + + 'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Great! Every thing seems to be at the right place.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Some attachments (%1$d) seem to be misplaced. Take a look at the following list and check the ones you would like to move.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Filename~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Current location~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Move to...~~', + + 'DBTools:LostAttachments:Step:RestoreResults' => 'Restore results:~~', + 'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d attachments were restored.~~', + + 'DBTools:LostAttachments:StoredAsInlineImage' => 'Stored as inline image~~', + 'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~' +)); diff --git a/datamodels/2.x/combodo-db-tools/zh_cn.dict.combodo-db-tools.php b/datamodels/2.x/combodo-db-tools/zh_cn.dict.combodo-db-tools.php new file mode 100644 index 000000000..49346c284 --- /dev/null +++ b/datamodels/2.x/combodo-db-tools/zh_cn.dict.combodo-db-tools.php @@ -0,0 +1,83 @@ + 'DB Tools~~', + 'DBTools:Class' => 'Class~~', + 'DBTools:Title' => 'Database Maintenance Tools~~', + 'DBTools:ErrorsFound' => 'Errors Found~~', + 'DBTools:Error' => 'Error~~', + 'DBTools:Count' => 'Count~~', + 'DBTools:SQLquery' => 'SQL query~~', + 'DBTools:FixitSQLquery' => 'SQL query To Fix it (indication)~~', + 'DBTools:SQLresult' => 'SQL result~~', + 'DBTools:NoError' => 'The database is OK~~', + 'DBTools:HideIds' => 'Error List~~', + 'DBTools:ShowIds' => 'Detailed view~~', + 'DBTools:ShowReport' => 'Report~~', + 'DBTools:IntegrityCheck' => 'Integrity check~~', + 'DBTools:FetchCheck' => 'Fetch Check (long)~~', + + 'DBTools:Analyze' => 'Analyze~~', + 'DBTools:Details' => 'Show Details~~', + 'DBTools:ShowAll' => 'Show All Errors~~', + + 'DBTools:Inconsistencies' => 'Database inconsistencies~~', + + 'DBAnalyzer-Integrity-OrphanRecord' => 'Orphan record in `%1$s`, it should have its counterpart in table `%2$s`~~', + 'DBAnalyzer-Integrity-InvalidExtKey' => 'Invalid external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-MissingExtKey' => 'Missing external key %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)~~', + 'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all~~', + 'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted~~', +)); + +// Database Info +Dict::Add('ZH CN', 'Chinese', '简体中文', array( + 'DBTools:DatabaseInfo' => 'Database Information~~', + 'DBTools:Base' => 'Base~~', + 'DBTools:Size' => 'Size~~', +)); + +// Lost attachments +Dict::Add('ZH CN', 'Chinese', '简体中文', array( + 'DBTools:LostAttachments' => 'Lost attachments~~', + 'DBTools:LostAttachments:Disclaimer' => 'Here you can search your database for lost or misplaced attachments. This is NOT a data recovery tool, is does not retrieve deleted data.~~', + + 'DBTools:LostAttachments:Button:Analyze' => 'Analyze~~', + 'DBTools:LostAttachments:Button:Restore' => 'Restore~~', + 'DBTools:LostAttachments:Button:Restore:Confirm' => 'This action cannot be undone, please confirm that you want to restore the selected files.~~', + 'DBTools:LostAttachments:Button:Busy' => 'Please wait...~~', + + 'DBTools:LostAttachments:Step:Analyze' => 'First, search for lost/misplaced attachments by analyzing the database.~~', + + 'DBTools:LostAttachments:Step:AnalyzeResults' => 'Analyze results:~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:None' => 'Great! Every thing seems to be at the right place.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Some' => 'Some attachments (%1$d) seem to be misplaced. Take a look at the following list and check the ones you would like to move.~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:Filename' => 'Filename~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:CurrentLocation' => 'Current location~~', + 'DBTools:LostAttachments:Step:AnalyzeResults:Item:TargetLocation' => 'Move to...~~', + + 'DBTools:LostAttachments:Step:RestoreResults' => 'Restore results:~~', + 'DBTools:LostAttachments:Step:RestoreResults:Results' => '%1$d/%2$d attachments were restored.~~', + + 'DBTools:LostAttachments:StoredAsInlineImage' => 'Stored as inline image~~', + 'DBTools:LostAttachments:History' => 'Attachment "%1$s" restored with DB tools~~' +));