Build-PorteoSite.ps1

<#
    .Synopsis
        Build-PorteoSite -TenantUrl "https://mysite-admin.sharepoint.com" -Credentials (Get-Credential) `
                     -SiteName "Site1" -Title "The Site" -Owner "name@mysite.onmicrosoft.com" -Type "TeamSite" `
                     -SrcConnection $srcConnection

    .Description
        This function builds a *Porteo* site. A *Porteo* site is a ***SimpleSharepoint*** base site, based on
        either a **TeamSite** or **ComunicationSite** template type.

        If the function is specified ***without*** the `-SrcConnection` argument a default site gets built
        with the following ***SimpleSharepoint*** lists:

        * Site Assets (SiteAssets)
        * Documents (Shared Documents)
        * Journal
        * Requests
        * SiteCollectionList
        * Links
        * SubsiteLists

        At this point, you would create this base site, then add contents to the above lists. You may
        also add some other lists, add to the _SiteAssets_ and any other *Pages* with content and
        branding. This created and modified site will be used to provision other sites on other
        tenants.

        To provision a new site, you now use the `-SrcConnection` argument to specify it as a source and
        use the `-TenantUrl` and `-Credentials` arguments to create the site on the target tenant. See
        the series of Examples below to see the process and sequence of operations.

        If the `-SrcConnection` argument **is** specified, the
        specified template site gets built as a base, i.e. TeamSite or CommunicationSite.
        Then the target site is provisioned from the site associated with the src connection.

        The site Pages are copied as well as the Pages' contents. Furthermore, the *Porteo* standard lists,
        which are listed above, have their structure and contents copied.

        The examples provide in sequence the process by which you may create a base *Porteo* site, modify it,
        and then use the result to provision another site.

        ***Note***: If the tenant site already exists, this function will return with an Error. You must either
        delete the target site first, or give use a different name.
    .Parameter TenantUrl
        This parameter holds the tenant adminstrative site url, e.g. https://mysite-admin.sharepoint.com
    .Parameter Credentials
        This parameter holds the credentials for the tenant adminstrator.
    .Parameter SiteName
        This parameter holds the name of the site to be created.
    .Parameter Title
        This parameter holds the title for the site to be created.
    .Parameter Type
        This paramter holds the type of site to be created, e.g. TeamSite or CommunicationSite.
    .Parameter Owner
        This paramter holds the owner of the new site, which is an email address.
    .Parameter SrcConnection
        This paramter holds the source to copy the template from. If it is not specified, the base *Porteo*
        site is built.

    .Example
    $creds = Get-Credential

    Gets the Credential for the subsequent examples.

    .Example
    $siteUrl = Build-PorteoSite -TenantUrl "https://mysite-admin.sharepoint.com" -Credentials $creds `
                 -SiteName "SiteTemplate" -Title "The Site Template" -Type "TeamSite" `
                 -Owner "name@site.onmicrosoft.com"

    Builds the first site to use as a template. Now, modify this site adding to lists, pages, documents.
    .Example
    $srcConn = Connect-PnPOnline -Url $siteUrl -Credentials $creds

    Gets the connection for the template site from which you will copy.
    .Example
    $dstCreds = Get-Credential

    Gets the tenant credentials to to build the new site.
    .Example
    $newSiteUrl = Build-PorteoSite -TenantUrl "https://client-admin.sharepoint.com" -Credentials $dstCreds `
                 -SiteName "MySite" -Title "My Great Site" -Type "TeamSite" `
                 -Owner "admin@company.com" -SrcConnection $srcConn

    Builds the new site "MySite" on the specified tenant and provisions it from the source site.
#>


function Build-PorteoSite {
    param(
        [parameter(Mandatory=$true)]
        [string]
        $tenantUrl,
        [parameter(Mandatory=$true)]
        [Object]
        $credentials,
        [parameter(Mandatory=$true,HelpMessage="No spaces")]
        [string]
        $siteName,
        [parameter(Mandatory=$true)]
        [string]
        $title,
        [parameter(Mandatory=$true)]
        [string]
        $owner,
        [parameter(Mandatory=$false,HelpMessage="Default is TeamSite")]
        [string]
        $type = "TeamSite",
        [parameter(Mandatory=$false)]
        [Object]
        $srcConnection
    )

    $connection = Connect-PnPOnline -Url $tenantUrl -Credentials $credentials -ReturnConnection
    $baseUrl = $tenantUrl.Replace("-admin", "")
    $siteurl = "$baseUrl/sites/$siteName"
    $site = Get-PnPTenantSite -Url $siteUrl  -ErrorAction SilentlyContinue
    if (-not $site)
    {
        $site = Add-SSPSite -Owner $owner -Url $siteUrl -Title $title -SiteName $siteName -Type $type -Connection $connection
        $siteUrl = $site

        Write-Host $siteUrl

        $destConn = Connect-PnPOnline -Url $siteUrl -Credentials $credentials -ReturnConnection
        $ignore = Set-PnpSite -NoScriptSite $false -Connection $destConn

        $ignore = Add-PorteoSiteDesigns -Type $type -Connection $connection

        if ($srcConnection)
        {
            $ignore = Copy-SSPSite -SrcConnection $srcConnection -DestConnection $destConn -Handlers $handlers
        } else {
            $ignore = New-PnPList -Title "Site Assets" -Template DocumentLibrary -OnQuickLaunch -Connection $destConn
            $ignore = Invoke-SSPSiteDesigns -SiteDesigns ("DefaultDesign", "AddJournal", "AddLinks", "AddRequests", "AddSiteLists") -Connection $destConn
        }
        return $siteUrl
    } else {
        Write-Host "Site $siteUrl Exists"
        return $siteUrl
    }
}


$handlers = @(
    "AuditSettings",
    "ComposedLook",
    "CustomActions",
    "ExtensibilityProviders",
    # "Features",
    "Fields",
    "Files",
    "Lists",
    "Pages",
    "Publishing",
    "RegionalSettings",
    "SearchSettings",
    "SitePolicy",
    "SupportedUILanguages",
    "TermGroups",
    "Workflows",
    "SiteSecurity",
    # "ContentTypes",
    "PropertyBagEntries",
    "PageContents",
    "WebSettings",
    "Navigation", # This seems to duplicate the naviagion sidebar.
    "ImageRenditions",
    # "ApplicationLifecycleManagement",
    # "Tenant",
    "WebApiPermissions",
    "SiteHeader",
    "SiteFooter",
    "Theme",
    "SiteSettings",
    "SyntexModels"
)