@@ -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 )]
0 commit comments