Skip to content

Commit 82ccd18

Browse files
committed
Refactors spo-add-fields-to-contenttype
1 parent 28621f2 commit 82ccd18

File tree

2 files changed

+150
-85
lines changed

2 files changed

+150
-85
lines changed

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

Lines changed: 136 additions & 77 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)
100-
101-
try {
102-
# Check if the field exists and create
103-
$field = m365 spo field get --webUrl $siteUrl --title $FieldName | ConvertFrom-Json
124+
$Script:Results = [System.Collections.Generic.List[pscustomobject]]::new()
125+
}
104126
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
109-
}
110-
else {
111-
Write-Host "Field '$FieldName' already exists. Skipping creation" -f Green
112-
}
127+
function Ensure-SiteField {
128+
param (
129+
[Parameter(Mandatory = $true)] [string]$WebUrl,
130+
[Parameter(Mandatory = $true)] [System.Collections.Hashtable]$Definition
131+
)
132+
133+
$fieldLookup = m365 spo field list --webUrl $WebUrl --output json | ConvertFrom-Json
134+
$existingField = $fieldLookup | Where-Object { $_.Title -eq $Definition.FieldName -or $_.InternalName -eq $Definition.FieldName -or $_.Id -eq $Definition.FieldId }
135+
136+
if ($existingField) {
137+
$Script:Results.Add([pscustomobject]@{
138+
Action = 'Field'
139+
Target = $Definition.FieldName
140+
Status = 'Skipped'
141+
Message = 'Field already exists'
142+
})
143+
return $existingField
113144
}
114-
catch {
115-
Write-Error "Error in CreateField - $_"
116-
throw
145+
146+
if (-not $PSCmdlet.ShouldProcess($Definition.FieldName, 'Create site column')) {
147+
$Script:Results.Add([pscustomobject]@{
148+
Action = 'Field'
149+
Target = $Definition.FieldName
150+
Status = 'WhatIf'
151+
Message = 'Field creation skipped'
152+
})
153+
return $null
117154
}
118-
}
119155
120-
function CreateAndAddFieldsToCTs {
121-
param ([string[]] $ContentTypes)
156+
$createOutput = m365 spo field add --webUrl $WebUrl --xml $Definition.FieldXml --output json 2>&1
157+
if ($LASTEXITCODE -ne 0) {
158+
$Script:Results.Add([pscustomobject]@{
159+
Action = 'Field'
160+
Target = $Definition.FieldName
161+
Status = 'Failed'
162+
Message = $createOutput
163+
})
164+
return $null
165+
}
122166
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-
}
136-
)
167+
$createdField = $createOutput | ConvertFrom-Json
168+
$Script:Results.Add([pscustomobject]@{
169+
Action = 'Field'
170+
Target = $Definition.FieldName
171+
Status = 'Created'
172+
Message = 'Field created successfully'
173+
})
174+
return $createdField
175+
}
137176
138-
foreach ($fieldToCreate in $fieldsToCreate) {
139-
Write-Host "Creating the field - $($fieldToCreate.FieldName)" -ForegroundColor Yellow
140-
CreateField -FieldName $($fieldToCreate.FieldName) -FieldXML $($fieldToCreate.FieldXML)
141-
}
142-
Write-Host `n `n
143-
#endregion
177+
function Add-FieldToContentType {
178+
param (
179+
[Parameter(Mandatory = $true)] [string]$WebUrl,
180+
[Parameter(Mandatory = $true)] [string]$ContentTypeName,
181+
[Parameter(Mandatory = $true)] [System.Collections.Hashtable]$Definition
182+
)
183+
184+
$contentTypeJson = m365 spo contenttype get --webUrl $WebUrl --name $ContentTypeName --output json 2>&1
185+
if ($LASTEXITCODE -ne 0) {
186+
$Script:Results.Add([pscustomobject]@{
187+
Action = 'ContentType'
188+
Target = $ContentTypeName
189+
Status = 'Failed'
190+
Message = $contentTypeJson
191+
})
192+
return
193+
}
144194
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-
}
195+
$contentType = $contentTypeJson | ConvertFrom-Json
196+
if (-not $contentType.StringId) {
197+
$Script:Results.Add([pscustomobject]@{
198+
Action = 'ContentType'
199+
Target = $ContentTypeName
200+
Status = 'Failed'
201+
Message = 'Content type not found'
202+
})
203+
return
204+
}
161205
162-
}
163-
#endregion
206+
if (-not $PSCmdlet.ShouldProcess($ContentTypeName, "Add field $($Definition.FieldName)")) {
207+
$Script:Results.Add([pscustomobject]@{
208+
Action = 'ContentType'
209+
Target = $ContentTypeName
210+
Status = 'WhatIf'
211+
Message = "Skipped adding field $($Definition.FieldName)"
212+
})
213+
return
164214
}
165-
catch {
166-
Write-Error "Error in CreateAndAddFieldsToCTs - $_"
215+
216+
$setOutput = m365 spo contenttype field set --webUrl $WebUrl --contentTypeId $contentType.StringId --id $Definition.FieldId --output json 2>&1
217+
if ($LASTEXITCODE -ne 0) {
218+
$Script:Results.Add([pscustomobject]@{
219+
Action = 'ContentType'
220+
Target = $ContentTypeName
221+
Status = 'Failed'
222+
Message = $setOutput
223+
})
224+
return
167225
}
168-
}
169226
170-
try {
171-
# SharePoint Online Site Url
172-
$siteUrl = "https://contoso.sharepoint.com/sites/CLIForM365"
227+
$Script:Results.Add([pscustomobject]@{
228+
Action = 'ContentType'
229+
Target = $ContentTypeName
230+
Status = 'Updated'
231+
Message = "Field $($Definition.FieldName) bound successfully"
232+
})
233+
}
173234
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)]

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://github.com/Adam-it.png",
63+
"name": "Adam Wójcik"
5864
}
5965
],
6066
"references": [

0 commit comments

Comments
 (0)