diff --git a/lib/tool/console/application.php b/lib/tool/console/application.php index 27e6884..da68e56 100644 --- a/lib/tool/console/application.php +++ b/lib/tool/console/application.php @@ -4,6 +4,7 @@ use Bitrix\Main\Localization\Loc; use Intervolga\Migrato\Tool\Console\Command\AutofixCommand; use Intervolga\Migrato\Tool\Console\Command\CheckExecCommand; +use Intervolga\Migrato\Tool\Console\Command\CleanDeletedXml; use Intervolga\Migrato\Tool\Console\Command\ClearCacheCommand; use Intervolga\Migrato\Tool\Console\Command\ExportCommand; use Intervolga\Migrato\Tool\Console\Command\ExportDataCommand; @@ -61,7 +62,8 @@ public function __construct() new LogCommand(), new CheckExecCommand(), new ReIndexFacetCommand(), - new Backup() + new Backup(), + new CleanDeletedXml() )); } diff --git a/lib/tool/console/command/cleandeletedxml.php b/lib/tool/console/command/cleandeletedxml.php new file mode 100644 index 0000000..270e34a --- /dev/null +++ b/lib/tool/console/command/cleandeletedxml.php @@ -0,0 +1,118 @@ +setName('cleandeletedxml'); + $this->setDescription('Удаление файлов, помеченных как удаленные'); + $this->addOption( + 'all', + null, + InputOption::VALUE_NONE, + 'Удалить все файлы, помеченные как удаленные' + ); + $this->addOption( + 'backup', + null, + InputOption::VALUE_NONE, + 'Создать резервную копию папки migrato перед удалением файлов' + ); + } + + public function executeInner() + { + if ($this->input->getOption('backup')) + { + $this->copyData(); + } + $result = $this->input->getOption('all') ? $this->cleanAll() : $this->clean(); + $count = count(array_merge(...array_values($result))); + if ($count) + { + $this->logger->add("Краткая сводка по удаленным файлам:", $this->logger::LEVEL_SHORT); + foreach ($result as $moduleId => $files) + { + if (count($files)) + { + $this->logger->add("Модуль {$moduleId}: удалено файлов " . count($files) . " шт.", $this->logger::LEVEL_SHORT, $this->logger::TYPE_INFO); + } + } + } + else + { + $this->logger->add("Ничего не удалено", $this->logger::LEVEL_NORMAL, $this->logger::TYPE_OK); + } + + } + + private function clean(): array + { + $modules = Config::getInstance()->getModules(); + $result = []; + foreach ($modules as $module) + { + if (isset($result[$module])) + { + continue; + } + $result[$module] = DataFileViewXml::getFilesMarkedAsDeletedRecursively(INTERVOLGA_MIGRATO_DIRECTORY . $module . '/'); + foreach ($result[$module] as $file) + { + $this->deleteFile($module, $file); + } + } + + return $result; + } + + private function cleanAll(): array + { + $files = DataFileViewXml::getFilesMarkedAsDeletedRecursively(INTERVOLGA_MIGRATO_DIRECTORY); + $result = []; + foreach ($files as $file) + { + $module = preg_match('/^' . preg_quote(INTERVOLGA_MIGRATO_DIRECTORY, '/') . '([^\/]+)\//', $file->getPath(), $matches) ? $matches[1] : ''; + if (!isset($result[$module])) + { + $result[$module] = []; + } + $result[$module][] = $file; + $this->deleteFile($module, $file); + } + + return $result; + } + + private function deleteFile(string $module, File $file): void + { + $deleteResult = $file->delete(); + if ($deleteResult) + { + $this->logger->add("Модуль {$module}: " . $file->getName(), $this->logger::LEVEL_DETAIL, $this->logger::TYPE_OK); + } + else + { + $this->logger->add("Модуль {$module}: " . $file->getName(), $this->logger::LEVEL_DETAIL, $this->logger::TYPE_FAIL); + } + } + + protected function copyData() + { + $copyDir = preg_replace('/\/$/', '_backup/', INTERVOLGA_MIGRATO_DIRECTORY); + Directory::deleteDirectory($copyDir); + + CopyDirFiles(INTERVOLGA_MIGRATO_DIRECTORY, $copyDir, false, true); + } +} \ No newline at end of file diff --git a/lib/tool/console/command/exportcommand.php b/lib/tool/console/command/exportcommand.php index 2b43688..522b4d1 100644 --- a/lib/tool/console/command/exportcommand.php +++ b/lib/tool/console/command/exportcommand.php @@ -1,6 +1,7 @@ setName('export'); $this->setDescription(Loc::getMessage('INTERVOLGA_MIGRATO.EXPORT_DESCRIPTION')); + $this->addOption( + 'clean-deleted', + null, + InputOption::VALUE_NONE, + 'Удалять файлы, а не проставлять deleted="true"' + ); } public function executeInner() { $this->runSubcommand('exportdata'); $this->runSubcommand('exportoptions'); + if ($this->input->getOption('clean-deleted')) + { + $this->runSubcommand('cleandeletedxml'); + } } } \ No newline at end of file diff --git a/lib/tool/datafileviewxml.php b/lib/tool/datafileviewxml.php index 97f825e..e32e704 100644 --- a/lib/tool/datafileviewxml.php +++ b/lib/tool/datafileviewxml.php @@ -37,6 +37,29 @@ protected static function markDataFileDeleted(File $file) $file->putContents($content); } + /** + * @param string $path + * + * @return \Bitrix\Main\IO\File[] + */ + public static function getFilesMarkedAsDeletedRecursively(string $path): array + { + $files = static::getFilesRecursive($path); + $filesDeleted = array(); + foreach ($files as $file) + { + $content = $file->getContents(); + $xmlParser = new \CDataXML(); + $xmlParser->LoadString($content); + $xmlArray = $xmlParser->getArray(); + if ($xmlArray["data"]["@"]["deleted"]) + { + $filesDeleted[] = $file; + } + } + return $filesDeleted; + } + /** * @param \Intervolga\Migrato\Data\Record $record * @param string $path @@ -183,6 +206,38 @@ protected static function getFiles($path) return $result; } + /** + * @param string $path + * + * @return \Bitrix\Main\IO\File[] + */ + protected static function getFilesRecursive($path): array + { + $result = array(); + $directory = new Directory($path); + if ($directory->isExists()) + { + foreach ($directory->getChildren() as $fileSystemEntry) + { + if ($fileSystemEntry instanceof File) + { + $name = strtolower($fileSystemEntry->getName()); + $extension = strtolower($fileSystemEntry->getExtension()); + if ((strpos($name, static::FILE_PREFIX) === 0) && $extension == static::FILE_EXT) + { + $result[] = $fileSystemEntry; + } + } + if ($fileSystemEntry instanceof Directory) + { + $result = array_merge($result, static::getFilesRecursive($fileSystemEntry->getPath())); + } + } + } + + return $result; + } + /** * @param \Bitrix\Main\IO\File $file *