From 6a604f31ed483082fc28c148486e3f7a72e9001a Mon Sep 17 00:00:00 2001 From: Oleh Posyniak <oposyniak@magento.com> Date: Fri, 30 Dec 2016 14:53:50 +0200 Subject: [PATCH] MAGETWO-62655: [GitHub] CLI won't work without write permissions #7933 --- .../Magento/Framework/Console/Cli.php | 50 ++++++--- .../Setup/Console/CompilerPreparation.php | 27 +++++ .../Unit/Console/CompilerPreparationTest.php | 103 ++++++++++++------ 3 files changed, 133 insertions(+), 47 deletions(-) diff --git a/lib/internal/Magento/Framework/Console/Cli.php b/lib/internal/Magento/Framework/Console/Cli.php index 6cc742273b4..38018a7c096 100644 --- a/lib/internal/Magento/Framework/Console/Cli.php +++ b/lib/internal/Magento/Framework/Console/Cli.php @@ -72,20 +72,7 @@ class Cli extends Console\Application $this->initObjectManager(); $this->assertGenerationPermissions(); - - /** - * Temporary workaround until the compiler is able to clear the generation directory - * @todo remove after MAGETWO-44493 resolved - */ - if (class_exists(CompilerPreparation::class)) { - $compilerPreparation = new CompilerPreparation( - $this->serviceManager, - new Console\Input\ArgvInput(), - new File() - ); - - $compilerPreparation->handleCompilerEnvironment(); - } + $this->assertCompilerPreparation(); if ($version == 'UNKNOWN') { $directoryList = new DirectoryList(BP); @@ -127,7 +114,7 @@ class Cli extends Console\Application } /** - * Gets application commands + * Gets application commands. * * @return array a list of available application commands */ @@ -207,6 +194,39 @@ class Cli extends Console\Application } } + /** + * Checks whether compiler preparation is being prepared. + * + * @return void + * @SuppressWarnings(PHPMD.ExitExpression) + */ + private function assertCompilerPreparation() + { + /** + * Temporary workaround until the compiler is able to clear the generation directory + * @todo remove after MAGETWO-44493 resolved + */ + if (class_exists(CompilerPreparation::class)) { + $compilerPreparation = new CompilerPreparation( + $this->serviceManager, + new Console\Input\ArgvInput(), + new File() + ); + + try { + $compilerPreparation->handleCompilerEnvironment(); + } catch (\Magento\Framework\Exception\FileSystemException $e) { + $output = new \Symfony\Component\Console\Output\ConsoleOutput(); + $output->writeln( + '<error>Command line user does not have read and write permissions on var/generation directory. Please' + . ' address this issue before using Magento command line.</error>' + ); + + exit(static::RETURN_FAILURE); + } + } + } + /** * Retrieves vendor commands. * diff --git a/setup/src/Magento/Setup/Console/CompilerPreparation.php b/setup/src/Magento/Setup/Console/CompilerPreparation.php index 3e677d30ce1..3fab11cbf08 100644 --- a/setup/src/Magento/Setup/Console/CompilerPreparation.php +++ b/setup/src/Magento/Setup/Console/CompilerPreparation.php @@ -9,7 +9,9 @@ namespace Magento\Setup\Console; use Magento\Framework\App\Bootstrap; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Console\GenerationDirectoryAccess; use Magento\Framework\Filesystem\Driver\File; +use Magento\Framework\Phrase; use Magento\Setup\Console\Command\DiCompileCommand; use Magento\Setup\Mvc\Bootstrap\InitParamListener; use Symfony\Component\Console\Input\ArgvInput; @@ -25,6 +27,11 @@ class CompilerPreparation /** @var File */ private $filesystemDriver; + /** + * @var GenerationDirectoryAccess + */ + private $generationDirectoryAccess; + /** * @param \Zend\ServiceManager\ServiceManager $serviceManager * @param ArgvInput $input @@ -63,10 +70,30 @@ class CompilerPreparation $compileDirList[] = $directoryList->getPath(DirectoryList::GENERATION); $compileDirList[] = $directoryList->getPath(DirectoryList::DI); + if (!$this->getGenerationDirectoryAccess()->check()) { + throw new \Magento\Framework\Exception\FileSystemException( + new Phrase('Generation directory can not be written.') + ); + } + foreach ($compileDirList as $compileDir) { if ($this->filesystemDriver->isExists($compileDir)) { $this->filesystemDriver->deleteDirectory($compileDir); } } } + + /** + * Retrieves generation directory access checker. + * + * @return GenerationDirectoryAccess the generation directory access checker + */ + private function getGenerationDirectoryAccess() + { + if (null === $this->generationDirectoryAccess) { + $this->generationDirectoryAccess = new GenerationDirectoryAccess($this->serviceManager); + } + + return $this->generationDirectoryAccess; + } } diff --git a/setup/src/Magento/Setup/Test/Unit/Console/CompilerPreparationTest.php b/setup/src/Magento/Setup/Test/Unit/Console/CompilerPreparationTest.php index 9351010dbd0..7cea01d8445 100644 --- a/setup/src/Magento/Setup/Test/Unit/Console/CompilerPreparationTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/CompilerPreparationTest.php @@ -3,46 +3,67 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Setup\Test\Unit\Console; - +use Magento\Framework\Console\GenerationDirectoryAccess; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Setup\Console\Command\DiCompileCommand; use Magento\Setup\Mvc\Bootstrap\InitParamListener; +use Magento\Framework\Filesystem\Driver\File; use Symfony\Component\Console\Input\ArgvInput; +use Zend\ServiceManager\ServiceManager; +use Magento\Setup\Console\CompilerPreparation; +use PHPUnit_Framework_MockObject_MockObject as Mock; class CompilerPreparationTest extends \PHPUnit_Framework_TestCase { - /** @var \Magento\Setup\Console\CompilerPreparation */ + /** + * @var CompilerPreparation|Mock + */ private $model; - /** @var \Zend\ServiceManager\ServiceManager | \PHPUnit_Framework_MockObject_MockObject */ + /** + * @var ServiceManager|Mock + */ private $serviceManagerMock; - /** @var \Symfony\Component\Console\Input\ArgvInput | \PHPUnit_Framework_MockObject_MockObject */ + /** + * @var ArgvInput|Mock + */ private $inputMock; - /** @var \Magento\Framework\Filesystem\Driver\File | \PHPUnit_Framework_MockObject_MockObject */ + /** + * @var File|Mock + */ private $filesystemDriverMock; + /** + * @var GenerationDirectoryAccess|Mock + */ + private $generationDirectoryAccessMock; + public function setUp() { - $this->serviceManagerMock = $this->getMockBuilder(\Zend\ServiceManager\ServiceManager::class) + $this->serviceManagerMock = $this->getMockBuilder(ServiceManager::class) + ->disableOriginalConstructor() + ->getMock(); + $this->inputMock = $this->getMockBuilder(ArgvInput::class) ->disableOriginalConstructor() ->getMock(); - $this->inputMock = $this->getMockBuilder(\Symfony\Component\Console\Input\ArgvInput::class) + $this->filesystemDriverMock = $this->getMockBuilder(File::class) ->disableOriginalConstructor() ->getMock(); - $this->filesystemDriverMock = $this->getMockBuilder(\Magento\Framework\Filesystem\Driver\File::class) + $this->generationDirectoryAccessMock = $this->getMockBuilder(GenerationDirectoryAccess::class) ->disableOriginalConstructor() ->getMock(); + $this->model = (new ObjectManager($this))->getObject( - \Magento\Setup\Console\CompilerPreparation::class, + CompilerPreparation::class, [ 'serviceManager' => $this->serviceManagerMock, 'input' => $this->inputMock, - 'filesystemDriver' => $this->filesystemDriverMock + 'filesystemDriver' => $this->filesystemDriverMock, + 'generationDirectoryAccess' => $this->generationDirectoryAccessMock, ] ); } @@ -56,21 +77,31 @@ class CompilerPreparationTest extends \PHPUnit_Framework_TestCase */ public function testClearGenerationDirWhenNeeded($commandName, $isCompileCommand, $isHelpOption, $dirExists = false) { - $this->inputMock->expects($this->once())->method('getFirstArgument')->willReturn($commandName); + $this->inputMock->expects($this->once()) + ->method('getFirstArgument') + ->willReturn($commandName); $this->inputMock->expects($this->atLeastOnce()) ->method('hasParameterOption') - ->with( - $this->logicalOr('--help', '-h') - )->willReturn($isHelpOption); + ->with($this->logicalOr('--help', '-h')) + ->willReturn($isHelpOption); + if ($isCompileCommand && !$isHelpOption) { $this->filesystemDriverMock->expects($this->exactly(2)) ->method('isExists') ->willReturn($dirExists); - $this->filesystemDriverMock->expects($this->exactly(((int)$dirExists) * 2))->method('deleteDirectory'); + $this->filesystemDriverMock->expects($this->exactly(((int)$dirExists) * 2)) + ->method('deleteDirectory'); } else { - $this->filesystemDriverMock->expects($this->never())->method('isExists'); - $this->filesystemDriverMock->expects($this->never())->method('deleteDirectory'); + $this->filesystemDriverMock->expects($this->never()) + ->method('isExists'); + $this->filesystemDriverMock->expects($this->never()) + ->method('deleteDirectory'); } + + $this->generationDirectoryAccessMock->expects($this->any()) + ->method('check') + ->willReturn(true); + $this->model->handleCompilerEnvironment(); } @@ -108,10 +139,6 @@ class CompilerPreparationTest extends \PHPUnit_Framework_TestCase $customGenerationDirectory = '/custom/generated/code/directory'; $defaultDiDirectory = '/custom/di/directory'; $mageInitParams = ['MAGE_DIRS' => ['generation' => ['path' => $customGenerationDirectory]]]; - - $this->inputMock->expects($this->once()) - ->method('getFirstArgument') - ->willReturn(DiCompileCommand::NAME); $dirValueMap = [ [ $customGenerationDirectory, @@ -122,16 +149,24 @@ class CompilerPreparationTest extends \PHPUnit_Framework_TestCase true ] ]; - // Filesystem mock - $this->filesystemDriverMock->expects($this->exactly(2))->method('isExists')->willReturn(true); + + $this->inputMock->expects($this->once()) + ->method('getFirstArgument') + ->willReturn(DiCompileCommand::NAME); + $this->filesystemDriverMock->expects($this->exactly(2)) + ->method('isExists') + ->willReturn(true); $this->filesystemDriverMock->expects($this->exactly(2)) ->method('deleteDirectory') - ->will($this->returnValueMap($dirValueMap)); - + ->willReturnMap($dirValueMap); $this->serviceManagerMock->expects($this->once()) ->method('get') ->with(InitParamListener::BOOTSTRAP_PARAM) ->willReturn($mageInitParams); + $this->generationDirectoryAccessMock->expects($this->once()) + ->method('check') + ->willReturn(true); + $this->model->handleCompilerEnvironment(); } @@ -139,10 +174,6 @@ class CompilerPreparationTest extends \PHPUnit_Framework_TestCase { $customGenerationDirectory = '/custom/generated/code/directory'; $customDiDirectory = '/custom/di/directory'; - - $this->inputMock->expects($this->once()) - ->method('getFirstArgument') - ->willReturn(DiCompileCommand::NAME); $dirResultMap = [ [ $this->logicalNot($this->equalTo($customGenerationDirectory)), @@ -154,10 +185,18 @@ class CompilerPreparationTest extends \PHPUnit_Framework_TestCase ] ]; - $this->filesystemDriverMock->expects($this->exactly(2))->method('isExists')->willReturn(true); + $this->inputMock->expects($this->once()) + ->method('getFirstArgument') + ->willReturn(DiCompileCommand::NAME); + $this->filesystemDriverMock->expects($this->exactly(2)) + ->method('isExists') + ->willReturn(true); $this->filesystemDriverMock->expects($this->exactly(2)) ->method('deleteDirectory') - ->will($this->returnValueMap($dirResultMap)); + ->willReturnMap($dirResultMap); + $this->generationDirectoryAccessMock->expects($this->once()) + ->method('check') + ->willReturn(true); $this->model->handleCompilerEnvironment(); } -- GitLab