From 93e1f6ae03ca99b7a4b7bfeaaee75997192dcbbc Mon Sep 17 00:00:00 2001 From: Lars Kaltefleiter Date: Fri, 12 Apr 2024 09:17:17 +0200 Subject: [PATCH 1/4] =?UTF-8?q?N=C2=B06964=20-=20Add=20API=20to=20allow=20?= =?UTF-8?q?modules=20to=20register=20files=20to=20include=20in=20the=20bac?= =?UTF-8?q?kup=20(#547)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Allow to include backup extra file via interface * Update application/applicationextension.inc.php Co-authored-by: Thomas Casteleyn * Add iBackupExtraFilesExtension to plugin list * decouple extra_files via config and interface * Add unit tests for iBackupExtraFilesExtension * Enable recursive creation of destination directories * Update application/applicationextension.inc.php Co-authored-by: Molkobain * Update setup/backup.class.inc.php Co-authored-by: Molkobain * Update tests/php-unit-tests/unitary-tests/application/applicationextension/ApplicationExtensionTest.php Co-authored-by: Molkobain * Update application/applicationextension.inc.php Co-authored-by: Molkobain * Update core/metamodel.class.php Co-authored-by: Molkobain * Update setup/backup.class.inc.php Co-authored-by: Molkobain --------- Co-authored-by: Thomas Casteleyn Co-authored-by: Molkobain --- application/applicationextension.inc.php | 20 ++++++- setup/backup.class.inc.php | 60 +++++++++++-------- .../ApplicationExtensionTest.php | 4 ++ ...plication-extension-usages-in-snippets.xml | 15 +++++ 4 files changed, 73 insertions(+), 26 deletions(-) diff --git a/application/applicationextension.inc.php b/application/applicationextension.inc.php index 106f029d0..915eda70d 100644 --- a/application/applicationextension.inc.php +++ b/application/applicationextension.inc.php @@ -2281,4 +2281,22 @@ interface iKPILoggerExtension * @return mixed */ public function LogOperation($oKpiLogData); -} \ No newline at end of file +} + +/** + * Implement this interface to add files to the backup + * + * @api + * @since 3.2.0 + */ +interface iBackupExtraFilesExtension +{ + /** + * Returns an array of files and directories to be included in the backup + * + * @api + * + * @return string[] + */ + public function GetExtraFiles(): array; +} diff --git a/setup/backup.class.inc.php b/setup/backup.class.inc.php index ebb7a542d..43c0aeeb8 100644 --- a/setup/backup.class.inc.php +++ b/setup/backup.class.inc.php @@ -265,35 +265,45 @@ class DBBackup SetupUtils::copydir($sExtraDir, $sFile); $aRet[] = $sFile; } + + $aExtraFiles = []; if (MetaModel::GetConfig() !== null) // During unattended install config file may be absent { $aExtraFiles = MetaModel::GetModuleSetting('itop-backup', 'extra_files', []); - foreach($aExtraFiles as $sExtraFileOrDir) + } + + foreach (utils::GetClassesForInterface('iBackupExtraFilesExtension', '', ['[\\\\/]lib[\\\\/]', '[\\\\/]node_modules[\\\\/]', '[\\\\/]test[\\\\/]', '[\\\\/]tests[\\\\/]']) as $sExtensionClass) + { + /** @var iBackupExtraFilesExtension $oExtensionInstance */ + $oExtensionInstance = new $sExtensionClass(); + $aExtraFiles = array_merge($aExtraFiles, $oExtensionInstance->GetExtraFiles()); + } + + foreach($aExtraFiles as $sExtraFileOrDir) + { + if(!file_exists(APPROOT.'/'.$sExtraFileOrDir)) { + continue; // Ignore non-existing files + } + + $sExtraFullPath = utils::RealPath(APPROOT.'/'.$sExtraFileOrDir, APPROOT); + if ($sExtraFullPath === false) { - if(!file_exists(APPROOT.'/'.$sExtraFileOrDir)) { - continue; // Ignore non-existing files - } - - $sExtraFullPath = utils::RealPath(APPROOT.'/'.$sExtraFileOrDir, APPROOT); - if ($sExtraFullPath === false) - { - throw new Exception("Backup: Aborting, resource '$sExtraFileOrDir'. Considered as UNSAFE because not inside the iTop directory."); - } - if (is_dir($sExtraFullPath)) - { - $sFile = $sTmpFolder.'/'.$sExtraFileOrDir; - $this->LogInfo("backup: adding directory '$sExtraFileOrDir'"); - SetupUtils::copydir($sExtraFullPath, $sFile); - $aRet[] = $sFile; - } - elseif (file_exists($sExtraFullPath)) - { - $sFile = $sTmpFolder.'/'.$sExtraFileOrDir; - $this->LogInfo("backup: adding file '$sExtraFileOrDir'"); - @mkdir(dirname($sFile), 0755, true); - copy($sExtraFullPath, $sFile); - $aRet[] = $sFile; - } + throw new Exception("Backup: Aborting, resource '$sExtraFileOrDir'. Considered as UNSAFE because not inside the iTop directory."); + } + if (is_dir($sExtraFullPath)) + { + $sFile = $sTmpFolder.'/'.$sExtraFileOrDir; + $this->LogInfo("backup: adding directory '$sExtraFileOrDir'"); + SetupUtils::copydir($sExtraFullPath, $sFile); + $aRet[] = $sFile; + } + elseif (file_exists($sExtraFullPath)) + { + $sFile = $sTmpFolder.'/'.$sExtraFileOrDir; + $this->LogInfo("backup: adding file '$sExtraFileOrDir'"); + @mkdir(dirname($sFile), 0755, true); + copy($sExtraFullPath, $sFile); + $aRet[] = $sFile; } } if (!$bSkipSQLDumpForTesting) diff --git a/tests/php-unit-tests/unitary-tests/application/applicationextension/ApplicationExtensionTest.php b/tests/php-unit-tests/unitary-tests/application/applicationextension/ApplicationExtensionTest.php index db3474b25..3e4f53fcd 100644 --- a/tests/php-unit-tests/unitary-tests/application/applicationextension/ApplicationExtensionTest.php +++ b/tests/php-unit-tests/unitary-tests/application/applicationextension/ApplicationExtensionTest.php @@ -161,6 +161,10 @@ class ApplicationExtensionTest extends ItopCustomDatamodelTestCase \iNewsroomProvider::class, static::ENUM_API_CALL_METHOD_GETCLASSESFORINTERFACE, ], + \iBackupExtraFilesExtension::class => [ + \iBackupExtraFilesExtension::class, + static::ENUM_API_CALL_METHOD_GETCLASSESFORINTERFACE, + ], ]; } } diff --git a/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml b/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml index 96d06ee9b..3a80b4c47 100644 --- a/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml +++ b/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml @@ -350,6 +350,21 @@ class ExampleFor_iKPILoggerExtension implements \iKPILoggerExtension { // Do nothing, we just need the class to exists for the unit test } +} + ]]> + + + core + 0 + From bbfa601ab1b0c07de433ea1f0fc5754c68c5082d Mon Sep 17 00:00:00 2001 From: Molkobain Date: Fri, 12 Apr 2024 09:58:49 +0200 Subject: [PATCH 2/4] =?UTF-8?q?N=C2=B07446=20-=20Add=20temporary=20workaro?= =?UTF-8?q?und=20to=20fix=20an=20issue=20due=20to=20DB=20views=20creation.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/BaseTestCase/ItopCustomDatamodelTestCase.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/php-unit-tests/src/BaseTestCase/ItopCustomDatamodelTestCase.php b/tests/php-unit-tests/src/BaseTestCase/ItopCustomDatamodelTestCase.php index da53441af..b7e62717b 100644 --- a/tests/php-unit-tests/src/BaseTestCase/ItopCustomDatamodelTestCase.php +++ b/tests/php-unit-tests/src/BaseTestCase/ItopCustomDatamodelTestCase.php @@ -191,7 +191,8 @@ abstract class ItopCustomDatamodelTestCase extends ItopDataTestCase CMDBSource::CreateDB($oTestConfig->Get('db_name')); MetaModel::Startup($sConfFile, false /* $bModelOnly */, true /* $bAllowCache */, false /* $bTraceSourceFiles */, $sTestEnv); // N°7446 For some reason we need to create the DB schema before starting the MM, then only we can create the tables. - MetaModel::DBCreate(); + // In 2.7, we can't call MetaModel::DBCreate() directly as the views creation will fail + $this->InvokeNonPublicStaticMethod(MetaModel::class, 'DBCreateTables', []); $this->MarkEnvironmentReady(); $this->debug('Preparation of custom environment "'.$sTestEnv.'" done.'); From a6d01739babe8cdfc81121fdc1dfd9116bfd32ef Mon Sep 17 00:00:00 2001 From: Molkobain Date: Fri, 12 Apr 2024 10:45:56 +0200 Subject: [PATCH 3/4] =?UTF-8?q?N=C2=B06964=20-=20Fix=20unit=20test=20data?= =?UTF-8?q?=20not=20compliant=20with=20tested=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Delta/application-extension-usages-in-snippets.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml b/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml index 3a80b4c47..beaadac93 100644 --- a/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml +++ b/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml @@ -359,7 +359,7 @@ class ExampleFor_iKPILoggerExtension implements \iKPILoggerExtension Date: Fri, 12 Apr 2024 10:50:59 +0200 Subject: [PATCH 4/4] =?UTF-8?q?N=C2=B06964=20-=20Improve=20PHPDoc=20and=20?= =?UTF-8?q?method=20name=20to=20explicit=20that=20paths=20are=20relative?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/applicationextension.inc.php | 7 ++----- setup/backup.class.inc.php | 2 +- .../Delta/application-extension-usages-in-snippets.xml | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/application/applicationextension.inc.php b/application/applicationextension.inc.php index 915eda70d..e5ef39465 100644 --- a/application/applicationextension.inc.php +++ b/application/applicationextension.inc.php @@ -2292,11 +2292,8 @@ interface iKPILoggerExtension interface iBackupExtraFilesExtension { /** - * Returns an array of files and directories to be included in the backup - * * @api - * - * @return string[] + * @return string[] Array of relative paths (from app root) for files and directories to be included in the backup */ - public function GetExtraFiles(): array; + public function GetExtraFilesRelPaths(): array; } diff --git a/setup/backup.class.inc.php b/setup/backup.class.inc.php index 43c0aeeb8..127f953ea 100644 --- a/setup/backup.class.inc.php +++ b/setup/backup.class.inc.php @@ -276,7 +276,7 @@ class DBBackup { /** @var iBackupExtraFilesExtension $oExtensionInstance */ $oExtensionInstance = new $sExtensionClass(); - $aExtraFiles = array_merge($aExtraFiles, $oExtensionInstance->GetExtraFiles()); + $aExtraFiles = array_merge($aExtraFiles, $oExtensionInstance->GetExtraFilesRelPaths()); } foreach($aExtraFiles as $sExtraFileOrDir) diff --git a/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml b/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml index beaadac93..631d3d45c 100644 --- a/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml +++ b/tests/php-unit-tests/unitary-tests/application/applicationextension/Delta/application-extension-usages-in-snippets.xml @@ -359,7 +359,7 @@ class ExampleFor_iKPILoggerExtension implements \iKPILoggerExtension