-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRemoveIniEntryWithFileGetContents.php
More file actions
119 lines (100 loc) · 4.12 KB
/
RemoveIniEntryWithFileGetContents.php
File metadata and controls
119 lines (100 loc) · 4.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<?php
declare(strict_types=1);
namespace Php\Pie\Installing\Ini;
use Composer\IO\IOInterface;
use Php\Pie\DependencyResolver\Package;
use Php\Pie\ExtensionType;
use Php\Pie\File\FailedToWriteFile;
use Php\Pie\File\SudoFilePut;
use Php\Pie\Platform\TargetPlatform;
use Webmozart\Assert\Assert;
use function array_filter;
use function array_map;
use function array_merge;
use function array_walk;
use function file_exists;
use function in_array;
use function is_dir;
use function preg_quote;
use function Safe\file_get_contents;
use function Safe\preg_replace;
use function Safe\scandir;
use function sprintf;
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 */
class RemoveIniEntryWithFileGetContents implements RemoveIniEntry
{
/** @return list<string> Returns a list of INI files that were updated to remove the extension */
public function __invoke(Package $package, TargetPlatform $targetPlatform, IOInterface $io): array
{
$allIniFiles = [];
$mainIni = $targetPlatform->phpBinaryPath->loadedIniConfigurationFile();
if ($mainIni !== null) {
$allIniFiles[] = $mainIni;
}
$additionalIniDirectory = $targetPlatform->phpBinaryPath->additionalIniDirectory();
if ($additionalIniDirectory !== null && file_exists($additionalIniDirectory) && is_dir($additionalIniDirectory)) {
$filenames = scandir($additionalIniDirectory);
Assert::isList($filenames);
Assert::allString($filenames);
$allIniFiles = array_merge(
array_map(
static function (string $path) use ($additionalIniDirectory): string {
return $additionalIniDirectory . DIRECTORY_SEPARATOR . $path;
},
array_filter(
$filenames,
static function (string $path) use ($additionalIniDirectory): bool {
if (in_array($path, ['.', '..'])) {
return false;
}
return file_exists($additionalIniDirectory . DIRECTORY_SEPARATOR . $path);
},
),
),
$allIniFiles,
);
}
// Make sure all symlinks are resolved
$allIniFiles = array_filter(array_map('realpath', $allIniFiles));
// Anchor on the right with \b so uninstalling `foo` doesn't also
// rewrite the prefix of `extension=foo_other`. preg_quote on the
// extension name is defence-in-depth in case future ExtensionName
// validation ever loosens past `^[A-Za-z][a-zA-Z0-9_]+$`.
$regex = sprintf(
'/^(%s\s*=\s*%s)\b/m',
$package->extensionType() === ExtensionType::PhpModule ? 'extension' : 'zend_extension',
preg_quote($package->extensionName()->name(), '/'),
);
$updatedIniFiles = [];
array_walk(
$allIniFiles,
static function (string $iniFile) use (&$updatedIniFiles, $regex, $package, $io): void {
$currentContent = file_get_contents($iniFile);
if ($currentContent === '') {
return;
}
$replacedContent = preg_replace(
$regex,
'; $1 ; removed by PIE',
$currentContent,
);
if ($replacedContent === $currentContent) {
return;
}
try {
SudoFilePut::contents($iniFile, $replacedContent);
} catch (FailedToWriteFile) {
$io->writeError(sprintf(
'<error>Failed to remove extension "%s" from INI file "%s"</error>',
$package->extensionName()->name(),
$iniFile,
));
return;
}
$updatedIniFiles[] = $iniFile;
},
);
return $updatedIniFiles;
}
}