setName('migrations:generate-metadata') ->setHidden(true) ->setDescription('Generate metadata from DB migrations - internal and should not be used'); parent::configure(); } public function execute(InputInterface $input, OutputInterface $output): int { $output->writeln( json_encode( [ 'migrations' => $this->extractMigrationMetadata() ], JSON_PRETTY_PRINT ) ); return 0; } private function extractMigrationMetadata(): array { return [ 'core' => $this->extractMigrationMetadataFromCore(), 'apps' => $this->extractMigrationMetadataFromApps() ]; } private function extractMigrationMetadataFromCore(): array { return $this->extractMigrationAttributes('core'); } /** * get all apps and extract attributes * * @return array * @throws \Exception */ private function extractMigrationMetadataFromApps(): array { $allApps = \OC_App::getAllApps(); $metadata = []; foreach ($allApps as $appId) { // We need to load app before being able to extract Migrations // If app was not enabled before, we will disable it afterward. $alreadyLoaded = $this->appManager->isInstalled($appId); if (!$alreadyLoaded) { $this->appManager->loadApp($appId); } $metadata[$appId] = $this->extractMigrationAttributes($appId); if (!$alreadyLoaded) { $this->appManager->disableApp($appId); } } return $metadata; } /** * We get all migrations from an app, and for each migration we extract attributes * * @param string $appId * * @return array * @throws \Exception */ private function extractMigrationAttributes(string $appId): array { $ms = new MigrationService($appId, $this->connection); $metadata = []; foreach($ms->getAvailableVersions() as $version) { $metadata[$version] = []; $class = new ReflectionClass($ms->createInstance($version)); $attributes = $class->getAttributes(); foreach ($attributes as $attribute) { $metadata[$version][] = $attribute->newInstance(); } } return $metadata; } }