ModulePathUnifier.psm1

function Test-IsEnabled {
    <#
    .SYNOPSIS
        Returns, whether the module should act.
     
    .DESCRIPTION
        Returns, whether the module should act.
 
        Should NOT act if:
        - Is Disabled
        - Is not on Windows
        - Is a SYSTEM account
     
    .EXAMPLE
        PS C:\> Test-IsEnabled
         
        Returns, whether the module should act.
    #>

    [OutputType([bool])]
    [CmdletBinding()]
    param ()

    process {
        $isWin = $PSVersionTable.PSVersion.Major -lt 6 -or $IsWindows
        if (-not $isWin) { return $false }

        if ($env:LOCALAPPDATA) {
            $disablePath = Join-Path $env:LOCALAPPDATA "ModulePathUnifier_Disabled.txt"
            if (Test-Path $disablePath) { return $false }
        }

        [System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value -notmatch '^S-1-5-'
    }
}

function Update-ModulePath {
    <#
    .SYNOPSIS
        Creates a central module path and updates the profile to load it.
     
    .DESCRIPTION
        Creates a central module path and updates the profile to load it.
     
    .EXAMPLE
        PS C:\> Update-ModulePath
         
        Creates a central module path and updates the profile to load it.
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    [CmdletBinding()]
    param ()
    
    process {
        if (-not (Test-IsEnabled)) { return }

        if (-not (Test-Path $script:modulePath)) {
            $null = New-Item -Path $script:modulePath -ItemType Directory -Force
        }
        $insertLine = 'if ($env:PSModulePath -notlike ''*{0}*'') {{ $env:PSModulePath = ''{0}'', $env:PSModulePath -join '';'' }}' -f $script:modulePath
        if ($env:PSModulePath -notlike "*$script:modulePath*") { $env:PSModulePath = $script:modulePath, $env:PSModulePath -join ';' }

        $path = $profile.CurrentUserAllHosts
        $profileFolder = Split-Path $Path

        if (-not (Test-Path $profileFolder)) {
            $null = New-Item -Path $profileFolder -ItemType Directory -Force
        }

        if (-not (Test-Path $path)) {
            $insertLine | Set-Content -Path $path
            return
        }
        if ((Get-Content -Path $Path) -contains $insertLine) {
            return
        }

        $profileContent = @($insertLine) + @(Get-Content -Path $path)
        $profileContent | Set-Content -Path $path
    }
}

function Copy-MpuModule {
    <#
    .SYNOPSIS
        Copies the calling command into the shared modulepath.
     
    .DESCRIPTION
        Copies the calling command into the shared modulepath.
        Call this during your module's import to make it available to all PowerShell versions.
     
    .EXAMPLE
        PS C:\> Copy-MpuModule
         
        Copies the calling command into the shared modulepath.
    #>

    [CmdletBinding()]
    param (
        
    )
    process {
        if (-not (Test-IsEnabled)) { return }

        $caller = (Get-PSCallStack)[1]

        $module = $caller.InvocationInfo.MyCommand.Module
        if (-not $module -and $caller.InvocationInfo.MyCommand.Name -like '*.psm1') {
            $module = Get-Module -Name ($caller.InvocationInfo.MyCommand.Path -replace 'psm1$', 'psd1') -ListAvailable -ErrorAction Ignore
            # Case: Module not found
            if (-not $module -or $module.Guid -eq [guid]::Empty) { return }
        }
        $moduleBase = $module.ModuleBase
        if (-not $moduleBase) { return }
        if ($moduleBase -like "$env:ProgramFiles*") { return }

        $targetRoot = Join-Path -Path $script:modulePath -ChildPath "$($module.Name)\$($module.Version)"
        if (Test-Path -Path "$targetRoot\$($module.Name).psd1") { return }
        if (-not (Test-Path -Path $targetRoot)) {
            $null = New-Item -Path $targetRoot -ItemType Directory -Force
        }

        Copy-Item -Path "$moduleBase\*" -Destination $targetRoot -Recurse
    }
}

function Disable-ModulePathUnifier {
    <#
    .SYNOPSIS
        Disables the ModulePathUnifier module.
     
    .DESCRIPTION
        Disables the ModulePathUnifier module.
        Sets a flag in the user profile (under LocalAppData) that tells this module to stop doing its work.
        Use Enable-ModulePathUnifier to reenable it.
     
    .EXAMPLE
        PS C:\> Disable-ModulePathUnifier
         
        Disables the ModulePathUnifier module.
    #>

    [CmdletBinding()]
    param (
        
    )
    process {
        if (-not $env:LOCALAPPDATA) { return }

        $disablePath = Join-Path $env:LOCALAPPDATA "ModulePathUnifier_Disabled.txt"
        'Module has been disabled and will not copy modules or maintain a central modulepath anymore. Does not affect your $profile content' | Set-Content $disablePath
    }
}

function Enable-ModulePathUnifier {
    <#
    .SYNOPSIS
        Re-enables this module after having previously disabled it.
     
    .DESCRIPTION
        Re-enables this module after having previously disabled it.
        Use Disable-ModulePathUnifier to disable this module.
     
    .EXAMPLE
        PS C:\> Enable-ModulePathUnifier
         
        Re-enables this module after having previously disabled it.
    #>

    [CmdletBinding()]
    param (
        
    )
    process {
        if (-not $env:LOCALAPPDATA) { return }

        $disablePath = Join-Path $env:LOCALAPPDATA "ModulePathUnifier_Disabled.txt"
        Remove-Item -Path $disablePath -ErrorAction Ignore

        $script:modulePath = ([System.Environment]::GetFolderPath('MyDocuments')),'PSModules' -join '\'
    }
}


if (Test-IsEnabled) {
    $script:modulePath = ([System.Environment]::GetFolderPath('MyDocuments')),'PSModules' -join '\'
    Update-ModulePath
}