public AddToken ( OfficeDevPnP.Core.Framework.Provisioning.ObjectHandlers.TokenDefinitions.TokenDefinition tokenDefinition ) : void | ||
tokenDefinition | OfficeDevPnP.Core.Framework.Provisioning.ObjectHandlers.TokenDefinitions.TokenDefinition | |
return | void |
public TokenParser AddExtendedTokens(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { var context = web.Context as ClientContext; foreach (var provider in template.Providers) { if (provider.Enabled) { try { if (!string.IsNullOrEmpty(provider.Configuration)) { provider.Configuration = parser.ParseString(provider.Configuration); } scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ExtensibilityProviders_Calling_tokenprovider_extensibility_callout__0_, provider.Assembly); var _providedTokens = _extManager.ExecuteTokenProviderCallOut(context, provider, template); if (_providedTokens != null) { foreach (var token in _providedTokens) { parser.AddToken(token); } } } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ExtensibilityProviders_tokenprovider_callout_failed___0_____1_, ex.Message, ex.StackTrace); throw; } } } return parser; } }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { if (template.Lists.Any()) { var rootWeb = (web.Context as ClientContext).Site.RootWeb; web.EnsureProperties(w => w.ServerRelativeUrl); web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl)); web.Context.ExecuteQueryRetry(); var existingLists = web.Lists.AsEnumerable().Select(existingList => existingList.RootFolder.ServerRelativeUrl).ToList(); var serverRelativeUrl = web.ServerRelativeUrl; var processedLists = new List<ListInfo>(); #region Lists foreach (var templateList in template.Lists) { // Check for the presence of the references content types and throw an exception if not present or in template if (templateList.ContentTypesEnabled) { var existingCts = web.Context.LoadQuery(web.AvailableContentTypes); web.Context.ExecuteQueryRetry(); foreach (var ct in templateList.ContentTypeBindings) { var found = template.ContentTypes.Any(t => t.Id.ToUpperInvariant() == ct.ContentTypeId.ToUpperInvariant()); if (found == false) { found = existingCts.Any(t => t.StringId.ToUpperInvariant() == ct.ContentTypeId.ToUpperInvariant()); } if (!found) { scope.LogError("Referenced content type {0} not available in site or in template", ct.ContentTypeId); throw new Exception(string.Format("Referenced content type {0} not available in site or in template", ct.ContentTypeId)); } } } var index = existingLists.FindIndex(x => x.Equals(UrlUtility.Combine(serverRelativeUrl, templateList.Url), StringComparison.OrdinalIgnoreCase)); if (index == -1) { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_list__0_, templateList.Title); var returnTuple = CreateList(web, templateList, parser, scope); var createdList = returnTuple.Item1; parser = returnTuple.Item2; processedLists.Add(new ListInfo { SiteList = createdList, TemplateList = templateList }); parser.AddToken(new ListIdToken(web, templateList.Title, createdList.Id)); parser.AddToken(new ListUrlToken(web, templateList.Title, createdList.RootFolder.ServerRelativeUrl.Substring(web.ServerRelativeUrl.Length + 1))); } catch (Exception ex) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_list__0__failed___1_____2_, templateList.Title, ex.Message, ex.StackTrace); throw; } } else { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_list__0_, templateList.Title); var existingList = web.Lists[index]; var returnTuple = UpdateList(web, existingList, templateList, parser, scope); var updatedList = returnTuple.Item1; parser = returnTuple.Item2; if (updatedList != null) { processedLists.Add(new ListInfo { SiteList = updatedList, TemplateList = templateList }); } } catch (Exception ex) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_list__0__failed___1_____2_, templateList.Title, ex.Message, ex.StackTrace); throw; } } } #endregion #region FieldRefs foreach (var listInfo in processedLists) { if (listInfo.TemplateList.FieldRefs.Any()) { foreach (var fieldRef in listInfo.TemplateList.FieldRefs) { var field = rootWeb.GetFieldById<Field>(fieldRef.Id); if (field != null) { if (!listInfo.SiteList.FieldExistsById(fieldRef.Id)) { CreateFieldRef(listInfo, field, fieldRef); } else { UpdateFieldRef(listInfo.SiteList, field.Id, fieldRef); } } } listInfo.SiteList.Update(); web.Context.ExecuteQueryRetry(); } } #endregion #region Fields foreach (var listInfo in processedLists) { if (listInfo.TemplateList.Fields.Any()) { foreach (var field in listInfo.TemplateList.Fields) { var fieldElement = XElement.Parse(parser.ParseString(field.SchemaXml, "~sitecollection", "~site")); if (fieldElement.Attribute("ID") == null) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field_schema_has_no_ID_attribute___0_, field.SchemaXml); throw new Exception(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field_schema_has_no_ID_attribute___0_, field.SchemaXml)); } var id = fieldElement.Attribute("ID").Value; Guid fieldGuid; if (!Guid.TryParse(id, out fieldGuid)) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_ID_for_field_is_not_a_valid_Guid___0_, field.SchemaXml); throw new Exception(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_ID_for_field_is_not_a_valid_Guid___0_, id)); } else { var fieldFromList = listInfo.SiteList.GetFieldById<Field>(fieldGuid); if (fieldFromList == null) { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_field__0_, fieldGuid); CreateField(fieldElement, listInfo, parser); } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_field__0__failed___1_____2_, fieldGuid, ex.Message, ex.StackTrace); throw; } } else { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_field__0_, fieldGuid); UpdateField(web, listInfo, fieldGuid, fieldElement, fieldFromList, scope, parser); } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_field__0__failed___1_____2_, fieldGuid, ex.Message, ex.StackTrace); throw; } } } } } listInfo.SiteList.Update(); web.Context.ExecuteQueryRetry(); } #endregion #region Default Field Values foreach (var listInfo in processedLists) { if (listInfo.TemplateList.FieldDefaults.Any()) { foreach (var fieldDefault in listInfo.TemplateList.FieldDefaults) { var field = listInfo.SiteList.Fields.GetByInternalNameOrTitle(fieldDefault.Key); field.DefaultValue = fieldDefault.Value; field.Update(); web.Context.ExecuteQueryRetry(); } } } #endregion #region Views foreach (var listInfo in processedLists) { var list = listInfo.TemplateList; var createdList = listInfo.SiteList; if (list.Views.Any() && list.RemoveExistingViews) { while (createdList.Views.Any()) { createdList.Views[0].DeleteObject(); } web.Context.ExecuteQueryRetry(); } var existingViews = createdList.Views; web.Context.Load(existingViews, vs => vs.Include(v => v.Title, v => v.Id)); web.Context.ExecuteQueryRetry(); foreach (var view in list.Views) { CreateView(web, view, existingViews, createdList, scope); } //// Removing existing views set the OnQuickLaunch option to false and need to be re-set. //if (list.OnQuickLaunch && list.RemoveExistingViews && list.Views.Count > 0) //{ // createdList.RefreshLoad(); // web.Context.ExecuteQueryRetry(); // createdList.OnQuickLaunch = list.OnQuickLaunch; // createdList.Update(); // web.Context.ExecuteQueryRetry(); //} } #endregion // If an existing view is updated, and the list is to be listed on the QuickLaunch, it is removed because the existing view will be deleted and recreated from scratch. foreach (var listInfo in processedLists) { listInfo.SiteList.OnQuickLaunch = listInfo.TemplateList.OnQuickLaunch; listInfo.SiteList.Update(); } web.Context.ExecuteQueryRetry(); } } return parser; }
private static void UpdateContentType(Web web, Microsoft.SharePoint.Client.ContentType existingContentType, ContentType templateContentType, TokenParser parser, PnPMonitoredScope scope) { var isDirty = false; if (existingContentType.Hidden != templateContentType.Hidden) { scope.LogPropertyUpdate("Hidden"); existingContentType.Hidden = templateContentType.Hidden; isDirty = true; } if (existingContentType.ReadOnly != templateContentType.ReadOnly) { scope.LogPropertyUpdate("ReadOnly"); existingContentType.ReadOnly = templateContentType.ReadOnly; isDirty = true; } if (existingContentType.Sealed != templateContentType.Sealed) { scope.LogPropertyUpdate("Sealed"); existingContentType.Sealed = templateContentType.Sealed; isDirty = true; } if (templateContentType.Description != null && existingContentType.Description != parser.ParseString(templateContentType.Description)) { scope.LogPropertyUpdate("Description"); existingContentType.Description = parser.ParseString(templateContentType.Description); isDirty = true; } if (templateContentType.DocumentTemplate != null && existingContentType.DocumentTemplate != parser.ParseString(templateContentType.DocumentTemplate)) { scope.LogPropertyUpdate("DocumentTemplate"); existingContentType.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate); isDirty = true; } if (existingContentType.Name != parser.ParseString(templateContentType.Name)) { scope.LogPropertyUpdate("Name"); existingContentType.Name = parser.ParseString(templateContentType.Name); isDirty = true; // CT is being renamed, add an extra token to the tokenparser parser.AddToken(new ContentTypeIdToken(web, existingContentType.Name, existingContentType.StringId)); } if (templateContentType.Group != null && existingContentType.Group != parser.ParseString(templateContentType.Group)) { scope.LogPropertyUpdate("Group"); existingContentType.Group = parser.ParseString(templateContentType.Group); isDirty = true; } if (templateContentType.DisplayFormUrl != null && existingContentType.DisplayFormUrl != parser.ParseString(templateContentType.DisplayFormUrl)) { scope.LogPropertyUpdate("DisplayFormUrl"); existingContentType.DisplayFormUrl = parser.ParseString(templateContentType.DisplayFormUrl); isDirty = true; } if (templateContentType.EditFormUrl != null && existingContentType.EditFormUrl != parser.ParseString(templateContentType.EditFormUrl)) { scope.LogPropertyUpdate("EditFormUrl"); existingContentType.EditFormUrl = parser.ParseString(templateContentType.EditFormUrl); isDirty = true; } if (templateContentType.NewFormUrl != null && existingContentType.NewFormUrl != parser.ParseString(templateContentType.NewFormUrl)) { scope.LogPropertyUpdate("NewFormUrl"); existingContentType.NewFormUrl = parser.ParseString(templateContentType.NewFormUrl); isDirty = true; } #if !CLIENTSDKV15 if (templateContentType.Name.ContainsResourceToken()) { existingContentType.NameResource.SetUserResourceValue(templateContentType.Name, parser); isDirty = true; } if (templateContentType.Description.ContainsResourceToken()) { existingContentType.DescriptionResource.SetUserResourceValue(templateContentType.Description, parser); isDirty = true; } #endif if (isDirty) { existingContentType.Update(true); web.Context.ExecuteQueryRetry(); } // Delta handling existingContentType.EnsureProperty(c => c.FieldLinks); List<Guid> targetIds = existingContentType.FieldLinks.AsEnumerable().Select(c1 => c1.Id).ToList(); List<Guid> sourceIds = templateContentType.FieldRefs.Select(c1 => c1.Id).ToList(); var fieldsNotPresentInTarget = sourceIds.Except(targetIds).ToArray(); if (fieldsNotPresentInTarget.Any()) { foreach (var fieldId in fieldsNotPresentInTarget) { var fieldRef = templateContentType.FieldRefs.Find(fr => fr.Id == fieldId); var field = web.Fields.GetById(fieldId); scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ContentTypes_Adding_field__0__to_content_type, fieldId); web.AddFieldToContentType(existingContentType, field, fieldRef.Required, fieldRef.Hidden); } } isDirty = false; foreach (var fieldId in targetIds.Intersect(sourceIds)) { var fieldLink = existingContentType.FieldLinks.FirstOrDefault(fl => fl.Id == fieldId); var fieldRef = templateContentType.FieldRefs.Find(fr => fr.Id == fieldId); if (fieldRef != null) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ContentTypes_Field__0__exists_in_content_type, fieldId); if (fieldLink.Required != fieldRef.Required) { scope.LogPropertyUpdate("Required"); fieldLink.Required = fieldRef.Required; isDirty = true; } if (fieldLink.Hidden != fieldRef.Hidden) { scope.LogPropertyUpdate("Hidden"); fieldLink.Hidden = fieldRef.Hidden; isDirty = true; } } } // The new CT is a DocumentSet, and the target should be, as well if (templateContentType.DocumentSetTemplate != null) { if (!Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.IsChildOfDocumentSetContentType(web.Context, existingContentType).Value) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ContentTypes_InvalidDocumentSet_Update_Request, existingContentType.Id, existingContentType.Name); } else { Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate templateToUpdate = Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.GetDocumentSetTemplate(web.Context, existingContentType); // TODO: Implement Delta Handling scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_DocumentSet_DeltaHandling_OnHold, existingContentType.Id, existingContentType.Name); } } if (isDirty) { existingContentType.Update(true); web.Context.ExecuteQueryRetry(); } }
public void RegexSpecialCharactersTests() { using (var ctx = TestCommon.CreateClientContext()) { ctx.Load(ctx.Web, w => w.Id, w => w.ServerRelativeUrl, w => w.Title, w => w.AssociatedOwnerGroup.Title, w => w.AssociatedMemberGroup.Title, w => w.AssociatedVisitorGroup.Title); ctx.Load(ctx.Site, s => s.ServerRelativeUrl); ctx.ExecuteQueryRetry(); var currentUser = ctx.Web.EnsureProperty(w => w.CurrentUser); ProvisioningTemplate template = new ProvisioningTemplate(); template.Parameters.Add("test(T)", "test"); var parser = new TokenParser(ctx.Web, template); var web = ctx.Web; var contentTypeName = "Test CT (TC) [TC].$"; var contentTypeId = "0x010801006439AECCDEAE4db2A422A3A04C79CC83"; var listGuid = Guid.NewGuid(); var listTitle = @"List (\,*+?|{[()^$.#"; var listUrl = "Lists/TestList"; var webPartTitle = @"Webpart (\*+?|{[()^$.#"; var webPartId = Guid.NewGuid(); var termSetName = @"Test TermSet (\*+?{[()^$.#"; var termGroupName = @"Group Name (\*+?{[()^$.#"; var termStoreName = @"Test TermStore (\*+?{[()^$.#"; var termSetId = Guid.NewGuid(); var termStoreId = Guid.NewGuid(); // Use fake data parser.AddToken(new ContentTypeIdToken(web, contentTypeName, contentTypeId)); parser.AddToken(new ListIdToken(web, listTitle, listGuid)); parser.AddToken(new ListUrlToken(web, listTitle, listUrl)); parser.AddToken(new WebPartIdToken(web, webPartTitle, webPartId)); parser.AddToken(new TermSetIdToken(web, termGroupName, termSetName, termSetId)); parser.AddToken(new TermStoreIdToken(web, termStoreName, termStoreId)); var resolvedContentTypeId = parser.ParseString($"{{contenttypeid:{contentTypeName}}}"); var resolvedListId = parser.ParseString($"{{listid:{listTitle}}}"); var resolvedListUrl = parser.ParseString($"{{listurl:{listTitle}}}"); var parameterExpectedResult = $"abc{"test"}/test"; var parameterTest1 = parser.ParseString("abc{parameter:TEST(T)}/test"); var parameterTest2 = parser.ParseString("abc{$test(T)}/test"); var resolvedWebpartId = parser.ParseString($"{{webpartid:{webPartTitle}}}"); var resolvedTermSetId = parser.ParseString($"{{termsetid:{termGroupName}:{termSetName}}}"); var resolvedTermStoreId = parser.ParseString($"{{termstoreid:{termStoreName}}}"); Assert.IsTrue(contentTypeId == resolvedContentTypeId); Assert.IsTrue(listUrl == resolvedListUrl); Guid outGuid; Assert.IsTrue(Guid.TryParse(resolvedListId, out outGuid)); Assert.IsTrue(parameterTest1 == parameterExpectedResult); Assert.IsTrue(parameterTest2 == parameterExpectedResult); Assert.IsTrue(Guid.TryParse(resolvedWebpartId, out outGuid)); Assert.IsTrue(Guid.TryParse(resolvedTermSetId, out outGuid)); Assert.IsTrue(Guid.TryParse(resolvedTermStoreId, out outGuid)); } }
private static Microsoft.SharePoint.Client.ContentType CreateContentType(Web web, ContentType templateContentType, TokenParser parser, FileConnectorBase connector, PnPMonitoredScope scope, List<Microsoft.SharePoint.Client.ContentType> existingCTs = null, List<Microsoft.SharePoint.Client.Field> existingFields = null, bool isNoScriptSite = false) { var name = parser.ParseString(templateContentType.Name); var description = parser.ParseString(templateContentType.Description); var id = parser.ParseString(templateContentType.Id); var group = parser.ParseString(templateContentType.Group); var createdCT = web.CreateContentType(name, description, id, group); foreach (var fieldRef in templateContentType.FieldRefs) { Microsoft.SharePoint.Client.Field field = null; try { // Try to get the field by ID field = web.Fields.GetById(fieldRef.Id); } catch (ArgumentException) { // In case of failure, if we have the name if (!String.IsNullOrEmpty(fieldRef.Name)) { // Let's try with that one field = web.Fields.GetByInternalNameOrTitle(fieldRef.Name); } } // Add it to the target content type // Notice that this code will fail if the field does not exist web.AddFieldToContentType(createdCT, field, fieldRef.Required, fieldRef.Hidden); } // Add new CTs parser.AddToken(new ContentTypeIdToken(web, name, id)); #if !ONPREMISES // Set resources if (templateContentType.Name.ContainsResourceToken()) { createdCT.NameResource.SetUserResourceValue(templateContentType.Name, parser); } if (templateContentType.Description.ContainsResourceToken()) { createdCT.DescriptionResource.SetUserResourceValue(templateContentType.Description, parser); } #endif //Reorder the elements so that the new created Content Type has the same order as defined in the //template. The order can be different if the new Content Type inherits from another Content Type. //In this case the new Content Type has all field of the original Content Type and missing fields //will be added at the end. To fix this issue we ordering the fields once more. createdCT.FieldLinks.Reorder(templateContentType.FieldRefs.Select(fld => parser.ParseString(fld.Name)).ToArray()); createdCT.ReadOnly = templateContentType.ReadOnly; createdCT.Hidden = templateContentType.Hidden; createdCT.Sealed = templateContentType.Sealed; if (templateContentType.DocumentSetTemplate == null) { // Only apply a document template when the contenttype is not a document set if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DocumentTemplate))) { createdCT.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate); } } // Skipping updates of forms as we can't upload forms to noscript sites if (!isNoScriptSite) { if (!String.IsNullOrEmpty(parser.ParseString(templateContentType.NewFormUrl))) { createdCT.NewFormUrl = parser.ParseString(templateContentType.NewFormUrl); } if (!String.IsNullOrEmpty(parser.ParseString(templateContentType.EditFormUrl))) { createdCT.EditFormUrl = parser.ParseString(templateContentType.EditFormUrl); } if (!String.IsNullOrEmpty(parser.ParseString(templateContentType.DisplayFormUrl))) { createdCT.DisplayFormUrl = parser.ParseString(templateContentType.DisplayFormUrl); } } else { if (!String.IsNullOrEmpty(parser.ParseString(templateContentType.DisplayFormUrl)) || !String.IsNullOrEmpty(parser.ParseString(templateContentType.EditFormUrl)) || !String.IsNullOrEmpty(parser.ParseString(templateContentType.NewFormUrl))) { // log message scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_SkipCustomFormUrls, name); } } createdCT.Update(true); web.Context.ExecuteQueryRetry(); // If the CT is a DocumentSet if (templateContentType.DocumentSetTemplate != null) { // Retrieve a reference to the DocumentSet Content Type Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate documentSetTemplate = Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.GetDocumentSetTemplate(web.Context, createdCT); // Load the collections to allow for deletion scenarions web.Context.Load(documentSetTemplate, d => d.AllowedContentTypes, d => d.DefaultDocuments, d => d.SharedFields, d => d.WelcomePageFields); web.Context.ExecuteQueryRetry(); if (!String.IsNullOrEmpty(templateContentType.DocumentSetTemplate.WelcomePage)) { // TODO: Customize the WelcomePage of the DocumentSet } // Add additional content types to the set of allowed content types bool hasDefaultDocumentContentTypeInTemplate = false; foreach (String ctId in templateContentType.DocumentSetTemplate.AllowedContentTypes) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == ctId); if (ct != null) { if (ct.Id.StringValue.Equals("0x0101", StringComparison.InvariantCultureIgnoreCase)) { hasDefaultDocumentContentTypeInTemplate = true; } documentSetTemplate.AllowedContentTypes.Add(ct.Id); } } // If the default document content type (0x0101) is not in our definition then remove it if (!hasDefaultDocumentContentTypeInTemplate) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == "0x0101"); if (ct != null) { documentSetTemplate.AllowedContentTypes.Remove(ct.Id); } } if (!isNoScriptSite) { foreach (var doc in templateContentType.DocumentSetTemplate.DefaultDocuments) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == doc.ContentTypeId); if (ct != null) { using (Stream fileStream = connector.GetFileStream(doc.FileSourcePath)) { documentSetTemplate.DefaultDocuments.Add(doc.Name, ct.Id, ReadFullStream(fileStream)); } } } } else { if (templateContentType.DocumentSetTemplate.DefaultDocuments.Any()) { scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_SkipDocumentSetDefaultDocuments, name); } } foreach (var sharedField in templateContentType.DocumentSetTemplate.SharedFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == sharedField); if (field != null) { documentSetTemplate.SharedFields.Add(field); } } foreach (var welcomePageField in templateContentType.DocumentSetTemplate.WelcomePageFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == welcomePageField); if (field != null) { documentSetTemplate.WelcomePageFields.Add(field); } } documentSetTemplate.Update(true); web.Context.ExecuteQueryRetry(); } web.Context.Load(createdCT); web.Context.ExecuteQueryRetry(); return createdCT; }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { // Check if this is not a noscript site as we're not allowed to write to the web property bag is that one bool isNoScriptSite = web.IsNoScriptSite(); web.EnsureProperties(w => w.ServerRelativeUrl, w => w.Url); // Build on the fly the list of additional files coming from the Directories var directoryFiles = new List <Model.File>(); foreach (var directory in template.Directories) { var metadataProperties = directory.GetMetadataProperties(); directoryFiles.AddRange(directory.GetDirectoryFiles(metadataProperties)); } var filesToProcess = template.Files.Union(directoryFiles).ToArray(); var siteAssetsFiles = filesToProcess.Where(f => f.Folder.ToLower().Contains("siteassets")).FirstOrDefault(); if (siteAssetsFiles != null) { // Need this so that we dont have access denied error during the first time upload, especially for modern sites web.Lists.EnsureSiteAssetsLibrary(); web.Context.ExecuteQueryRetry(); } var currentFileIndex = 0; var originalWeb = web; // Used to store and re-store context in case files are deployed to masterpage gallery foreach (var file in filesToProcess) { file.Src = parser.ParseString(file.Src); var targetFileName = parser.ParseString( !String.IsNullOrEmpty(file.TargetFileName) ? file.TargetFileName : template.Connector.GetFilenamePart(file.Src) ); currentFileIndex++; WriteSubProgress("File", targetFileName, currentFileIndex, filesToProcess.Length); var folderName = parser.ParseString(file.Folder); if (folderName.ToLower().Contains("/_catalogs/")) { // Edge case where you have files in the template which should be provisioned to the site collection // master page gallery and not to a connected subsite web = web.Context.GetSiteCollectionContext().Web; web.EnsureProperties(w => w.ServerRelativeUrl, w => w.Url); } if (folderName.ToLower().StartsWith((web.ServerRelativeUrl.ToLower()))) { folderName = folderName.Substring(web.ServerRelativeUrl.Length); } if (SkipFile(isNoScriptSite, targetFileName, folderName)) { // add log message scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_Files_SkipFileUpload, targetFileName, folderName); continue; } var folder = web.EnsureFolderPath(folderName); #if !SP2013 //register folder UniqueId as Token folder.EnsureProperties(p => p.UniqueId, p => p.ServerRelativeUrl); parser.AddToken(new FileUniqueIdToken(web, folder.ServerRelativeUrl.Substring(web.ServerRelativeUrl.Length).TrimStart("/".ToCharArray()), folder.UniqueId)); parser.AddToken(new FileUniqueIdEncodedToken(web, folder.ServerRelativeUrl.Substring(web.ServerRelativeUrl.Length).TrimStart("/".ToCharArray()), folder.UniqueId)); #endif var checkedOut = false; var targetFile = folder.GetFile(template.Connector.GetFilenamePart(targetFileName)); if (targetFile != null) { if (file.Overwrite) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Files_Uploading_and_overwriting_existing_file__0_, targetFileName); checkedOut = CheckOutIfNeeded(web, targetFile); using (var stream = FileUtilities.GetFileStream(template, file)) { targetFile = UploadFile(folder, stream, targetFileName, file.Overwrite); } } else { checkedOut = CheckOutIfNeeded(web, targetFile); } } else { using (var stream = FileUtilities.GetFileStream(template, file)) { if (stream == null) { throw new FileNotFoundException($"File {file.Src} does not exist"); } else { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Files_Uploading_file__0_, targetFileName); targetFile = UploadFile(folder, stream, targetFileName, file.Overwrite); } } checkedOut = CheckOutIfNeeded(web, targetFile); } if (targetFile != null) { // Add the fileuniqueid tokens #if !SP2013 targetFile.EnsureProperties(p => p.UniqueId, p => p.ServerRelativeUrl); parser.AddToken(new FileUniqueIdToken(web, targetFile.ServerRelativeUrl.Substring(web.ServerRelativeUrl.Length).TrimStart("/".ToCharArray()), targetFile.UniqueId)); parser.AddToken(new FileUniqueIdEncodedToken(web, targetFile.ServerRelativeUrl.Substring(web.ServerRelativeUrl.Length).TrimStart("/".ToCharArray()), targetFile.UniqueId)); #endif #if !SP2013 bool webPartsNeedLocalization = false; #endif if (file.WebParts != null && file.WebParts.Any()) { targetFile.EnsureProperties(f => f.ServerRelativeUrl); var existingWebParts = web.GetWebParts(targetFile.ServerRelativeUrl).ToList(); foreach (var webPart in file.WebParts) { // check if the webpart is already set on the page if (existingWebParts.FirstOrDefault(w => w.WebPart.Title == parser.ParseString(webPart.Title)) == null) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Files_Adding_webpart___0___to_page, webPart.Title); var wpEntity = new WebPartEntity(); wpEntity.WebPartTitle = parser.ParseString(webPart.Title); wpEntity.WebPartXml = parser.ParseXmlString(webPart.Contents).Trim(new[] { '\n', ' ' }); wpEntity.WebPartZone = webPart.Zone; wpEntity.WebPartIndex = (int)webPart.Order; var wpd = web.AddWebPartToWebPartPage(targetFile.ServerRelativeUrl, wpEntity); #if !SP2013 if (webPart.Title.ContainsResourceToken()) { // update data based on where it was added - needed in order to localize wp title wpd.EnsureProperties(w => w.ZoneId, w => w.WebPart, w => w.WebPart.Properties); webPart.Zone = wpd.ZoneId; webPart.Order = (uint)wpd.WebPart.ZoneIndex; webPartsNeedLocalization = true; } #endif } } } #if !SP2013 if (webPartsNeedLocalization) { file.LocalizeWebParts(web, parser, targetFile, scope); } #endif //Set Properties before Checkin if (file.Properties != null && file.Properties.Any()) { Dictionary <string, string> transformedProperties = file.Properties.ToDictionary(property => property.Key, property => parser.ParseString(property.Value)); SetFileProperties(targetFile, transformedProperties, parser, false); } switch (file.Level) { case Model.FileLevel.Published: { targetFile.PublishFileToLevel(Microsoft.SharePoint.Client.FileLevel.Published); break; } case Model.FileLevel.Draft: { targetFile.PublishFileToLevel(Microsoft.SharePoint.Client.FileLevel.Draft); break; } default: { if (checkedOut) { targetFile.CheckIn("", CheckinType.MajorCheckIn); web.Context.ExecuteQueryRetry(); } break; } } // Don't set security when nothing is defined. This otherwise breaks on files set outside of a list if (file.Security != null && (file.Security.ClearSubscopes == true || file.Security.CopyRoleAssignments == true || file.Security.RoleAssignments.Count > 0)) { targetFile.ListItemAllFields.SetSecurity(parser, file.Security, WriteMessage); } } web = originalWeb; // restore context in case files are provisioned to the master page gallery #1059 } } WriteMessage("Done processing files", ProvisioningMessageType.Completed); return(parser); }
public override TokenParser ProvisionObjects(Tenant tenant, Model.ProvisioningHierarchy hierarchy, string sequenceId, TokenParser tokenParser, ApplyConfiguration configuration) { using (var scope = new PnPMonitoredScope(CoreResources.Provisioning_ObjectHandlers_Provisioning)) { bool nowait = false; if (configuration != null) { nowait = configuration.Tenant.DoNotWaitForSitesToBeFullyCreated; } var sequence = hierarchy.Sequences.FirstOrDefault(s => s.ID == sequenceId); if (sequence != null) { var siteUrls = new Dictionary <Guid, string>(); TokenParser siteTokenParser = null; var tenantThemes = tenant.GetAllTenantThemes(); tenant.Context.Load(tenantThemes); tenant.Context.ExecuteQueryRetry(); foreach (var sitecollection in sequence.SiteCollections) { ClientContext siteContext = null; switch (sitecollection) { case TeamSiteCollection t: { TeamSiteCollectionCreationInformation siteInfo = new TeamSiteCollectionCreationInformation() { Alias = tokenParser.ParseString(t.Alias), DisplayName = tokenParser.ParseString(t.Title), Description = tokenParser.ParseString(t.Description), Classification = tokenParser.ParseString(t.Classification), IsPublic = t.IsPublic, Lcid = (uint)t.Language }; if (Guid.TryParse(t.SiteDesign, out Guid siteDesignId)) { siteInfo.SiteDesignId = siteDesignId; } var groupSiteInfo = Sites.SiteCollection.GetGroupInfoAsync(tenant.Context as ClientContext, siteInfo.Alias).GetAwaiter().GetResult(); if (groupSiteInfo == null) { var graphAccessToken = PnPProvisioningContext.Current.AcquireCookie(Core.Utilities.Graph.GraphHelper.MicrosoftGraphBaseURI); WriteMessage($"Creating Team Site {siteInfo.Alias}", ProvisioningMessageType.Progress); siteContext = Sites.SiteCollection.Create(tenant.Context as ClientContext, siteInfo, configuration.Tenant.DelayAfterModernSiteCreation, noWait: nowait, graphAccessToken: graphAccessToken); } else { if (groupSiteInfo.ContainsKey("siteUrl")) { WriteMessage($"Using existing Team Site {siteInfo.Alias}", ProvisioningMessageType.Progress); siteContext = (tenant.Context as ClientContext).Clone(groupSiteInfo["siteUrl"], configuration.AccessTokens); } } if (t.IsHubSite) { siteContext.Load(siteContext.Site, s => s.Id); siteContext.ExecuteQueryRetry(); RegisterAsHubSite(tenant, siteContext.Url, siteContext.Site.Id, t.HubSiteLogoUrl, t.HubSiteTitle, tokenParser); } if (!string.IsNullOrEmpty(t.Theme)) { var parsedTheme = tokenParser.ParseString(t.Theme); if (tenantThemes.FirstOrDefault(th => th.Name == parsedTheme) != null) { tenant.SetWebTheme(parsedTheme, siteContext.Url); tenant.Context.ExecuteQueryRetry(); } else { WriteMessage($"Theme {parsedTheme} doesn't exist in the tenant, will not be applied", ProvisioningMessageType.Warning); } } if (t.Teamify) { try { WriteMessage($"Teamifying the O365 group connected site at URL - {siteContext.Url}", ProvisioningMessageType.Progress); siteContext.TeamifyAsync().GetAwaiter().GetResult(); } catch (Exception ex) { WriteMessage($"Teamifying site at URL - {siteContext.Url} failed due to an exception:- {ex.Message}", ProvisioningMessageType.Warning); } } if (t.HideTeamify) { try { WriteMessage($"Teamify prompt is now hidden for site at URL - {siteContext.Url}", ProvisioningMessageType.Progress); siteContext.HideTeamifyPrompt().GetAwaiter().GetResult(); } catch (Exception ex) { WriteMessage($"Teamify prompt couldn't be hidden for site at URL - {siteContext.Url} due to an exception:- {ex.Message}", ProvisioningMessageType.Warning); } } siteUrls.Add(t.Id, siteContext.Url); if (!string.IsNullOrEmpty(t.ProvisioningId)) { _additionalTokens.Add(new SequenceSiteUrlUrlToken(null, t.ProvisioningId, siteContext.Url)); siteContext.Web.EnsureProperty(w => w.Id); _additionalTokens.Add(new SequenceSiteIdToken(null, t.ProvisioningId, siteContext.Web.Id)); siteContext.Site.EnsureProperties(s => s.Id, s => s.GroupId); _additionalTokens.Add(new SequenceSiteCollectionIdToken(null, t.ProvisioningId, siteContext.Site.Id)); _additionalTokens.Add(new SequenceSiteGroupIdToken(null, t.ProvisioningId, siteContext.Site.GroupId)); } break; } case CommunicationSiteCollection c: { var siteUrl = tokenParser.ParseString(c.Url); if (!siteUrl.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase)) { var rootSiteUrl = tenant.GetRootSiteUrl(); tenant.Context.ExecuteQueryRetry(); siteUrl = UrlUtility.Combine(rootSiteUrl.Value, siteUrl); } CommunicationSiteCollectionCreationInformation siteInfo = new CommunicationSiteCollectionCreationInformation() { ShareByEmailEnabled = c.AllowFileSharingForGuestUsers, Classification = tokenParser.ParseString(c.Classification), Description = tokenParser.ParseString(c.Description), Lcid = (uint)c.Language, Owner = tokenParser.ParseString(c.Owner), Title = tokenParser.ParseString(c.Title), Url = siteUrl }; if (Guid.TryParse(c.SiteDesign, out Guid siteDesignId)) { siteInfo.SiteDesignId = siteDesignId; } else { if (!string.IsNullOrEmpty(c.SiteDesign)) { siteInfo.SiteDesign = (CommunicationSiteDesign)Enum.Parse(typeof(CommunicationSiteDesign), c.SiteDesign); } else { siteInfo.SiteDesign = CommunicationSiteDesign.Showcase; } } // check if site exists if (tenant.SiteExistsAnywhere(siteInfo.Url) == SiteExistence.Yes) { WriteMessage($"Using existing Communications Site at {siteInfo.Url}", ProvisioningMessageType.Progress); siteContext = (tenant.Context as ClientContext).Clone(siteInfo.Url, configuration.AccessTokens); } else if (tenant.SiteExistsAnywhere(siteInfo.Url) == SiteExistence.Recycled) { var errorMessage = $"The requested Communications Site at {siteInfo.Url} is in the Recycle Bin and cannot be created"; WriteMessage(errorMessage, ProvisioningMessageType.Error); throw new RecycledSiteException(errorMessage); } else { WriteMessage($"Creating Communications Site at {siteInfo.Url}", ProvisioningMessageType.Progress); siteContext = Sites.SiteCollection.Create(tenant.Context as ClientContext, siteInfo, configuration.Tenant.DelayAfterModernSiteCreation, noWait: nowait); } if (c.IsHubSite) { siteContext.Load(siteContext.Site, s => s.Id); siteContext.ExecuteQueryRetry(); RegisterAsHubSite(tenant, siteInfo.Url, siteContext.Site.Id, c.HubSiteLogoUrl, c.HubSiteTitle, tokenParser); } if (!string.IsNullOrEmpty(c.Theme)) { var parsedTheme = tokenParser.ParseString(c.Theme); if (tenantThemes.FirstOrDefault(th => th.Name == parsedTheme) != null) { tenant.SetWebTheme(parsedTheme, siteInfo.Url); tenant.Context.ExecuteQueryRetry(); } else { WriteMessage($"Theme {parsedTheme} doesn't exist in the tenant, will not be applied", ProvisioningMessageType.Warning); } } siteUrls.Add(c.Id, siteInfo.Url); if (!string.IsNullOrEmpty(c.ProvisioningId)) { _additionalTokens.Add(new SequenceSiteUrlUrlToken(null, c.ProvisioningId, siteInfo.Url)); siteContext.Web.EnsureProperty(w => w.Id); _additionalTokens.Add(new SequenceSiteIdToken(null, c.ProvisioningId, siteContext.Web.Id)); siteContext.Site.EnsureProperties(s => s.Id, s => s.GroupId); _additionalTokens.Add(new SequenceSiteCollectionIdToken(null, c.ProvisioningId, siteContext.Site.Id)); _additionalTokens.Add(new SequenceSiteGroupIdToken(null, c.ProvisioningId, siteContext.Site.GroupId)); } break; } case TeamNoGroupSiteCollection t: { var siteUrl = tokenParser.ParseString(t.Url); TeamNoGroupSiteCollectionCreationInformation siteInfo = new TeamNoGroupSiteCollectionCreationInformation() { Lcid = (uint)t.Language, Url = siteUrl, Title = tokenParser.ParseString(t.Title), Description = tokenParser.ParseString(t.Description), Owner = tokenParser.ParseString(t.Owner) }; if (tenant.SiteExistsAnywhere(siteUrl) == SiteExistence.Yes) { WriteMessage($"Using existing Team Site at {siteUrl}", ProvisioningMessageType.Progress); siteContext = (tenant.Context as ClientContext).Clone(siteUrl, configuration.AccessTokens); } else if (tenant.SiteExistsAnywhere(siteUrl) == SiteExistence.Recycled) { var errorMessage = $"The requested Team Site at {siteUrl} is in the Recycle Bin and cannot be created"; WriteMessage(errorMessage, ProvisioningMessageType.Error); throw new RecycledSiteException(errorMessage); } else { WriteMessage($"Creating Team Site with no Office 365 group at {siteUrl}", ProvisioningMessageType.Progress); siteContext = Sites.SiteCollection.Create(tenant.Context as ClientContext, siteInfo, configuration.Tenant.DelayAfterModernSiteCreation, noWait: nowait); } if (t.Groupify) { if (string.IsNullOrEmpty(t.Alias)) { // We generate the alias, if it is missing t.Alias = t.Title.Replace(" ", string.Empty).ToLower(); } // In case we need to groupify the just created site var groupifyInformation = new TeamSiteCollectionGroupifyInformation { Alias = t.Alias, // Mandatory Classification = t.Classification, // Optional Description = t.Description, DisplayName = t.Title, HubSiteId = Guid.Empty, // Optional, so far we skip it IsPublic = t.IsPublic, // Mandatory KeepOldHomePage = t.KeepOldHomePage, // Optional, but we provide it Lcid = (uint)t.Language, Owners = new string[] { t.Owner }, }; tenant.GroupifySite(siteUrl, groupifyInformation); } if (t.IsHubSite) { siteContext.Load(siteContext.Site, s => s.Id); siteContext.ExecuteQueryRetry(); RegisterAsHubSite(tenant, siteContext.Url, siteContext.Site.Id, t.HubSiteLogoUrl, t.HubSiteTitle, tokenParser); } if (!string.IsNullOrEmpty(t.Theme)) { var parsedTheme = tokenParser.ParseString(t.Theme); if (tenantThemes.FirstOrDefault(th => th.Name == parsedTheme) != null) { tenant.SetWebTheme(parsedTheme, siteContext.Url); tenant.Context.ExecuteQueryRetry(); } else { WriteMessage($"Theme {parsedTheme} doesn't exist in the tenant, will not be applied", ProvisioningMessageType.Warning); } } siteUrls.Add(t.Id, siteContext.Url); if (!string.IsNullOrEmpty(t.ProvisioningId)) { _additionalTokens.Add(new SequenceSiteUrlUrlToken(null, t.ProvisioningId, siteContext.Url)); siteContext.Web.EnsureProperty(w => w.Id); _additionalTokens.Add(new SequenceSiteIdToken(null, t.ProvisioningId, siteContext.Web.Id)); siteContext.Site.EnsureProperties(s => s.Id, s => s.GroupId); _additionalTokens.Add(new SequenceSiteCollectionIdToken(null, t.ProvisioningId, siteContext.Site.Id)); _additionalTokens.Add(new SequenceSiteGroupIdToken(null, t.ProvisioningId, siteContext.Site.GroupId)); } break; } } var web = siteContext.Web; if (siteTokenParser == null) { siteTokenParser = new TokenParser(tenant, hierarchy, configuration.ToApplyingInformation()); foreach (var token in _additionalTokens) { siteTokenParser.AddToken(token); } } foreach (var subsite in sitecollection.Sites) { var subSiteObject = (TeamNoGroupSubSite)subsite; web.EnsureProperties(w => w.Webs.IncludeWithDefaultProperties(), w => w.ServerRelativeUrl); siteTokenParser = CreateSubSites(hierarchy, siteTokenParser, sitecollection, siteContext, web, subSiteObject); } siteTokenParser = null; } // System.Threading.Thread.Sleep(TimeSpan.FromMinutes(10)); WriteMessage("Applying templates", ProvisioningMessageType.Progress); var currentSite = ""; var provisioningTemplateApplyingInformation = configuration.ToApplyingInformation(); provisioningTemplateApplyingInformation.ProgressDelegate = (string message, int step, int total) => { configuration.ProgressDelegate?.Invoke($"{currentSite} : {message}", step, total); }; foreach (var sitecollection in sequence.SiteCollections) { currentSite = sitecollection.ProvisioningId != null ? sitecollection.ProvisioningId : sitecollection.Title; siteUrls.TryGetValue(sitecollection.Id, out string siteUrl); if (siteUrl != null) { using (var clonedContext = tenant.Context.Clone(siteUrl, configuration.AccessTokens)) { var web = clonedContext.Web; foreach (var templateRef in sitecollection.Templates) { var provisioningTemplate = hierarchy.Templates.FirstOrDefault(t => t.Id == templateRef); if (provisioningTemplate != null) { provisioningTemplate.Connector = hierarchy.Connector; //if (siteTokenParser == null) //{ siteTokenParser = new TokenParser(web, provisioningTemplate, configuration.ToApplyingInformation()); foreach (var token in _additionalTokens) { siteTokenParser.AddToken(token); } //} //else //{ // siteTokenParser.Rebase(web, provisioningTemplate); //} WriteMessage($"Applying Template", ProvisioningMessageType.Progress); new SiteToTemplateConversion().ApplyRemoteTemplate(web, provisioningTemplate, provisioningTemplateApplyingInformation, true, siteTokenParser); } else { WriteMessage($"Referenced template ID {templateRef} not found", ProvisioningMessageType.Error); } } if (siteTokenParser == null) { siteTokenParser = new TokenParser(tenant, hierarchy, configuration.ToApplyingInformation()); foreach (var token in _additionalTokens) { siteTokenParser.AddToken(token); } } foreach (var subsite in sitecollection.Sites) { var subSiteObject = (TeamNoGroupSubSite)subsite; web.EnsureProperties(w => w.Webs.IncludeWithDefaultProperties(), w => w.ServerRelativeUrl); siteTokenParser = ApplySubSiteTemplates(hierarchy, siteTokenParser, sitecollection, clonedContext, web, subSiteObject, provisioningTemplateApplyingInformation); } if (sitecollection.IsHubSite) { RESTUtilities.ExecuteGet(web, "/_api/web/hubsitedata(true)").GetAwaiter().GetResult(); } } } } } return(tokenParser); } }
//TODO: refactor this private void AddWebParts(Web web, Page page, TokenParser parser) { var url = parser.ParseString(page.Url); ContentPage contentPage = page as ContentPage; if (contentPage != null) { var file = web.GetFileByServerRelativeUrl(url); file.CheckOut(); foreach (var model in contentPage.WebParts) { try { model.Contents = parser.ParseString(model.Contents); string oldId = null; string newId = null; if (!WebPartsModelProvider.IsV3FormatXml(model.Contents)) { var id = WebPartsModelProvider.GetWebPartControlId(model.Contents); var idToReplace = GetNewControlId(); model.Contents = model.Contents.Replace(id, idToReplace); newId = this.GetIdFromControlId(idToReplace); oldId = this.GetIdFromControlId(id); } var addedWebPart = this.AddWebPart(web, model, file); newId = newId ?? addedWebPart.Id.ToString().ToLower(); oldId = oldId ?? GetWebPartIdFromSchema(model.Contents).ToLower(); parser.AddToken(new IdToken(web, newId, oldId)); } catch (Exception ex) { Log.Error(Constants.LOGGING_SOURCE_FRAMEWORK_PROVISIONING, "Could not add webpart: {0} - {1}", ex.Message, ex.StackTrace); } } var html = parser.ParseString(contentPage.Html); if (!string.IsNullOrEmpty(html)) { web.AddHtmlToWikiPage(url, html); } file.CheckIn(String.Empty, CheckinType.MajorCheckIn); return; } }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { var context = web.Context as ClientContext; web.EnsureProperties(w => w.ServerRelativeUrl, w => w.RootFolder.WelcomePage); // Check if this is not a noscript site as we're not allowed to update some properties bool isNoScriptSite = web.IsNoScriptSite(); foreach (var page in template.Pages) { var url = parser.ParseString(page.Url); if (!url.ToLower().StartsWith(web.ServerRelativeUrl.ToLower())) { url = UrlUtility.Combine(web.ServerRelativeUrl, url); } var exists = true; Microsoft.SharePoint.Client.File file = null; try { file = web.GetFileByServerRelativeUrl(url); web.Context.Load(file); web.Context.ExecuteQueryRetry(); } catch (ServerException ex) { if (ex.ServerErrorTypeName == "System.IO.FileNotFoundException") { exists = false; } } if (exists) { if (page.Overwrite) { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0_, url); if (page.WelcomePage && url.Contains(web.RootFolder.WelcomePage)) web.SetHomePage(string.Empty); file.DeleteObject(); web.Context.ExecuteQueryRetry(); web.AddWikiPageByUrl(url); if (page.Layout == WikiPageLayout.Custom) { web.AddLayoutToWikiPage(WikiPageLayout.OneColumn, url); } else { web.AddLayoutToWikiPage(page.Layout, url); } } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0__failed___1_____2_, url, ex.Message, ex.StackTrace); } } } else { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0_, url); web.AddWikiPageByUrl(url); if (page.Layout == WikiPageLayout.Custom) { web.AddLayoutToWikiPage(WikiPageLayout.OneColumn, url); } else { web.AddLayoutToWikiPage(page.Layout, url); } } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0__failed___1_____2_, url, ex.Message, ex.StackTrace); } } if (page.WelcomePage) { web.RootFolder.EnsureProperty(p => p.ServerRelativeUrl); var rootFolderRelativeUrl = url.Substring(web.RootFolder.ServerRelativeUrl.Length); web.SetHomePage(rootFolderRelativeUrl); } #if !SP2013 bool webPartsNeedLocalization = false; #endif if (page.WebParts != null & page.WebParts.Any()) { if (!isNoScriptSite) { var existingWebParts = web.GetWebParts(url); foreach (var webPart in page.WebParts) { if (existingWebParts.FirstOrDefault(w => w.WebPart.Title == parser.ParseString(webPart.Title)) == null) { WebPartEntity wpEntity = new WebPartEntity(); wpEntity.WebPartTitle = parser.ParseString(webPart.Title); wpEntity.WebPartXml = parser.ParseString(webPart.Contents.Trim(new[] { '\n', ' ' })); var wpd = web.AddWebPartToWikiPage(url, wpEntity, (int)webPart.Row, (int)webPart.Column, false); #if !SP2013 if (webPart.Title.ContainsResourceToken()) { // update data based on where it was added - needed in order to localize wp title #if !SP2016 wpd.EnsureProperties(w => w.ZoneId, w => w.WebPart, w => w.WebPart.Properties); webPart.Zone = wpd.ZoneId; #else wpd.EnsureProperties(w => w.WebPart, w => w.WebPart.Properties); #endif webPart.Order = (uint)wpd.WebPart.ZoneIndex; webPartsNeedLocalization = true; } #endif } } var allWebParts = web.GetWebParts(url); foreach (var webpart in allWebParts) { parser.AddToken(new WebPartIdToken(web, webpart.WebPart.Title, webpart.Id)); } } else { scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_Pages_SkipAddingWebParts, page.Url); } } #if !SP2013 if (webPartsNeedLocalization) { page.LocalizeWebParts(web, parser, scope); } #endif file = web.GetFileByServerRelativeUrl(url); file.EnsureProperty(f => f.ListItemAllFields); if (page.Fields.Any()) { var item = file.ListItemAllFields; foreach (var fieldValue in page.Fields) { item[fieldValue.Key] = parser.ParseString(fieldValue.Value); } item.Update(); web.Context.ExecuteQueryRetry(); } if (page.Security != null && page.Security.RoleAssignments.Count != 0) { web.Context.Load(file.ListItemAllFields); web.Context.ExecuteQueryRetry(); file.ListItemAllFields.SetSecurity(parser, page.Security); } } } return parser; }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { if (template.Lists.Any()) { var rootWeb = (web.Context as ClientContext).Site.RootWeb; rootWeb.Context.Load(rootWeb.Fields); web.Context.Load(web, w => w.ServerRelativeUrl); web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties( l => l.RootFolder.ServerRelativeUrl, l => l.Title, l => l.ParentWebUrl, l => l.Id, l => l.Description, l => l.OnQuickLaunch, l => l.Hidden, l => l.Fields.IncludeWithDefaultProperties( f => f.SchemaXml ), l => l.ContentTypesEnabled, l => l.ContentTypes.IncludeWithDefaultProperties( ct => ct.Id, ct => ct.StringId, ct => ct.Name), l => l.EnableAttachments, l => l.EnableFolderCreation, l => l.EnableMinorVersions, l => l.DraftVersionVisibility, l => l.Views #if !CLIENTSDKV15 , l => l.MajorWithMinorVersionsLimit #endif )); var existingCts = web.AvailableContentTypes; web.Context.Load(existingCts, cts => cts.IncludeWithDefaultProperties( ct => ct.Id, ct => ct.StringId, ct => ct.Name)); web.Context.ExecuteQueryRetry(); var existingLists = web.Lists.AsEnumerable().Select(existingList => existingList.RootFolder.ServerRelativeUrl).ToList(); var serverRelativeUrl = web.ServerRelativeUrl; var processedLists = new List<ListInfo>(); #region Lists foreach (var templateList in template.Lists) { // Check for the presence of the references content types and throw an exception if not present or in template if (templateList.ContentTypesEnabled) { foreach (var ct in templateList.ContentTypeBindings) { var found = template.ContentTypes.Any(t => t.Id.ToUpperInvariant() == ct.ContentTypeId.ToUpperInvariant()); if (found == false) { found = existingCts.Any(t => t.StringId.ToUpperInvariant() == ct.ContentTypeId.ToUpperInvariant()); } if (!found) { scope.LogError("Referenced content type {0} not available in site or in template", ct.ContentTypeId); throw new Exception(string.Format("Referenced content type {0} not available in site or in template", ct.ContentTypeId)); } } } var index = existingLists.FindIndex(x => x.Equals(UrlUtility.Combine(serverRelativeUrl, templateList.Url), StringComparison.OrdinalIgnoreCase)); if (index == -1) { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_list__0_, templateList.Title); var returnTuple = CreateList(web, templateList, parser, scope); var createdList = returnTuple.Item1; parser = returnTuple.Item2; processedLists.Add(new ListInfo { SiteList = createdList, TemplateList = templateList }); parser.AddToken(new ListIdToken(web, templateList.Title, createdList.Id)); parser.AddToken(new ListUrlToken(web, templateList.Title, createdList.RootFolder.ServerRelativeUrl.Substring(web.ServerRelativeUrl.Length + (web.ServerRelativeUrl == "/" ? 0 : 1)))); } catch (Exception ex) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_list__0__failed___1_____2_, templateList.Title, ex.Message, ex.StackTrace); //throw; } } else { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_list__0_, templateList.Title); var existingList = web.Lists[index]; var returnTuple = UpdateList(web, existingList, templateList, parser, scope); var updatedList = returnTuple.Item1; parser = returnTuple.Item2; if (updatedList != null) { processedLists.Add(new ListInfo { SiteList = updatedList, TemplateList = templateList }); } //add lists tokens if they was not added (happens for lists created by features) var listIdToken = new ListIdToken(web, templateList.Title, existingList.Id); var listUrlToken = new ListUrlToken(web, templateList.Title, existingList.RootFolder.ServerRelativeUrl.Substring(web.ServerRelativeUrl.Length + (web.ServerRelativeUrl == "/" ? 0 : 1))); var isTokensExist = parser.Tokens.Any(t => t.GetTokens().Any(x => x.Equals(listIdToken.GetTokens().First()))); if (!isTokensExist) { parser.AddToken(listIdToken); parser.AddToken(listUrlToken); } } catch (Exception ex) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_list__0__failed___1_____2_, templateList.Title, ex.Message, ex.StackTrace); //throw; } } } #endregion #region FieldRefs foreach (var listInfo in processedLists) { if (listInfo.TemplateList.FieldRefs.Any()) { foreach (var fieldRef in listInfo.TemplateList.FieldRefs) { var field = rootWeb.Fields.AsEnumerable().FirstOrDefault(f => f.IsPropertyAvailable("Id") && f.Id.ToString().Equals(fieldRef.Id.ToString(), StringComparison.InvariantCultureIgnoreCase)); if (field != null) { if (!listInfo.SiteList.Fields.AsEnumerable().Any(item => item.IsPropertyAvailable("Id") && item.Id.ToString().Equals(fieldRef.Id.ToString(), StringComparison.InvariantCultureIgnoreCase))) { try { CreateFieldRef(listInfo, field, fieldRef); } catch (Exception ex) { scope.LogError("Could not create FieldRef: {0} - {1}", ex.Message, ex.StackTrace); } } else { try { UpdateFieldRef(listInfo.SiteList, field.Id, fieldRef); } catch (Exception ex) { scope.LogError("Could not update FieldRef: {0} - {1}", ex.Message, ex.StackTrace); } } } } listInfo.SiteList.Update(); web.Context.ExecuteQueryRetry(); } } #endregion //Update list fields var updatedLists = web.Lists; web.Context.Load(updatedLists, lc => lc.IncludeWithDefaultProperties( l => l.Fields.IncludeWithDefaultProperties( f => f.SchemaXml ))); web.Context.ExecuteQueryRetry(); #region Fields foreach (var listInfo in processedLists) { if (listInfo.TemplateList.Fields.Any()) { foreach (var field in listInfo.TemplateList.Fields) { var fieldElement = XElement.Parse(parser.ParseString(field.SchemaXml, TokenParser.SPSiteTokenKeys)); if (fieldElement.Attribute("ID") == null) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field_schema_has_no_ID_attribute___0_, field.SchemaXml); throw new Exception(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field_schema_has_no_ID_attribute___0_, field.SchemaXml)); } var id = fieldElement.Attribute("ID").Value; Guid fieldGuid; if (!Guid.TryParse(id, out fieldGuid)) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_ID_for_field_is_not_a_valid_Guid___0_, field.SchemaXml); throw new Exception(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_ID_for_field_is_not_a_valid_Guid___0_, id)); } else { var fieldFromList = listInfo.SiteList.Fields.AsEnumerable().FirstOrDefault(f => f.IsPropertyAvailable("Id") && f.Id.ToString().Equals(fieldGuid.ToString(), StringComparison.InvariantCultureIgnoreCase)); if(fieldFromList == null){ var list = updatedLists.AsEnumerable().FirstOrDefault(l => l.Id.ToString().Equals(listInfo.SiteList.Id.ToString(), StringComparison.InvariantCultureIgnoreCase)); fieldFromList = list.Fields.AsEnumerable().FirstOrDefault(f => f.IsPropertyAvailable("Id") && f.Id.ToString().Equals(fieldGuid.ToString(), StringComparison.InvariantCultureIgnoreCase)); } if (fieldFromList == null) { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_field__0_, fieldGuid); CreateField(fieldElement, listInfo, parser, field.SchemaXml); } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_field__0__failed___1_____2_, fieldGuid, ex.Message, ex.StackTrace); } } else { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_field__0_, fieldGuid); UpdateField(web, listInfo, fieldGuid, fieldElement, fieldFromList, scope, parser, field.SchemaXml); } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_field__0__failed___1_____2_, fieldGuid, ex.Message, ex.StackTrace); } } } } } listInfo.SiteList.Update(); web.Context.ExecuteQueryRetry(); } #endregion #region Default Field Values foreach (var listInfo in processedLists) { if (listInfo.TemplateList.FieldDefaults.Any()) { foreach (var fieldDefault in listInfo.TemplateList.FieldDefaults) { var field = listInfo.SiteList.Fields.GetByInternalNameOrTitle(fieldDefault.Key); field.DefaultValue = fieldDefault.Value; field.Update(); } web.Context.ExecuteQueryRetry(); } } #endregion #region Views foreach (var listInfo in processedLists) { var list = listInfo.TemplateList; var createdList = listInfo.SiteList; if (list.Views.Any() && list.RemoveExistingViews) { while (createdList.Views.Any()) { createdList.Views[0].DeleteObject(); } web.Context.ExecuteQueryRetry(); } var existingViews = createdList.Views; web.Context.Load(existingViews, vs => vs.IncludeWithDefaultProperties(v => v.ViewFields)); web.Context.ExecuteQueryRetry(); foreach (var view in list.Views) { SPClient.View existingView = null; string viewName = Path.GetFileNameWithoutExtension( view.GetAttributeValue("Url") ); if( !string.IsNullOrEmpty( viewName ) ) { existingView = existingViews.FirstOrDefault(v => string.Equals(Path.GetFileNameWithoutExtension(v.ServerRelativeUrl), viewName, StringComparison.OrdinalIgnoreCase)); } else { string viewTitle = view.GetAttributeValue("DisplayName"); existingView = existingViews.FirstOrDefault(v => v.Title == viewTitle); } if (null != existingView) { View tempView = ExtractView(existingView); if ((null != tempView) && tempView.Equals(view)) { //Not needed to update view if it is not modified continue; } } CreateOrUpdateView(web, view, existingView, createdList, scope); } //// Removing existing views set the OnQuickLaunch option to false and need to be re-set. //if (list.OnQuickLaunch && list.RemoveExistingViews && list.Views.Count > 0) //{ // createdList.RefreshLoad(); // web.Context.ExecuteQueryRetry(); // createdList.OnQuickLaunch = list.OnQuickLaunch; // createdList.Update(); // web.Context.ExecuteQueryRetry(); //} } #endregion #region Forms foreach (var listInfo in processedLists) { var targetForms = listInfo.SiteList.Forms; var templateForms = listInfo.TemplateList.Forms.OrderByDescending(x => x.IsDefault).ToArray();//create default first try { foreach (var templateForm in templateForms) { var formName = GetPageName(templateForm.ServerRelativeUrl); var form = targetForms.FirstOrDefault(x => GetPageName(x.ServerRelativeUrl).EndsWith(formName)); if (form == null) { CreateForm(templateForm, listInfo, false); } } if (templateForms.Any()) { listInfo.SiteList.Context.ExecuteQueryRetry(); } } catch (Exception exception) { var message = string.Format("Problem with form exporting for {0}", listInfo.TemplateList.Title); scope.LogError(exception, message); } } #endregion #region Folders // Folders are supported for document libraries and generic lists only foreach (var list in processedLists) { list.SiteList.EnsureProperties(l => l.BaseType); if ((list.SiteList.BaseType == BaseType.DocumentLibrary | list.SiteList.BaseType == BaseType.GenericList) && list.TemplateList.Folders != null && list.TemplateList.Folders.Count > 0) { list.SiteList.EnableFolderCreation = true; list.SiteList.Update(); web.Context.ExecuteQueryRetry(); var rootFolder = list.SiteList.RootFolder; foreach (var folder in list.TemplateList.Folders) { CreateFolderInList(rootFolder, folder, parser, scope); } } } #endregion // If an existing view is updated, and the list is to be listed on the QuickLaunch, it is removed because the existing view will be deleted and recreated from scratch. foreach (var listInfo in processedLists) { listInfo.SiteList.OnQuickLaunch = listInfo.TemplateList.OnQuickLaunch; listInfo.SiteList.Update(); } web.Context.ExecuteQueryRetry(); } } return parser; }
private Tuple<List, TokenParser> CreateList(Web web, ListInstance list, TokenParser parser, PnPMonitoredScope scope) { var listCreate = new ListCreationInformation(); listCreate.Description = list.Description; listCreate.TemplateType = list.TemplateType; listCreate.Title = parser.ParseString(list.Title); // the line of code below doesn't add the list to QuickLaunch // the OnQuickLaunch property is re-set on the Created List object listCreate.QuickLaunchOption = list.OnQuickLaunch ? QuickLaunchOptions.On : QuickLaunchOptions.Off; listCreate.Url = parser.ParseString(list.Url); listCreate.TemplateFeatureId = list.TemplateFeatureID; var createdList = web.Lists.Add(listCreate); createdList.Update(); web.Context.Load(createdList, l => l.BaseTemplate, l => l.RootFolder.ServerRelativeUrl, l => l.Title, l => l.ParentWebUrl, l => l.Id, l => l.Description, l => l.OnQuickLaunch, l => l.Hidden, l => l.Fields.IncludeWithDefaultProperties( f => f.SchemaXml ), l => l.ContentTypesEnabled, l => l.ContentTypes.IncludeWithDefaultProperties( ct => ct.Id, ct => ct.StringId, ct => ct.Name), l => l.EnableAttachments, l => l.EnableFolderCreation, l => l.EnableMinorVersions, l => l.DraftVersionVisibility, l => l.Views #if !CLIENTSDKV15 , l => l.MajorWithMinorVersionsLimit #endif ); web.Context.ExecuteQueryRetry(); #if !CLIENTSDKV15 if (list.Title.ContainsResourceToken()) { createdList.TitleResource.SetUserResourceValue(list.Title, parser); } if(list.Description.ContainsResourceToken()) { createdList.DescriptionResource.SetUserResourceValue(list.Description, parser); } #endif if (!String.IsNullOrEmpty(list.DocumentTemplate)) { var documentTemplateUrl = parser.ParseString(list.DocumentTemplate); var templateFolderUrl = documentTemplateUrl.Substring(0, documentTemplateUrl.LastIndexOf('/')); var templateForder = web.GetFolderByServerRelativeUrl(templateFolderUrl); var templateName = documentTemplateUrl.Substring(documentTemplateUrl.LastIndexOf('/') + 1); var templateStream = new MemoryStream(Encoding.UTF8.GetBytes(list.DocumentTemplateContent)); templateForder.UploadFile(templateName, templateStream, true); createdList.DocumentTemplateUrl = documentTemplateUrl; } // EnableAttachments are not supported for DocumentLibraries and Surveys // TODO: the user should be warned if (createdList.BaseTemplate != (int)ListTemplateType.DocumentLibrary && createdList.BaseTemplate != (int)ListTemplateType.Survey) { createdList.EnableAttachments = list.EnableAttachments; } createdList.EnableModeration = list.EnableModeration; // Done for all other lists than for Survey - With Surveys versioning configuration will cause an exception if (createdList.BaseTemplate != (int)ListTemplateType.Survey) { createdList.EnableVersioning = list.EnableVersioning; if (list.EnableVersioning) { #if !CLIENTSDKV15 createdList.MajorVersionLimit = list.MaxVersionLimit; #endif if (createdList.BaseTemplate == (int)ListTemplateType.DocumentLibrary) { // Only supported on Document Libraries createdList.EnableMinorVersions = list.EnableMinorVersions; createdList.DraftVersionVisibility = (DraftVisibilityType)list.DraftVersionVisibility; if (list.EnableMinorVersions) { createdList.MajorWithMinorVersionsLimit = list.MinorVersionLimit; // Set only if enabled, otherwise you'll get exception due setting value to zero. // DraftVisibilityType.Approver is available only when the EnableModeration option of the list is true if (DraftVisibilityType.Approver == (DraftVisibilityType)list.DraftVersionVisibility) { if (list.EnableModeration) { createdList.DraftVersionVisibility = (DraftVisibilityType)list.DraftVersionVisibility; } else { scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstances_DraftVersionVisibility_not_applied_because_EnableModeration_is_not_set_to_true); WriteWarning(CoreResources.Provisioning_ObjectHandlers_ListInstances_DraftVersionVisibility_not_applied_because_EnableModeration_is_not_set_to_true, ProvisioningMessageType.Warning); } } else { createdList.DraftVersionVisibility = (DraftVisibilityType)list.DraftVersionVisibility; } } } } } createdList.OnQuickLaunch = list.OnQuickLaunch; if (createdList.BaseTemplate != (int)ListTemplateType.DiscussionBoard && createdList.BaseTemplate != (int)ListTemplateType.Events) { createdList.EnableFolderCreation = list.EnableFolderCreation; } createdList.Hidden = list.Hidden; if (createdList.BaseTemplate != (int)ListTemplateType.Survey) { createdList.ContentTypesEnabled = list.ContentTypesEnabled; } createdList.Update(); web.Context.Load(createdList.Views); web.Context.Load(createdList.Forms); web.Context.Load(createdList, l => l.Id); web.Context.Load(createdList, l => l.RootFolder.ServerRelativeUrl); web.Context.Load(createdList, l => l.ContentTypesEnabled); web.Context.Load(createdList.ContentTypes); web.Context.ExecuteQueryRetry(); parser.AddToken(new ListIdProvisionToken(web, createdList.Id, list.ID)); parser.AddToken(new ListNameProvisionToken(web, createdList.Id, list.ID)); if (createdList.BaseTemplate != (int)ListTemplateType.Survey) { // Remove existing content types only if there are custom content type bindings var contentTypesToRemove = new List<ContentType>(); if (list.RemoveExistingContentTypes && list.ContentTypeBindings.Count > 0) { contentTypesToRemove.AddRange(createdList.ContentTypes); } List<ContentType> listCTypes = new List<ContentType>(); listCTypes.AddRange(createdList.ContentTypes); var contentTypeAdded = false; ContentTypeBinding defaultCtBinding = null; foreach (var ctBinding in list.ContentTypeBindings) { var contentType = web.AvailableContentTypes.AsEnumerable().FirstOrDefault(item => item.Id.StringValue.Equals(ctBinding.ContentTypeId, StringComparison.OrdinalIgnoreCase)); if (contentType != null) { // Check if CT is already available var name = contentType.EnsureProperty(ct => ct.Name); if (!listCTypes.Any( ct=> ct.Name == name ) ) { if (createdList.ContentTypesEnabled == false) { createdList.ContentTypesEnabled = true; createdList.Update(); createdList.Context.ExecuteQueryRetry(); } createdList.ContentTypes.AddExistingContentType(contentType); listCTypes.Add(contentType); contentTypeAdded = true; } if (ctBinding.Default) { defaultCtBinding = ctBinding; } } } if (contentTypeAdded) { web.Context.ExecuteQueryRetry(); } // default ContentTypeBinding should be set last because // list extension .SetDefaultContentTypeToList() re-sets // the list.RootFolder UniqueContentTypeOrder property // which may cause missing CTs from the "New Button" if (defaultCtBinding != null) { createdList.SetDefaultContentTypeToList(defaultCtBinding.ContentTypeId); } var ctDeleted = false; // Effectively remove existing content types, if any foreach (var ct in contentTypesToRemove) { var shouldDelete = true; shouldDelete &= (createdList.BaseTemplate != (int)ListTemplateType.DocumentLibrary || !ct.StringId.StartsWith(BuiltInContentTypeId.Folder + "00")); if (shouldDelete) { ct.DeleteObject(); ctDeleted = true; } } if (ctDeleted) { web.Context.ExecuteQueryRetry(); } } if (list.Security != null) { try { createdList.SetSecurity(parser, list.Security); } catch (Exception ex) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_list__0__failed___1_____2_, list.Title, ex.Message, ex.StackTrace); } } return Tuple.Create(createdList, parser); }
private Tuple<List, TokenParser> UpdateList(Web web, List existingList, ListInstance templateList, TokenParser parser, PnPMonitoredScope scope) { try { web.Context.Load(existingList, l => l.Forms); web.Context.ExecuteQueryRetry(); } catch (Exception ex) { scope.LogDebug("Loading forms on list {0} failed. {1}. {2}", existingList.Title, ex.Message, ex.StackTrace); } if (existingList.BaseTemplate == templateList.TemplateType) { var isDirty = false; if (parser.ParseString(templateList.Title) != existingList.Title) { var oldTitle = existingList.Title; existingList.Title = parser.ParseString(templateList.Title); if (!oldTitle.Equals(existingList.Title, StringComparison.OrdinalIgnoreCase)) { parser.AddToken(new ListIdToken(web, existingList.Title, existingList.Id)); parser.AddToken(new ListUrlToken(web, existingList.Title, existingList.RootFolder.ServerRelativeUrl.Substring(web.ServerRelativeUrl.Length + (web.ServerRelativeUrl == "/" ? 0 : 1)))); } isDirty = true; } if (!string.IsNullOrEmpty(templateList.DocumentTemplate)) { if (existingList.DocumentTemplateUrl != parser.ParseString(templateList.DocumentTemplate)) { var documentTemplateUrl = parser.ParseString(templateList.DocumentTemplate); var templateFolderUrl = documentTemplateUrl.Substring(0, documentTemplateUrl.LastIndexOf('/')); var templateForder = web.GetFolderByServerRelativeUrl(templateFolderUrl); var templateName = documentTemplateUrl.Substring(documentTemplateUrl.LastIndexOf('/') + 1); var templateStream = new MemoryStream(Encoding.UTF8.GetBytes(templateList.DocumentTemplateContent)); templateForder.UploadFile(templateName, templateStream, true); existingList.DocumentTemplateUrl = documentTemplateUrl; isDirty = true; } } if (!string.IsNullOrEmpty(templateList.Description) && templateList.Description != existingList.Description) { existingList.Description = templateList.Description; isDirty = true; } if (templateList.Hidden != existingList.Hidden) { existingList.Hidden = templateList.Hidden; isDirty = true; } if (templateList.OnQuickLaunch != existingList.OnQuickLaunch) { existingList.OnQuickLaunch = templateList.OnQuickLaunch; isDirty = true; } if (existingList.BaseTemplate != (int)ListTemplateType.Survey && templateList.ContentTypesEnabled != existingList.ContentTypesEnabled) { existingList.ContentTypesEnabled = templateList.ContentTypesEnabled; isDirty = true; } if (existingList.BaseTemplate != (int)ListTemplateType.Survey && existingList.BaseTemplate != (int)ListTemplateType.DocumentLibrary) { // https://msdn.microsoft.com/EN-US/library/microsoft.sharepoint.splist.enableattachments.aspx // The EnableAttachments property does not apply to any list that has a base type of Survey or DocumentLibrary. // If you set this property to true for either type of list, it throws an SPException. if (templateList.EnableAttachments != existingList.EnableAttachments) { existingList.EnableAttachments = templateList.EnableAttachments; isDirty = true; } } if (existingList.BaseTemplate != (int)ListTemplateType.DiscussionBoard) { if (templateList.EnableFolderCreation != existingList.EnableFolderCreation) { existingList.EnableFolderCreation = templateList.EnableFolderCreation; isDirty = true; } } #if !CLIENTSDKV15 if(templateList.Title.ContainsResourceToken()) { if(existingList.TitleResource.SetUserResourceValue(templateList.Title, parser)) { isDirty = true; } } #endif if (templateList.EnableVersioning) { if (existingList.EnableVersioning != templateList.EnableVersioning) { existingList.EnableVersioning = templateList.EnableVersioning; isDirty = true; } #if !CLIENTSDKV15 if (existingList.IsObjectPropertyInstantiated("MajorVersionLimit") && existingList.MajorVersionLimit != templateList.MaxVersionLimit) { existingList.MajorVersionLimit = templateList.MaxVersionLimit; isDirty = true; } #endif if (existingList.BaseType == BaseType.DocumentLibrary) { // Only supported on Document Libraries if (templateList.EnableMinorVersions != existingList.EnableMinorVersions) { existingList.EnableMinorVersions = templateList.EnableMinorVersions; isDirty = true; } if ((DraftVisibilityType)templateList.DraftVersionVisibility != existingList.DraftVersionVisibility) { existingList.DraftVersionVisibility = (DraftVisibilityType)templateList.DraftVersionVisibility; isDirty = true; } if (templateList.EnableMinorVersions) { if (templateList.MinorVersionLimit != existingList.MajorWithMinorVersionsLimit) { existingList.MajorWithMinorVersionsLimit = templateList.MinorVersionLimit; } if (DraftVisibilityType.Approver == (DraftVisibilityType)templateList.DraftVersionVisibility) { if (templateList.EnableModeration) { if ((DraftVisibilityType)templateList.DraftVersionVisibility != existingList.DraftVersionVisibility) { existingList.DraftVersionVisibility = (DraftVisibilityType)templateList.DraftVersionVisibility; isDirty = true; } } } else { if ((DraftVisibilityType)templateList.DraftVersionVisibility != existingList.DraftVersionVisibility) { existingList.DraftVersionVisibility = (DraftVisibilityType)templateList.DraftVersionVisibility; isDirty = true; } } } } } if (isDirty) { existingList.Update(); web.Context.ExecuteQueryRetry(); } if (existingList.ContentTypesEnabled) { // Check if we need to add a content type var existingContentTypes = existingList.ContentTypes; var bindingsToAdd = templateList.ContentTypeBindings.Where(ctb => existingContentTypes.All(ct => !ctb.ContentTypeId.Equals(ct.StringId, StringComparison.InvariantCultureIgnoreCase))).ToList(); var defaultCtBinding = templateList.ContentTypeBindings.FirstOrDefault(ctb => ctb.Default == true); var bindingAddedToList = false; foreach (var ctb in bindingsToAdd) { // Added a check so that if no bindings were actually added then the SetDefaultContentTypeToList method will not be executed // This is to address a specific scenario when OOTB PWA lists can not be updated as they are centrally managed var contentType = web.AvailableContentTypes.AsEnumerable().FirstOrDefault(item => item.Id.StringValue.Equals(ctb.ContentTypeId, StringComparison.OrdinalIgnoreCase)); if (contentType != null) { // Check if CT is already available var name = contentType.EnsureProperty(ct => ct.Name); if (!existingList.ContentTypes.AsEnumerable().Any(item => item.Name == name)) { if (existingList.ContentTypesEnabled == false) { existingList.ContentTypesEnabled = true; existingList.Update(); existingList.Context.ExecuteQueryRetry(); } existingList.ContentTypes.AddExistingContentType(contentType); bindingAddedToList = true; } } } if (bindingAddedToList) { web.Context.ExecuteQueryRetry(); } // default ContentTypeBinding should be set last because // list extension .SetDefaultContentTypeToList() re-sets // the list.RootFolder UniqueContentTypeOrder property // which may cause missing CTs from the "New Button" if (defaultCtBinding != null && bindingAddedToList) { existingList.SetDefaultContentTypeToList(defaultCtBinding.ContentTypeId); } } if (templateList.Security != null) { try { existingList.SetSecurity(parser, templateList.Security); } catch (Exception ex) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_list__0__failed___1_____2_, templateList.Title, ex.Message, ex.StackTrace); } } return Tuple.Create(existingList, parser); } else { scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstances_List__0____1____2___exists_but_is_of_a_different_type__Skipping_list_, templateList.Title, templateList.Url, existingList.Id); WriteWarning(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_List__0____1____2___exists_but_is_of_a_different_type__Skipping_list_, templateList.Title, templateList.Url, existingList.Id), ProvisioningMessageType.Warning); return null; } }
public override TokenParser ProvisionObjects(Web web, Model.ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { this.reusedTerms = new List <ReusedTerm>(); TaxonomySession taxSession = TaxonomySession.GetTaxonomySession(web.Context); TermStore termStore = null; TermGroup siteCollectionTermGroup = null; try { termStore = taxSession.GetDefaultKeywordsTermStore(); web.Context.Load(termStore, ts => ts.Languages, ts => ts.DefaultLanguage, ts => ts.Groups.Include( tg => tg.Name, tg => tg.Id, tg => tg.TermSets.Include( tset => tset.Name, tset => tset.Id))); siteCollectionTermGroup = termStore.GetSiteCollectionGroup((web.Context as ClientContext).Site, false); web.Context.Load(siteCollectionTermGroup); web.Context.ExecuteQueryRetry(); } catch (ServerException) { // If the GetDefaultSiteCollectionTermStore method call fails ... raise a specific Warning WriteMessage(CoreResources.Provisioning_ObjectHandlers_TermGroups_Wrong_Configuration, ProvisioningMessageType.Warning); // and exit skipping the current handler return(parser); } SiteCollectionTermGroupNameToken siteCollectionTermGroupNameToken = new SiteCollectionTermGroupNameToken(web); foreach (var modelTermGroup in template.TermGroups) { #region Group var newGroup = false; var normalizedGroupName = TaxonomyItem.NormalizeName(web.Context, modelTermGroup.Name); web.Context.ExecuteQueryRetry(); TermGroup group = termStore.Groups.FirstOrDefault( g => g.Id == modelTermGroup.Id || g.Name == normalizedGroupName.Value); if (group == null) { var parsedGroupName = parser.ParseString(modelTermGroup.Name); var parsedDescription = parser.ParseString(modelTermGroup.Description); if (modelTermGroup.Name == "Site Collection" || parsedGroupName == siteCollectionTermGroupNameToken.GetReplaceValue() || modelTermGroup.SiteCollectionTermGroup) { var site = (web.Context as ClientContext).Site; group = termStore.GetSiteCollectionGroup(site, true); web.Context.Load(group, g => g.Name, g => g.Id, g => g.TermSets.Include( tset => tset.Name, tset => tset.Id)); web.Context.ExecuteQueryRetry(); } else { var parsedNormalizedGroupName = TaxonomyItem.NormalizeName(web.Context, parsedGroupName); web.Context.ExecuteQueryRetry(); group = termStore.Groups.FirstOrDefault(g => g.Name == parsedNormalizedGroupName.Value); if (group == null) { if (modelTermGroup.Id == Guid.Empty) { modelTermGroup.Id = Guid.NewGuid(); } group = termStore.CreateGroup(parsedGroupName, modelTermGroup.Id); group.Description = parsedDescription; #if !ONPREMISES // Handle TermGroup Contributors, if any if (modelTermGroup.Contributors != null && modelTermGroup.Contributors.Count > 0) { foreach (var c in modelTermGroup.Contributors) { group.AddContributor(c.Name); } } // Handle TermGroup Managers, if any if (modelTermGroup.Managers != null && modelTermGroup.Managers.Count > 0) { foreach (var m in modelTermGroup.Managers) { group.AddGroupManager(m.Name); } } #endif termStore.CommitAll(); web.Context.Load(group); web.Context.ExecuteQueryRetry(); newGroup = true; } } } #endregion #region TermSets foreach (var modelTermSet in modelTermGroup.TermSets) { TermSet set = null; var newTermSet = false; var normalizedTermSetName = TaxonomyItem.NormalizeName(web.Context, modelTermSet.Name); web.Context.ExecuteQueryRetry(); if (!newGroup) { set = group.TermSets.FirstOrDefault( ts => ts.Id == modelTermSet.Id || ts.Name == normalizedTermSetName.Value); } if (set == null) { if (modelTermSet.Id == Guid.Empty) { modelTermSet.Id = Guid.NewGuid(); } set = group.CreateTermSet(parser.ParseString(modelTermSet.Name), modelTermSet.Id, modelTermSet.Language ?? termStore.DefaultLanguage); parser.AddToken(new TermSetIdToken(web, group.Name, modelTermSet.Name, modelTermSet.Id)); if (!siteCollectionTermGroup.ServerObjectIsNull.Value) { if (group.Name == siteCollectionTermGroup.Name) { parser.AddToken((new SiteCollectionTermSetIdToken(web, modelTermSet.Name, modelTermSet.Id))); } } newTermSet = true; set.Description = parser.ParseString(modelTermSet.Description); set.IsOpenForTermCreation = modelTermSet.IsOpenForTermCreation; set.IsAvailableForTagging = modelTermSet.IsAvailableForTagging; foreach (var property in modelTermSet.Properties) { set.SetCustomProperty(property.Key, parser.ParseString(property.Value)); } if (modelTermSet.Owner != null) { set.Owner = modelTermSet.Owner; } termStore.CommitAll(); web.Context.Load(set); web.Context.ExecuteQueryRetry(); } web.Context.Load(set, s => s.Terms.Include(t => t.Id, t => t.Name)); web.Context.ExecuteQueryRetry(); var terms = set.Terms; foreach (var modelTerm in modelTermSet.Terms) { if (!newTermSet) { if (terms.Any()) { var term = terms.FirstOrDefault(t => t.Id == modelTerm.Id); if (term == null) { var normalizedTermName = TaxonomyItem.NormalizeName(web.Context, modelTerm.Name); web.Context.ExecuteQueryRetry(); term = terms.FirstOrDefault(t => t.Name == normalizedTermName.Value); if (term == null) { var returnTuple = CreateTerm <TermSet>(web, modelTerm, set, termStore, parser, scope); if (returnTuple != null) { modelTerm.Id = returnTuple.Item1; parser = returnTuple.Item2; } } else { modelTerm.Id = term.Id; } } else { modelTerm.Id = term.Id; } if (term != null) { CheckChildTerms(web, modelTerm, term, termStore, parser, scope); } } else { var returnTuple = CreateTerm <TermSet>(web, modelTerm, set, termStore, parser, scope); if (returnTuple != null) { modelTerm.Id = returnTuple.Item1; parser = returnTuple.Item2; } } } else { var returnTuple = CreateTerm <TermSet>(web, modelTerm, set, termStore, parser, scope); if (returnTuple != null) { modelTerm.Id = returnTuple.Item1; parser = returnTuple.Item2; } } } // do we need custom sorting? if (modelTermSet.Terms.Any(t => t.CustomSortOrder > -1)) { var sortedTerms = modelTermSet.Terms.OrderBy(t => t.CustomSortOrder); var customSortString = sortedTerms.Aggregate(string.Empty, (a, i) => a + i.Id.ToString() + ":"); customSortString = customSortString.TrimEnd(new[] { ':' }); set.CustomSortOrder = customSortString; termStore.CommitAll(); web.Context.ExecuteQueryRetry(); } } #endregion } foreach (var reusedTerm in this.reusedTerms) { TryReuseTerm(web, reusedTerm.ModelTerm, reusedTerm.Parent, reusedTerm.TermStore, parser, scope); } } return(parser); }
public override TokenParser ProvisionObjects(Tenant tenant, Model.ProvisioningHierarchy hierarchy, string sequenceId, TokenParser tokenParser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(CoreResources.Provisioning_ObjectHandlers_Provisioning)) { var sequence = hierarchy.Sequences.FirstOrDefault(s => s.ID == sequenceId); if (sequence != null) { var siteUrls = new Dictionary <Guid, string>(); TokenParser siteTokenParser = null; foreach (var sitecollection in sequence.SiteCollections) { ClientContext siteContext = null; switch (sitecollection) { case TeamSiteCollection t: { TeamSiteCollectionCreationInformation siteInfo = new TeamSiteCollectionCreationInformation() { Alias = tokenParser.ParseString(t.Alias), DisplayName = tokenParser.ParseString(t.Title), Description = tokenParser.ParseString(t.Description), Classification = tokenParser.ParseString(t.Classification), IsPublic = t.IsPublic }; var groupSiteInfo = Sites.SiteCollection.GetGroupInfo(tenant.Context as ClientContext, siteInfo.Alias).GetAwaiter().GetResult(); if (groupSiteInfo == null) { WriteMessage($"Creating Team Site {siteInfo.Alias}", ProvisioningMessageType.Progress); siteContext = Sites.SiteCollection.Create(tenant.Context as ClientContext, siteInfo); } else { if (groupSiteInfo.ContainsKey("siteUrl")) { WriteMessage($"Using existing Team Site {siteInfo.Alias}", ProvisioningMessageType.Progress); siteContext = (tenant.Context as ClientContext).Clone(groupSiteInfo["siteUrl"], applyingInformation.AccessTokens); } } if (t.IsHubSite) { RegisterAsHubSite(tenant, siteContext.Url, t.HubSiteLogoUrl); } if (!string.IsNullOrEmpty(t.Theme)) { var parsedTheme = tokenParser.ParseString(t.Theme); tenant.SetWebTheme(parsedTheme, siteContext.Url); tenant.Context.ExecuteQueryRetry(); } siteUrls.Add(t.Id, siteContext.Url); if (!string.IsNullOrEmpty(t.ProvisioningId)) { _additionalTokens.Add(new SequenceSiteUrlUrlToken(null, t.ProvisioningId, siteContext.Url)); } break; } case CommunicationSiteCollection c: { var siteUrl = tokenParser.ParseString(c.Url); if (!siteUrl.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase)) { var rootSiteUrl = tenant.GetRootSiteUrl(); tenant.Context.ExecuteQueryRetry(); siteUrl = UrlUtility.Combine(rootSiteUrl.Value, siteUrl); } CommunicationSiteCollectionCreationInformation siteInfo = new CommunicationSiteCollectionCreationInformation() { AllowFileSharingForGuestUsers = c.AllowFileSharingForGuestUsers, Classification = tokenParser.ParseString(c.Classification), Description = tokenParser.ParseString(c.Description), Lcid = (uint)c.Language, Owner = tokenParser.ParseString(c.Owner), Title = tokenParser.ParseString(c.Title), Url = siteUrl }; if (Guid.TryParse(c.SiteDesign, out Guid siteDesignId)) { siteInfo.SiteDesignId = siteDesignId; } else { if (!string.IsNullOrEmpty(c.SiteDesign)) { siteInfo.SiteDesign = (CommunicationSiteDesign)Enum.Parse(typeof(CommunicationSiteDesign), c.SiteDesign); } else { siteInfo.SiteDesign = CommunicationSiteDesign.Showcase; } } // check if site exists if (tenant.SiteExists(siteInfo.Url)) { WriteMessage($"Using existing Communications Site at {siteInfo.Url}", ProvisioningMessageType.Progress); siteContext = (tenant.Context as ClientContext).Clone(siteInfo.Url, applyingInformation.AccessTokens); } else { WriteMessage($"Creating Communications Site at {siteInfo.Url}", ProvisioningMessageType.Progress); siteContext = Sites.SiteCollection.Create(tenant.Context as ClientContext, siteInfo); } if (c.IsHubSite) { RegisterAsHubSite(tenant, siteInfo.Url, c.HubSiteLogoUrl); } if (!string.IsNullOrEmpty(c.Theme)) { var parsedTheme = tokenParser.ParseString(c.Theme); tenant.SetWebTheme(parsedTheme, siteInfo.Url); tenant.Context.ExecuteQueryRetry(); } siteUrls.Add(c.Id, siteInfo.Url); if (!string.IsNullOrEmpty(c.ProvisioningId)) { _additionalTokens.Add(new SequenceSiteUrlUrlToken(null, c.ProvisioningId, siteInfo.Url)); } break; } case TeamNoGroupSiteCollection t: { SiteEntity siteInfo = new SiteEntity() { Lcid = (uint)t.Language, Template = "STS#3", TimeZoneId = t.TimeZoneId, Title = tokenParser.ParseString(t.Title), Url = tokenParser.ParseString(t.Url), SiteOwnerLogin = tokenParser.ParseString(t.Owner), }; WriteMessage($"Creating Team Site with no Office 365 group at {siteInfo.Url}", ProvisioningMessageType.Progress); if (tenant.SiteExists(t.Url)) { WriteMessage($"Using existing Team Site at {siteInfo.Url}", ProvisioningMessageType.Progress); siteContext = (tenant.Context as ClientContext).Clone(t.Url, applyingInformation.AccessTokens); } else { tenant.CreateSiteCollection(siteInfo, false, true); siteContext = tenant.Context.Clone(t.Url, applyingInformation.AccessTokens); } if (t.IsHubSite) { RegisterAsHubSite(tenant, siteContext.Url, t.HubSiteLogoUrl); } if (!string.IsNullOrEmpty(t.Theme)) { var parsedTheme = tokenParser.ParseString(t.Theme); tenant.SetWebTheme(parsedTheme, siteContext.Url); tenant.Context.ExecuteQueryRetry(); } siteUrls.Add(t.Id, siteContext.Url); if (!string.IsNullOrEmpty(t.ProvisioningId)) { _additionalTokens.Add(new SequenceSiteUrlUrlToken(null, t.ProvisioningId, siteContext.Url)); } break; } } var web = siteContext.Web; foreach (var subsite in sitecollection.Sites) { var subSiteObject = (TeamNoGroupSubSite)subsite; web.EnsureProperties(w => w.Webs.IncludeWithDefaultProperties(), w => w.ServerRelativeUrl); siteTokenParser = CreateSubSites(hierarchy, siteTokenParser, sitecollection, siteContext, web, subSiteObject); } } // System.Threading.Thread.Sleep(TimeSpan.FromMinutes(10)); WriteMessage("Applying templates", ProvisioningMessageType.Progress); var provisioningTemplateApplyingInformation = new ProvisioningTemplateApplyingInformation(); provisioningTemplateApplyingInformation.AccessTokens = applyingInformation.AccessTokens; provisioningTemplateApplyingInformation.MessagesDelegate = applyingInformation.MessagesDelegate; provisioningTemplateApplyingInformation.ProgressDelegate = applyingInformation.ProgressDelegate; foreach (var sitecollection in sequence.SiteCollections) { siteUrls.TryGetValue(sitecollection.Id, out string siteUrl); if (siteUrl != null) { using (var clonedContext = tenant.Context.Clone(siteUrl, applyingInformation.AccessTokens)) { var web = clonedContext.Web; foreach (var templateRef in sitecollection.Templates) { var provisioningTemplate = hierarchy.Templates.FirstOrDefault(t => t.Id == templateRef); if (provisioningTemplate != null) { provisioningTemplate.Connector = hierarchy.Connector; if (siteTokenParser == null) { siteTokenParser = new TokenParser(web, provisioningTemplate, applyingInformation); foreach (var token in _additionalTokens) { siteTokenParser.AddToken(token); } } else { siteTokenParser.Rebase(web, provisioningTemplate); } WriteMessage($"Applying Template", ProvisioningMessageType.Progress); new SiteToTemplateConversion().ApplyRemoteTemplate(web, provisioningTemplate, provisioningTemplateApplyingInformation, true, siteTokenParser); } else { WriteMessage($"Referenced template ID {templateRef} not found", ProvisioningMessageType.Error); } } if (siteTokenParser == null) { siteTokenParser = new TokenParser(tenant, hierarchy, applyingInformation); foreach (var token in _additionalTokens) { siteTokenParser.AddToken(token); } } foreach (var subsite in sitecollection.Sites) { var subSiteObject = (TeamNoGroupSubSite)subsite; web.EnsureProperties(w => w.Webs.IncludeWithDefaultProperties(), w => w.ServerRelativeUrl); siteTokenParser = ApplySubSiteTemplates(hierarchy, siteTokenParser, sitecollection, clonedContext, web, subSiteObject, provisioningTemplateApplyingInformation); } } } } } return(tokenParser); } }
private Tuple<List, TokenParser> UpdateList(Web web, List existingList, ListInstance templateList, TokenParser parser, PnPMonitoredScope scope, bool isNoScriptSite = false) { web.Context.Load(existingList, l => l.Title, l => l.Description, l => l.OnQuickLaunch, l => l.Hidden, l => l.ContentTypesEnabled, l => l.EnableAttachments, l => l.EnableVersioning, l => l.EnableFolderCreation, l => l.EnableModeration, l => l.EnableMinorVersions, l => l.ForceCheckout, l => l.DraftVersionVisibility, l => l.Views, l => l.DocumentTemplateUrl, l => l.RootFolder, l => l.BaseType, l => l.BaseTemplate #if !SP2013 , l => l.MajorWithMinorVersionsLimit , l => l.MajorVersionLimit #endif ); web.Context.ExecuteQueryRetry(); if (existingList.BaseTemplate == templateList.TemplateType) { var isDirty = false; if (parser.ParseString(templateList.Title) != existingList.Title) { var oldTitle = existingList.Title; existingList.Title = parser.ParseString(templateList.Title); if (!oldTitle.Equals(existingList.Title, StringComparison.OrdinalIgnoreCase)) { parser.AddToken(new ListIdToken(web, existingList.Title, existingList.Id)); parser.AddToken(new ListUrlToken(web, existingList.Title, existingList.RootFolder.ServerRelativeUrl.Substring(web.ServerRelativeUrl.Length + 1))); } isDirty = true; } if (!string.IsNullOrEmpty(templateList.DocumentTemplate)) { if (existingList.DocumentTemplateUrl != parser.ParseString(templateList.DocumentTemplate)) { existingList.DocumentTemplateUrl = parser.ParseString(templateList.DocumentTemplate); isDirty = true; } } if (!string.IsNullOrEmpty(templateList.Description) && templateList.Description != existingList.Description) { existingList.Description = templateList.Description; isDirty = true; } if (templateList.Hidden != existingList.Hidden) { existingList.Hidden = templateList.Hidden; isDirty = true; } if (templateList.OnQuickLaunch != existingList.OnQuickLaunch) { existingList.OnQuickLaunch = templateList.OnQuickLaunch; isDirty = true; } if (existingList.BaseTemplate != (int)ListTemplateType.Survey && templateList.ContentTypesEnabled != existingList.ContentTypesEnabled) { existingList.ContentTypesEnabled = templateList.ContentTypesEnabled; isDirty = true; } if (existingList.BaseTemplate != (int)ListTemplateType.Survey && existingList.BaseTemplate != (int)ListTemplateType.DocumentLibrary && existingList.BaseTemplate != (int)ListTemplateType.PictureLibrary) { // https://msdn.microsoft.com/EN-US/library/microsoft.sharepoint.splist.enableattachments.aspx // The EnableAttachments property does not apply to any list that has a base type of Survey, DocumentLibrary or PictureLibrary. // If you set this property to true for either type of list, it throws an SPException. if (templateList.EnableAttachments != existingList.EnableAttachments) { existingList.EnableAttachments = templateList.EnableAttachments; isDirty = true; } } if (existingList.BaseTemplate != (int)ListTemplateType.DiscussionBoard) { if (templateList.EnableFolderCreation != existingList.EnableFolderCreation) { existingList.EnableFolderCreation = templateList.EnableFolderCreation; isDirty = true; } } #if !SP2013 if (templateList.Title.ContainsResourceToken()) { if (existingList.TitleResource.SetUserResourceValue(templateList.Title, parser)) { isDirty = true; } } #endif if (existingList.EnableModeration != templateList.EnableModeration) { existingList.EnableModeration = templateList.EnableModeration; isDirty = true; } if (templateList.ForceCheckout != existingList.ForceCheckout) { existingList.ForceCheckout = templateList.ForceCheckout; isDirty = true; } if (templateList.EnableVersioning) { if (existingList.EnableVersioning != templateList.EnableVersioning) { existingList.EnableVersioning = templateList.EnableVersioning; isDirty = true; } #if !SP2013 if (existingList.MajorVersionLimit != templateList.MaxVersionLimit) { existingList.MajorVersionLimit = templateList.MaxVersionLimit; isDirty = true; } #endif if (existingList.BaseType == BaseType.DocumentLibrary) { // Only supported on Document Libraries if (templateList.EnableMinorVersions != existingList.EnableMinorVersions) { existingList.EnableMinorVersions = templateList.EnableMinorVersions; isDirty = true; } if ((DraftVisibilityType)templateList.DraftVersionVisibility != existingList.DraftVersionVisibility) { existingList.DraftVersionVisibility = (DraftVisibilityType)templateList.DraftVersionVisibility; isDirty = true; } if (templateList.EnableMinorVersions) { if (templateList.MinorVersionLimit != existingList.MajorWithMinorVersionsLimit) { existingList.MajorWithMinorVersionsLimit = templateList.MinorVersionLimit; } if (DraftVisibilityType.Approver == (DraftVisibilityType)templateList.DraftVersionVisibility) { if (templateList.EnableModeration) { if ((DraftVisibilityType)templateList.DraftVersionVisibility != existingList.DraftVersionVisibility) { existingList.DraftVersionVisibility = (DraftVisibilityType)templateList.DraftVersionVisibility; isDirty = true; } } } else { if ((DraftVisibilityType)templateList.DraftVersionVisibility != existingList.DraftVersionVisibility) { existingList.DraftVersionVisibility = (DraftVisibilityType)templateList.DraftVersionVisibility; isDirty = true; } } } } } else { if (existingList.EnableVersioning != templateList.EnableVersioning) { existingList.EnableVersioning = templateList.EnableVersioning; isDirty = true; } } if (isDirty) { existingList.Update(); web.Context.ExecuteQueryRetry(); isDirty = false; } #region UserCustomActions if (!isNoScriptSite) { // Add any UserCustomActions var existingUserCustomActions = existingList.UserCustomActions; web.Context.Load(existingUserCustomActions); web.Context.ExecuteQueryRetry(); foreach (CustomAction userCustomAction in templateList.UserCustomActions) { // Check for existing custom actions before adding (compare by custom action name) if (!existingUserCustomActions.AsEnumerable().Any(uca => uca.Name == userCustomAction.Name)) { CreateListCustomAction(existingList, parser, userCustomAction); isDirty = true; } else { var existingCustomAction = existingUserCustomActions.AsEnumerable().FirstOrDefault(uca => uca.Name == userCustomAction.Name); if (existingCustomAction != null) { isDirty = true; // If the custom action already exists if (userCustomAction.Remove) { // And if we need to remove it, we simply delete it existingCustomAction.DeleteObject(); } else { // Otherwise we update it, and before we force the target // registration type and ID to avoid issues userCustomAction.RegistrationType = UserCustomActionRegistrationType.List; userCustomAction.RegistrationId = existingList.Id.ToString("B").ToUpper(); ObjectCustomActions.UpdateCustomAction(parser, scope, userCustomAction, existingCustomAction); // Blank out these values again to avoid inconsistent domain model data userCustomAction.RegistrationType = UserCustomActionRegistrationType.None; userCustomAction.RegistrationId = null; } } } } if (isDirty) { existingList.Update(); web.Context.ExecuteQueryRetry(); isDirty = false; } } else { scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstances_SkipAddingOrUpdatingCustomActions); } #endregion if (existingList.ContentTypesEnabled) { // Check if we need to add a content type var existingContentTypes = existingList.ContentTypes; web.Context.Load(existingContentTypes, cts => cts.Include(ct => ct.StringId)); web.Context.ExecuteQueryRetry(); var bindingsToAdd = templateList.ContentTypeBindings.Where(ctb => existingContentTypes.All(ct => !ctb.ContentTypeId.Equals(ct.StringId, StringComparison.InvariantCultureIgnoreCase))).ToList(); var defaultCtBinding = templateList.ContentTypeBindings.FirstOrDefault(ctb => ctb.Default == true); var currentDefaultContentTypeId = existingContentTypes.First().StringId; foreach (var ctb in bindingsToAdd) { var tempCT = web.GetContentTypeById(ctb.ContentTypeId, searchInSiteHierarchy: true); if (tempCT != null) { // Get the name of the existing CT var name = tempCT.EnsureProperty(ct => ct.Name); // If the CT does not exist in the target list, and we don't have to remove it if (!existingList.ContentTypeExistsByName(name) && !ctb.Remove) { existingList.AddContentTypeToListById(ctb.ContentTypeId, searchContentTypeInSiteHierarchy: true); } // Else if the CT exists in the target list, and we have to remove it else if (existingList.ContentTypeExistsByName(name) && ctb.Remove) { // Then remove it from the target list existingList.RemoveContentTypeByName(name); } } } // default ContentTypeBinding should be set last because // list extension .SetDefaultContentTypeToList() re-sets // the list.RootFolder UniqueContentTypeOrder property // which may cause missing CTs from the "New Button" if (defaultCtBinding != null) { // Only update the defualt contenttype when we detect a change in default value if (!currentDefaultContentTypeId.Equals(defaultCtBinding.ContentTypeId, StringComparison.InvariantCultureIgnoreCase)) { existingList.SetDefaultContentTypeToList(defaultCtBinding.ContentTypeId); } } } if (templateList.Security != null) { existingList.SetSecurity(parser, templateList.Security); } return Tuple.Create(existingList, parser); } else { scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstances_List__0____1____2___exists_but_is_of_a_different_type__Skipping_list_, templateList.Title, templateList.Url, existingList.Id); WriteWarning(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_List__0____1____2___exists_but_is_of_a_different_type__Skipping_list_, templateList.Title, templateList.Url, existingList.Id), ProvisioningMessageType.Warning); return null; } }
public override void ProvisionObjects(Web web, ProvisioningTemplate template) { Log.Info(Constants.LOGGING_SOURCE_FRAMEWORK_PROVISIONING, CoreResources.Provisioning_ObjectHandlers_ListInstances); if (template.Lists.Any()) { var rootWeb = (web.Context as ClientContext).Site.RootWeb; if (!web.IsPropertyAvailable("ServerRelativeUrl")) { web.Context.Load(web, w => w.ServerRelativeUrl); web.Context.ExecuteQueryRetry(); } web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl)); web.Context.ExecuteQueryRetry(); var existingLists = web.Lists.AsEnumerable <List>().Select(existingList => existingList.RootFolder.ServerRelativeUrl).ToList(); var serverRelativeUrl = web.ServerRelativeUrl; var createdLists = new List <ListInfo>(); #region Lists foreach (var list in template.Lists) { if (existingLists.FindIndex(x => x.Equals(UrlUtility.Combine(serverRelativeUrl, list.Url), StringComparison.OrdinalIgnoreCase)) == -1) { var listCreate = new ListCreationInformation(); listCreate.Description = list.Description; listCreate.TemplateType = list.TemplateType; listCreate.Title = list.Title; // the line of code below doesn't add the list to QuickLaunch // the OnQuickLaunch property is re-set on the Created List object listCreate.QuickLaunchOption = list.OnQuickLaunch ? QuickLaunchOptions.On : QuickLaunchOptions.Off; listCreate.Url = list.Url.ToParsedString(); listCreate.TemplateFeatureId = list.TemplateFeatureID; var createdList = web.Lists.Add(listCreate); createdList.Update(); web.Context.Load(createdList, l => l.BaseTemplate); web.Context.ExecuteQueryRetry(); if (!String.IsNullOrEmpty(list.DocumentTemplate)) { createdList.DocumentTemplateUrl = list.DocumentTemplate.ToParsedString(); } // EnableAttachments are not supported for DocumentLibraries and Surveys // TODO: the user should be warned if (createdList.BaseTemplate != (int)ListTemplateType.DocumentLibrary && createdList.BaseTemplate != (int)ListTemplateType.Survey) { createdList.EnableAttachments = list.EnableAttachments; } createdList.EnableModeration = list.EnableModeration; createdList.EnableVersioning = list.EnableVersioning; if (list.EnableVersioning) { createdList.MajorVersionLimit = list.MaxVersionLimit; if (createdList.BaseTemplate == (int)ListTemplateType.DocumentLibrary) { // Only supported on Document Libraries createdList.EnableMinorVersions = list.EnableMinorVersions; createdList.DraftVersionVisibility = (DraftVisibilityType)list.DraftVersionVisibility; // TODO: User should be notified that MinorVersionLimit and DraftVersionVisibility will not be applied if (list.EnableMinorVersions) { createdList.MajorWithMinorVersionsLimit = list.MinorVersionLimit; // Set only if enabled, otherwise you'll get exception due setting value to zero. // DraftVisibilityType.Approver is available only when the EnableModeration option of the list is true if (DraftVisibilityType.Approver == (DraftVisibilityType)list.DraftVersionVisibility) { if (list.EnableModeration) { createdList.DraftVersionVisibility = (DraftVisibilityType)list.DraftVersionVisibility; } else { // TODO: User should be notified that DraftVersionVisibility is not applied because .EnableModeration is false } } else { createdList.DraftVersionVisibility = (DraftVisibilityType)list.DraftVersionVisibility; } } } } createdList.OnQuickLaunch = list.OnQuickLaunch; if (createdList.BaseTemplate != (int)ListTemplateType.DiscussionBoard) { createdList.EnableFolderCreation = list.EnableFolderCreation; } createdList.Hidden = list.Hidden; createdList.ContentTypesEnabled = list.ContentTypesEnabled; createdList.Update(); web.Context.Load(createdList.Views); web.Context.Load(createdList, l => l.Id); web.Context.Load(createdList, l => l.RootFolder.ServerRelativeUrl); web.Context.Load(createdList.ContentTypes); web.Context.ExecuteQueryRetry(); // Remove existing content types only if there are custom content type bindings List <Microsoft.SharePoint.Client.ContentType> contentTypesToRemove = new List <Microsoft.SharePoint.Client.ContentType>(); if (list.RemoveExistingContentTypes && list.ContentTypeBindings.Count > 0) { foreach (var ct in createdList.ContentTypes) { contentTypesToRemove.Add(ct); } } ContentTypeBinding defaultCtBinding = null; foreach (var ctBinding in list.ContentTypeBindings) { createdList.AddContentTypeToListById(ctBinding.ContentTypeId, searchContentTypeInSiteHierarchy: true); if (ctBinding.Default) { defaultCtBinding = ctBinding; } } // default ContentTypeBinding should be set last because // list extension .SetDefaultContentTypeToList() re-sets // the list.RootFolder UniqueContentTypeOrder property // which may cause missing CTs from the "New Button" if (defaultCtBinding != null) { createdList.SetDefaultContentTypeToList(defaultCtBinding.ContentTypeId); } // Effectively remove existing content types, if any foreach (var ct in contentTypesToRemove) { ct.DeleteObject(); web.Context.ExecuteQueryRetry(); } createdLists.Add(new ListInfo { CreatedList = createdList, ListInstance = list }); TokenParser.AddToken(new ListIdToken(web, list.Title, createdList.Id)); TokenParser.AddToken(new ListUrlToken(web, list.Title, createdList.RootFolder.ServerRelativeUrl.Substring(web.ServerRelativeUrl.Length + 1))); } } #endregion #region FieldRefs foreach (var listInfo in createdLists) { if (listInfo.ListInstance.FieldRefs.Any()) { foreach (var fieldRef in listInfo.ListInstance.FieldRefs) { var field = rootWeb.GetFieldById <Field>(fieldRef.Id); if (field != null) { if (!listInfo.CreatedList.FieldExistsById(fieldRef.Id)) { var createdField = listInfo.CreatedList.Fields.Add(field); if (!string.IsNullOrEmpty(fieldRef.DisplayName)) { createdField.Title = fieldRef.DisplayName; } createdField.Hidden = fieldRef.Hidden; createdField.Required = fieldRef.Required; createdField.Update(); } } } listInfo.CreatedList.Update(); web.Context.ExecuteQueryRetry(); } } #endregion #region Fields foreach (var listInfo in createdLists) { if (listInfo.ListInstance.Fields.Any()) { foreach (var field in listInfo.ListInstance.Fields) { XElement fieldElement = XElement.Parse(field.SchemaXml.ToParsedString()); var id = fieldElement.Attribute("ID").Value; Guid fieldGuid = Guid.Empty; if (Guid.TryParse(id, out fieldGuid)) { if (!listInfo.CreatedList.FieldExistsById(fieldGuid)) { var listIdentifier = fieldElement.Attribute("List") != null?fieldElement.Attribute("List").Value : null; if (listIdentifier != null) { // Temporary remove list attribute from fieldElement fieldElement.Attribute("List").Remove(); } var fieldXml = fieldElement.ToString(); listInfo.CreatedList.Fields.AddFieldAsXml(fieldXml, false, AddFieldOptions.DefaultValue); } } } } listInfo.CreatedList.Update(); web.Context.ExecuteQueryRetry(); } #endregion #region Views foreach (var listInfo in createdLists) { var list = listInfo.ListInstance; var createdList = listInfo.CreatedList; if (list.Views.Any() && list.RemoveExistingViews) { while (createdList.Views.Any()) { createdList.Views[0].DeleteObject(); } web.Context.ExecuteQueryRetry(); } foreach (var view in list.Views) { var viewDoc = XDocument.Parse(view.SchemaXml); var displayNameXml = viewDoc.Root.Attribute("DisplayName"); if (displayNameXml == null) { throw new ApplicationException("Invalid View element, missing a valid value for the attribute DisplayName."); } var viewTitle = displayNameXml.Value; // Type var viewTypeString = viewDoc.Root.Attribute("Type") != null?viewDoc.Root.Attribute("Type").Value : "None"; viewTypeString = viewTypeString[0].ToString().ToUpper() + viewTypeString.Substring(1).ToLower(); var viewType = (ViewType)Enum.Parse(typeof(ViewType), viewTypeString); // Fields string[] viewFields = null; var viewFieldsElement = viewDoc.Descendants("ViewFields").FirstOrDefault(); if (viewFieldsElement != null) { viewFields = (from field in viewDoc.Descendants("ViewFields").Descendants("FieldRef") select field.Attribute("Name").Value).ToArray(); } // Default view var viewDefault = viewDoc.Root.Attribute("DefaultView") != null && Boolean.Parse(viewDoc.Root.Attribute("DefaultView").Value); // Row limit bool viewPaged = true; uint viewRowLimit = 30; var rowLimitElement = viewDoc.Descendants("RowLimit").FirstOrDefault(); if (rowLimitElement != null) { if (rowLimitElement.Attribute("Paged") != null) { viewPaged = bool.Parse(rowLimitElement.Attribute("Paged").Value); } viewRowLimit = uint.Parse(rowLimitElement.Value); } // Query var viewQuery = new StringBuilder(); foreach (var queryElement in viewDoc.Descendants("Query").Elements()) { viewQuery.Append(queryElement.ToString()); } var viewCI = new ViewCreationInformation { ViewFields = viewFields, RowLimit = viewRowLimit, Paged = viewPaged, Title = viewTitle, Query = viewQuery.ToString(), ViewTypeKind = viewType, PersonalView = false, SetAsDefaultView = viewDefault }; createdList.Views.Add(viewCI); createdList.Update(); web.Context.ExecuteQueryRetry(); } // Removing existing views set the OnQuickLaunch option to false and need to be re-set. if (list.OnQuickLaunch && list.RemoveExistingViews && list.Views.Count > 0) { createdList.RefreshLoad(); web.Context.ExecuteQueryRetry(); createdList.OnQuickLaunch = list.OnQuickLaunch; createdList.Update(); web.Context.ExecuteQueryRetry(); } } #endregion #region DataRows foreach (var listInfo in createdLists) { var listInstance = listInfo.ListInstance; if (listInstance.DataRows != null && listInstance.DataRows.Any()) { var list = listInfo.CreatedList; foreach (var dataRow in listInfo.ListInstance.DataRows) { ListItemCreationInformation listitemCI = new ListItemCreationInformation(); var listitem = list.AddItem(listitemCI); foreach (var dataValue in dataRow.Values) { listitem[dataValue.Key.ToParsedString()] = dataValue.Value.ToParsedString(); } listitem.Update(); web.Context.ExecuteQueryRetry(); // TODO: Run in batches? } } } #endregion } }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { // Changed by Paolo Pialorsi to embrace the new sub-site attributes to break role inheritance and copy role assignments // if this is a sub site then we're not provisioning security as by default security is inherited from the root site //if (web.IsSubSite() && !template.Security.BreakRoleInheritance) //{ // scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_SiteSecurity_Context_web_is_subweb__skipping_site_security_provisioning); // return parser; //} if (web.IsSubSite() && template.Security.BreakRoleInheritance) { web.BreakRoleInheritance(template.Security.CopyRoleAssignments, template.Security.ClearSubscopes); web.Update(); web.Context.ExecuteQueryRetry(); } var siteSecurity = template.Security; var ownerGroup = web.AssociatedOwnerGroup; var memberGroup = web.AssociatedMemberGroup; var visitorGroup = web.AssociatedVisitorGroup; web.Context.Load(ownerGroup, o => o.Title, o => o.Users); web.Context.Load(memberGroup, o => o.Title, o => o.Users); web.Context.Load(visitorGroup, o => o.Title, o => o.Users); web.Context.Load(web.SiteUsers); web.Context.ExecuteQueryRetry(); if (!ownerGroup.ServerObjectIsNull()) { AddUserToGroup(web, ownerGroup, siteSecurity.AdditionalOwners, scope, parser); } if (!memberGroup.ServerObjectIsNull()) { AddUserToGroup(web, memberGroup, siteSecurity.AdditionalMembers, scope, parser); } if (!visitorGroup.ServerObjectIsNull()) { AddUserToGroup(web, visitorGroup, siteSecurity.AdditionalVisitors, scope, parser); } foreach (var siteGroup in siteSecurity.SiteGroups) { Group group; var allGroups = web.Context.LoadQuery(web.SiteGroups.Include(gr => gr.LoginName)); web.Context.ExecuteQueryRetry(); string parsedGroupTitle = parser.ParseString(siteGroup.Title); string parsedGroupOwner = parser.ParseString(siteGroup.Owner); string parsedGroupDescription = parser.ParseString(siteGroup.Description); if (!web.GroupExists(parsedGroupTitle)) { scope.LogDebug("Creating group {0}", parsedGroupTitle); group = web.AddGroup( parsedGroupTitle, parsedGroupDescription, parsedGroupTitle == parsedGroupOwner); group.AllowMembersEditMembership = siteGroup.AllowMembersEditMembership; group.AllowRequestToJoinLeave = siteGroup.AllowRequestToJoinLeave; group.AutoAcceptRequestToJoinLeave = siteGroup.AutoAcceptRequestToJoinLeave; if (parsedGroupTitle != parsedGroupOwner) { Principal ownerPrincipal = allGroups.FirstOrDefault(gr => gr.LoginName == parsedGroupOwner); if (ownerPrincipal == null) { ownerPrincipal = web.EnsureUser(parsedGroupOwner); } group.Owner = ownerPrincipal; } group.Update(); web.Context.Load(group, g => g.Id, g => g.Title); web.Context.ExecuteQueryRetry(); parser.AddToken(new GroupIdToken(web, group.Title, group.Id)); } else { group = web.SiteGroups.GetByName(parsedGroupTitle); web.Context.Load(group, g => g.Title, g => g.Description, g => g.AllowMembersEditMembership, g => g.AllowRequestToJoinLeave, g => g.AutoAcceptRequestToJoinLeave, g => g.Owner.LoginName); web.Context.ExecuteQueryRetry(); var isDirty = false; if (!String.IsNullOrEmpty(group.Description) && group.Description != parsedGroupDescription) { group.Description = parsedGroupDescription; isDirty = true; } if (group.AllowMembersEditMembership != siteGroup.AllowMembersEditMembership) { group.AllowMembersEditMembership = siteGroup.AllowMembersEditMembership; isDirty = true; } if (group.AllowRequestToJoinLeave != siteGroup.AllowRequestToJoinLeave) { group.AllowRequestToJoinLeave = siteGroup.AllowRequestToJoinLeave; isDirty = true; } if (group.AutoAcceptRequestToJoinLeave != siteGroup.AutoAcceptRequestToJoinLeave) { group.AutoAcceptRequestToJoinLeave = siteGroup.AutoAcceptRequestToJoinLeave; isDirty = true; } if (group.Owner.LoginName != parsedGroupOwner) { if (parsedGroupTitle != parsedGroupOwner) { Principal ownerPrincipal = allGroups.FirstOrDefault(gr => gr.LoginName == parsedGroupOwner); if (ownerPrincipal == null) { ownerPrincipal = web.EnsureUser(parsedGroupOwner); } group.Owner = ownerPrincipal; } else { group.Owner = group; } isDirty = true; } if (isDirty) { scope.LogDebug("Updating existing group {0}", group.Title); group.Update(); web.Context.ExecuteQueryRetry(); } } if (group != null && siteGroup.Members.Any()) { AddUserToGroup(web, group, siteGroup.Members, scope, parser); } } foreach (var admin in siteSecurity.AdditionalAdministrators) { var parsedAdminName = parser.ParseString(admin.Name); try { var user = web.EnsureUser(parsedAdminName); user.IsSiteAdmin = true; user.Update(); web.Context.ExecuteQueryRetry(); } catch (Exception ex) { scope.LogWarning(ex, "Failed to add AdditionalAdministrator {0}", parsedAdminName); } } // With the change from october, manage permission levels on subsites as well if (siteSecurity.SiteSecurityPermissions != null) { var existingRoleDefinitions = web.Context.LoadQuery(web.RoleDefinitions.Include(wr => wr.Name, wr => wr.BasePermissions, wr => wr.Description)); web.Context.ExecuteQueryRetry(); if (siteSecurity.SiteSecurityPermissions.RoleDefinitions.Any()) { foreach (var templateRoleDefinition in siteSecurity.SiteSecurityPermissions.RoleDefinitions) { var roleDefinitions = existingRoleDefinitions as RoleDefinition[] ?? existingRoleDefinitions.ToArray(); var siteRoleDefinition = roleDefinitions.FirstOrDefault(erd => erd.Name == parser.ParseString(templateRoleDefinition.Name)); if (siteRoleDefinition == null) { scope.LogDebug("Creating role definition {0}", parser.ParseString(templateRoleDefinition.Name)); var roleDefinitionCI = new RoleDefinitionCreationInformation(); roleDefinitionCI.Name = parser.ParseString(templateRoleDefinition.Name); roleDefinitionCI.Description = parser.ParseString(templateRoleDefinition.Description); BasePermissions basePermissions = new BasePermissions(); foreach (var permission in templateRoleDefinition.Permissions) { basePermissions.Set(permission); } roleDefinitionCI.BasePermissions = basePermissions; web.RoleDefinitions.Add(roleDefinitionCI); web.Context.ExecuteQueryRetry(); } else { var isDirty = false; if (siteRoleDefinition.Description != parser.ParseString(templateRoleDefinition.Description)) { siteRoleDefinition.Description = parser.ParseString(templateRoleDefinition.Description); isDirty = true; } var templateBasePermissions = new BasePermissions(); templateRoleDefinition.Permissions.ForEach(p => templateBasePermissions.Set(p)); if (siteRoleDefinition.BasePermissions != templateBasePermissions) { isDirty = true; foreach (var permission in templateRoleDefinition.Permissions) { siteRoleDefinition.BasePermissions.Set(permission); } } if (isDirty) { scope.LogDebug("Updating role definition {0}", parser.ParseString(templateRoleDefinition.Name)); siteRoleDefinition.Update(); web.Context.ExecuteQueryRetry(); } } } } var webRoleDefinitions = web.Context.LoadQuery(web.RoleDefinitions); var groups = web.Context.LoadQuery(web.SiteGroups.Include(g => g.LoginName)); web.Context.ExecuteQueryRetry(); if (siteSecurity.SiteSecurityPermissions.RoleAssignments.Any()) { foreach (var roleAssignment in siteSecurity.SiteSecurityPermissions.RoleAssignments) { var roleDefinition = webRoleDefinitions.FirstOrDefault(r => r.Name == parser.ParseString(roleAssignment.RoleDefinition)); if (roleDefinition != null) { Principal principal = groups.FirstOrDefault(g => g.LoginName == parser.ParseString(roleAssignment.Principal)); if (principal == null) { var parsedUser = parser.ParseString(roleAssignment.Principal); if (parsedUser.Contains("#ext#")) { principal = web.SiteUsers.FirstOrDefault(u => u.LoginName.Equals(parsedUser)); if (principal == null) { scope.LogInfo($"Skipping external user {parsedUser}"); } } else { try { principal = web.EnsureUser(parsedUser); web.Context.ExecuteQueryRetry(); } catch (Exception ex) { scope.LogWarning(ex, "Failed to EnsureUser {0}", parsedUser); } } } if (principal != null) { var roleDefinitionBindingCollection = new RoleDefinitionBindingCollection(web.Context); roleDefinitionBindingCollection.Add(roleDefinition); web.RoleAssignments.Add(principal, roleDefinitionBindingCollection); web.Context.ExecuteQueryRetry(); } } else { scope.LogWarning("Role assignment {0} not found in web", roleAssignment.RoleDefinition); } } } } } return(parser); }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { // Changed by Paolo Pialorsi to embrace the new sub-site attributes to break role inheritance and copy role assignments // if this is a sub site then we're not provisioning security as by default security is inherited from the root site //if (web.IsSubSite() && !template.Security.BreakRoleInheritance) //{ // scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_SiteSecurity_Context_web_is_subweb__skipping_site_security_provisioning); // return parser; //} if (web.IsSubSite() && template.Security.BreakRoleInheritance) { web.BreakRoleInheritance(template.Security.CopyRoleAssignments, template.Security.ClearSubscopes); web.Update(); web.Context.ExecuteQueryRetry(); } var siteSecurity = template.Security; var ownerGroup = web.AssociatedOwnerGroup; var memberGroup = web.AssociatedMemberGroup; var visitorGroup = web.AssociatedVisitorGroup; web.Context.Load(ownerGroup, o => o.Title, o => o.Users); web.Context.Load(memberGroup, o => o.Title, o => o.Users); web.Context.Load(visitorGroup, o => o.Title, o => o.Users); web.Context.Load(web.SiteUsers); web.Context.ExecuteQueryRetry(); if (!ownerGroup.ServerObjectIsNull()) { AddUserToGroup(web, ownerGroup, siteSecurity.AdditionalOwners, scope, parser); } if (!memberGroup.ServerObjectIsNull()) { AddUserToGroup(web, memberGroup, siteSecurity.AdditionalMembers, scope, parser); } if (!visitorGroup.ServerObjectIsNull()) { AddUserToGroup(web, visitorGroup, siteSecurity.AdditionalVisitors, scope, parser); } //sorting groups with respect to possible dependency through Owner property. Groups that are owners of other groups must be processed prior owned groups. for (int i = 0; i < siteSecurity.SiteGroups.Count; i++) { var currentGroup = siteSecurity.SiteGroups[i]; string currentGroupOwner = currentGroup.Owner; string currentGroupTitle = parser.ParseString(currentGroup.Title); if (currentGroupOwner != "SHAREPOINT\\system" && currentGroupOwner != currentGroupTitle && !(currentGroupOwner.StartsWith("{{associated") && currentGroupOwner.EndsWith("group}}"))) { for (int j = i + 1; j < siteSecurity.SiteGroups.Count; j++) { if (siteSecurity.SiteGroups[j].Title == currentGroupOwner) { siteSecurity.SiteGroups.Insert(i, siteSecurity.SiteGroups[j]); siteSecurity.SiteGroups.RemoveAt(j); i--; break; } } } } foreach (var siteGroup in siteSecurity.SiteGroups) { Group group; var allGroups = web.Context.LoadQuery(web.SiteGroups.Include(gr => gr.LoginName)); web.Context.ExecuteQueryRetry(); string parsedGroupTitle = parser.ParseString(siteGroup.Title); string parsedGroupOwner = parser.ParseString(siteGroup.Owner); string parsedGroupDescription = parser.ParseString(siteGroup.Description); if (!web.GroupExists(parsedGroupTitle)) { scope.LogDebug("Creating group {0}", parsedGroupTitle); group = web.AddGroup( parsedGroupTitle, //If the description is more than 512 characters long a server exception will be thrown. PnPHttpUtility.ConvertSimpleHtmlToText(parsedGroupDescription, int.MaxValue), parsedGroupTitle == parsedGroupOwner); group.AllowMembersEditMembership = siteGroup.AllowMembersEditMembership; group.AllowRequestToJoinLeave = siteGroup.AllowRequestToJoinLeave; group.AutoAcceptRequestToJoinLeave = siteGroup.AutoAcceptRequestToJoinLeave; group.OnlyAllowMembersViewMembership = siteGroup.OnlyAllowMembersViewMembership; group.RequestToJoinLeaveEmailSetting = siteGroup.RequestToJoinLeaveEmailSetting; if (parsedGroupTitle != parsedGroupOwner) { Principal ownerPrincipal = allGroups.FirstOrDefault(gr => gr.LoginName == parsedGroupOwner); if (ownerPrincipal == null) { ownerPrincipal = web.EnsureUser(parsedGroupOwner); } group.Owner = ownerPrincipal; } group.Update(); web.Context.Load(group, g => g.Id, g => g.Title); web.Context.ExecuteQueryRetry(); parser.AddToken(new GroupIdToken(web, group.Title, group.Id)); var groupItem = web.SiteUserInfoList.GetItemById(group.Id); groupItem["Notes"] = parsedGroupDescription; groupItem.Update(); web.Context.ExecuteQueryRetry(); } else { group = web.SiteGroups.GetByName(parsedGroupTitle); web.Context.Load(group, g => g.Id, g => g.Title, g => g.Description, g => g.AllowMembersEditMembership, g => g.AllowRequestToJoinLeave, g => g.AutoAcceptRequestToJoinLeave, g => g.OnlyAllowMembersViewMembership, g => g.RequestToJoinLeaveEmailSetting, g => g.Owner.LoginName); web.Context.ExecuteQueryRetry(); var groupNeedsUpdate = false; var executeQuery = false; if (!String.IsNullOrEmpty(parsedGroupDescription)) { var groupItem = web.SiteUserInfoList.GetItemById(group.Id); web.Context.Load(groupItem, g => g["Notes"]); web.Context.ExecuteQueryRetry(); var description = groupItem["Notes"]?.ToString(); if (description != parsedGroupDescription) { groupItem["Notes"] = parsedGroupDescription; groupItem.Update(); executeQuery = true; } var plainTextDescription = PnPHttpUtility.ConvertSimpleHtmlToText(parsedGroupDescription, int.MaxValue); if (group.Description != plainTextDescription) { //If the description is more than 512 characters long a server exception will be thrown. group.Description = plainTextDescription; groupNeedsUpdate = true; } } if (group.AllowMembersEditMembership != siteGroup.AllowMembersEditMembership) { group.AllowMembersEditMembership = siteGroup.AllowMembersEditMembership; groupNeedsUpdate = true; } if (group.AllowRequestToJoinLeave != siteGroup.AllowRequestToJoinLeave) { group.AllowRequestToJoinLeave = siteGroup.AllowRequestToJoinLeave; groupNeedsUpdate = true; } if (group.AutoAcceptRequestToJoinLeave != siteGroup.AutoAcceptRequestToJoinLeave) { group.AutoAcceptRequestToJoinLeave = siteGroup.AutoAcceptRequestToJoinLeave; groupNeedsUpdate = true; } if (group.OnlyAllowMembersViewMembership != siteGroup.OnlyAllowMembersViewMembership) { group.OnlyAllowMembersViewMembership = siteGroup.OnlyAllowMembersViewMembership; groupNeedsUpdate = true; } if (!String.IsNullOrEmpty(group.RequestToJoinLeaveEmailSetting) && group.RequestToJoinLeaveEmailSetting != siteGroup.RequestToJoinLeaveEmailSetting) { group.RequestToJoinLeaveEmailSetting = siteGroup.RequestToJoinLeaveEmailSetting; groupNeedsUpdate = true; } if (group.Owner.LoginName != parsedGroupOwner) { if (parsedGroupTitle != parsedGroupOwner) { Principal ownerPrincipal = allGroups.FirstOrDefault(gr => gr.LoginName == parsedGroupOwner); if (ownerPrincipal == null) { ownerPrincipal = web.EnsureUser(parsedGroupOwner); } group.Owner = ownerPrincipal; } else { group.Owner = group; } groupNeedsUpdate = true; } if (groupNeedsUpdate) { scope.LogDebug("Updating existing group {0}", group.Title); group.Update(); executeQuery = true; } if (executeQuery) { web.Context.ExecuteQueryRetry(); } } if (group != null && siteGroup.Members.Any()) { AddUserToGroup(web, group, siteGroup.Members, scope, parser); } } foreach (var admin in siteSecurity.AdditionalAdministrators) { var parsedAdminName = parser.ParseString(admin.Name); try { var user = web.EnsureUser(parsedAdminName); user.IsSiteAdmin = true; user.Update(); web.Context.ExecuteQueryRetry(); } catch (Exception ex) { scope.LogWarning(ex, "Failed to add AdditionalAdministrator {0}", parsedAdminName); } } // With the change from october, manage permission levels on subsites as well if (siteSecurity.SiteSecurityPermissions != null) { var existingRoleDefinitions = web.Context.LoadQuery(web.RoleDefinitions.Include(wr => wr.Name, wr => wr.BasePermissions, wr => wr.Description)); web.Context.ExecuteQueryRetry(); if (siteSecurity.SiteSecurityPermissions.RoleDefinitions.Any()) { foreach (var templateRoleDefinition in siteSecurity.SiteSecurityPermissions.RoleDefinitions) { var roleDefinitions = existingRoleDefinitions as RoleDefinition[] ?? existingRoleDefinitions.ToArray(); var parsedRoleDefinitionName = parser.ParseString(templateRoleDefinition.Name); var parsedTemplateRoleDefinitionDesc = parser.ParseString(templateRoleDefinition.Description); var siteRoleDefinition = roleDefinitions.FirstOrDefault(erd => erd.Name == parsedRoleDefinitionName); if (siteRoleDefinition == null) { scope.LogDebug("Creating role definition {0}", parsedRoleDefinitionName); var roleDefinitionCI = new RoleDefinitionCreationInformation(); roleDefinitionCI.Name = parsedRoleDefinitionName; roleDefinitionCI.Description = parsedTemplateRoleDefinitionDesc; BasePermissions basePermissions = new BasePermissions(); foreach (var permission in templateRoleDefinition.Permissions) { basePermissions.Set(permission); } roleDefinitionCI.BasePermissions = basePermissions; var newRoleDefinition = web.RoleDefinitions.Add(roleDefinitionCI); web.Context.Load(newRoleDefinition, nrd => nrd.Name, nrd => nrd.Id); web.Context.ExecuteQueryRetry(); parser.AddToken(new RoleDefinitionIdToken(web, newRoleDefinition.Name, newRoleDefinition.Id)); } else { var isDirty = false; if (siteRoleDefinition.Description != parsedTemplateRoleDefinitionDesc) { siteRoleDefinition.Description = parsedTemplateRoleDefinitionDesc; isDirty = true; } var templateBasePermissions = new BasePermissions(); templateRoleDefinition.Permissions.ForEach(p => templateBasePermissions.Set(p)); if (siteRoleDefinition.BasePermissions != templateBasePermissions) { isDirty = true; foreach (var permission in templateRoleDefinition.Permissions) { siteRoleDefinition.BasePermissions.Set(permission); } } if (isDirty) { scope.LogDebug("Updating role definition {0}", parsedRoleDefinitionName); siteRoleDefinition.Update(); web.Context.ExecuteQueryRetry(); } } } } var webRoleDefinitions = web.Context.LoadQuery(web.RoleDefinitions); var webRoleAssignments = web.Context.LoadQuery(web.RoleAssignments); var groups = web.Context.LoadQuery(web.SiteGroups.Include(g => g.LoginName)); web.Context.ExecuteQueryRetry(); if (siteSecurity.SiteSecurityPermissions.RoleAssignments.Any()) { foreach (var roleAssignment in siteSecurity.SiteSecurityPermissions.RoleAssignments) { var parsedRoleDefinition = parser.ParseString(roleAssignment.RoleDefinition); if (!roleAssignment.Remove) { var roleDefinition = webRoleDefinitions.FirstOrDefault(r => r.Name == parsedRoleDefinition); if (roleDefinition != null) { Principal principal = GetPrincipal(web, parser, scope, groups, roleAssignment); if (principal != null) { var roleDefinitionBindingCollection = new RoleDefinitionBindingCollection(web.Context); roleDefinitionBindingCollection.Add(roleDefinition); web.RoleAssignments.Add(principal, roleDefinitionBindingCollection); web.Context.ExecuteQueryRetry(); } } else { scope.LogWarning("Role assignment {0} not found in web", roleAssignment.RoleDefinition); } } else { var principal = GetPrincipal(web, parser, scope, groups, roleAssignment); var assignmentsForPrincipal = webRoleAssignments.Where(t => t.PrincipalId == principal.Id); foreach (var assignmentForPrincipal in assignmentsForPrincipal) { var binding = assignmentForPrincipal.EnsureProperty(r => r.RoleDefinitionBindings).FirstOrDefault(b => b.Name == parsedRoleDefinition); if (binding != null) { assignmentForPrincipal.DeleteObject(); web.Context.ExecuteQueryRetry(); break; } } } } } } } return(parser); }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { var context = web.Context as ClientContext; web.EnsureProperties(w => w.ServerRelativeUrl, w => w.RootFolder.WelcomePage); // Check if this is not a noscript site as we're not allowed to update some properties bool isNoScriptSite = web.IsNoScriptSite(); foreach (var page in template.Pages) { var url = parser.ParseString(page.Url); if (!url.ToLower().StartsWith(web.ServerRelativeUrl.ToLower())) { url = UrlUtility.Combine(web.ServerRelativeUrl, url); } var exists = true; Microsoft.SharePoint.Client.File file = null; try { file = web.GetFileByServerRelativeUrl(url); web.Context.Load(file); web.Context.ExecuteQueryRetry(); } catch (ServerException ex) { if (ex.ServerErrorTypeName == "System.IO.FileNotFoundException") { exists = false; } } if (exists) { if (page.Overwrite) { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0_, url); // determine url of current home page string welcomePageUrl = web.RootFolder.WelcomePage; string welcomePageServerRelativeUrl = welcomePageUrl != null ? UrlUtility.Combine(web.ServerRelativeUrl, web.RootFolder.WelcomePage) : null; bool overwriteWelcomePage = string.Equals(url, welcomePageServerRelativeUrl, StringComparison.InvariantCultureIgnoreCase); // temporarily reset home page so we can delete it if (overwriteWelcomePage) { web.SetHomePage(string.Empty); } file.DeleteObject(); web.Context.ExecuteQueryRetry(); web.AddWikiPageByUrl(url); if (page.Layout == WikiPageLayout.Custom) { web.AddLayoutToWikiPage(WikiPageLayout.OneColumn, url); } else { web.AddLayoutToWikiPage(page.Layout, url); } if (overwriteWelcomePage) { // restore welcome page to previous value web.SetHomePage(welcomePageUrl); } } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0__failed___1_____2_, url, ex.Message, ex.StackTrace); } } } else { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0_, url); web.AddWikiPageByUrl(url); if (page.Layout == WikiPageLayout.Custom) { web.AddLayoutToWikiPage(WikiPageLayout.OneColumn, url); } else { web.AddLayoutToWikiPage(page.Layout, url); } } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0__failed___1_____2_, url, ex.Message, ex.StackTrace); } } #pragma warning disable 618 if (page.WelcomePage) #pragma warning restore 618 { web.RootFolder.EnsureProperty(p => p.ServerRelativeUrl); var rootFolderRelativeUrl = url.Substring(web.RootFolder.ServerRelativeUrl.Length); web.SetHomePage(rootFolderRelativeUrl); } #if !SP2013 bool webPartsNeedLocalization = false; #endif if (page.WebParts != null & page.WebParts.Any()) { if (!isNoScriptSite) { var existingWebParts = web.GetWebParts(url); foreach (var webPart in page.WebParts) { if (existingWebParts.FirstOrDefault(w => w.WebPart.Title == parser.ParseString(webPart.Title)) == null) { WebPartEntity wpEntity = new WebPartEntity(); wpEntity.WebPartTitle = parser.ParseString(webPart.Title); wpEntity.WebPartXml = parser.ParseXmlStringWebpart(webPart.Contents.Trim(new[] { '\n', ' ' }), web, "~sitecollection", "~site"); var wpd = web.AddWebPartToWikiPage(url, wpEntity, (int)webPart.Row, (int)webPart.Column, false); #if !SP2013 if (webPart.Title.ContainsResourceToken()) { // update data based on where it was added - needed in order to localize wp title #if !SP2016 wpd.EnsureProperties(w => w.ZoneId, w => w.WebPart, w => w.WebPart.Properties); webPart.Zone = wpd.ZoneId; #else wpd.EnsureProperties(w => w.WebPart, w => w.WebPart.Properties); #endif webPart.Order = (uint)wpd.WebPart.ZoneIndex; webPartsNeedLocalization = true; } #endif } } // Remove any existing WebPartIdToken tokens in the parser that were added by other pages. They won't apply to this page, // and they'll cause issues if this page contains web parts with the same name as web parts on other pages. parser.Tokens.RemoveAll(t => t is WebPartIdToken); var allWebParts = web.GetWebParts(url); foreach (var webpart in allWebParts) { parser.AddToken(new WebPartIdToken(web, webpart.WebPart.Title, webpart.Id)); } } else { scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_Pages_SkipAddingWebParts, page.Url); } } #if !SP2013 if (webPartsNeedLocalization) { page.LocalizeWebParts(web, parser, scope); } #endif file = web.GetFileByServerRelativeUrl(url); file.EnsureProperty(f => f.ListItemAllFields); if (page.Fields.Any()) { var item = file.ListItemAllFields; foreach (var fieldValue in page.Fields) { item[fieldValue.Key] = parser.ParseString(fieldValue.Value); } item.Update(); web.Context.ExecuteQueryRetry(); } if (page.Security != null && page.Security.RoleAssignments.Count != 0) { web.Context.Load(file.ListItemAllFields); web.Context.ExecuteQueryRetry(); file.ListItemAllFields.SetSecurity(parser, page.Security); } } } return(parser); }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { var context = web.Context as ClientContext; web.EnsureProperties(w => w.ServerRelativeUrl, w => w.RootFolder.WelcomePage); foreach (var page in template.Pages) { var url = parser.ParseString(page.Url); if (!url.ToLower().StartsWith(web.ServerRelativeUrl.ToLower())) { url = UrlUtility.Combine(web.ServerRelativeUrl, url); } var exists = true; Microsoft.SharePoint.Client.File file = null; try { file = web.GetFileByServerRelativeUrl(url); web.Context.Load(file); web.Context.ExecuteQuery(); } catch (ServerException ex) { if (ex.ServerErrorTypeName == "System.IO.FileNotFoundException") { exists = false; } } if (exists) { if (page.Overwrite) { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0_, url); if (page.WelcomePage && url.Contains(web.RootFolder.WelcomePage)) { web.SetHomePage(string.Empty); } file.DeleteObject(); web.Context.ExecuteQueryRetry(); web.AddWikiPageByUrl(url); if (page.Layout == WikiPageLayout.Custom) { web.AddLayoutToWikiPage(WikiPageLayout.OneColumn, url); } else { web.AddLayoutToWikiPage(page.Layout, url); } } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0__failed___1_____2_, url, ex.Message, ex.StackTrace); } } } else { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0_, url); web.AddWikiPageByUrl(url); web.AddLayoutToWikiPage(page.Layout, url); } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0__failed___1_____2_, url, ex.Message, ex.StackTrace); } } if (page.WelcomePage) { web.RootFolder.EnsureProperty(p => p.ServerRelativeUrl); var rootFolderRelativeUrl = url.Substring(web.RootFolder.ServerRelativeUrl.Length); web.SetHomePage(rootFolderRelativeUrl); } if (page.WebParts != null & page.WebParts.Any()) { var existingWebParts = web.GetWebParts(url); foreach (var webpart in page.WebParts) { if (existingWebParts.FirstOrDefault(w => w.WebPart.Title == webpart.Title) == null) { WebPartEntity wpEntity = new WebPartEntity(); wpEntity.WebPartTitle = webpart.Title; wpEntity.WebPartXml = parser.ParseString(webpart.Contents.Trim(new[] { '\n', ' ' })); web.AddWebPartToWikiPage(url, wpEntity, (int)webpart.Row, (int)webpart.Column, false); } } var allWebParts = web.GetWebParts(url); foreach (var webpart in allWebParts) { parser.AddToken(new WebPartIdToken(web, webpart.WebPart.Title, webpart.Id)); } } file = web.GetFileByServerRelativeUrl(url); file.EnsureProperty(f => f.ListItemAllFields); if (page.Fields.Any()) { var item = file.ListItemAllFields; foreach (var fieldValue in page.Fields) { item[fieldValue.Key] = parser.ParseString(fieldValue.Value); } item.Update(); web.Context.ExecuteQueryRetry(); } if (page.Security != null && page.Security.RoleAssignments.Count != 0) { web.Context.Load(file.ListItemAllFields); web.Context.ExecuteQuery(); file.ListItemAllFields.SetSecurity(parser, page.Security); } } } return(parser); }
private TokenParser ProcessSiteDesigns(Web web, ProvisioningTemplate template, TokenParser parser, PnPMonitoredScope scope) { if (template.Tenant.SiteDesigns != null && template.Tenant.SiteDesigns.Any()) { using (var tenantContext = web.Context.Clone(web.GetTenantAdministrationUrl())) { var tenant = new Tenant(tenantContext); var existingDesigns = tenant.GetSiteDesigns(); tenantContext.Load(existingDesigns); tenantContext.ExecuteQueryRetry(); foreach (var siteDesign in template.Tenant.SiteDesigns) { var designTitle = parser.ParseString(siteDesign.Title); var designDescription = parser.ParseString(siteDesign.Description); var designPreviewImageUrl = parser.ParseString(siteDesign.PreviewImageUrl); var designPreviewImageAltText = parser.ParseString(siteDesign.PreviewImageAltText); var existingSiteDesign = existingDesigns.FirstOrDefault(d => d.Title == designTitle); if (existingSiteDesign == null) { TenantSiteDesignCreationInfo siteDesignCreationInfo = new TenantSiteDesignCreationInfo() { Title = designTitle, Description = designDescription, PreviewImageUrl = designPreviewImageUrl, PreviewImageAltText = designPreviewImageAltText, IsDefault = siteDesign.IsDefault, }; switch ((int)siteDesign.WebTemplate) { case 0: { siteDesignCreationInfo.WebTemplate = "64"; break; } case 1: { siteDesignCreationInfo.WebTemplate = "68"; break; } } if (siteDesign.SiteScripts != null && siteDesign.SiteScripts.Any()) { List <Guid> ids = new List <Guid>(); foreach (var siteScriptRef in siteDesign.SiteScripts) { ids.Add(Guid.Parse(parser.ParseString(siteScriptRef))); } siteDesignCreationInfo.SiteScriptIds = ids.ToArray(); } var design = tenant.CreateSiteDesign(siteDesignCreationInfo); tenantContext.Load(design); tenantContext.ExecuteQueryRetry(); if (siteDesign.Grants != null && siteDesign.Grants.Any()) { foreach (var grant in siteDesign.Grants) { var rights = (TenantSiteDesignPrincipalRights)Enum.Parse(typeof(TenantSiteDesignPrincipalRights), grant.Right.ToString()); tenant.GrantSiteDesignRights(design.Id, new[] { grant.Principal }, rights); } tenantContext.ExecuteQueryRetry(); } parser.AddToken(new SiteDesignIdToken(web, design.Title, design.Id)); } else { if (siteDesign.Overwrite) { var existingId = existingSiteDesign.Id; existingSiteDesign = Tenant.GetSiteDesign(tenantContext, existingId); tenantContext.ExecuteQueryRetry(); existingSiteDesign.Title = designTitle; existingSiteDesign.Description = designDescription; existingSiteDesign.PreviewImageUrl = designPreviewImageUrl; existingSiteDesign.PreviewImageAltText = designPreviewImageAltText; existingSiteDesign.IsDefault = siteDesign.IsDefault; switch ((int)siteDesign.WebTemplate) { case 0: { existingSiteDesign.WebTemplate = "64"; break; } case 1: { existingSiteDesign.WebTemplate = "68"; break; } } tenant.UpdateSiteDesign(existingSiteDesign); tenantContext.ExecuteQueryRetry(); var existingToken = parser.Tokens.OfType <SiteDesignIdToken>().FirstOrDefault(t => t.GetReplaceValue() == existingId.ToString()); if (existingToken != null) { parser.Tokens.Remove(existingToken); } parser.AddToken(new SiteScriptIdToken(web, designTitle, existingId)); if (siteDesign.Grants != null && siteDesign.Grants.Any()) { var existingRights = Tenant.GetSiteDesignRights(tenantContext, existingId); tenantContext.Load(existingRights); tenantContext.ExecuteQueryRetry(); foreach (var existingRight in existingRights) { Tenant.RevokeSiteDesignRights(tenantContext, existingId, new[] { existingRight.PrincipalName }); } foreach (var grant in siteDesign.Grants) { var rights = (TenantSiteDesignPrincipalRights)Enum.Parse(typeof(TenantSiteDesignPrincipalRights), grant.Right.ToString()); tenant.GrantSiteDesignRights(existingId, new[] { parser.ParseString(grant.Principal) }, rights); } tenantContext.ExecuteQueryRetry(); } } } } } } return(parser); }
private static void CreateField(Web web, XElement templateFieldElement, PnPMonitoredScope scope, TokenParser parser, string originalFieldXml) { var listIdentifier = templateFieldElement.Attribute("List") != null?templateFieldElement.Attribute("List").Value : null; if (listIdentifier != null) { // Temporary remove list attribute from list templateFieldElement.Attribute("List").Remove(); } var fieldXml = parser.ParseString(templateFieldElement.ToString(), "~sitecollection", "~site"); if (IsFieldXmlValid(fieldXml, parser, web.Context)) { var field = web.Fields.AddFieldAsXml(fieldXml, false, AddFieldOptions.AddFieldInternalNameHint); web.Context.Load(field, f => f.TypeAsString, f => f.DefaultValue, f => f.InternalName, f => f.Title); web.Context.ExecuteQueryRetry(); // Add newly created field to token set, this allows to create a field + use it in a formula in the same provisioning template parser.AddToken(new FieldTitleToken(web, field.InternalName, field.Title)); bool isDirty = false; #if !SP2013 if (originalFieldXml.ContainsResourceToken()) { var originalFieldElement = XElement.Parse(originalFieldXml); var nameAttributeValue = originalFieldElement.Attribute("DisplayName") != null?originalFieldElement.Attribute("DisplayName").Value : ""; if (nameAttributeValue.ContainsResourceToken()) { field.TitleResource.SetUserResourceValue(nameAttributeValue, parser); isDirty = true; } var descriptionAttributeValue = originalFieldElement.Attribute("Description") != null?originalFieldElement.Attribute("Description").Value : ""; if (descriptionAttributeValue.ContainsResourceToken()) { field.DescriptionResource.SetUserResourceValue(descriptionAttributeValue, parser); isDirty = true; } } #endif if (isDirty) { field.Update(); web.Context.ExecuteQueryRetry(); } if ((field.TypeAsString == "TaxonomyFieldType" || field.TypeAsString == "TaxonomyFieldTypeMulti")) { var taxField = web.Context.CastTo <TaxonomyField>(field); if (!string.IsNullOrEmpty(field.DefaultValue)) { ValidateTaxonomyFieldDefaultValue(taxField); } SetTaxonomyFieldOpenValue(taxField, originalFieldXml); } } else { // The field Xml was found invalid var tokenString = parser.GetLeftOverTokens(fieldXml).Aggregate(String.Empty, (acc, i) => acc + " " + i); scope.LogError("The field was found invalid: {0}", tokenString); throw new Exception($"The field was found invalid: {tokenString}"); } }
private static void CreateField(Web web, XElement templateFieldElement, PnPMonitoredScope scope, TokenParser parser, string originalFieldXml) { var listIdentifier = templateFieldElement.Attribute("List") != null ? templateFieldElement.Attribute("List").Value : null; if (listIdentifier != null) { // Temporary remove list attribute from list templateFieldElement.Attribute("List").Remove(); } var fieldXml = parser.ParseString(templateFieldElement.ToString(), "~sitecollection", "~site"); if (IsFieldXmlValid(fieldXml, parser, web.Context)) { var field = web.Fields.AddFieldAsXml(fieldXml, false, AddFieldOptions.AddFieldInternalNameHint); web.Context.Load(field, f => f.TypeAsString, f => f.DefaultValue, f => f.InternalName, f => f.Title); web.Context.ExecuteQueryRetry(); // Add newly created field to token set, this allows to create a field + use it in a formula in the same provisioning template parser.AddToken(new FieldTitleToken(web, field.InternalName, field.Title)); bool isDirty = false; #if !SP2013 if (originalFieldXml.ContainsResourceToken()) { var originalFieldElement = XElement.Parse(originalFieldXml); var nameAttributeValue = originalFieldElement.Attribute("DisplayName") != null ? originalFieldElement.Attribute("DisplayName").Value : ""; if (nameAttributeValue.ContainsResourceToken()) { field.TitleResource.SetUserResourceValue(nameAttributeValue, parser); isDirty = true; } var descriptionAttributeValue = originalFieldElement.Attribute("Description") != null ? originalFieldElement.Attribute("Description").Value : ""; if (descriptionAttributeValue.ContainsResourceToken()) { field.DescriptionResource.SetUserResourceValue(descriptionAttributeValue, parser); isDirty = true; } } #endif if (isDirty) { field.Update(); web.Context.ExecuteQueryRetry(); } if ((field.TypeAsString == "TaxonomyFieldType" || field.TypeAsString == "TaxonomyFieldTypeMulti") && !string.IsNullOrEmpty(field.DefaultValue)) { var taxField = web.Context.CastTo<TaxonomyField>(field); ValidateTaxonomyFieldDefaultValue(taxField); } } else { // The field Xml was found invalid var tokenString = parser.GetLeftOverTokens(fieldXml).Aggregate(String.Empty, (acc, i) => acc + " " + i); scope.LogError("The field was found invalid: {0}", tokenString); throw new Exception(string.Format("The field was found invalid: {0}", tokenString)); } }
private static Microsoft.SharePoint.Client.ContentType CreateContentType(Web web, ContentType templateContentType, TokenParser parser, FileConnectorBase connector, PnPMonitoredScope scope, List <Microsoft.SharePoint.Client.ContentType> existingCTs = null, List <Microsoft.SharePoint.Client.Field> existingFields = null, bool isNoScriptSite = false) { var name = parser.ParseString(templateContentType.Name); var description = parser.ParseString(templateContentType.Description); var id = parser.ParseString(templateContentType.Id); var group = parser.ParseString(templateContentType.Group); var createdCT = web.CreateContentType(name, description, id, group); foreach (var fieldRef in templateContentType.FieldRefs) { Microsoft.SharePoint.Client.Field field = null; try { field = web.AvailableFields.GetById(fieldRef.Id); } catch (ArgumentException) { if (!string.IsNullOrEmpty(fieldRef.Name)) { field = web.AvailableFields.GetByInternalNameOrTitle(fieldRef.Name); } } // Add it to the target content type // Notice that this code will fail if the field does not exist web.AddFieldToContentType(createdCT, field, fieldRef.Required, fieldRef.Hidden); } // Add new CTs parser.AddToken(new ContentTypeIdToken(web, name, id)); #if !ONPREMISES // Set resources if (templateContentType.Name.ContainsResourceToken()) { createdCT.NameResource.SetUserResourceValue(templateContentType.Name, parser); } if (templateContentType.Description.ContainsResourceToken()) { createdCT.DescriptionResource.SetUserResourceValue(templateContentType.Description, parser); } #endif //Reorder the elements so that the new created Content Type has the same order as defined in the //template. The order can be different if the new Content Type inherits from another Content Type. //In this case the new Content Type has all field of the original Content Type and missing fields //will be added at the end. To fix this issue we ordering the fields once more. createdCT.FieldLinks.Reorder(templateContentType.FieldRefs.Select(fld => parser.ParseString(fld.Name)).ToArray()); createdCT.ReadOnly = templateContentType.ReadOnly; createdCT.Hidden = templateContentType.Hidden; createdCT.Sealed = templateContentType.Sealed; if (templateContentType.DocumentSetTemplate == null) { // Only apply a document template when the contenttype is not a document set if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DocumentTemplate))) { createdCT.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate); } } // Skipping updates of forms as we can't upload forms to noscript sites if (!isNoScriptSite) { if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.NewFormUrl))) { createdCT.NewFormUrl = parser.ParseString(templateContentType.NewFormUrl); } if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.EditFormUrl))) { createdCT.EditFormUrl = parser.ParseString(templateContentType.EditFormUrl); } if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DisplayFormUrl))) { createdCT.DisplayFormUrl = parser.ParseString(templateContentType.DisplayFormUrl); } } else { if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DisplayFormUrl)) || !string.IsNullOrEmpty(parser.ParseString(templateContentType.EditFormUrl)) || !string.IsNullOrEmpty(parser.ParseString(templateContentType.NewFormUrl))) { // log message scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_SkipCustomFormUrls, name); } } createdCT.Update(true); web.Context.ExecuteQueryRetry(); // If the CT is a DocumentSet if (templateContentType.DocumentSetTemplate != null) { // Retrieve a reference to the DocumentSet Content Type Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate documentSetTemplate = Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.GetDocumentSetTemplate(web.Context, createdCT); // Load the collections to allow for deletion scenarions web.Context.Load(documentSetTemplate, d => d.AllowedContentTypes, d => d.DefaultDocuments, d => d.SharedFields, d => d.WelcomePageFields); web.Context.ExecuteQueryRetry(); if (!String.IsNullOrEmpty(templateContentType.DocumentSetTemplate.WelcomePage)) { // TODO: Customize the WelcomePage of the DocumentSet } // Add additional content types to the set of allowed content types bool hasDefaultDocumentContentTypeInTemplate = false; foreach (String ctId in templateContentType.DocumentSetTemplate.AllowedContentTypes) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == ctId); if (ct != null) { if (ct.Id.StringValue.Equals("0x0101", StringComparison.InvariantCultureIgnoreCase)) { hasDefaultDocumentContentTypeInTemplate = true; } documentSetTemplate.AllowedContentTypes.Add(ct.Id); } } // If the default document content type (0x0101) is not in our definition then remove it if (!hasDefaultDocumentContentTypeInTemplate) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == "0x0101"); if (ct != null) { documentSetTemplate.AllowedContentTypes.Remove(ct.Id); } } if (!isNoScriptSite) { foreach (var doc in templateContentType.DocumentSetTemplate.DefaultDocuments) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == doc.ContentTypeId); if (ct != null) { using (Stream fileStream = connector.GetFileStream(doc.FileSourcePath)) { documentSetTemplate.DefaultDocuments.Add(doc.Name, ct.Id, ReadFullStream(fileStream)); } } } } else { if (templateContentType.DocumentSetTemplate.DefaultDocuments.Any()) { scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_SkipDocumentSetDefaultDocuments, name); } } foreach (var sharedField in templateContentType.DocumentSetTemplate.SharedFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == sharedField); if (field != null) { documentSetTemplate.SharedFields.Add(field); } } foreach (var welcomePageField in templateContentType.DocumentSetTemplate.WelcomePageFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == welcomePageField); if (field != null) { documentSetTemplate.WelcomePageFields.Add(field); } } documentSetTemplate.Update(true); web.Context.ExecuteQueryRetry(); } web.Context.Load(createdCT); web.Context.ExecuteQueryRetry(); return(createdCT); }
private static Microsoft.SharePoint.Client.ContentType CreateContentType(Web web, ContentType templateContentType, TokenParser parser, FileConnectorBase connector, List<Microsoft.SharePoint.Client.ContentType> existingCTs = null, List<Microsoft.SharePoint.Client.Field> existingFields = null) { var name = parser.ParseString(templateContentType.Name); var description = parser.ParseString(templateContentType.Description); var id = parser.ParseString(templateContentType.Id); var group = parser.ParseString(templateContentType.Group); var createdCT = web.CreateContentType(name, description, id, group); foreach (var fieldRef in templateContentType.FieldRefs) { var field = web.Fields.GetById(fieldRef.Id); web.AddFieldToContentType(createdCT, field, fieldRef.Required, fieldRef.Hidden); } // Add new CTs parser.AddToken(new ContentTypeIdToken(web, name, id)); #if !CLIENTSDKV15 // Set resources if (templateContentType.Name.ContainsResourceToken()) { createdCT.NameResource.SetUserResourceValue(templateContentType.Name, parser); } if(templateContentType.Description.ContainsResourceToken()) { createdCT.DescriptionResource.SetUserResourceValue(templateContentType.Description, parser); } #endif //Reorder the elements so that the new created Content Type has the same order as defined in the //template. The order can be different if the new Content Type inherits from another Content Type. //In this case the new Content Type has all field of the original Content Type and missing fields //will be added at the end. To fix this issue we ordering the fields once more. createdCT.FieldLinks.Reorder(templateContentType.FieldRefs.Select(fld => fld.Name).ToArray()); createdCT.ReadOnly = templateContentType.ReadOnly; createdCT.Hidden = templateContentType.Hidden; createdCT.Sealed = templateContentType.Sealed; if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DocumentTemplate))) { createdCT.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate); } if (!String.IsNullOrEmpty(templateContentType.NewFormUrl)) { createdCT.NewFormUrl = templateContentType.NewFormUrl; } if (!String.IsNullOrEmpty(templateContentType.EditFormUrl)) { createdCT.EditFormUrl = templateContentType.EditFormUrl; } if (!String.IsNullOrEmpty(templateContentType.DisplayFormUrl)) { createdCT.DisplayFormUrl = templateContentType.DisplayFormUrl; } createdCT.Update(true); web.Context.ExecuteQueryRetry(); // If the CT is a DocumentSet if (templateContentType.DocumentSetTemplate != null) { // Retrieve a reference to the DocumentSet Content Type Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate documentSetTemplate = Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.GetDocumentSetTemplate(web.Context, createdCT); if (!String.IsNullOrEmpty(templateContentType.DocumentSetTemplate.WelcomePage)) { // TODO: Customize the WelcomePage of the DocumentSet } foreach (String ctId in templateContentType.DocumentSetTemplate.AllowedContentTypes) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == ctId); if (ct != null) { documentSetTemplate.AllowedContentTypes.Add(ct.Id); } } foreach (var doc in templateContentType.DocumentSetTemplate.DefaultDocuments) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == doc.ContentTypeId); if (ct != null) { using (Stream fileStream = connector.GetFileStream(doc.FileSourcePath)) { documentSetTemplate.DefaultDocuments.Add(doc.Name, ct.Id, ReadFullStream(fileStream)); } } } foreach (var sharedField in templateContentType.DocumentSetTemplate.SharedFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == sharedField); if (field != null) { documentSetTemplate.SharedFields.Add(field); } } foreach (var welcomePageField in templateContentType.DocumentSetTemplate.WelcomePageFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == welcomePageField); if (field != null) { documentSetTemplate.WelcomePageFields.Add(field); } } documentSetTemplate.Update(true); web.Context.ExecuteQueryRetry(); } web.Context.Load(createdCT); web.Context.ExecuteQueryRetry(); return createdCT; }
public override void ProvisionObjects(Microsoft.SharePoint.Client.Web web, Model.ProvisioningTemplate template) { Log.Info(Constants.LOGGING_SOURCE_FRAMEWORK_PROVISIONING, CoreResources.Provisioning_ObjectHandlers_TermGroups); TaxonomySession taxSession = TaxonomySession.GetTaxonomySession(web.Context); var termStore = taxSession.GetDefaultKeywordsTermStore(); web.Context.Load(termStore, ts => ts.DefaultLanguage, ts => ts.Groups.Include( tg => tg.Name, tg => tg.Id, tg => tg.TermSets.Include( tset => tset.Name, tset => tset.Id))); web.Context.ExecuteQueryRetry(); foreach (var modelTermGroup in template.TermGroups) { #region Group var newGroup = false; TermGroup group = termStore.Groups.FirstOrDefault(g => g.Id == modelTermGroup.Id); if (group == null) { group = termStore.Groups.FirstOrDefault(g => g.Name == modelTermGroup.Name); if (group == null) { if (modelTermGroup.Id == Guid.Empty) { modelTermGroup.Id = Guid.NewGuid(); } group = termStore.CreateGroup(modelTermGroup.Name.ToParsedString(), modelTermGroup.Id); group.Description = modelTermGroup.Description; termStore.CommitAll(); web.Context.Load(group); web.Context.ExecuteQueryRetry(); newGroup = true; } } #endregion #region TermSets foreach (var modelTermSet in modelTermGroup.TermSets) { TermSet set = null; var newTermSet = false; if (!newGroup) { set = group.TermSets.FirstOrDefault(ts => ts.Id == modelTermSet.Id); if (set == null) { set = group.TermSets.FirstOrDefault(ts => ts.Name == modelTermSet.Name); } } if (set == null) { if (modelTermSet.Id == Guid.Empty) { modelTermSet.Id = Guid.NewGuid(); } set = group.CreateTermSet(modelTermSet.Name.ToParsedString(), modelTermSet.Id, modelTermSet.Language ?? termStore.DefaultLanguage); TokenParser.AddToken(new TermSetIdToken(web, modelTermGroup.Name, modelTermSet.Name, modelTermSet.Id)); newTermSet = true; set.IsOpenForTermCreation = modelTermSet.IsOpenForTermCreation; set.IsAvailableForTagging = modelTermSet.IsAvailableForTagging; foreach (var property in modelTermSet.Properties) { set.SetCustomProperty(property.Key, property.Value); } if (modelTermSet.Owner != null) { set.Owner = modelTermSet.Owner; } termStore.CommitAll(); web.Context.Load(set); web.Context.ExecuteQueryRetry(); } web.Context.Load(set, s => s.Terms.Include(t => t.Id, t => t.Name)); web.Context.ExecuteQueryRetry(); var terms = set.Terms; foreach (var modelTerm in modelTermSet.Terms) { if (!newTermSet) { if (terms.Any()) { var term = terms.FirstOrDefault(t => t.Id == modelTerm.Id); if (term == null) { term = terms.FirstOrDefault(t => t.Name == modelTerm.Name); if (term == null) { modelTerm.Id = CreateTerm <TermSet>(web, modelTerm, set, termStore); } else { modelTerm.Id = term.Id; } } else { modelTerm.Id = term.Id; } } else { modelTerm.Id = CreateTerm <TermSet>(web, modelTerm, set, termStore); } } else { modelTerm.Id = CreateTerm <TermSet>(web, modelTerm, set, termStore); } } // do we need custom sorting? if (modelTermSet.Terms.Any(t => t.CustomSortOrder > -1)) { var sortedTerms = modelTermSet.Terms.OrderBy(t => t.CustomSortOrder); var customSortString = sortedTerms.Aggregate(string.Empty, (a, i) => a + i.Id.ToString() + ":"); customSortString = customSortString.TrimEnd(new[] { ':' }); set.CustomSortOrder = customSortString; termStore.CommitAll(); web.Context.ExecuteQueryRetry(); } } #endregion } }
private Tuple<List, TokenParser> UpdateList(Web web, List existingList, ListInstance templateList, TokenParser parser, PnPMonitoredScope scope) { web.Context.Load(existingList, l => l.Title, l => l.Description, l => l.OnQuickLaunch, l => l.Hidden, l => l.ContentTypesEnabled, l => l.EnableAttachments, l => l.EnableFolderCreation, l => l.EnableMinorVersions, l => l.DraftVersionVisibility, l => l.Views, l => l.RootFolder #if !CLIENTSDKV15 , l => l.MajorWithMinorVersionsLimit #endif ); web.Context.ExecuteQueryRetry(); if (existingList.BaseTemplate == templateList.TemplateType) { var isDirty = false; if (parser.ParseString(templateList.Title) != existingList.Title) { var oldTitle = existingList.Title; existingList.Title = parser.ParseString(templateList.Title); if (!oldTitle.Equals(existingList.Title, StringComparison.OrdinalIgnoreCase)) { parser.AddToken(new ListIdToken(web, existingList.Title, existingList.Id)); parser.AddToken(new ListUrlToken(web, existingList.Title, existingList.RootFolder.ServerRelativeUrl.Substring(web.ServerRelativeUrl.Length + 1))); } isDirty = true; } if (!string.IsNullOrEmpty(templateList.DocumentTemplate)) { if (existingList.DocumentTemplateUrl != parser.ParseString(templateList.DocumentTemplate)) { existingList.DocumentTemplateUrl = parser.ParseString(templateList.DocumentTemplate); isDirty = true; } } if (!string.IsNullOrEmpty(templateList.Description) && templateList.Description != existingList.Description) { existingList.Description = templateList.Description; isDirty = true; } if (templateList.Hidden != existingList.Hidden) { existingList.Hidden = templateList.Hidden; isDirty = true; } if (templateList.OnQuickLaunch != existingList.OnQuickLaunch) { existingList.OnQuickLaunch = templateList.OnQuickLaunch; isDirty = true; } if (existingList.BaseTemplate != (int)ListTemplateType.Survey && templateList.ContentTypesEnabled != existingList.ContentTypesEnabled) { existingList.ContentTypesEnabled = templateList.ContentTypesEnabled; isDirty = true; } if (existingList.BaseTemplate != (int)ListTemplateType.Survey && existingList.BaseTemplate != (int)ListTemplateType.DocumentLibrary) { // https://msdn.microsoft.com/EN-US/library/microsoft.sharepoint.splist.enableattachments.aspx // The EnableAttachments property does not apply to any list that has a base type of Survey or DocumentLibrary. // If you set this property to true for either type of list, it throws an SPException. if (templateList.EnableAttachments != existingList.EnableAttachments) { existingList.EnableAttachments = templateList.EnableAttachments; isDirty = true; } } if (existingList.BaseTemplate != (int)ListTemplateType.DiscussionBoard) { if (templateList.EnableFolderCreation != existingList.EnableFolderCreation) { existingList.EnableFolderCreation = templateList.EnableFolderCreation; isDirty = true; } } if (templateList.EnableVersioning) { if (existingList.EnableVersioning != templateList.EnableVersioning) { existingList.EnableVersioning = templateList.EnableVersioning; isDirty = true; } #if !CLIENTSDKV15 if (existingList.IsObjectPropertyInstantiated("MajorVersionLimit") && existingList.MajorVersionLimit != templateList.MaxVersionLimit) { existingList.MajorVersionLimit = templateList.MaxVersionLimit; isDirty = true; } #endif if (existingList.BaseType == BaseType.DocumentLibrary) { // Only supported on Document Libraries if (templateList.EnableMinorVersions != existingList.EnableMinorVersions) { existingList.EnableMinorVersions = templateList.EnableMinorVersions; isDirty = true; } if ((DraftVisibilityType)templateList.DraftVersionVisibility != existingList.DraftVersionVisibility) { existingList.DraftVersionVisibility = (DraftVisibilityType)templateList.DraftVersionVisibility; isDirty = true; } if (templateList.EnableMinorVersions) { if (templateList.MinorVersionLimit != existingList.MajorWithMinorVersionsLimit) { existingList.MajorWithMinorVersionsLimit = templateList.MinorVersionLimit; } if (DraftVisibilityType.Approver == (DraftVisibilityType)templateList.DraftVersionVisibility) { if (templateList.EnableModeration) { if ((DraftVisibilityType)templateList.DraftVersionVisibility != existingList.DraftVersionVisibility) { existingList.DraftVersionVisibility = (DraftVisibilityType)templateList.DraftVersionVisibility; isDirty = true; } } } else { if ((DraftVisibilityType)templateList.DraftVersionVisibility != existingList.DraftVersionVisibility) { existingList.DraftVersionVisibility = (DraftVisibilityType)templateList.DraftVersionVisibility; isDirty = true; } } } } } if (isDirty) { existingList.Update(); web.Context.ExecuteQueryRetry(); } if (existingList.ContentTypesEnabled) { // Check if we need to add a content type var existingContentTypes = existingList.ContentTypes; web.Context.Load(existingContentTypes, cts => cts.Include(ct => ct.StringId)); web.Context.ExecuteQueryRetry(); var bindingsToAdd = templateList.ContentTypeBindings.Where(ctb => existingContentTypes.All(ct => !ctb.ContentTypeId.Equals(ct.StringId, StringComparison.InvariantCultureIgnoreCase))).ToList(); var defaultCtBinding = templateList.ContentTypeBindings.FirstOrDefault(ctb => ctb.Default == true); var bindingAddedToList = false; foreach (var ctb in bindingsToAdd) { // Added a check so that if no bindings were actually added then the SetDefaultContentTypeToList method will not be executed // This is to address a specific scenario when OOTB PWA lists can not be updated as they are centrally managed var addedToList = existingList.AddContentTypeToListById(ctb.ContentTypeId, searchContentTypeInSiteHierarchy: true); if (addedToList) { bindingAddedToList = true; } } // default ContentTypeBinding should be set last because // list extension .SetDefaultContentTypeToList() re-sets // the list.RootFolder UniqueContentTypeOrder property // which may cause missing CTs from the "New Button" if (defaultCtBinding != null && bindingAddedToList) { existingList.SetDefaultContentTypeToList(defaultCtBinding.ContentTypeId); } } if (templateList.Security != null) { existingList.SetSecurity(parser, templateList.Security); } return Tuple.Create(existingList, parser); } else { scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstances_List__0____1____2___exists_but_is_of_a_different_type__Skipping_list_, templateList.Title, templateList.Url, existingList.Id); WriteWarning(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_List__0____1____2___exists_but_is_of_a_different_type__Skipping_list_, templateList.Title, templateList.Url, existingList.Id), ProvisioningMessageType.Warning); return null; } }
private void UpdateContentType( Web web, ProvisioningTemplate template, Microsoft.SharePoint.Client.ContentType existingContentType, ContentType templateContentType, TokenParser parser, PnPMonitoredScope scope, bool isNoScriptSite = false ) { var isDirty = false; var reOrderFields = false; if (existingContentType.Hidden != templateContentType.Hidden) { scope.LogPropertyUpdate("Hidden"); existingContentType.Hidden = templateContentType.Hidden; isDirty = true; } if (existingContentType.ReadOnly != templateContentType.ReadOnly) { scope.LogPropertyUpdate("ReadOnly"); existingContentType.ReadOnly = templateContentType.ReadOnly; isDirty = true; } if (existingContentType.Sealed != templateContentType.Sealed) { scope.LogPropertyUpdate("Sealed"); existingContentType.Sealed = templateContentType.Sealed; isDirty = true; } if (templateContentType.Description != null && existingContentType.Description != parser.ParseString(templateContentType.Description)) { scope.LogPropertyUpdate("Description"); existingContentType.Description = parser.ParseString(templateContentType.Description); isDirty = true; } if (templateContentType.DocumentTemplate != null && existingContentType.DocumentTemplate != parser.ParseString(templateContentType.DocumentTemplate)) { scope.LogPropertyUpdate("DocumentTemplate"); existingContentType.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate); isDirty = true; } if (existingContentType.Name != parser.ParseString(templateContentType.Name)) { scope.LogPropertyUpdate("Name"); existingContentType.Name = parser.ParseString(templateContentType.Name); isDirty = true; // CT is being renamed, add an extra token to the tokenparser parser.AddToken(new ContentTypeIdToken(web, existingContentType.Name, existingContentType.StringId)); } if (templateContentType.Group != null && existingContentType.Group != parser.ParseString(templateContentType.Group)) { scope.LogPropertyUpdate("Group"); existingContentType.Group = parser.ParseString(templateContentType.Group); isDirty = true; } if (!isNoScriptSite) { if (templateContentType.DisplayFormUrl != null && existingContentType.DisplayFormUrl != parser.ParseString(templateContentType.DisplayFormUrl)) { scope.LogPropertyUpdate("DisplayFormUrl"); existingContentType.DisplayFormUrl = parser.ParseString(templateContentType.DisplayFormUrl); isDirty = true; } if (templateContentType.EditFormUrl != null && existingContentType.EditFormUrl != parser.ParseString(templateContentType.EditFormUrl)) { scope.LogPropertyUpdate("EditFormUrl"); existingContentType.EditFormUrl = parser.ParseString(templateContentType.EditFormUrl); isDirty = true; } if (templateContentType.NewFormUrl != null && existingContentType.NewFormUrl != parser.ParseString(templateContentType.NewFormUrl)) { scope.LogPropertyUpdate("NewFormUrl"); existingContentType.NewFormUrl = parser.ParseString(templateContentType.NewFormUrl); isDirty = true; } } else { if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DisplayFormUrl)) || !string.IsNullOrEmpty(parser.ParseString(templateContentType.EditFormUrl)) || !string.IsNullOrEmpty(parser.ParseString(templateContentType.NewFormUrl))) { // log message scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_SkipCustomFormUrls, existingContentType.Name); } } #if !SP2013 if (templateContentType.Name.ContainsResourceToken()) { existingContentType.NameResource.SetUserResourceValue(templateContentType.Name, parser); isDirty = true; } if (templateContentType.Description.ContainsResourceToken()) { existingContentType.DescriptionResource.SetUserResourceValue(templateContentType.Description, parser); isDirty = true; } #endif if (isDirty) { existingContentType.Update(true); web.Context.ExecuteQueryRetry(); } // Set flag to reorder fields CT fields are not equal to template fields var existingFieldNames = existingContentType.FieldLinks.AsEnumerable().Select(fld => fld.Name).ToArray(); var ctFieldNames = templateContentType.FieldRefs.Select(fld => parser.ParseString(fld.Name)).ToArray(); reOrderFields = !existingFieldNames.SequenceEqual(ctFieldNames); // Delta handling existingContentType.EnsureProperty(c => c.FieldLinks); var targetIds = existingContentType.FieldLinks.AsEnumerable().Select(c1 => c1.Id).ToList(); var sourceIds = templateContentType.FieldRefs.Select(c1 => c1.Id).ToList(); var fieldsNotPresentInTarget = sourceIds.Except(targetIds).ToArray(); if (fieldsNotPresentInTarget.Any()) { // Set flag to reorder fields when new fields are added. reOrderFields = true; foreach (var fieldId in fieldsNotPresentInTarget) { var fieldRef = templateContentType.FieldRefs.First(fr => fr.Id == fieldId); var templateField = template.SiteFields.FirstOrDefault(tf => (Guid)XElement.Parse(parser.ParseString(tf.SchemaXml)).Attribute("ID") == fieldRef.Id); var fieldStep = templateField != null?templateField.GetFieldProvisioningStep(parser) : FieldAndListProvisioningStepHelper.Step.ListAndStandardFields; if (fieldStep != _step) { continue; // Do not handle this field at this step } Microsoft.SharePoint.Client.Field field = null; if (_step == FieldAndListProvisioningStepHelper.Step.LookupFields && templateField != null && XElement.Parse(parser.ParseString(templateField.SchemaXml)).Attribute("FieldRef") != null) { // Because the id of dependent lookup cannot be set and is autogenerated, // we have to retrieve the actual field id and convert it into a token var mappedFieldId = Guid.Parse(parser.ParseString(fieldRef.Id.ToString("D"))); field = web.AvailableFields.GetById(mappedFieldId); } else { field = web.AvailableFields.GetById(fieldRef.Id); } scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ContentTypes_Adding_field__0__to_content_type, fieldId); web.AddFieldToContentType(existingContentType, field, fieldRef.Required, fieldRef.Hidden); } } // Reorder fields if (reOrderFields) { existingContentType.FieldLinks.Reorder(ctFieldNames); isDirty = true; } foreach (var fieldId in targetIds.Intersect(sourceIds)) { var fieldLink = existingContentType.FieldLinks.FirstOrDefault(fl => fl.Id == fieldId); var fieldRef = templateContentType.FieldRefs.Find(fr => fr.Id == fieldId); if (fieldRef != null) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ContentTypes_Field__0__exists_in_content_type, fieldId); if (fieldLink.Required != fieldRef.Required) { scope.LogPropertyUpdate("Required"); fieldLink.Required = fieldRef.Required; isDirty = true; } if (fieldLink.Hidden != fieldRef.Hidden) { scope.LogPropertyUpdate("Hidden"); fieldLink.Hidden = fieldRef.Hidden; isDirty = true; } } } // The new CT is a DocumentSet, and the target should be, as well if (templateContentType.DocumentSetTemplate != null) { if (!Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.IsChildOfDocumentSetContentType(web.Context, existingContentType).Value) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ContentTypes_InvalidDocumentSet_Update_Request, existingContentType.Id, existingContentType.Name); } else { Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate templateToUpdate = Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.GetDocumentSetTemplate(web.Context, existingContentType); // TODO: Implement Delta Handling scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_DocumentSet_DeltaHandling_OnHold, existingContentType.Id, existingContentType.Name); } } if (isDirty) { existingContentType.Update(true); web.Context.ExecuteQueryRetry(); } }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { // Changed by Paolo Pialorsi to embrace the new sub-site attributes for break role inheritance and copy role assignments // if this is a sub site then we're not provisioning security as by default security is inherited from the root site //if (web.IsSubSite() && !template.Security.BreakRoleInheritance) //{ // scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_SiteSecurity_Context_web_is_subweb__skipping_site_security_provisioning); // return parser; //} if (web.IsSubSite() && template.Security.BreakRoleInheritance) { web.BreakRoleInheritance(template.Security.CopyRoleAssignments, template.Security.ClearSubscopes); web.Update(); web.Context.ExecuteQueryRetry(); } var siteSecurity = template.Security; var ownerGroup = web.AssociatedOwnerGroup; var memberGroup = web.AssociatedMemberGroup; var visitorGroup = web.AssociatedVisitorGroup; web.Context.Load(ownerGroup, o => o.Title, o => o.Users); web.Context.Load(memberGroup, o => o.Title, o => o.Users); web.Context.Load(visitorGroup, o => o.Title, o => o.Users); web.Context.ExecuteQueryRetry(); if (!ownerGroup.ServerObjectIsNull.Value) { AddUserToGroup(web, ownerGroup, siteSecurity.AdditionalOwners, scope, parser); } if (!memberGroup.ServerObjectIsNull.Value) { AddUserToGroup(web, memberGroup, siteSecurity.AdditionalMembers, scope, parser); } if (!visitorGroup.ServerObjectIsNull.Value) { AddUserToGroup(web, visitorGroup, siteSecurity.AdditionalVisitors, scope, parser); } foreach (var siteGroup in siteSecurity.SiteGroups) { Group group; var allGroups = web.Context.LoadQuery(web.SiteGroups.Include(gr => gr.LoginName)); web.Context.ExecuteQueryRetry(); string parsedGroupTitle = parser.ParseString(siteGroup.Title); string parsedGroupOwner = parser.ParseString(siteGroup.Owner); string parsedGroupDescription = parser.ParseString(siteGroup.Description); if (!web.GroupExists(parsedGroupTitle)) { scope.LogDebug("Creating group {0}", parsedGroupTitle); group = web.AddGroup( parsedGroupTitle, parsedGroupDescription, parsedGroupTitle == parsedGroupOwner); group.AllowMembersEditMembership = siteGroup.AllowMembersEditMembership; group.AllowRequestToJoinLeave = siteGroup.AllowRequestToJoinLeave; group.AutoAcceptRequestToJoinLeave = siteGroup.AutoAcceptRequestToJoinLeave; if (parsedGroupTitle != parsedGroupOwner) { Principal ownerPrincipal = allGroups.FirstOrDefault(gr => gr.LoginName == parsedGroupOwner); if (ownerPrincipal == null) { ownerPrincipal = web.EnsureUser(parsedGroupOwner); } group.Owner = ownerPrincipal; } group.Update(); web.Context.Load(group, g => g.Id, g => g.Title); web.Context.ExecuteQueryRetry(); parser.AddToken(new GroupIdToken(web, group.Title, group.Id)); } else { group = web.SiteGroups.GetByName(parsedGroupTitle); web.Context.Load(group, g => g.Title, g => g.Description, g => g.AllowMembersEditMembership, g => g.AllowRequestToJoinLeave, g => g.AutoAcceptRequestToJoinLeave, g => g.Owner.LoginName); web.Context.ExecuteQueryRetry(); var isDirty = false; if (!String.IsNullOrEmpty(group.Description) && group.Description != parsedGroupDescription) { group.Description = parsedGroupDescription; isDirty = true; } if (group.AllowMembersEditMembership != siteGroup.AllowMembersEditMembership) { group.AllowMembersEditMembership = siteGroup.AllowMembersEditMembership; isDirty = true; } if (group.AllowRequestToJoinLeave != siteGroup.AllowRequestToJoinLeave) { group.AllowRequestToJoinLeave = siteGroup.AllowRequestToJoinLeave; isDirty = true; } if (group.AutoAcceptRequestToJoinLeave != siteGroup.AutoAcceptRequestToJoinLeave) { group.AutoAcceptRequestToJoinLeave = siteGroup.AutoAcceptRequestToJoinLeave; isDirty = true; } if (group.Owner.LoginName != parsedGroupOwner) { if (parsedGroupTitle != parsedGroupOwner) { Principal ownerPrincipal = allGroups.FirstOrDefault(gr => gr.LoginName == parsedGroupOwner); if (ownerPrincipal == null) { ownerPrincipal = web.EnsureUser(parsedGroupOwner); } group.Owner = ownerPrincipal; } else { group.Owner = group; } isDirty = true; } if (isDirty) { scope.LogDebug("Updating existing group {0}", group.Title); group.Update(); web.Context.ExecuteQueryRetry(); } } if (group != null && siteGroup.Members.Any()) { AddUserToGroup(web, group, siteGroup.Members, scope, parser); } } foreach (var admin in siteSecurity.AdditionalAdministrators) { var parsedAdminName = parser.ParseString(admin.Name); var user = web.EnsureUser(parsedAdminName); user.IsSiteAdmin = true; user.Update(); web.Context.ExecuteQueryRetry(); } if (!web.IsSubSite() && siteSecurity.SiteSecurityPermissions != null) // Only manage permissions levels on sitecol level { var existingRoleDefinitions = web.Context.LoadQuery(web.RoleDefinitions.Include(wr => wr.Name, wr => wr.BasePermissions, wr => wr.Description)); web.Context.ExecuteQueryRetry(); if (siteSecurity.SiteSecurityPermissions.RoleDefinitions.Any()) { foreach (var templateRoleDefinition in siteSecurity.SiteSecurityPermissions.RoleDefinitions) { var roleDefinitions = existingRoleDefinitions as RoleDefinition[] ?? existingRoleDefinitions.ToArray(); var siteRoleDefinition = roleDefinitions.FirstOrDefault(erd => erd.Name == parser.ParseString(templateRoleDefinition.Name)); if (siteRoleDefinition == null) { scope.LogDebug("Creation role definition {0}", parser.ParseString(templateRoleDefinition.Name)); var roleDefinitionCI = new RoleDefinitionCreationInformation(); roleDefinitionCI.Name = parser.ParseString(templateRoleDefinition.Name); roleDefinitionCI.Description = parser.ParseString(templateRoleDefinition.Description); BasePermissions basePermissions = new BasePermissions(); foreach (var permission in templateRoleDefinition.Permissions) { basePermissions.Set(permission); } roleDefinitionCI.BasePermissions = basePermissions; web.RoleDefinitions.Add(roleDefinitionCI); web.Context.ExecuteQueryRetry(); } else { var isDirty = false; if (siteRoleDefinition.Description != parser.ParseString(templateRoleDefinition.Description)) { siteRoleDefinition.Description = parser.ParseString(templateRoleDefinition.Description); isDirty = true; } var templateBasePermissions = new BasePermissions(); templateRoleDefinition.Permissions.ForEach(p => templateBasePermissions.Set(p)); if (siteRoleDefinition.BasePermissions != templateBasePermissions) { isDirty = true; foreach (var permission in templateRoleDefinition.Permissions) { siteRoleDefinition.BasePermissions.Set(permission); } } if (isDirty) { scope.LogDebug("Updating role definition {0}", parser.ParseString(templateRoleDefinition.Name)); siteRoleDefinition.Update(); web.Context.ExecuteQueryRetry(); } } } } var webRoleDefinitions = web.Context.LoadQuery(web.RoleDefinitions); var groups = web.Context.LoadQuery(web.SiteGroups.Include(g => g.LoginName)); web.Context.ExecuteQueryRetry(); if (siteSecurity.SiteSecurityPermissions.RoleAssignments.Any()) { foreach (var roleAssignment in siteSecurity.SiteSecurityPermissions.RoleAssignments) { Principal principal = groups.FirstOrDefault(g => g.LoginName == parser.ParseString(roleAssignment.Principal)); if (principal == null) { principal = web.EnsureUser(parser.ParseString(roleAssignment.Principal)); } var roleDefinitionBindingCollection = new RoleDefinitionBindingCollection(web.Context); var roleDefinition = webRoleDefinitions.FirstOrDefault(r => r.Name == parser.ParseString(roleAssignment.RoleDefinition)); if (roleDefinition != null) { roleDefinitionBindingCollection.Add(roleDefinition); } web.RoleAssignments.Add(principal, roleDefinitionBindingCollection); web.Context.ExecuteQueryRetry(); } } } } return parser; }
private Microsoft.SharePoint.Client.ContentType CreateContentType( Web web, ProvisioningTemplate template, ContentType templateContentType, TokenParser parser, FileConnectorBase connector, PnPMonitoredScope scope, List <Microsoft.SharePoint.Client.ContentType> existingCTs = null, List <Microsoft.SharePoint.Client.Field> existingFields = null, bool isNoScriptSite = false) { var name = parser.ParseString(templateContentType.Name); var description = parser.ParseString(templateContentType.Description); var id = parser.ParseString(templateContentType.Id); var group = parser.ParseString(templateContentType.Group); var createdCT = web.CreateContentType(name, description, id, group); var fieldsRefsToProcess = templateContentType.FieldRefs.Select(fr => new { FieldRef = fr, TemplateField = template.SiteFields.FirstOrDefault(tf => (Guid)XElement.Parse(parser.ParseString(tf.SchemaXml)).Attribute("ID") == fr.Id) }).Where(frData => frData.TemplateField == null || // Process fields refs if the target is not defined in the current template frData.TemplateField.GetFieldProvisioningStep(parser) == _step // or process field ref only if the current step is matching ).Select(fr => fr.FieldRef).ToArray(); foreach (var fieldRef in fieldsRefsToProcess) { Microsoft.SharePoint.Client.Field field = null; try { field = web.AvailableFields.GetById(fieldRef.Id); } catch (ArgumentException) { if (!string.IsNullOrEmpty(fieldRef.Name)) { field = web.AvailableFields.GetByInternalNameOrTitle(fieldRef.Name); } } // Add it to the target content type // Notice that this code will fail if the field does not exist web.AddFieldToContentType(createdCT, field, fieldRef.Required, fieldRef.Hidden); } // Add new CTs parser.AddToken(new ContentTypeIdToken(web, name, id)); #if !ONPREMISES // Set resources if (templateContentType.Name.ContainsResourceToken()) { createdCT.NameResource.SetUserResourceValue(templateContentType.Name, parser); } if (templateContentType.Description.ContainsResourceToken()) { createdCT.DescriptionResource.SetUserResourceValue(templateContentType.Description, parser); } #endif //Reorder the elements so that the new created Content Type has the same order as defined in the //template. The order can be different if the new Content Type inherits from another Content Type. //In this case the new Content Type has all field of the original Content Type and missing fields //will be added at the end. To fix this issue we ordering the fields once more. createdCT.FieldLinks.Reorder(templateContentType.FieldRefs.Select(fld => parser.ParseString(fld.Name)).ToArray()); createdCT.ReadOnly = templateContentType.ReadOnly; createdCT.Hidden = templateContentType.Hidden; createdCT.Sealed = templateContentType.Sealed; if (templateContentType.DocumentSetTemplate == null) { // Only apply a document template when the contenttype is not a document set if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DocumentTemplate))) { createdCT.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate); } } // Skipping updates of forms as we can't upload forms to noscript sites if (!isNoScriptSite) { if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.NewFormUrl))) { createdCT.NewFormUrl = parser.ParseString(templateContentType.NewFormUrl); } if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.EditFormUrl))) { createdCT.EditFormUrl = parser.ParseString(templateContentType.EditFormUrl); } if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DisplayFormUrl))) { createdCT.DisplayFormUrl = parser.ParseString(templateContentType.DisplayFormUrl); } } else { if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DisplayFormUrl)) || !string.IsNullOrEmpty(parser.ParseString(templateContentType.EditFormUrl)) || !string.IsNullOrEmpty(parser.ParseString(templateContentType.NewFormUrl))) { // log message scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_SkipCustomFormUrls, name); } } createdCT.Update(true); web.Context.ExecuteQueryRetry(); // If the CT is a DocumentSet if (templateContentType.DocumentSetTemplate != null) { // Retrieve a reference to the DocumentSet Content Type Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate documentSetTemplate = Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.GetDocumentSetTemplate(web.Context, createdCT); // Load the collections to allow for deletion scenarions web.Context.Load(documentSetTemplate, d => d.AllowedContentTypes, d => d.DefaultDocuments, d => d.SharedFields, d => d.WelcomePageFields); web.Context.ExecuteQueryRetry(); if (!String.IsNullOrEmpty(templateContentType.DocumentSetTemplate.WelcomePage)) { // TODO: Customize the WelcomePage of the DocumentSet } // Add additional content types to the set of allowed content types bool hasDefaultDocumentContentTypeInTemplate = false; foreach (String ctId in templateContentType.DocumentSetTemplate.AllowedContentTypes) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == ctId); if (ct != null) { if (ct.Id.StringValue.Equals("0x0101", StringComparison.InvariantCultureIgnoreCase)) { hasDefaultDocumentContentTypeInTemplate = true; } documentSetTemplate.AllowedContentTypes.Add(ct.Id); } } // If the default document content type (0x0101) is not in our definition then remove it if (!hasDefaultDocumentContentTypeInTemplate) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == "0x0101"); if (ct != null) { documentSetTemplate.AllowedContentTypes.Remove(ct.Id); } } if (!isNoScriptSite) { foreach (var doc in templateContentType.DocumentSetTemplate.DefaultDocuments) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == doc.ContentTypeId); if (ct != null) { using (Stream fileStream = connector.GetFileStream(doc.FileSourcePath)) { documentSetTemplate.DefaultDocuments.Add(doc.Name, ct.Id, ReadFullStream(fileStream)); } } } } else { if (templateContentType.DocumentSetTemplate.DefaultDocuments.Any()) { scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_SkipDocumentSetDefaultDocuments, name); } } foreach (var sharedField in templateContentType.DocumentSetTemplate.SharedFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == sharedField); if (field != null) { documentSetTemplate.SharedFields.Add(field); } } foreach (var welcomePageField in templateContentType.DocumentSetTemplate.WelcomePageFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == welcomePageField); if (field != null) { documentSetTemplate.WelcomePageFields.Add(field); } } documentSetTemplate.Update(true); web.Context.ExecuteQueryRetry(); } else if (templateContentType.Id.StartsWith(BuiltInContentTypeId.Workflow2013Task + "00")) { // If the Workflow Task (SP2013) contains more than one outcomeChoice, the Form UI will not show // the buttons associated each to choices, but fallback to classic Save and Cancel buttons. // +"00" is used to target only inherited content types and not alter OOB var outcomeFields = web.Context.LoadQuery( createdCT.Fields.Where(f => f.TypeAsString == "OutcomeChoice")); web.Context.ExecuteQueryRetry(); if (outcomeFields.Any()) { // 2 OutcomeChoice specified means the user has certainly push its own. // Let's remove the default outcome field var field = outcomeFields.FirstOrDefault(f => f.StaticName == "TaskOutcome"); if (field != null) { var fl = createdCT.FieldLinks.GetById(field.Id); fl.DeleteObject(); createdCT.Update(true); web.Context.ExecuteQueryRetry(); } } } web.Context.Load(createdCT); web.Context.ExecuteQueryRetry(); return(createdCT); }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { var context = web.Context as ClientContext; web.EnsureProperties(w => w.ServerRelativeUrl, w => w.RootFolder.WelcomePage); foreach (var page in template.Pages) { var url = parser.ParseString(page.Url); if (!url.ToLower().StartsWith(web.ServerRelativeUrl.ToLower())) { url = UrlUtility.Combine(web.ServerRelativeUrl, url); } var exists = true; Microsoft.SharePoint.Client.File file = null; try { file = web.GetFileByServerRelativeUrl(url); web.Context.Load(file); web.Context.ExecuteQuery(); } catch (ServerException ex) { if (ex.ServerErrorTypeName == "System.IO.FileNotFoundException") { exists = false; } } if (exists) { if (page.Overwrite) { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0_, url); if (page.WelcomePage && url.Contains(web.RootFolder.WelcomePage)) web.SetHomePage(string.Empty); file.DeleteObject(); web.Context.ExecuteQueryRetry(); web.AddWikiPageByUrl(url); if (page.Layout == WikiPageLayout.Custom) { web.AddLayoutToWikiPage(WikiPageLayout.OneColumn, url); } else { web.AddLayoutToWikiPage(page.Layout, url); } } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Overwriting_existing_page__0__failed___1_____2_, url, ex.Message, ex.StackTrace); } } } else { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0_, url); web.AddWikiPageByUrl(url); web.AddLayoutToWikiPage(page.Layout, url); } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_Pages_Creating_new_page__0__failed___1_____2_, url, ex.Message, ex.StackTrace); } } if (page.WelcomePage) { web.RootFolder.EnsureProperty(p => p.ServerRelativeUrl); var rootFolderRelativeUrl = url.Substring(web.RootFolder.ServerRelativeUrl.Length); web.SetHomePage(rootFolderRelativeUrl); } if (page.WebParts != null & page.WebParts.Any()) { var existingWebParts = web.GetWebParts(url); foreach (var webpart in page.WebParts) { if (existingWebParts.FirstOrDefault(w => w.WebPart.Title == webpart.Title) == null) { WebPartEntity wpEntity = new WebPartEntity(); wpEntity.WebPartTitle = webpart.Title; wpEntity.WebPartXml = parser.ParseString(webpart.Contents.Trim(new[] { '\n', ' ' })); web.AddWebPartToWikiPage(url, wpEntity, (int)webpart.Row, (int)webpart.Column, false); } } var allWebParts = web.GetWebParts(url); foreach (var webpart in allWebParts) { parser.AddToken(new WebPartIdToken(web, webpart.WebPart.Title, webpart.Id)); } } file = web.GetFileByServerRelativeUrl(url); file.EnsureProperty(f => f.ListItemAllFields); if (page.Fields.Any()) { var item = file.ListItemAllFields; foreach (var fieldValue in page.Fields) { item[fieldValue.Key] = parser.ParseString(fieldValue.Value); } item.Update(); web.Context.ExecuteQueryRetry(); } if (page.Security != null && page.Security.RoleAssignments.Count != 0) { web.Context.Load(file.ListItemAllFields); web.Context.ExecuteQuery(); file.ListItemAllFields.SetSecurity(parser, page.Security); } } } return parser; }
public override TokenParser ProvisionObjects(Web web, Model.ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { TaxonomySession taxSession = TaxonomySession.GetTaxonomySession(web.Context); var termStore = taxSession.GetDefaultKeywordsTermStore(); web.Context.Load(termStore, ts => ts.DefaultLanguage, ts => ts.Groups.Include( tg => tg.Name, tg => tg.Id, tg => tg.TermSets.Include( tset => tset.Name, tset => tset.Id))); web.Context.ExecuteQueryRetry(); foreach (var modelTermGroup in template.TermGroups) { #region Group var newGroup = false; TermGroup group = termStore.Groups.FirstOrDefault(g => g.Id == modelTermGroup.Id); if (group == null) { if (modelTermGroup.Name == "Site Collection") { var site = (web.Context as ClientContext).Site; group = termStore.GetSiteCollectionGroup(site, true); web.Context.Load(group, g => g.Name, g => g.Id, g => g.TermSets.Include( tset => tset.Name, tset => tset.Id)); web.Context.ExecuteQueryRetry(); } else { var parsedGroupName = parser.ParseString(modelTermGroup.Name); group = termStore.Groups.FirstOrDefault(g => g.Name == parsedGroupName); if (group == null) { if (modelTermGroup.Id == Guid.Empty) { modelTermGroup.Id = Guid.NewGuid(); } group = termStore.CreateGroup(parsedGroupName, modelTermGroup.Id); group.Description = modelTermGroup.Description; termStore.CommitAll(); web.Context.Load(group); web.Context.ExecuteQueryRetry(); newGroup = true; } } } #endregion #region TermSets foreach (var modelTermSet in modelTermGroup.TermSets) { TermSet set = null; var newTermSet = false; if (!newGroup) { set = group.TermSets.FirstOrDefault(ts => ts.Id == modelTermSet.Id); if (set == null) { set = group.TermSets.FirstOrDefault(ts => ts.Name == modelTermSet.Name); } } if (set == null) { if (modelTermSet.Id == Guid.Empty) { modelTermSet.Id = Guid.NewGuid(); } set = group.CreateTermSet(parser.ParseString(modelTermSet.Name), modelTermSet.Id, modelTermSet.Language ?? termStore.DefaultLanguage); parser.AddToken(new TermSetIdToken(web, modelTermGroup.Name, modelTermSet.Name, modelTermSet.Id)); newTermSet = true; set.IsOpenForTermCreation = modelTermSet.IsOpenForTermCreation; set.IsAvailableForTagging = modelTermSet.IsAvailableForTagging; foreach (var property in modelTermSet.Properties) { set.SetCustomProperty(property.Key, property.Value); } if (modelTermSet.Owner != null) { set.Owner = modelTermSet.Owner; } termStore.CommitAll(); web.Context.Load(set); web.Context.ExecuteQueryRetry(); } web.Context.Load(set, s => s.Terms.Include(t => t.Id, t => t.Name)); web.Context.ExecuteQueryRetry(); var terms = set.Terms; foreach (var modelTerm in modelTermSet.Terms) { if (!newTermSet) { if (terms.Any()) { var term = terms.FirstOrDefault(t => t.Id == modelTerm.Id); if (term == null) { term = terms.FirstOrDefault(t => t.Name == modelTerm.Name); if (term == null) { var returnTuple = CreateTerm <TermSet>(web, modelTerm, set, termStore, parser, scope); modelTerm.Id = returnTuple.Item1; parser = returnTuple.Item2; } else { modelTerm.Id = term.Id; } } else { modelTerm.Id = term.Id; } } else { var returnTuple = CreateTerm <TermSet>(web, modelTerm, set, termStore, parser, scope); modelTerm.Id = returnTuple.Item1; parser = returnTuple.Item2; } } else { var returnTuple = CreateTerm <TermSet>(web, modelTerm, set, termStore, parser, scope); modelTerm.Id = returnTuple.Item1; parser = returnTuple.Item2; } } // do we need custom sorting? if (modelTermSet.Terms.Any(t => t.CustomSortOrder > -1)) { var sortedTerms = modelTermSet.Terms.OrderBy(t => t.CustomSortOrder); var customSortString = sortedTerms.Aggregate(string.Empty, (a, i) => a + i.Id.ToString() + ":"); customSortString = customSortString.TrimEnd(new[] { ':' }); set.CustomSortOrder = customSortString; termStore.CommitAll(); web.Context.ExecuteQueryRetry(); } } #endregion } } return(parser); }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { if (template.Lists.Any()) { var rootWeb = (web.Context as ClientContext).Site.RootWeb; web.EnsureProperties(w => w.ServerRelativeUrl); web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl)); web.Context.ExecuteQueryRetry(); var existingLists = web.Lists.AsEnumerable().ToList(); var serverRelativeUrl = web.ServerRelativeUrl; var processedLists = new List<ListInfo>(); // Check if this is not a noscript site as we're not allowed to update some properties bool isNoScriptSite = web.IsNoScriptSite(); #region Lists foreach (var templateList in template.Lists) { // Check for the presence of the references content types and throw an exception if not present or in template if (templateList.ContentTypesEnabled) { var existingCts = web.Context.LoadQuery(web.AvailableContentTypes); web.Context.ExecuteQueryRetry(); foreach (var ct in templateList.ContentTypeBindings) { var found = template.ContentTypes.Any(t => t.Id.ToUpperInvariant() == ct.ContentTypeId.ToUpperInvariant()); if (found == false) { found = existingCts.Any(t => t.StringId.ToUpperInvariant() == ct.ContentTypeId.ToUpperInvariant()); } if (!found) { scope.LogError("Referenced content type {0} not available in site or in template", ct.ContentTypeId); throw new Exception(string.Format("Referenced content type {0} not available in site or in template", ct.ContentTypeId)); } } } // check if the List exists by url or by title var index = existingLists.FindIndex(x => x.Title.Equals(templateList.Title, StringComparison.OrdinalIgnoreCase) || x.RootFolder.ServerRelativeUrl.Equals(UrlUtility.Combine(serverRelativeUrl, templateList.Url), StringComparison.OrdinalIgnoreCase)); if (index == -1) { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_list__0_, templateList.Title); var returnTuple = CreateList(web, templateList, parser, scope, isNoScriptSite); var createdList = returnTuple.Item1; parser = returnTuple.Item2; processedLists.Add(new ListInfo { SiteList = createdList, TemplateList = templateList }); parser.AddToken(new ListIdToken(web, templateList.Title, createdList.Id)); parser.AddToken(new ListUrlToken(web, templateList.Title, createdList.RootFolder.ServerRelativeUrl.Substring(web.ServerRelativeUrl.Length + 1))); } catch (Exception ex) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_list__0__failed___1_____2_, templateList.Title, ex.Message, ex.StackTrace); throw; } } else { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_list__0_, templateList.Title); var existingList = web.Lists[index]; var returnTuple = UpdateList(web, existingList, templateList, parser, scope, isNoScriptSite); var updatedList = returnTuple.Item1; parser = returnTuple.Item2; if (updatedList != null) { processedLists.Add(new ListInfo { SiteList = updatedList, TemplateList = templateList }); } } catch (Exception ex) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_list__0__failed___1_____2_, templateList.Title, ex.Message, ex.StackTrace); throw; } } } #endregion #region FieldRefs foreach (var listInfo in processedLists) { if (listInfo.TemplateList.FieldRefs.Any()) { foreach (var fieldRef in listInfo.TemplateList.FieldRefs) { var field = rootWeb.GetFieldById<Field>(fieldRef.Id); if (field == null) { // log missing referenced field this.WriteWarning(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_InvalidFieldReference, listInfo.TemplateList.Title, fieldRef.Name, fieldRef.Id), ProvisioningMessageType.Error); // move onto next field reference continue; } if (!listInfo.SiteList.FieldExistsById(fieldRef.Id)) { field = CreateFieldRef(listInfo, field, fieldRef); } else { field = UpdateFieldRef(listInfo.SiteList, field.Id, fieldRef); } field.EnsureProperties(f => f.InternalName, f => f.Title); parser.AddToken(new FieldTitleToken(web, field.InternalName, field.Title)); #if !SP2013 var siteField = template.SiteFields.FirstOrDefault(f => Guid.Parse(XElement.Parse(f.SchemaXml).Attribute("ID").Value).Equals(field.Id)); if (siteField != null && siteField.SchemaXml.ContainsResourceToken()) { var isDirty = false; var originalFieldElement = XElement.Parse(siteField.SchemaXml); var nameAttributeValue = originalFieldElement.Attribute("DisplayName") != null ? originalFieldElement.Attribute("DisplayName").Value : ""; if (nameAttributeValue.ContainsResourceToken()) { if (field.TitleResource.SetUserResourceValue(nameAttributeValue, parser)) { isDirty = true; } } var descriptionAttributeValue = originalFieldElement.Attribute("Description") != null ? originalFieldElement.Attribute("Description").Value : ""; if (descriptionAttributeValue.ContainsResourceToken()) { if (field.DescriptionResource.SetUserResourceValue(descriptionAttributeValue, parser)) { isDirty = true; } } if (isDirty) { field.Update(); field.Context.ExecuteQueryRetry(); } } #endif } listInfo.SiteList.Update(); web.Context.ExecuteQueryRetry(); } } #endregion #region Fields foreach (var listInfo in processedLists) { if (listInfo.TemplateList.Fields.Any()) { foreach (var field in listInfo.TemplateList.Fields) { var fieldElement = XElement.Parse(parser.ParseString(field.SchemaXml, "~sitecollection", "~site")); if (fieldElement.Attribute("ID") == null) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field_schema_has_no_ID_attribute___0_, field.SchemaXml); throw new Exception(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field_schema_has_no_ID_attribute___0_, field.SchemaXml)); } var id = fieldElement.Attribute("ID").Value; Guid fieldGuid; if (!Guid.TryParse(id, out fieldGuid)) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_ID_for_field_is_not_a_valid_Guid___0_, field.SchemaXml); throw new Exception(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_ID_for_field_is_not_a_valid_Guid___0_, id)); } else { var fieldFromList = listInfo.SiteList.GetFieldById<Field>(fieldGuid); if (fieldFromList == null) { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_field__0_, fieldGuid); var createdField = CreateField(fieldElement, listInfo, parser, field.SchemaXml, web.Context, scope); if (createdField != null) { createdField.EnsureProperties(f => f.InternalName, f => f.Title); parser.AddToken(new FieldTitleToken(web, createdField.InternalName, createdField.Title)); } } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_field__0__failed___1_____2_, fieldGuid, ex.Message, ex.StackTrace); throw; } } else { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_field__0_, fieldGuid); var updatedField = UpdateField(web, listInfo, fieldGuid, fieldElement, fieldFromList, scope, parser, field.SchemaXml); if (updatedField != null) { updatedField.EnsureProperties(f => f.InternalName, f => f.Title); parser.AddToken(new FieldTitleToken(web, updatedField.InternalName, updatedField.Title)); } } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_field__0__failed___1_____2_, fieldGuid, ex.Message, ex.StackTrace); throw; } } } } } listInfo.SiteList.Update(); web.Context.ExecuteQueryRetry(); } #endregion #region Default Field Values foreach (var listInfo in processedLists) { if (listInfo.TemplateList.FieldDefaults.Any()) { foreach (var fieldDefault in listInfo.TemplateList.FieldDefaults) { var field = listInfo.SiteList.Fields.GetByInternalNameOrTitle(fieldDefault.Key); field.DefaultValue = fieldDefault.Value; field.Update(); web.Context.ExecuteQueryRetry(); } } } #endregion #region Views foreach (var listInfo in processedLists) { var list = listInfo.TemplateList; var createdList = listInfo.SiteList; if (list.Views.Any() && list.RemoveExistingViews) { while (createdList.Views.Any()) { createdList.Views[0].DeleteObject(); } web.Context.ExecuteQueryRetry(); } var existingViews = createdList.Views; web.Context.Load(existingViews, vs => vs.Include(v => v.Title, v => v.Id)); web.Context.ExecuteQueryRetry(); foreach (var view in list.Views) { CreateView(web, view, existingViews, createdList, scope); } //// Removing existing views set the OnQuickLaunch option to false and need to be re-set. //if (list.OnQuickLaunch && list.RemoveExistingViews && list.Views.Count > 0) //{ // createdList.RefreshLoad(); // web.Context.ExecuteQueryRetry(); // createdList.OnQuickLaunch = list.OnQuickLaunch; // createdList.Update(); // web.Context.ExecuteQueryRetry(); //} } #endregion #region Folders // Folders are supported for document libraries and generic lists only foreach (var list in processedLists) { list.SiteList.EnsureProperties(l => l.BaseType); if ((list.SiteList.BaseType == BaseType.DocumentLibrary | list.SiteList.BaseType == BaseType.GenericList) && list.TemplateList.Folders != null && list.TemplateList.Folders.Count > 0) { list.SiteList.EnableFolderCreation = true; list.SiteList.Update(); web.Context.ExecuteQueryRetry(); var rootFolder = list.SiteList.RootFolder; foreach (var folder in list.TemplateList.Folders) { CreateFolderInList(rootFolder, folder, parser, scope); } } } #endregion // If an existing view is updated, and the list is to be listed on the QuickLaunch, it is removed because the existing view will be deleted and recreated from scratch. foreach (var listInfo in processedLists) { listInfo.SiteList.OnQuickLaunch = listInfo.TemplateList.OnQuickLaunch; listInfo.SiteList.Update(); } web.Context.ExecuteQueryRetry(); } } return parser; }
public override TokenParser ProvisionObjects(Tenant tenant, Model.ProvisioningHierarchy hierarchy, string sequenceId, TokenParser tokenParser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(CoreResources.Provisioning_ObjectHandlers_Provisioning)) { var sequence = hierarchy.Sequences.FirstOrDefault(s => s.ID == sequenceId); if (sequence != null) { var siteUrls = new Dictionary <Guid, string>(); TokenParser siteTokenParser = null; foreach (var sitecollection in sequence.SiteCollections) { ClientContext siteContext = null; switch (sitecollection) { case TeamSiteCollection t: { TeamSiteCollectionCreationInformation siteInfo = new TeamSiteCollectionCreationInformation() { Alias = tokenParser.ParseString(t.Alias), DisplayName = tokenParser.ParseString(t.Title), Description = tokenParser.ParseString(t.Description), Classification = tokenParser.ParseString(t.Classification), IsPublic = t.IsPublic }; var groupSiteInfo = Sites.SiteCollection.GetGroupInfoAsync(tenant.Context as ClientContext, siteInfo.Alias).GetAwaiter().GetResult(); if (groupSiteInfo == null) { WriteMessage($"Creating Team Site {siteInfo.Alias}", ProvisioningMessageType.Progress); siteContext = Sites.SiteCollection.Create(tenant.Context as ClientContext, siteInfo, applyingInformation.DelayAfterModernSiteCreation); } else { if (groupSiteInfo.ContainsKey("siteUrl")) { WriteMessage($"Using existing Team Site {siteInfo.Alias}", ProvisioningMessageType.Progress); siteContext = (tenant.Context as ClientContext).Clone(groupSiteInfo["siteUrl"], applyingInformation.AccessTokens); } } if (t.IsHubSite) { siteContext.Load(siteContext.Site, s => s.Id); siteContext.ExecuteQueryRetry(); RegisterAsHubSite(tenant, siteContext.Url, siteContext.Site.Id, t.HubSiteLogoUrl, t.HubSiteTitle, tokenParser); } if (!string.IsNullOrEmpty(t.Theme)) { var parsedTheme = tokenParser.ParseString(t.Theme); tenant.SetWebTheme(parsedTheme, siteContext.Url); tenant.Context.ExecuteQueryRetry(); } if (t.Teamify) { try { WriteMessage($"Teamifying the O365 group connected site at URL - {siteContext.Url}", ProvisioningMessageType.Progress); siteContext.TeamifyAsync().GetAwaiter().GetResult(); } catch (Exception ex) { WriteMessage($"Teamifying site at URL - {siteContext.Url} failed due to an exception:- {ex.Message}", ProvisioningMessageType.Warning); } } if (t.HideTeamify) { try { WriteMessage($"Teamify prompt is now hidden for site at URL - {siteContext.Url}", ProvisioningMessageType.Progress); siteContext.HideTeamifyPrompt().GetAwaiter().GetResult(); } catch (Exception ex) { WriteMessage($"Teamify prompt couldn't be hidden for site at URL - {siteContext.Url} due to an exception:- {ex.Message}", ProvisioningMessageType.Warning); } } siteUrls.Add(t.Id, siteContext.Url); if (!string.IsNullOrEmpty(t.ProvisioningId)) { _additionalTokens.Add(new SequenceSiteUrlUrlToken(null, t.ProvisioningId, siteContext.Url)); siteContext.Web.EnsureProperty(w => w.Id); _additionalTokens.Add(new SequenceSiteIdToken(null, t.ProvisioningId, siteContext.Web.Id)); siteContext.Site.EnsureProperties(s => s.Id, s => s.GroupId); _additionalTokens.Add(new SequenceSiteCollectionIdToken(null, t.ProvisioningId, siteContext.Site.Id)); _additionalTokens.Add(new SequenceSiteGroupIdToken(null, t.ProvisioningId, siteContext.Site.GroupId)); } break; } case CommunicationSiteCollection c: { var siteUrl = tokenParser.ParseString(c.Url); if (!siteUrl.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase)) { var rootSiteUrl = tenant.GetRootSiteUrl(); tenant.Context.ExecuteQueryRetry(); siteUrl = UrlUtility.Combine(rootSiteUrl.Value, siteUrl); } CommunicationSiteCollectionCreationInformation siteInfo = new CommunicationSiteCollectionCreationInformation() { ShareByEmailEnabled = c.AllowFileSharingForGuestUsers, Classification = tokenParser.ParseString(c.Classification), Description = tokenParser.ParseString(c.Description), Lcid = (uint)c.Language, Owner = tokenParser.ParseString(c.Owner), Title = tokenParser.ParseString(c.Title), Url = siteUrl }; if (Guid.TryParse(c.SiteDesign, out Guid siteDesignId)) { siteInfo.SiteDesignId = siteDesignId; } else { if (!string.IsNullOrEmpty(c.SiteDesign)) { siteInfo.SiteDesign = (CommunicationSiteDesign)Enum.Parse(typeof(CommunicationSiteDesign), c.SiteDesign); } else { siteInfo.SiteDesign = CommunicationSiteDesign.Showcase; } } // check if site exists if (tenant.SiteExists(siteInfo.Url)) { WriteMessage($"Using existing Communications Site at {siteInfo.Url}", ProvisioningMessageType.Progress); siteContext = (tenant.Context as ClientContext).Clone(siteInfo.Url, applyingInformation.AccessTokens); } else { WriteMessage($"Creating Communications Site at {siteInfo.Url}", ProvisioningMessageType.Progress); siteContext = Sites.SiteCollection.Create(tenant.Context as ClientContext, siteInfo, applyingInformation.DelayAfterModernSiteCreation); } if (c.IsHubSite) { siteContext.Load(siteContext.Site, s => s.Id); siteContext.ExecuteQueryRetry(); RegisterAsHubSite(tenant, siteInfo.Url, siteContext.Site.Id, c.HubSiteLogoUrl, c.HubSiteTitle, tokenParser); } if (!string.IsNullOrEmpty(c.Theme)) { var parsedTheme = tokenParser.ParseString(c.Theme); tenant.SetWebTheme(parsedTheme, siteInfo.Url); tenant.Context.ExecuteQueryRetry(); } siteUrls.Add(c.Id, siteInfo.Url); if (!string.IsNullOrEmpty(c.ProvisioningId)) { _additionalTokens.Add(new SequenceSiteUrlUrlToken(null, c.ProvisioningId, siteInfo.Url)); siteContext.Web.EnsureProperty(w => w.Id); _additionalTokens.Add(new SequenceSiteIdToken(null, c.ProvisioningId, siteContext.Web.Id)); siteContext.Site.EnsureProperties(s => s.Id, s => s.GroupId); _additionalTokens.Add(new SequenceSiteCollectionIdToken(null, c.ProvisioningId, siteContext.Site.Id)); _additionalTokens.Add(new SequenceSiteGroupIdToken(null, c.ProvisioningId, siteContext.Site.GroupId)); } break; } case TeamNoGroupSiteCollection t: { var siteUrl = tokenParser.ParseString(t.Url); TeamNoGroupSiteCollectionCreationInformation siteInfo = new TeamNoGroupSiteCollectionCreationInformation() { Lcid = (uint)t.Language, Url = siteUrl, Title = tokenParser.ParseString(t.Title), Description = tokenParser.ParseString(t.Description), Owner = tokenParser.ParseString(t.Owner) }; if (tenant.SiteExists(siteUrl)) { WriteMessage($"Using existing Team Site at {siteUrl}", ProvisioningMessageType.Progress); siteContext = (tenant.Context as ClientContext).Clone(siteUrl, applyingInformation.AccessTokens); } else { WriteMessage($"Creating Team Site with no Office 365 group at {siteUrl}", ProvisioningMessageType.Progress); siteContext = Sites.SiteCollection.Create(tenant.Context as ClientContext, siteInfo, applyingInformation.DelayAfterModernSiteCreation); } if (t.IsHubSite) { siteContext.Load(siteContext.Site, s => s.Id); siteContext.ExecuteQueryRetry(); RegisterAsHubSite(tenant, siteContext.Url, siteContext.Site.Id, t.HubSiteLogoUrl, t.HubSiteTitle, tokenParser); } if (!string.IsNullOrEmpty(t.Theme)) { var parsedTheme = tokenParser.ParseString(t.Theme); tenant.SetWebTheme(parsedTheme, siteContext.Url); tenant.Context.ExecuteQueryRetry(); } siteUrls.Add(t.Id, siteContext.Url); if (!string.IsNullOrEmpty(t.ProvisioningId)) { _additionalTokens.Add(new SequenceSiteUrlUrlToken(null, t.ProvisioningId, siteContext.Url)); siteContext.Web.EnsureProperty(w => w.Id); _additionalTokens.Add(new SequenceSiteIdToken(null, t.ProvisioningId, siteContext.Web.Id)); siteContext.Site.EnsureProperties(s => s.Id, s => s.GroupId); _additionalTokens.Add(new SequenceSiteCollectionIdToken(null, t.ProvisioningId, siteContext.Site.Id)); _additionalTokens.Add(new SequenceSiteGroupIdToken(null, t.ProvisioningId, siteContext.Site.GroupId)); } break; } } var web = siteContext.Web; if (siteTokenParser == null) { siteTokenParser = new TokenParser(tenant, hierarchy, applyingInformation); foreach (var token in _additionalTokens) { siteTokenParser.AddToken(token); } } foreach (var subsite in sitecollection.Sites) { var subSiteObject = (TeamNoGroupSubSite)subsite; web.EnsureProperties(w => w.Webs.IncludeWithDefaultProperties(), w => w.ServerRelativeUrl); siteTokenParser = CreateSubSites(hierarchy, siteTokenParser, sitecollection, siteContext, web, subSiteObject); } siteTokenParser = null; } // System.Threading.Thread.Sleep(TimeSpan.FromMinutes(10)); WriteMessage("Applying templates", ProvisioningMessageType.Progress); var currentSite = ""; var provisioningTemplateApplyingInformation = new ProvisioningTemplateApplyingInformation(); provisioningTemplateApplyingInformation.AccessTokens = applyingInformation.AccessTokens; provisioningTemplateApplyingInformation.MessagesDelegate = applyingInformation.MessagesDelegate; provisioningTemplateApplyingInformation.ProgressDelegate = (string message, int step, int total) => { applyingInformation.ProgressDelegate?.Invoke($"{currentSite} : {message}", step, total); }; provisioningTemplateApplyingInformation.SiteProvisionedDelegate = applyingInformation.SiteProvisionedDelegate; foreach (var sitecollection in sequence.SiteCollections) { currentSite = sitecollection.ProvisioningId != null ? sitecollection.ProvisioningId : sitecollection.Title; siteUrls.TryGetValue(sitecollection.Id, out string siteUrl); if (siteUrl != null) { using (var clonedContext = tenant.Context.Clone(siteUrl, applyingInformation.AccessTokens)) { var web = clonedContext.Web; foreach (var templateRef in sitecollection.Templates) { var provisioningTemplate = hierarchy.Templates.FirstOrDefault(t => t.Id == templateRef); if (provisioningTemplate != null) { provisioningTemplate.Connector = hierarchy.Connector; //if (siteTokenParser == null) //{ siteTokenParser = new TokenParser(web, provisioningTemplate, applyingInformation); foreach (var token in _additionalTokens) { siteTokenParser.AddToken(token); } //} //else //{ // siteTokenParser.Rebase(web, provisioningTemplate); //} WriteMessage($"Applying Template", ProvisioningMessageType.Progress); new SiteToTemplateConversion().ApplyRemoteTemplate(web, provisioningTemplate, provisioningTemplateApplyingInformation, true, siteTokenParser); } else { WriteMessage($"Referenced template ID {templateRef} not found", ProvisioningMessageType.Error); } } if (siteTokenParser == null) { siteTokenParser = new TokenParser(tenant, hierarchy, applyingInformation); foreach (var token in _additionalTokens) { siteTokenParser.AddToken(token); } } foreach (var subsite in sitecollection.Sites) { var subSiteObject = (TeamNoGroupSubSite)subsite; web.EnsureProperties(w => w.Webs.IncludeWithDefaultProperties(), w => w.ServerRelativeUrl); siteTokenParser = ApplySubSiteTemplates(hierarchy, siteTokenParser, sitecollection, clonedContext, web, subSiteObject, provisioningTemplateApplyingInformation); } if (sitecollection.IsHubSite) { RESTUtilities.ExecuteGet(web, "/_api/web/hubsitedata(true)").GetAwaiter().GetResult(); } } } } } return(tokenParser); } }