From d35075769edca8e3ecb1a7674fd479a33fb730b3 Mon Sep 17 00:00:00 2001 From: Edvinas Aleksejonokas Date: Tue, 23 May 2017 12:56:18 +0300 Subject: [PATCH 01/13] ESDEV-4443 Add CopyGlobFilteredFileManager --- composer.json | 4 +- .../CopyGlobFilteredFileManager.php | 163 ++++++++ .../GlobListMatcher/GlobListMatcher.php | 92 +++++ .../GlobMatcher/GlobMatcher.php | 48 +++ .../Integration/AbstractGlobMatcher.php | 76 ++++ .../Integration/WebmozartGlobMatcher.php | 46 +++ .../Iteration/BlacklistFilterIterator.php | 92 +++++ .../CopyGlobFilteredFileManagerTest.php | 389 ++++++++++++++++++ 8 files changed, 909 insertions(+), 1 deletion(-) create mode 100644 src/Utilities/CopyFileManager/CopyGlobFilteredFileManager.php create mode 100644 src/Utilities/CopyFileManager/GlobMatcher/GlobListMatcher/GlobListMatcher.php create mode 100644 src/Utilities/CopyFileManager/GlobMatcher/GlobMatcher.php create mode 100644 src/Utilities/CopyFileManager/GlobMatcher/Integration/AbstractGlobMatcher.php create mode 100644 src/Utilities/CopyFileManager/GlobMatcher/Integration/WebmozartGlobMatcher.php create mode 100644 src/Utilities/CopyFileManager/GlobMatcher/Iteration/BlacklistFilterIterator.php create mode 100644 tests/Unit/Utilities/CopyFileManager/CopyGlobFilteredFileManagerTest.php diff --git a/composer.json b/composer.json index 20e60c0..b0c72c1 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,9 @@ "prefer-stable": true, "require": { "composer-plugin-api": "^1.0", - "symfony/filesystem": "^3.0" + "symfony/filesystem": "^3.0", + "webmozart/glob": "^4.1", + "webmozart/path-util": "^2.3" }, "require-dev": { "phpunit/phpunit": "^4.8", diff --git a/src/Utilities/CopyFileManager/CopyGlobFilteredFileManager.php b/src/Utilities/CopyFileManager/CopyGlobFilteredFileManager.php new file mode 100644 index 0000000..05bd95c --- /dev/null +++ b/src/Utilities/CopyFileManager/CopyGlobFilteredFileManager.php @@ -0,0 +1,163 @@ +. + * + * @link http://www.oxid-esales.com + * @copyright (C) OXID eSales AG 2003-2017 + * @version OXID eShop Composer plugin + */ + +namespace OxidEsales\ComposerPlugin\Utilities\CopyFileManager; + +use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher\GlobMatcher; +use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher\Iteration\BlacklistFilterIterator; +use Symfony\Component\Filesystem\Filesystem; +use Webmozart\PathUtil\Path; + +/** + * Class CopyGlobFilteredFileManager. + * + * Copies files/directories from source to destination which matches the criteria described in a glob filter. + */ +class CopyGlobFilteredFileManager +{ + /** + * Copy files/directories from source to destination. + * + * @param string $sourcePath Absolute path to file or directory. + * @param string $destinationPath Absolute path to file or directory. + * @param array|null $globExpressionList List of glob expressions, e.g. ["*.txt", "*.pdf"]. + * + * @throws \InvalidArgumentException If given $sourcePath is not a string. + * @throws \InvalidArgumentException If given $destinationPath is not a string. + * + * @return null + */ + public static function copy($sourcePath, $destinationPath, $globExpressionList = null) + { + if (!is_string($sourcePath)) { + $message = "Given value \"$sourcePath\" is not a valid source path entry. ". + "Valid entry must be an absolute path to an existing file or directory."; + + throw new \InvalidArgumentException($message); + } + + if (!is_string($destinationPath)) { + $message = "Given value \"$destinationPath\" is not a valid destination path entry. ". + "Valid entry must be an absolute path to an existing directory."; + + throw new \InvalidArgumentException($message); + } + + if (!file_exists($sourcePath)) { + return; + } + + if (is_dir($sourcePath)) { + self::copyDirectory($sourcePath, $destinationPath, $globExpressionList); + } else { + self::copyFile($sourcePath, $destinationPath, $globExpressionList); + } + } + + /** + * Returns relative path from an absolute path to a file. + * + * @param string $sourcePath Absolute path to a file. + * + * @return string + */ + private static function getRelativePathForSingleFile($sourcePath) + { + return Path::makeRelative($sourcePath, Path::getDirectory($sourcePath)); + } + + /** + * Return an iterator which iterates through a given directory tree in a one-dimensional fashion. + * + * Consider the following file/directory structure as an example: + * + * * directory_a + * * file_a_a + * * directory_b + * * file_b_a + * * file_b_b + * * file_c + * + * RecursiveDirectoryIterator would iterate through: + * * directory_a [iterator] + * * directory_b [iterator] + * * file_c [SplFileInfo] + * + * In contrast current method would iterate through: + * * directory_a [SplFileInfo] + * * directory_a/file_a_a [SplFileInfo] + * * directory_b [SplFileInfo] + * * directory_b/file_b_a [SplFileInfo] + * * directory_b/file_b_b [SplFileInfo] + * * file_c [SplFileInfo] + * + * @param string $sourcePath Absolute path to directory. + * + * @return \Iterator + */ + private static function getFlatFileListIterator($sourcePath) + { + $recursiveFileIterator = new \RecursiveDirectoryIterator($sourcePath, \FilesystemIterator::SKIP_DOTS); + $flatFileListIterator = new \RecursiveIteratorIterator($recursiveFileIterator); + + return $flatFileListIterator; + } + + /** + * Copy whole directory using given glob filters. + * + * @param string $sourcePath Absolute path to directory. + * @param string $destinationPath Absolute path to directory. + * @param array $globExpressionList List of glob expressions, e.g. ["*.txt", "*.pdf"]. + */ + private static function copyDirectory($sourcePath, $destinationPath, $globExpressionList) + { + $filesystem = new Filesystem(); + + $flatFileListIterator = self::getFlatFileListIterator($sourcePath); + $filteredFileListIterator = new BlacklistFilterIterator( + $flatFileListIterator, + $sourcePath, + $globExpressionList + ); + + $filesystem->mirror($sourcePath, $destinationPath, $filteredFileListIterator, ["override" => true]); + } + + /** + * Copy file using given glob filters. + * + * @param string $sourcePathOfFile Absolute path to file. + * @param string $destinationPath Absolute path to directory. + * @param array $globExpressionList List of glob expressions, e.g. ["*.txt", "*.pdf"]. + */ + private static function copyFile($sourcePathOfFile, $destinationPath, $globExpressionList) + { + $filesystem = new Filesystem(); + + $relativeSourcePath = self::getRelativePathForSingleFile($sourcePathOfFile); + + if (!GlobMatcher::matchAny($relativeSourcePath, $globExpressionList)) { + $filesystem->copy($sourcePathOfFile, $destinationPath, ["override" => true]); + } + } +} diff --git a/src/Utilities/CopyFileManager/GlobMatcher/GlobListMatcher/GlobListMatcher.php b/src/Utilities/CopyFileManager/GlobMatcher/GlobListMatcher/GlobListMatcher.php new file mode 100644 index 0000000..ddb83b9 --- /dev/null +++ b/src/Utilities/CopyFileManager/GlobMatcher/GlobListMatcher/GlobListMatcher.php @@ -0,0 +1,92 @@ +. + * + * @link http://www.oxid-esales.com + * @copyright (C) OXID eSales AG 2003-2017 + * @version OXID eShop Composer plugin + */ + +namespace OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher\GlobListMatcher; + +use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher\Integration\AbstractGlobMatcher; + +/** + * Class GlobListMatcher. + * + * Enables glob matching for a relative path against a list of glob expressions. + */ +class GlobListMatcher +{ + /** @var AbstractGlobMatcher */ + protected $globMatcher; + + /** + * GlobListMatcher constructor. + * + * @param AbstractGlobMatcher $globMatcher Instance of a variant from AbstractGlobMatcher. + */ + public function __construct($globMatcher) + { + $this->globMatcher = $globMatcher; + } + + /** + * Returns true if given relative path matches against at least one glob expression from provided list. + * + * @param string $relativePath + * @param array $globExpressionList List of glob expressions, e.g. ["*.txt", "*.pdf"]. + * + * @throws \InvalidArgumentException If $globExpressionList is not a \Traversable instance. + * + * @return bool + */ + public function matchAny($relativePath, $globExpressionList) + { + if (!is_array($globExpressionList) && (!$globExpressionList instanceof \Traversable) + && (!is_null($globExpressionList))) { + $message = "Given value \"$globExpressionList\" is not a valid glob expression list. ". + "Valid entry must be a list of glob expressions e.g. [\"*.txt\", \"*.pdf\"]."; + + throw new \InvalidArgumentException($message); + } + + if (count($globExpressionList) > 0) { + return $this->isMatchInList($relativePath, $globExpressionList); + } + + return false; + } + + /** + * Returns true if the supplied globMatcher indicates a match for at least one item in given glob expression list. + * + * @param string $relativePath + * @param array $globExpressionList List of glob expressions, e.g. ["*.txt", "*.pdf"]. + * + * @return bool + */ + private function isMatchInList($relativePath, $globExpressionList) + { + foreach ($globExpressionList as $globExpression) { + if ($this->globMatcher->match($relativePath, $globExpression)) { + return true; + } + } + + return false; + } +} diff --git a/src/Utilities/CopyFileManager/GlobMatcher/GlobMatcher.php b/src/Utilities/CopyFileManager/GlobMatcher/GlobMatcher.php new file mode 100644 index 0000000..6181e6b --- /dev/null +++ b/src/Utilities/CopyFileManager/GlobMatcher/GlobMatcher.php @@ -0,0 +1,48 @@ +. + * + * @link http://www.oxid-esales.com + * @copyright (C) OXID eSales AG 2003-2017 + * @version OXID eShop Composer plugin + */ + +namespace OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher; + +use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher\Integration\WebmozartGlobMatcher; +use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher\GlobListMatcher\GlobListMatcher; + +/** + * Class GlobMatcher. + * + * Expose multiple glob matching interface for given relative path. + */ +class GlobMatcher +{ + /** + * @param string $relativePath Relative path to match against. + * @param array $globExpressionList List of glob expressions, e.g. ["*.txt", "*.pdf"]. + * + * @return bool True if given path matches any of given glob expression. + */ + public static function matchAny($relativePath, $globExpressionList) + { + $globMatcher = new WebmozartGlobMatcher(); + $globListMatcher = new GlobListMatcher($globMatcher); + + return $globListMatcher->matchAny($relativePath, $globExpressionList); + } +} diff --git a/src/Utilities/CopyFileManager/GlobMatcher/Integration/AbstractGlobMatcher.php b/src/Utilities/CopyFileManager/GlobMatcher/Integration/AbstractGlobMatcher.php new file mode 100644 index 0000000..8ec8c58 --- /dev/null +++ b/src/Utilities/CopyFileManager/GlobMatcher/Integration/AbstractGlobMatcher.php @@ -0,0 +1,76 @@ +. + * + * @link http://www.oxid-esales.com + * @copyright (C) OXID eSales AG 2003-2017 + * @version OXID eShop Composer plugin + */ + +namespace OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher\Integration; + +use InvalidArgumentException; +use Webmozart\PathUtil\Path; + +/** + * Class AbstractGlobMatcher. + * + * Abstract which defines API for matching a path against a glob expression. + */ +abstract class AbstractGlobMatcher +{ + /** + * Returns true if given path matches a glob expression. + * + * @param string $relativePath + * @param string $globExpression Glob filter expressions, e.g. "*.txt" or "*.pdf". + * + * @throws \InvalidArgumentException If given $globExpression is not a valid string. + * @throws \InvalidArgumentException If given $globExpression is an absolute path. + * + * @return bool + */ + public function match($relativePath, $globExpression) + { + if (!is_string($globExpression) && !is_null($globExpression)) { + $message = "Given value \"$globExpression\" is not a valid glob expression. ". + "Valid expression must be a string e.g. \"*.txt\"."; + + throw new InvalidArgumentException($message); + } + + if (Path::isAbsolute((string)$globExpression)) { + $message = "Given value \"$globExpression\" is an absolute path. ". + "Glob expression can only be accepted if it's a relative path."; + + throw new InvalidArgumentException($message); + } + + if (is_null($globExpression)) { + return true; + } + + return static::isGlobMatch($relativePath, $globExpression); + } + + /** + * Implementation details for matching a given path against glob expression. + * + * @param string $relativePath + * @param string $globExpression Glob filter expressions, e.g. "*.txt" or "*.pdf". + */ + abstract protected function isGlobMatch($relativePath, $globExpression); +} diff --git a/src/Utilities/CopyFileManager/GlobMatcher/Integration/WebmozartGlobMatcher.php b/src/Utilities/CopyFileManager/GlobMatcher/Integration/WebmozartGlobMatcher.php new file mode 100644 index 0000000..99e422f --- /dev/null +++ b/src/Utilities/CopyFileManager/GlobMatcher/Integration/WebmozartGlobMatcher.php @@ -0,0 +1,46 @@ +. + * + * @link http://www.oxid-esales.com + * @copyright (C) OXID eSales AG 2003-2017 + * @version OXID eShop Composer plugin + */ + +namespace OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher\Integration; + +use Webmozart\Glob\Glob; + +/** + * Class WebmozartGlobMatcher. + * + * An integration of "webmozart/glob" package to match AbstractGlobMatcher. + */ +class WebmozartGlobMatcher extends AbstractGlobMatcher +{ + /** + * Check if given path matches provided glob expression using "webmozart/glob" package. + * + * @param string $relativePath + * @param string $globExpression Glob filter expressions, e.g. "*.txt" or "*.pdf". + * + * @return bool True in case the path matches the given glob expression. + */ + protected function isGlobMatch($relativePath, $globExpression) + { + return Glob::match("/$relativePath", "/$globExpression"); + } +} diff --git a/src/Utilities/CopyFileManager/GlobMatcher/Iteration/BlacklistFilterIterator.php b/src/Utilities/CopyFileManager/GlobMatcher/Iteration/BlacklistFilterIterator.php new file mode 100644 index 0000000..f38e030 --- /dev/null +++ b/src/Utilities/CopyFileManager/GlobMatcher/Iteration/BlacklistFilterIterator.php @@ -0,0 +1,92 @@ +. + * + * @link http://www.oxid-esales.com + * @copyright (C) OXID eSales AG 2003-2017 + * @version OXID eShop Composer plugin + */ + +namespace OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher\Iteration; + +use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher\GlobMatcher; +use Webmozart\PathUtil\Path; + +/** + * Class BlacklistFilterIterator. + * + * An iterator which iterates through given iterator of files/directories and filters out the items described in list of + * glob filter definitions (black list filtering). + */ +class BlacklistFilterIterator extends \FilterIterator +{ + /** @var array List of glob expressions, e.g. ["*.txt", "*.pdf"]. */ + private $globExpressionList; + + /** @var string Absolute root path from the start of iteration. */ + private $rootPath; + + /** + * BlacklistFilterIterator constructor. + * + * @param \Iterator $iterator An iterator which iterates through files/directories. + * @param string $rootPath Absolute root path from the start of iteration. + * @param array $globExpressionList List of glob expressions, e.g. ["*.txt", "*.pdf"]. + */ + public function __construct(\Iterator $iterator, $rootPath, $globExpressionList) + { + parent::__construct($iterator); + + $this->globExpressionList = $globExpressionList; + $this->rootPath = $rootPath; + } + + /** + * {@inheritdoc} + * + * @return bool + */ + public function accept() + { + $path = $this->convertFromSplFileInfoToString(parent::current()); + + return !GlobMatcher::matchAny($this->getRelativePath($path), $this->globExpressionList); + } + + /** + * Get relative path from given item of iteration compared to provided root path. + * + * @param string $absolutePath Absolute path from iteration. + * + * @return string + */ + private function getRelativePath($absolutePath) + { + return Path::makeRelative($absolutePath, $this->rootPath); + } + + /** + * Returns string to absolute path from an entry of SplFileInfo. + * + * @param \SplFileInfo $item Item from iteration. + * + * @return string + */ + private function convertFromSplFileInfoToString(\SplFileInfo $item) + { + return (string)$item; + } +} diff --git a/tests/Unit/Utilities/CopyFileManager/CopyGlobFilteredFileManagerTest.php b/tests/Unit/Utilities/CopyFileManager/CopyGlobFilteredFileManagerTest.php new file mode 100644 index 0000000..28c29d0 --- /dev/null +++ b/tests/Unit/Utilities/CopyFileManager/CopyGlobFilteredFileManagerTest.php @@ -0,0 +1,389 @@ +. + * + * @link http://www.oxid-esales.com + * @copyright (C) OXID eSales AG 2003-2016 + * @version OXID eShop Composer plugin + */ + +namespace OxidEsales\ComposerPlugin\Tests\Unit\Utilities\CopyFileManager; + +use org\bovigo\vfs\vfsStream; +use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\CopyGlobFilteredFileManager; +use Webmozart\PathUtil\Path; + +/** + * Class CopyGlobFilteredFileManagerTest. + * + * @covers \OxidEsales\ComposerPlugin\Utilities\CopyFileManager\CopyGlobFilteredFileManager + * @covers \OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher\GlobMatcher + * @covers \OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher\Iteration\BlacklistFilterIterator + * @covers \OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher\Integration\AbstractGlobMatcher + * @covers \OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher\Integration\WebmozartGlobMatcher + * @covers \OxidEsales\ComposerPlugin\Utilities\CopyFileManager\GlobMatcher\GlobListMatcher\GlobListMatcher + */ +class CopyGlobFilteredFileManagerTest extends \PHPUnit_Framework_TestCase +{ + /** @var array */ + private $filter; + + public function testBasicFileCopyOperation() + { + $inputFiles = [ + "module.php" => "PHP_1", + ]; + + $this->prepareVirtualFileSystem($inputFiles, []); + + $this->simulateCopyWithFilter('module.php', 'module.php'); + + $this->assertFileCopyIsIdentical(['module.php']); + } + + public function testNoExceptionThrownWhenSourceFileDoesNotExist() + { + $this->prepareVirtualFileSystem([], []); + $this->simulateCopyWithFilter('module.php', 'module.php'); + + $this->assertFilesNotExistInDestination(['module.php']); + } + + public function testThrowsExceptionWhenSourceValueIsInvalid() + { + $inputFiles = [ + "module.php" => "PHP_1", + ]; + + $this->prepareVirtualFileSystem($inputFiles, []); + + $this->setExpectedException( + \InvalidArgumentException::class, + "Given value \"1\" is not a valid source path entry. ". + "Valid entry must be an absolute path to an existing file or directory." + ); + + $destinationPath = $this->getSourcePath('module.php'); + CopyGlobFilteredFileManager::copy(1, $destinationPath); + } + + public function testThrowsExceptionWhenDestinationValueIsInvalid() + { + $inputFiles = [ + "module.php" => "PHP_1", + ]; + + $this->prepareVirtualFileSystem($inputFiles, []); + + $this->setExpectedException( + \InvalidArgumentException::class, + "Given value \"1\" is not a valid destination path entry. ". + "Valid entry must be an absolute path to an existing directory." + ); + + $sourcePath = $this->getSourcePath('module.php'); + CopyGlobFilteredFileManager::copy($sourcePath, 1); + } + + public function testThrowsExceptionWhenFilterValueIsInvalid() + { + $inputFiles = [ + "module.php" => "PHP_1", + ]; + + $this->prepareVirtualFileSystem($inputFiles, []); + + $this->setExpectedException( + \InvalidArgumentException::class, + "Given value \"1\" is not a valid glob expression list. ". + "Valid entry must be a list of glob expressions e.g. [\"*.txt\", \"*.pdf\"]." + ); + + $this->setFilter(1); + $this->simulateCopyWithFilter('module.php', 'module.php'); + } + + public function testThrowsExceptionWhenFilterItemValueIsInvalid() + { + $inputFiles = [ + "module.php" => "PHP_1", + ]; + + $this->prepareVirtualFileSystem($inputFiles, []); + + $this->setExpectedException( + \InvalidArgumentException::class, + "Given value \"1\" is not a valid glob expression. ". + "Valid expression must be a string e.g. \"*.txt\"." + ); + + $this->setFilter([1]); + $this->simulateCopyWithFilter('module.php', 'module.php'); + } + + public function testThrowsExceptionWhenFilterItemValueIsAbsolutePath() + { + $inputFiles = [ + "module.php" => "PHP_1", + ]; + + $this->prepareVirtualFileSystem($inputFiles, []); + + $this->setExpectedException( + \InvalidArgumentException::class, + "Given value \"/some/absolute/path/*.*\" is an absolute path. ". + "Glob expression can only be accepted if it's a relative path." + ); + + $this->setFilter(["/some/absolute/path/*.*"]); + $this->simulateCopyWithFilter('module.php', 'module.php'); + } + + public function testSingleFileCopyFilteringOperation() + { + $inputFiles = [ + "module.txt" => "TXT_1", + ]; + + $this->prepareVirtualFileSystem($inputFiles, []); + + $this->setFilter(["*.txt"]); + $this->simulateCopyWithFilter('module.txt', 'module.txt'); + + $this->assertFilesExistInSource(['module.txt']); + $this->assertFilesNotExistInDestination(['modules.txt']); + } + + public function testSingleFileCopyFilteringOperationWhenNoFilterIsDefined() + { + $inputFiles = [ + "module.txt" => "TXT_1", + ]; + + $this->prepareVirtualFileSystem($inputFiles, []); + + $this->setFilter(null); + $this->simulateCopyWithFilter('module.txt', 'module.txt'); + + $this->assertFilesExistInSource(['module.txt']); + $this->assertFilesNotExistInDestination(['modules.txt']); + } + + public function testSingleFileCopyFilteringOperationWhenFilterIsEmpty() + { + $inputFiles = [ + "module.txt" => "TXT_1", + ]; + + $this->prepareVirtualFileSystem($inputFiles, []); + + $this->setFilter([]); + $this->simulateCopyWithFilter('module.txt', 'module.txt'); + + $this->assertFilesExistInSource(['module.txt']); + $this->assertFilesNotExistInDestination(['modules.txt']); + } + + public function testSingleFileCopyFilteringOperationWhenFilterContainsEmptyValues() + { + $inputFiles = [ + "module.txt" => "TXT_1", + ]; + + $this->prepareVirtualFileSystem($inputFiles, []); + + $this->setFilter([null]); + $this->simulateCopyWithFilter('module.txt', 'module.txt'); + + $this->assertFilesExistInSource(['module.txt']); + $this->assertFilesNotExistInDestination(['modules.txt']); + } + + public function testBasicDirectoryTreeCopyOperation() + { + $inputFiles = [ + "module.php" => "PHP_1", + "readme.md" => "MD_1", + ]; + + $this->prepareVirtualFileSystem($inputFiles, []); + + $this->simulateCopyWithFilter(); + + $this->assertFileCopyIsIdentical([ + "module.php", + "readme.md", + ]); + } + + public function testCopyOverwritesFilesByDefault() + { + $inputFiles = [ + "module.php" => "PHP_1", + ]; + + $outputFiles = [ + "module.php" => "PHP_2", + ]; + + $this->prepareVirtualFileSystem($inputFiles, $outputFiles); + + $this->simulateCopyWithFilter(); + + $this->assertFileCopyIsIdentical(["module.php"]); + } + + public function testCopyDoesNotThrowAnErrorWhenSourceIsMissing() + { + $this->prepareVirtualFileSystem([], []); + + $this->simulateCopyWithFilter('module.php'); + + $this->assertFilesNotExistInDestination(["module.php"]); + } + + public function testFilteringFileCopyOperation() + { + $inputFiles = [ + "module.php" => "PHP_1", + "readme.md" => "MD_1", + "documentation.txt" => "TXT_1", + "src" => [ + "a.php" => "PHP_2", + "b.php" => "PHP_3", + "c.php" => "PHP_3", + ], + "tests" => [ + "test.php" => "PHP_4", + "unit" => [ + "test.php" => "PHP_5", + ], + "integration" => [ + "test.php" => "PHP_6", + ] + ], + "documentation" => [ + "document_a.pdf" => "PDF_1", + "document_b.pdf" => "PDF_2", + "index.txt" => "TXT_2", + "example.php" => "PHP_7", + ] + ]; + + $this->prepareVirtualFileSystem($inputFiles, []); + + $this->setFilter([ + "**/*.md", + "**/*.txt", + "tests/**/*.*", + "documentation/**/*.pdf", + ]); + $this->simulateCopyWithFilter(); + + $this->assertFileCopyIsIdentical([ + "module.php", + "src/a.php", + "src/b.php", + "src/c.php", + "documentation/example.php", + ]); + + $this->assertFilesNotExistInDestination([ + "readme.md", + "documentation.txt", + "tests/test.php", + "tests/unit/test.php", + "tests/integration/test.php", + "documentation/document_a.pdf", + "documentation/document_b.pdf", + "documentation/index.txt", + ]); + } + + protected function setFilter($filter) + { + $this->filter = $filter; + } + + protected function prepareVirtualFileSystem($inputStructure, $outputStructure) + { + vfsStream::setup('root', 777); + vfsStream::create([ + 'src' => $inputStructure, + 'dest' => $outputStructure, + ]); + } + + protected function simulateCopyWithFilter($source = null, $destination = null) + { + $sourcePath = $this->getSourcePath($source); + $destinationPath = $this->getDestinationPath($destination); + + CopyGlobFilteredFileManager::copy($sourcePath, $destinationPath, $this->filter); + } + + protected function getSourcePath($suffixForSource = null) + { + return Path::join(vfsStream::url('root/src'), !is_null($suffixForSource) ? $suffixForSource : ""); + } + + protected function getDestinationPath($suffixForDestination = null) + { + return Path::join(vfsStream::url('root/dest'), !is_null($suffixForDestination) ? $suffixForDestination : ""); + } + + protected function assertFilesExistInSource($paths) + { + foreach ($paths as $path) { + $this->assertFileExists($this->getSourcePath($path)); + } + } + + protected function assertFilesExistInDestination($paths) + { + foreach ($paths as $path) { + $this->assertFileExists($this->getDestinationPath($path)); + } + } + + protected function assertFilesNotExistInSource($paths) + { + foreach ($paths as $path) { + $this->assertFileNotExists($this->getSourcePath($path)); + } + } + + protected function assertFilesNotExistInDestination($paths) + { + foreach ($paths as $path) { + $this->assertFileNotExists($this->getDestinationPath($path)); + } + } + + protected function assertFileCopyIsIdentical($paths) + { + foreach ($paths as $path) { + $this->assertFileEquals($this->getSourcePath($path), $this->getDestinationPath($path)); + } + } + + protected function assertFileCopyIsDifferent($paths) + { + foreach ($paths as $path) { + $this->assertFileNotEquals($this->getSourcePath($path), $this->getDestinationPath($path)); + } + } +} From d5ed711faf6361b93b9dcc671e9641a7ef46dae3 Mon Sep 17 00:00:00 2001 From: Edvinas Aleksejonokas Date: Tue, 30 May 2017 15:13:37 +0300 Subject: [PATCH 02/13] ESDEV-4443 Integrate CopyGlobFilteredFileManager --- src/Installer/AbstractInstaller.php | 32 ++-- .../DirectoriesSkipIteratorBuilder.php | 29 ---- .../DirectoryRecursiveFilterIterator.php | 68 -------- src/Installer/ModuleInstaller.php | 15 +- src/Installer/PackagesInstaller.php | 3 +- src/Installer/ShopInstaller.php | 36 ++--- src/Installer/ThemeInstaller.php | 45 +++--- .../DirectoryRecursiveFilterIteratorTest.php | 61 ------- .../Installer/ModuleInstallerTest.php | 149 +++++++++++++++++- .../Installer/PackagesInstallerTest.php | 4 - .../Installer/ShopInstallerTest.php | 61 +++++-- .../Installer/ThemeInstallerTest.php | 108 +++++++++++-- 12 files changed, 356 insertions(+), 255 deletions(-) delete mode 100644 src/Installer/DirectoriesSkipIteratorBuilder.php delete mode 100644 src/Installer/DirectoryRecursiveFilterIterator.php delete mode 100644 tests/Integration/Installer/DirectoryRecursiveFilterIteratorTest.php diff --git a/src/Installer/AbstractInstaller.php b/src/Installer/AbstractInstaller.php index 30774f6..11aedfc 100644 --- a/src/Installer/AbstractInstaller.php +++ b/src/Installer/AbstractInstaller.php @@ -24,7 +24,6 @@ use Composer\IO\IOInterface; use Composer\Package\PackageInterface; -use Symfony\Component\Filesystem\Filesystem; /** * Class is responsible for preparing project structure. @@ -46,8 +45,11 @@ abstract class AbstractInstaller /** Used to decide what the shop source directory is. */ const EXTRA_PARAMETER_SOURCE_PATH = 'source-path'; - /** @var Filesystem */ - private $fileSystem; + /** List of glob expressions used to blacklist files being copied. */ + const EXTRA_PARAMETER_FILTER_BLACKLIST = 'blacklist-filter'; + + /** Glob expression to filter all files, might be used to filter whole directory. */ + const BLACKLIST_ALL_FILES = '**/*.*'; /** @var IOInterface */ private $io; @@ -61,14 +63,12 @@ abstract class AbstractInstaller /** * AbstractInstaller constructor. * - * @param Filesystem $fileSystem * @param IOInterface $io * @param string $rootDirectory * @param PackageInterface $package */ - public function __construct(Filesystem $fileSystem, IOInterface $io, $rootDirectory, PackageInterface $package) + public function __construct(IOInterface $io, $rootDirectory, PackageInterface $package) { - $this->fileSystem = $fileSystem; $this->io = $io; $this->rootDirectory = $rootDirectory; $this->package = $package; @@ -98,14 +98,6 @@ public function isInstalled() return false; } - /** - * @return Filesystem - */ - protected function getFileSystem() - { - return $this->fileSystem; - } - /** * @return IOInterface */ @@ -134,7 +126,7 @@ public function getPackage() * Search for parameter with specific key in "extra" composer configuration block * * @param string $extraParameterKey - * @return null|string + * @return array|string|null */ protected function getExtraParameterValueByKey($extraParameterKey) { @@ -149,6 +141,16 @@ protected function getExtraParameterValueByKey($extraParameterKey) return $extraParameterValue; } + /** + * Return the value defined in composer extra parameters for blacklist filtering. + * + * @return array + */ + protected function getBlacklistFilterValue() + { + return $this->getExtraParameterValueByKey(static::EXTRA_PARAMETER_FILTER_BLACKLIST); + } + /** * @param string $messageToAsk * @return bool diff --git a/src/Installer/DirectoriesSkipIteratorBuilder.php b/src/Installer/DirectoriesSkipIteratorBuilder.php deleted file mode 100644 index b9da797..0000000 --- a/src/Installer/DirectoriesSkipIteratorBuilder.php +++ /dev/null @@ -1,29 +0,0 @@ -. - * - * @link http://www.oxid-esales.com - * @copyright (C) OXID eSales AG 2003-2016 - * @version OXID eShop Composer plugin - */ - -namespace OxidEsales\ComposerPlugin\Installer; - -use RecursiveFilterIterator; -use RecursiveIterator; - -class DirectoryRecursiveFilterIterator extends RecursiveFilterIterator -{ - /** @var array */ - private $directoriesToSkip = []; - - /** - * DirectoryRecursiveFilterIterator constructor. - * - * @param RecursiveIterator $iterator - * @param $directoriesToSkip - */ - public function __construct(RecursiveIterator $iterator, $directoriesToSkip) - { - $this->directoriesToSkip = $directoriesToSkip; - parent::__construct($iterator); - } - - /** - * If directory start matches the one from provided array, it will be skipped - * - * @return bool - */ - public function accept() - { - foreach ($this->directoriesToSkip as $skip) { - $skip = preg_quote(rtrim($skip, '/'), '/'); - if (preg_match("/^${skip}(\\/|$)/", $this->current()->getPathName())) { - return false; - } - } - return true; - } - - /** - * @return DirectoryRecursiveFilterIterator - */ - public function getChildren() - { - return new self($this->getInnerIterator()->getChildren(), $this->directoriesToSkip); - } -} diff --git a/src/Installer/ModuleInstaller.php b/src/Installer/ModuleInstaller.php index 9036eeb..b0d326b 100644 --- a/src/Installer/ModuleInstaller.php +++ b/src/Installer/ModuleInstaller.php @@ -22,6 +22,8 @@ namespace OxidEsales\ComposerPlugin\Installer; +use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\CopyGlobFilteredFileManager; + /** * @inheritdoc */ @@ -45,7 +47,12 @@ public function isInstalled() public function install($packagePath) { $this->getIO()->write("Installing module {$this->getPackage()->getName()} package."); - $this->getFileSystem()->mirror($this->formSourcePath($packagePath), $this->formTargetPath()); + + CopyGlobFilteredFileManager::copy( + $this->formSourcePath($packagePath), + $this->formTargetPath(), + $this->getBlacklistFilterValue() + ); } /** @@ -58,11 +65,11 @@ public function update($packagePath) if ($this->askQuestionIfNotInstalled("Update operation will overwrite {$this->getPackage()->getName()} files." ." Do you want to continue? (Yes/No) ")) { $this->getIO()->write("Copying module {$this->getPackage()->getName()} files..."); - $this->getFileSystem()->mirror( + + CopyGlobFilteredFileManager::copy( $this->formSourcePath($packagePath), $this->formTargetPath(), - null, - ['override' => true] + $this->getBlacklistFilterValue() ); } } diff --git a/src/Installer/PackagesInstaller.php b/src/Installer/PackagesInstaller.php index 7c58f78..aabcfb8 100644 --- a/src/Installer/PackagesInstaller.php +++ b/src/Installer/PackagesInstaller.php @@ -24,7 +24,6 @@ use Composer\Installer\LibraryInstaller; use Composer\Package\PackageInterface; -use Symfony\Component\Filesystem\Filesystem; /** * Class responsible for triggering installation process. @@ -108,6 +107,6 @@ public function getShopSourcePath() */ protected function createInstaller(PackageInterface $package) { - return new $this->installers[$package->getType()](new Filesystem(), $this->io, $this->getShopSourcePath(), $package); + return new $this->installers[$package->getType()]($this->io, $this->getShopSourcePath(), $package); } } diff --git a/src/Installer/ShopInstaller.php b/src/Installer/ShopInstaller.php index 4e7e39e..054017e 100644 --- a/src/Installer/ShopInstaller.php +++ b/src/Installer/ShopInstaller.php @@ -22,19 +22,13 @@ namespace OxidEsales\ComposerPlugin\Installer; +use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\CopyGlobFilteredFileManager; + /** * @inheritdoc */ class ShopInstaller extends AbstractInstaller { - /** @var array Directories which shouldn't be copied. */ - private $directoriesToSkip = [ - 'Application/Component', - 'Application/Controller', - 'Application/Model', - 'Core' - ]; - /** * @return bool */ @@ -64,33 +58,29 @@ public function update($packagePath) $this->getIO()->write("Installing shop package."); if ($this->askQuestionIfNotInstalled('Do you want to overwrite existing OXID eShop files? (Yes/No) ')) { $this->getIO()->write("Copying shop files to source directory..."); - $this->copyFiles($packagePath, ['override' => true]); + $this->copyFiles($packagePath); } } - /** - * @return DirectoriesSkipIteratorBuilder - */ - protected function getDirectoriesToSkipIteratorBuilder() - { - return new DirectoriesSkipIteratorBuilder(); - } - /** * @param $packagePath - * @param array $options */ - protected function copyFiles($packagePath, $options = []) + protected function copyFiles($packagePath) { $packagePath = rtrim($packagePath, '/') . '/source'; $root = $this->getRootDirectory(); - $iterator = $this->getDirectoriesToSkipIteratorBuilder(); - $fileSystem = $this->getFileSystem(); - $fileSystem->mirror($packagePath, $root, $iterator->build($packagePath, $this->directoriesToSkip), $options); + CopyGlobFilteredFileManager::copy( + $packagePath, + $root, + $this->getBlacklistFilterValue() + ); if (file_exists($root.'/config.inc.php.dist') && !file_exists($root.'/config.inc.php')) { - $fileSystem->copy($root.'/config.inc.php.dist', $root.'/config.inc.php'); + CopyGlobFilteredFileManager::copy( + $root.'/config.inc.php.dist', + $root.'/config.inc.php' + ); } } } diff --git a/src/Installer/ThemeInstaller.php b/src/Installer/ThemeInstaller.php index 9038485..e2f9646 100644 --- a/src/Installer/ThemeInstaller.php +++ b/src/Installer/ThemeInstaller.php @@ -22,6 +22,9 @@ namespace OxidEsales\ComposerPlugin\Installer; +use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\CopyGlobFilteredFileManager; +use Webmozart\PathUtil\Path; + /** * @inheritdoc */ @@ -59,21 +62,29 @@ public function update($packagePath) if ($this->askQuestionIfNotInstalled("Update operation will overwrite {$this->getPackage()->getName()} files." ." Do you want to continue? (Yes/No) ")) { $this->getIO()->write("Copying theme {$this->getPackage()->getName()} files..."); - $this->copyFiles($packagePath, ['override' => true]); + $this->copyFiles($packagePath); } } /** * @param string $packagePath - * @param array $options */ - protected function copyFiles($packagePath, $options = []) + protected function copyFiles($packagePath) { - $iterator = $this->getDirectoriesToSkipIteratorBuilder() - ->build($packagePath, [$this->formAssetsDirectoryName()]); - $fileSystem = $this->getFileSystem(); - $fileSystem->mirror($packagePath, $this->formThemeTargetPath(), $iterator, $options); - $this->installAssets($packagePath, $options); + $filter = [Path::join($this->formAssetsDirectoryName(), AbstractInstaller::BLACKLIST_ALL_FILES)]; + $filterFromExtras = $this->getBlacklistFilterValue(); + + if (is_array($filterFromExtras)) { + $filter = array_merge($filter, $filterFromExtras); + } + + CopyGlobFilteredFileManager::copy( + $packagePath, + $this->formThemeTargetPath(), + $filter + ); + + $this->installAssets($packagePath); } /** @@ -88,9 +99,8 @@ protected function formThemeTargetPath() /** * @param string $packagePath - * @param array $options */ - protected function installAssets($packagePath, $options) + protected function installAssets($packagePath) { $package = $this->getPackage(); $target = $this->getRootDirectory() . '/out/' . $this->formThemeDirectoryName($package); @@ -98,9 +108,12 @@ protected function installAssets($packagePath, $options) $assetsDirectory = $this->formAssetsDirectoryName(); $source = $packagePath . '/' . $assetsDirectory; - $fileSystem = $this->getFileSystem(); if (file_exists($source)) { - $fileSystem->mirror($source, $target, null, $options); + CopyGlobFilteredFileManager::copy( + $source, + $target, + $this->getBlacklistFilterValue() + ); } } @@ -128,12 +141,4 @@ protected function formAssetsDirectoryName() } return $assetsDirectory; } - - /** - * @return DirectoriesSkipIteratorBuilder - */ - protected function getDirectoriesToSkipIteratorBuilder() - { - return new DirectoriesSkipIteratorBuilder(); - } } diff --git a/tests/Integration/Installer/DirectoryRecursiveFilterIteratorTest.php b/tests/Integration/Installer/DirectoryRecursiveFilterIteratorTest.php deleted file mode 100644 index d098b2e..0000000 --- a/tests/Integration/Installer/DirectoryRecursiveFilterIteratorTest.php +++ /dev/null @@ -1,61 +0,0 @@ -. - * - * @link http://www.oxid-esales.com - * @copyright (C) OXID eSales AG 2003-2016 - * @version OXID eShop Composer plugin - */ - -namespace OxidEsales\ComposerPlugin\Tests\Integration\Installer; - -use org\bovigo\vfs\vfsStream; -use OxidEsales\ComposerPlugin\Installer\DirectoryRecursiveFilterIterator; - -class DirectoryRecursiveFilterIteratorTest extends \PHPUnit_Framework_TestCase -{ - public function testFilteringDirectories() - { - $structure = [ - 'Directory' => [ - 'NotSkipped' => [], - 'Skipped' => [ - 'SkippedInside' => [], - 'Class.php' => 'content' - ], - 'SkippedNot' => [], - ] - ]; - vfsStream::setup('root', 777, ['projectRoot' => $structure]); - $rootPath = vfsStream::url('root/projectRoot'); - - $directoryIterator = new \RecursiveDirectoryIterator($rootPath, \FilesystemIterator::SKIP_DOTS); - $directoryFilter = new DirectoryRecursiveFilterIterator($directoryIterator, [$rootPath.'/Directory/Skipped']); - $iterator = new \RecursiveIteratorIterator($directoryFilter, \RecursiveIteratorIterator::SELF_FIRST); - - $result = []; - foreach ($iterator as $path) { - $result[] = $path->getPathName(); - } - - $expected = [ - $rootPath.'/Directory', - $rootPath.'/Directory/NotSkipped', - $rootPath.'/Directory/SkippedNot' - ]; - $this->assertEquals($expected, $result); - } -} diff --git a/tests/Integration/Installer/ModuleInstallerTest.php b/tests/Integration/Installer/ModuleInstallerTest.php index 2f911c8..e2d7db7 100644 --- a/tests/Integration/Installer/ModuleInstallerTest.php +++ b/tests/Integration/Installer/ModuleInstallerTest.php @@ -26,7 +26,7 @@ use Composer\Package\Package; use OxidEsales\ComposerPlugin\Installer\ModuleInstaller; use org\bovigo\vfs\vfsStream; -use Symfony\Component\Filesystem\Filesystem; +use Webmozart\PathUtil\Path; class ModuleInstallerTest extends \PHPUnit_Framework_TestCase { @@ -40,7 +40,7 @@ public function testChecksIfModuleIsNotInstalled() vfsStream::setup('root', 777, ['projectRoot' => $this->getStructurePreparator()->prepareStructure($structure)]); $rootPath = vfsStream::url('root/projectRoot/source'); - $shopPreparator = new ModuleInstaller(new Filesystem(), new NullIO, $rootPath, new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev')); + $shopPreparator = new ModuleInstaller(new NullIO, $rootPath, new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev')); $this->assertFalse($shopPreparator->isInstalled()); } @@ -53,7 +53,7 @@ public function testChecksIfModuleIsInstalled() vfsStream::setup('root', 777, ['projectRoot' => $this->getStructurePreparator()->prepareStructure($structure)]); $rootPath = vfsStream::url('root/projectRoot/source'); - $shopPreparator = new ModuleInstaller(new Filesystem(), new NullIO, $rootPath, new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev')); + $shopPreparator = new ModuleInstaller(new NullIO, $rootPath, new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev')); $this->assertTrue($shopPreparator->isInstalled()); } @@ -86,7 +86,7 @@ public function testChecksIfModuleFilesExistsAfterInstallation($composerExtras, $installedModuleMetadata = "$eshopRootPath/$installedModuleMetadata"; $package = new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev'); - $shopPreparator = new ModuleInstaller(new Filesystem(), new NullIO(), $eshopRootPath, $package); + $shopPreparator = new ModuleInstaller(new NullIO(), $eshopRootPath, $package); $package->setExtra($composerExtras); $moduleInVendor = "$rootPath/vendor/" . static::PRODUCT_NAME_IN_COMPOSER_FILE . ""; $shopPreparator->install($moduleInVendor); @@ -108,7 +108,7 @@ public function testCheckIfModuleIsInstalledFromProvidedSourceDirectory() $installedModuleMetadata = "$eshopRootPath/modules/erp/metadata.php"; $package = new Package('oxid-esales/erp', 'dev', 'dev'); - $shopPreparator = new ModuleInstaller(new Filesystem(), new NullIO(), $eshopRootPath, $package); + $shopPreparator = new ModuleInstaller(new NullIO(), $eshopRootPath, $package); $package->setExtra( [ModuleInstaller::EXTRA_PARAMETER_KEY_ROOT => [ ModuleInstaller::EXTRA_PARAMETER_KEY_SOURCE => 'copy_this/modules/erp', @@ -128,4 +128,143 @@ public function getStructurePreparator() { return new StructurePreparator(); } + + public function testBlacklistedFilesArePresentWhenNoBlacklistFilterIsDefined() + { + $structure = [ + 'vendor' => [ + 'test-vendor' => [ + 'test-package' => [ + 'metadata.php' => 'meta data', + 'module.php' => 'module', + 'readme.txt' => 'readme', + ] + ] + ] + ]; + + vfsStream::setup('root', 777, ['projectRoot' => $structure]); + + $rootPath = vfsStream::url('root/projectRoot'); + $shopRootPath = Path::join($rootPath, 'source'); + $installedModulePath = Path::join($shopRootPath, 'modules', 'test-vendor', 'test-package'); + $moduleSourcePath = Path::join($rootPath, 'vendor', 'test-vendor', 'test-package'); + + $package = new Package('test-vendor/test-package', 'dev', 'dev'); + $moduleInstaller = new ModuleInstaller(new NullIO(), $shopRootPath, $package); + $moduleInstaller->install($moduleSourcePath); + + $this->assertFileExists(Path::join($installedModulePath, 'metadata.php')); + $this->assertFileExists(Path::join($installedModulePath, 'module.php')); + $this->assertFileExists(Path::join($installedModulePath, 'readme.txt')); + } + + public function testBlacklistedFilesArePresentWhenEmptyBlacklistFilterIsDefined() + { + $structure = [ + 'vendor' => [ + 'test-vendor' => [ + 'test-package' => [ + 'metadata.php' => 'meta data', + 'module.php' => 'module', + 'readme.txt' => 'readme', + ] + ] + ] + ]; + + vfsStream::setup('root', 777, ['projectRoot' => $structure]); + + $rootPath = vfsStream::url('root/projectRoot'); + $shopRootPath = Path::join($rootPath, 'source'); + $installedModulePath = Path::join($shopRootPath, 'modules', 'test-vendor', 'test-package'); + $moduleSourcePath = Path::join($rootPath, 'vendor', 'test-vendor', 'test-package'); + + $package = new Package('test-vendor/test-package', 'dev', 'dev'); + $package->setExtra([ + 'oxideshop' => [ + 'blacklist-filter' => [], + ] + ]); + $moduleInstaller = new ModuleInstaller(new NullIO(), $shopRootPath, $package); + $moduleInstaller->install($moduleSourcePath); + + $this->assertFileExists(Path::join($installedModulePath, 'metadata.php')); + $this->assertFileExists(Path::join($installedModulePath, 'module.php')); + $this->assertFileExists(Path::join($installedModulePath, 'readme.txt')); + } + + public function testBlacklistedFilesArePresentWhenDifferentBlacklistFilterIsDefined() + { + $structure = [ + 'vendor' => [ + 'test-vendor' => [ + 'test-package' => [ + 'metadata.php' => 'meta data', + 'module.php' => 'module', + 'readme.txt' => 'readme', + ] + ] + ] + ]; + + vfsStream::setup('root', 777, ['projectRoot' => $structure]); + + $rootPath = vfsStream::url('root/projectRoot'); + $shopRootPath = Path::join($rootPath, 'source'); + $installedModulePath = Path::join($shopRootPath, 'modules', 'test-vendor', 'test-package'); + $moduleSourcePath = Path::join($rootPath, 'vendor', 'test-vendor', 'test-package'); + + $package = new Package('test-vendor/test-package', 'dev', 'dev'); + $package->setExtra([ + 'oxideshop' => [ + 'blacklist-filter' => [ + "**/*.pdf", + ], + ] + ]); + $moduleInstaller = new ModuleInstaller(new NullIO(), $shopRootPath, $package); + $moduleInstaller->install($moduleSourcePath); + + $this->assertFileExists(Path::join($installedModulePath, 'metadata.php')); + $this->assertFileExists(Path::join($installedModulePath, 'module.php')); + $this->assertFileExists(Path::join($installedModulePath, 'readme.txt')); + } + + public function testBlacklistedFilesAreSkippedWhenABlacklistFilterIsDefined() + { + $structure = [ + 'vendor' => [ + 'test-vendor' => [ + 'test-package' => [ + 'metadata.php' => 'meta data', + 'module.php' => 'module', + 'readme.txt' => 'readme', + ] + ] + ] + ]; + + vfsStream::setup('root', 777, ['projectRoot' => $structure]); + + $rootPath = vfsStream::url('root/projectRoot'); + $shopRootPath = Path::join($rootPath, 'source'); + $installedModulePath = Path::join($shopRootPath, 'modules', 'test-vendor', 'test-package'); + $moduleSourcePath = Path::join($rootPath, 'vendor', 'test-vendor', 'test-package'); + + $package = new Package('test-vendor/test-package', 'dev', 'dev'); + $package->setExtra([ + 'oxideshop' => [ + 'blacklist-filter' => [ + "**/*.txt", + ], + ] + ]); + $moduleInstaller = new ModuleInstaller(new NullIO(), $shopRootPath, $package); + $moduleInstaller->install($moduleSourcePath); + + $this->assertFileExists(Path::join($installedModulePath, 'metadata.php')); + $this->assertFileExists(Path::join($installedModulePath, 'module.php')); + $this->assertFileNotExists(Path::join($installedModulePath, 'readme.txt')); + } } diff --git a/tests/Integration/Installer/PackagesInstallerTest.php b/tests/Integration/Installer/PackagesInstallerTest.php index d70c14f..abecfd8 100644 --- a/tests/Integration/Installer/PackagesInstallerTest.php +++ b/tests/Integration/Installer/PackagesInstallerTest.php @@ -25,11 +25,7 @@ use Composer\Composer; use Composer\Config; use Composer\IO\NullIO; -use org\bovigo\vfs\vfsStream; -use org\bovigo\vfs\vfsStreamWrapper; -use org\bovigo\vfs\visitor\vfsStreamStructureVisitor; use OxidEsales\ComposerPlugin\Installer\PackagesInstaller; -use Symfony\Component\Filesystem\Filesystem; class PackagesInstallerTest extends \PHPUnit_Framework_TestCase { diff --git a/tests/Integration/Installer/ShopInstallerTest.php b/tests/Integration/Installer/ShopInstallerTest.php index 23960e8..28fc9dc 100644 --- a/tests/Integration/Installer/ShopInstallerTest.php +++ b/tests/Integration/Installer/ShopInstallerTest.php @@ -26,7 +26,7 @@ use Composer\Package\Package; use OxidEsales\ComposerPlugin\Installer\ShopInstaller; use org\bovigo\vfs\vfsStream; -use Symfony\Component\Filesystem\Filesystem; +use Webmozart\PathUtil\Path; class ShopInstallerTest extends \PHPUnit_Framework_TestCase { @@ -38,7 +38,7 @@ public function testChecksIfPackageIsNotInstalled() vfsStream::setup('root', 777, ['projectRoot' => $this->getStructurePreparator()->prepareStructure($structure)]); $rootPath = vfsStream::url('root/projectRoot/source'); - $shopPreparator = new ShopInstaller(new Filesystem(), new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); + $shopPreparator = new ShopInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); $this->assertFalse($shopPreparator->isInstalled()); } @@ -53,7 +53,7 @@ public function testChecksIfPackageInstalled() vfsStream::setup('root', 777, ['projectRoot' => $this->getStructurePreparator()->prepareStructure($structure)]); $rootPath = vfsStream::url('root/projectRoot/source'); - $shopPreparator = new ShopInstaller(new Filesystem(), new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); + $shopPreparator = new ShopInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); $this->assertTrue($shopPreparator->isInstalled()); } @@ -71,7 +71,7 @@ public function testInstallationOfPackage() $rootPath = vfsStream::url('root/projectRoot/source'); $shopDirectory = "$rootPath/vendor/oxideshop_ce"; - $shopPreparator = new ShopInstaller(new Filesystem(), new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); + $shopPreparator = new ShopInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); $shopPreparator->install($shopDirectory); $this->assertFileExists($rootPath . '/index.php'); @@ -91,7 +91,7 @@ public function testInstallCreatesConfigInc() $rootPath = vfsStream::url('root/projectRoot/source'); $shopDirectory = "$rootPath/vendor/oxideshop_ce"; - $shopPreparator = new ShopInstaller(new Filesystem(), new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); + $shopPreparator = new ShopInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); $shopPreparator->install($shopDirectory); $this->assertFileExists($rootPath . '/config.inc.php'); @@ -100,24 +100,55 @@ public function testInstallCreatesConfigInc() public function testInstallDoesNotCopyClasses() { $structure = [ - 'source/vendor/oxideshop_ce/source' => [ - 'Core/Class.php' => ' ' ' [ + 'vendor' => [ + 'oxideshop_ce' => [ + 'source' => [ + 'Class.php' => 'Class', + 'Core' => [ + 'Class.php' => 'Class', + ], + 'Application' => [ + 'Model' => [ + 'Class.php' => 'Class', + ], + 'Controller' => [ + 'Class.php' => 'Class' + ] + ] + ] + ] + ] ] ]; - vfsStream::setup('root', 777, ['projectRoot' => $this->getStructurePreparator()->prepareStructure($structure)]); + + vfsStream::setup('root', 777, ['projectRoot' => $structure]); $rootPath = vfsStream::url('root/projectRoot/source'); $shopDirectory = "$rootPath/vendor/oxideshop_ce"; - $shopPreparator = new ShopInstaller(new Filesystem(), new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); + $package = new Package('oxid-esales/oxideshop-ce', 'dev', 'dev'); + $package->setExtra([ + 'oxideshop' => [ + 'blacklist-filter' => [ + "Application/Component/**/*.*", + "Application/Controller/**/*.*", + "Application/Model/**/*.*", + "Core/**/*.*" + ] + ] + ]); + + $shopPreparator = new ShopInstaller(new NullIO, $rootPath, $package); $shopPreparator->install($shopDirectory); - $this->assertFileNotExists($rootPath . '/Core/Class.php'); - $this->assertFileNotExists($rootPath . '/Application/Model/Class.php'); - $this->assertFileNotExists($rootPath . '/Application/Controller/Class.php'); - $this->assertFileNotExists($rootPath . '/Application/Controller'); + $this->assertFileExists(Path::join($rootPath, 'Class.php')); + $this->assertFileNotExists(Path::join($rootPath, 'Core')); + $this->assertFileNotExists(Path::join($rootPath, 'Core', 'Class.php')); + $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Model')); + $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Model', 'Class.php')); + $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Controller')); + $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Controller', 'Class.php')); } /** diff --git a/tests/Integration/Installer/ThemeInstallerTest.php b/tests/Integration/Installer/ThemeInstallerTest.php index 54773d1..bc84adb 100644 --- a/tests/Integration/Installer/ThemeInstallerTest.php +++ b/tests/Integration/Installer/ThemeInstallerTest.php @@ -26,7 +26,7 @@ use Composer\Package\Package; use org\bovigo\vfs\vfsStream; use OxidEsales\ComposerPlugin\Installer\ThemeInstaller; -use Symfony\Component\Filesystem\Filesystem; +use Webmozart\PathUtil\Path; class ThemeInstallerTest extends \PHPUnit_Framework_TestCase { @@ -41,7 +41,7 @@ public function testChecksIfThemeIsNotInstalled() $rootPath = vfsStream::url('root/projectRoot/source'); $package = new Package(static::THEME_NAME_IN_COMPOSER, 'dev', 'dev'); - $themeInstaller = new ThemeInstaller(new Filesystem(), new NullIO, $rootPath, $package); + $themeInstaller = new ThemeInstaller(new NullIO, $rootPath, $package); $this->assertFalse($themeInstaller->isInstalled()); } @@ -55,7 +55,7 @@ public function testChecksIfThemeIsInstalled() $rootPath = vfsStream::url('root/projectRoot/source'); $package = new Package(static::THEME_NAME_IN_COMPOSER, 'dev', 'dev'); - $shopPreparator = new ThemeInstaller(new Filesystem(), new NullIO(), $rootPath, $package); + $shopPreparator = new ThemeInstaller(new NullIO(), $rootPath, $package); $this->assertTrue($shopPreparator->isInstalled()); } @@ -148,19 +148,109 @@ protected function getStructurePreparator() */ protected function simulateInstallation($composerExtras, $rootPath, $eshopRootPath) { + $vendorName = explode("/", static::THEME_NAME_IN_COMPOSER)[0]; + $packageName = explode("/", static::THEME_NAME_IN_COMPOSER)[1]; + $structure = [ - 'vendor/' . static::THEME_NAME_IN_COMPOSER => [ - 'theme.php' => ' '.class {}', - 'custom_directory_name/custom_style.css' => '.class {}', + 'vendor' => [ + $vendorName => [ + $packageName => [ + 'theme.php' => ' 'readme', + 'out' => [ + 'style.css' => '.class {}', + 'readme.pdf' => 'PDF', + ], + 'custom_directory_name' => [ + 'custom_style.css' => '.class {}', + ] + ] + ] ] ]; - vfsStream::setup('root', 777, ['projectRoot' => $this->getStructurePreparator()->prepareStructure($structure)]); + + vfsStream::setup('root', 777, ['projectRoot' => $structure]); $package = new Package(static::THEME_NAME_IN_COMPOSER, 'dev', 'dev'); - $shopPreparator = new ThemeInstaller(new Filesystem(), new NullIO(), $eshopRootPath, $package); + $shopPreparator = new ThemeInstaller(new NullIO(), $eshopRootPath, $package); $package->setExtra($composerExtras); $themeInVendor = "$rootPath/vendor/" . static::THEME_NAME_IN_COMPOSER; $shopPreparator->install($themeInVendor); } + + public function testBlacklistedFilesArePresentWhenNoBlacklistFilterIsDefined() + { + $composerExtraParameters = [ + 'oxideshop' => [ + 'target-directory' => 'flow', + ] + ]; + + $rootPath = vfsStream::url('root/projectRoot'); + $shopRootPath = Path::join($rootPath, 'source'); + + $this->simulateInstallation($composerExtraParameters, $rootPath, $shopRootPath); + + $this->assertFileExists(Path::join($shopRootPath, 'Application', 'views', 'flow', 'readme.txt')); + $this->assertFileExists(Path::join($shopRootPath, 'out', 'flow', 'readme.pdf')); + } + + public function testBlacklistedFilesArePresentWhenEmptyBlacklistFilterIsDefined() + { + $composerExtraParameters = [ + 'oxideshop' => [ + 'target-directory' => 'flow', + 'blacklist-filter' => [], + ] + ]; + + $rootPath = vfsStream::url('root/projectRoot'); + $shopRootPath = Path::join($rootPath, 'source'); + + $this->simulateInstallation($composerExtraParameters, $rootPath, $shopRootPath); + + $this->assertFileExists(Path::join($shopRootPath, 'Application', 'views', 'flow', 'readme.txt')); + $this->assertFileExists(Path::join($shopRootPath, 'out', 'flow', 'readme.pdf')); + } + + public function testBlacklistedFilesArePresentWhenDifferentBlacklistFilterIsDefined() + { + $composerExtraParameters = [ + 'oxideshop' => [ + 'target-directory' => 'flow', + 'blacklist-filter' => [ + '**/*.doc' + ], + ] + ]; + + $rootPath = vfsStream::url('root/projectRoot'); + $shopRootPath = Path::join($rootPath, 'source'); + + $this->simulateInstallation($composerExtraParameters, $rootPath, $shopRootPath); + + $this->assertFileExists(Path::join($shopRootPath, 'Application', 'views', 'flow', 'readme.txt')); + $this->assertFileExists(Path::join($shopRootPath, 'out', 'flow', 'readme.pdf')); + } + + public function testBlacklistedFilesAreSkippedWhenABlacklistFilterIsDefined() + { + $composerExtraParameters = [ + 'oxideshop' => [ + 'target-directory' => 'flow', + 'blacklist-filter' => [ + "**/*.txt", + "**/*.pdf", + ], + ] + ]; + + $rootPath = vfsStream::url('root/projectRoot'); + $shopRootPath = Path::join($rootPath, 'source'); + + $this->simulateInstallation($composerExtraParameters, $rootPath, $shopRootPath); + + $this->assertFileNotExists(Path::join($shopRootPath, 'Application', 'views', 'flow', 'readme.txt')); + $this->assertFileNotExists(Path::join($shopRootPath, 'out', 'flow', 'readme.pdf')); + } } From 2dfd9c820fc8e7d46da98feab1474bb19bc2bff9 Mon Sep 17 00:00:00 2001 From: Edvinas Aleksejonokas Date: Tue, 30 May 2017 15:59:50 +0300 Subject: [PATCH 03/13] ESDEV-4443 Restructure Package Installers Part 1 Git does not handle file renames and content changes at the same time. Because of this commit has been splitted into two parts: 1) Renaming of files 2) Updating of contents --- .../AbstractPackageInstaller.php} | 0 .../{ModuleInstaller.php => Package/ModulePackageInstaller.php} | 0 .../{ShopInstaller.php => Package/ShopPackageInstaller.php} | 0 .../{ThemeInstaller.php => Package/ThemePackageInstaller.php} | 0 .../{PackagesInstaller.php => PackageInstallerTrigger.php} | 0 .../ModulePackageInstallerTest.php} | 0 .../ShopPackageInstallerTest.php} | 0 .../ThemePackageInstallerTest.php} | 0 ...{PackagesInstallerTest.php => PackageInstallerTriggerTest.php} | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename src/Installer/{AbstractInstaller.php => Package/AbstractPackageInstaller.php} (100%) rename src/Installer/{ModuleInstaller.php => Package/ModulePackageInstaller.php} (100%) rename src/Installer/{ShopInstaller.php => Package/ShopPackageInstaller.php} (100%) rename src/Installer/{ThemeInstaller.php => Package/ThemePackageInstaller.php} (100%) rename src/Installer/{PackagesInstaller.php => PackageInstallerTrigger.php} (100%) rename tests/Integration/Installer/{ModuleInstallerTest.php => Package/ModulePackageInstallerTest.php} (100%) rename tests/Integration/Installer/{ShopInstallerTest.php => Package/ShopPackageInstallerTest.php} (100%) rename tests/Integration/Installer/{ThemeInstallerTest.php => Package/ThemePackageInstallerTest.php} (100%) rename tests/Integration/Installer/{PackagesInstallerTest.php => PackageInstallerTriggerTest.php} (100%) diff --git a/src/Installer/AbstractInstaller.php b/src/Installer/Package/AbstractPackageInstaller.php similarity index 100% rename from src/Installer/AbstractInstaller.php rename to src/Installer/Package/AbstractPackageInstaller.php diff --git a/src/Installer/ModuleInstaller.php b/src/Installer/Package/ModulePackageInstaller.php similarity index 100% rename from src/Installer/ModuleInstaller.php rename to src/Installer/Package/ModulePackageInstaller.php diff --git a/src/Installer/ShopInstaller.php b/src/Installer/Package/ShopPackageInstaller.php similarity index 100% rename from src/Installer/ShopInstaller.php rename to src/Installer/Package/ShopPackageInstaller.php diff --git a/src/Installer/ThemeInstaller.php b/src/Installer/Package/ThemePackageInstaller.php similarity index 100% rename from src/Installer/ThemeInstaller.php rename to src/Installer/Package/ThemePackageInstaller.php diff --git a/src/Installer/PackagesInstaller.php b/src/Installer/PackageInstallerTrigger.php similarity index 100% rename from src/Installer/PackagesInstaller.php rename to src/Installer/PackageInstallerTrigger.php diff --git a/tests/Integration/Installer/ModuleInstallerTest.php b/tests/Integration/Installer/Package/ModulePackageInstallerTest.php similarity index 100% rename from tests/Integration/Installer/ModuleInstallerTest.php rename to tests/Integration/Installer/Package/ModulePackageInstallerTest.php diff --git a/tests/Integration/Installer/ShopInstallerTest.php b/tests/Integration/Installer/Package/ShopPackageInstallerTest.php similarity index 100% rename from tests/Integration/Installer/ShopInstallerTest.php rename to tests/Integration/Installer/Package/ShopPackageInstallerTest.php diff --git a/tests/Integration/Installer/ThemeInstallerTest.php b/tests/Integration/Installer/Package/ThemePackageInstallerTest.php similarity index 100% rename from tests/Integration/Installer/ThemeInstallerTest.php rename to tests/Integration/Installer/Package/ThemePackageInstallerTest.php diff --git a/tests/Integration/Installer/PackagesInstallerTest.php b/tests/Integration/Installer/PackageInstallerTriggerTest.php similarity index 100% rename from tests/Integration/Installer/PackagesInstallerTest.php rename to tests/Integration/Installer/PackageInstallerTriggerTest.php From fa590890c12e1b6a4597a8c64e22f51f64ec0880 Mon Sep 17 00:00:00 2001 From: Edvinas Aleksejonokas Date: Tue, 30 May 2017 16:14:59 +0300 Subject: [PATCH 04/13] ESDEV-4443 Restructure Package Installers Part 2 Git does not handle file renames and content changes at the same time. Because of this commit has been splitted into two parts: 1) Renaming of files 2) Updating of contents --- .../Package/AbstractPackageInstaller.php | 4 +-- .../Package/ModulePackageInstaller.php | 4 +-- .../Package/ShopPackageInstaller.php | 4 +-- .../Package/ThemePackageInstaller.php | 6 ++-- src/Installer/PackageInstallerTrigger.php | 18 ++++++---- src/Plugin.php | 22 ++++++------- .../Package/ModulePackageInstallerTest.php | 33 ++++++++++--------- .../Package/ShopPackageInstallerTest.php | 17 +++++----- .../Package/ThemePackageInstallerTest.php | 33 ++++++++++--------- .../Installer/PackageInstallerTriggerTest.php | 8 ++--- 10 files changed, 78 insertions(+), 71 deletions(-) diff --git a/src/Installer/Package/AbstractPackageInstaller.php b/src/Installer/Package/AbstractPackageInstaller.php index 11aedfc..2158ace 100644 --- a/src/Installer/Package/AbstractPackageInstaller.php +++ b/src/Installer/Package/AbstractPackageInstaller.php @@ -20,7 +20,7 @@ * @version OXID eShop Composer plugin */ -namespace OxidEsales\ComposerPlugin\Installer; +namespace OxidEsales\ComposerPlugin\Installer\Package; use Composer\IO\IOInterface; use Composer\Package\PackageInterface; @@ -29,7 +29,7 @@ * Class is responsible for preparing project structure. * It copies necessary files to specific directories. */ -abstract class AbstractInstaller +abstract class AbstractPackageInstaller { const EXTRA_PARAMETER_KEY_ROOT = 'oxideshop'; diff --git a/src/Installer/Package/ModulePackageInstaller.php b/src/Installer/Package/ModulePackageInstaller.php index b0d326b..1554343 100644 --- a/src/Installer/Package/ModulePackageInstaller.php +++ b/src/Installer/Package/ModulePackageInstaller.php @@ -20,14 +20,14 @@ * @version OXID eShop Composer plugin */ -namespace OxidEsales\ComposerPlugin\Installer; +namespace OxidEsales\ComposerPlugin\Installer\Package; use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\CopyGlobFilteredFileManager; /** * @inheritdoc */ -class ModuleInstaller extends AbstractInstaller +class ModulePackageInstaller extends AbstractPackageInstaller { const METADATA_FILE_NAME = 'metadata.php'; diff --git a/src/Installer/Package/ShopPackageInstaller.php b/src/Installer/Package/ShopPackageInstaller.php index 054017e..558ae2f 100644 --- a/src/Installer/Package/ShopPackageInstaller.php +++ b/src/Installer/Package/ShopPackageInstaller.php @@ -20,14 +20,14 @@ * @version OXID eShop Composer plugin */ -namespace OxidEsales\ComposerPlugin\Installer; +namespace OxidEsales\ComposerPlugin\Installer\Package; use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\CopyGlobFilteredFileManager; /** * @inheritdoc */ -class ShopInstaller extends AbstractInstaller +class ShopPackageInstaller extends AbstractPackageInstaller { /** * @return bool diff --git a/src/Installer/Package/ThemePackageInstaller.php b/src/Installer/Package/ThemePackageInstaller.php index e2f9646..13d4bec 100644 --- a/src/Installer/Package/ThemePackageInstaller.php +++ b/src/Installer/Package/ThemePackageInstaller.php @@ -20,7 +20,7 @@ * @version OXID eShop Composer plugin */ -namespace OxidEsales\ComposerPlugin\Installer; +namespace OxidEsales\ComposerPlugin\Installer\Package; use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\CopyGlobFilteredFileManager; use Webmozart\PathUtil\Path; @@ -28,7 +28,7 @@ /** * @inheritdoc */ -class ThemeInstaller extends AbstractInstaller +class ThemePackageInstaller extends AbstractPackageInstaller { const METADATA_FILE_NAME = 'theme.php'; const PATH_TO_THEMES = "Application/views"; @@ -71,7 +71,7 @@ public function update($packagePath) */ protected function copyFiles($packagePath) { - $filter = [Path::join($this->formAssetsDirectoryName(), AbstractInstaller::BLACKLIST_ALL_FILES)]; + $filter = [Path::join($this->formAssetsDirectoryName(), AbstractPackageInstaller::BLACKLIST_ALL_FILES)]; $filterFromExtras = $this->getBlacklistFilterValue(); if (is_array($filterFromExtras)) { diff --git a/src/Installer/PackageInstallerTrigger.php b/src/Installer/PackageInstallerTrigger.php index aabcfb8..2520d0f 100644 --- a/src/Installer/PackageInstallerTrigger.php +++ b/src/Installer/PackageInstallerTrigger.php @@ -24,11 +24,15 @@ use Composer\Installer\LibraryInstaller; use Composer\Package\PackageInterface; +use OxidEsales\ComposerPlugin\Installer\Package\AbstractPackageInstaller; +use OxidEsales\ComposerPlugin\Installer\Package\ShopPackageInstaller; +use OxidEsales\ComposerPlugin\Installer\Package\ModulePackageInstaller; +use OxidEsales\ComposerPlugin\Installer\Package\ThemePackageInstaller; /** * Class responsible for triggering installation process. */ -class PackagesInstaller extends LibraryInstaller +class PackageInstallerTrigger extends LibraryInstaller { const TYPE_ESHOP = 'oxideshop'; const TYPE_MODULE = 'oxideshop-module'; @@ -37,9 +41,9 @@ class PackagesInstaller extends LibraryInstaller /** @var array Available installers for packages. */ private $installers = [ - self::TYPE_ESHOP => ShopInstaller::class, - self::TYPE_MODULE => ModuleInstaller::class, - self::TYPE_THEME => ThemeInstaller::class, + self::TYPE_ESHOP => ShopPackageInstaller::class, + self::TYPE_MODULE => ModulePackageInstaller::class, + self::TYPE_THEME => ThemePackageInstaller::class, ]; /** @@ -92,8 +96,8 @@ public function getShopSourcePath() { $shopSource = getcwd() . '/source'; - if (isset($this->settings[AbstractInstaller::EXTRA_PARAMETER_SOURCE_PATH])) { - $shopSource = $this->settings[AbstractInstaller::EXTRA_PARAMETER_SOURCE_PATH]; + if (isset($this->settings[AbstractPackageInstaller::EXTRA_PARAMETER_SOURCE_PATH])) { + $shopSource = $this->settings[AbstractPackageInstaller::EXTRA_PARAMETER_SOURCE_PATH]; } return $shopSource; @@ -103,7 +107,7 @@ public function getShopSourcePath() * Creates package installer. * * @param PackageInterface $package - * @return AbstractInstaller + * @return AbstractPackageInstaller */ protected function createInstaller(PackageInterface $package) { diff --git a/src/Plugin.php b/src/Plugin.php index 579a5cc..d9ce20d 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -26,8 +26,8 @@ use Composer\EventDispatcher\EventSubscriberInterface; use Composer\IO\IOInterface; use Composer\Plugin\PluginInterface; -use OxidEsales\ComposerPlugin\Installer\AbstractInstaller; -use OxidEsales\ComposerPlugin\Installer\PackagesInstaller; +use OxidEsales\ComposerPlugin\Installer\Package\AbstractPackageInstaller; +use OxidEsales\ComposerPlugin\Installer\PackageInstallerTrigger; class Plugin implements PluginInterface, EventSubscriberInterface { @@ -41,8 +41,8 @@ class Plugin implements PluginInterface, EventSubscriberInterface /** @var IOInterface */ private $io; - /** @var PackagesInstaller */ - private $packageInstaller; + /** @var PackageInstallerTrigger */ + private $packageInstallerTrigger; /** * Register events. @@ -65,16 +65,16 @@ public static function getSubscribedEvents() */ public function activate(Composer $composer, IOInterface $io) { - $installer = new PackagesInstaller($io, $composer); + $installer = new PackageInstallerTrigger($io, $composer); $composer->getInstallationManager()->addInstaller($installer); $this->composer = $composer; $this->io = $io; - $this->packageInstaller = $installer; + $this->packageInstallerTrigger = $installer; $extraSettings = $this->composer->getPackage()->getExtra(); - if (isset($extraSettings[AbstractInstaller::EXTRA_PARAMETER_KEY_ROOT])) { - $this->packageInstaller->setSettings($extraSettings[AbstractInstaller::EXTRA_PARAMETER_KEY_ROOT]); + if (isset($extraSettings[AbstractPackageInstaller::EXTRA_PARAMETER_KEY_ROOT])) { + $this->packageInstallerTrigger->setSettings($extraSettings[AbstractPackageInstaller::EXTRA_PARAMETER_KEY_ROOT]); } } @@ -99,12 +99,12 @@ protected function executeAction($actionName) $repo = $this->composer->getRepositoryManager()->getLocalRepository(); foreach ($repo->getPackages() as $package) { - if ($this->packageInstaller->supports($package->getType())) { + if ($this->packageInstallerTrigger->supports($package->getType())) { if ($actionName === static::ACTION_INSTALL) { - $this->packageInstaller->installPackage($package); + $this->packageInstallerTrigger->installPackage($package); } if ($actionName === static::ACTION_UPDATE) { - $this->packageInstaller->updatePackage($package); + $this->packageInstallerTrigger->updatePackage($package); } } } diff --git a/tests/Integration/Installer/Package/ModulePackageInstallerTest.php b/tests/Integration/Installer/Package/ModulePackageInstallerTest.php index e2d7db7..a165c78 100644 --- a/tests/Integration/Installer/Package/ModulePackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ModulePackageInstallerTest.php @@ -20,15 +20,16 @@ * @version OXID eShop Composer plugin */ -namespace OxidEsales\ComposerPlugin\Tests\Integration\Installer; +namespace OxidEsales\ComposerPlugin\Tests\Integration\Installer\Package; use Composer\IO\NullIO; use Composer\Package\Package; -use OxidEsales\ComposerPlugin\Installer\ModuleInstaller; +use OxidEsales\ComposerPlugin\Installer\Package\ModulePackageInstaller; use org\bovigo\vfs\vfsStream; +use OxidEsales\ComposerPlugin\Tests\Integration\Installer\StructurePreparator; use Webmozart\PathUtil\Path; -class ModuleInstallerTest extends \PHPUnit_Framework_TestCase +class ModulePackageInstallerTest extends \PHPUnit_Framework_TestCase { const PRODUCT_NAME_IN_COMPOSER_FILE = "oxid-esales/paypal-module"; @@ -40,7 +41,7 @@ public function testChecksIfModuleIsNotInstalled() vfsStream::setup('root', 777, ['projectRoot' => $this->getStructurePreparator()->prepareStructure($structure)]); $rootPath = vfsStream::url('root/projectRoot/source'); - $shopPreparator = new ModuleInstaller(new NullIO, $rootPath, new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev')); + $shopPreparator = new ModulePackageInstaller(new NullIO, $rootPath, new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev')); $this->assertFalse($shopPreparator->isInstalled()); } @@ -53,15 +54,15 @@ public function testChecksIfModuleIsInstalled() vfsStream::setup('root', 777, ['projectRoot' => $this->getStructurePreparator()->prepareStructure($structure)]); $rootPath = vfsStream::url('root/projectRoot/source'); - $shopPreparator = new ModuleInstaller(new NullIO, $rootPath, new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev')); + $shopPreparator = new ModulePackageInstaller(new NullIO, $rootPath, new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev')); $this->assertTrue($shopPreparator->isInstalled()); } public function providerChecksIfModuleFilesExistsAfterInstallation() { return [ - [[ModuleInstaller::EXTRA_PARAMETER_KEY_ROOT => [ModuleInstaller::EXTRA_PARAMETER_KEY_TARGET => 'oe/paypal']], 'modules/oe/paypal/metadata.php'], - [[ModuleInstaller::EXTRA_PARAMETER_KEY_ROOT => [ModuleInstaller::EXTRA_PARAMETER_KEY_TARGET => 'paypal']], 'modules/paypal/metadata.php'], + [[ModulePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ModulePackageInstaller::EXTRA_PARAMETER_KEY_TARGET => 'oe/paypal']], 'modules/oe/paypal/metadata.php'], + [[ModulePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ModulePackageInstaller::EXTRA_PARAMETER_KEY_TARGET => 'paypal']], 'modules/paypal/metadata.php'], [[], 'modules/oxid-esales/paypal-module/metadata.php'] ]; } @@ -86,7 +87,7 @@ public function testChecksIfModuleFilesExistsAfterInstallation($composerExtras, $installedModuleMetadata = "$eshopRootPath/$installedModuleMetadata"; $package = new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev'); - $shopPreparator = new ModuleInstaller(new NullIO(), $eshopRootPath, $package); + $shopPreparator = new ModulePackageInstaller(new NullIO(), $eshopRootPath, $package); $package->setExtra($composerExtras); $moduleInVendor = "$rootPath/vendor/" . static::PRODUCT_NAME_IN_COMPOSER_FILE . ""; $shopPreparator->install($moduleInVendor); @@ -108,11 +109,11 @@ public function testCheckIfModuleIsInstalledFromProvidedSourceDirectory() $installedModuleMetadata = "$eshopRootPath/modules/erp/metadata.php"; $package = new Package('oxid-esales/erp', 'dev', 'dev'); - $shopPreparator = new ModuleInstaller(new NullIO(), $eshopRootPath, $package); + $shopPreparator = new ModulePackageInstaller(new NullIO(), $eshopRootPath, $package); $package->setExtra( - [ModuleInstaller::EXTRA_PARAMETER_KEY_ROOT => [ - ModuleInstaller::EXTRA_PARAMETER_KEY_SOURCE => 'copy_this/modules/erp', - ModuleInstaller::EXTRA_PARAMETER_KEY_TARGET => 'erp', + [ModulePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ + ModulePackageInstaller::EXTRA_PARAMETER_KEY_SOURCE => 'copy_this/modules/erp', + ModulePackageInstaller::EXTRA_PARAMETER_KEY_TARGET => 'erp', ]] ); $moduleInVendor = "$rootPath/vendor/oxid-esales/erp"; @@ -151,7 +152,7 @@ public function testBlacklistedFilesArePresentWhenNoBlacklistFilterIsDefined() $moduleSourcePath = Path::join($rootPath, 'vendor', 'test-vendor', 'test-package'); $package = new Package('test-vendor/test-package', 'dev', 'dev'); - $moduleInstaller = new ModuleInstaller(new NullIO(), $shopRootPath, $package); + $moduleInstaller = new ModulePackageInstaller(new NullIO(), $shopRootPath, $package); $moduleInstaller->install($moduleSourcePath); $this->assertFileExists(Path::join($installedModulePath, 'metadata.php')); @@ -186,7 +187,7 @@ public function testBlacklistedFilesArePresentWhenEmptyBlacklistFilterIsDefined( 'blacklist-filter' => [], ] ]); - $moduleInstaller = new ModuleInstaller(new NullIO(), $shopRootPath, $package); + $moduleInstaller = new ModulePackageInstaller(new NullIO(), $shopRootPath, $package); $moduleInstaller->install($moduleSourcePath); $this->assertFileExists(Path::join($installedModulePath, 'metadata.php')); @@ -223,7 +224,7 @@ public function testBlacklistedFilesArePresentWhenDifferentBlacklistFilterIsDefi ], ] ]); - $moduleInstaller = new ModuleInstaller(new NullIO(), $shopRootPath, $package); + $moduleInstaller = new ModulePackageInstaller(new NullIO(), $shopRootPath, $package); $moduleInstaller->install($moduleSourcePath); $this->assertFileExists(Path::join($installedModulePath, 'metadata.php')); @@ -260,7 +261,7 @@ public function testBlacklistedFilesAreSkippedWhenABlacklistFilterIsDefined() ], ] ]); - $moduleInstaller = new ModuleInstaller(new NullIO(), $shopRootPath, $package); + $moduleInstaller = new ModulePackageInstaller(new NullIO(), $shopRootPath, $package); $moduleInstaller->install($moduleSourcePath); $this->assertFileExists(Path::join($installedModulePath, 'metadata.php')); diff --git a/tests/Integration/Installer/Package/ShopPackageInstallerTest.php b/tests/Integration/Installer/Package/ShopPackageInstallerTest.php index 28fc9dc..73496e4 100644 --- a/tests/Integration/Installer/Package/ShopPackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ShopPackageInstallerTest.php @@ -20,15 +20,16 @@ * @version OXID eShop Composer plugin */ -namespace OxidEsales\ComposerPlugin\Tests\Integration\Installer; +namespace OxidEsales\ComposerPlugin\Tests\Integration\Installer\Package; use Composer\IO\NullIO; use Composer\Package\Package; -use OxidEsales\ComposerPlugin\Installer\ShopInstaller; +use OxidEsales\ComposerPlugin\Installer\Package\ShopPackageInstaller; use org\bovigo\vfs\vfsStream; +use OxidEsales\ComposerPlugin\Tests\Integration\Installer\StructurePreparator; use Webmozart\PathUtil\Path; -class ShopInstallerTest extends \PHPUnit_Framework_TestCase +class ShopPackageInstallerTest extends \PHPUnit_Framework_TestCase { public function testChecksIfPackageIsNotInstalled() { @@ -38,7 +39,7 @@ public function testChecksIfPackageIsNotInstalled() vfsStream::setup('root', 777, ['projectRoot' => $this->getStructurePreparator()->prepareStructure($structure)]); $rootPath = vfsStream::url('root/projectRoot/source'); - $shopPreparator = new ShopInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); + $shopPreparator = new ShopPackageInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); $this->assertFalse($shopPreparator->isInstalled()); } @@ -53,7 +54,7 @@ public function testChecksIfPackageInstalled() vfsStream::setup('root', 777, ['projectRoot' => $this->getStructurePreparator()->prepareStructure($structure)]); $rootPath = vfsStream::url('root/projectRoot/source'); - $shopPreparator = new ShopInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); + $shopPreparator = new ShopPackageInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); $this->assertTrue($shopPreparator->isInstalled()); } @@ -71,7 +72,7 @@ public function testInstallationOfPackage() $rootPath = vfsStream::url('root/projectRoot/source'); $shopDirectory = "$rootPath/vendor/oxideshop_ce"; - $shopPreparator = new ShopInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); + $shopPreparator = new ShopPackageInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); $shopPreparator->install($shopDirectory); $this->assertFileExists($rootPath . '/index.php'); @@ -91,7 +92,7 @@ public function testInstallCreatesConfigInc() $rootPath = vfsStream::url('root/projectRoot/source'); $shopDirectory = "$rootPath/vendor/oxideshop_ce"; - $shopPreparator = new ShopInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); + $shopPreparator = new ShopPackageInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); $shopPreparator->install($shopDirectory); $this->assertFileExists($rootPath . '/config.inc.php'); @@ -139,7 +140,7 @@ public function testInstallDoesNotCopyClasses() ] ]); - $shopPreparator = new ShopInstaller(new NullIO, $rootPath, $package); + $shopPreparator = new ShopPackageInstaller(new NullIO, $rootPath, $package); $shopPreparator->install($shopDirectory); $this->assertFileExists(Path::join($rootPath, 'Class.php')); diff --git a/tests/Integration/Installer/Package/ThemePackageInstallerTest.php b/tests/Integration/Installer/Package/ThemePackageInstallerTest.php index bc84adb..7c68f63 100644 --- a/tests/Integration/Installer/Package/ThemePackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ThemePackageInstallerTest.php @@ -20,15 +20,16 @@ * @version OXID eShop Composer plugin */ -namespace OxidEsales\ComposerPlugin\Tests\Integration\Installer; +namespace OxidEsales\ComposerPlugin\Tests\Integration\Installer\Package; use Composer\IO\NullIO; use Composer\Package\Package; use org\bovigo\vfs\vfsStream; -use OxidEsales\ComposerPlugin\Installer\ThemeInstaller; +use OxidEsales\ComposerPlugin\Installer\Package\ThemePackageInstaller; +use OxidEsales\ComposerPlugin\Tests\Integration\Installer\StructurePreparator; use Webmozart\PathUtil\Path; -class ThemeInstallerTest extends \PHPUnit_Framework_TestCase +class ThemePackageInstallerTest extends \PHPUnit_Framework_TestCase { const THEME_NAME_IN_COMPOSER = "oxid-esales/flow-theme"; @@ -41,7 +42,7 @@ public function testChecksIfThemeIsNotInstalled() $rootPath = vfsStream::url('root/projectRoot/source'); $package = new Package(static::THEME_NAME_IN_COMPOSER, 'dev', 'dev'); - $themeInstaller = new ThemeInstaller(new NullIO, $rootPath, $package); + $themeInstaller = new ThemePackageInstaller(new NullIO, $rootPath, $package); $this->assertFalse($themeInstaller->isInstalled()); } @@ -55,7 +56,7 @@ public function testChecksIfThemeIsInstalled() $rootPath = vfsStream::url('root/projectRoot/source'); $package = new Package(static::THEME_NAME_IN_COMPOSER, 'dev', 'dev'); - $shopPreparator = new ThemeInstaller(new NullIO(), $rootPath, $package); + $shopPreparator = new ThemePackageInstaller(new NullIO(), $rootPath, $package); $this->assertTrue($shopPreparator->isInstalled()); } @@ -66,7 +67,7 @@ public function providerChecksIfThemeFilesExistsAfterInstallation() { return [ [ - [ThemeInstaller::EXTRA_PARAMETER_KEY_ROOT => [ThemeInstaller::EXTRA_PARAMETER_KEY_TARGET => 'flow']], + [ThemePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ThemePackageInstaller::EXTRA_PARAMETER_KEY_TARGET => 'flow']], 'Application/views/flow/theme.php', 'out/flow/style.css' ], @@ -76,14 +77,14 @@ public function providerChecksIfThemeFilesExistsAfterInstallation() 'out/flow-theme/style.css' ], [ - [ThemeInstaller::EXTRA_PARAMETER_KEY_ROOT => [ThemeInstaller::EXTRA_PARAMETER_KEY_ASSETS => 'custom_directory_name']], + [ThemePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ThemePackageInstaller::EXTRA_PARAMETER_KEY_ASSETS => 'custom_directory_name']], 'Application/views/flow-theme/theme.php', 'out/flow-theme/custom_style.css' ], [ - [ThemeInstaller::EXTRA_PARAMETER_KEY_ROOT => [ - ThemeInstaller::EXTRA_PARAMETER_KEY_TARGET => 'flow', - ThemeInstaller::EXTRA_PARAMETER_KEY_ASSETS => 'custom_directory_name', + [ThemePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ + ThemePackageInstaller::EXTRA_PARAMETER_KEY_TARGET => 'flow', + ThemePackageInstaller::EXTRA_PARAMETER_KEY_ASSETS => 'custom_directory_name', ]], 'Application/views/flow/theme.php', 'out/flow/custom_style.css' @@ -111,9 +112,9 @@ public function testChecksIfThemeFilesExistsAfterInstallation($composerExtras, $ public function testChecksIfAssetFileDoesNotExist() { - $composerExtras = [ThemeInstaller::EXTRA_PARAMETER_KEY_ROOT => [ - ThemeInstaller::EXTRA_PARAMETER_KEY_TARGET => 'flow', - ThemeInstaller::EXTRA_PARAMETER_KEY_ASSETS => 'non_existing_directory', + $composerExtras = [ThemePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ + ThemePackageInstaller::EXTRA_PARAMETER_KEY_TARGET => 'flow', + ThemePackageInstaller::EXTRA_PARAMETER_KEY_ASSETS => 'non_existing_directory', ]]; $rootPath = vfsStream::url('root/projectRoot'); @@ -124,8 +125,8 @@ public function testChecksIfAssetFileDoesNotExist() public function testChecksIfAssetsDirectoryWasNotCopied() { - $composerExtras = [ThemeInstaller::EXTRA_PARAMETER_KEY_ROOT => [ - ThemeInstaller::EXTRA_PARAMETER_KEY_TARGET => 'flow' + $composerExtras = [ThemePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ + ThemePackageInstaller::EXTRA_PARAMETER_KEY_TARGET => 'flow' ]]; $rootPath = vfsStream::url('root/projectRoot'); @@ -172,7 +173,7 @@ protected function simulateInstallation($composerExtras, $rootPath, $eshopRootPa vfsStream::setup('root', 777, ['projectRoot' => $structure]); $package = new Package(static::THEME_NAME_IN_COMPOSER, 'dev', 'dev'); - $shopPreparator = new ThemeInstaller(new NullIO(), $eshopRootPath, $package); + $shopPreparator = new ThemePackageInstaller(new NullIO(), $eshopRootPath, $package); $package->setExtra($composerExtras); $themeInVendor = "$rootPath/vendor/" . static::THEME_NAME_IN_COMPOSER; $shopPreparator->install($themeInVendor); diff --git a/tests/Integration/Installer/PackageInstallerTriggerTest.php b/tests/Integration/Installer/PackageInstallerTriggerTest.php index abecfd8..8422155 100644 --- a/tests/Integration/Installer/PackageInstallerTriggerTest.php +++ b/tests/Integration/Installer/PackageInstallerTriggerTest.php @@ -25,9 +25,9 @@ use Composer\Composer; use Composer\Config; use Composer\IO\NullIO; -use OxidEsales\ComposerPlugin\Installer\PackagesInstaller; +use OxidEsales\ComposerPlugin\Installer\PackageInstallerTrigger; -class PackagesInstallerTest extends \PHPUnit_Framework_TestCase +class PackageInstallerTriggerTest extends \PHPUnit_Framework_TestCase { /** * The composer.json file already in source for 5.3. @@ -38,7 +38,7 @@ public function testGetShopSourcePathByConfiguration() $composerMock = $this->getMock(Composer::class); $composerMock->method('getConfig')->withAnyParameters()->willReturn($composerConfigMock); - $packageInstallerStub = new PackagesInstaller(new NullIO(), $composerMock); + $packageInstallerStub = new PackageInstallerTrigger(new NullIO(), $composerMock); $packageInstallerStub->setSettings([ 'source-path' => 'some/path/to/source' ]); @@ -54,7 +54,7 @@ public function testGetShopSourcePathFor60() $composerMock = $this->getMock(Composer::class); $composerMock->method('getConfig')->withAnyParameters()->willReturn($composerConfigMock); - $packageInstallerStub = new PackagesInstaller(new NullIO(), $composerMock); + $packageInstallerStub = new PackageInstallerTrigger(new NullIO(), $composerMock); $result = $packageInstallerStub->getShopSourcePath(); $this->assertEquals($result, getcwd() . '/source'); From 7e62f9ccb58f83a2686012aa4ff726f795da6c2e Mon Sep 17 00:00:00 2001 From: Edvinas Aleksejonokas Date: Tue, 23 May 2017 13:02:18 +0300 Subject: [PATCH 05/13] ESDEV-4443 Refactor --- .../Package/AbstractPackageInstaller.php | 63 ++++++++++++------- .../Package/ModulePackageInstaller.php | 59 ++++++++--------- .../Package/ShopPackageInstaller.php | 27 +++++--- .../Package/ThemePackageInstaller.php | 11 ++-- src/Installer/PackageInstallerTrigger.php | 8 ++- src/Plugin.php | 12 +++- .../Package/ModulePackageInstallerTest.php | 39 +++++++----- .../Package/ShopPackageInstallerTest.php | 19 ++++-- .../Package/ThemePackageInstallerTest.php | 13 +++- 9 files changed, 156 insertions(+), 95 deletions(-) diff --git a/src/Installer/Package/AbstractPackageInstaller.php b/src/Installer/Package/AbstractPackageInstaller.php index 2158ace..9089821 100644 --- a/src/Installer/Package/AbstractPackageInstaller.php +++ b/src/Installer/Package/AbstractPackageInstaller.php @@ -63,8 +63,8 @@ abstract class AbstractPackageInstaller /** * AbstractInstaller constructor. * - * @param IOInterface $io - * @param string $rootDirectory + * @param IOInterface $io + * @param string $rootDirectory * @param PackageInterface $package */ public function __construct(IOInterface $io, $rootDirectory, PackageInterface $package) @@ -122,23 +122,31 @@ public function getPackage() return $this->package; } + /** + * @return string + */ + protected function getPackageName() + { + return $this->package->getName(); + } + /** * Search for parameter with specific key in "extra" composer configuration block * * @param string $extraParameterKey + * @param string $defaultValue + * * @return array|string|null */ - protected function getExtraParameterValueByKey($extraParameterKey) + protected function getExtraParameterValueByKey($extraParameterKey, $defaultValue = null) { - $extraParameterValue = null; - $package = $this->getPackage(); - $extraParameters = $package->getExtra(); - if (isset($extraParameters[static::EXTRA_PARAMETER_KEY_ROOT]) - && isset($extraParameters[static::EXTRA_PARAMETER_KEY_ROOT][$extraParameterKey]) - ) { - $extraParameterValue = $extraParameters[static::EXTRA_PARAMETER_KEY_ROOT][$extraParameterKey]; - } - return $extraParameterValue; + $extraParameters = $this->getPackage()->getExtra(); + + $extraParameterValue = isset($extraParameters[static::EXTRA_PARAMETER_KEY_ROOT][$extraParameterKey])? + $extraParameters[static::EXTRA_PARAMETER_KEY_ROOT][$extraParameterKey]: + null; + + return (!empty($extraParameterValue)) ? $extraParameterValue : $defaultValue; } /** @@ -148,7 +156,7 @@ protected function getExtraParameterValueByKey($extraParameterKey) */ protected function getBlacklistFilterValue() { - return $this->getExtraParameterValueByKey(static::EXTRA_PARAMETER_FILTER_BLACKLIST); + return $this->getExtraParameterValueByKey(static::EXTRA_PARAMETER_FILTER_BLACKLIST, []); } /** @@ -157,22 +165,33 @@ protected function getBlacklistFilterValue() */ protected function askQuestionIfNotInstalled($messageToAsk) { - if ($this->isInstalled()) { - return $this->askQuestion($messageToAsk); - } - return true; + return $this->isInstalled() ? $this->askQuestion($messageToAsk) : true; } /** + * Returns true if the human answer to the given question was answered with a positive value (Yes/yes/Y/y). + * * @param string $messageToAsk * @return bool */ protected function askQuestion($messageToAsk) { - $response = $this->getIO()->ask($messageToAsk, 'No'); - if ((strtolower($response) === 'yes' || strtolower($response) === 'y')) { - return true; - } - return false; + $userInput = $this->getIO()->ask($messageToAsk, 'No'); + + return $this->isPositiveUserInput($userInput); + } + + /** + * Return true if the input from user is a positive answer (Yes/yes/Y/y) + * + * @param string $userInput Raw user input + * + * @return bool + */ + private function isPositiveUserInput($userInput) + { + $positiveAnswers = ['yes', 'y']; + + return in_array(strtolower(trim($userInput)), $positiveAnswers, true); } } diff --git a/src/Installer/Package/ModulePackageInstaller.php b/src/Installer/Package/ModulePackageInstaller.php index 1554343..5b72a06 100644 --- a/src/Installer/Package/ModulePackageInstaller.php +++ b/src/Installer/Package/ModulePackageInstaller.php @@ -23,6 +23,7 @@ namespace OxidEsales\ComposerPlugin\Installer\Package; use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\CopyGlobFilteredFileManager; +use Webmozart\PathUtil\Path; /** * @inheritdoc @@ -30,13 +31,14 @@ class ModulePackageInstaller extends AbstractPackageInstaller { const METADATA_FILE_NAME = 'metadata.php'; + const MODULES_DIRECTORY = 'modules'; /** * @return bool */ public function isInstalled() { - return file_exists($this->formTargetPath() . '/' . static::METADATA_FILE_NAME . ''); + return file_exists(Path::join($this->formTargetPath(), static::METADATA_FILE_NAME)); } /** @@ -46,13 +48,8 @@ public function isInstalled() */ public function install($packagePath) { - $this->getIO()->write("Installing module {$this->getPackage()->getName()} package."); - - CopyGlobFilteredFileManager::copy( - $this->formSourcePath($packagePath), - $this->formTargetPath(), - $this->getBlacklistFilterValue() - ); + $this->getIO()->write("Installing module {$this->getPackageName()} package."); + $this->copyPackage($packagePath); } /** @@ -62,18 +59,27 @@ public function install($packagePath) */ public function update($packagePath) { - if ($this->askQuestionIfNotInstalled("Update operation will overwrite {$this->getPackage()->getName()} files." + if ($this->askQuestionIfNotInstalled("Update operation will overwrite {$this->getPackageName()} files." ." Do you want to continue? (Yes/No) ")) { - $this->getIO()->write("Copying module {$this->getPackage()->getName()} files..."); - - CopyGlobFilteredFileManager::copy( - $this->formSourcePath($packagePath), - $this->formTargetPath(), - $this->getBlacklistFilterValue() - ); + $this->getIO()->write("Copying module {$this->getPackageName()} files..."); + $this->copyPackage($packagePath); } } + /** + * Copy files from package source to defined target path. + * + * @param string $packagePath Absolute path to the package. + */ + protected function copyPackage($packagePath) + { + CopyGlobFilteredFileManager::copy( + $this->formSourcePath($packagePath), + $this->formTargetPath(), + $this->getBlacklistFilterValue() + ); + } + /** * If module source directory option provided add it's relative path. * Otherwise return plain package path. @@ -86,11 +92,9 @@ protected function formSourcePath($packagePath) { $sourceDirectory = $this->getExtraParameterValueByKey(static::EXTRA_PARAMETER_KEY_SOURCE); - if (empty($sourceDirectory)) { - return $packagePath; - } - - return $packagePath . "/$sourceDirectory"; + return !empty($sourceDirectory)? + Path::join($packagePath, $sourceDirectory): + $packagePath; } /** @@ -98,12 +102,11 @@ protected function formSourcePath($packagePath) */ protected function formTargetPath() { - $package = $this->getPackage(); - $targetDirectory = $this->getExtraParameterValueByKey(static::EXTRA_PARAMETER_KEY_TARGET); - if (is_null($targetDirectory)) { - $targetDirectory = $package->getName(); - } - $targetDirectory = $this->getRootDirectory() . "/modules/$targetDirectory"; - return $targetDirectory; + $targetDirectory = $this->getExtraParameterValueByKey( + static::EXTRA_PARAMETER_KEY_TARGET, + $this->getPackage()->getName() + ); + + return Path::join($this->getRootDirectory(), static::MODULES_DIRECTORY, $targetDirectory); } } diff --git a/src/Installer/Package/ShopPackageInstaller.php b/src/Installer/Package/ShopPackageInstaller.php index 558ae2f..e0e6681 100644 --- a/src/Installer/Package/ShopPackageInstaller.php +++ b/src/Installer/Package/ShopPackageInstaller.php @@ -23,18 +23,25 @@ namespace OxidEsales\ComposerPlugin\Installer\Package; use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\CopyGlobFilteredFileManager; +use Webmozart\PathUtil\Path; /** * @inheritdoc */ class ShopPackageInstaller extends AbstractPackageInstaller { + const FILE_TO_CHECK_IF_PACKAGE_INSTALLED = 'index.php'; + const SHOP_SOURCE_CONFIGURATION_FILE = 'config.inc.php'; + const DISTRIBUTION_FILE_EXTENSION_MARK = '.dist'; + const SHOP_SOURCE_DIRECTORY = 'source'; + const SHOP_SOURCE_SETUP_DIRECTORY = 'Setup'; + /** * @return bool */ public function isInstalled() { - return file_exists($this->getRootDirectory() .'/index.php'); + return file_exists(Path::join($this->getRootDirectory(), self::FILE_TO_CHECK_IF_PACKAGE_INSTALLED)); } /** @@ -45,7 +52,7 @@ public function isInstalled() public function install($packagePath) { $this->getIO()->write("Installing shop package."); - $this->copyFiles($packagePath); + $this->copyPackage($packagePath); } /** @@ -58,16 +65,16 @@ public function update($packagePath) $this->getIO()->write("Installing shop package."); if ($this->askQuestionIfNotInstalled('Do you want to overwrite existing OXID eShop files? (Yes/No) ')) { $this->getIO()->write("Copying shop files to source directory..."); - $this->copyFiles($packagePath); + $this->copyPackage($packagePath); } } /** * @param $packagePath */ - protected function copyFiles($packagePath) + protected function copyPackage($packagePath) { - $packagePath = rtrim($packagePath, '/') . '/source'; + $packagePath = Path::join($packagePath, self::SHOP_SOURCE_DIRECTORY); $root = $this->getRootDirectory(); CopyGlobFilteredFileManager::copy( @@ -76,11 +83,11 @@ protected function copyFiles($packagePath) $this->getBlacklistFilterValue() ); - if (file_exists($root.'/config.inc.php.dist') && !file_exists($root.'/config.inc.php')) { - CopyGlobFilteredFileManager::copy( - $root.'/config.inc.php.dist', - $root.'/config.inc.php' - ); + $pathToConfig = Path::join($root, self::SHOP_SOURCE_CONFIGURATION_FILE); + $pathToConfigDist = $pathToConfig . self::DISTRIBUTION_FILE_EXTENSION_MARK; + + if (!file_exists($pathToConfig)) { + CopyGlobFilteredFileManager::copy($pathToConfigDist, $pathToConfig); } } } diff --git a/src/Installer/Package/ThemePackageInstaller.php b/src/Installer/Package/ThemePackageInstaller.php index 13d4bec..0d27d19 100644 --- a/src/Installer/Package/ThemePackageInstaller.php +++ b/src/Installer/Package/ThemePackageInstaller.php @@ -24,6 +24,7 @@ use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\CopyGlobFilteredFileManager; use Webmozart\PathUtil\Path; +use Composer\Package\PackageInterface; /** * @inheritdoc @@ -49,7 +50,7 @@ public function isInstalled() public function install($packagePath) { $this->getIO()->write("Installing {$this->getPackage()->getName()} package"); - $this->copyFiles($packagePath); + $this->copyPackage($packagePath); } /** @@ -62,14 +63,14 @@ public function update($packagePath) if ($this->askQuestionIfNotInstalled("Update operation will overwrite {$this->getPackage()->getName()} files." ." Do you want to continue? (Yes/No) ")) { $this->getIO()->write("Copying theme {$this->getPackage()->getName()} files..."); - $this->copyFiles($packagePath); + $this->copyPackage($packagePath); } } /** * @param string $packagePath */ - protected function copyFiles($packagePath) + protected function copyPackage($packagePath) { $filter = [Path::join($this->formAssetsDirectoryName(), AbstractPackageInstaller::BLACKLIST_ALL_FILES)]; $filterFromExtras = $this->getBlacklistFilterValue(); @@ -118,8 +119,8 @@ protected function installAssets($packagePath) } /** - * @param $package - * @return mixed + * @param PackageInterface $package + * @return string */ protected function formThemeDirectoryName($package) { diff --git a/src/Installer/PackageInstallerTrigger.php b/src/Installer/PackageInstallerTrigger.php index 2520d0f..ca20ef7 100644 --- a/src/Installer/PackageInstallerTrigger.php +++ b/src/Installer/PackageInstallerTrigger.php @@ -28,6 +28,7 @@ use OxidEsales\ComposerPlugin\Installer\Package\ShopPackageInstaller; use OxidEsales\ComposerPlugin\Installer\Package\ModulePackageInstaller; use OxidEsales\ComposerPlugin\Installer\Package\ThemePackageInstaller; +use Webmozart\PathUtil\Path; /** * Class responsible for triggering installation process. @@ -63,7 +64,7 @@ public function supports($packageType) } /** - * @param array set additional settings + * @param array $settings Set additional settings. */ public function setSettings($settings) { @@ -81,6 +82,9 @@ public function installPackage(PackageInterface $package) } } + /** + * @param PackageInterface $package + */ public function updatePackage(PackageInterface $package) { $installer = $this->createInstaller($package); @@ -94,7 +98,7 @@ public function updatePackage(PackageInterface $package) */ public function getShopSourcePath() { - $shopSource = getcwd() . '/source'; + $shopSource = Path::join(getcwd(), ShopPackageInstaller::SHOP_SOURCE_DIRECTORY); if (isset($this->settings[AbstractPackageInstaller::EXTRA_PARAMETER_SOURCE_PATH])) { $shopSource = $this->settings[AbstractPackageInstaller::EXTRA_PARAMETER_SOURCE_PATH]; diff --git a/src/Plugin.php b/src/Plugin.php index d9ce20d..0f06bd4 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -29,6 +29,9 @@ use OxidEsales\ComposerPlugin\Installer\Package\AbstractPackageInstaller; use OxidEsales\ComposerPlugin\Installer\PackageInstallerTrigger; +/** + * Class Plugin. + */ class Plugin implements PluginInterface, EventSubscriberInterface { const ACTION_INSTALL = 'install'; @@ -65,12 +68,12 @@ public static function getSubscribedEvents() */ public function activate(Composer $composer, IOInterface $io) { - $installer = new PackageInstallerTrigger($io, $composer); - $composer->getInstallationManager()->addInstaller($installer); + $packageInstallerTrigger = new PackageInstallerTrigger($io, $composer); + $composer->getInstallationManager()->addInstaller($packageInstallerTrigger); $this->composer = $composer; $this->io = $io; - $this->packageInstallerTrigger = $installer; + $this->packageInstallerTrigger = $packageInstallerTrigger; $extraSettings = $this->composer->getPackage()->getExtra(); if (isset($extraSettings[AbstractPackageInstaller::EXTRA_PARAMETER_KEY_ROOT])) { @@ -94,6 +97,9 @@ public function updatePackages() $this->executeAction(static::ACTION_UPDATE); } + /** + * @param string $actionName + */ protected function executeAction($actionName) { $repo = $this->composer->getRepositoryManager()->getLocalRepository(); diff --git a/tests/Integration/Installer/Package/ModulePackageInstallerTest.php b/tests/Integration/Installer/Package/ModulePackageInstallerTest.php index a165c78..80df2ab 100644 --- a/tests/Integration/Installer/Package/ModulePackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ModulePackageInstallerTest.php @@ -22,8 +22,10 @@ namespace OxidEsales\ComposerPlugin\Tests\Integration\Installer\Package; +use Composer\IO\IOInterface; use Composer\IO\NullIO; use Composer\Package\Package; +use Composer\Package\PackageInterface; use OxidEsales\ComposerPlugin\Installer\Package\ModulePackageInstaller; use org\bovigo\vfs\vfsStream; use OxidEsales\ComposerPlugin\Tests\Integration\Installer\StructurePreparator; @@ -33,6 +35,11 @@ class ModulePackageInstallerTest extends \PHPUnit_Framework_TestCase { const PRODUCT_NAME_IN_COMPOSER_FILE = "oxid-esales/paypal-module"; + protected function getSut(IOInterface $io, $rootPath, PackageInterface $package) + { + return new ModulePackageInstaller($io, $rootPath, $package); + } + public function testChecksIfModuleIsNotInstalled() { $structure = [ @@ -41,7 +48,7 @@ public function testChecksIfModuleIsNotInstalled() vfsStream::setup('root', 777, ['projectRoot' => $this->getStructurePreparator()->prepareStructure($structure)]); $rootPath = vfsStream::url('root/projectRoot/source'); - $shopPreparator = new ModulePackageInstaller(new NullIO, $rootPath, new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev')); + $shopPreparator = $this->getSut(new NullIO, $rootPath, new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev')); $this->assertFalse($shopPreparator->isInstalled()); } @@ -54,7 +61,7 @@ public function testChecksIfModuleIsInstalled() vfsStream::setup('root', 777, ['projectRoot' => $this->getStructurePreparator()->prepareStructure($structure)]); $rootPath = vfsStream::url('root/projectRoot/source'); - $shopPreparator = new ModulePackageInstaller(new NullIO, $rootPath, new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev')); + $shopPreparator = $this->getSut(new NullIO, $rootPath, new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev')); $this->assertTrue($shopPreparator->isInstalled()); } @@ -70,7 +77,7 @@ public function providerChecksIfModuleFilesExistsAfterInstallation() /** * @param $composerExtras * @param $installedModuleMetadata - * + * * @dataProvider providerChecksIfModuleFilesExistsAfterInstallation */ public function testChecksIfModuleFilesExistsAfterInstallation($composerExtras, $installedModuleMetadata) @@ -87,7 +94,7 @@ public function testChecksIfModuleFilesExistsAfterInstallation($composerExtras, $installedModuleMetadata = "$eshopRootPath/$installedModuleMetadata"; $package = new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev'); - $shopPreparator = new ModulePackageInstaller(new NullIO(), $eshopRootPath, $package); + $shopPreparator = $this->getSut(new NullIO(), $eshopRootPath, $package); $package->setExtra($composerExtras); $moduleInVendor = "$rootPath/vendor/" . static::PRODUCT_NAME_IN_COMPOSER_FILE . ""; $shopPreparator->install($moduleInVendor); @@ -109,7 +116,7 @@ public function testCheckIfModuleIsInstalledFromProvidedSourceDirectory() $installedModuleMetadata = "$eshopRootPath/modules/erp/metadata.php"; $package = new Package('oxid-esales/erp', 'dev', 'dev'); - $shopPreparator = new ModulePackageInstaller(new NullIO(), $eshopRootPath, $package); + $shopPreparator = $this->getSut(new NullIO(), $eshopRootPath, $package); $package->setExtra( [ModulePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ ModulePackageInstaller::EXTRA_PARAMETER_KEY_SOURCE => 'copy_this/modules/erp', @@ -152,8 +159,8 @@ public function testBlacklistedFilesArePresentWhenNoBlacklistFilterIsDefined() $moduleSourcePath = Path::join($rootPath, 'vendor', 'test-vendor', 'test-package'); $package = new Package('test-vendor/test-package', 'dev', 'dev'); - $moduleInstaller = new ModulePackageInstaller(new NullIO(), $shopRootPath, $package); - $moduleInstaller->install($moduleSourcePath); + $sut = $this->getSut(new NullIO(), $shopRootPath, $package); + $sut->install($moduleSourcePath); $this->assertFileExists(Path::join($installedModulePath, 'metadata.php')); $this->assertFileExists(Path::join($installedModulePath, 'module.php')); @@ -183,12 +190,12 @@ public function testBlacklistedFilesArePresentWhenEmptyBlacklistFilterIsDefined( $package = new Package('test-vendor/test-package', 'dev', 'dev'); $package->setExtra([ - 'oxideshop' => [ - 'blacklist-filter' => [], - ] + 'oxideshop' => [ + 'blacklist-filter' => [], + ] ]); - $moduleInstaller = new ModulePackageInstaller(new NullIO(), $shopRootPath, $package); - $moduleInstaller->install($moduleSourcePath); + $sut = $this->getSut(new NullIO(), $shopRootPath, $package); + $sut->install($moduleSourcePath); $this->assertFileExists(Path::join($installedModulePath, 'metadata.php')); $this->assertFileExists(Path::join($installedModulePath, 'module.php')); @@ -224,8 +231,8 @@ public function testBlacklistedFilesArePresentWhenDifferentBlacklistFilterIsDefi ], ] ]); - $moduleInstaller = new ModulePackageInstaller(new NullIO(), $shopRootPath, $package); - $moduleInstaller->install($moduleSourcePath); + $sut = $this->getSut(new NullIO(), $shopRootPath, $package); + $sut->install($moduleSourcePath); $this->assertFileExists(Path::join($installedModulePath, 'metadata.php')); $this->assertFileExists(Path::join($installedModulePath, 'module.php')); @@ -261,8 +268,8 @@ public function testBlacklistedFilesAreSkippedWhenABlacklistFilterIsDefined() ], ] ]); - $moduleInstaller = new ModulePackageInstaller(new NullIO(), $shopRootPath, $package); - $moduleInstaller->install($moduleSourcePath); + $sut = $this->getSut(new NullIO(), $shopRootPath, $package); + $sut->install($moduleSourcePath); $this->assertFileExists(Path::join($installedModulePath, 'metadata.php')); $this->assertFileExists(Path::join($installedModulePath, 'module.php')); diff --git a/tests/Integration/Installer/Package/ShopPackageInstallerTest.php b/tests/Integration/Installer/Package/ShopPackageInstallerTest.php index 73496e4..b4d702e 100644 --- a/tests/Integration/Installer/Package/ShopPackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ShopPackageInstallerTest.php @@ -22,8 +22,10 @@ namespace OxidEsales\ComposerPlugin\Tests\Integration\Installer\Package; +use Composer\IO\IOInterface; use Composer\IO\NullIO; use Composer\Package\Package; +use Composer\Package\PackageInterface; use OxidEsales\ComposerPlugin\Installer\Package\ShopPackageInstaller; use org\bovigo\vfs\vfsStream; use OxidEsales\ComposerPlugin\Tests\Integration\Installer\StructurePreparator; @@ -31,6 +33,11 @@ class ShopPackageInstallerTest extends \PHPUnit_Framework_TestCase { + protected function getSut(IOInterface $io, $rootPath, PackageInterface $package) + { + return new ShopPackageInstaller($io, $rootPath, $package); + } + public function testChecksIfPackageIsNotInstalled() { $structure = [ @@ -39,7 +46,7 @@ public function testChecksIfPackageIsNotInstalled() vfsStream::setup('root', 777, ['projectRoot' => $this->getStructurePreparator()->prepareStructure($structure)]); $rootPath = vfsStream::url('root/projectRoot/source'); - $shopPreparator = new ShopPackageInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); + $shopPreparator = $this->getSut(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); $this->assertFalse($shopPreparator->isInstalled()); } @@ -54,7 +61,7 @@ public function testChecksIfPackageInstalled() vfsStream::setup('root', 777, ['projectRoot' => $this->getStructurePreparator()->prepareStructure($structure)]); $rootPath = vfsStream::url('root/projectRoot/source'); - $shopPreparator = new ShopPackageInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); + $shopPreparator = $this->getSut(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); $this->assertTrue($shopPreparator->isInstalled()); } @@ -72,7 +79,7 @@ public function testInstallationOfPackage() $rootPath = vfsStream::url('root/projectRoot/source'); $shopDirectory = "$rootPath/vendor/oxideshop_ce"; - $shopPreparator = new ShopPackageInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); + $shopPreparator = $this->getSut(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); $shopPreparator->install($shopDirectory); $this->assertFileExists($rootPath . '/index.php'); @@ -92,7 +99,7 @@ public function testInstallCreatesConfigInc() $rootPath = vfsStream::url('root/projectRoot/source'); $shopDirectory = "$rootPath/vendor/oxideshop_ce"; - $shopPreparator = new ShopPackageInstaller(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); + $shopPreparator = $this->getSut(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); $shopPreparator->install($shopDirectory); $this->assertFileExists($rootPath . '/config.inc.php'); @@ -140,8 +147,8 @@ public function testInstallDoesNotCopyClasses() ] ]); - $shopPreparator = new ShopPackageInstaller(new NullIO, $rootPath, $package); - $shopPreparator->install($shopDirectory); + $sut = $this->getSut(new NullIO, $rootPath, $package); + $sut->install($shopDirectory); $this->assertFileExists(Path::join($rootPath, 'Class.php')); $this->assertFileNotExists(Path::join($rootPath, 'Core')); diff --git a/tests/Integration/Installer/Package/ThemePackageInstallerTest.php b/tests/Integration/Installer/Package/ThemePackageInstallerTest.php index 7c68f63..dc86e90 100644 --- a/tests/Integration/Installer/Package/ThemePackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ThemePackageInstallerTest.php @@ -22,8 +22,10 @@ namespace OxidEsales\ComposerPlugin\Tests\Integration\Installer\Package; +use Composer\IO\IOInterface; use Composer\IO\NullIO; use Composer\Package\Package; +use Composer\Package\PackageInterface; use org\bovigo\vfs\vfsStream; use OxidEsales\ComposerPlugin\Installer\Package\ThemePackageInstaller; use OxidEsales\ComposerPlugin\Tests\Integration\Installer\StructurePreparator; @@ -33,6 +35,11 @@ class ThemePackageInstallerTest extends \PHPUnit_Framework_TestCase { const THEME_NAME_IN_COMPOSER = "oxid-esales/flow-theme"; + protected function getSut(IOInterface $io, $rootPath, PackageInterface $package) + { + return new ThemePackageInstaller($io, $rootPath, $package); + } + public function testChecksIfThemeIsNotInstalled() { $structure = [ @@ -42,7 +49,7 @@ public function testChecksIfThemeIsNotInstalled() $rootPath = vfsStream::url('root/projectRoot/source'); $package = new Package(static::THEME_NAME_IN_COMPOSER, 'dev', 'dev'); - $themeInstaller = new ThemePackageInstaller(new NullIO, $rootPath, $package); + $themeInstaller = $this->getSut(new NullIO, $rootPath, $package); $this->assertFalse($themeInstaller->isInstalled()); } @@ -56,7 +63,7 @@ public function testChecksIfThemeIsInstalled() $rootPath = vfsStream::url('root/projectRoot/source'); $package = new Package(static::THEME_NAME_IN_COMPOSER, 'dev', 'dev'); - $shopPreparator = new ThemePackageInstaller(new NullIO(), $rootPath, $package); + $shopPreparator = $this->getSut(new NullIO(), $rootPath, $package); $this->assertTrue($shopPreparator->isInstalled()); } @@ -173,7 +180,7 @@ protected function simulateInstallation($composerExtras, $rootPath, $eshopRootPa vfsStream::setup('root', 777, ['projectRoot' => $structure]); $package = new Package(static::THEME_NAME_IN_COMPOSER, 'dev', 'dev'); - $shopPreparator = new ThemePackageInstaller(new NullIO(), $eshopRootPath, $package); + $shopPreparator = $this->getSut(new NullIO(), $eshopRootPath, $package); $package->setExtra($composerExtras); $themeInVendor = "$rootPath/vendor/" . static::THEME_NAME_IN_COMPOSER; $shopPreparator->install($themeInVendor); From c6c82ce2d715e7024cf044d77dda2ab1c9734c0a Mon Sep 17 00:00:00 2001 From: Edvinas Aleksejonokas Date: Fri, 26 May 2017 13:26:43 +0300 Subject: [PATCH 06/13] ESDEV-4443 Add VfsFileStructureOperator --- src/Utilities/VfsFileStructureOperator.php | 76 +++++ .../VfsFileStructureOperatorTest.php | 265 ++++++++++++++++++ 2 files changed, 341 insertions(+) create mode 100644 src/Utilities/VfsFileStructureOperator.php create mode 100644 tests/Unit/Utilities/VfsFileStructureOperatorTest.php diff --git a/src/Utilities/VfsFileStructureOperator.php b/src/Utilities/VfsFileStructureOperator.php new file mode 100644 index 0000000..3b72d06 --- /dev/null +++ b/src/Utilities/VfsFileStructureOperator.php @@ -0,0 +1,76 @@ +. + * + * @link http://www.oxid-esales.com + * @copyright (C) OXID eSales AG 2003-2016 + * @version OXID eShop Composer plugin + */ + +namespace OxidEsales\ComposerPlugin\Utilities; + +/** + * Class VfsFileStructureOperator. + */ +class VfsFileStructureOperator +{ + /** + * Convert given flat file system structure into nested one. + * + * @param array|null $flatFileSystemStructure + * + * @return array + */ + public static function nest($flatFileSystemStructure = null) + { + if (!is_null($flatFileSystemStructure) && !is_array($flatFileSystemStructure)) { + throw new \InvalidArgumentException("Given input argument must be an array."); + } + + if (is_null($flatFileSystemStructure)) { + return []; + } + + $nestedFileSystemStructure = []; + + foreach ($flatFileSystemStructure as $pathEntry => $contents) { + $pathEntries = explode(DIRECTORY_SEPARATOR, $pathEntry); + + $pointerToBranch = &$nestedFileSystemStructure; + foreach ($pathEntries as $singlePathEntry) { + $singlePathEntry = trim($singlePathEntry); + + if ($singlePathEntry !== '') { + if (!is_array($pointerToBranch)) { + $pointerToBranch = []; + } + + if (!key_exists($singlePathEntry, $pointerToBranch)) { + $pointerToBranch[$singlePathEntry] = []; + } + + $pointerToBranch = &$pointerToBranch[$singlePathEntry]; + } + } + + if (substr($pathEntry, -1) !== DIRECTORY_SEPARATOR) { + $pointerToBranch = $contents; + } + } + + return $nestedFileSystemStructure; + } +} diff --git a/tests/Unit/Utilities/VfsFileStructureOperatorTest.php b/tests/Unit/Utilities/VfsFileStructureOperatorTest.php new file mode 100644 index 0000000..133acaf --- /dev/null +++ b/tests/Unit/Utilities/VfsFileStructureOperatorTest.php @@ -0,0 +1,265 @@ +. + * + * @link http://www.oxid-esales.com + * @copyright (C) OXID eSales AG 2003-2016 + * @version OXID eShop Composer plugin + */ + +namespace OxidEsales\ComposerPlugin\Tests\Unit\Utilities; + +use OxidEsales\ComposerPlugin\Utilities\VfsFileStructureOperator; + +/** + * Class FileStructureOperatorTest. + */ +class VfsFileStructureOperatorTest extends \PHPUnit_Framework_TestCase +{ + public function testReturnEmptyListWhenNoInputIsProvided() + { + $this->assertSame([], VfsFileStructureOperator::nest()); + } + + public function testReturnEmptyListWhenNullInputIsProvided() + { + $this->assertSame([], VfsFileStructureOperator::nest(null)); + } + + public function testReturnEmptyListWhenEmptyInputArrayIsProvided() + { + $this->assertSame([], VfsFileStructureOperator::nest([])); + } + + public function testThrowAnExceptionIfInputIsNotAnArray() + { + $this->setExpectedException(\InvalidArgumentException::class, "Given input argument must be an array."); + VfsFileStructureOperator::nest(1); + } + + public function testReturnArrayAsIsWhenOnlyItemIsPresent() + { + $this->assertSame(['abc'], VfsFileStructureOperator::nest(['abc'])); + } + + public function testReturnArrayAsIsWhenMultipleItemsArePresent() + { + $this->assertSame(['abc', 'def'], VfsFileStructureOperator::nest(['abc', 'def'])); + } + + public function testReturnArrayAsIsWhenOnlyOneFileIsPresent() + { + $input = [ + 'file' => 'Contents' + ]; + + $this->assertSame($input, VfsFileStructureOperator::nest($input)); + } + + public function testReturnArrayAsIsWhenOnlyOneFileIsPresentIgnoringSpacesAtBeginningAndEnd() + { + $input = [ + ' file ' => 'Contents' + ]; + + $expectedOutput = [ + 'file' => 'Contents' + ]; + + $this->assertSame($expectedOutput, VfsFileStructureOperator::nest($input)); + } + + public function testReturnArrayAsIsWhenMultipleFilesArePresent() + { + $input = [ + 'file' => 'Contents', + 'second_file' => 'Second Contents' + ]; + + $this->assertSame($input, VfsFileStructureOperator::nest($input)); + } + + public function testReturnArrayWithSingleItemWhenSameMultipleFilesArePresentLastOneBeingAsOverrider() + { + $input = [ + 'file' => 'Contents', + ' file ' => 'Second Contents' + ]; + + $expectedOutput = [ + 'file' => 'Second Contents', + ]; + + $this->assertSame($expectedOutput, VfsFileStructureOperator::nest($input)); + } + + public function testReturnNestedArrayWhenSingleItemContainsMultiLevelPath() + { + $input = [ + 'directory/file' => 'contents' + ]; + + $expectedOutput = [ + 'directory' => [ + 'file' => 'contents' + ] + ]; + + $this->assertSame($expectedOutput, VfsFileStructureOperator::nest($input)); + } + + public function testReturnNestedArrayWhenLastItemContainsMultiLevelPath() + { + $input = [ + 'directory/fake_file' => 'contents', + 'directory/fake_file/real_file' => 'real contents', + ]; + + $expectedOutput = [ + 'directory' => [ + 'fake_file' => [ + 'real_file' => 'real contents' + ] + ] + ]; + + $this->assertSame($expectedOutput, VfsFileStructureOperator::nest($input)); + } + + public function testReturnNestedArrayWhenSingleItemContainsMultiLevelPathWithTrailingSlash() + { + $input = [ + 'directory/sub/' => 'contents' + ]; + + $expectedOutput = [ + 'directory' => [ + 'sub' => [] + ] + ]; + + $this->assertSame($expectedOutput, VfsFileStructureOperator::nest($input)); + } + + public function testReturnNestedArrayWhenMultipleItemsContainsMultiLevelPathWithSameBase() + { + $input = [ + 'directory/file' => 'contents', + 'directory/second_file' => 'second contents', + ]; + + $expectedOutput = [ + 'directory' => [ + 'file' => 'contents', + 'second_file' => 'second contents', + ] + ]; + + $this->assertSame($expectedOutput, VfsFileStructureOperator::nest($input)); + } + + public function testReturnNestedArrayWhenMultipleItemsContainsMultiLevelPathWithSameBaseButWithBreakPointInTheMiddle() + { + $input = [ + 'directory/file' => 'contents', + 'directory_a/file' => 'a contents', + 'directory/second_file' => 'second contents', + ]; + + $expectedOutput = [ + 'directory' => [ + 'file' => 'contents', + 'second_file' => 'second contents', + ], + 'directory_a' => [ + 'file' => 'a contents', + ] + ]; + + $this->assertSame($expectedOutput, VfsFileStructureOperator::nest($input)); + } + + public function testReturnNestedArrayWhenSingleItemContainsMultiLevelPathMoreThenOneLevelDeep() + { + $input = [ + 'directory/another_directory/file' => 'contents' + ]; + + $expectedOutput = [ + 'directory' => [ + 'another_directory' => [ + 'file' => 'contents' + ] + ] + ]; + + $this->assertSame($expectedOutput, VfsFileStructureOperator::nest($input)); + } + + public function testReturnNestedArrayWhenMultipleItemsContainsMultiLevelPathWithDifferentBase() + { + $input = [ + 'directory/file' => 'contents', + 'second_directory/second_file' => 'second contents', + ]; + + $expectedOutput = [ + 'directory' => [ + 'file' => 'contents', + ], + 'second_directory' => [ + 'second_file' => 'second contents', + ] + ]; + + $this->assertSame($expectedOutput, VfsFileStructureOperator::nest($input)); + } + + public function testReturnNestedArrayWhenComplexCasePresented() + { + $input = [ + 'file' => 'contents', + 'directory/file' => 'second contents', + 'directory_a/directory_b/directory_c/file' => 'third contents', + 'directory/file_b' => 'b contents', + ' file_c ' => 'c contents', + ' file_c ' => 'c override contents', + 'fake_file' => 'fake contents', + 'fake_file/real_file' => 'real contents', + ]; + + $expectedOutput = [ + 'file' => 'contents', + 'directory' => [ + 'file' => 'second contents', + 'file_b' => 'b contents', + ], + 'directory_a' => [ + 'directory_b' => [ + 'directory_c' => [ + 'file' => 'third contents', + ] + ] + ], + 'file_c' => 'c override contents', + 'fake_file' => [ + 'real_file' => 'real contents', + ] + ]; + + $this->assertSame($expectedOutput, VfsFileStructureOperator::nest($input)); + } +} From 327c26877cf6fde0c69769cf66227c9d158294d4 Mon Sep 17 00:00:00 2001 From: Edvinas Aleksejonokas Date: Fri, 26 May 2017 13:38:21 +0300 Subject: [PATCH 07/13] ESDEV-4443 Integrate VfsFileStructureOperator Why this integration took place? * Previous `StructurePreparator` was able to handle only one file entry per given directory path; * Previous `StructurePreparator` was not covered with tests. --- .../Package/ModulePackageInstallerTest.php | 128 ++++++------------ .../Package/ShopPackageInstallerTest.php | 82 ++++------- .../Package/ThemePackageInstallerTest.php | 69 +++------- .../Installer/StructurePreparator.php | 49 ------- 4 files changed, 86 insertions(+), 242 deletions(-) delete mode 100644 tests/Integration/Installer/StructurePreparator.php diff --git a/tests/Integration/Installer/Package/ModulePackageInstallerTest.php b/tests/Integration/Installer/Package/ModulePackageInstallerTest.php index 80df2ab..bb72288 100644 --- a/tests/Integration/Installer/Package/ModulePackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ModulePackageInstallerTest.php @@ -27,14 +27,12 @@ use Composer\Package\Package; use Composer\Package\PackageInterface; use OxidEsales\ComposerPlugin\Installer\Package\ModulePackageInstaller; +use OxidEsales\ComposerPlugin\Utilities\VfsFileStructureOperator; use org\bovigo\vfs\vfsStream; -use OxidEsales\ComposerPlugin\Tests\Integration\Installer\StructurePreparator; use Webmozart\PathUtil\Path; class ModulePackageInstallerTest extends \PHPUnit_Framework_TestCase { - const PRODUCT_NAME_IN_COMPOSER_FILE = "oxid-esales/paypal-module"; - protected function getSut(IOInterface $io, $rootPath, PackageInterface $package) { return new ModulePackageInstaller($io, $rootPath, $package); @@ -42,26 +40,26 @@ protected function getSut(IOInterface $io, $rootPath, PackageInterface $package) public function testChecksIfModuleIsNotInstalled() { - $structure = [ - 'vendor/'.static::PRODUCT_NAME_IN_COMPOSER_FILE.'/metadata.php' => ' $this->getStructurePreparator()->prepareStructure($structure)]); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/oxid-esales/paypal-module/metadata.php' => 'getSut(new NullIO, $rootPath, new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev')); + $shopPreparator = $this->getSut(new NullIO, $rootPath, new Package('oxid-esales/paypal-module', 'dev', 'dev')); $this->assertFalse($shopPreparator->isInstalled()); } public function testChecksIfModuleIsInstalled() { - $structure = [ - 'source/modules/oxid-esales/paypal-module/metadata.php' => ' ' $this->getStructurePreparator()->prepareStructure($structure)]); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/source/modules/oxid-esales/paypal-module/metadata.php' => ' 'getSut(new NullIO, $rootPath, new Package(static::PRODUCT_NAME_IN_COMPOSER_FILE, 'dev', 'dev')); + $shopPreparator = $this->getSut(new NullIO, $rootPath, new Package('oxid-esales/paypal-module', 'dev', 'dev')); $this->assertTrue($shopPreparator->isInstalled()); } @@ -82,21 +80,18 @@ public function providerChecksIfModuleFilesExistsAfterInstallation() */ public function testChecksIfModuleFilesExistsAfterInstallation($composerExtras, $installedModuleMetadata) { - $structure = [ - 'vendor/oxid-esales/paypal-module' => [ - 'metadata.php' => ' $this->getStructurePreparator()->prepareStructure($structure)]); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/oxid-esales/paypal-module/metadata.php' => 'getSut(new NullIO(), $eshopRootPath, $package); $package->setExtra($composerExtras); - $moduleInVendor = "$rootPath/vendor/" . static::PRODUCT_NAME_IN_COMPOSER_FILE . ""; + $moduleInVendor = "$rootPath/vendor/oxid-esales/paypal-module"; $shopPreparator->install($moduleInVendor); $this->assertFileExists($installedModuleMetadata); @@ -104,12 +99,9 @@ public function testChecksIfModuleFilesExistsAfterInstallation($composerExtras, public function testCheckIfModuleIsInstalledFromProvidedSourceDirectory() { - $structure = [ - 'vendor/oxid-esales/erp/copy_this/modules/erp' => [ - 'metadata.php' => ' $this->getStructurePreparator()->prepareStructure($structure)]); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/oxid-esales/erp/copy_this/modules/erp/metadata.php' => 'assertFileExists($installedModuleMetadata); } - /** - * @return StructurePreparator - */ - public function getStructurePreparator() - { - return new StructurePreparator(); - } - public function testBlacklistedFilesArePresentWhenNoBlacklistFilterIsDefined() { - $structure = [ - 'vendor' => [ - 'test-vendor' => [ - 'test-package' => [ - 'metadata.php' => 'meta data', - 'module.php' => 'module', - 'readme.txt' => 'readme', - ] - ] - ] - ]; - - vfsStream::setup('root', 777, ['projectRoot' => $structure]); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/test-vendor/test-package/metadata.php' => 'meta data', + 'projectRoot/vendor/test-vendor/test-package/module.php' => 'module', + 'projectRoot/vendor/test-vendor/test-package/readme.txt' => 'readme', + ])); $rootPath = vfsStream::url('root/projectRoot'); $shopRootPath = Path::join($rootPath, 'source'); @@ -169,19 +145,11 @@ public function testBlacklistedFilesArePresentWhenNoBlacklistFilterIsDefined() public function testBlacklistedFilesArePresentWhenEmptyBlacklistFilterIsDefined() { - $structure = [ - 'vendor' => [ - 'test-vendor' => [ - 'test-package' => [ - 'metadata.php' => 'meta data', - 'module.php' => 'module', - 'readme.txt' => 'readme', - ] - ] - ] - ]; - - vfsStream::setup('root', 777, ['projectRoot' => $structure]); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/test-vendor/test-package/metadata.php' => 'meta data', + 'projectRoot/vendor/test-vendor/test-package/module.php' => 'module', + 'projectRoot/vendor/test-vendor/test-package/readme.txt' => 'readme', + ])); $rootPath = vfsStream::url('root/projectRoot'); $shopRootPath = Path::join($rootPath, 'source'); @@ -204,19 +172,11 @@ public function testBlacklistedFilesArePresentWhenEmptyBlacklistFilterIsDefined( public function testBlacklistedFilesArePresentWhenDifferentBlacklistFilterIsDefined() { - $structure = [ - 'vendor' => [ - 'test-vendor' => [ - 'test-package' => [ - 'metadata.php' => 'meta data', - 'module.php' => 'module', - 'readme.txt' => 'readme', - ] - ] - ] - ]; - - vfsStream::setup('root', 777, ['projectRoot' => $structure]); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/test-vendor/test-package/metadata.php' => 'meta data', + 'projectRoot/vendor/test-vendor/test-package/module.php' => 'module', + 'projectRoot/vendor/test-vendor/test-package/readme.txt' => 'readme', + ])); $rootPath = vfsStream::url('root/projectRoot'); $shopRootPath = Path::join($rootPath, 'source'); @@ -241,19 +201,11 @@ public function testBlacklistedFilesArePresentWhenDifferentBlacklistFilterIsDefi public function testBlacklistedFilesAreSkippedWhenABlacklistFilterIsDefined() { - $structure = [ - 'vendor' => [ - 'test-vendor' => [ - 'test-package' => [ - 'metadata.php' => 'meta data', - 'module.php' => 'module', - 'readme.txt' => 'readme', - ] - ] - ] - ]; - - vfsStream::setup('root', 777, ['projectRoot' => $structure]); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/test-vendor/test-package/metadata.php' => 'meta data', + 'projectRoot/vendor/test-vendor/test-package/module.php' => 'module', + 'projectRoot/vendor/test-vendor/test-package/readme.txt' => 'readme', + ])); $rootPath = vfsStream::url('root/projectRoot'); $shopRootPath = Path::join($rootPath, 'source'); diff --git a/tests/Integration/Installer/Package/ShopPackageInstallerTest.php b/tests/Integration/Installer/Package/ShopPackageInstallerTest.php index b4d702e..5e9eeca 100644 --- a/tests/Integration/Installer/Package/ShopPackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ShopPackageInstallerTest.php @@ -27,8 +27,8 @@ use Composer\Package\Package; use Composer\Package\PackageInterface; use OxidEsales\ComposerPlugin\Installer\Package\ShopPackageInstaller; +use OxidEsales\ComposerPlugin\Utilities\VfsFileStructureOperator; use org\bovigo\vfs\vfsStream; -use OxidEsales\ComposerPlugin\Tests\Integration\Installer\StructurePreparator; use Webmozart\PathUtil\Path; class ShopPackageInstallerTest extends \PHPUnit_Framework_TestCase @@ -40,10 +40,10 @@ protected function getSut(IOInterface $io, $rootPath, PackageInterface $package) public function testChecksIfPackageIsNotInstalled() { - $structure = [ - 'source/vendor/oxideshop_ce/source/index.php' => ' $this->getStructurePreparator()->prepareStructure($structure)]); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/source/vendor/oxideshop_ce/source/index.php' => 'getSut(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); @@ -52,13 +52,11 @@ public function testChecksIfPackageIsNotInstalled() public function testChecksIfPackageInstalled() { - $structure = [ - 'source' => [ - 'index.php' => ' ' $this->getStructurePreparator()->prepareStructure($structure)]); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/source/index.php' => ' 'getSut(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); @@ -67,14 +65,11 @@ public function testChecksIfPackageInstalled() public function testInstallationOfPackage() { - $structure = [ - 'source/vendor/oxideshop_ce/source' => [ - 'index.php' => ' ' ' $this->getStructurePreparator()->prepareStructure($structure)]); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/source/vendor/oxideshop_ce/source/index.php' => ' ' ' [ - 'config.inc.php.dist' => ' $this->getStructurePreparator()->prepareStructure($structure)]); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/source/vendor/oxideshop_ce/source/config.inc.php.dist' => ' [ - 'vendor' => [ - 'oxideshop_ce' => [ - 'source' => [ - 'Class.php' => 'Class', - 'Core' => [ - 'Class.php' => 'Class', - ], - 'Application' => [ - 'Model' => [ - 'Class.php' => 'Class', - ], - 'Controller' => [ - 'Class.php' => 'Class' - ] - ] - ] - ] - ] - ] - ]; - - vfsStream::setup('root', 777, ['projectRoot' => $structure]); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/source/vendor/oxideshop_ce/source/Class.php' => 'Class', + 'projectRoot/source/vendor/oxideshop_ce/source/Core/Class.php' => 'Class', + 'projectRoot/source/vendor/oxideshop_ce/source/Application/Model/Class.php' => 'Class', + 'projectRoot/source/vendor/oxideshop_ce/source/Application/Controller/Class.php' => 'Class', + ])); $rootPath = vfsStream::url('root/projectRoot/source'); $shopDirectory = "$rootPath/vendor/oxideshop_ce"; @@ -158,12 +132,4 @@ public function testInstallDoesNotCopyClasses() $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Controller')); $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Controller', 'Class.php')); } - - /** - * @return StructurePreparator - */ - public function getStructurePreparator() - { - return new StructurePreparator(); - } } diff --git a/tests/Integration/Installer/Package/ThemePackageInstallerTest.php b/tests/Integration/Installer/Package/ThemePackageInstallerTest.php index dc86e90..bad0f0a 100644 --- a/tests/Integration/Installer/Package/ThemePackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ThemePackageInstallerTest.php @@ -28,13 +28,11 @@ use Composer\Package\PackageInterface; use org\bovigo\vfs\vfsStream; use OxidEsales\ComposerPlugin\Installer\Package\ThemePackageInstaller; -use OxidEsales\ComposerPlugin\Tests\Integration\Installer\StructurePreparator; +use OxidEsales\ComposerPlugin\Utilities\VfsFileStructureOperator; use Webmozart\PathUtil\Path; class ThemePackageInstallerTest extends \PHPUnit_Framework_TestCase { - const THEME_NAME_IN_COMPOSER = "oxid-esales/flow-theme"; - protected function getSut(IOInterface $io, $rootPath, PackageInterface $package) { return new ThemePackageInstaller($io, $rootPath, $package); @@ -42,27 +40,27 @@ protected function getSut(IOInterface $io, $rootPath, PackageInterface $package) public function testChecksIfThemeIsNotInstalled() { - $structure = [ - 'vendor/'.static::THEME_NAME_IN_COMPOSER.'/theme.php' => ' $this->getStructurePreparator()->prepareStructure($structure)]); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/'."oxid-esales/flow-theme".'/theme.php' => 'getSut(new NullIO, $rootPath, $package); $this->assertFalse($themeInstaller->isInstalled()); } public function testChecksIfThemeIsInstalled() { - $structure = [ - 'source/Application/views/flow-theme/theme.php' => ' ' $this->getStructurePreparator()->prepareStructure($structure)]); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/source/Application/views/flow-theme/theme.php' => ' 'getSut(new NullIO(), $rootPath, $package); $this->assertTrue($shopPreparator->isInstalled()); } @@ -142,47 +140,24 @@ public function testChecksIfAssetsDirectoryWasNotCopied() $this->assertFileNotExists($eshopRootPath . '/Application/views/flow/out/style.css'); } - /** - * @return StructurePreparator - */ - protected function getStructurePreparator() - { - return new StructurePreparator(); - } - /** * @param $composerExtras * @return string */ protected function simulateInstallation($composerExtras, $rootPath, $eshopRootPath) { - $vendorName = explode("/", static::THEME_NAME_IN_COMPOSER)[0]; - $packageName = explode("/", static::THEME_NAME_IN_COMPOSER)[1]; - - $structure = [ - 'vendor' => [ - $vendorName => [ - $packageName => [ - 'theme.php' => ' 'readme', - 'out' => [ - 'style.css' => '.class {}', - 'readme.pdf' => 'PDF', - ], - 'custom_directory_name' => [ - 'custom_style.css' => '.class {}', - ] - ] - ] - ] - ]; - - vfsStream::setup('root', 777, ['projectRoot' => $structure]); - - $package = new Package(static::THEME_NAME_IN_COMPOSER, 'dev', 'dev'); + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/oxid-esales/flow-theme/theme.php' => ' 'readme', + 'projectRoot/vendor/oxid-esales/flow-theme/out/style.css' => '.class {}', + 'projectRoot/vendor/oxid-esales/flow-theme/out/readme.pdf' => 'PDF', + 'projectRoot/vendor/oxid-esales/flow-theme/custom_directory_name/custom_style.css' => '.class {}', + ])); + + $package = new Package("oxid-esales/flow-theme", 'dev', 'dev'); $shopPreparator = $this->getSut(new NullIO(), $eshopRootPath, $package); $package->setExtra($composerExtras); - $themeInVendor = "$rootPath/vendor/" . static::THEME_NAME_IN_COMPOSER; + $themeInVendor = "$rootPath/vendor/oxid-esales/flow-theme"; $shopPreparator->install($themeInVendor); } diff --git a/tests/Integration/Installer/StructurePreparator.php b/tests/Integration/Installer/StructurePreparator.php deleted file mode 100644 index 93585fd..0000000 --- a/tests/Integration/Installer/StructurePreparator.php +++ /dev/null @@ -1,49 +0,0 @@ -. - * - * @link http://www.oxid-esales.com - * @copyright (C) OXID eSales AG 2003-2016 - * @version OXID eShop Composer plugin - */ - -namespace OxidEsales\ComposerPlugin\Tests\Integration\Installer; - -/** - * Makes a structure for vfsStream. - */ -class StructurePreparator -{ - /** - * @param array $structure - * - * @return array - */ - public function prepareStructure($structure) - { - $newStructure = []; - foreach ($structure as $path => $element) { - $position = &$newStructure; - foreach (explode('/', $path) as $part) { - $position[$part] = []; - $position = &$position[$part]; - } - $position = strpos($path, '/') === false ? [] : $position; - $position = is_array($element) ? $this->prepareStructure($element) : $element; - } - return $newStructure; - } -} From 1e95b9b2805717fa4c4bb5fdb647ace94e6a7614 Mon Sep 17 00:00:00 2001 From: Edvinas Aleksejonokas Date: Wed, 24 May 2017 17:42:49 +0300 Subject: [PATCH 08/13] ESDEV-4443 Add exceptions to ShopPackageInstaller * Skip copying `.htaccess` files if they already exist * Skip copying `Setup` folder if shop is already configured Solves the following issues on github: * #4 * #3 --- .../Package/ShopPackageInstaller.php | 150 ++++++++- .../Package/ShopPackageInstallerTest.php | 311 +++++++++++++++++- 2 files changed, 442 insertions(+), 19 deletions(-) diff --git a/src/Installer/Package/ShopPackageInstaller.php b/src/Installer/Package/ShopPackageInstaller.php index e0e6681..eee0823 100644 --- a/src/Installer/Package/ShopPackageInstaller.php +++ b/src/Installer/Package/ShopPackageInstaller.php @@ -23,6 +23,7 @@ namespace OxidEsales\ComposerPlugin\Installer\Package; use OxidEsales\ComposerPlugin\Utilities\CopyFileManager\CopyGlobFilteredFileManager; +use Webmozart\Glob\Iterator\GlobIterator; use Webmozart\PathUtil\Path; /** @@ -35,13 +36,17 @@ class ShopPackageInstaller extends AbstractPackageInstaller const DISTRIBUTION_FILE_EXTENSION_MARK = '.dist'; const SHOP_SOURCE_DIRECTORY = 'source'; const SHOP_SOURCE_SETUP_DIRECTORY = 'Setup'; + const HTACCESS_FILTER = '**/.htaccess'; + const SETUP_FILES_FILTER = self::SHOP_SOURCE_SETUP_DIRECTORY . '/**/*.*'; /** * @return bool */ public function isInstalled() { - return file_exists(Path::join($this->getRootDirectory(), self::FILE_TO_CHECK_IF_PACKAGE_INSTALLED)); + return file_exists( + Path::join($this->getTargetDirectoryOfShopSource(), self::FILE_TO_CHECK_IF_PACKAGE_INSTALLED) + ); } /** @@ -70,24 +75,151 @@ public function update($packagePath) } /** - * @param $packagePath + * @param string $packagePath */ - protected function copyPackage($packagePath) + private function copyPackage($packagePath) { - $packagePath = Path::join($packagePath, self::SHOP_SOURCE_DIRECTORY); - $root = $this->getRootDirectory(); + $this->copyShopSourceFromPackageToTarget($packagePath); + $this->copySetupFilesIfNecessary($packagePath); + $this->copyConfigurationDistFileWithinTarget(); + $this->copyHtaccessFilesIfNecessary($packagePath); + } + + /** + * Copy shop source files from package source to defined target path. + * + * @param string $packagePath + */ + private function copyShopSourceFromPackageToTarget($packagePath) + { + $blacklistFilterWithHtAccess = array_merge( + $this->getBlacklistFilterValue(), + [self::HTACCESS_FILTER, self::SETUP_FILES_FILTER] + ); CopyGlobFilteredFileManager::copy( - $packagePath, - $root, - $this->getBlacklistFilterValue() + $this->getPackageDirectoryOfShopSource($packagePath), + $this->getTargetDirectoryOfShopSource(), + $blacklistFilterWithHtAccess ); + } - $pathToConfig = Path::join($root, self::SHOP_SOURCE_CONFIGURATION_FILE); + /** + * Copy shop's configuration file from distribution file if necessary. + */ + private function copyConfigurationDistFileWithinTarget() + { + $pathToConfig = Path::join($this->getTargetDirectoryOfShopSource(), self::SHOP_SOURCE_CONFIGURATION_FILE); $pathToConfigDist = $pathToConfig . self::DISTRIBUTION_FILE_EXTENSION_MARK; if (!file_exists($pathToConfig)) { CopyGlobFilteredFileManager::copy($pathToConfigDist, $pathToConfig); } } + + /** + * Copy shop's htaccess files from package if necessary. + * + * @param string $packagePath Absolute path which points to shop's package directory. + */ + private function copyHtaccessFilesIfNecessary($packagePath) + { + $packageDirectoryOfShopSource = $this->getPackageDirectoryOfShopSource($packagePath); + $installationDirectoryOfShopSource = $this->getTargetDirectoryOfShopSource(); + + $htAccessFilesIterator = new GlobIterator(Path::join($packageDirectoryOfShopSource, self::HTACCESS_FILTER)); + + foreach ($htAccessFilesIterator as $absolutePathToHtAccessFromPackage) { + $relativePathOfSourceFromPackage = Path::makeRelative( + $absolutePathToHtAccessFromPackage, + $packageDirectoryOfShopSource + ); + $absolutePathToHtAccessFromInstallation = Path::join( + $installationDirectoryOfShopSource, + $relativePathOfSourceFromPackage + ); + + if (!file_exists($absolutePathToHtAccessFromInstallation)) { + CopyGlobFilteredFileManager::copy( + $absolutePathToHtAccessFromPackage, + $absolutePathToHtAccessFromInstallation + ); + } + } + } + + /** + * Copy shop's setup files from package if necessary. + * + * @param string $packagePath Absolute path which points to shop's package directory. + */ + private function copySetupFilesIfNecessary($packagePath) + { + $packageDirectoryOfShopSource = $this->getPackageDirectoryOfShopSource($packagePath); + $installationDirectoryOfShopSource = $this->getTargetDirectoryOfShopSource(); + + $shopConfigFileName = Path::join($installationDirectoryOfShopSource, self::SHOP_SOURCE_CONFIGURATION_FILE); + + if ($this->isConfigFileNotConfiguredOrMissing($shopConfigFileName)) { + CopyGlobFilteredFileManager::copy( + Path::join($packageDirectoryOfShopSource, self::SHOP_SOURCE_SETUP_DIRECTORY), + Path::join($installationDirectoryOfShopSource, self::SHOP_SOURCE_SETUP_DIRECTORY) + ); + } + } + + /** + * Return true if config file is not configured or missing. + * + * @param string $shopConfigFileName Absolute path to shop configuration file to check. + * + * @return bool + */ + private function isConfigFileNotConfiguredOrMissing($shopConfigFileName) + { + if (!file_exists($shopConfigFileName)) { + return true; + } + + $shopConfigFileContents = file_get_contents($shopConfigFileName); + $wordsIndicatingNotConfigured = [ + '', + '', + '', + '', + '', + '', + '', + ]; + + foreach ($wordsIndicatingNotConfigured as $word) { + if (strpos($shopConfigFileContents, $word) !== false) { + return true; + } + } + + return false; + } + + /** + * Return package directory which points to shop's source directory. + * + * @param string $packagePath Absolute path which points to shop's package directory. + * + * @return string + */ + private function getPackageDirectoryOfShopSource($packagePath) + { + return Path::join($packagePath, self::SHOP_SOURCE_DIRECTORY); + } + + /** + * Return target directory where shop's source files needs to be copied. + * + * @return string + */ + private function getTargetDirectoryOfShopSource() + { + return $this->getRootDirectory(); + } } diff --git a/tests/Integration/Installer/Package/ShopPackageInstallerTest.php b/tests/Integration/Installer/Package/ShopPackageInstallerTest.php index 5e9eeca..92ea2af 100644 --- a/tests/Integration/Installer/Package/ShopPackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ShopPackageInstallerTest.php @@ -109,6 +109,306 @@ public function testInstallDoesNotCopyClasses() $rootPath = vfsStream::url('root/projectRoot/source'); $shopDirectory = "$rootPath/vendor/oxideshop_ce"; + $sut = $this->getSut(new NullIO, $rootPath, $this->getShopPackage()); + $sut->install($shopDirectory); + + $this->assertFileExists(Path::join($rootPath, 'Class.php')); + $this->assertFileNotExists(Path::join($rootPath, 'Core')); + $this->assertFileNotExists(Path::join($rootPath, 'Core', 'Class.php')); + $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Model')); + $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Model', 'Class.php')); + $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Controller')); + $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Controller', 'Class.php')); + } + + public function testInstallCopiesHtaccessFilesDuringFirstRun() + { + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/.htaccess' => 'Original htaccess', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/bin/.htaccess' => 'Original htaccess', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/cache/.htaccess' => 'Original htaccess', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/out/downloads/.htaccess' => 'Original htaccess', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Application/views/admin/tpl/.htaccess' => 'Original htaccess', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/test/.htaccess' => 'Original htaccess', + ])); + + $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); + $installedShopSourcePath = Path::join($projectRoot, 'source'); + $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); + $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); + + $sut = $this->getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); + $sut->install($packageShopRootPath); + + $this->assertFileEquals( + Path::join($packageShopSourcePath, '.htaccess'), + Path::join($installedShopSourcePath, '.htaccess') + ); + $this->assertFileEquals( + Path::join($packageShopSourcePath, 'bin', '.htaccess'), + Path::join($installedShopSourcePath, 'bin', '.htaccess') + ); + $this->assertFileEquals( + Path::join($packageShopSourcePath, 'cache', '.htaccess'), + Path::join($installedShopSourcePath, 'cache', '.htaccess') + ); + $this->assertFileEquals( + Path::join($packageShopSourcePath, 'out', 'downloads', '.htaccess'), + Path::join($installedShopSourcePath, 'out', 'downloads', '.htaccess') + ); + $this->assertFileEquals( + Path::join($packageShopSourcePath, 'Application', 'views', 'admin', 'tpl', '.htaccess'), + Path::join($installedShopSourcePath, 'Application', 'views', 'admin', 'tpl', '.htaccess') + ); + $this->assertFileEquals( + Path::join($packageShopSourcePath, 'test', '.htaccess'), + Path::join($installedShopSourcePath, 'test', '.htaccess') + ); + } + + public function testInstallDoesNotCopyHtaccessFilesDuringSecondRun() + { + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/.htaccess' => 'Original htaccess', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/bin/.htaccess' => 'Original htaccess', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/cache/.htaccess' => 'Original htaccess', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/out/downloads/.htaccess' => 'Original htaccess', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Application/views/admin/tpl/.htaccess' => 'Original htaccess', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/test/.htaccess' => 'Original htaccess', + ])); + + $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); + $installedShopSourcePath = Path::join($projectRoot, 'source'); + $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); + $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); + + $sut = $this->getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); + $sut->install($packageShopRootPath); + file_put_contents(Path::join($installedShopSourcePath, '.htaccess'), 'Updated htaccess'); + file_put_contents(Path::join($installedShopSourcePath, 'bin', '.htaccess'), 'Updated htaccess'); + file_put_contents(Path::join($installedShopSourcePath, 'cache', '.htaccess'), 'Updated htaccess'); + file_put_contents(Path::join($installedShopSourcePath, 'out', 'downloads', '.htaccess'), 'Updated htaccess'); + file_put_contents( + Path::join($installedShopSourcePath, 'Application', 'views', 'admin', 'tpl', '.htaccess'), + 'Updated htaccess' + ); + file_put_contents(Path::join($installedShopSourcePath, 'test', '.htaccess'), 'Updated htaccess'); + $sut->install($packageShopRootPath); + + $this->assertFileNotEquals( + Path::join($packageShopSourcePath, '.htaccess'), + Path::join($installedShopSourcePath, '.htaccess') + ); + $this->assertFileNotEquals( + Path::join($packageShopSourcePath, 'bin', '.htaccess'), + Path::join($installedShopSourcePath, 'bin', '.htaccess') + ); + $this->assertFileNotEquals( + Path::join($packageShopSourcePath, 'cache', '.htaccess'), + Path::join($installedShopSourcePath, 'cache', '.htaccess') + ); + $this->assertFileNotEquals( + Path::join($packageShopSourcePath, 'out', 'downloads', '.htaccess'), + Path::join($installedShopSourcePath, 'out', 'downloads', '.htaccess') + ); + $this->assertFileNotEquals( + Path::join($packageShopSourcePath, 'Application', 'views', 'admin', 'tpl', '.htaccess'), + Path::join($installedShopSourcePath, 'Application', 'views', 'admin', 'tpl', '.htaccess') + ); + $this->assertFileNotEquals( + Path::join($packageShopSourcePath, 'test', '.htaccess'), + Path::join($installedShopSourcePath, 'test', '.htaccess') + ); + } + + public function testInstallCopiesSetupFilesIfShopConfigIsMissing() + { + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/config.inc.php.dist' => 'Example config', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Setup/index.php' => 'Setup index.php file', + ])); + + $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); + $installedShopSourcePath = Path::join($projectRoot, 'source'); + $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); + $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); + + $sut = $this->getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); + $sut->install($packageShopRootPath); + + $this->assertFileEquals( + Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), + Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) + ); + } + + public function testInstallOverwritesSetupFilesIfShopConfigIsMissing() + { + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/config.inc.php.dist' => 'Example config', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Setup/index.php' => 'Setup index.php file', + 'projectRoot/source/Setup/index.php' => 'Old Setup index.php file', + ])); + + $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); + $installedShopSourcePath = Path::join($projectRoot, 'source'); + $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); + $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); + + $sut = $this->getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); + + $this->assertFileNotEquals( + Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), + Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) + ); + $sut->install($packageShopRootPath); + $this->assertFileEquals( + Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), + Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) + ); + } + + public function testInstallCopiesSetupFilesIfShopConfigIsNotConfigured() + { + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/config.inc.php.dist' => 'Example config', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Setup/index.php' => 'Setup index.php file', + 'projectRoot/source/config.inc.php' => <<<'EOT' + $this->dbType = 'pdo_mysql'; + $this->dbHost = ''; + $this->dbPort = 3306; + $this->dbName = ''; + $this->dbUser = ''; + $this->dbPwd = ''; + $this->sShopURL = ''; + $this->sShopDir = ''; + $this->sCompileDir = ''; +EOT + ])); + + $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); + $installedShopSourcePath = Path::join($projectRoot, 'source'); + $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); + $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); + + $sut = $this->getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); + $sut->install($packageShopRootPath); + + $this->assertFileEquals( + Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), + Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) + ); + } + + public function testInstallOverwritesSetupFilesIfShopConfigIsNotConfigured() + { + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/config.inc.php.dist' => 'Example config', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Setup/index.php' => 'Setup index.php file', + + 'projectRoot/source/Setup/index.php' => 'Old Setup index.php file', + 'projectRoot/source/config.inc.php' => <<<'EOT' + $this->dbType = 'pdo_mysql'; + $this->dbHost = ''; + $this->dbPort = 3306; + $this->dbName = ''; + $this->dbUser = ''; + $this->dbPwd = ''; + $this->sShopURL = ''; + $this->sShopDir = ''; + $this->sCompileDir = ''; +EOT + ])); + + $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); + $installedShopSourcePath = Path::join($projectRoot, 'source'); + $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); + $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); + + $sut = $this->getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); + + $this->assertFileNotEquals( + Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), + Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) + ); + $sut->install($packageShopRootPath); + $this->assertFileEquals( + Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), + Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) + ); + } + + public function testInstallDoesNotCopySetupFilesIfShopConfigIsConfigured() + { + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/config.inc.php.dist' => 'Example config', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Setup/index.php' => 'Setup index.php file', + 'projectRoot/source/config.inc.php' => <<<'EOT' + $this->dbType = 'pdo_mysql'; + $this->dbHost = 'somehost'; + $this->dbPort = 3306; + $this->dbName = 'some_db_name'; + $this->dbUser = 'db_user'; + $this->dbPwd = 'db_pass'; + $this->sShopURL = 'http://some_url/'; + $this->sShopDir = '/var/www/shopdir/source'; + $this->sCompileDir = '/var/www/shopdir/source/tmp'; +EOT + ])); + + $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); + $installedShopSourcePath = Path::join($projectRoot, 'source'); + $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); + $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); + + $sut = $this->getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); + $sut->install($packageShopRootPath); + + $this->assertFileNotExists(Path::join($installedShopSourcePath, Path::join('Setup', 'index.php'))); + } + + public function testInstallDoesNotOverwriteSetupFilesIfShopConfigIsConfigured() + { + vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/config.inc.php.dist' => 'Example config', + 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Setup/index.php' => 'Setup index.php file', + 'projectRoot/source/Setup/index.php' => 'Old Setup index.php file', + 'projectRoot/source/config.inc.php' => <<<'EOT' + $this->dbType = 'pdo_mysql'; + $this->dbHost = 'somehost'; + $this->dbPort = 3306; + $this->dbName = 'some_db_name'; + $this->dbUser = 'db_user'; + $this->dbPwd = 'db_pass'; + $this->sShopURL = 'http://some_url/'; + $this->sShopDir = '/var/www/shopdir/source'; + $this->sCompileDir = '/var/www/shopdir/source/tmp'; +EOT + ])); + + $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); + $installedShopSourcePath = Path::join($projectRoot, 'source'); + $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); + $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); + + $sut = $this->getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); + + $this->assertFileNotEquals( + Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), + Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) + ); + $sut->install($packageShopRootPath); + $this->assertFileNotEquals( + Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), + Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) + ); + } + + /** + * @return Package + */ + private function getShopPackage() + { $package = new Package('oxid-esales/oxideshop-ce', 'dev', 'dev'); $package->setExtra([ 'oxideshop' => [ @@ -121,15 +421,6 @@ public function testInstallDoesNotCopyClasses() ] ]); - $sut = $this->getSut(new NullIO, $rootPath, $package); - $sut->install($shopDirectory); - - $this->assertFileExists(Path::join($rootPath, 'Class.php')); - $this->assertFileNotExists(Path::join($rootPath, 'Core')); - $this->assertFileNotExists(Path::join($rootPath, 'Core', 'Class.php')); - $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Model')); - $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Model', 'Class.php')); - $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Controller')); - $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Controller', 'Class.php')); + return $package; } } From 1f14d051cbeb92cb677959c1b85b852b26cc225b Mon Sep 17 00:00:00 2001 From: Edvinas Aleksejonokas Date: Thu, 1 Jun 2017 17:57:15 +0300 Subject: [PATCH 09/13] ESDEV-4443 Refactor Package Installer tests Task: ESDEV-4536 Goals of refactoring: * Improve readability of tests * Each test should be read as code example * Emphasize the input and output data which matters to the test * Clear structure of Arrange/Act/Assert * Minimize the differences between different types of Package Installers * Improve test case readability context by providing hard coded strings for package source and installation locations * Improve readability of test names so that in case of failure it would be easier to understand the broken behavior --- .../Package/AbstractPackageInstallerTest.php | 97 ++++ .../Package/ModulePackageInstallerTest.php | 366 +++++++++----- .../ShopPackageInstallerHtaccessFilesTest.php | 103 ++++ .../ShopPackageInstallerSetupFilesTest.php | 195 ++++++++ .../Package/ShopPackageInstallerTest.php | 441 ++++------------- .../Package/ThemePackageInstallerTest.php | 462 ++++++++++++------ 6 files changed, 1039 insertions(+), 625 deletions(-) create mode 100644 tests/Integration/Installer/Package/AbstractPackageInstallerTest.php create mode 100644 tests/Integration/Installer/Package/ShopPackageInstallerHtaccessFilesTest.php create mode 100644 tests/Integration/Installer/Package/ShopPackageInstallerSetupFilesTest.php diff --git a/tests/Integration/Installer/Package/AbstractPackageInstallerTest.php b/tests/Integration/Installer/Package/AbstractPackageInstallerTest.php new file mode 100644 index 0000000..4e12542 --- /dev/null +++ b/tests/Integration/Installer/Package/AbstractPackageInstallerTest.php @@ -0,0 +1,97 @@ +. + * + * @link http://www.oxid-esales.com + * @copyright (C) OXID eSales AG 2003-2016 + * @version OXID eShop Composer plugin + */ + +namespace OxidEsales\ComposerPlugin\Tests\Integration\Installer\Package; + +use OxidEsales\ComposerPlugin\Utilities\VfsFileStructureOperator; +use org\bovigo\vfs\vfsStream; +use Webmozart\PathUtil\Path; + +abstract class AbstractPackageInstallerTest extends \PHPUnit_Framework_TestCase +{ + public function setUp() + { + $this->setupVirtualFileSystem(); + } + + protected function setupVirtualFileSystem() + { + vfsStream::setup('root', 777, + [ + 'vendor' => [], + 'source' => [], + ] + ); + } + + protected function setupVirtualProjectRoot($prefix, $input) + { + $updated = []; + + foreach ($input as $path => $contents) { + $updated[Path::join($prefix, $path)] = $contents; + } + + return vfsStream::create(VfsFileStructureOperator::nest($updated)); + } + + protected function getVirtualShopSourcePath() + { + return $this->getVirtualFileSystemRootPath('source'); + } + + protected function getVirtualVendorPath() + { + return $this->getVirtualFileSystemRootPath('vendor'); + } + + protected function getVirtualFileSystemRootPath($suffix = '') + { + return Path::join(vfsStream::url('root'), $suffix); + } + + protected function assertVirtualFileExists($path) + { + $this->assertFileExists($this->getVirtualFileSystemRootPath($path)); + } + + protected function assertVirtualFileNotExists($path) + { + $this->assertFileNotExists($this->getVirtualFileSystemRootPath($path)); + } + + protected function assertVirtualFileEquals($expected, $actual) + { + $this->assertFileEquals( + $this->getVirtualFileSystemRootPath($expected), + $this->getVirtualFileSystemRootPath($actual) + ); + } + + protected function assertVirtualFileNotEquals($expected, $actual) + { + $this->assertFileNotEquals( + $this->getVirtualFileSystemRootPath($expected), + $this->getVirtualFileSystemRootPath($actual) + ); + } +} diff --git a/tests/Integration/Installer/Package/ModulePackageInstallerTest.php b/tests/Integration/Installer/Package/ModulePackageInstallerTest.php index bb72288..4ac7a76 100644 --- a/tests/Integration/Installer/Package/ModulePackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ModulePackageInstallerTest.php @@ -26,205 +26,309 @@ use Composer\IO\NullIO; use Composer\Package\Package; use Composer\Package\PackageInterface; +use OxidEsales\ComposerPlugin\Installer\Package\AbstractPackageInstaller; use OxidEsales\ComposerPlugin\Installer\Package\ModulePackageInstaller; use OxidEsales\ComposerPlugin\Utilities\VfsFileStructureOperator; use org\bovigo\vfs\vfsStream; use Webmozart\PathUtil\Path; -class ModulePackageInstallerTest extends \PHPUnit_Framework_TestCase +class ModulePackageInstallerTest extends AbstractPackageInstallerTest { - protected function getSut(IOInterface $io, $rootPath, PackageInterface $package) + protected function getPackageInstaller($packageName, $version = '1.0.0', $extra = []) { - return new ModulePackageInstaller($io, $rootPath, $package); + $package = new Package($packageName, $version, $version); + $package->setExtra($extra); + + return new ModulePackageInstaller( + new NullIO(), + $this->getVirtualShopSourcePath(), + $package + ); + } + + public function testModuleNotInstalledByDefault() + { + $installer = $this->getPackageInstaller('test-vendor/test-package'); + + $this->assertFalse($installer->isInstalled()); } - public function testChecksIfModuleIsNotInstalled() + public function testModuleIsInstalledIfAlreadyExistsInShop() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/oxid-esales/paypal-module/metadata.php' => 'setupVirtualProjectRoot('source/modules/test-vendor/test-package', [ + 'metadata.php' => 'getPackageInstaller('test-vendor/test-package'); - $shopPreparator = $this->getSut(new NullIO, $rootPath, new Package('oxid-esales/paypal-module', 'dev', 'dev')); - $this->assertFalse($shopPreparator->isInstalled()); + $this->assertTrue($installer->isInstalled()); } - public function testChecksIfModuleIsInstalled() + public function testModuleIsInstalledAfterInstallProcess() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/source/modules/oxid-esales/paypal-module/metadata.php' => ' 'setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'metadata.php' => 'getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $shopPreparator = $this->getSut(new NullIO, $rootPath, new Package('oxid-esales/paypal-module', 'dev', 'dev')); - $this->assertTrue($shopPreparator->isInstalled()); + $this->assertTrue($installer->isInstalled()); } - public function providerChecksIfModuleFilesExistsAfterInstallation() + public function testModuleFilesAreCopiedAfterInstallProcess() { - return [ - [[ModulePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ModulePackageInstaller::EXTRA_PARAMETER_KEY_TARGET => 'oe/paypal']], 'modules/oe/paypal/metadata.php'], - [[ModulePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ModulePackageInstaller::EXTRA_PARAMETER_KEY_TARGET => 'paypal']], 'modules/paypal/metadata.php'], - [[], 'modules/oxid-esales/paypal-module/metadata.php'] - ]; + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'metadata.php' => 'getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/metadata.php', + 'source/modules/test-vendor/test-package/metadata.php' + ); } - /** - * @param $composerExtras - * @param $installedModuleMetadata - * - * @dataProvider providerChecksIfModuleFilesExistsAfterInstallation - */ - public function testChecksIfModuleFilesExistsAfterInstallation($composerExtras, $installedModuleMetadata) + public function testModuleFilesAreCopiedAfterInstallProcessWithSameSourceDirectory() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/oxid-esales/paypal-module/metadata.php' => 'setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'metadata.php' => 'getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'source-directory' => '' + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $rootPath = vfsStream::url('root/projectRoot'); - $eshopRootPath = "$rootPath/source"; - $installedModuleMetadata = "$eshopRootPath/$installedModuleMetadata"; + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/metadata.php', + 'source/modules/test-vendor/test-package/metadata.php' + ); + } - $package = new Package('oxid-esales/paypal-module', 'dev', 'dev'); - $shopPreparator = $this->getSut(new NullIO(), $eshopRootPath, $package); - $package->setExtra($composerExtras); - $moduleInVendor = "$rootPath/vendor/oxid-esales/paypal-module"; - $shopPreparator->install($moduleInVendor); + public function testModuleFilesAreCopiedAfterInstallProcessWithSameTargetDirectory() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'metadata.php' => 'assertFileExists($installedModuleMetadata); + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'target-directory' => 'test-vendor/test-package' + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/metadata.php', + 'source/modules/test-vendor/test-package/metadata.php' + ); } - public function testCheckIfModuleIsInstalledFromProvidedSourceDirectory() + public function testModuleFilesAreCopiedAfterInstallProcessWithSameSourceDirectoryAndSameTargetDirectory() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/oxid-esales/erp/copy_this/modules/erp/metadata.php' => 'setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'metadata.php' => 'getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'source-directory' => '', + 'target-directory' => 'test-vendor/test-package' + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $package = new Package('oxid-esales/erp', 'dev', 'dev'); - $shopPreparator = $this->getSut(new NullIO(), $eshopRootPath, $package); - $package->setExtra( - [ModulePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ - ModulePackageInstaller::EXTRA_PARAMETER_KEY_SOURCE => 'copy_this/modules/erp', - ModulePackageInstaller::EXTRA_PARAMETER_KEY_TARGET => 'erp', - ]] + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/metadata.php', + 'source/modules/test-vendor/test-package/metadata.php' ); - $moduleInVendor = "$rootPath/vendor/oxid-esales/erp"; - $shopPreparator->install($moduleInVendor); + } - $this->assertFileExists($installedModuleMetadata); + public function testModuleFilesAreCopiedAfterInstallProcessWithCustomSourceDirectory() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/custom-root', [ + 'metadata.php' => 'getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'source-directory' => 'custom-root', + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/custom-root/metadata.php', + 'source/modules/test-vendor/test-package/metadata.php' + ); } - public function testBlacklistedFilesArePresentWhenNoBlacklistFilterIsDefined() + public function testModuleFilesAreCopiedAfterInstallProcessWithCustomTargetDirectory() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/test-vendor/test-package/metadata.php' => 'meta data', - 'projectRoot/vendor/test-vendor/test-package/module.php' => 'module', - 'projectRoot/vendor/test-vendor/test-package/readme.txt' => 'readme', - ])); + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'metadata.php' => 'getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'target-directory' => 'custom-vendor/custom-package', + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $rootPath = vfsStream::url('root/projectRoot'); - $shopRootPath = Path::join($rootPath, 'source'); - $installedModulePath = Path::join($shopRootPath, 'modules', 'test-vendor', 'test-package'); - $moduleSourcePath = Path::join($rootPath, 'vendor', 'test-vendor', 'test-package'); + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/metadata.php', + 'source/modules/custom-vendor/custom-package/metadata.php' + ); + } - $package = new Package('test-vendor/test-package', 'dev', 'dev'); - $sut = $this->getSut(new NullIO(), $shopRootPath, $package); - $sut->install($moduleSourcePath); + public function testModuleFilesAreCopiedAfterInstallProcessWithCustomSourceDirectoryAndCustomTargetDirectory() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/custom-root', [ + 'metadata.php' => 'assertFileExists(Path::join($installedModulePath, 'metadata.php')); - $this->assertFileExists(Path::join($installedModulePath, 'module.php')); - $this->assertFileExists(Path::join($installedModulePath, 'readme.txt')); + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'source-directory' => 'custom-root', + 'target-directory' => 'custom-vendor/custom-package', + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/custom-root/metadata.php', + 'source/modules/custom-vendor/custom-package/metadata.php' + ); } - public function testBlacklistedFilesArePresentWhenEmptyBlacklistFilterIsDefined() + public function testBlacklistedFilesArePresentWhenNoBlacklistFilterIsDefined() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/test-vendor/test-package/metadata.php' => 'meta data', - 'projectRoot/vendor/test-vendor/test-package/module.php' => 'module', - 'projectRoot/vendor/test-vendor/test-package/readme.txt' => 'readme', - ])); + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'metadata.php' => ' ' 'readme', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileExists('source/modules/test-vendor/test-package/metadata.php'); + $this->assertVirtualFileExists('source/modules/test-vendor/test-package/module.php'); + $this->assertVirtualFileExists('source/modules/test-vendor/test-package/readme.txt'); + } - $rootPath = vfsStream::url('root/projectRoot'); - $shopRootPath = Path::join($rootPath, 'source'); - $installedModulePath = Path::join($shopRootPath, 'modules', 'test-vendor', 'test-package'); - $moduleSourcePath = Path::join($rootPath, 'vendor', 'test-vendor', 'test-package'); + public function testBlacklistedFilesArePresentWhenEmptyBlacklistFilterIsDefined() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'metadata.php' => ' ' 'readme', + ]); - $package = new Package('test-vendor/test-package', 'dev', 'dev'); - $package->setExtra([ + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ 'oxideshop' => [ - 'blacklist-filter' => [], + 'blacklist-filter' => [] ] ]); - $sut = $this->getSut(new NullIO(), $shopRootPath, $package); - $sut->install($moduleSourcePath); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $this->assertFileExists(Path::join($installedModulePath, 'metadata.php')); - $this->assertFileExists(Path::join($installedModulePath, 'module.php')); - $this->assertFileExists(Path::join($installedModulePath, 'readme.txt')); + $this->assertVirtualFileExists('source/modules/test-vendor/test-package/metadata.php'); + $this->assertVirtualFileExists('source/modules/test-vendor/test-package/module.php'); + $this->assertVirtualFileExists('source/modules/test-vendor/test-package/readme.txt'); } public function testBlacklistedFilesArePresentWhenDifferentBlacklistFilterIsDefined() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/test-vendor/test-package/metadata.php' => 'meta data', - 'projectRoot/vendor/test-vendor/test-package/module.php' => 'module', - 'projectRoot/vendor/test-vendor/test-package/readme.txt' => 'readme', - ])); - - $rootPath = vfsStream::url('root/projectRoot'); - $shopRootPath = Path::join($rootPath, 'source'); - $installedModulePath = Path::join($shopRootPath, 'modules', 'test-vendor', 'test-package'); - $moduleSourcePath = Path::join($rootPath, 'vendor', 'test-vendor', 'test-package'); + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'metadata.php' => ' ' 'readme', + ]); - $package = new Package('test-vendor/test-package', 'dev', 'dev'); - $package->setExtra([ + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ 'oxideshop' => [ 'blacklist-filter' => [ - "**/*.pdf", - ], + '**/*.pdf' + ] ] ]); - $sut = $this->getSut(new NullIO(), $shopRootPath, $package); - $sut->install($moduleSourcePath); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $this->assertFileExists(Path::join($installedModulePath, 'metadata.php')); - $this->assertFileExists(Path::join($installedModulePath, 'module.php')); - $this->assertFileExists(Path::join($installedModulePath, 'readme.txt')); + $this->assertVirtualFileExists('source/modules/test-vendor/test-package/metadata.php'); + $this->assertVirtualFileExists('source/modules/test-vendor/test-package/module.php'); + $this->assertVirtualFileExists('source/modules/test-vendor/test-package/readme.txt'); } public function testBlacklistedFilesAreSkippedWhenABlacklistFilterIsDefined() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/test-vendor/test-package/metadata.php' => 'meta data', - 'projectRoot/vendor/test-vendor/test-package/module.php' => 'module', - 'projectRoot/vendor/test-vendor/test-package/readme.txt' => 'readme', - ])); + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'metadata.php' => ' ' 'readme', + ]); - $rootPath = vfsStream::url('root/projectRoot'); - $shopRootPath = Path::join($rootPath, 'source'); - $installedModulePath = Path::join($shopRootPath, 'modules', 'test-vendor', 'test-package'); - $moduleSourcePath = Path::join($rootPath, 'vendor', 'test-vendor', 'test-package'); + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'blacklist-filter' => [ + '**/*.txt' + ] + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileExists('source/modules/test-vendor/test-package/metadata.php'); + $this->assertVirtualFileExists('source/modules/test-vendor/test-package/module.php'); + $this->assertVirtualFileNotExists('source/modules/test-vendor/test-package/readme.txt'); + } - $package = new Package('test-vendor/test-package', 'dev', 'dev'); - $package->setExtra([ + public function testComplexCase() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/custom-root', [ + 'metadata.php' => ' ' 'readme', + 'readme.pdf' => 'PDF', + 'documentation/readme.txt' => 'readme', + 'documentation/example.php' => ' 'getPackageInstaller('test-vendor/test-package', '1.0.0', [ 'oxideshop' => [ + 'source-directory' => 'custom-root', + 'target-directory' => 'custom-out', 'blacklist-filter' => [ - "**/*.txt", - ], + '**/*.txt', + '**/*.pdf', + 'documentation/**/*.*', + ] ] ]); - $sut = $this->getSut(new NullIO(), $shopRootPath, $package); - $sut->install($moduleSourcePath); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $this->assertFileExists(Path::join($installedModulePath, 'metadata.php')); - $this->assertFileExists(Path::join($installedModulePath, 'module.php')); - $this->assertFileNotExists(Path::join($installedModulePath, 'readme.txt')); + $this->assertTrue($installer->isInstalled()); + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/custom-root/metadata.php', + 'source/modules/custom-out/metadata.php' + ); + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/custom-root/module.php', + 'source/modules/custom-out/module.php' + ); + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/custom-root/model/model.php', + 'source/modules/custom-out/model/model.php' + ); + $this->assertVirtualFileNotExists('source/modules/custom-out/readme.txt'); + $this->assertVirtualFileNotExists('source/modules/custom-out/readme.pdf'); + $this->assertVirtualFileNotExists('source/modules/custom-out/documentation'); + $this->assertVirtualFileNotExists('source/modules/custom-out/documentation/readme.txt'); + $this->assertVirtualFileNotExists('source/modules/custom-out/documentation/example.php'); } } diff --git a/tests/Integration/Installer/Package/ShopPackageInstallerHtaccessFilesTest.php b/tests/Integration/Installer/Package/ShopPackageInstallerHtaccessFilesTest.php new file mode 100644 index 0000000..c913b26 --- /dev/null +++ b/tests/Integration/Installer/Package/ShopPackageInstallerHtaccessFilesTest.php @@ -0,0 +1,103 @@ +. + * + * @link http://www.oxid-esales.com + * @copyright (C) OXID eSales AG 2003-2016 + * @version OXID eShop Composer plugin + */ + +namespace OxidEsales\ComposerPlugin\Tests\Integration\Installer\Package; + +use Composer\IO\IOInterface; +use Composer\IO\NullIO; +use Composer\Package\Package; +use Composer\Package\PackageInterface; +use OxidEsales\ComposerPlugin\Installer\Package\ShopPackageInstaller; +use OxidEsales\ComposerPlugin\Utilities\VfsFileStructureOperator; +use org\bovigo\vfs\vfsStream; +use Webmozart\PathUtil\Path; + +class ShopPackageInstallerHtaccessFilesTest extends AbstractPackageInstallerTest +{ + protected function getPackageInstaller($packageName, $version = '1.0.0', $extra = []) + { + $package = new Package($packageName, $version, $version); + $extra['oxideshop']['blacklist-filter'] = [ + "Application/Component/**/*.*", + "Application/Controller/**/*.*", + "Application/Model/**/*.*", + "Core/**/*.*" + ]; + $package->setExtra($extra); + + return new ShopPackageInstaller( + new NullIO(), + $this->getVirtualShopSourcePath(), + $package + ); + } + + public function HtaccessFilesProvider() + { + return [ + ['.htaccess'], + ['bin/.htaccess'], + ['cache/.htaccess'], + ['out/downloads/.htaccess'], + ['Application/views/admin/tpl/.htaccess'], + ['test/.htaccess'], + ]; + } + + /** + * @dataProvider HtaccessFilesProvider + */ + public function testShopInstallProcessCopiesHtaccessFilesIfTheyAreMissing($htaccessFile) + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/source', [ + 'index.php' => ' 'Original htaccess', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals("vendor/test-vendor/test-package/source/$htaccessFile", "source/$htaccessFile"); + } + + /** + * @dataProvider HtaccessFilesProvider + */ + public function testShopInstallProcessDoesNotCopyHtaccessFilesIfTheyAreAlreadyPresent($htaccessFile) + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/source', [ + 'index.php' => ' 'Original htaccess', + ]); + $this->setupVirtualProjectRoot('source', [ + $htaccessFile => 'Old', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileNotEquals( + "vendor/test-vendor/test-package/source/$htaccessFile", + "source/$htaccessFile" + ); + } +} diff --git a/tests/Integration/Installer/Package/ShopPackageInstallerSetupFilesTest.php b/tests/Integration/Installer/Package/ShopPackageInstallerSetupFilesTest.php new file mode 100644 index 0000000..6a2389f --- /dev/null +++ b/tests/Integration/Installer/Package/ShopPackageInstallerSetupFilesTest.php @@ -0,0 +1,195 @@ +. + * + * @link http://www.oxid-esales.com + * @copyright (C) OXID eSales AG 2003-2016 + * @version OXID eShop Composer plugin + */ + +namespace OxidEsales\ComposerPlugin\Tests\Integration\Installer\Package; + +use Composer\IO\IOInterface; +use Composer\IO\NullIO; +use Composer\Package\Package; +use Composer\Package\PackageInterface; +use OxidEsales\ComposerPlugin\Installer\Package\ShopPackageInstaller; +use OxidEsales\ComposerPlugin\Utilities\VfsFileStructureOperator; +use org\bovigo\vfs\vfsStream; +use Webmozart\PathUtil\Path; + +class ShopPackageInstallerSetupFilesTest extends AbstractPackageInstallerTest +{ + protected function getPackageInstaller($packageName, $version = '1.0.0', $extra = []) + { + $package = new Package($packageName, $version, $version); + $extra['oxideshop']['blacklist-filter'] = [ + "Application/Component/**/*.*", + "Application/Controller/**/*.*", + "Application/Model/**/*.*", + "Core/**/*.*" + ]; + $package->setExtra($extra); + + return new ShopPackageInstaller( + new NullIO(), + $this->getVirtualShopSourcePath(), + $package + ); + } + + public function testShopInstallProcessCopiesSetupFilesIfShopConfigIsMissing() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/source', [ + 'index.php' => ' 'dist', + 'Setup/index.php' => 'getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + "vendor/test-vendor/test-package/source/Setup/index.php", + "source/Setup/index.php" + ); + } + + public function testShopInstallProcessOverwritesSetupFilesIfShopConfigIsMissing() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/source', [ + 'index.php' => ' 'dist', + 'Setup/index.php' => 'setupVirtualProjectRoot('source', [ + 'Setup/index.php' => 'Old index file' + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + "vendor/test-vendor/test-package/source/Setup/index.php", + "source/Setup/index.php" + ); + } + + public function testShopInstallProcessCopiesSetupFilesIfShopConfigIsNotConfigured() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/source', [ + 'index.php' => ' 'setupVirtualProjectRoot('source', [ + 'config.inc.php' => $this->getNonConfiguredConfigFileContents(), + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + "vendor/test-vendor/test-package/source/Setup/index.php", + "source/Setup/index.php" + ); + } + + public function testShopInstallProcessOverwritesSetupFilesIfShopConfigIsNotConfigured() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/source', [ + 'index.php' => ' 'setupVirtualProjectRoot('source', [ + 'config.inc.php' => $this->getNonConfiguredConfigFileContents(), + 'Setup/index.php' => 'Old index file' + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + "vendor/test-vendor/test-package/source/Setup/index.php", + "source/Setup/index.php" + ); + } + + public function testShopInstallProcessDoesNotCopySetupFilesIfShopConfigIsConfigured() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/source', [ + 'index.php' => ' 'setupVirtualProjectRoot('source', [ + 'config.inc.php' => $this->getConfiguredConfigFileContents(), + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileNotExists('source/Setup/index.php'); + } + + public function testShopInstallProcessDoesNotOverwriteSetupFilesIfShopConfigIsConfigured() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/source', [ + 'index.php' => ' 'setupVirtualProjectRoot('source', [ + 'config.inc.php' => $this->getConfiguredConfigFileContents(), + 'Setup/index.php' => 'Old index file' + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileNotEquals( + "vendor/test-vendor/test-package/source/Setup/index.php", + "source/Setup/index.php" + ); + } + + protected function getNonConfiguredConfigFileContents() + { + return <<<'EOT' + $this->dbType = 'pdo_mysql'; + $this->dbHost = ''; + $this->dbPort = 3306; + $this->dbName = ''; + $this->dbUser = ''; + $this->dbPwd = ''; + $this->sShopURL = ''; + $this->sShopDir = ''; + $this->sCompileDir = ''; +EOT; + } + + protected function getConfiguredConfigFileContents() + { + return <<<'EOT' + $this->dbType = 'pdo_mysql'; + $this->dbHost = 'test_host'; + $this->dbPort = 3306; + $this->dbName = 'test_db'; + $this->dbUser = 'test_user'; + $this->dbPwd = 'test_password'; + $this->sShopURL = 'http://test.url/'; + $this->sShopDir = '/var/www/test/dir'; + $this->sCompileDir = '/var/www/test/dir/tmp'; +EOT; + } +} diff --git a/tests/Integration/Installer/Package/ShopPackageInstallerTest.php b/tests/Integration/Installer/Package/ShopPackageInstallerTest.php index 92ea2af..4ac53c6 100644 --- a/tests/Integration/Installer/Package/ShopPackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ShopPackageInstallerTest.php @@ -31,396 +31,139 @@ use org\bovigo\vfs\vfsStream; use Webmozart\PathUtil\Path; -class ShopPackageInstallerTest extends \PHPUnit_Framework_TestCase +class ShopPackageInstallerTest extends AbstractPackageInstallerTest { - protected function getSut(IOInterface $io, $rootPath, PackageInterface $package) + protected function getPackageInstaller($packageName, $version = '1.0.0', $extra = []) { - return new ShopPackageInstaller($io, $rootPath, $package); - } - - public function testChecksIfPackageIsNotInstalled() - { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/source/vendor/oxideshop_ce/source/index.php' => 'getSut(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); - $this->assertFalse($shopPreparator->isInstalled()); - } - - public function testChecksIfPackageInstalled() - { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/source/index.php' => ' 'getSut(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); - $this->assertTrue($shopPreparator->isInstalled()); - } - - public function testInstallationOfPackage() - { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/source/vendor/oxideshop_ce/source/index.php' => ' ' 'getSut(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); - $shopPreparator->install($shopDirectory); - - $this->assertFileExists($rootPath . '/index.php'); - $this->assertFileExists($rootPath . '/Application/views/template.tpl'); - $this->assertFileExists($rootPath . '/config.inc.php.dist'); + $package = new Package($packageName, $version, $version); + $extra['oxideshop']['blacklist-filter'] = [ + "Application/Component/**/*.*", + "Application/Controller/**/*.*", + "Application/Model/**/*.*", + "Core/**/*.*" + ]; + $package->setExtra($extra); + + return new ShopPackageInstaller( + new NullIO(), + $this->getVirtualShopSourcePath(), + $package + ); } - public function testInstallCreatesConfigInc() + public function testShopNotInstalledByDefault() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/source/vendor/oxideshop_ce/source/config.inc.php.dist' => 'getPackageInstaller('test-vendor/test-package'); - $shopPreparator = $this->getSut(new NullIO, $rootPath, new Package('oxid-esales/oxideshop-ce', 'dev', 'dev')); - $shopPreparator->install($shopDirectory); - - $this->assertFileExists($rootPath . '/config.inc.php'); + $this->assertFalse($installer->isInstalled()); } - public function testInstallDoesNotCopyClasses() + public function testShopIsInstalledIfSourceFilesAlreadyExist() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/source/vendor/oxideshop_ce/source/Class.php' => 'Class', - 'projectRoot/source/vendor/oxideshop_ce/source/Core/Class.php' => 'Class', - 'projectRoot/source/vendor/oxideshop_ce/source/Application/Model/Class.php' => 'Class', - 'projectRoot/source/vendor/oxideshop_ce/source/Application/Controller/Class.php' => 'Class', - ])); - - $rootPath = vfsStream::url('root/projectRoot/source'); - $shopDirectory = "$rootPath/vendor/oxideshop_ce"; + $this->setupVirtualProjectRoot('source/', [ + 'index.php' => 'getSut(new NullIO, $rootPath, $this->getShopPackage()); - $sut->install($shopDirectory); + $installer = $this->getPackageInstaller('test-vendor/test-package'); - $this->assertFileExists(Path::join($rootPath, 'Class.php')); - $this->assertFileNotExists(Path::join($rootPath, 'Core')); - $this->assertFileNotExists(Path::join($rootPath, 'Core', 'Class.php')); - $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Model')); - $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Model', 'Class.php')); - $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Controller')); - $this->assertFileNotExists(Path::join($rootPath, 'Application', 'Controller', 'Class.php')); + $this->assertTrue($installer->isInstalled()); + $this->assertVirtualFileExists('source/index.php'); } - public function testInstallCopiesHtaccessFilesDuringFirstRun() + public function testShopIsInstalledAfterInstallProcess() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/.htaccess' => 'Original htaccess', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/bin/.htaccess' => 'Original htaccess', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/cache/.htaccess' => 'Original htaccess', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/out/downloads/.htaccess' => 'Original htaccess', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Application/views/admin/tpl/.htaccess' => 'Original htaccess', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/test/.htaccess' => 'Original htaccess', - ])); - - $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); - $installedShopSourcePath = Path::join($projectRoot, 'source'); - $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); - $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/source', [ + 'index.php' => 'getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); - $sut->install($packageShopRootPath); + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $this->assertFileEquals( - Path::join($packageShopSourcePath, '.htaccess'), - Path::join($installedShopSourcePath, '.htaccess') - ); - $this->assertFileEquals( - Path::join($packageShopSourcePath, 'bin', '.htaccess'), - Path::join($installedShopSourcePath, 'bin', '.htaccess') - ); - $this->assertFileEquals( - Path::join($packageShopSourcePath, 'cache', '.htaccess'), - Path::join($installedShopSourcePath, 'cache', '.htaccess') - ); - $this->assertFileEquals( - Path::join($packageShopSourcePath, 'out', 'downloads', '.htaccess'), - Path::join($installedShopSourcePath, 'out', 'downloads', '.htaccess') - ); - $this->assertFileEquals( - Path::join($packageShopSourcePath, 'Application', 'views', 'admin', 'tpl', '.htaccess'), - Path::join($installedShopSourcePath, 'Application', 'views', 'admin', 'tpl', '.htaccess') - ); - $this->assertFileEquals( - Path::join($packageShopSourcePath, 'test', '.htaccess'), - Path::join($installedShopSourcePath, 'test', '.htaccess') - ); + $this->assertTrue($installer->isInstalled()); } - public function testInstallDoesNotCopyHtaccessFilesDuringSecondRun() + public function testShopFilesAreCopiedAfterInstallProcess() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/.htaccess' => 'Original htaccess', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/bin/.htaccess' => 'Original htaccess', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/cache/.htaccess' => 'Original htaccess', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/out/downloads/.htaccess' => 'Original htaccess', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Application/views/admin/tpl/.htaccess' => 'Original htaccess', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/test/.htaccess' => 'Original htaccess', - ])); - - $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); - $installedShopSourcePath = Path::join($projectRoot, 'source'); - $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); - $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); - - $sut = $this->getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); - $sut->install($packageShopRootPath); - file_put_contents(Path::join($installedShopSourcePath, '.htaccess'), 'Updated htaccess'); - file_put_contents(Path::join($installedShopSourcePath, 'bin', '.htaccess'), 'Updated htaccess'); - file_put_contents(Path::join($installedShopSourcePath, 'cache', '.htaccess'), 'Updated htaccess'); - file_put_contents(Path::join($installedShopSourcePath, 'out', 'downloads', '.htaccess'), 'Updated htaccess'); - file_put_contents( - Path::join($installedShopSourcePath, 'Application', 'views', 'admin', 'tpl', '.htaccess'), - 'Updated htaccess' - ); - file_put_contents(Path::join($installedShopSourcePath, 'test', '.htaccess'), 'Updated htaccess'); - $sut->install($packageShopRootPath); - - $this->assertFileNotEquals( - Path::join($packageShopSourcePath, '.htaccess'), - Path::join($installedShopSourcePath, '.htaccess') - ); - $this->assertFileNotEquals( - Path::join($packageShopSourcePath, 'bin', '.htaccess'), - Path::join($installedShopSourcePath, 'bin', '.htaccess') - ); - $this->assertFileNotEquals( - Path::join($packageShopSourcePath, 'cache', '.htaccess'), - Path::join($installedShopSourcePath, 'cache', '.htaccess') - ); - $this->assertFileNotEquals( - Path::join($packageShopSourcePath, 'out', 'downloads', '.htaccess'), - Path::join($installedShopSourcePath, 'out', 'downloads', '.htaccess') - ); - $this->assertFileNotEquals( - Path::join($packageShopSourcePath, 'Application', 'views', 'admin', 'tpl', '.htaccess'), - Path::join($installedShopSourcePath, 'Application', 'views', 'admin', 'tpl', '.htaccess') - ); - $this->assertFileNotEquals( - Path::join($packageShopSourcePath, 'test', '.htaccess'), - Path::join($installedShopSourcePath, 'test', '.htaccess') - ); - } - - public function testInstallCopiesSetupFilesIfShopConfigIsMissing() - { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/config.inc.php.dist' => 'Example config', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Setup/index.php' => 'Setup index.php file', - ])); - - $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); - $installedShopSourcePath = Path::join($projectRoot, 'source'); - $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); - $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/source', [ + 'index.php' => ' 'tpl', + 'config.inc.php.dist' => 'dist', + ]); - $sut = $this->getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); - $sut->install($packageShopRootPath); + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $this->assertFileEquals( - Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), - Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/source/index.php', + 'source/index.php' ); - } - - public function testInstallOverwritesSetupFilesIfShopConfigIsMissing() - { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/config.inc.php.dist' => 'Example config', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Setup/index.php' => 'Setup index.php file', - 'projectRoot/source/Setup/index.php' => 'Old Setup index.php file', - ])); - - $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); - $installedShopSourcePath = Path::join($projectRoot, 'source'); - $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); - $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); - - $sut = $this->getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); - - $this->assertFileNotEquals( - Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), - Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/source/Application/views/template.tpl', + 'source/Application/views/template.tpl' ); - $sut->install($packageShopRootPath); - $this->assertFileEquals( - Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), - Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/source/config.inc.php.dist', + 'source/config.inc.php.dist' ); } - public function testInstallCopiesSetupFilesIfShopConfigIsNotConfigured() + public function testShopInstallProcessCopiesConfigFileIfItDoesNotExist() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/config.inc.php.dist' => 'Example config', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Setup/index.php' => 'Setup index.php file', - 'projectRoot/source/config.inc.php' => <<<'EOT' - $this->dbType = 'pdo_mysql'; - $this->dbHost = ''; - $this->dbPort = 3306; - $this->dbName = ''; - $this->dbUser = ''; - $this->dbPwd = ''; - $this->sShopURL = ''; - $this->sShopDir = ''; - $this->sCompileDir = ''; -EOT - ])); - - $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); - $installedShopSourcePath = Path::join($projectRoot, 'source'); - $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); - $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/source', [ + 'index.php' => ' 'dist', + ]); - $sut = $this->getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); - $sut->install($packageShopRootPath); + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $this->assertFileEquals( - Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), - Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/source/config.inc.php.dist', + 'source/config.inc.php' ); } - public function testInstallOverwritesSetupFilesIfShopConfigIsNotConfigured() + public function testShopInstallProcessDoesNotCopyConfigFileIfItAlreadyExists() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/config.inc.php.dist' => 'Example config', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Setup/index.php' => 'Setup index.php file', - - 'projectRoot/source/Setup/index.php' => 'Old Setup index.php file', - 'projectRoot/source/config.inc.php' => <<<'EOT' - $this->dbType = 'pdo_mysql'; - $this->dbHost = ''; - $this->dbPort = 3306; - $this->dbName = ''; - $this->dbUser = ''; - $this->dbPwd = ''; - $this->sShopURL = ''; - $this->sShopDir = ''; - $this->sCompileDir = ''; -EOT - ])); - - $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); - $installedShopSourcePath = Path::join($projectRoot, 'source'); - $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); - $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/source', [ + 'index.php' => ' 'dist', + ]); + $this->setupVirtualProjectRoot('source', [ + 'config.inc.php' => 'old', + ]); - $sut = $this->getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $this->assertFileNotEquals( - Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), - Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) - ); - $sut->install($packageShopRootPath); - $this->assertFileEquals( - Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), - Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) + $this->assertVirtualFileNotEquals( + 'vendor/test-vendor/test-package/source/config.inc.php.dist', + 'source/config.inc.php' ); } - public function testInstallDoesNotCopySetupFilesIfShopConfigIsConfigured() - { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/config.inc.php.dist' => 'Example config', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Setup/index.php' => 'Setup index.php file', - 'projectRoot/source/config.inc.php' => <<<'EOT' - $this->dbType = 'pdo_mysql'; - $this->dbHost = 'somehost'; - $this->dbPort = 3306; - $this->dbName = 'some_db_name'; - $this->dbUser = 'db_user'; - $this->dbPwd = 'db_pass'; - $this->sShopURL = 'http://some_url/'; - $this->sShopDir = '/var/www/shopdir/source'; - $this->sCompileDir = '/var/www/shopdir/source/tmp'; -EOT - ])); - - $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); - $installedShopSourcePath = Path::join($projectRoot, 'source'); - $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); - $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); - - $sut = $this->getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); - $sut->install($packageShopRootPath); - - $this->assertFileNotExists(Path::join($installedShopSourcePath, Path::join('Setup', 'index.php'))); - } - - public function testInstallDoesNotOverwriteSetupFilesIfShopConfigIsConfigured() + public function testShopInstallProcessDoesNotCopyFilteredClasses() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/config.inc.php.dist' => 'Example config', - 'projectRoot/vendor/oxid-esales/oxideshop-ce/source/Setup/index.php' => 'Setup index.php file', - 'projectRoot/source/Setup/index.php' => 'Old Setup index.php file', - 'projectRoot/source/config.inc.php' => <<<'EOT' - $this->dbType = 'pdo_mysql'; - $this->dbHost = 'somehost'; - $this->dbPort = 3306; - $this->dbName = 'some_db_name'; - $this->dbUser = 'db_user'; - $this->dbPwd = 'db_pass'; - $this->sShopURL = 'http://some_url/'; - $this->sShopDir = '/var/www/shopdir/source'; - $this->sCompileDir = '/var/www/shopdir/source/tmp'; -EOT - ])); - - $projectRoot = vfsStream::url(Path::join('root', 'projectRoot')); - $installedShopSourcePath = Path::join($projectRoot, 'source'); - $packageShopRootPath = Path::join($projectRoot, 'vendor', 'oxid-esales', 'oxideshop-ce'); - $packageShopSourcePath = Path::join($packageShopRootPath, 'source'); + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/source', [ + 'index.php' => ' ' ' ' ' ' 'dist', + ]); - $sut = $this->getSut(new NullIO, $installedShopSourcePath, $this->getShopPackage()); + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $this->assertFileNotEquals( - Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), - Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/source/Class.php', + 'source/Class.php' ); - $sut->install($packageShopRootPath); - $this->assertFileNotEquals( - Path::join($packageShopSourcePath, Path::join('Setup', 'index.php')), - Path::join($installedShopSourcePath, Path::join('Setup', 'index.php')) - ); - } - - /** - * @return Package - */ - private function getShopPackage() - { - $package = new Package('oxid-esales/oxideshop-ce', 'dev', 'dev'); - $package->setExtra([ - 'oxideshop' => [ - 'blacklist-filter' => [ - "Application/Component/**/*.*", - "Application/Controller/**/*.*", - "Application/Model/**/*.*", - "Core/**/*.*" - ] - ] - ]); - - return $package; + $this->assertVirtualFileNotExists('source/Core/Class.php'); + $this->assertVirtualFileNotExists('source/Application/Model/Class.php'); + $this->assertVirtualFileNotExists('source/Application/Controller/Class.php'); + $this->assertVirtualFileNotExists('source/Application/Component/Class.php'); } } diff --git a/tests/Integration/Installer/Package/ThemePackageInstallerTest.php b/tests/Integration/Installer/Package/ThemePackageInstallerTest.php index bad0f0a..3e1c27b 100644 --- a/tests/Integration/Installer/Package/ThemePackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ThemePackageInstallerTest.php @@ -31,209 +31,381 @@ use OxidEsales\ComposerPlugin\Utilities\VfsFileStructureOperator; use Webmozart\PathUtil\Path; -class ThemePackageInstallerTest extends \PHPUnit_Framework_TestCase +class ThemePackageInstallerTest extends AbstractPackageInstallerTest { - protected function getSut(IOInterface $io, $rootPath, PackageInterface $package) + protected function getPackageInstaller($packageName, $version = '1.0.0', $extra = []) { - return new ThemePackageInstaller($io, $rootPath, $package); + $package = new Package($packageName, $version, $version); + $package->setExtra($extra); + + return new ThemePackageInstaller( + new NullIO(), + $this->getVirtualShopSourcePath(), + $package + ); } - public function testChecksIfThemeIsNotInstalled() + public function testThemeNotInstalledByDefault() { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/'."oxid-esales/flow-theme".'/theme.php' => 'getPackageInstaller('test-vendor/test-package'); - $rootPath = vfsStream::url('root/projectRoot/source'); + $this->assertFalse($installer->isInstalled()); + } + + public function testThemeIsInstalledIfAlreadyExistsInShop() + { + $this->setupVirtualProjectRoot('source/Application/views/test-package', [ + 'theme.php' => 'getSut(new NullIO, $rootPath, $package); - $this->assertFalse($themeInstaller->isInstalled()); + $installer = $this->getPackageInstaller('test-vendor/test-package'); + + $this->assertTrue($installer->isInstalled()); } - public function testChecksIfThemeIsInstalled() - { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/source/Application/views/flow-theme/theme.php' => ' 'setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => 'getSut(new NullIO(), $rootPath, $package); - $this->assertTrue($shopPreparator->isInstalled()); + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertTrue($installer->isInstalled()); } - /** - * @return array - */ - public function providerChecksIfThemeFilesExistsAfterInstallation() + public function testThemeFilesAreCopiedAfterInstallProcess() { - return [ - [ - [ThemePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ThemePackageInstaller::EXTRA_PARAMETER_KEY_TARGET => 'flow']], - 'Application/views/flow/theme.php', - 'out/flow/style.css' - ], - [ - [], - 'Application/views/flow-theme/theme.php', - 'out/flow-theme/style.css' - ], - [ - [ThemePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ThemePackageInstaller::EXTRA_PARAMETER_KEY_ASSETS => 'custom_directory_name']], - 'Application/views/flow-theme/theme.php', - 'out/flow-theme/custom_style.css' - ], - [ - [ThemePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ - ThemePackageInstaller::EXTRA_PARAMETER_KEY_TARGET => 'flow', - ThemePackageInstaller::EXTRA_PARAMETER_KEY_ASSETS => 'custom_directory_name', - ]], - 'Application/views/flow/theme.php', - 'out/flow/custom_style.css' - ], - ]; + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => 'getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/theme.php', + 'source/Application/views/test-package/theme.php' + ); } - /** - * @param $composerExtras - * @param $installedThemeMetadata - * @param $assetsFile - * @dataProvider providerChecksIfThemeFilesExistsAfterInstallation - */ - public function testChecksIfThemeFilesExistsAfterInstallation($composerExtras, $installedThemeMetadata, $assetsFile) + public function testThemeFilesAreCopiedAfterInstallProcessWithSameTargetDirectory() { - $rootPath = vfsStream::url('root/projectRoot'); - $eshopRootPath = "$rootPath/source"; - $this->simulateInstallation($composerExtras, $rootPath, $eshopRootPath); + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => 'assertFileExists($installedThemeMetadata); - $this->assertFileExists($assetsFile); + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'target-directory' => 'test-package', + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/theme.php', + 'source/Application/views/test-package/theme.php' + ); } - public function testChecksIfAssetFileDoesNotExist() + public function testThemeFilesAreCopiedAfterInstallProcessWithCustomTargetDirectory() { - $composerExtras = [ThemePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ - ThemePackageInstaller::EXTRA_PARAMETER_KEY_TARGET => 'flow', - ThemePackageInstaller::EXTRA_PARAMETER_KEY_ASSETS => 'non_existing_directory', - ]]; + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => 'getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'target-directory' => 'custom-package', + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/theme.php', + 'source/Application/views/custom-package/theme.php' + ); + } - $rootPath = vfsStream::url('root/projectRoot'); - $eshopRootPath = "$rootPath/source"; - $this->simulateInstallation($composerExtras, $rootPath, $eshopRootPath); - $this->assertFileNotExists($eshopRootPath.'/out/non_existing_directory'); + public function testThemeAssetsAreCopiedAfterInstallProcess() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => ' 'css', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/out/style.css', + 'source/out/test-package/style.css' + ); } - public function testChecksIfAssetsDirectoryWasNotCopied() + public function testThemeAssetsAreCopiedAfterInstallProcessWithSameAssetsDirectory() { - $composerExtras = [ThemePackageInstaller::EXTRA_PARAMETER_KEY_ROOT => [ - ThemePackageInstaller::EXTRA_PARAMETER_KEY_TARGET => 'flow' - ]]; + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => ' 'css', + ]); - $rootPath = vfsStream::url('root/projectRoot'); - $eshopRootPath = "$rootPath/source"; - $this->simulateInstallation($composerExtras, $rootPath, $eshopRootPath); - $this->assertFileNotExists($eshopRootPath . '/Application/views/flow/out/style.css'); - } - - /** - * @param $composerExtras - * @return string - */ - protected function simulateInstallation($composerExtras, $rootPath, $eshopRootPath) - { - vfsStream::setup('root', 777, VfsFileStructureOperator::nest([ - 'projectRoot/vendor/oxid-esales/flow-theme/theme.php' => ' 'readme', - 'projectRoot/vendor/oxid-esales/flow-theme/out/style.css' => '.class {}', - 'projectRoot/vendor/oxid-esales/flow-theme/out/readme.pdf' => 'PDF', - 'projectRoot/vendor/oxid-esales/flow-theme/custom_directory_name/custom_style.css' => '.class {}', - ])); - - $package = new Package("oxid-esales/flow-theme", 'dev', 'dev'); - $shopPreparator = $this->getSut(new NullIO(), $eshopRootPath, $package); - $package->setExtra($composerExtras); - $themeInVendor = "$rootPath/vendor/oxid-esales/flow-theme"; - $shopPreparator->install($themeInVendor); + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'assets-directory' => 'out', + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/out/style.css', + 'source/out/test-package/style.css' + ); } - public function testBlacklistedFilesArePresentWhenNoBlacklistFilterIsDefined() + public function testThemeAssetsAreCopiedAfterInstallProcessWithSameTargetDirectory() { - $composerExtraParameters = [ + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => ' 'css', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ 'oxideshop' => [ - 'target-directory' => 'flow', + 'target-directory' => 'test-package', ] - ]; + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $rootPath = vfsStream::url('root/projectRoot'); - $shopRootPath = Path::join($rootPath, 'source'); + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/out/style.css', + 'source/out/test-package/style.css' + ); + } - $this->simulateInstallation($composerExtraParameters, $rootPath, $shopRootPath); + public function testThemeAssetsAreCopiedAfterInstallProcessWithSameAssetsDirectoryAndSameTargetDirectory() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => ' 'css', + ]); - $this->assertFileExists(Path::join($shopRootPath, 'Application', 'views', 'flow', 'readme.txt')); - $this->assertFileExists(Path::join($shopRootPath, 'out', 'flow', 'readme.pdf')); + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'assets-directory' => 'out', + 'target-directory' => 'test-package', + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/out/style.css', + 'source/out/test-package/style.css' + ); } - public function testBlacklistedFilesArePresentWhenEmptyBlacklistFilterIsDefined() + public function testThemeAssetsAreCopiedAfterInstallProcessWithCustomAssetsDirectory() { - $composerExtraParameters = [ + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => ' 'css', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ 'oxideshop' => [ - 'target-directory' => 'flow', - 'blacklist-filter' => [], + 'assets-directory' => 'custom_assets', ] - ]; + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/custom_assets/custom_style.css', + 'source/out/test-package/custom_style.css' + ); + } - $rootPath = vfsStream::url('root/projectRoot'); - $shopRootPath = Path::join($rootPath, 'source'); + public function testThemeAssetsAreCopiedAfterInstallProcessWithCustomTargetDirectory() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => ' 'css', + ]); - $this->simulateInstallation($composerExtraParameters, $rootPath, $shopRootPath); + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'target-directory' => 'custom-package', + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $this->assertFileExists(Path::join($shopRootPath, 'Application', 'views', 'flow', 'readme.txt')); - $this->assertFileExists(Path::join($shopRootPath, 'out', 'flow', 'readme.pdf')); + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/out/style.css', + 'source/out/custom-package/style.css' + ); + } + + public function testThemeAssetsAreCopiedAfterInstallProcessWithCustomAssetsDirectoryAndCustomTargetDirectory() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => ' 'css', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'assets-directory' => 'custom_assets', + 'target-directory' => 'custom-package', + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/custom_assets/custom_style.css', + 'source/out/custom-package/custom_style.css' + ); + } + + public function testThemeAssetsAreNotCopiedAfterInstallProcessWithNonExistingCustomAssetsDirectory() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => 'getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'assets-directory' => 'custom_assets', + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileNotExists('source/out/test-package/custom_style.css'); + } + + public function testBlacklistedFilesArePresentWhenNoBlacklistFilterIsDefined() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => ' 'txt', + 'out/style.css' => 'css', + 'out/style.pdf' => 'PDF', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileExists('source/Application/views/test-package/theme.php'); + $this->assertVirtualFileExists('source/Application/views/test-package/theme.txt'); + $this->assertVirtualFileExists('source/out/test-package/style.css'); + $this->assertVirtualFileExists('source/out/test-package/style.pdf'); + } + + public function testBlacklistedFilesArePresentWhenEmptyBlacklistFilterIsDefined() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => ' 'txt', + 'out/style.css' => 'css', + 'out/style.pdf' => 'PDF', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'blacklist-filter' => [] + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileExists('source/Application/views/test-package/theme.php'); + $this->assertVirtualFileExists('source/Application/views/test-package/theme.txt'); + $this->assertVirtualFileExists('source/out/test-package/style.css'); + $this->assertVirtualFileExists('source/out/test-package/style.pdf'); } public function testBlacklistedFilesArePresentWhenDifferentBlacklistFilterIsDefined() { - $composerExtraParameters = [ + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => ' 'txt', + 'out/style.css' => 'css', + 'out/style.pdf' => 'PDF', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ 'oxideshop' => [ - 'target-directory' => 'flow', 'blacklist-filter' => [ '**/*.doc' - ], + ] ] - ]; + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $rootPath = vfsStream::url('root/projectRoot'); - $shopRootPath = Path::join($rootPath, 'source'); - - $this->simulateInstallation($composerExtraParameters, $rootPath, $shopRootPath); - - $this->assertFileExists(Path::join($shopRootPath, 'Application', 'views', 'flow', 'readme.txt')); - $this->assertFileExists(Path::join($shopRootPath, 'out', 'flow', 'readme.pdf')); + $this->assertVirtualFileExists('source/Application/views/test-package/theme.php'); + $this->assertVirtualFileExists('source/Application/views/test-package/theme.txt'); + $this->assertVirtualFileExists('source/out/test-package/style.css'); + $this->assertVirtualFileExists('source/out/test-package/style.pdf'); } public function testBlacklistedFilesAreSkippedWhenABlacklistFilterIsDefined() { - $composerExtraParameters = [ + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => ' 'txt', + 'out/style.css' => 'css', + 'out/style.pdf' => 'PDF', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ 'oxideshop' => [ - 'target-directory' => 'flow', 'blacklist-filter' => [ - "**/*.txt", - "**/*.pdf", - ], + '**/*.txt', + '**/*.pdf', + ] ] - ]; + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); - $rootPath = vfsStream::url('root/projectRoot'); - $shopRootPath = Path::join($rootPath, 'source'); - - $this->simulateInstallation($composerExtraParameters, $rootPath, $shopRootPath); + $this->assertVirtualFileExists('source/Application/views/test-package/theme.php'); + $this->assertVirtualFileNotExists('source/Application/views/test-package/theme.txt'); + $this->assertVirtualFileExists('source/out/test-package/style.css'); + $this->assertVirtualFileNotExists('source/out/test-package/style.pdf'); + } - $this->assertFileNotExists(Path::join($shopRootPath, 'Application', 'views', 'flow', 'readme.txt')); - $this->assertFileNotExists(Path::join($shopRootPath, 'out', 'flow', 'readme.pdf')); + public function testComplexCase() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => ' 'txt', + 'out/style.css' => 'css', + 'out/style.pdf' => 'PDF', + 'custom_assets/custom_style.css' => 'css', + 'custom_assets/custom_style.pdf' => 'PDF', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'assets-directory' => 'custom_assets', + 'target-directory' => 'custom-package', + 'blacklist-filter' => [ + '**/*.txt', + '**/*.pdf', + ] + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertTrue($installer->isInstalled()); + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/theme.php', + 'source/Application/views/custom-package/theme.php' + ); + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/custom_assets/custom_style.css', + 'source/out/custom-package/custom_style.css' + ); + $this->assertVirtualFileNotExists('source/Application/views/custom-package/theme.txt'); + $this->assertVirtualFileNotExists('source/out/custom-package/style.css'); + $this->assertVirtualFileNotExists('source/out/custom-package/style.pdf'); + $this->assertVirtualFileNotExists('source/out/custom-package/custom_style.pdf'); } } From e84cde28911de357782bf7b15327cc3440657ef9 Mon Sep 17 00:00:00 2001 From: Edvinas Aleksejonokas Date: Fri, 2 Jun 2017 17:17:51 +0300 Subject: [PATCH 10/13] ESDEV-4443 Integrate Travis Task: ESDEV-4539 --- .travis.yml | 15 +++++++++++++++ README.rst | 3 +++ 2 files changed, 18 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..fd1eeb9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,15 @@ +language: php + +notifications: + email: false + +php: + - "5.6" + - "7.0" + - "7.1" + +install: + - composer install + +script: + - vendor/bin/phpunit tests diff --git a/README.rst b/README.rst index 4d4c643..89ef6a5 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,9 @@ OXID eShop composer plugin ========================== +.. image:: https://travis-ci.org/OXID-eSales/oxideshop_composer_plugin.svg?branch=master + :target: https://travis-ci.org/OXID-eSales/oxideshop_composer_plugin + This plugin is used to install OXID eShop and OXID eShop third party integrations (modules, themes). More information how to install OXID eShop using this plugin can be found `here `__. From dbdb8d906369706020d808c085c8a134413b898d Mon Sep 17 00:00:00 2001 From: Edvinas Aleksejonokas Date: Mon, 5 Jun 2017 11:35:12 +0300 Subject: [PATCH 11/13] ESDEV-4443 Add packagist badge --- README.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.rst b/README.rst index 89ef6a5..2f7df49 100644 --- a/README.rst +++ b/README.rst @@ -4,6 +4,9 @@ OXID eShop composer plugin .. image:: https://travis-ci.org/OXID-eSales/oxideshop_composer_plugin.svg?branch=master :target: https://travis-ci.org/OXID-eSales/oxideshop_composer_plugin +.. image:: https://img.shields.io/packagist/v/oxid-esales/oxideshop-composer-plugin.svg?maxAge=3600 + :target: https://packagist.org/packages/oxid-esales/oxideshop-composer-plugin + This plugin is used to install OXID eShop and OXID eShop third party integrations (modules, themes). More information how to install OXID eShop using this plugin can be found `here `__. From f270589a5fa662b26336159cd54b9daa1c898df1 Mon Sep 17 00:00:00 2001 From: Edvinas Aleksejonokas Date: Mon, 12 Jun 2017 13:31:26 +0300 Subject: [PATCH 12/13] ESDEV-4541 Change globExpressionList definition Feedback/request to change from review. As empty filter and null filter does not have different behaviour there is no need to have null filter available. --- .../CopyGlobFilteredFileManager.php | 8 ++++---- .../CopyGlobFilteredFileManagerTest.php | 17 +---------------- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/Utilities/CopyFileManager/CopyGlobFilteredFileManager.php b/src/Utilities/CopyFileManager/CopyGlobFilteredFileManager.php index 05bd95c..cdd92c9 100644 --- a/src/Utilities/CopyFileManager/CopyGlobFilteredFileManager.php +++ b/src/Utilities/CopyFileManager/CopyGlobFilteredFileManager.php @@ -37,16 +37,16 @@ class CopyGlobFilteredFileManager /** * Copy files/directories from source to destination. * - * @param string $sourcePath Absolute path to file or directory. - * @param string $destinationPath Absolute path to file or directory. - * @param array|null $globExpressionList List of glob expressions, e.g. ["*.txt", "*.pdf"]. + * @param string $sourcePath Absolute path to file or directory. + * @param string $destinationPath Absolute path to file or directory. + * @param array $globExpressionList List of glob expressions, e.g. ["*.txt", "*.pdf"]. * * @throws \InvalidArgumentException If given $sourcePath is not a string. * @throws \InvalidArgumentException If given $destinationPath is not a string. * * @return null */ - public static function copy($sourcePath, $destinationPath, $globExpressionList = null) + public static function copy($sourcePath, $destinationPath, $globExpressionList = []) { if (!is_string($sourcePath)) { $message = "Given value \"$sourcePath\" is not a valid source path entry. ". diff --git a/tests/Unit/Utilities/CopyFileManager/CopyGlobFilteredFileManagerTest.php b/tests/Unit/Utilities/CopyFileManager/CopyGlobFilteredFileManagerTest.php index 28c29d0..b273683 100644 --- a/tests/Unit/Utilities/CopyFileManager/CopyGlobFilteredFileManagerTest.php +++ b/tests/Unit/Utilities/CopyFileManager/CopyGlobFilteredFileManagerTest.php @@ -39,7 +39,7 @@ class CopyGlobFilteredFileManagerTest extends \PHPUnit_Framework_TestCase { /** @var array */ - private $filter; + private $filter = []; public function testBasicFileCopyOperation() { @@ -167,21 +167,6 @@ public function testSingleFileCopyFilteringOperation() $this->assertFilesNotExistInDestination(['modules.txt']); } - public function testSingleFileCopyFilteringOperationWhenNoFilterIsDefined() - { - $inputFiles = [ - "module.txt" => "TXT_1", - ]; - - $this->prepareVirtualFileSystem($inputFiles, []); - - $this->setFilter(null); - $this->simulateCopyWithFilter('module.txt', 'module.txt'); - - $this->assertFilesExistInSource(['module.txt']); - $this->assertFilesNotExistInDestination(['modules.txt']); - } - public function testSingleFileCopyFilteringOperationWhenFilterIsEmpty() { $inputFiles = [ From d54c286e0ef97d75244b58134bdf535427f111f2 Mon Sep 17 00:00:00 2001 From: Edvinas Aleksejonokas Date: Mon, 12 Jun 2017 14:16:43 +0300 Subject: [PATCH 13/13] ESDEV-4541 Exclude `.git` files Feedback/request to change from review. There is no reason to copy .git files as they will not be used for run-time. --- .../Package/AbstractPackageInstaller.php | 38 ++++++++++++- .../Package/ModulePackageInstaller.php | 7 ++- .../Package/ShopPackageInstaller.php | 12 +++-- .../Package/ThemePackageInstaller.php | 13 +++-- .../Package/ModulePackageInstallerTest.php | 50 +++++++++++++++++ .../Package/ShopPackageInstallerTest.php | 31 +++++++++-- .../Package/ThemePackageInstallerTest.php | 53 +++++++++++++++++++ 7 files changed, 186 insertions(+), 18 deletions(-) diff --git a/src/Installer/Package/AbstractPackageInstaller.php b/src/Installer/Package/AbstractPackageInstaller.php index 9089821..8a082ce 100644 --- a/src/Installer/Package/AbstractPackageInstaller.php +++ b/src/Installer/Package/AbstractPackageInstaller.php @@ -49,7 +49,16 @@ abstract class AbstractPackageInstaller const EXTRA_PARAMETER_FILTER_BLACKLIST = 'blacklist-filter'; /** Glob expression to filter all files, might be used to filter whole directory. */ - const BLACKLIST_ALL_FILES = '**/*.*'; + const BLACKLIST_ALL_FILES = '**/*'; + + /** Name of directory to be excluded for VCS */ + const BLACKLIST_VCS_DIRECTORY = '.git'; + + /** Name of ignore files to be excluded for VCS */ + const BLACKLIST_VCS_IGNORE_FILE = '.gitignore'; + + /** Glob filter expression to exclude VCS files */ + const BLACKLIST_VCS_DIRECTORY_FILTER = self::BLACKLIST_VCS_DIRECTORY . DIRECTORY_SEPARATOR . self::BLACKLIST_ALL_FILES; /** @var IOInterface */ private $io; @@ -159,6 +168,33 @@ protected function getBlacklistFilterValue() return $this->getExtraParameterValueByKey(static::EXTRA_PARAMETER_FILTER_BLACKLIST, []); } + /** + * Get VCS glob filter expression + * + * @return array + */ + protected function getVCSFilter() + { + return [self::BLACKLIST_VCS_DIRECTORY_FILTER, self::BLACKLIST_VCS_IGNORE_FILE]; + } + + /** + * Combine multiple glob expression lists into one list + * + * @param array $listOfGlobExpressionLists E.g. [["*.txt", "*.pdf"], ["*.md"]] + * + * @return array + */ + protected function getCombinedFilters($listOfGlobExpressionLists) + { + $filters = []; + foreach ($listOfGlobExpressionLists as $filter) { + $filters = array_merge($filters, $filter); + } + + return $filters; + } + /** * @param string $messageToAsk * @return bool diff --git a/src/Installer/Package/ModulePackageInstaller.php b/src/Installer/Package/ModulePackageInstaller.php index 5b72a06..532e211 100644 --- a/src/Installer/Package/ModulePackageInstaller.php +++ b/src/Installer/Package/ModulePackageInstaller.php @@ -73,10 +73,15 @@ public function update($packagePath) */ protected function copyPackage($packagePath) { + $filtersToApply = [ + $this->getBlacklistFilterValue(), + $this->getVCSFilter(), + ]; + CopyGlobFilteredFileManager::copy( $this->formSourcePath($packagePath), $this->formTargetPath(), - $this->getBlacklistFilterValue() + $this->getCombinedFilters($filtersToApply) ); } diff --git a/src/Installer/Package/ShopPackageInstaller.php b/src/Installer/Package/ShopPackageInstaller.php index eee0823..a0f38ee 100644 --- a/src/Installer/Package/ShopPackageInstaller.php +++ b/src/Installer/Package/ShopPackageInstaller.php @@ -37,7 +37,7 @@ class ShopPackageInstaller extends AbstractPackageInstaller const SHOP_SOURCE_DIRECTORY = 'source'; const SHOP_SOURCE_SETUP_DIRECTORY = 'Setup'; const HTACCESS_FILTER = '**/.htaccess'; - const SETUP_FILES_FILTER = self::SHOP_SOURCE_SETUP_DIRECTORY . '/**/*.*'; + const SETUP_FILES_FILTER = self::SHOP_SOURCE_SETUP_DIRECTORY . AbstractPackageInstaller::BLACKLIST_ALL_FILES; /** * @return bool @@ -92,15 +92,17 @@ private function copyPackage($packagePath) */ private function copyShopSourceFromPackageToTarget($packagePath) { - $blacklistFilterWithHtAccess = array_merge( + $filtersToApply = [ $this->getBlacklistFilterValue(), - [self::HTACCESS_FILTER, self::SETUP_FILES_FILTER] - ); + [self::HTACCESS_FILTER], + [self::SETUP_FILES_FILTER], + $this->getVCSFilter(), + ]; CopyGlobFilteredFileManager::copy( $this->getPackageDirectoryOfShopSource($packagePath), $this->getTargetDirectoryOfShopSource(), - $blacklistFilterWithHtAccess + $this->getCombinedFilters($filtersToApply) ); } diff --git a/src/Installer/Package/ThemePackageInstaller.php b/src/Installer/Package/ThemePackageInstaller.php index 0d27d19..20ea76f 100644 --- a/src/Installer/Package/ThemePackageInstaller.php +++ b/src/Installer/Package/ThemePackageInstaller.php @@ -72,17 +72,16 @@ public function update($packagePath) */ protected function copyPackage($packagePath) { - $filter = [Path::join($this->formAssetsDirectoryName(), AbstractPackageInstaller::BLACKLIST_ALL_FILES)]; - $filterFromExtras = $this->getBlacklistFilterValue(); - - if (is_array($filterFromExtras)) { - $filter = array_merge($filter, $filterFromExtras); - } + $filtersToApply = [ + [Path::join($this->formAssetsDirectoryName(), AbstractPackageInstaller::BLACKLIST_ALL_FILES)], + $this->getBlacklistFilterValue(), + $this->getVCSFilter(), + ]; CopyGlobFilteredFileManager::copy( $packagePath, $this->formThemeTargetPath(), - $filter + $this->getCombinedFilters($filtersToApply) ); $this->installAssets($packagePath); diff --git a/tests/Integration/Installer/Package/ModulePackageInstallerTest.php b/tests/Integration/Installer/Package/ModulePackageInstallerTest.php index 4ac7a76..140a632 100644 --- a/tests/Integration/Installer/Package/ModulePackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ModulePackageInstallerTest.php @@ -287,6 +287,56 @@ public function testBlacklistedFilesAreSkippedWhenABlacklistFilterIsDefined() $this->assertVirtualFileNotExists('source/modules/test-vendor/test-package/readme.txt'); } + public function testVCSFilesAreSkippedWhenNoBlacklistFilterIsDefined() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'metadata.php' => ' 'HEAD', + '.git/index' => 'index', + '.git/objects/ff/fftest' => 'blob', + '.gitignore' => 'git ignore', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileExists('source/modules/test-vendor/test-package/metadata.php'); + $this->assertVirtualFileNotExists('source/modules/test-vendor/test-package/.git/HEAD'); + $this->assertVirtualFileNotExists('source/modules/test-vendor/test-package/.git/index'); + $this->assertVirtualFileNotExists('source/modules/test-vendor/test-package/.git/objects/ff/fftest'); + $this->assertVirtualFileNotExists('source/modules/test-vendor/test-package/.gitignore'); + } + + public function testVCSFilesAreSkippedWhenABlacklistFilterIsDefined() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'metadata.php' => ' ' 'readme', + '.git/HEAD' => 'HEAD', + '.git/index' => 'index', + '.git/objects/ff/fftest' => 'blob', + '.gitignore' => 'git ignore', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'blacklist-filter' => [ + '**/*.txt' + ] + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileExists('source/modules/test-vendor/test-package/metadata.php'); + $this->assertVirtualFileExists('source/modules/test-vendor/test-package/module.php'); + $this->assertVirtualFileNotExists('source/modules/test-vendor/test-package/readme.txt'); + $this->assertVirtualFileNotExists('source/modules/test-vendor/test-package/.git/HEAD'); + $this->assertVirtualFileNotExists('source/modules/test-vendor/test-package/.git/index'); + $this->assertVirtualFileNotExists('source/modules/test-vendor/test-package/.git/objects/ff/fftest'); + $this->assertVirtualFileNotExists('source/modules/test-vendor/test-package/.gitignore'); + } + public function testComplexCase() { $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/custom-root', [ diff --git a/tests/Integration/Installer/Package/ShopPackageInstallerTest.php b/tests/Integration/Installer/Package/ShopPackageInstallerTest.php index 4ac53c6..846b315 100644 --- a/tests/Integration/Installer/Package/ShopPackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ShopPackageInstallerTest.php @@ -37,10 +37,10 @@ protected function getPackageInstaller($packageName, $version = '1.0.0', $extra { $package = new Package($packageName, $version, $version); $extra['oxideshop']['blacklist-filter'] = [ - "Application/Component/**/*.*", - "Application/Controller/**/*.*", - "Application/Model/**/*.*", - "Core/**/*.*" + "Application/Component/**/*", + "Application/Controller/**/*", + "Application/Model/**/*", + "Core/**/*" ]; $package->setExtra($extra); @@ -166,4 +166,27 @@ public function testShopInstallProcessDoesNotCopyFilteredClasses() $this->assertVirtualFileNotExists('source/Application/Controller/Class.php'); $this->assertVirtualFileNotExists('source/Application/Component/Class.php'); } + + public function testShopInstallProcessDoesNotCopyVCSFiles() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package/source', [ + 'index.php' => ' 'HEAD', + '.git/index' => 'index', + '.git/objects/ff/fftest' => 'blob', + '.gitignore' => 'git ignore', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileEquals( + 'vendor/test-vendor/test-package/source/index.php', + 'source/index.php' + ); + $this->assertVirtualFileNotExists('source/.git/HEAD'); + $this->assertVirtualFileNotExists('source/.git/index'); + $this->assertVirtualFileNotExists('source/.git/objects/ff/fftest'); + $this->assertVirtualFileNotExists('source/.gitignore'); + } } diff --git a/tests/Integration/Installer/Package/ThemePackageInstallerTest.php b/tests/Integration/Installer/Package/ThemePackageInstallerTest.php index 3e1c27b..78624f4 100644 --- a/tests/Integration/Installer/Package/ThemePackageInstallerTest.php +++ b/tests/Integration/Installer/Package/ThemePackageInstallerTest.php @@ -371,6 +371,59 @@ public function testBlacklistedFilesAreSkippedWhenABlacklistFilterIsDefined() $this->assertVirtualFileNotExists('source/out/test-package/style.pdf'); } + public function testVCSFilesAreSkippedWhenNoBlacklistFilterIsDefined() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => ' 'HEAD', + '.git/index' => 'index', + '.git/objects/ff/fftest' => 'blob', + '.gitignore' => 'git ignore', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0'); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileExists('source/Application/views/test-package/theme.php'); + $this->assertVirtualFileNotExists('source/Application/views/test-package/.git/HEAD'); + $this->assertVirtualFileNotExists('source/Application/views/test-package/.git/index'); + $this->assertVirtualFileNotExists('source/Application/views/test-package/.git/objects/ff/fftest'); + $this->assertVirtualFileNotExists('source/Application/views/test-package/.gitignore'); + } + + public function testVCSFilesAreSkippedWhenABlacklistFilterIsDefined() + { + $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [ + 'theme.php' => ' 'txt', + '.git/HEAD' => 'HEAD', + '.git/index' => 'index', + '.git/objects/ff/fftest' => 'blob', + '.gitignore' => 'git ignore', + 'out/style.css' => 'css', + 'out/style.pdf' => 'PDF', + ]); + + $installer = $this->getPackageInstaller('test-vendor/test-package', '1.0.0', [ + 'oxideshop' => [ + 'blacklist-filter' => [ + '**/*.txt', + '**/*.pdf', + ] + ] + ]); + $installer->install($this->getVirtualFileSystemRootPath('vendor/test-vendor/test-package')); + + $this->assertVirtualFileExists('source/Application/views/test-package/theme.php'); + $this->assertVirtualFileNotExists('source/Application/views/test-package/theme.txt'); + $this->assertVirtualFileExists('source/out/test-package/style.css'); + $this->assertVirtualFileNotExists('source/out/test-package/style.pdf'); + $this->assertVirtualFileNotExists('source/Application/views/test-package/.git/HEAD'); + $this->assertVirtualFileNotExists('source/Application/views/test-package/.git/index'); + $this->assertVirtualFileNotExists('source/Application/views/test-package/.git/objects/ff/fftest'); + $this->assertVirtualFileNotExists('source/Application/views/test-package/.gitignore'); + } + public function testComplexCase() { $this->setupVirtualProjectRoot('vendor/test-vendor/test-package', [