diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index f810a9ba..549c691b 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -486,18 +486,6 @@ parameters:
count: 1
path: test/unit/Installing/InstallForPhpProject/InstallSelectedPackageTest.php
- -
- message: '#^Parameter \#1 \$filename of function file_exists expects string, string\|false given\.$#'
- identifier: argument.type
- count: 1
- path: test/unit/Platform/TargetPhp/PhpBinaryPathTest.php
-
- -
- message: '#^Parameter \#1 \$filename of function is_dir expects string, string\|false given\.$#'
- identifier: argument.type
- count: 1
- path: test/unit/Platform/TargetPhp/PhpBinaryPathTest.php
-
-
message: '#^Method Php\\PieUnitTest\\SelfManage\\Verify\\FallbackVerificationUsingOpenSslTest\:\:prepareCertificateAndSignature\(\) should return array\{string, string\} but returns array\{mixed, mixed\}\.$#'
identifier: return.type
diff --git a/src/Building/WindowsBuild.php b/src/Building/WindowsBuild.php
index 39bb2a1b..c724accf 100644
--- a/src/Building/WindowsBuild.php
+++ b/src/Building/WindowsBuild.php
@@ -26,10 +26,13 @@ public function __invoke(
): BinaryFile {
$prebuiltDll = WindowsExtensionAssetName::determineDllName($targetPlatform, $downloadedPackage);
- $io->write(sprintf(
- 'Nothing to do on Windows, prebuilt DLL found: %s',
- $prebuiltDll,
- ));
+ $io->write(
+ sprintf(
+ 'Nothing to build on Windows, prebuilt DLL found: %s',
+ $prebuiltDll,
+ ),
+ verbosity: IOInterface::VERBOSE,
+ );
return BinaryFile::fromFileWithSha256Checksum($prebuiltDll);
}
diff --git a/src/Platform/TargetPhp/PhpBinaryPath.php b/src/Platform/TargetPhp/PhpBinaryPath.php
index 61216ccc..9f4a5579 100644
--- a/src/Platform/TargetPhp/PhpBinaryPath.php
+++ b/src/Platform/TargetPhp/PhpBinaryPath.php
@@ -107,18 +107,20 @@ public function extensionPath(): string
return $extensionPath;
}
+ // `extension_dir` may be a relative URL on Windows, so resolve it according to the location of PHP
+ if (self::operatingSystem() === OperatingSystem::Windows) {
+ $phpPath = dirname($this->phpBinaryPath);
+ $attemptExtensionPath = $phpPath . DIRECTORY_SEPARATOR . $extensionPath;
+
+ if (file_exists($attemptExtensionPath) && is_dir($attemptExtensionPath)) {
+ return $attemptExtensionPath;
+ }
+ }
+
// if the path is absolute, try to create it
if (mkdir($extensionPath, 0777, true) && file_exists($extensionPath) && is_dir($extensionPath)) {
return $extensionPath;
}
-
- // `extension_dir` may be a relative URL on Windows, so resolve it according to the location of PHP
- $phpPath = dirname($this->phpBinaryPath);
- $attemptExtensionPath = $phpPath . DIRECTORY_SEPARATOR . $extensionPath;
-
- if (file_exists($attemptExtensionPath) && is_dir($attemptExtensionPath)) {
- return $attemptExtensionPath;
- }
}
throw new RuntimeException('Could not determine extension path for ' . $this->phpBinaryPath);
diff --git a/test/integration/Command/BuildCommandTest.php b/test/integration/Command/BuildCommandTest.php
index 7e8d7010..07123e58 100644
--- a/test/integration/Command/BuildCommandTest.php
+++ b/test/integration/Command/BuildCommandTest.php
@@ -31,7 +31,7 @@ public function testBuildCommandWillBuildTheExtension(): void
$outputString = $this->commandTester->getDisplay();
if (Platform::isWindows()) {
- self::assertStringContainsString('Nothing to do on Windows', $outputString);
+ self::assertStringContainsString('Found prebuilt archive', $outputString);
return;
}
diff --git a/test/unit/Platform/TargetPhp/PhpBinaryPathTest.php b/test/unit/Platform/TargetPhp/PhpBinaryPathTest.php
index acd93e7f..064139e4 100644
--- a/test/unit/Platform/TargetPhp/PhpBinaryPathTest.php
+++ b/test/unit/Platform/TargetPhp/PhpBinaryPathTest.php
@@ -16,7 +16,9 @@
use Php\Pie\Util\Process;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
+use PHPUnit\Framework\Attributes\RequiresOperatingSystemFamily;
use PHPUnit\Framework\TestCase;
+use ReflectionMethod;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\PhpExecutableFinder;
@@ -35,11 +37,13 @@
use function ini_get;
use function is_dir;
use function is_executable;
+use function mkdir;
use function php_uname;
use function phpversion;
use function sprintf;
use function strtolower;
use function sys_get_temp_dir;
+use function trim;
use function uniqid;
use const DIRECTORY_SEPARATOR;
@@ -235,11 +239,28 @@ public function testPhpIntSize(): void
);
}
- public function testExtensionPath(): void
+ #[RequiresOperatingSystemFamily('Linux')]
+ public function testExtensionPathOnLinuxThatAlreadyExists(): void
{
$phpBinary = PhpBinaryPath::fromCurrentProcess();
- $expectedExtensionDir = ini_get('extension_dir');
+ $expectedExtensionDir = (string) ini_get('extension_dir');
+ self::assertNotEmpty($expectedExtensionDir);
+ self::assertDirectoryExists($expectedExtensionDir);
+
+ self::assertSame(
+ $expectedExtensionDir,
+ $phpBinary->extensionPath(),
+ );
+ }
+
+ #[RequiresOperatingSystemFamily('Windows')]
+ public function testExtensionPathOnWindows(): void
+ {
+ $phpBinary = PhpBinaryPath::fromCurrentProcess();
+
+ $expectedExtensionDir = (string) ini_get('extension_dir');
+ self::assertNotEmpty($expectedExtensionDir);
// `extension_dir` may be a relative URL on Windows (e.g. "ext"), so resolve it according to the location of PHP
if (! file_exists($expectedExtensionDir) || ! is_dir($expectedExtensionDir)) {
@@ -255,9 +276,32 @@ public function testExtensionPath(): void
);
}
+ #[RequiresOperatingSystemFamily('Windows')]
+ public function testRelativeExtensionPathOnWindowsIsFilled(): void
+ {
+ $phpBinary = $this->createPartialMock(PhpBinaryPath::class, ['phpinfo']);
+ (new ReflectionMethod($phpBinary, '__construct'))
+ ->invoke($phpBinary, trim((string) (new PhpExecutableFinder())->find()), null);
+
+ $configuredExtensionPath = 'foo';
+ self::assertDirectoryDoesNotExist($configuredExtensionPath, 'test cannot run if the same-named extension dir already exists in cwd');
+
+ $fullExtensionPath = dirname($phpBinary->phpBinaryPath) . DIRECTORY_SEPARATOR . $configuredExtensionPath;
+ mkdir($fullExtensionPath, 0777, true);
+ self::assertDirectoryExists($fullExtensionPath);
+
+ $phpBinary->expects(self::once())
+ ->method('phpinfo')
+ ->willReturn(sprintf('extension_dir => %s => %s', $configuredExtensionPath, $configuredExtensionPath));
+
+ self::assertSame($fullExtensionPath, $phpBinary->extensionPath());
+ }
+
public function testExtensionPathIsImplicitlyCreated(): void
{
$phpBinary = $this->createPartialMock(PhpBinaryPath::class, ['phpinfo']);
+ (new ReflectionMethod($phpBinary, '__construct'))
+ ->invoke($phpBinary, trim((string) (new PhpExecutableFinder())->find()), null);
$configuredExtensionPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid('PIE_non_existent_extension_path', true);
self::assertDirectoryDoesNotExist($configuredExtensionPath);