@@ -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 " />
0 commit comments