Skip to content

Commit d162c3e

Browse files
authored
Merge pull request #889 from Adam-it/refactors-spo-add-fields-to-contenttype
Refactors spo add fields to contenttype
2 parents 5698ad3 + 7450d86 commit d162c3e

File tree

2 files changed

+148
-82
lines changed

2 files changed

+148
-82
lines changed

scripts/spo-add-fields-to-contenttypes/README.md

Lines changed: 134 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -94,100 +94,159 @@ finally {
9494
# [CLI for Microsoft 365](#tab/cli-m365-ps)
9595

9696
```powershell
97+
# .\Add-FieldsToContentTypes.ps1 -SiteUrl "https://contoso.sharepoint.com/sites/CLIForM365" -ContentTypes "My Review CT","Global User Review CT" -WhatIf
98+
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
99+
param (
100+
[Parameter(Mandatory = $true, HelpMessage = "Absolute URL of the site where the fields and content types exist.")]
101+
[ValidatePattern('^https://')]
102+
[string]$SiteUrl,
103+
104+
[Parameter(Mandatory = $true, HelpMessage = "Content type names to which the fields should be added.")]
105+
[ValidateNotNullOrEmpty()]
106+
[string[]]$ContentTypes,
107+
108+
[Parameter(HelpMessage = "Optional override for the field definitions.")]
109+
[ValidateNotNull()]
110+
[System.Collections.Hashtable[]]$FieldDefinitions
111+
)
112+
113+
begin {
114+
Write-Verbose "Ensuring CLI for Microsoft 365 session."
115+
m365 login --ensure
116+
117+
if (-not $FieldDefinitions) {
118+
$FieldDefinitions = @(
119+
@{ FieldName = 'admin_review'; FieldId = '3eccccb1-9789-40e9-bee8-0e27a2b0ea9f'; FieldXml = "<Field Type='User' DisplayName='Admin Reviewer' Required='false' EnforceUniqueValues='false' Hidden='false' UserSelectionMode='PeopleAndGroups' Group='My Site Columns' ID='{3eccccb1-9789-40e9-bee8-0e27a2b0ea9f}' StaticName='admin_review' Name='admin_review' />" },
120+
@{ FieldName = 'admin_reviewdate'; FieldId = 'bee79067-c92c-4d9c-b80c-63a75a468b16'; FieldXml = "<Field Type='DateTime' DisplayName='Admin Review Date' Required='false' EnforceUniqueValues='false' Hidden='false' Group='My Site Columns' ID='{bee79067-c92c-4d9c-b80c-63a75a468b16}' StaticName='admin_reviewdate' Name='admin_reviewdate' />" }
121+
)
122+
}
97123
98-
function CreateField {
99-
param ([string] $FieldName, [string] $FieldXML)
124+
$Script:Results = [System.Collections.Generic.List[pscustomobject]]::new()
100125
101-
try {
102-
# Check if the field exists and create
103-
$field = m365 spo field get --webUrl $siteUrl --title $FieldName | ConvertFrom-Json
126+
function Ensure-SiteField {
127+
param (
128+
[Parameter(Mandatory = $true)] [string]$WebUrl,
129+
[Parameter(Mandatory = $true)] [System.Collections.Hashtable]$Definition
130+
)
104131
105-
if ($null -eq $field) {
106-
# Add new field based on XML
107-
m365 spo field add --webUrl $siteUrl --xml $FieldXML
108-
Write-Host "Successfully created field '$FieldName'" -ForegroundColor Green
132+
$fieldLookup = m365 spo field list --webUrl $WebUrl --output json | ConvertFrom-Json
133+
$existingField = $fieldLookup | Where-Object { $_.Title -eq $Definition.FieldName -or $_.InternalName -eq $Definition.FieldName -or $_.Id -eq $Definition.FieldId }
134+
135+
if ($existingField) {
136+
$Script:Results.Add([pscustomobject]@{
137+
Action = 'Field'
138+
Target = $Definition.FieldName
139+
Status = 'Skipped'
140+
Message = 'Field already exists'
141+
})
142+
return $existingField
109143
}
110-
else {
111-
Write-Host "Field '$FieldName' already exists. Skipping creation" -f Green
144+
145+
if (-not $PSCmdlet.ShouldProcess($Definition.FieldName, 'Create site column')) {
146+
$Script:Results.Add([pscustomobject]@{
147+
Action = 'Field'
148+
Target = $Definition.FieldName
149+
Status = 'WhatIf'
150+
Message = 'Field creation skipped'
151+
})
152+
return $null
112153
}
113-
}
114-
catch {
115-
Write-Error "Error in CreateField - $_"
116-
throw
117-
}
118-
}
119154
120-
function CreateAndAddFieldsToCTs {
121-
param ([string[]] $ContentTypes)
155+
$createOutput = m365 spo field add --webUrl $WebUrl --xml $Definition.FieldXml --output json 2>&1
156+
if ($LASTEXITCODE -ne 0) {
157+
$Script:Results.Add([pscustomobject]@{
158+
Action = 'Field'
159+
Target = $Definition.FieldName
160+
Status = 'Failed'
161+
Message = $createOutput
162+
})
163+
return $null
164+
}
122165
123-
try {
124-
#region Create SharePoint Site Columns
125-
$fieldsToCreate = @(
126-
@{
127-
FieldName = "admin_review"
128-
FieldID = "3eccccb1-9789-40e9-bee8-0e27a2b0ea9f"
129-
FieldXML = "<Field Type='User' DisplayName='Admin Reviewer' Required='false' EnforceUniqueValues='false' Hidden='false' UserSelectionMode='PeopleAndGroups' Group='My Site Columns' ID='{3eccccb1-9789-40e9-bee8-0e27a2b0ea9f}' StaticName='admin_review' Name='admin_review'></Field>"
130-
},
131-
@{
132-
FieldName = "admin_reviewdate"
133-
FieldID = "bee79067-c92c-4d9c-b80c-63a75a468b16"
134-
FieldXML = "<Field Type='DateTime' DisplayName='Admin Review Date' Required='false' EnforceUniqueValues='false' Hidden='false' Group='My Site Columns' ID='{bee79067-c92c-4d9c-b80c-63a75a468b16}' StaticName='admin_reviewdate' Name='admin_reviewdate'></Field>"
135-
}
166+
$createdField = $createOutput | ConvertFrom-Json
167+
$Script:Results.Add([pscustomobject]@{
168+
Action = 'Field'
169+
Target = $Definition.FieldName
170+
Status = 'Created'
171+
Message = 'Field created successfully'
172+
})
173+
return $createdField
174+
}
175+
176+
function Add-FieldToContentType {
177+
param (
178+
[Parameter(Mandatory = $true)] [string]$WebUrl,
179+
[Parameter(Mandatory = $true)] [string]$ContentTypeName,
180+
[Parameter(Mandatory = $true)] [System.Collections.Hashtable]$Definition
136181
)
137182
138-
foreach ($fieldToCreate in $fieldsToCreate) {
139-
Write-Host "Creating the field - $($fieldToCreate.FieldName)" -ForegroundColor Yellow
140-
CreateField -FieldName $($fieldToCreate.FieldName) -FieldXML $($fieldToCreate.FieldXML)
183+
$contentTypeJson = m365 spo contenttype get --webUrl $WebUrl --name $ContentTypeName --output json 2>&1
184+
if ($LASTEXITCODE -ne 0) {
185+
$Script:Results.Add([pscustomobject]@{
186+
Action = 'ContentType'
187+
Target = $ContentTypeName
188+
Status = 'Failed'
189+
Message = $contentTypeJson
190+
})
191+
return
141192
}
142-
Write-Host `n `n
143-
#endregion
144193
145-
#region Add Site Columns to Content Types
146-
foreach ($contentType in $ContentTypes) {
147-
$contentTypeObj = m365 spo contenttype get --webUrl $siteUrl --name $contentType | ConvertFrom-Json
148-
if ($contentTypeObj.StringId) {
149-
foreach ($fieldToCreate in $fieldsToCreate) {
150-
Write-Host "Adding field - $($fieldToCreate.FieldName) to CT $contentType" -ForegroundColor Yellow
151-
152-
m365 spo contenttype field set --webUrl $siteUrl --contentTypeId $contentTypeObj.StringId --id $fieldToCreate.FieldID
153-
Write-Host "Successfully added fields to CT $contentType" -ForegroundColor Green
154-
Write-Host `n
155-
}
156-
}
157-
else {
158-
Write-Host "Content Type not found: $contentType" -ForegroundColor Green
159-
Write-Host `n
160-
}
194+
$contentType = $contentTypeJson | ConvertFrom-Json
195+
if (-not $contentType.StringId) {
196+
$Script:Results.Add([pscustomobject]@{
197+
Action = 'ContentType'
198+
Target = $ContentTypeName
199+
Status = 'Failed'
200+
Message = 'Content type not found'
201+
})
202+
return
203+
}
161204
205+
if (-not $PSCmdlet.ShouldProcess($ContentTypeName, "Add field $($Definition.FieldName)")) {
206+
$Script:Results.Add([pscustomobject]@{
207+
Action = 'ContentType'
208+
Target = $ContentTypeName
209+
Status = 'WhatIf'
210+
Message = "Skipped adding field $($Definition.FieldName)"
211+
})
212+
return
162213
}
163-
#endregion
164-
}
165-
catch {
166-
Write-Error "Error in CreateAndAddFieldsToCTs - $_"
214+
215+
$setOutput = m365 spo contenttype field set --webUrl $WebUrl --contentTypeId $contentType.StringId --id $Definition.FieldId --output json 2>&1
216+
if ($LASTEXITCODE -ne 0) {
217+
$Script:Results.Add([pscustomobject]@{
218+
Action = 'ContentType'
219+
Target = $ContentTypeName
220+
Status = 'Failed'
221+
Message = $setOutput
222+
})
223+
return
224+
}
225+
226+
$Script:Results.Add([pscustomobject]@{
227+
Action = 'ContentType'
228+
Target = $ContentTypeName
229+
Status = 'Updated'
230+
Message = "Field $($Definition.FieldName) bound successfully"
231+
})
167232
}
168233
}
169234
170-
try {
171-
# SharePoint Online Site Url
172-
$siteUrl = "https://contoso.sharepoint.com/sites/CLIForM365"
173-
174-
# Get Credentials to connect
175-
$m365Status = m365 status
176-
if ($m365Status -match "Logged Out") {
177-
m365 login
235+
process {
236+
foreach ($definition in $FieldDefinitions) {
237+
Ensure-SiteField -WebUrl $SiteUrl -Definition $definition
178238
}
179239
180-
# Create and add fields to SharePoint content types
181-
CreateAndAddFieldsToCTs -ContentTypes @("My Review CT", "Global User Review CT")
182-
}
183-
catch {
184-
Write-Error "Something wrong: " $_
185-
}
186-
finally {
187-
# Disconnect SharePoint online connection
188-
m365 logout
240+
foreach ($contentType in $ContentTypes) {
241+
foreach ($definition in $FieldDefinitions) {
242+
Add-FieldToContentType -WebUrl $SiteUrl -ContentTypeName $contentType -Definition $definition
243+
}
244+
}
189245
}
190246
247+
end {
248+
$Script:Results | Sort-Object Action, Target | Format-Table -AutoSize
249+
}
191250
```
192251

193252
[!INCLUDE [More about CLI for Microsoft 365](../../docfx/includes/MORE-CLIM365.md)]
@@ -200,6 +259,7 @@ finally {
200259
| ------------------- |
201260
| Ahamed Fazil Buhari |
202261
| [Ganesh Sanap](https://ganeshsanapblogs.wordpress.com/about) |
262+
| Adam Wójcik |
203263

204264
[!INCLUDE [DISCLAIMER](../../docfx/includes/DISCLAIMER.md)]
205265
<img src="https://m365-visitor-stats.azurewebsites.net/script-samples/scripts/spo-add-fields-to-contenttypes" aria-hidden="true" />

scripts/spo-add-fields-to-contenttypes/assets/sample.json

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,29 @@
99
"Script to create site columns and add them to content types"
1010
],
1111
"creationDateTime": "2023-09-06",
12-
"updateDateTime": "2023-10-24",
13-
"products": ["SharePoint"],
12+
"updateDateTime": "2025-11-12",
13+
"products": [
14+
"SharePoint"
15+
],
1416
"metadata": [
1517
{
1618
"key": "PNP-POWERSHELL",
1719
"value": "2.2.0"
1820
},
1921
{
2022
"key": "CLI-FOR-MICROSOFT365",
21-
"value": "7.0.0"
23+
"value": "11.0.0"
2224
}
2325
],
24-
"categories": ["Provision"],
26+
"categories": [
27+
"Provision"
28+
],
2529
"tags": [
2630
"Connect-PnPOnline",
2731
"Get-PnPField",
2832
"Add-PnPFieldFromXml",
2933
"Add-PnPFieldToContentType",
30-
"m365 status",
31-
"m365 login",
32-
"m365 logout",
33-
"m365 spo field get",
34+
"m365 spo field list",
3435
"m365 spo field add",
3536
"m365 spo contenttype get",
3637
"m365 spo contenttype field set"
@@ -55,6 +56,11 @@
5556
"company": "",
5657
"pictureUrl": "https://github.com/ahamedfazil.png",
5758
"name": "Ahamed Fazil Buhari"
59+
},
60+
{
61+
"gitHubAccount": "Adam-it",
62+
"pictureUrl": "https://avatars.githubusercontent.com/u/58668583?v=4",
63+
"name": "Adam Wójcik"
5864
}
5965
],
6066
"references": [

0 commit comments

Comments
 (0)