/** * Extracts the compressed file and copies the files from the root directory * only if the compressed file contains a single directory. * @param string $file Compressed file. * @param string $path Destination path. * @param Format\FormatInterface $format Format. * * @throws Exception\IO\Input\FileEmptyException * @throws Exception\IO\Input\FileFormatNotSupportedException * @throws Exception\IO\Input\FileNotFoundException * @throws Exception\IO\Input\FileNotReadableException * @throws Exception\IO\Output\NotSingleDirectoryException * @throws Exception\IO\Output\TargetDirectoryNotWritableException * * @return bool */ public function extractWithoutRootDirectory($file, $path, FormatInterface $format = null) { $this->initializeIfNotInitialized(); // extract to a temporary place $tempDirectory = sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid(time()) . DIRECTORY_SEPARATOR; $this->extract($file, $tempDirectory, $format); // move directory $iterator = new \FilesystemIterator($tempDirectory, \FilesystemIterator::SKIP_DOTS); $hasSingleRootDirectory = true; $singleRootDirectoryName = null; $numberDirectories = 0; while ($iterator->valid() && $hasSingleRootDirectory) { $uncompressedResource = $iterator->current(); if (false === $uncompressedResource->isDir()) { $hasSingleRootDirectory = false; } $singleRootDirectoryName = $uncompressedResource->getRealPath(); $numberDirectories++; if ($numberDirectories > 1) { $hasSingleRootDirectory = false; } $iterator->next(); } if (false === $hasSingleRootDirectory) { // it is not a compressed file with a single directory $this->filesystem->remove($tempDirectory); throw new Exception\IO\Output\NotSingleDirectoryException($file); } $this->filesystem->remove($path); $this->filesystem->rename($singleRootDirectoryName, $path); return true; }
/** * {@inheritdoc} */ public function extract($source, $target, FormatChainInterface $chainFormat) { $chainFormats = $chainFormat->getChainFormats(); foreach ($chainFormats as $format) { if (false === $this->supportChecker->isFormatSupported($format)) { throw new FileFormatNotSupportedException($source, $format); } } $success = true; $lastFile = $source; $tempDirectories = []; for ($i = 0, $formatsCount = count($chainFormats); $i < $formatsCount && true === $success; $i++) { if ($i + 1 === $formatsCount) { // last $success = $this->extractFormat($lastFile, $target, $chainFormats[$i]); } else { $tempDirectory = $target . DIRECTORY_SEPARATOR . 'step_' . $i; $tempDirectories[] = $tempDirectory; $success = $this->extractFormat($lastFile, $tempDirectory, $chainFormats[$i]); // look for the uncompressed file $iterator = new \FilesystemIterator($tempDirectory, \FilesystemIterator::SKIP_DOTS); $extractedFile = null; while ($iterator->valid()) { $extractedFile = $iterator->current(); $iterator->next(); } if (null === $extractedFile) { throw new FileCorruptedException($lastFile); } $lastFile = $extractedFile->getRealPath(); } } // clean temp directories foreach ($tempDirectories as $directory) { $this->filesystem->remove($directory); } return $success; }