2

I'm running a script in which I'm trying to get the item whose content has broken links, (links that redirect the user to a page with 404 as response). But I always get the same result, no broken links. However, I still have to identify a couple of items that should appear on the final report.

Does anyone know how I can get those items on a report?

Here is the script:

$database = "master"
$root = Get-Item -Path (@{$true="$($database):"; $false="$($database):\content\"}[(Test-Path -Path "$($database):\content\")]) 
$linksToCheck =  @("internal")
$linkTypes = [ordered]@{"Internal Links"="internal";"External Links (General Link only)"="external"};

$versionOptions = [ordered]@{
    "Latest"="1"
}

$props = @{
    Parameters = @(
        @{Name="root"; Title="Choose the report root"; Tooltip="Only items in this branch will be returned."; Columns=9},
        @{Name="searchVersion"; Value="1"; Title="Version"; Options=$versionOptions; Tooltip="Choose a version."; Columns="3"; Placeholder="All"},
        @{Name="linksToCheck"; Title="Link types to check"; Options=$linkTypes; Tooltip="which link types you want to check"; Editor="checklist"} 
    )
    Title = "Broken Links Report"
    Description = "Choose the criteria for the report."
    Width = 550
    Height = 300
    ShowHints = $true
    Icon = [regex]::Replace($PSScript.Appearance.Icon, "Office", "OfficeWhite", [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
}

$result = Read-Variable @props

if($result -eq "cancel"){
    exit
}

filter HasBrokenLink {
    param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [Sitecore.Data.Items.Item]$Item,

        [Parameter()]
        [bool]$IncludeAllVersions
    )

    if(!$Item) { return }
    if($linksToCheck.Contains("internal")) {
        $brokenLinks = $item.Links.GetBrokenLinks($IncludeAllVersions)
        if($brokenlinks -ne $null -and $brokenlinks.Length -gt 0) {
            $finalRenderings = Get-Rendering -Item $Item -FinalLayout
            $sharedRenderings = Get-Rendering -Item $Item
            $uniqueIdLookup = New-Object System.Collections.Generic.HashSet[string]
            foreach($brokenLink in $brokenLinks) {
                if([ID]::IsNullOrEmpty($brokenLink.SourceFieldID)) { continue }
                $fieldItem = Get-Item -Path "$($Item.Database.Name):\" -ID $brokenLink.SourceFieldID
                if(!$fieldItem) { continue }
                $renderings = & {
                    switch($fieldItem.ID) {
                        "{04BF00DB-F5FB-41F7-8AB7-22408372A981}" {
                            $finalRenderings
                        }
                        default {
                            $sharedRenderings
                        }
                    }
                }
                $brokenRendering = $renderings | Where-Object { $_.Datasource -eq $brokenLink.TargetPath -and !$uniqueIdLookup.Contains($_.UniqueId) } | Select-Object -First 1
                if(!$brokenRendering) { continue }
                $uniqueIdLookup.Add($brokenRendering.UniqueId) > $null
                $brokenRenderingItem = Get-Item -Path "master:" -ID $brokenRendering.ItemId
                $brokenItem = [pscustomobject]@{
                    "ID"=$Item.ID
                    "Icon"=$Item.__Icon
                    "DisplayName"=$Item.DisplayName
                    "ItemPath"=$Item.ItemPath
                    "Version"=$Item.Version
                    "Language"=$Item.Language
                    "__Updated"=$Item.__Updated
                    "__Updated by"=$Item."__Updated by"
                    "Link Field"=$fieldItem.Name
                    "Rendering" = $brokenRenderingItem.Name
                    "Target Path"=$brokenLink.TargetPath
                    "Status Code"="Missing Target Item"
                    "BrokenLink"=$brokenLink
                    "Link Type" = "Internal"
                }

                $brokenItem

            }
        }
    }

    if($linksToCheck.Contains("external")){
        if($IncludeAllVersions){
            $allItems = Get-Item "$($item.Database.Name):" -Version * -Language * -Id $item.Id
        } else {
            $allItems = @(Get-Item "$($item.Database.Name):" -Language * -Id $item.Id)
        }
        foreach($checkedItem in $allItems){
            foreach($field in $checkedItem.Fields) {
                if ($field.Type -eq 'General Link' -and $field.Value -like '*linktype="external"*') { 
                    $found = $field.Value -match '.*url="(.*?)".*'
                    if($found) {
                        $url = $matches[1]
                    }

                    try{ 
                        $response = Invoke-WebRequest -Uri $url -UseBasicParsing -Method head
                    } 
                    catch {
                        $statuscode = $_.Exception.Response.StatusCode.Value__

                        if(!$statuscode) {
                            $statuscode = "Not reachable"
                        }

                        $brokenItem = [pscustomobject]@{
                            "ID"=$checkedItem.ID
                            "Icon"=$checkedItem.__Icon
                            "DisplayName"=$checkedItem.DisplayName
                            "ItemPath"=$checkedItem.ItemPath
                            "Version"=$checkedItem.Version
                            "Language"=$checkedItem.Language
                            "__Updated"=$checkedItem.__Updated
                            "__Updated by"=$checkedItem."__Updated by"
                            "Link Field"=$field.Name
                            "Target Path"=$url
                            "Status Code"=$statuscode
                            "Link Type"="External"
                        }

                        $brokenItem
                    }
                }
            }
        }
    }
}

$items = @($root) + @(($root.Axes.GetDescendants() | Initialize-Item)) | HasBrokenLink -IncludeAllVersions (!$searchVersion)

if($items.Count -eq 0){
    Show-Alert "There are no items found which have broken links in the current language."
} else {
    $props = @{
        Title = "Broken Links Report"
        InfoTitle = "$($items.Count) items with broken links found!"
        InfoDescription = "The report checked for $($linksToCheck -join ' & ') links in $(@('all versions','latest versions')[[byte]($searchVersion='1')]) of items."
        MissingDataMessage = "There are no items found which have broken links in the current language."
        PageSize = 25
        ViewName = "BrokenLinks"
        Property = @(
            "Icon","Status Code", 
            @{Label="Name"; Expression={$_.DisplayName} }, 
            @{Label="Item Path"; Expression={$_.ItemPath} },"Link Field", "Rendering","Target Path",
            "Link Type",
            "Version",
            "Language",
            @{Label="Updated"; Expression={$_.__Updated} },
            @{Label="Updated by"; Expression={$_."__Updated by"} }
        )
    }

    $items | Show-ListView @props
}
Close-Window

3 Answers 3

0

You can use following PS snippet to fetch all the broken links from the database:

function GetBrokenLinks {
param([string]$db)

  $database= [Sitecore.Configuration.Factory]::GetDatabase($db)
  $linkDb = [Sitecore.Globals]::LinkDatabase
  $itemLinks = $linkDb.GetBrokenLinks($database)
  $brokenItems = @()
  foreach($itemlink in $itemLinks){
    $sourceItem = Get-Item -Path $db -ID $itemLink.SourceItemID
    if($sourceItem.Paths.IsContentItem -or $sourceItem.Paths.IsMediaItem){
       $sourceField = $sourceItem.Fields[$itemlink.SourceFieldID]
       $brokenItem = New-Object -TypeName PSObject
       $brokenItem | Add-Member -Name 'ID' -MemberType Noteproperty -Value $sourceItem.ID
       $brokenItem | Add-Member -Name 'Path' -MemberType Noteproperty -Value $sourceItem.Paths.FullPath
       $brokenItem | Add-Member -Name 'Field' -MemberType Noteproperty -Value $sourceField.DisplayName
       $brokenItem | Add-Member -Name 'FieldType' -MemberType Noteproperty -Value $sourceField.Type
       $brokenItem | Add-Member -Name 'BrokenID' -MemberType Noteproperty -Value $itemlink.TargetPath
       $brokenItems +=  $brokenItem 
    }
  }
  $brokenItems | Show-ListView  -Property `
    @{ Label = "Item ID"; Expression = { $_.ID } },
    @{ Label = "Item Path"; Expression = { $_.Paths.FullPath } },
    @{ Label = "Field"; Expression = { $_.Field } },
    @{ Label = "Field Type"; Expression = { $_.FieldType } },
    @{ Label = "Broken ID"; Expression = { $_.BrokenID } }
 }

 GetBrokenLinks "master"

Above function takes database name as a parameter and returns the output in tabular format which can be easily downloaded.

enter image description here

Hope this helps!!!

0

You can use the below script to get broken links using powershell script -

# Set the root item from which you want to start checking for broken links
$rootItem = Get-Item -Path "master:/sitecore/content/YourRootItem"

# Define a function to check if a link is broken
function Check-BrokenLink {
    param (
        [Sitecore.Data.Fields.LinkField]$linkField
    )

    if ($linkField -ne $null) {
        $targetItem = $linkField.TargetItem
        if ($targetItem -eq $null) {
            Write-Output "Broken link found: $($linkField.Item.Paths.FullPath) - $($linkField.Value)"
        }
    }
}

# Recursive function to check all items under the specified root item
function Check-AllItems {
    param (
        [Sitecore.Data.Items.Item]$item
    )

    # Check if the item is null
    if ($item -eq $null) {
        return
    }

    # Check for broken links in the item
    $item.Fields | ForEach-Object {
        if ($_ -is [Sitecore.Data.Fields.LinkField]) {
            Check-BrokenLink -linkField $_
        }
    }

    # Recursively check all child items
    $item.Children | ForEach-Object {
        Check-AllItems -item $_
    }
}

# Start checking for broken links from the root item
Check-AllItems -item $rootItem
0

In your Sitecore instance, you can get the broken link report by the following steps.

  1. In your start menu, go to Reporting Tools => PowerShell Reports => Content Audit => Broken Links

enter image description here

  1. Provide the report root, check link types and version.

enter image description here

It will generate a report for you.

Hope this helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.