Skip to content

Commit bbd9510

Browse files
committed
Add PHP Switcher feature, that lets you switching the "current" PHP version
1 parent 2bc64d6 commit bbd9510

12 files changed

+483
-4
lines changed

PhpManager/PhpManager.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
# TypesToProcess = @()
2020
# FormatsToProcess = @()
2121
# NestedModules = @()
22-
FunctionsToExport = 'Get-PhpAvailableVersion', 'Install-Php', 'Update-Php', 'Uninstall-Php', 'Get-Php', 'Set-PhpIniKey', 'Get-PhpIniKey', 'Get-PhpExtension', 'Enable-PhpExtension', 'Disable-PhpExtension', 'Install-PhpExtension', 'Update-PhpCAInfo', 'Set-PhpDownloadCache', 'Get-PhpDownloadCache'
22+
FunctionsToExport = 'Get-PhpAvailableVersion', 'Install-Php', 'Update-Php', 'Uninstall-Php', 'Get-Php', 'Set-PhpIniKey', 'Get-PhpIniKey', 'Get-PhpExtension', 'Enable-PhpExtension', 'Disable-PhpExtension', 'Install-PhpExtension', 'Update-PhpCAInfo', 'Set-PhpDownloadCache', 'Get-PhpDownloadCache', 'Initialize-PhpSwitcher', 'Add-PhpToSwitcher', 'Remove-PhpFromSwitcher', 'Switch-Php', 'Move-PhpSwitcher', 'Remove-PhpSwitcher'
2323
CmdletsToExport = ''
2424
VariablesToExport = ''
2525
AliasesToExport = ''

