fileSystem = $fileSystem; $this->importPath = $importPath; } /** * {@inheritdoc} */ public static function getSubscribedEvents() { return [ ReinstallEvents::POST_DUMP => 'onDumpPost', ]; } /** * Callback for POST_DUMP event. * * @param \Drupal\reinstall\DumperEvent $event * The post-dump event. */ public function onDumpPost(DumperEvent $event) { if ($event->storage->getEntityTypeId() !== 'file') { return; } $this->dumpFiles($event->bundleName, $event->entities); } /** * Dump the actual files for a file entity bundle. * * @param string $bundleName * The bundle name. * @param array $files * The file URLs. */ public function dumpFiles(string $bundleName, array $files) { $importPath = $this->importPath; $dir = "$importPath/$bundleName"; $usedNamespaces = array_keys(array_reduce($files, [__CLASS__, 'namespacesReducer'], [])); $lists = []; foreach ($usedNamespaces as $ns) { // XXX Consider using \0 to support xargs: file names MAY contain spaces. $path = "$dir/$ns.list.txt"; $nsDir = "$dir/$ns"; if (!is_dir($nsDir)) { echo "Creating $nsDir\n"; mkdir($nsDir, 0777, TRUE); } // fopen() is in text mode by default. $lists[$ns] = [ 'dir' => $nsDir, 'handle' => fopen($path, 'w'), ]; } /** @var \Drupal\file\Entity\File $file */ foreach ($files as $file) { $uri = $file->getFileUri(); $target = file_uri_target($uri); $ns = $this->fileSystem->uriScheme($uri); fwrite($lists[$ns]['handle'], $target . "\n"); $dest = $lists[$ns]['dir'] . '/' . $target; $dir = dirname($dest); if (!is_dir($dir)) { mkdir($dir, 0777, TRUE); } file_unmanaged_copy($uri, $dest, FILE_EXISTS_REPLACE); } foreach ($lists as $list) { fclose($list['handle']); } } /** * An array_reduce() callback to collect namespaces from file entities. * * @param string[] $accu * The namespaces accumulator. * @param \Drupal\file\Entity\File $fileItem * A file description. * * @return string[] * An array of namespaces used on the site. * * @see \Drupal\reinstall\Dumper::dumpFiles() */ protected static function namespacesReducer(array $accu, File $fileItem) { $uri = $fileItem->getFileUri(); // Plain filenames without a namespace. Should not happen, but... if (FALSE === ($len = Unicode::strpos($uri, '://'))) { return $accu; }; $namespace = Unicode::substr($uri, 0, $len); $accu[$namespace] = TRUE; return $accu; } }