diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php index 75191cd..1905843 100644 --- a/src/Console/InstallCommand.php +++ b/src/Console/InstallCommand.php @@ -469,10 +469,10 @@ private function installMcpServerConfig(): void $this->output->write(" {$ideDisplay}... "); $results = []; - $php = $this->getPhpPathForMcpClient($mcpClient); + $php = $mcpClient->getPhpPath(); if ($this->shouldInstallMcp()) { try { - $artisan = $this->getArtisanPathForMcpClient($mcpClient); + $artisan = $mcpClient->getArtisanPath(); $result = $mcpClient->installMcp('laravel-boost', $php, [$artisan, 'boost:mcp']); if ($result) { @@ -492,7 +492,7 @@ private function installMcpServerConfig(): void try { $result = $mcpClient->installMcp( key: 'herd', - command: $this->getPhpPathForMcpClient($mcpClient), + command: $mcpClient->getPhpPath(), args: [$this->herd->mcpPath()], env: ['SITE_PATH' => base_path()] ); @@ -524,16 +524,6 @@ private function installMcpServerConfig(): void } } - private function getPhpPathForMcpClient(McpClient $mcpClient): string - { - return $mcpClient->useAbsolutePathForMcp() ? PHP_BINARY : 'php'; - } - - private function getArtisanPathForMcpClient(McpClient $mcpClient): string - { - return $mcpClient->useAbsolutePathForMcp() ? base_path('artisan') : './artisan'; - } - /** * Is the project actually using localization for their new features? */ diff --git a/src/Contracts/McpClient.php b/src/Contracts/McpClient.php index 19c9b6d..68c106b 100644 --- a/src/Contracts/McpClient.php +++ b/src/Contracts/McpClient.php @@ -21,6 +21,16 @@ public function mcpClientName(): ?string; */ public function useAbsolutePathForMcp(): bool; + /** + * Get the PHP executable path for this MCP client. + */ + public function getPhpPath(): string; + + /** + * Get the artisan path for this MCP client. + */ + public function getArtisanPath(): string; + /** * Install an MCP server configuration in this IDE. * diff --git a/src/Install/CodeEnvironment/CodeEnvironment.php b/src/Install/CodeEnvironment/CodeEnvironment.php index 9b1e131..3ba0ede 100644 --- a/src/Install/CodeEnvironment/CodeEnvironment.php +++ b/src/Install/CodeEnvironment/CodeEnvironment.php @@ -40,6 +40,17 @@ public function useAbsolutePathForMcp(): bool return $this->useAbsolutePathForMcp; } + public function getPhpPath(): string + { + return $this->useAbsolutePathForMcp() ? PHP_BINARY : 'php'; + } + + public function getArtisanPath(): string + { + return $this->useAbsolutePathForMcp() ? getcwd().'/artisan' : './artisan'; + + } + /** * Get the detection configuration for system-wide installation detection. * diff --git a/tests/Unit/Console/InstallCommandPhpPathTest.php b/tests/Unit/Console/InstallCommandPhpPathTest.php deleted file mode 100644 index d6aa0b9..0000000 --- a/tests/Unit/Console/InstallCommandPhpPathTest.php +++ /dev/null @@ -1,37 +0,0 @@ -toBe(PHP_BINARY); -}); - -test('getPhpPathForMcpClient returns php string for Cursor', function () { - $installCommand = new InstallCommand; - $strategyFactory = Mockery::mock(DetectionStrategyFactory::class); - $cursor = new Cursor($strategyFactory); - - $phpPath = invokePrivateMethod($installCommand, 'getPhpPathForMcpClient', [$cursor]); - - expect($phpPath)->toBe('php'); -}); - -function invokePrivateMethod(object $object, string $methodName, array $parameters = []): mixed -{ - $reflection = new ReflectionClass($object); - $method = $reflection->getMethod($methodName); - $method->setAccessible(true); - - return $method->invokeArgs($object, $parameters); -} diff --git a/tests/Unit/Install/CodeEnvironment/CodeEnvironmentPathResolutionTest.php b/tests/Unit/Install/CodeEnvironment/CodeEnvironmentPathResolutionTest.php new file mode 100644 index 0000000..415f7f7 --- /dev/null +++ b/tests/Unit/Install/CodeEnvironment/CodeEnvironmentPathResolutionTest.php @@ -0,0 +1,39 @@ +getPhpPath())->toBe(PHP_BINARY); +}); + +test('PhpStorm returns absolute artisan path', function () { + $strategyFactory = Mockery::mock(DetectionStrategyFactory::class); + $phpStorm = new PhpStorm($strategyFactory); + + $artisanPath = $phpStorm->getArtisanPath(); + + // Should be an absolute path ending with 'artisan' + expect($artisanPath)->toEndWith('artisan') + ->and($artisanPath)->not()->toBe('./artisan'); +}); + +test('Cursor returns relative php string', function () { + $strategyFactory = Mockery::mock(DetectionStrategyFactory::class); + $cursor = new Cursor($strategyFactory); + + expect($cursor->getPhpPath())->toBe('php'); +}); + +test('Cursor returns relative artisan path', function () { + $strategyFactory = Mockery::mock(DetectionStrategyFactory::class); + $cursor = new Cursor($strategyFactory); + + expect($cursor->getArtisanPath())->toBe('./artisan'); +});