AddToken() public method

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;
        }
Esempio n. 3
0
        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);
            }
        }
Esempio n. 8
0
        //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;
            }
        }
Esempio n. 9
0
        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;
        }
Esempio n. 10
0
        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;
        }
Esempio n. 11
0
        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);
        }
Esempio n. 12
0
        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);
        }
Esempio n. 14
0
        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;
            }
        }
Esempio n. 16
0
        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);
        }
Esempio n. 18
0
        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);
        }
Esempio n. 19
0
        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);
        }
Esempio n. 20
0
        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);
        }
Esempio n. 21
0
        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);
        }
Esempio n. 22
0
        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}");
            }
        }
Esempio n. 23
0
        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);
        }
Esempio n. 25
0
        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;
        }
Esempio n. 26
0
        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
            }
        }
Esempio n. 27
0
        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;
            }
        }
Esempio n. 28
0
        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;
        }
Esempio n. 30
0
        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);
        }
Esempio n. 31
0
        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);
            }
        }