Functions/ModuleManagement/Import-FpsModule.ps1

<#
.SYNOPSIS
    Installs or updates given module and imports it into the PowerShell Session.
.DESCRIPTION
    1. If modules is already imported, do nothing
        (i) Except if Force is set.
    2. If module is already installed
        a. Test if there is a newer version available.
        b. Updates module if there is a newer version.
    3. If module is not yet installed, installes module.
    4. Imports module
    5. Cleanup previous installations of the module
       (i) Except if KeepPreviousVersions is set.
.EXAMPLE
    Import-FpsModule -ModuleNames 'CredentialManager'
.EXAMPLE
    $feedPassword = ConvertTo-SecureString -String 'ff34885a8624460a8555y03w1shth12wa2va11d' -AsPlainText -Force
    $feedCredential = New-Object System.Management.Automation.PSCredential ('dummy@org.nl', $feedPassword)
    Import-FpsModule `
        -ModuleNames 'FpsDevelopment' `
        -Repository 'fpstools_internal' `
        -feedCredential $feedCredential `
        -Force
#>

function Import-FpsModule {
    [CmdletBinding()]
    param (
        # The module name of the module(s) to install/update/import.
        [Parameter(Mandatory=$true, 
                       ValueFromPipeline=$true,
                       ValueFromPipelineByPropertyName=$true)]
        [string[]] $ModuleNames,

        # Specifies the friendly name of a repository that has been registered by running Register-PSRepository.
        [string] $Repository = 'PSGallery',

        # PowerShell Credential object with credentials to access the PowerShell Feed/Repository.
        # Not required for default Repository 'PSGallery'.
        [PSCredential] $FeedCredential,

        # Default all previous versions of the module will be removed. To keep older modules set KeepPreviousVersions.
        [switch] $KeepPreviousVersions,

        # Forces the installation/update and import of modules.
        [switch] $Force

    )

    foreach($moduleName in $ModuleNames){
    
        'Importing module {0}.' -f $moduleName | Write-Host

        # if module is already loaded into the PS Session, continue
        if (Get-Module -name $moduleName) {
            ' Module {0} is already imported.' -f $moduleName | Write-Host

            if($Force -eq $false){
                continue
            }
        } 
            
        # if module is installed on local system
        if (Get-Module -name $moduleName -ListAvailable) {
            ' Module {0} is already installed, validating if the module is up-to-date.' -f $moduleName | Write-Host

            # Validate if module is up-to-date
            $latestVersionLocal = (Get-Module -name $moduleName -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1 ).Version
            try {
                $params = @{
                    Name       = $moduleName
                    Repository = $Repository
                }
                if([string]::IsNullOrEmpty($FeedCredential) -eq $false){
                    $params += @{ Credential = $FeedCredential}
                }
                $latestVersionGallery = (Find-Module @params).Version
                
                ' Module {0} installed version is ''{1}'', latest from gallery is ''{2}''. ' -f 
                    $moduleName, $latestVersionLocal.ToString(), $latestVersionGallery.ToString() | Write-Host 
            } catch {
                ' Module {0} currently not available online.' -f $moduleName | Write-Host
            }

            # Update module if required
            if([version] $latestVersionLocal -lt [version] $latestVersionGallery){
                
                ' Updating {0} to {1}' -f 
                    $moduleName, $latestVersionGallery.ToString() | Write-Host

                $params = @{
                    Name         = $moduleName
                    Repository   = $Repository
                    AllowClobber = $true
                    Scope        = 'CurrentUser'
                    Force        = $true
                }
                if([string]::IsNullOrEmpty($FeedCredential) -eq $false){
                    $params += @{ Credential = $FeedCredential}
                }
                Install-Module @params
            }
                
            # Import module
            Import-Module $moduleName -DisableNameChecking -Force:$Force

            continue
        }
        
        # First install module
        ' Module {0} is not yet installed; Installing module..' -f $ModuleName | Write-Host

        $params = @{
            Name        = $moduleName
            Repository  = $Repository
            ErrorAction = 'SilentlyContinue'
        }
        if([string]::IsNullOrEmpty($FeedCredential) -eq $false){
            $params += @{ Credential = $FeedCredential}
        }
        if(Find-Module @params){

            $params = @{
                Name         = $moduleName
                Repository   = $Repository
                AllowClobber = $true
                Scope        = 'CurrentUser'
                Force        = $true
            }
            if([string]::IsNullOrEmpty($FeedCredential) -eq $false){
                $params += @{ Credential = $FeedCredential}
            }
            Install-Module @params
            Import-Module $ModuleName -DisableNameChecking -Force:$Force
        }
        
        # Cleanup previous installations of the module
        if($KeepPreviousVersions -eq $false){
            Get-Module -ListAvailable -Name $ModuleName | 
                Sort-Object -Property Version | 
                Select-Object -Skip 1 | 
                Uninstall-Module -Force -ErrorAction SilentlyContinue
        }
    }
}

Export-ModuleMember -Function Import-FpsModule