From 93e1f6ae03ca99b7a4b7bfeaaee75997192dcbbc Mon Sep 17 00:00:00 2001 From: Lars Kaltefleiter Date: Fri, 12 Apr 2024 09:17:17 +0200 Subject: [PATCH] =?UTF-8?q?N=C2=B06964=20-=20Add=20API=20to=20allow=20modu?= =?UTF-8?q?les=20to=20register=20files=20to=20include=20in=20the=20backup?= =?UTF-8?q?=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 +