public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { // if this is a sub site then we're not provisioning fields. Technically this can be done but it's not a recommended practice if (web.IsSubSite() && !applyingInformation.ProvisionFieldsToSubWebs) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Fields_Context_web_is_subweb__skipping_site_columns); WriteMessage("This template contains fields and you are provisioning to a subweb. If you still want to provision these fields, set the ProvisionFieldsToSubWebs property to true.", ProvisioningMessageType.Warning); return(parser); } var existingFields = web.Fields; web.Context.Load(existingFields, fs => fs.Include(f => f.Id)); web.Context.ExecuteQueryRetry(); var existingFieldIds = existingFields.AsEnumerable <SPField>().Select(l => l.Id).ToList(); var fields = template.SiteFields; var currentFieldIndex = 0; foreach (var field in fields) { currentFieldIndex++; XElement templateFieldElement = XElement.Parse(parser.ParseXmlString(field.SchemaXml, "~sitecollection", "~site")); var fieldId = templateFieldElement.Attribute("ID").Value; var fieldInternalName = templateFieldElement.Attribute("InternalName") != null?templateFieldElement.Attribute("InternalName").Value : ""; WriteMessage($"Field|{(!string.IsNullOrWhiteSpace(fieldInternalName) ? fieldInternalName : fieldId)}|{currentFieldIndex}|{fields.Count}", ProvisioningMessageType.Progress); if (!existingFieldIds.Contains(Guid.Parse(fieldId))) { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Fields_Adding_field__0__to_site, fieldId); CreateField(web, templateFieldElement, scope, parser, field.SchemaXml); } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_Fields_Adding_field__0__failed___1_____2_, fieldId, ex.Message, ex.StackTrace); throw; } } else { try { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Fields_Updating_field__0__in_site, fieldId); UpdateField(web, fieldId, templateFieldElement, scope, parser, field.SchemaXml); } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_Fields_Updating_field__0__failed___1_____2_, fieldId, ex.Message, ex.StackTrace); throw; } } } } WriteMessage($"Done processing fields", ProvisioningMessageType.Completed); return(parser); }
private static void CreateField(Web web, XElement templateFieldElement, PnPMonitoredScope scope, TokenParser parser, string originalFieldXml) { var fieldXml = parser.ParseXmlString(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.Id, 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}"); } }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { var site = (web.Context as ClientContext).Site; if (!String.IsNullOrEmpty(template.SiteSearchSettings)) { site.SetSearchConfiguration(parser.ParseXmlString(template.SiteSearchSettings)); } if (!String.IsNullOrEmpty(template.WebSearchSettings)) { web.SetSearchConfiguration(parser.ParseXmlString(template.WebSearchSettings)); } } return(parser); }
internal static XElement GetSchemaXml(this Field templateField, TokenParser parser, params string[] tokensToSkip) { XElement schemaElement; if (!_fieldXmlDictionary.TryGetValue(templateField, out schemaElement)) { schemaElement = XElement.Parse(parser.ParseXmlString(templateField.SchemaXml, tokensToSkip)); _fieldXmlDictionary[templateField] = schemaElement; } return(schemaElement); }
internal static Guid GetFieldId(this Field templateField, TokenParser parser) { XElement schemaElement; if (!_fieldXmlDictionary.TryGetValue(templateField, out schemaElement)) { schemaElement = XElement.Parse(parser.ParseXmlString(templateField.SchemaXml)); _fieldXmlDictionary[templateField] = schemaElement; } var id = (Guid)schemaElement.Attribute("ID"); return(id); }
internal static Step GetFieldProvisioningStep(this Field templateField, TokenParser parser) { XElement schemaElement; if (!_fieldXmlDictionary.TryGetValue(templateField, out schemaElement)) { schemaElement = XElement.Parse(parser.ParseXmlString(templateField.SchemaXml)); _fieldXmlDictionary[templateField] = schemaElement; } var type = (string)schemaElement.Attribute("Type"); if (type != "Lookup" && type != "LookupMulti") { return(Step.ListAndStandardFields); } return(Step.LookupFields); }
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++; WriteMessage($"File|{targetFileName}|{currentFileIndex}|{filesToProcess.Length}", ProvisioningMessageType.Progress); 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); 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 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); } 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); } } web = originalWeb; // restore context in case files are provisioned to the master page gallery #1059 } } WriteMessage("Done processing files", ProvisioningMessageType.Completed); return(parser); }
private void UpdateField(Web web, string fieldId, XElement templateFieldElement, PnPMonitoredScope scope, TokenParser parser, string originalFieldXml) { var existingField = web.Fields.GetById(Guid.Parse(fieldId)); web.Context.Load(existingField, f => f.SchemaXml); web.Context.ExecuteQueryRetry(); XElement existingFieldElement = XElement.Parse(existingField.SchemaXml); XNodeEqualityComparer equalityComparer = new XNodeEqualityComparer(); if (equalityComparer.GetHashCode(existingFieldElement) != equalityComparer.GetHashCode(templateFieldElement)) // Is field different in template? { if (existingFieldElement.Attribute("Type").Value == templateFieldElement.Attribute("Type").Value) // Is existing field of the same type? { var listIdentifier = templateFieldElement.Attribute("List") != null?templateFieldElement.Attribute("List").Value : null; if (listIdentifier != null) { // Temporary remove list attribute from list templateFieldElement.Attribute("List").Remove(); } if (IsFieldXmlValid(parser.ParseXmlString(originalFieldXml), parser, web.Context)) { foreach (var attribute in templateFieldElement.Attributes()) { if (existingFieldElement.Attribute(attribute.Name) != null) { existingFieldElement.Attribute(attribute.Name).Value = attribute.Value; } else { existingFieldElement.Add(attribute); } } foreach (var element in templateFieldElement.Elements()) { if (existingFieldElement.Element(element.Name) != null) { existingFieldElement.Element(element.Name).Remove(); } existingFieldElement.Add(element); } if (string.Equals(templateFieldElement.Attribute("Type").Value, "Calculated", StringComparison.OrdinalIgnoreCase)) { var fieldRefsElement = existingFieldElement.Descendants("FieldRefs").FirstOrDefault(); if (fieldRefsElement != null) { fieldRefsElement.Remove(); } } if (existingFieldElement.Attribute("Version") != null) { existingFieldElement.Attributes("Version").Remove(); } existingField.SchemaXml = parser.ParseXmlString(existingFieldElement.ToString(), "~sitecollection", "~site"); existingField.UpdateAndPushChanges(true); web.Context.Load(existingField, f => f.TypeAsString, f => f.DefaultValue); try { web.Context.ExecuteQueryRetry(); } catch (ServerException se) { if (se.ServerErrorTypeName == "Microsoft.SharePoint.Client.ClientServiceTimeoutException") { string fieldName = existingFieldElement.Attribute("Name") != null?existingFieldElement.Attribute("Name").Value : existingFieldElement.Attribute("StaticName").Value; WriteMessage(string.Format(CoreResources.Provisioning_ObjectHandlers_Fields_Updating_field__0__timeout, fieldName), ProvisioningMessageType.Warning); scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_Fields_Updating_field__0__timeout, fieldName); web.Context.Load(existingField, f => f.TypeAsString, f => f.DefaultValue); web.Context.ExecuteQueryRetry(); } else { throw; } } 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()) { existingField.TitleResource.SetUserResourceValue(nameAttributeValue, parser); isDirty = true; } var descriptionAttributeValue = originalFieldElement.Attribute("Description") != null?originalFieldElement.Attribute("Description").Value : ""; if (descriptionAttributeValue.ContainsResourceToken()) { existingField.DescriptionResource.SetUserResourceValue(descriptionAttributeValue, parser); isDirty = true; } } #endif if (isDirty) { existingField.Update(); web.Context.ExecuteQueryRetry(); } if ((existingField.TypeAsString == "TaxonomyFieldType" || existingField.TypeAsString == "TaxonomyFieldTypeMulti")) { var taxField = web.Context.CastTo <TaxonomyField>(existingField); if (!string.IsNullOrEmpty(existingField.DefaultValue)) { ValidateTaxonomyFieldDefaultValue(taxField); } SetTaxonomyFieldOpenValue(taxField, originalFieldXml); } } else { // The field Xml was found invalid var tokenString = parser.GetLeftOverTokens(originalFieldXml).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}"); } } else { var fieldName = existingFieldElement.Attribute("Name") != null?existingFieldElement.Attribute("Name").Value : existingFieldElement.Attribute("StaticName").Value; WriteMessage(string.Format(CoreResources.Provisioning_ObjectHandlers_Fields_Field__0____1___exists_but_is_of_different_type__Skipping_field_, fieldName, fieldId), ProvisioningMessageType.Warning); scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_Fields_Field__0____1___exists_but_is_of_different_type__Skipping_field_, fieldName, fieldId); } } }
public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation) { using (var scope = new PnPMonitoredScope(this.Name)) { // Get a reference to infrastructural services WorkflowServicesManager servicesManager = null; try { servicesManager = new WorkflowServicesManager(web.Context, web); } catch (ServerException) { // If there is no workflow service present in the farm this method will throw an error. // Swallow the exception } if (servicesManager != null) { var deploymentService = servicesManager.GetWorkflowDeploymentService(); var subscriptionService = servicesManager.GetWorkflowSubscriptionService(); // Pre-load useful properties web.EnsureProperty(w => w.Id); // Provision Workflow Definitions foreach (var templateDefinition in template.Workflows.WorkflowDefinitions) { // Load the Workflow Definition XAML Stream xamlStream = template.Connector.GetFileStream(templateDefinition.XamlPath); XElement xaml = XElement.Load(xamlStream); int retryCount = 5; int retryAttempts = 1; int delay = 2000; while (retryAttempts <= retryCount) { try { var workflowDefinition = deploymentService.GetDefinition(templateDefinition.Id); web.Context.Load(workflowDefinition); web.Context.ExecuteQueryRetry(); // If Definition does not exist, create it // Prevent an exception if already exists if (workflowDefinition.ServerObjectIsNull()) { // Create the WorkflowDefinition instance workflowDefinition = new Microsoft.SharePoint.Client.WorkflowServices.WorkflowDefinition(web.Context) { AssociationUrl = templateDefinition.AssociationUrl, Description = templateDefinition.Description, DisplayName = templateDefinition.DisplayName, FormField = templateDefinition.FormField, DraftVersion = templateDefinition.DraftVersion, Id = templateDefinition.Id, InitiationUrl = templateDefinition.InitiationUrl, RequiresAssociationForm = templateDefinition.RequiresAssociationForm, RequiresInitiationForm = templateDefinition.RequiresInitiationForm, RestrictToScope = parser.ParseString(templateDefinition.RestrictToScope), RestrictToType = templateDefinition.RestrictToType != "Universal" ? templateDefinition.RestrictToType : null, Xaml = parser.ParseXmlString(xaml.ToString()), }; // Save the Workflow Definition var newDefinition = deploymentService.SaveDefinition(workflowDefinition); web.Context.ExecuteQueryRetry(); // Let's publish the Workflow Definition, if needed if (templateDefinition.Published) { deploymentService.PublishDefinition(newDefinition.Value); web.Context.ExecuteQueryRetry(); } } else { // Otherwise update the XAML definition workflowDefinition.AssociationUrl = templateDefinition.AssociationUrl; workflowDefinition.Description = templateDefinition.Description; workflowDefinition.DisplayName = templateDefinition.DisplayName; workflowDefinition.FormField = templateDefinition.FormField; workflowDefinition.DraftVersion = templateDefinition.DraftVersion; workflowDefinition.InitiationUrl = templateDefinition.InitiationUrl; workflowDefinition.RequiresAssociationForm = templateDefinition.RequiresAssociationForm; workflowDefinition.RequiresInitiationForm = templateDefinition.RequiresInitiationForm; workflowDefinition.RestrictToScope = parser.ParseString(templateDefinition.RestrictToScope); workflowDefinition.RestrictToType = templateDefinition.RestrictToType != "Universal" ? templateDefinition.RestrictToType : null; workflowDefinition.Xaml = parser.ParseXmlString(xaml.ToString()); var updatedDefinition = deploymentService.SaveDefinition(workflowDefinition); web.Context.ExecuteQueryRetry(); // Let's publish the Workflow Definition, if needed if (templateDefinition.Published) { deploymentService.PublishDefinition(updatedDefinition.Value); web.Context.ExecuteQueryRetry(); } } // If we are here, we have the workflow definition // and we did not have any exception. // Thus, we can exit from the loop break; } catch (Exception ex) { // check exception is due to connection closed issue if (ex is ServerException && ((ServerException)ex).ServerErrorCode == -2130575223 && ((ServerException)ex).ServerErrorTypeName.Equals("Microsoft.SharePoint.SPException", StringComparison.InvariantCultureIgnoreCase) && ((ServerException)ex).Message.Contains("A connection that was expected to be kept alive was closed by the server.") ) { WriteMessage($"Connection closed whilst adding Workflow Definition, trying again in {delay}ms", ProvisioningMessageType.Warning); Thread.Sleep(delay); retryAttempts++; delay = delay * 2; // double delay for next retry } else { throw; } } } } // get existing subscriptions var existingWorkflowSubscriptions = web.GetWorkflowSubscriptions(); foreach (var subscription in template.Workflows.WorkflowSubscriptions) { Microsoft.SharePoint.Client.WorkflowServices.WorkflowSubscription workflowSubscription = null; // Check if the subscription already exists before adding it, and // if already exists a subscription with the same name and with the same DefinitionId, // it is a duplicate and we just need to update it string subscriptionName; if (subscription.PropertyDefinitions.TryGetValue("SharePointWorkflowContext.Subscription.Name", out subscriptionName) && existingWorkflowSubscriptions.Any(s => s.PropertyDefinitions["SharePointWorkflowContext.Subscription.Name"] == subscriptionName && s.DefinitionId == subscription.DefinitionId)) { // Thus, delete it before adding it again! WriteMessage($"Workflow Subscription '{subscription.Name}' already exists. It will be updated.", ProvisioningMessageType.Warning); workflowSubscription = existingWorkflowSubscriptions.FirstOrDefault((s => s.PropertyDefinitions["SharePointWorkflowContext.Subscription.Name"] == subscriptionName && s.DefinitionId == subscription.DefinitionId)); } if (workflowSubscription != null) { // Update The existing subscription instead of delete the existing one. // Only update the following properties workflowSubscription.Enabled = subscription.Enabled; workflowSubscription.EventTypes = subscription.EventTypes; workflowSubscription.ManualStartBypassesActivationLimit = subscription.ManualStartBypassesActivationLimit; workflowSubscription.StatusFieldName = subscription.StatusFieldName; } else { // Create the WorkflowDefinition instance workflowSubscription = new Microsoft.SharePoint.Client.WorkflowServices.WorkflowSubscription(web.Context) { DefinitionId = subscription.DefinitionId, Enabled = subscription.Enabled, EventSourceId = (!String.IsNullOrEmpty(subscription.EventSourceId)) ? Guid.Parse(parser.ParseString(subscription.EventSourceId)) : web.Id, EventTypes = subscription.EventTypes, #if !ONPREMISES ParentContentTypeId = subscription.ParentContentTypeId, #endif ManualStartBypassesActivationLimit = subscription.ManualStartBypassesActivationLimit, Name = subscription.Name, StatusFieldName = subscription.StatusFieldName, }; foreach (var propertyDefinition in subscription.PropertyDefinitions .Where(d => d.Key == "TaskListId" || d.Key == "HistoryListId" || d.Key == "SharePointWorkflowContext.Subscription.Id" || d.Key == "SharePointWorkflowContext.Subscription.Name" || d.Key == "CreatedBySPD" || d.Key == "StatusColumnCreated")) // If set to "0" the status column will be created automatically. { workflowSubscription.SetProperty(propertyDefinition.Key, parser.ParseString(propertyDefinition.Value)); } } if (!String.IsNullOrEmpty(subscription.ListId)) { // It is a List Workflow Guid targetListId = Guid.Parse(parser.ParseString(subscription.ListId)); subscriptionService.PublishSubscriptionForList(workflowSubscription, targetListId); } else { // It is a Site Workflow subscriptionService.PublishSubscription(workflowSubscription); } web.Context.ExecuteQueryRetry(); } } } 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.ParseXmlString(webPart.Contents.Trim(new[] { '\n', ' ' }), "~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)) { // 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(); var context = web.Context as ClientContext; 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 currentFileIndex = 0; foreach (var file in filesToProcess) { var targetFileName = !String.IsNullOrEmpty(file.TargetFileName) ? file.TargetFileName : file.Src; currentFileIndex++; WriteMessage($"File|{targetFileName}|{currentFileIndex}|{filesToProcess.Length}", ProvisioningMessageType.Progress); var folderName = parser.ParseString(file.Folder); 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); 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 = GetFileStream(template, file)) { targetFile = UploadFile(template, file, folder, stream); } } else { checkedOut = CheckOutIfNeeded(web, targetFile); } } else { using (var stream = GetFileStream(template, file)) { scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Files_Uploading_file__0_, targetFileName); targetFile = UploadFile(template, file, folder, stream); } checkedOut = CheckOutIfNeeded(web, targetFile); } if (targetFile != null) { 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, false); } #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 #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 } } } #if !SP2013 if (webPartsNeedLocalization) { file.LocalizeWebParts(web, parser, targetFile, scope); } #endif 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("Done processing files", ProvisioningMessageType.Completed); return(parser); }