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 +