Repository: php/pie (php)

Issue:
INI setup should elevate privileges
```
PHP Warning:  touch(): Unable to create file /etc/php/8.3/cli/conf.d/74-example_pie_extension.ini because Permission denied in <path>/src/Installing/Ini/StandardAdditionalPhpIniDirectory.php on line 64
```

No attempt is made to elevate privs here, apply that.

Pull request description:
Check the additional php.ini dir is writable
Fixes #177

Patch:
diff --git a/src/Installing/Ini/StandardAdditionalPhpIniDirectory.php b/src/Installing/Ini/StandardAdditionalPhpIniDirectory.php
index a627b90..84a4b50 100644
--- a/src/Installing/Ini/StandardAdditionalPhpIniDirectory.php
+++ b/src/Installing/Ini/StandardAdditionalPhpIniDirectory.php
@@ -10,6 +10,7 @@ use Php\Pie\Platform\TargetPlatform;
 use Symfony\Component\Console\Output\OutputInterface;
 
 use function file_exists;
+use function is_writable;
 use function rtrim;
 use function sprintf;
 use function touch;
@@ -43,6 +44,18 @@ final class StandardAdditionalPhpIniDirectory implements SetupIniApproach
             return false;
         }
 
+        if (! file_exists($additionalIniFilesPath) || ! is_writable($additionalIniFilesPath)) {
+            $output->writeln(
+                sprintf(
+                    'PHP is configured to use additional INI file path %s, but it did not exist, or is not writable by PIE.',
+                    $additionalIniFilesPath,
+                ),
+                OutputInterface::VERBOSITY_VERBOSE,
+            );
+
+            return false;
+        }
+
         $expectedIniFile = sprintf(
             '%s%s%d-%s.ini',
             rtrim($additionalIniFilesPath, DIRECTORY_SEPARATOR),


Test patch:
diff --git a/test/unit/Installing/Ini/StandardAdditionalPhpIniDirectoryTest.php b/test/unit/Installing/Ini/StandardAdditionalPhpIniDirectoryTest.php
index 404a1d0..83f5b9e 100644
--- a/test/unit/Installing/Ini/StandardAdditionalPhpIniDirectoryTest.php
+++ b/test/unit/Installing/Ini/StandardAdditionalPhpIniDirectoryTest.php
@@ -134,6 +134,29 @@ final class StandardAdditionalPhpIniDirectoryTest extends TestCase
         ));
     }
 
+    public function testSetupReturnsWhenAdditionalPhpIniDirectoryDoesNotExist(): void
+    {
+        $this->mockPhpBinary
+            ->expects(self::once())
+            ->method('additionalIniDirectory')
+            ->willReturn('/path/to/something/does/not/exist');
+
+        $this->checkAndAddExtensionToIniIfNeeded
+            ->expects(self::never())
+            ->method('__invoke');
+
+        self::assertFalse($this->standardAdditionalPhpIniDirectory->setup(
+            $this->targetPlatform,
+            $this->downloadedPackage,
+            $this->binaryFile,
+            $this->output,
+        ));
+        self::assertStringContainsString(
+            'PHP is configured to use additional INI file path /path/to/something/does/not/exist, but it did not exist, or is not writable by PIE.',
+            $this->output->fetch(),
+        );
+    }
+
     public function testReturnsTrueWhenCheckAndAddExtensionIsInvoked(): void
     {
         $additionalPhpIniDirectory = tempnam(sys_get_temp_dir(), 'pie_additional_php_ini_path');