-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added INI enable approach for phpenmod
- Loading branch information
Showing
5 changed files
with
668 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Php\Pie\Installing\Ini; | ||
|
||
use Composer\Util\Platform; | ||
use Php\Pie\BinaryFile; | ||
use Php\Pie\Downloading\DownloadedPackage; | ||
use Php\Pie\Platform\TargetPlatform; | ||
use Php\Pie\Util\Process; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
use Symfony\Component\Process\Exception\ProcessFailedException; | ||
|
||
use function file_exists; | ||
use function is_dir; | ||
use function is_writable; | ||
use function preg_match; | ||
use function rtrim; | ||
use function sprintf; | ||
use function touch; | ||
use function unlink; | ||
|
||
use const DIRECTORY_SEPARATOR; | ||
|
||
/** @internal This is not public API for PIE, so should not be depended upon unless you accept the risk of BC breaks */ | ||
final class OndrejPhpenmod implements SetupIniApproach | ||
{ | ||
private const DEFAULT_PHPENMOD = 'phpenmod'; | ||
private const DEFAULT_MODS_AVAILABLE_PATH = '/etc/php/%s/mods-available'; | ||
|
||
public function __construct( | ||
private readonly CheckAndAddExtensionToIniIfNeeded $checkAndAddExtensionToIniIfNeeded, | ||
private readonly string $phpenmod = self::DEFAULT_PHPENMOD, | ||
private readonly string $modsAvailablePath = self::DEFAULT_MODS_AVAILABLE_PATH, | ||
) { | ||
} | ||
|
||
public function canBeUsed(TargetPlatform $targetPlatform): bool | ||
{ | ||
return $this->phpenmodPath() !== null; | ||
} | ||
|
||
public function setup( | ||
TargetPlatform $targetPlatform, | ||
DownloadedPackage $downloadedPackage, | ||
BinaryFile $binaryFile, | ||
OutputInterface $output, | ||
): bool { | ||
$phpenmodPath = $this->phpenmodPath(); | ||
|
||
/** In practice, this shouldn't happen since {@see canBeUsed()} checks this */ | ||
if ($phpenmodPath === null) { | ||
return false; | ||
} | ||
|
||
// the Ondrej repo uses an additional php.ini directory, if this isn't set, we may not actually be using Ondrej repo for this particular PHP install | ||
$additionalPhpIniPath = $targetPlatform->phpBinaryPath->additionalIniDirectory(); | ||
|
||
if ($additionalPhpIniPath === null) { | ||
$output->writeln( | ||
'Additional INI file path was not set - may not be Ondrej PHP repo', | ||
OutputInterface::VERBOSITY_VERBOSE, | ||
); | ||
|
||
return false; | ||
} | ||
|
||
// Cursory check for the expected PHP INI directory; this is another indication we're using the Ondrej repo | ||
if (preg_match('#/etc/php/\d\.\d/[a-z-_]+/conf.d#', $additionalPhpIniPath) !== 1) { | ||
$output->writeln( | ||
sprintf( | ||
'Warning: additional INI file path was not in the expected format (/etc/php/{version}/{sapi}/conf.d). Path was: %s', | ||
$additionalPhpIniPath, | ||
), | ||
OutputInterface::VERBOSITY_VERY_VERBOSE, | ||
); | ||
} | ||
|
||
$expectedModsAvailablePath = sprintf($this->modsAvailablePath, $targetPlatform->phpBinaryPath->majorMinorVersion()); | ||
|
||
if (! file_exists($expectedModsAvailablePath)) { | ||
$output->writeln( | ||
sprintf( | ||
'Mods available path %s does not exist', | ||
$expectedModsAvailablePath, | ||
), | ||
OutputInterface::VERBOSITY_VERBOSE, | ||
); | ||
|
||
return false; | ||
} | ||
|
||
if (! is_dir($expectedModsAvailablePath)) { | ||
$output->writeln( | ||
sprintf( | ||
'Mods available path %s is not a directory', | ||
$expectedModsAvailablePath, | ||
), | ||
OutputInterface::VERBOSITY_VERBOSE, | ||
); | ||
|
||
return false; | ||
} | ||
|
||
if (! is_writable($expectedModsAvailablePath)) { | ||
$output->writeln( | ||
sprintf( | ||
'Mods available path %s is not writable', | ||
$expectedModsAvailablePath, | ||
), | ||
OutputInterface::VERBOSITY_VERBOSE, | ||
); | ||
|
||
return false; | ||
} | ||
|
||
$expectedIniFile = sprintf( | ||
'%s%s%s.ini', | ||
rtrim($expectedModsAvailablePath, DIRECTORY_SEPARATOR), | ||
DIRECTORY_SEPARATOR, | ||
$downloadedPackage->package->extensionName->name(), | ||
); | ||
|
||
$pieCreatedTheIniFile = false; | ||
if (! file_exists($expectedIniFile)) { | ||
$output->writeln( | ||
sprintf( | ||
'Creating new INI file based on extension priority: %s', | ||
$expectedIniFile, | ||
), | ||
OutputInterface::VERBOSITY_VERY_VERBOSE, | ||
); | ||
$pieCreatedTheIniFile = true; | ||
touch($expectedIniFile); | ||
} | ||
|
||
$addingExtensionWasSuccessful = ($this->checkAndAddExtensionToIniIfNeeded)( | ||
$expectedIniFile, | ||
$targetPlatform, | ||
$downloadedPackage, | ||
$output, | ||
static function () use ($phpenmodPath, $targetPlatform, $downloadedPackage, $output): bool { | ||
try { | ||
Process::run([ | ||
$phpenmodPath, | ||
'-v', | ||
$targetPlatform->phpBinaryPath->majorMinorVersion(), | ||
'-s', | ||
'ALL', | ||
$downloadedPackage->package->extensionName->name(), | ||
]); | ||
|
||
return true; | ||
} catch (ProcessFailedException $processFailedException) { | ||
$output->writeln( | ||
sprintf( | ||
'Failed to use %s to enable %s for PHP %s: %s', | ||
$phpenmodPath, | ||
$downloadedPackage->package->extensionName->name(), | ||
$targetPlatform->phpBinaryPath->majorMinorVersion(), | ||
$processFailedException->getMessage(), | ||
), | ||
OutputInterface::VERBOSITY_VERBOSE, | ||
); | ||
|
||
return false; | ||
} | ||
}, | ||
); | ||
|
||
if (! $addingExtensionWasSuccessful && $pieCreatedTheIniFile) { | ||
unlink($expectedIniFile); | ||
} | ||
|
||
return $addingExtensionWasSuccessful; | ||
} | ||
|
||
/** @return non-empty-string|null */ | ||
private function phpenmodPath(): string|null | ||
{ | ||
if (Platform::isWindows()) { | ||
return null; | ||
} | ||
|
||
try { | ||
$phpenmodPath = Process::run(['which', $this->phpenmod]); | ||
|
||
return $phpenmodPath !== '' ? $phpenmodPath : null; | ||
} catch (ProcessFailedException) { | ||
return null; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#!/usr/bin/env bash | ||
|
||
echo "something bad happened" | ||
exit 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#!/usr/bin/env bash | ||
|
||
echo "hi" | ||
exit 0 |
Oops, something went wrong.