Thursday, 15 July 2010

Replacing the Page Contact on all pages for all sites in a site collection using PowerShell

Here is the scenario: A page author at your company has decided to leave and there are a large number of publishing pages in SharePoint associated with them as a Page Contact. Your options are to a) manually replace the Page Contact on each page in each site with the person now responsible for managing publishing pages in the site collection, b) pay the old page author more money and persuade them to stay to avoid the extra management costs, or c) use this PowerShell script below to walk through each page in each site of the site collection and automatically change the Page Contact from the old page author to the new one:

#Set up default variables
$webSiteUrl = "http://portal"

#Add SharePoint assemblies
Add-Type -AssemblyName "Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
Add-Type -AssemblyName "Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

#Get site and web objects
$site = Get-SPSite $webSiteUrl

#Set original and new Page Contact AD accounts
$originalContact = "DOMAIN\oldpageauthor"
$newContact = "DOMAIN\newpageauthor"

#Walk through each Publishing Web and change the page contact on every page
#where the original contact equals the originalContact variable set above
$site | Get-SPWeb -limit all | ForEach-Object {
    #Check to see if site is a publishing site
    if ([Microsoft.SharePoint.Publishing.PublishingWeb]::IsPublishingWeb($_)) {
        write-host "Reviewing pages in"$_.Title"site...."
        #Get the Publishing Web and pages within it
        $publishingWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($_)
        $publishingPages = $publishingWeb.GetPublishingPages()
        foreach ($publishingPage in $publishingPages)
        {
            $originalUser = $_.AllUsers[$originalContact]
            #Check if the new user exists in the web - if not, create them
            try
            {
                $newUser = $_.AllUsers[$newContact]
            }
            catch
            {
                $_.AllUsers.Add($newContact, "", "", "")
                $_.Update()
                $newUser = $_.AllUsers[$newContact]
            }
            #Check to ensure the page isn't checked out
            if ($publishingPage.ListItem.File.CheckOutStatus -eq "None")
            {
                #Check to ensure a Page Contact has been set on the page
                if ($publishingPage.Contact -ne $null)
                {
                    #If the Page Contact is set to the original user,
                    #change to the new user and check in the page
                    if ($publishingPage.Contact.ToString() -eq $originalUser.ToString())
                    {
                        $publishingPage.ListItem.File.CheckOut()
                        $publishingPage.Contact = $newUser
                        $publishingPage.Update()
                        $publishingPage.ListItem.File.CheckIn("Contact name changed", [Microsoft.SharePoint.SPCheckinType]::MajorCheckIn)
                        write-host "Page contact for"$publishingPage.Title"changed to"$publishingPage.Contact.LoginName
                    }
                    else
                    {
                        #Notify administrator that the Page Contact is someone other than the originalContact specified in this script
                        write-host "Page contact for"$publishingPage.Title"is"$publishingPage.Contact.LoginName"and shall not be modified"
                    }
                }
                else
                {
                    #Notify administrator that the Page Contact has not been set on this page
                    write-host "Page contact for"$publishingPage.Title"has not been set and shall not be modified"
                }
            }
            else
            {
                #Notify administrator that the page is checked out and cannot be modified
                write-host "Page"$publishingPage.Title"is currently checked out to"$publishingPage.ListItem.File.CheckedOutBy"and cannot be modified"
            }
        }
    }
    else
    {
        #Notify administrator that the site is not a publishing site
        write-host $_.Title"is not a publishing site"
    }
}

#Dispose of Site object
$site.Dispose()

In summary, this script does the following:

- Connects to a site collection and walks through each site
- Checks to see if the site is a publishing site before making any changes (if not it moves on to the next site)
- Checks each publishing page in the site
- If a page is already checked out then it doesn't make any changes to the page
- If a Page Contact is set to someone else other than the old author you specified then it doesn't make any changes
- If the Page Contact is set to the old author then it will check out the page, change the contact to the new author specified and check the page back in again
- Reports all activities to the console whilst reviewing the sites - see below for an example log:

Reviewing pages in PAC Portal site....
Page contact for Home has not been set and shall not be modified
Page Query Web Parts test is currently checked out to DOMAIN\spadmin and cannot be modified
Reviewing pages in Publishing Site site....
Page contact for Home changed to DOMAIN\newpageauthor
Page contact for Test is DOMAIN\phil.childs and shall not be modifed
Reviewing pages in Search site....
Page contact for Search Center has not been set and shall not be modified
Page contact for Advanced search has not been set and shall not be modified
Page contact for People Search has not been set and shall not be modified
Page contact for Search Results has not been set and shall not be modified
Page contact for People Results has not been set and shall not be modified
Team is not a publishing site

Note: If approval is required on pages in your publishing sites, then you will need to go through manually and approve any pages changed by this script to publish them (of course, this can be done in PowerShell, but I think I’ll leave that to another time!)

2 comments: