diff --git a/src/Installing/Ini/RemoveIniEntryWithFileGetContents.php b/src/Installing/Ini/RemoveIniEntryWithFileGetContents.php index 8cc9bee9..ffed9c30 100644 --- a/src/Installing/Ini/RemoveIniEntryWithFileGetContents.php +++ b/src/Installing/Ini/RemoveIniEntryWithFileGetContents.php @@ -59,6 +59,9 @@ static function (string $path) use ($additionalIniDirectory): bool { ); } + // Make sure all symlinks are resolved + $allIniFiles = array_filter(array_map('realpath', $allIniFiles)); + $regex = sprintf( '/^(%s\s*=\s*%s)/m', $package->extensionType() === ExtensionType::PhpModule ? 'extension' : 'zend_extension', diff --git a/test/unit/Installing/Ini/RemoveIniEntryWithFileGetContentsTest.php b/test/unit/Installing/Ini/RemoveIniEntryWithFileGetContentsTest.php index 9eca6987..e596825e 100644 --- a/test/unit/Installing/Ini/RemoveIniEntryWithFileGetContentsTest.php +++ b/test/unit/Installing/Ini/RemoveIniEntryWithFileGetContentsTest.php @@ -18,15 +18,21 @@ use Php\Pie\Platform\ThreadSafetyMode; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\RequiresOperatingSystemFamily; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Output\OutputInterface; use Webmozart\Assert\Assert; use function file_get_contents; use function file_put_contents; +use function is_link; use function mkdir; +use function realpath; +use function symlink; use function sys_get_temp_dir; +use function tempnam; use function uniqid; +use function unlink; use const DIRECTORY_SEPARATOR; @@ -42,7 +48,7 @@ public function setUp(): void { parent::setUp(); - $this->iniFilePath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . uniqid('pie_remove_ini_test', true); + $this->iniFilePath = realpath(sys_get_temp_dir()) . DIRECTORY_SEPARATOR . uniqid('pie_remove_ini_test', true); mkdir($this->iniFilePath); Assert::positiveInteger(file_put_contents( $this->iniFilePath . DIRECTORY_SEPARATOR . 'with_commented_exts.ini', @@ -121,4 +127,66 @@ public function testRelevantIniFilesHaveExtensionRemoved(ExtensionType $extensio file_get_contents($this->iniFilePath . DIRECTORY_SEPARATOR . 'with_active_exts.ini'), ); } + + #[RequiresOperatingSystemFamily('Linux')] + public function testSymlinkedIniFilesAreResolved(): void + { + $realIni = $this->iniFilePath . DIRECTORY_SEPARATOR . 'with_active_exts.ini'; + $symlinkedIni = tempnam(sys_get_temp_dir(), 'pie_ini_removal_test_link_'); + unlink($symlinkedIni); + symlink($realIni, $symlinkedIni); + self::assertTrue(is_link($symlinkedIni)); + + $phpBinaryPath = $this->createMock(PhpBinaryPath::class); + $phpBinaryPath + ->method('loadedIniConfigurationFile') + ->willReturn($symlinkedIni); + $phpBinaryPath + ->method('additionalIniDirectory') + ->willReturn(null); + + $package = new Package( + $this->createMock(CompletePackageInterface::class), + ExtensionType::PhpModule, + ExtensionName::normaliseFromString('foobar'), + 'foobar/foobar', + '1.2.3', + null, + ); + + $targetPlatform = new TargetPlatform( + OperatingSystem::NonWindows, + OperatingSystemFamily::Linux, + $phpBinaryPath, + Architecture::x86_64, + ThreadSafetyMode::ThreadSafe, + 1, + null, + ); + + $affectedFiles = (new RemoveIniEntryWithFileGetContents())( + $package, + $targetPlatform, + $this->createMock(OutputInterface::class), + ); + + self::assertSame( + [$realIni], + $affectedFiles, + ); + + self::assertTrue(is_link($symlinkedIni)); + + $expectedIniContent = "; extension=foobar ; removed by PIE\nzend_extension=foobar\n"; + self::assertSame( + $expectedIniContent, + file_get_contents($realIni), + ); + self::assertSame( + $expectedIniContent, + file_get_contents($symlinkedIni), + ); + + unlink($symlinkedIni); + } }