Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
117 commits
Select commit Hold shift + click to select a range
d6abc95
Implement list by os arch
drissboumlik Feb 2, 2026
d58f425
Implement install by os arch (wip)
drissboumlik Feb 2, 2026
6122956
Implement install ext by os arch (wip)
drissboumlik Feb 2, 2026
2d44d28
Add helpers to get php accurate data
drissboumlik Feb 5, 2026
163128a
Add Can-Use-Cache helper
drissboumlik Feb 5, 2026
e847862
Remove formatting fetched data from Get-Data-From-Cache
drissboumlik Feb 5, 2026
ba7e4de
Refactor Resolve-Arch
drissboumlik Feb 5, 2026
be004c6
Refactor php list commands and include nts versions
drissboumlik Feb 5, 2026
3c32db7
Add buildType property to returned object in Get-Current-PHP-Version
drissboumlik Feb 5, 2026
b093d8a
Refactor checking for current php version
drissboumlik Feb 5, 2026
e441668
Refactor Is-PHP-Version-Installed
drissboumlik Feb 5, 2026
3095b00
Refactor checking for current php version
drissboumlik Feb 5, 2026
a4087da
Refactor and include nts versions
drissboumlik Feb 5, 2026
362396e
Refresh cached list after downloading new php version
drissboumlik Feb 5, 2026
66832d3
Fix bug Get-Matching-PHP-Versions
drissboumlik Feb 5, 2026
77fe7dd
Add helper to check equality of two php versions
drissboumlik Feb 5, 2026
37cbdb5
Refactor uninstall command
drissboumlik Feb 5, 2026
1cdda4a
Refresh cached list after removing php version
drissboumlik Feb 5, 2026
418f2c4
Replace Count with Length
drissboumlik Feb 5, 2026
bb919cf
Refactor use command
drissboumlik Feb 5, 2026
b479257
Convert hashtable to custom object
drissboumlik Feb 6, 2026
c1374bc
Trim text
drissboumlik Feb 6, 2026
9b94b10
Remove unused variable
drissboumlik Feb 6, 2026
8e79cfe
Remove Get-PHP-Path-By-Version and related tests
drissboumlik Feb 6, 2026
65c2683
Fix use.tests.ps1
drissboumlik Feb 6, 2026
76a5224
Fix current.tests.ps1
drissboumlik Feb 6, 2026
5666b04
Fix uninstall.tests.ps1
drissboumlik Feb 6, 2026
32c7223
Fix list.tests.ps1
drissboumlik Feb 6, 2026
572d500
Fix install.tests.ps1
drissboumlik Feb 6, 2026
cf8e718
Remove unused function
drissboumlik Feb 7, 2026
bbae42e
Fix common.tests.ps1
drissboumlik Feb 7, 2026
076ce5b
Handle errors for Can-Use-Cache
drissboumlik Feb 7, 2026
6a79335
Add tests for Can-Use-Cache
drissboumlik Feb 7, 2026
bb06d0d
Remove unused assertion
drissboumlik Feb 7, 2026
c6fda90
Make sure first match is selected
drissboumlik Feb 7, 2026
ea80fc1
Add tests for Resolve-Arch
drissboumlik Feb 7, 2026
3d8e6b8
Fix typo
drissboumlik Feb 7, 2026
c995458
Add tests for Get-PHPInstallInfo
drissboumlik Feb 7, 2026
d2f2bab
Add tests for Is-Two-PHP-Versions-Equal
drissboumlik Feb 7, 2026
5090c3f
Add tests for Get-BinaryArchitecture-From-DLL
drissboumlik Feb 7, 2026
a07291f
Fix ini.tests.ps1
drissboumlik Feb 7, 2026
ac0aa81
Fix common.tests.ps1
drissboumlik Feb 7, 2026
d33259b
Convert fetched versions to pscustomobject
drissboumlik Feb 7, 2026
923a888
Fix list.tests.ps1
drissboumlik Feb 7, 2026
6828a2b
Add tests for Refresh-Installed-PHP-Versions-Cache
drissboumlik Feb 7, 2026
7bf0984
Add tests for Get-Installed-PHP-Versions-From-Directory
drissboumlik Feb 7, 2026
5cd3cc2
Fix router.tests.ps1
drissboumlik Feb 7, 2026
d673f91
Add tests for Invoke-PVMProfile
drissboumlik Feb 7, 2026
6299eba
Filter by arch after fetching from source/cache
drissboumlik Feb 7, 2026
b3d41ae
Add tests for handeling both arch
drissboumlik Feb 7, 2026
796b287
Fix dynamic property assignment
drissboumlik Feb 7, 2026
7d7d395
Handle existence of previous xdebug line
drissboumlik Feb 7, 2026
27aedce
Use TestDrive for current php path
drissboumlik Feb 7, 2026
a775c5f
Remove test tag
drissboumlik Feb 8, 2026
b1a41a7
Format date before printing
drissboumlik Feb 8, 2026
3bb057a
Convert seconds to single
drissboumlik Feb 8, 2026
26d7b6c
Add arch and buildtype to xdebug fetched list items
drissboumlik Feb 8, 2026
ae1f8ea
Sort xdebug list by type and arch
drissboumlik Feb 8, 2026
90101db
Fix current.tests.ps1
drissboumlik Feb 8, 2026
31a5aac
Add tests covering missing paths for Format-NiceTimestamp
drissboumlik Feb 9, 2026
8b78040
Add tests covering missing paths for Show-Log
drissboumlik Feb 9, 2026
8a748da
Print xdebug compiler version
drissboumlik Feb 9, 2026
32534a0
Added helper Get-OrUpdateCache to refactor cache fetching process w/ …
drissboumlik Feb 9, 2026
9159a05
Refactor cache fetching with Get-OrUpdateCache
drissboumlik Feb 9, 2026
2a781c0
Cover missing paths in current.tests.ps1
drissboumlik Feb 9, 2026
9bef158
Fix log-data mock
drissboumlik Feb 10, 2026
477e7b0
Fix common.tests.ps1
drissboumlik Feb 10, 2026
527019c
Cover missing paths in common.tests.ps1
drissboumlik Feb 10, 2026
2c6881e
Add tests covering missing paths in router.tests.ps1
drissboumlik Feb 11, 2026
606527f
Truncate fetched xdebug list
drissboumlik Feb 14, 2026
7e69451
Add forground color to success xdebug installation message
drissboumlik Feb 14, 2026
d04ac3e
Cache fetched xdebug list
drissboumlik Feb 14, 2026
cb83103
Data is already cached in the helper
drissboumlik Feb 14, 2026
460a88b
Add filter by buildType to Get-Installed-PHP-Versions
drissboumlik Feb 16, 2026
a8d19a6
Add filter by buildType to xdebug installation
drissboumlik Feb 16, 2026
5978d8f
Add Resolve-BuildType helper
drissboumlik Feb 16, 2026
2ea7342
Move xdebug helpers to ini file
drissboumlik Feb 16, 2026
30f9853
Add filter by buildType to php list command
drissboumlik Feb 16, 2026
66e4f76
Add filter by buildType to install php command
drissboumlik Feb 16, 2026
d8e5d39
Add tests covering Get-Installed-PHP-Versions for buildtype filter
drissboumlik Feb 16, 2026
0144f11
Add tests covering Resolve-BuildType
drissboumlik Feb 16, 2026
4e28603
Add tests covering Get-PHP-Versions for buildtype filter
drissboumlik Feb 16, 2026
fffe54e
Add tests covering Get-Available-PHP-Versions for buildtype filter
drissboumlik Feb 16, 2026
27f91ee
Remove all imports from tests/* files
drissboumlik Feb 16, 2026
6a1ecec
Force order on hashtable
drissboumlik Feb 16, 2026
19e06c1
Replace match with eq
drissboumlik Feb 16, 2026
572f466
Add sorting option for tests results w/ tests
drissboumlik Feb 17, 2026
79e6be0
Get arch and buildType from current php version
drissboumlik Feb 17, 2026
41f59e5
Fix typo
drissboumlik Feb 17, 2026
7cea3ca
Fix spacings for duration
drissboumlik Feb 18, 2026
107c118
Fix mock Make-Directory
drissboumlik Feb 18, 2026
44b6780
Make index start from 0
drissboumlik Feb 19, 2026
a1f7483
Refactor extension fetching to Get-Extension-From-URL
drissboumlik Feb 20, 2026
3fcddc9
Fix returned value for null checking
drissboumlik Feb 20, 2026
49cd56d
Refactor and use cache for heavy data fetching (wip)
drissboumlik Feb 21, 2026
66a9c7a
Fix arch and buildtype filtering
drissboumlik Feb 22, 2026
16e5b67
Disable caching for categories fetching
drissboumlik Feb 23, 2026
8668885
Fix typo
drissboumlik Feb 23, 2026
f1077d4
Fix function name
drissboumlik Feb 23, 2026
0068930
Remove unnecessary property
drissboumlik Feb 23, 2026
3691308
Check null object
drissboumlik Feb 23, 2026
85ae284
Add missing tests for new functions
drissboumlik Feb 23, 2026
670e4d1
Adapt tests to cover missing paths
drissboumlik Feb 23, 2026
8a1a794
Handle empty result
drissboumlik Feb 24, 2026
9bff651
Fetch accurate extName if available
drissboumlik Feb 24, 2026
13e8d14
Handle categories with multiple pages
drissboumlik Feb 24, 2026
fd92a60
Adapt tests to new results handling
drissboumlik Feb 24, 2026
ff4c9c1
Add tests for Get-Extension-Matching-Categories-By-Page
drissboumlik Feb 24, 2026
6296ec0
Fetch all extesions links for categories with multiple pages
drissboumlik Feb 24, 2026
4e90e5c
Add tests for Get-Packages-From-Source-Links catch block
drissboumlik Feb 25, 2026
21079d3
Add tests for Get-Extension-Categories-By-Page
drissboumlik Feb 25, 2026
84eec7e
Add break lines to extensions printing
drissboumlik Feb 25, 2026
18d661a
Include rc versions and sort
drissboumlik Feb 26, 2026
83b7f96
Add tests covering catch blog
drissboumlik Feb 26, 2026
6fbd081
Refactor Add-Missing-PHPExtension-To-Ini
drissboumlik Feb 27, 2026
997dd88
Add tests covering catch block in Install-IniExtension
drissboumlik Feb 27, 2026
9166d1a
Mock CACH_PATH
drissboumlik Feb 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
433 changes: 217 additions & 216 deletions readme.md

Large diffs are not rendered by default.

110 changes: 80 additions & 30 deletions src/actions/common.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,62 @@ function Is-PVM-Setup {
}
}

function Refresh-Installed-PHP-Versions-Cache {
try {
$installedVersions = Get-Installed-PHP-Versions-From-Directory
$cached = Cache-Data -cacheFileName "installed_php_versions" -data $installedVersions -depth 1

return 0
} catch {
$logged = Log-Data -data @{
header = "$($MyInvocation.MyCommand.Name) - Failed to refresh installed PHP versions cache"
exception = $_
}

return -1
}
}

function Get-Installed-PHP-Versions-From-Directory {
$directories = Get-All-Subdirectories -path "$STORAGE_PATH\php"
$installedVersions = $directories | ForEach-Object {
if (Test-Path "$($_.FullName)\php.exe"){
$phpInfo = Get-PHPInstallInfo -path $_.FullName

return $phpInfo
}
return $null
}

$installedVersions = ($installedVersions | Sort-Object { [version]$_.Version })

$cached = Cache-Data -cacheFileName "installed_php_versions" -data $installedVersions -depth 1

return $installedVersions
}

function Get-Installed-PHP-Versions {

param ($arch = $null, $buildType = $null)
try {
$directories = Get-All-Subdirectories -path "$STORAGE_PATH\php"
$names = $directories | ForEach-Object {
if (Test-Path "$($_.FullName)\php.exe"){
return $_.Name
}
return $null
$installedVersions = Get-OrUpdateCache -cacheFileName "installed_php_versions" -depth 1 -compute {
Get-Installed-PHP-Versions-From-Directory
}

if ($null -eq $installedVersions) {
return @()
}

if ($arch) {
$installedVersions = $installedVersions | Where-Object { $_.Arch -eq $arch }
}

if ($buildType) {
$installedVersions = $installedVersions | Where-Object { $_.BuildType -eq $buildType }
}
return ($names | Sort-Object { [version]$_ })

$installedVersions = $installedVersions | Sort-Object { [version]$_.Version }

return $installedVersions
} catch {
$logged = Log-Data -data @{
header = "$($MyInvocation.MyCommand.Name) - Failed to retrieve installed PHP versions"
Expand All @@ -64,47 +109,48 @@ function Get-UserSelected-PHP-Version {
if (-not $installedVersions -or $installedVersions.Count -eq 0) {
return $null
}
if ($installedVersions.Count -eq 1) {
$version = $($installedVersions)
if ($installedVersions.Length -eq 1) {
$versionObj = $($installedVersions)
} else {
$currentVersion = Get-Current-PHP-Version
if ($currentVersion -and $currentVersion.version) {
$currentVersion = $currentVersion.version
}
$index = 0
Write-Host "`nInstalled versions :"
$installedVersions | ForEach-Object {
$versionNumber = $_
$_ | Add-Member -NotePropertyName "index" -NotePropertyValue $index -Force
$isCurrent = ""
if ($currentVersion -eq $versionNumber) {
if (Is-Two-PHP-Versions-Equal -version1 $currentVersion -version2 $_) {
$isCurrent = "(Current)"
}
Write-Host " - $versionNumber $isCurrent"
$metaData = ""
if ($_.Arch) {
$metaData += $_.Arch + " "
}
if ($_.BuildType) {
$metaData += $_.BuildType
}
$versionNumber = "$($_.version) ".PadRight(15, '.')
Write-Host " [$index] $versionNumber $metaData $isCurrent"
$index++
}
$response = Read-Host "`nEnter the exact version to use. (or press Enter to cancel)"
$response = Read-Host "`nInsert the [number] matching the version to uninstall (or press Enter to cancel)"
$response = $response.Trim()
if (-not $response) {
return @{ code = -1; message = "Operation cancelled."; color = "DarkYellow"}
}
$version = $response
$versionObj = $installedVersions | Where-Object { $_.index -eq $response }
}
$phpPath = Get-PHP-Path-By-Version -version $version

return @{ code = 0; version = $version; path = $phpPath }
return @{ code = 0; version = $versionObj.version; arch = $versionObj.arch; buildType = $versionObj.BuildType; path = $versionObj.InstallPath }
}

function Get-Matching-PHP-Versions {
param ($version)

try {
$installedVersions = Get-Installed-PHP-Versions # You should have this function

$matchingVersions = @()
foreach ($v in $installedVersions) {
if ($v -like "$version*") {
$matchingVersions += ($v -replace 'php', '')
}
}
$installedVersions = Get-Installed-PHP-Versions

$matchingVersions = $installedVersions | Where-Object { $_.Version -like "$version*" }

return $matchingVersions
} catch {
$logged = Log-Data -data @{
Expand All @@ -120,8 +166,12 @@ function Is-PHP-Version-Installed {
param ($version)

try {
$installedVersions = Get-Matching-PHP-Versions -version $version
return ($installedVersions -contains $version)
$installedVersions = Get-Matching-PHP-Versions -version $version.version
return ($installedVersions | Where-Object {
$_.Version -eq $version.version -and
$_.Arch -eq $version.arch -and
$_.BuildType -eq $version.BuildType
})
} catch {
$logged = Log-Data -data @{
header = "$($MyInvocation.MyCommand.Name) - Failed to check if PHP version $version is installed"
Expand Down
123 changes: 63 additions & 60 deletions src/actions/current.ps1
Original file line number Diff line number Diff line change
@@ -1,61 +1,64 @@

function Get-PHP-Status {
param($phpPath)

$status = @{ opcache = $false; xdebug = $false }
try {
$phpIniPath = "$phpPath\php.ini"
if (-not (Test-Path $phpIniPath)) {
return $status
}

$iniContent = Get-Content $phpIniPath

foreach ($line in $iniContent) {
$trimmed = $line.Trim()
if ($trimmed -match '^(;)?\s*zend_extension\s*=.*opcache.*$') {
$status.opcache = -not $trimmed.StartsWith(';')
}

if ($trimmed -match '^(;)?\s*zend_extension\s*=.*xdebug.*$') {
$status.xdebug = -not $trimmed.StartsWith(';')
}
}
} catch {
$logged = Log-Data -data @{
header = "$($MyInvocation.MyCommand.Name) - Failed to retrieve PHP status"
exception = $_
}
Write-Host "An error occurred while checking PHP status: $_"
}

return $status
}

function Get-Current-PHP-Version {

try {
$emptyResult = @{ version = $null; path = $null; status = @{ opcache = $false; xdebug = $false } }
$currentPhpVersionPath = Get-Item $PHP_CURRENT_VERSION_PATH
if (-not $currentPhpVersionPath) {
return $emptyResult
}

$currentPhpVersionPath = $currentPhpVersionPath.Target
if (-not (Is-Directory-Exists -path $currentPhpVersionPath)) {
return $emptyResult
}

return @{
version = $(Split-Path $currentPhpVersionPath -Leaf)
path = $currentPhpVersionPath
status = Get-PHP-Status -phpPath $currentPhpVersionPath
}
} catch {
$logged = Log-Data -data @{
header = "$($MyInvocation.MyCommand.Name) - Failed to retrieve current PHP version"
exception = $_
}
return $emptyResult
}

function Get-PHP-Status {
param($phpPath)

$status = @{ opcache = $false; xdebug = $false }
try {
$phpIniPath = "$phpPath\php.ini"
if (-not (Test-Path $phpIniPath)) {
return $status
}

$iniContent = Get-Content $phpIniPath

foreach ($line in $iniContent) {
$trimmed = $line.Trim()
if ($trimmed -match '^(;)?\s*zend_extension\s*=.*opcache.*$') {
$status.opcache = -not $trimmed.StartsWith(';')
}

if ($trimmed -match '^(;)?\s*zend_extension\s*=.*xdebug.*$') {
$status.xdebug = -not $trimmed.StartsWith(';')
}
}
} catch {
$logged = Log-Data -data @{
header = "$($MyInvocation.MyCommand.Name) - Failed to retrieve PHP status"
exception = $_
}
Write-Host "An error occurred while checking PHP status: $_"
}

return $status
}

function Get-Current-PHP-Version {

try {
$emptyResult = @{ version = $null; path = $null; status = @{ opcache = $false; xdebug = $false } }
$currentPhpVersionPath = Get-Item $PHP_CURRENT_VERSION_PATH
if (-not $currentPhpVersionPath) {
return $emptyResult
}

$currentPhpVersionPath = $currentPhpVersionPath.Target
if (-not (Is-Directory-Exists -path $currentPhpVersionPath)) {
return $emptyResult
}
$phpInfo = Get-PHPInstallInfo -path $currentPhpVersionPath

return @{
version = $phpInfo.Version
arch = $phpInfo.Arch
buildType = $phpInfo.BuildType
path = $phpInfo.InstallPath
status = Get-PHP-Status -phpPath $currentPhpVersionPath
}
} catch {
$logged = Log-Data -data @{
header = "$($MyInvocation.MyCommand.Name) - Failed to retrieve current PHP version"
exception = $_
}
return $emptyResult
}
}
Loading