PhpManager/private/Get-PhpManagerConfigurationKey.ps1

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,22 @@ Function Get-PhpManagerConfigurationKey
1111
[Parameter(Mandatory = $True, Position = 0)]
1212
[ValidateNotNull()]
1313
[ValidateLength(1, [int]::MaxValue)]
14-
[string]$Key
14+
[string]$Key,
15+
[Parameter(Mandatory = $False, Position = 1)]
16+
[ValidateSet('Any', 'CurrentUser', 'AllUsers')]
17+
[string]$Scope = 'Any'
1518
)
1619
Begin {
1720
$result = $null
1821
}
1922
Process {
20-
$folders = @($Env:LOCALAPPDATA, $Env:ProgramData)
23+
If ($Scope -eq 'CurrentUser') {
24+
$folders = @($Env:LOCALAPPDATA)
25+
} ElseIf ($Scope -eq 'AllUsers') {
26+
$folders = @($Env:ProgramData)
27+
} Else {
28+
$folders = @($Env:LOCALAPPDATA, $Env:ProgramData)
29+
}
2130
ForEach ($folder in $folders) {
2231
If ($folder) {
2332
$path = Join-Path -Path $folder -ChildPath 'phpmanager.json'
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
Function Get-PhpSwitcher
2+
{
3+
<#
4+
.Synopsis
5+
Gets the currently configured PHP Switcher (if configured).
6+
7+
.Outputs
8+
PSCustomObject|$null
9+
#>
10+
Begin {
11+
$result = $null
12+
}
13+
Process {
14+
$scope = 'CurrentUser'
15+
$data = Get-PhpManagerConfigurationKey -Key 'PHP_SWITCHER' -Scope $scope
16+
If ($data -eq $null) {
17+
$scope = 'AllUsers'
18+
$data = Get-PhpManagerConfigurationKey -Key 'PHP_SWITCHER' -Scope $scope
19+
}
20+
If ($data -ne $null) {
21+
$result = New-Object PSObject
22+
$result | Add-Member -MemberType NoteProperty -Name 'Scope' -Value $scope
23+
$alias = ''
24+
If ($data | Get-Member -Name 'Alias') {
25+
If ($data.Alias) {
26+
$alias = [string]$data.Alias
27+
}
28+
}
29+
$result | Add-Member -MemberType NoteProperty -Name 'Alias' -Value $alias
30+
$targets = @{}
31+
If ($data | Get-Member -Name 'Targets') {
32+
Try {
33+
$data.Targets.PSObject.Properties | ForEach-Object {
34+
$targets[$_.Name] = [string] $_.Value
35+
}
36+
}
37+
Catch {
38+
Write-Debug $_.Exception.Message
39+
}
40+
}
41+
$result | Add-Member -MemberType NoteProperty -Name 'Targets' -Value $targets
42+
}
43+
}
44+
End {
45+
$result
46+
}
47+
}

PhpManager/private/Install-PhpFromUrl.ps1

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,26 @@ function Install-PhpFromUrl() {
113113
}
114114
Write-Debug "Extracting $temporaryFile to destination directory"
115115
Expand-Archive -LiteralPath $temporaryFile -DestinationPath $Path -Force
116+
Try {
117+
$apacheFile = [System.IO.Path]::Combine($Path, 'Apache.conf')
118+
If (-Not(Test-Path -LiteralPath $apacheFile)) {
119+
$apacheDlls = @(Get-ChildItem -LiteralPath $Path -Filter 'php*apache*.dll')
120+
If ($apacheDlls.Count -gt 1) {
121+
$apacheDlls = $apacheDlls | Where-Object { $_.BaseName -match '^php(\d+(_\d+)*)apache(\d+(_\d+)*)$' }
122+
}
123+
If ($apacheDlls.Count -eq 1) {
124+
$match = $apacheDlls[0].BaseName | Select-String -Pattern '^php(\d+(?:_\d+)*)apache(?:\d+(?:_\d+)*)$'
125+
If ($match) {
126+
$moduleName = 'php' + $match.Matches[0].Groups[1].Value + '_module'
127+
$fullName = $apacheDlls[0].FullName
128+
Set-Content -LiteralPath $apacheFile -Value "LoadModule $moduleName ""$fullName"""
129+
}
130+
}
131+
}
132+
}
133+
Catch {
134+
Write-Debug 'Failed to configure the Apache.conf file'
135+
}
116136
} Finally {
117137
If (-Not($keepTemporaryFile)) {
118138
Try {

PhpManager/private/Set-PhpManagerConfigurationKey.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Function Set-PhpManagerConfigurationKey
4747
}
4848
Process {
4949
If ($null -eq $Value) {
50-
$json.PSObject.Properties.Remove($key)
50+
$json.PSObject.Properties.Remove($Key)
5151
} Else {
5252
$json | Add-Member -MemberType NoteProperty -Name $Key -Value $Value -Force
5353
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
Function Add-PhpToSwitcher
2+
{
3+
<#
4+
.Synopsis
5+
Adds a PHP installation to the PHP Switcher.
6+
7+
.Parameter Name
8+
The symbolic name to give to the PHP installation.
9+
10+
.Parameter Path
11+
The path to an existing PHP installation to be added to the PHP Switcher.
12+
13+
.Parameter Force
14+
Force adding the PHP installation to the PHP Switcher even if another installation is already defined with the specified name.
15+
16+
.Example
17+
Initialize-PhpSwitcher C:\PHP
18+
Add-PhpToSwitcher 5.6 C:\PHP5.6
19+
Add-PhpToSwitcher 7.2 C:\PHP7.2
20+
Switch-Php 5.6
21+
#>
22+
Param (
23+
[Parameter(Mandatory = $True, Position = 0, HelpMessage = 'The symbolic name to give to the PHP installation')]
24+
[ValidateNotNull()]
25+
[ValidateLength(1, [int]::MaxValue)]
26+
[string]$Name,
27+
[Parameter(Mandatory = $True, Position = 1, HelpMessage = 'The path to an existing PHP installation to be added to the PHP Switcher')]
28+
[ValidateNotNull()]
29+
[ValidateLength(1, [int]::MaxValue)]
30+
[string]$Path,
31+
[switch]$Force
32+
)
33+
Begin {
34+
}
35+
Process {
36+
$switcher = Get-PhpSwitcher
37+
if ($null -eq $switcher) {
38+
Throw 'PHP Switcher is not initialized: you can initialize it with the Initialize-PhpSwitcher command'
39+
}
40+
If ($switcher.Targets.ContainsKey($Name) -and -Not($Force)) {
41+
Throw "Another PHP installation (" + $switcher.Targets[$Name] + ") is already assigned to the PHP Switcher with the name $Name. Use the -Force flag to force the operation anyway."
42+
}
43+
$Path = [System.IO.Path]::GetFullPath($Path)
44+
If (-Not(Test-Path -LiteralPath $Path -PathType Container)) {
45+
Throw "Unable to find the folder $Path"
46+
}
47+
$pathInfo = Get-Item -LiteralPath $Path
48+
If ($pathInfo.LinkType -eq 'Junction') {
49+
Throw "$Path must be a regular directory (it is a junction)."
50+
}
51+
Get-PhpVersionFromPath -Path $Path | Out-Null
52+
$switcher.Targets[$Name] = $Path
53+
Set-PhpManagerConfigurationKey -Key 'PHP_SWITCHER' -Value $switcher -Scope $switcher.Scope
54+
}
55+
End {
56+
}
57+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
Function Initialize-PhpSwitcher
2+
{
3+
<#
4+
.Synopsis
5+
Initializes the PHP Switcher.
6+
7+
.Parameter Alias
8+
The path where PHP will be visible when switching to a PHP version.
9+
10+
.Parameter Scope
11+
Initialize the PHP Switcher for the current user only ('CurrentUser' - default), or for any user ('AllUsers').
12+
13+
.Parameter Force
14+
Force the creation of a PHP Switcher even if there's already an existing switcher.
15+
16+
.Example
17+
Initialize-PhpSwitcher C:\PHP
18+
Add-PhpToSwitcher 5.6 C:\PHP5.6
19+
Add-PhpToSwitcher 7.2 C:\PHP7.2
20+
Switch-Php 5.6
21+
#>
22+
Param (
23+
[Parameter(Mandatory = $True, Position = 0, HelpMessage = 'The path where PHP will be visible when switching to a PHP version')]
24+
[ValidateNotNull()]
25+
[ValidateLength(1, [int]::MaxValue)]
26+
[string]$Alias,
27+
[Parameter(Mandatory = $False, Position = 99, HelpMessage = 'Initialize the PHP Switcher for the current user only (''CurrentUser''), or for any user (''AllUsers'')')]
28+
[ValidateSet('CurrentUser', 'AllUsers')]
29+
[string]$Scope = 'CurrentUser',
30+
[switch]$Force
31+
)
32+
Begin {
33+
34+
}
35+
Process {
36+
$existingSwitcher = Get-PhpSwitcher
37+
if ($null -ne $existingSwitcher) {
38+
if ($Scope -eq 'AllUsers' -and $existingSwitcher.Scope -eq 'CurrentUser') {
39+
Throw 'It''s not possible to create a PHP Switcher for all users while there''s a PHP Switcher for the current user.'
40+
}
41+
if ($Scope -eq $existingSwitcher.Scope) {
42+
If (-Not($Force)) {
43+
Throw 'Another PHP Switcher already exists. You should delete it first (with the Remove-PhpSwitcher command), or use the -Force flag.'
44+
}
45+
} Else {
46+
$existingSwitcher = $null
47+
}
48+
}
49+
$newSwitcher = @{}
50+
$Alias = [System.IO.Path]::GetFullPath($Alias)
51+
If (Test-Path -LiteralPath $Alias -PathType Container) {
52+
$aliasItem = Get-Item -LiteralPath $Alias
53+
If ($aliasItem.LinkType -ne 'Junction') {
54+
Throw "$Alias already exist and it's not a junction."
55+
}
56+
} ElseIf (Test-Path -LiteralPath $Alias) {
57+
Throw "$Alias already exist and it's not a junction."
58+
}
59+
$newSwitcher.Alias = $Alias
60+
$newSwitcher.Targets = @{}
61+
If ($existingSwitcher) {
62+
Remove-PhpSwitcher
63+
}
64+
Set-PhpManagerConfigurationKey -Key 'PHP_SWITCHER' -Value $newSwitcher -Scope $Scope
65+
Write-Verbose 'The new PHP Switcher has been created.'
66+
}
67+
End {
68+
}
69+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
Function Move-PhpSwitcher
2+
{
3+
<#
4+
.Synopsis
5+
Changes the path will be visible when switching to a PHP version.
6+
7+
.Parameter NewAlias
8+
The path where PHP will be visible when switching to a PHP version.
9+
10+
.Example
11+
Move-PhpSwitcher C:\PHP
12+
#>
13+
Param (
14+
[Parameter(Mandatory = $True, Position = 0, HelpMessage = 'The new path where PHP will be visible when switching to a PHP version')]
15+
[ValidateNotNull()]
16+
[ValidateLength(1, [int]::MaxValue)]
17+
[string]$NewAlias
18+
)
19+
Begin {
20+
}
21+
Process {
22+
$switcher = Get-PhpSwitcher
23+
if ($null -eq $switcher) {
24+
Throw 'PHP Switcher is not initialized: you can initialize it with the Initialize-PhpSwitcher command'
25+
}
26+
$NewAlias = [System.IO.Path]::GetFullPath($NewAlias)
27+
$newAliasJunction = $null
28+
If (Test-Path -LiteralPath $NewAlias -PathType Container) {
29+
$newAliasJunction = Get-Item -LiteralPath $NewAlias
30+
If ($newAliasJunction.LinkType -ne 'Junction') {
31+
Throw "$NewAlias already exist and it's not a junction."
32+
}
33+
} ElseIf (Test-Path -LiteralPath $NewAlias) {
34+
Throw "$NewAlias already exist and it's not a junction."
35+
}
36+
$oldAlias = $switcher.Alias
37+
$dsc = [System.IO.Path]::DirectorySeparatorChar
38+
If ($oldAlias.TrimEnd($dsc) -ne $NewAlias.TrimEnd($dsc)) {
39+
$recreateAs = $null
40+
If (Test-Path -LiteralPath $oldAlias -PathType Container) {
41+
$oldAliasItem = Get-Item -LiteralPath $oldAlias
42+
If ($oldAliasItem.LinkType -eq 'Junction') {
43+
If ($oldAliasItem | Get-Member -Name 'Target') {
44+
$s = [string]$oldAliasItem.Target
45+
If (Test-Path -LiteralPath $s -PathType Container) {
46+
$sItem = Get-Item -LiteralPath $s
47+
If (-Not($sItem.LinkType)) {
48+
$recreateAs = $s
49+
}
50+
}
51+
}
52+
Remove-PhpFolderFromPath -Path $oldAlias
53+
Remove-Item -LiteralPath $oldAlias -Recurse -Force
54+
}
55+
}
56+
$switcher.Alias = $NewAlias
57+
If ($recreateAs -ne $null) {
58+
If ($newAliasJunction -ne $null) {
59+
Remove-Item -LiteralPath $NewAlias -Recurse -Force
60+
}
61+
New-Item -ItemType Junction -Path $NewAlias -Value $recreateAs | Out-Null
62+
Add-PhpFolderToPath -Path $NewAlias -Persist $(If ($switcher.Scope -eq 'AllUsers') { 'System' } Else { 'User' } ) -CurrentProcess
63+
}
64+
Set-PhpManagerConfigurationKey -Key 'PHP_SWITCHER' -Value $switcher -Scope $switcher.Scope
65+
}
66+
}
67+
End {
68+
}
69+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
Function Remove-PhpFromSwitcher
2+
{
3+
<#
4+
.Synopsis
5+
Removes a PHP installation from the PHP Switcher.
6+
7+
.Parameter Name
8+
The symbolic name of the PHP installation to be removed from the PHP Switcher.
9+
If no symbolic name exists with this name, nothing occurs.
10+
11+
.Parameter Force
12+
Force removing the PHP installation from the PHP Switcher even if it is the currently active one.
13+
14+
.Example
15+
Initialize-PhpSwitcher C:\PHP
16+
Add-PhpToSwitcher 5.6 C:\PHP5.6
17+
Add-PhpToSwitcher 7.2 C:\PHP7.2
18+
Remove-PhpFromSwitcher 5.6
19+
#>
20+
Param (
21+
[Parameter(Mandatory = $True, Position = 0, HelpMessage = 'The symbolic name of the PHP installation to be removed from the PHP Switcher')]
22+
[ValidateNotNull()]
23+
[ValidateLength(1, [int]::MaxValue)]
24+
[string]$Name,
25+
[switch]$Force
26+
)
27+
Begin {
28+
}
29+
Process {
30+
$switcher = Get-PhpSwitcher
31+
if ($null -eq $switcher) {
32+
Throw 'PHP Switcher is not initialized: you can initialize it with the Initialize-PhpSwitcher command'
33+
}
34+
If ($switcher.Targets.ContainsKey($Name)) {
35+
If (-Not($Force)) {
36+
If (Test-Path -LiteralPath $switcher.Alias -PathType Container) {
37+
$aliasItem = Get-Item -LiteralPath $switcher.Alias
38+
If ($aliasItem.LinkType -eq 'Junction') {
39+
$aliasTarget = [string]$aliasItem.Target
40+
$dsc = [System.IO.Path]::DirectorySeparatorChar
41+
if ($aliasTarget.TrimEnd($dsc) -eq $switcher.Targets[$Name].TrimEnd($dsc)) {
42+
Throw "$Name is the currently active version for the PHP Switcher. Use -Force to remove it anyway."
43+
}
44+
}
45+
}
46+
}
47+
$switcher.Targets.Remove($Name)
48+
Set-PhpManagerConfigurationKey -Key 'PHP_SWITCHER' -Value $switcher -Scope $switcher.Scope
49+
}
50+
}
51+
End {
52+
}
53+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Function Remove-PhpSwitcher
2+
{
3+
Begin {
4+
}
5+
Process {
6+
$switcher = Get-PhpSwitcher
7+
If ($switcher -ne $null) {
8+
Remove-PhpFolderFromPath -Path $switcher.Alias
9+
If (Test-Path -LiteralPath $switcher.Alias -PathType Container) {
10+
$aliasItem = Get-Item -LiteralPath $switcher.Alias
11+
If ($aliasItem.LinkType -eq 'Junction') {
12+
Remove-Item -LiteralPath $switcher.Alias -Force -Recurse
13+
}
14+
}
15+
Set-PhpManagerConfigurationKey -Key 'PHP_SWITCHER' -Value $null -Scope $switcher.Scope
16+
Write-Output ('The PHP Switcher has been deleted (scope: ' + $switcher.Scope + ').')
17+
} Else {
18+
Write-Output 'No PHP Switcher is defined.'
19+
}
20+
}
21+
End {
22+
}
23+
}

0 commit comments

Comments
 (0)