From 720fed1a431bd7b3c29da9065432c4289b12f659 Mon Sep 17 00:00:00 2001 From: NasirNobin Date: Tue, 22 Mar 2022 19:07:45 +0600 Subject: [PATCH] refactor code & tests --- cli/Valet/Brew.php | 55 +++++++++++++++++---------- cli/valet.php | 5 ++- tests/BrewTest.php | 92 +++++++++++++++++++++++++++++----------------- 3 files changed, 97 insertions(+), 55 deletions(-) diff --git a/cli/Valet/Brew.php b/cli/Valet/Brew.php index d42e63b..8caf5a4 100644 --- a/cli/Valet/Brew.php +++ b/cli/Valet/Brew.php @@ -303,37 +303,59 @@ function ($version) use ($resolvedPhpVersion) { * Get PHP binary path for a given PHP Version * * @param string|null $phpVersion + * @param boolean $skipCache * * @return string */ - public function getPhpBinaryPath($phpVersion = null) + public function whichPhp($phpVersion = null, $skipCache = false) { if(! $phpVersion){ return BREW_PREFIX.'/bin/php'; } - $phpBinaryPath = null; $versionInteger = preg_replace('~[^\d]~', '', $phpVersion); $symlinkedValetPhpPath = BREW_PREFIX. "/bin/valetphp{$versionInteger}"; - // If the symlinked valet php path exists, then we can use that - if ($this->files->isLink($symlinkedValetPhpPath)) { + // If the symlinked Valet PHP path exists, then we can use that + if (!$skipCache && $this->files->isLink($symlinkedValetPhpPath)) { $phpBinaryPath = $this->files->readLink($symlinkedValetPhpPath); - // Still make sure that the version of the binrary exists + // Still make sure that the version of the binary exists if ($this->files->exists($phpBinaryPath)) { - return $symlinkedValetPhpPath; + return $phpBinaryPath; } } - // If the symlinked valet php path doesn't exist, then we need to look for the correct binary path - $cellar = $this->cli->runAsUser("brew --cellar $phpVersion"); // Example output: `/opt/homebrew/Cellar/php@8.0` - $details = json_decode($this->cli->runAsUser("brew info --json $phpVersion")); + // Create a symlink to the Valet PHP version, so next time valet won't have to look for the binary path + if ($phpBinaryPath = $this->getPhpBinaryPath($phpVersion)) { + $this->files->symlinkAsUser($phpBinaryPath, $symlinkedValetPhpPath); + } - if (!empty($details[0]->linked_keg)) { - $phpDirectory = $details[0]->linked_keg; - } elseif (!empty($details[0]->installed[0]->version)) { - $phpDirectory = $details[0]->installed[0]->version; + return $phpBinaryPath ?: BREW_PREFIX.'/bin/php'; + } + + + /** + * Get PHP binary path from PHP Version + * + * @param string $phpVersion + * @return string + */ + public function getPhpBinaryPath($phpVersion) + { + $phpBinaryPath = null; + + // If the symlinked Valet PHP path doesn't exist, then we need to look for the correct binary path + $cellar = $this->cli->runAsUser("brew --cellar $phpVersion"); // Example output: `/opt/homebrew/Cellar/php@8.0` + $details = json_decode($this->cli->runAsUser("brew info --json $phpVersion"), true); + $phpDirectory = data_get($details, '0.linked_keg'); + + if (is_null($phpDirectory) && $installed = data_get($details, '0.installed')) { + $phpDirectory = data_get(collect($installed)->where('installed_as_dependency', false)->last(), 'version'); + + if (is_null($phpDirectory)) { + $phpDirectory = data_get(collect($installed)->last(), 'version'); + } } if (isset($phpDirectory) && $this->files->exists(trim($cellar).'/'.$phpDirectory.'/bin/php')) { @@ -345,12 +367,7 @@ public function getPhpBinaryPath($phpVersion = null) $phpBinaryPath = BREW_PREFIX."/opt/{$phpVersion}/bin/php"; } - // Create a symlink to the valet php version, so next time valet won't have to look for the binary path - if($phpBinaryPath){ - $this->files->symlinkAsUser($phpBinaryPath, $symlinkedValetPhpPath); - } - - return $phpBinaryPath ?: BREW_PREFIX.'/bin/php'; + return $phpBinaryPath; } /** diff --git a/cli/valet.php b/cli/valet.php index e91fd81..dcc7ce9 100755 --- a/cli/valet.php +++ b/cli/valet.php @@ -564,7 +564,7 @@ /** * Get PHP Birnary */ - $app->command('which-php [site]', function ($site = null) { + $app->command('which-php [site] [--skip-cache]', function ($site, $skipCache) { $host = Site::host($site ?: getcwd()).'.'.Configuration::read()['tld']; $phpVersion = Site::customPhpVersion($host); @@ -577,9 +577,10 @@ $phpVersion = $phpVersion ? PhpFpm::normalizePhpVersion($phpVersion) : null; - return output(Brew::getPhpBinaryPath($phpVersion)); + return output(Brew::whichPhp($phpVersion, $skipCache)); })->descriptions('Get the PHP binary path for a given site', [ 'site' => 'The site to get the PHP binary path for', + '--skip-cache' => 'Force a re-check of the PHP binary path', ]); /** diff --git a/tests/BrewTest.php b/tests/BrewTest.php index 056b909..15cf218 100644 --- a/tests/BrewTest.php +++ b/tests/BrewTest.php @@ -395,49 +395,73 @@ public function test_restart_linked_php_will_pass_through_linked_php_formula_to_ $brewMock->restartLinkedPhp(); } + public function test_it_can_get_php_binary_path_from_php_version_and_create_symblink() + { + // Scenario when there is no linked Valet PHP exists + $brewMock = Mockery::mock(Brew::class, [Mockery::mock(CommandLine::class), $files = Mockery::mock(Filesystem::class)])->makePartial(); + $files->shouldReceive('isLink')->once()->with(BREW_PREFIX."/bin/valetphp74")->andReturn(false); + $files->shouldReceive('symlinkAsUser')->once()->withArgs([BREW_PREFIX."/Cellar/php@7.4/7.4.6/bin/php", BREW_PREFIX."/bin/valetphp74"]); + $brewMock->shouldReceive('getPhpBinaryPath')->once()->with('php@7.4')->andReturn(BREW_PREFIX."/Cellar/php@7.4/7.4.6/bin/php"); + $this->assertEquals(BREW_PREFIX."/Cellar/php@7.4/7.4.6/bin/php", $brewMock->whichPhp('php@7.4')); + + // Scenario when there is a linked Valet PHP exists + $brewMock = Mockery::mock(Brew::class, [Mockery::mock(CommandLine::class), $files = Mockery::mock(Filesystem::class)])->makePartial(); + $brewMock->shouldNotHaveReceived('getPhpBinaryPath'); + $files->shouldReceive('isLink')->once()->with(BREW_PREFIX."/bin/valetphp81")->andReturn(true); + $files->shouldReceive('readLink')->once()->with(BREW_PREFIX."/bin/valetphp81")->andReturn(BREW_PREFIX."/Cellar/php@8.1/8.1.5/bin/php"); + $files->shouldReceive('exists')->once()->with(BREW_PREFIX."/Cellar/php@8.1/8.1.5/bin/php")->andReturn(true); + $files->shouldNotHaveReceived('symlinkAsUser'); + $this->assertEquals(BREW_PREFIX."/Cellar/php@8.1/8.1.5/bin/php", $brewMock->whichPhp('php@8.1')); + + // Check with $skipCache enabled + $brewMock = Mockery::mock(Brew::class, [Mockery::mock(CommandLine::class), $files = Mockery::mock(Filesystem::class)])->makePartial(); + $brewMock->shouldReceive('getPhpBinaryPath')->once()->with('php@7.4')->andReturn(BREW_PREFIX."/Cellar/php@7.4/7.4.6/bin/php"); + $files->shouldReceive('symlinkAsUser')->once()->withArgs([BREW_PREFIX."/Cellar/php@7.4/7.4.6/bin/php", BREW_PREFIX."/bin/valetphp74"]); + $this->assertEquals(BREW_PREFIX."/Cellar/php@7.4/7.4.6/bin/php", $brewMock->whichPhp('php@7.4', true)); + + // Scenario when non PHP Version is proivided + $brewMock = Mockery::mock(Brew::class, [Mockery::mock(CommandLine::class), Mockery::mock(Filesystem::class)])->makePartial(); + $this->assertEquals(BREW_PREFIX.'/bin/php', $brewMock->whichPhp(null)); + } + public function test_it_can_get_php_binary_path_from_php_version() { - // Scenario when there is no linked valet php exists - $files = Mockery::mock(Filesystem::class); - $cli = Mockery::mock(CommandLine::class); - $files->shouldReceive('isLink')->once()->with(BREW_PREFIX."/bin/valetphp74")->andReturn(false); + // linked_keg + $brewMock = Mockery::mock(Brew::class, [$cli = Mockery::mock(CommandLine::class), $files = Mockery::mock(Filesystem::class)])->makePartial(); $cli->shouldReceive('runAsUser')->once()->with("brew --cellar php@7.4")->andReturn(BREW_PREFIX."/Cellar/php@7.4"); $cli->shouldReceive('runAsUser')->once()->with("brew info --json php@7.4")->andReturn('[{"linked_keg":"7.4.6","installed":[{"version":"7.4.5"}]}]'); $files->shouldReceive('exists')->once()->with(BREW_PREFIX."/Cellar/php@7.4/7.4.6/bin/php")->andReturn(true); - $files->shouldReceive('symlinkAsUser')->once()->withArgs([BREW_PREFIX."/Cellar/php@7.4/7.4.6/bin/php", BREW_PREFIX."/bin/valetphp74"]); - swap(CommandLine::class, $cli); - swap(Filesystem::class, $files); - $this->assertEquals(BREW_PREFIX."/Cellar/php@7.4/7.4.6/bin/php", resolve(Brew::class)->getPhpBinaryPath('php@7.4')); + $this->assertEquals(BREW_PREFIX."/Cellar/php@7.4/7.4.6/bin/php", $brewMock->getPhpBinaryPath('php@7.4')); + + // no linked_keg + $brewMock = Mockery::mock(Brew::class, [$cli = Mockery::mock(CommandLine::class), $files = Mockery::mock(Filesystem::class)])->makePartial(); + $cli->shouldReceive('runAsUser')->once()->with("brew --cellar php@8.0")->andReturn(BREW_PREFIX."/Cellar/php@8.0"); + $cli->shouldReceive('runAsUser')->once()->with("brew info --json php@8.0")->andReturn('[{"installed":[{"version":"8.0.5"}]}]'); + $files->shouldReceive('exists')->once()->with(BREW_PREFIX."/Cellar/php@8.0/8.0.5/bin/php")->andReturn(true); + $this->assertEquals(BREW_PREFIX."/Cellar/php@8.0/8.0.5/bin/php", $brewMock->getPhpBinaryPath('php@8.0')); + + // installed_as_dependency + $brewMock = Mockery::mock(Brew::class, [$cli = Mockery::mock(CommandLine::class), $files = Mockery::mock(Filesystem::class)])->makePartial(); + $cli->shouldReceive('runAsUser')->once()->with("brew --cellar php@8.1")->andReturn(BREW_PREFIX."/Cellar/php@8.1"); + $cli->shouldReceive('runAsUser')->once()->with("brew info --json php@8.1") + ->andReturn('[{"installed":[{"version":"8.1.1", "installed_as_dependency":true}, {"version":"8.1.2", "installed_as_dependency":false}]}]'); + $files->shouldReceive('exists')->once()->with(BREW_PREFIX."/Cellar/php@8.1/8.1.2/bin/php")->andReturn(true); + $this->assertEquals(BREW_PREFIX."/Cellar/php@8.1/8.1.2/bin/php", $brewMock->getPhpBinaryPath('php@8.1')); + + // installed_as_dependency 2 + $brewMock = Mockery::mock(Brew::class, [$cli = Mockery::mock(CommandLine::class), $files = Mockery::mock(Filesystem::class)])->makePartial(); + $cli->shouldReceive('runAsUser')->once()->with("brew --cellar php@7.4")->andReturn(BREW_PREFIX."/Cellar/php@7.4"); + $cli->shouldReceive('runAsUser')->once()->with("brew info --json php@7.4") + ->andReturn('[{"installed":[{"version":"7.4.1", "installed_as_dependency":false}, {"version":"7.4.3", "installed_as_dependency":false}]}]'); + $files->shouldReceive('exists')->once()->with(BREW_PREFIX."/Cellar/php@7.4/7.4.3/bin/php")->andReturn(true); + $this->assertEquals(BREW_PREFIX."/Cellar/php@7.4/7.4.3/bin/php", $brewMock->getPhpBinaryPath('php@7.4')); // Scenario when user has installed directly though shivammathur/homebrew-php - $files = Mockery::mock(Filesystem::class); - $cli = Mockery::mock(CommandLine::class); - $files->shouldReceive('isLink')->once()->with(BREW_PREFIX."/bin/valetphp74")->andReturn(false); + $brewMock = Mockery::mock(Brew::class, [$cli = Mockery::mock(CommandLine::class), $files = Mockery::mock(Filesystem::class)])->makePartial(); $cli->shouldReceive('runAsUser')->once()->with("brew --cellar php@7.4")->andReturn(BREW_PREFIX."/Cellar/php@7.4"); - $cli->shouldReceive('runAsUser')->once()->with("brew info --json php@7.4")->andReturn('[{"installed":[{"version":"7.4.5"}]}]'); - $files->shouldReceive('exists')->once()->with(BREW_PREFIX."/Cellar/php@7.4/7.4.5/bin/php")->andReturn(false); + $cli->shouldReceive('runAsUser')->once()->with("brew info --json php@7.4")->andReturn(false); $files->shouldReceive('exists')->once()->with(BREW_PREFIX."/opt/php@7.4/bin/php")->andReturn(true); - $files->shouldReceive('symlinkAsUser')->once()->withArgs([BREW_PREFIX ."/opt/php@7.4/bin/php", BREW_PREFIX."/bin/valetphp74"]); - swap(CommandLine::class, $cli); - swap(Filesystem::class, $files); - $this->assertEquals(BREW_PREFIX ."/opt/php@7.4/bin/php", resolve(Brew::class)->getPhpBinaryPath('php@7.4')); - - // Scenario when there is a linked valet php exists - $files = Mockery::mock(Filesystem::class); - $cli = Mockery::mock(CommandLine::class); - $files->shouldReceive('isLink')->once()->with(BREW_PREFIX."/bin/valetphp74")->andReturn(true); - $files->shouldReceive('readLink')->once()->with(BREW_PREFIX."/bin/valetphp74")->andReturn(BREW_PREFIX."/Cellar/php@7.4/7.4.5/bin/php"); - $files->shouldReceive('exists')->once()->with(BREW_PREFIX."/Cellar/php@7.4/7.4.5/bin/php")->andReturn(true); - swap(CommandLine::class, $cli); - swap(Filesystem::class, $files); - $this->assertEquals(BREW_PREFIX."/bin/valetphp74", resolve(Brew::class)->getPhpBinaryPath('php@7.4')); - - // Scenario when non php version is proivided - $files = Mockery::mock(Filesystem::class); - $cli = Mockery::mock(CommandLine::class); - swap(CommandLine::class, $cli); - swap(Filesystem::class, $files); - $this->assertEquals(BREW_PREFIX.'/bin/php', resolve(Brew::class)->getPhpBinaryPath(null)); + $this->assertEquals(BREW_PREFIX."/opt/php@7.4/bin/php", $brewMock->getPhpBinaryPath('php@7.4')); } /**