Pax8API/Private/Test-Pax8ProductMatch.ps1

function ConvertTo-Pax8SearchText {
    param (
        [object]$Value
    )

    if ($null -eq $Value) {
        return ''
    }

    if ($Value -is [string]) {
        return $Value
    }

    if ($Value -is [System.Collections.IDictionary]) {
        return ($Value | ConvertTo-Json -Depth 20 -Compress)
    }

    if ($Value.PSObject.Properties.Count -gt 0) {
        return ($Value | ConvertTo-Json -Depth 20 -Compress)
    }

    [string]$Value
}

function Get-Pax8NormalizedSearchText {
    param (
        [string]$Text
    )

    if ([string]::IsNullOrWhiteSpace($Text)) {
        return ''
    }

    (($Text.ToLowerInvariant() -replace '[^a-z0-9]+', ' ') -replace '\s+', ' ').Trim()
}

function Test-Pax8ProductMatch {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [object]$Product,

        [Parameter(Mandatory)]
        [string]$Search,

        [string[]]$Property = @('name', 'vendorName', 'sku', 'vendorSku', 'altVendorSku'),

        [switch]$Exact
    )

    if ([string]::IsNullOrWhiteSpace($Search)) {
        return $true
    }

    $values = foreach ($propertyName in $Property) {
        if ($Product.PSObject.Properties[$propertyName]) {
            ConvertTo-Pax8SearchText -Value $Product.$propertyName
        }
    }

    $values = @($values | Where-Object { -not [string]::IsNullOrWhiteSpace([string]$_) })
    if ($values.Count -eq 0) {
        return $false
    }

    if ($Exact) {
        foreach ($value in $values) {
            if ([string]::Equals([string]$value, $Search, [System.StringComparison]::OrdinalIgnoreCase)) {
                return $true
            }
        }

        return $false
    }

    $searchPattern = if ($Search -match '[*?\[]') { $Search } else { "*$Search*" }
    foreach ($value in $values) {
        if ([string]$value -like $searchPattern) {
            return $true
        }
    }

    $normalizedSearch = Get-Pax8NormalizedSearchText -Text ($Search -replace '[*?]', ' ')
    $normalizedHaystack = Get-Pax8NormalizedSearchText -Text ($values -join ' ')
    if ([string]::IsNullOrWhiteSpace($normalizedSearch)) {
        return $true
    }

    if ($normalizedHaystack.Contains($normalizedSearch)) {
        return $true
    }

    $tokens = @($normalizedSearch -split '\s+' | Where-Object { $_ })
    foreach ($token in $tokens) {
        if (-not $normalizedHaystack.Contains($token)) {
            return $false
        }
    }

    $true
}

function Get-Pax8ProductSearchScore {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [object]$Product,

        [Parameter(Mandatory)]
        [string]$Search
    )

    $name = if ($Product.PSObject.Properties['name']) { [string]$Product.name } else { '' }
    $normalizedName = Get-Pax8NormalizedSearchText -Text $name
    $normalizedSearch = Get-Pax8NormalizedSearchText -Text ($Search -replace '[*?]', ' ')

    if ($normalizedName -eq $normalizedSearch) {
        return 0
    }

    if ($normalizedName.Contains($normalizedSearch)) {
        return 10
    }

    $tokens = @($normalizedSearch -split '\s+' | Where-Object { $_ })
    $missingNameTokens = @($tokens | Where-Object { -not $normalizedName.Contains($_) })
    if ($missingNameTokens.Count -eq 0) {
        return 20
    }

    30
}