Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
55 changes: 55 additions & 0 deletions src/actions/install.ps1
Original file line number Diff line number Diff line change
@@ -1,4 +1,59 @@

function Get-Latest-PHP-Version {
param ($arch = $null, $buildType = $null)

try {
$urls = Get-Source-Urls
$allVersions = @()

foreach ($key in $urls.Keys) {
$url = $urls[$key]
try {
$html = Invoke-WebRequest -Uri $url
$links = $html.Links

$filteredLinks = $links | Where-Object {
$_.href -match "php-\d+(\.\d+)*-(?:nts-)?win.*\.zip$" -and
$_.href -notmatch "php-debug" -and
$_.href -notmatch "php-devel"
}

$filteredLinks | ForEach-Object {
$version = $_.href -replace '/downloads/releases/archives/|/downloads/releases/|php-|-nts|-Win.*|.zip', ''
$fileName = $_.href -split "/"
$fileName = $fileName[$fileName.Count - 1]
$allVersions += @{
href = $_.href
version = $version
fileName = $fileName
BuildType = if ($fileName -match 'nts') { 'NTS' } else { 'TS' }
arch = ($fileName -replace '.*\b(x64|x86)\b.*', '$1')
}
}
} catch {
continue
}
}

if ($arch) {
$allVersions = $allVersions | Where-Object { $_.arch -eq $arch }
}
if ($buildType) {
$allVersions = $allVersions | Where-Object { $_.BuildType -eq $buildType }
}

# Sort by version number (descending) and return the first one
$latest = $allVersions | Sort-Object { [version]$_.version } -Descending | Select-Object -First 1

return $latest
} catch {
$logged = Log-Data -data @{
header = "$($MyInvocation.MyCommand.Name) - Failed to get latest PHP version"
exception = $_
}
return $null
}
}
function Get-PHP-Versions-From-Url {
param ($url, $version)

Expand Down
14 changes: 11 additions & 3 deletions src/core/router.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ function Invoke-PVMInstall {
param($arguments)

$version = $arguments[0]
$arch = Resolve-Arch -arguments $arguments
$buildType = Resolve-BuildType -arguments $arguments

if ($version -eq 'auto') {
$result = Auto-Select-PHP-Version
Expand All @@ -74,16 +76,22 @@ function Invoke-PVMInstall {
}

$version = $result.version
} elseif ($version -eq 'latest') {
$latestVersion = Get-Latest-PHP-Version -arch $arch -buildType $buildType
if (-not $latestVersion) {
Write-Host "`nFailed to find the latest PHP version"
return -1
}

$version = $latestVersion.version
Write-Host "`nLatest available PHP version is $version"
}

if (-not $version) {
Write-Host "`nPlease provide a PHP version to install"
return -1
}

$arch = Resolve-Arch -arguments $arguments
$buildType = Resolve-BuildType -arguments $arguments

$result = Install-PHP -version $version -arch $arch -buildType $buildType
Display-Msg-By-ExitCode -result $result
return 0
Expand Down
61 changes: 61 additions & 0 deletions tests/install.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,67 @@ Describe "Get-Source-Urls Tests" {
}
}

Describe "Get-Latest-PHP-Version Tests" -tag i {
BeforeEach {
Reset-MockState
Mock Write-Host {}
}

It "Should return the latest available version" {
$mockLinks = @(
@{ href = "/downloads/releases/php-8.0.10-Win32-vs16-x64.zip" },
@{ href = "/downloads/releases/php-8.1.12-Win32-vs16-x64.zip" },
@{ href = "/downloads/releases/php-8.2.1-Win32-vs16-x64.zip" },
@{ href = "/downloads/releases/php-8.1.15-nts-Win32-vs16-x64.zip" }
)

Set-MockWebResponse -url $PHP_WIN_ARCHIVES_URL -links $mockLinks
Set-MockWebResponse -url $PHP_WIN_RELEASES_URL -links $mockLinks

$result = Get-Latest-PHP-Version

$result | Should -Not -BeNullOrEmpty
$result.version | Should -Be "8.2.1"
$result.arch | Should -Be "x64"
$result.BuildType | Should -Be "TS"
}

It "Should filter by architecture and build type" {
$mockLinks = @(
@{ href = "/downloads/releases/php-8.3.0-Win32-vs16-x64.zip" },
@{ href = "/downloads/releases/php-8.3.1-nts-Win32-vs16-x64.zip" },
@{ href = "/downloads/releases/php-8.3.2-Win32-vs16-x86.zip" },
@{ href = "/downloads/releases/php-8.3.3-nts-Win32-vs16-x86.zip" }
)

Set-MockWebResponse -url $PHP_WIN_ARCHIVES_URL -links $mockLinks
Set-MockWebResponse -url $PHP_WIN_RELEASES_URL -links $mockLinks

$result = Get-Latest-PHP-Version -arch "x86" -buildType "NTS"

$result | Should -Not -BeNullOrEmpty
$result.version | Should -Be "8.3.3"
$result.arch | Should -Be "x86"
$result.BuildType | Should -Be "NTS"
}

It "Should return null when no versions are available" {
Set-MockWebResponse -url $PHP_WIN_ARCHIVES_URL -links @()
Set-MockWebResponse -url $PHP_WIN_RELEASES_URL -links @()

$result = Get-Latest-PHP-Version

$result | Should -BeNullOrEmpty
}

It "Should handle exception gracefully" {
Mock Get-Source-Urls { throw 'Error' }

$result = Get-Latest-PHP-Version

$result | Should -BeNullOrEmpty
}
}

Describe "Get-PHP-Versions-From-Url Tests" {
BeforeEach {
Expand Down
21 changes: 21 additions & 0 deletions tests/router.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,27 @@ Describe "Invoke-PVMInstall Tests" {
}
}

It "Should install latest PHP version when 'latest' argument is provided" {
$arguments = @("latest")
Mock Get-Latest-PHP-Version { return @{version = "8.6.0"} }

$result = Invoke-PVMInstall -arguments $arguments
$result | Should -Be 0

Assert-MockCalled Install-PHP -Times 1 -ParameterFilter {
$version -eq "8.6.0"
}
}

It "Should return -1 when no latest PHP version was found" {
$arguments = @("latest")
Mock Get-Latest-PHP-Version { return $null }

$result = Invoke-PVMInstall -arguments $arguments

$result | Should -Be -1
}

It "Should return -1 when detected PHP version is already installed" {
$arguments = @("auto")
Mock Auto-Select-PHP-Version { return @{ code = 0; version = "8.2" } }
Expand Down
Loading