ParseString() public method

public ParseString ( string input ) : string
input string
return string
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (template.ComposedLook != null &&
                    !template.ComposedLook.Equals(ComposedLook.Empty))
                {
                    bool executeQueryNeeded = false;
                    if (executeQueryNeeded)
                    {
                        web.Context.ExecuteQueryRetry();
                    }

                    if (String.IsNullOrEmpty(template.ComposedLook.ColorFile) &&
                        String.IsNullOrEmpty(template.ComposedLook.FontFile) &&
                        String.IsNullOrEmpty(template.ComposedLook.BackgroundFile))
                    {
                        // Apply OOB theme
                        web.SetComposedLookByUrl(template.ComposedLook.Name);
                    }
                    else
                    {
                        // Apply custom theme
                        string colorFile = null;
                        if (!string.IsNullOrEmpty(template.ComposedLook.ColorFile))
                        {
                            colorFile = parser.ParseString(template.ComposedLook.ColorFile);
                        }
                        string backgroundFile = null;
                        if (!string.IsNullOrEmpty(template.ComposedLook.BackgroundFile))
                        {
                            backgroundFile = parser.ParseString(template.ComposedLook.BackgroundFile);
                        }
                        string fontFile = null;
                        if (!string.IsNullOrEmpty(template.ComposedLook.FontFile))
                        {
                            fontFile = parser.ParseString(template.ComposedLook.FontFile);
                        }

                        string masterUrl = null;
                        if (template.WebSettings != null && !string.IsNullOrEmpty(template.WebSettings.MasterPageUrl))
                        {
                            masterUrl = parser.ParseString(template.WebSettings.MasterPageUrl);
                        }
                        web.CreateComposedLookByUrl(template.ComposedLook.Name, colorFile, fontFile, backgroundFile, masterUrl);
                        web.SetComposedLookByUrl(template.ComposedLook.Name, colorFile, fontFile, backgroundFile, masterUrl);

                        var composedLookJson = JsonConvert.SerializeObject(template.ComposedLook);

                        web.SetPropertyBagValue("_PnP_ProvisioningTemplateComposedLookInfo", composedLookJson);
                    }

                    // Persist composed look info in property bag

                }
            }
            return parser;
        }
 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))
     {
         var context = web.Context as ClientContext;
         foreach (var handler in template.ExtensibilityHandlers
             .Union(template.Providers)
             .Union(applyingInformation.ExtensibilityHandlers))
         {
             if (handler.Enabled)
             {
                 try
                 {
                     if (!string.IsNullOrEmpty(handler.Configuration))
                     {
                         //replace tokens in configuration data
                         handler.Configuration = parser.ParseString(handler.Configuration);
                     }
                     scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ExtensibilityProviders_Calling_extensibility_callout__0_, handler.Assembly);
                     _extManager.ExecuteExtensibilityProvisionCallOut(context, handler, template, applyingInformation, parser, scope);
                 }
                 catch (Exception ex)
                 {
                     scope.LogError(CoreResources.Provisioning_ObjectHandlers_ExtensibilityProviders_callout_failed___0_____1_, ex.Message, ex.StackTrace);
                     throw;
                 }
             }
         }
     }
     return parser;
 }
        public void ParseTests()
        {
            using (var ctx = TestCommon.CreateClientContext())
            {
                ctx.Load(ctx.Web, w => w.ServerRelativeUrl);
                ctx.Load(ctx.Site, s => s.ServerRelativeUrl);

                var masterCatalog = ctx.Web.GetCatalog((int)ListTemplateType.MasterPageCatalog);
                ctx.Load(masterCatalog, m => m.RootFolder.ServerRelativeUrl);

                var themesCatalog = ctx.Web.GetCatalog((int)ListTemplateType.ThemeCatalog);
                ctx.Load(themesCatalog, t => t.RootFolder.ServerRelativeUrl);

                ctx.ExecuteQueryRetry();

                ProvisioningTemplate template = new ProvisioningTemplate();
                template.Parameters.Add("test", "test");

                var parser = new TokenParser(ctx.Web, template);

                var site1 = parser.ParseString("~siTE/test");
                var site2 = parser.ParseString("{site}/test");
                var sitecol1 = parser.ParseString("~siteCOLLECTION/test");
                var sitecol2 = parser.ParseString("{sitecollection}/test");
                var masterUrl1 = parser.ParseString("~masterpagecatalog/test");
                var masterUrl2 = parser.ParseString("{masterpagecatalog}/test");
                var themeUrl1 = parser.ParseString("~themecatalog/test");
                var themeUrl2 = parser.ParseString("{themecatalog}/test");
                var parameterTest1 = parser.ParseString("abc{parameter:TEST}/test");
                var parameterTest2 = parser.ParseString("abc{$test}/test");

                Assert.IsTrue(site1 == string.Format("{0}/test", ctx.Web.ServerRelativeUrl));
                Assert.IsTrue(site2 == string.Format("{0}/test", ctx.Web.ServerRelativeUrl));
                Assert.IsTrue(sitecol1 == string.Format("{0}/test", ctx.Site.ServerRelativeUrl));
                Assert.IsTrue(sitecol2 == string.Format("{0}/test", ctx.Site.ServerRelativeUrl));
                Assert.IsTrue(masterUrl1 == string.Format("{0}/test", masterCatalog.RootFolder.ServerRelativeUrl));
                Assert.IsTrue(masterUrl2 == string.Format("{0}/test", masterCatalog.RootFolder.ServerRelativeUrl));
                Assert.IsTrue(themeUrl1 == string.Format("{0}/test", themesCatalog.RootFolder.ServerRelativeUrl));
                Assert.IsTrue(themeUrl2 == string.Format("{0}/test", themesCatalog.RootFolder.ServerRelativeUrl));
                Assert.IsTrue(parameterTest1 == "abctest/test");
                Assert.IsTrue(parameterTest2 == "abctest/test");

            }
        }
示例#5
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                // if this is a sub site then we're not provisioning fields. Technically this can be done but it's not a recommended practice
                if (web.IsSubSite())
                {
                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Fields_Context_web_is_subweb__skipping_site_columns);
                    return parser;
                }

                var existingFields = web.Fields;

                web.Context.Load(existingFields, fs => fs.Include(f => f.Id));
                web.Context.ExecuteQueryRetry();
                var existingFieldIds = existingFields.AsEnumerable<SPField>().Select(l => l.Id).ToList();
                var fields = template.SiteFields;

                foreach (var field in fields)
                {
                    XElement templateFieldElement = XElement.Parse(parser.ParseString(field.SchemaXml, "~sitecollection", "~site"));
                    var fieldId = templateFieldElement.Attribute("ID").Value;

                    if (!existingFieldIds.Contains(Guid.Parse(fieldId)))
                    {
                        try
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Fields_Adding_field__0__to_site, fieldId);
                            CreateField(web, templateFieldElement, scope, parser, field.SchemaXml);
                        }
                        catch (Exception ex)
                        {
                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_Fields_Adding_field__0__failed___1_____2_, fieldId, ex.Message, ex.StackTrace);
                            throw;
                        }
                    }
                    else
                        try
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Fields_Updating_field__0__in_site, fieldId);
                            UpdateField(web, fieldId, templateFieldElement, scope, parser, field.SchemaXml);
                        }
                        catch (Exception ex)
                        {
                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_Fields_Updating_field__0__failed___1_____2_, fieldId, ex.Message, ex.StackTrace);
                            throw;
                        }
                }
            }
            return parser;
        }
        public static bool ValidateCustomActions(CustomActionCollection source, CustomActionCollection target, TokenParser tokenParser, Web web = null)
        {
            int sCount = 0;
            int tCount = 0;

            if (web != null && web.IsNoScriptSite())
            {
                Console.WriteLine("Skipping validation of custom actions due to noscript site.");
                return true;
            }

            foreach (CustomAction srcSCA in source)
            {
                //Only count the enabled ones
                if (srcSCA.Enabled && !srcSCA.Remove)
                {
                    // ensure token in source are parsed before comparing with target
                    srcSCA.Title = tokenParser.ParseString(srcSCA.Title);
                    srcSCA.ImageUrl = tokenParser.ParseString(srcSCA.ImageUrl);
                    srcSCA.ScriptBlock = tokenParser.ParseString(srcSCA.ScriptBlock);
                    srcSCA.ScriptSrc = tokenParser.ParseString(srcSCA.ScriptSrc, "~site", "~sitecollection");
                    srcSCA.Title = tokenParser.ParseString(srcSCA.Title);
                    srcSCA.Url = tokenParser.ParseString(srcSCA.Url);
                    if (srcSCA.CommandUIExtension != null)
                    {
                        srcSCA.CommandUIExtension = XElement.Parse(tokenParser.ParseString(srcSCA.CommandUIExtension.ToString()));
                    }

                    sCount++;
                    foreach (CustomAction tgtSCA in target)
                    {
                        if (tgtSCA.CommandUIExtension != null)
                        {
                            // Drop the namespace attribute before comparing (xmlns="http://schemas.microsoft.com/sharepoint").
                            // SharePoint injects this namespace when we extract a custom action that has a commandUIExtension
                            tgtSCA.CommandUIExtension = RemoveAllNamespaces(tgtSCA.CommandUIExtension);
                        }

                        // Use our custom action "Equals" implementation
                        if (srcSCA.Equals(tgtSCA))
                        {
                            tCount++;
                            break;
                        }
                        else
                        {
                            Console.WriteLine("{0} is not matching", tgtSCA.Name);
                        }
                    }
                }
            }

            if (sCount != tCount)
            {
                return false;
            }

            // cross check that enabled false custom actions do not exist anymore
            foreach (CustomAction srcSCA in source)
            {
                if (!srcSCA.Enabled || srcSCA.Remove)
                {
                    var ca = target.Where(w => w.Name == srcSCA.Name).FirstOrDefault();
                    if (ca != null)
                    {
                        return false;
                    }
                }
            }

            return true;
        }
        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;
                                    }
                                }
                                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);
        }
示例#8
0
        private void CallWebHooks(ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateWebhookKind kind, ObjectHandlerBase objectHandler = null)
        {
            using (var scope = new PnPMonitoredScope("ProvisioningTemplate WebHook Call"))
            {
                if (template.ProvisioningTemplateWebhooks != null && template.ProvisioningTemplateWebhooks.Any())
                {
                    foreach (var webhook in template.ProvisioningTemplateWebhooks.Where(w => w.Kind == kind))
                    {
                        SimpleTokenParser internalParser = new SimpleTokenParser();
                        foreach (var webhookparam in webhook.Parameters)
                        {
                            internalParser.AddToken(new WebhookParameter(parser.ParseString(webhookparam.Key), parser.ParseString(webhookparam.Value)));
                        }
                        var url = parser.ParseString(webhook.Url); // parse for template scoped parameters
                        url = internalParser.ParseString(url);     // parse for webhook scoped parameters


                        switch (webhook.Method)
                        {
                        case ProvisioningTemplateWebhookMethod.GET:
                        {
                            if (kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted || kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted)
                            {
                                url += $"&__handler={objectHandler.InternalName}";
                            }
                            try
                            {
                                using (var client = new HttpClient())
                                {
                                    if (webhook.Async)
                                    {
                                        client.GetAsync(url);
                                    }
                                    else
                                    {
                                        client.GetAsync(url).GetAwaiter().GetResult();
                                    }
                                }
                            }
                            catch (HttpRequestException ex)
                            {
                                scope.LogError(ex, "Error calling provisioning template webhook");
                            }
                            break;
                        }

                        case ProvisioningTemplateWebhookMethod.POST:
                        {
                            if (kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted || kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted)
                            {
                                webhook.Parameters.Add("__handler", objectHandler.InternalName);
                            }
                            try
                            {
                                using (var client = new HttpClient())
                                {
                                    if (webhook.Async)
                                    {
                                        switch (webhook.BodyFormat)
                                        {
                                        case ProvisioningTemplateWebhookBodyFormat.Json:
                                            client.PostAsJsonAsync(url, webhook.Parameters);
                                            break;

                                        case ProvisioningTemplateWebhookBodyFormat.Xml:
                                            client.PostAsXmlAsync(url, webhook.Parameters);
                                            break;

                                        case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                                            var content = new FormUrlEncodedContent(webhook.Parameters);
                                            client.PostAsync(url, content);
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        switch (webhook.BodyFormat)
                                        {
                                        case ProvisioningTemplateWebhookBodyFormat.Json:
                                            client.PostAsJsonAsync(url, webhook.Parameters).GetAwaiter().GetResult();
                                            break;

                                        case ProvisioningTemplateWebhookBodyFormat.Xml:
                                            client.PostAsXmlAsync(url, webhook.Parameters).GetAwaiter().GetResult();
                                            break;

                                        case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                                            var content = new FormUrlEncodedContent(webhook.Parameters);
                                            client.PostAsync(url, content).GetAwaiter().GetResult();
                                            break;
                                        }
                                    }
                                }
                            }
                            catch (HttpRequestException ex)
                            {
                                scope.LogError(ex, "Error calling provisioning template webhook");
                            }
                            break;
                        }
                        }
                    }
                }
            }
        }
        private void CreateFolderInList(Microsoft.SharePoint.Client.Folder parentFolder, Model.Folder folder, TokenParser parser, PnPMonitoredScope scope)
        {
            // Determine the folder name, parsing any token
            String targetFolderName = parser.ParseString(folder.Name);

            // Check if the folder already exists
            if (parentFolder.FolderExists(targetFolderName))
            {
                // Log a warning if the folder already exists
                String warningFolderAlreadyExists = String.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_FolderAlreadyExists, targetFolderName, parentFolder.ServerRelativeUrl);
                scope.LogWarning(warningFolderAlreadyExists);
                WriteWarning(warningFolderAlreadyExists, ProvisioningMessageType.Warning);
            }

            // Create it or get a reference to it
            var currentFolder = parentFolder.EnsureFolder(targetFolderName);

            if (currentFolder != null)
            {
                // Handle any child-folder
                if (folder.Folders != null && folder.Folders.Count > 0)
                {
                    foreach (var childFolder in folder.Folders)
                    {
                        CreateFolderInList(currentFolder, childFolder, parser, scope);
                    }
                }

                // Handle current folder security
                if (folder.Security != null && folder.Security.RoleAssignments.Count != 0)
                {
                    var currentFolderItem = currentFolder.ListItemAllFields;
                    parentFolder.Context.Load(currentFolderItem);
                    parentFolder.Context.ExecuteQueryRetry();
                    currentFolderItem.SetSecurity(parser, folder.Security);
                }
            }
        }
        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;
            }
        }
示例#11
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                // Get a reference to infrastructural services
                WorkflowServicesManager servicesManager = null;

                try
                {
                    servicesManager = new WorkflowServicesManager(web.Context, web);
                }
                catch (ServerException)
                {
                    // If there is no workflow service present in the farm this method will throw an error.
                    // Swallow the exception
                }

                if (servicesManager != null)
                {
                    var deploymentService = servicesManager.GetWorkflowDeploymentService();
                    var subscriptionService = servicesManager.GetWorkflowSubscriptionService();

                    // Pre-load useful properties
                    web.EnsureProperty(w => w.Id);

                    // Provision Workflow Definitions
                    foreach (var definition in template.Workflows.WorkflowDefinitions)
                    {
                        // Load the Workflow Definition XAML
                        Stream xamlStream = template.Connector.GetFileStream(definition.XamlPath);
                        System.Xml.Linq.XElement xaml = System.Xml.Linq.XElement.Load(xamlStream);

                        // Create the WorkflowDefinition instance
                        Microsoft.SharePoint.Client.WorkflowServices.WorkflowDefinition workflowDefinition =
                            new Microsoft.SharePoint.Client.WorkflowServices.WorkflowDefinition(web.Context)
                            {
                                AssociationUrl = definition.AssociationUrl,
                                Description = definition.Description,
                                DisplayName = definition.DisplayName,
                                FormField = definition.FormField,
                                DraftVersion = definition.DraftVersion,
                                Id = definition.Id,
                                InitiationUrl = definition.InitiationUrl,
                                RequiresAssociationForm = definition.RequiresAssociationForm,
                                RequiresInitiationForm = definition.RequiresInitiationForm,
                                RestrictToScope = parser.ParseString(definition.RestrictToScope),
                                RestrictToType = definition.RestrictToType != "Universal" ? definition.RestrictToType : null,
                                Xaml = xaml.ToString(),
                            };

                        //foreach (var p in definition.Properties)
                        //{
                        //    workflowDefinition.SetProperty(p.Key, parser.ParseString(p.Value));
                        //}

                        // Save the Workflow Definition
                        var definitionId = deploymentService.SaveDefinition(workflowDefinition);
                        web.Context.Load(workflowDefinition);
                        web.Context.ExecuteQueryRetry();

                        // Let's publish the Workflow Definition, if needed
                        if (definition.Published)
                        {
                            deploymentService.PublishDefinition(definitionId.Value);
                        }
                    }

                    // get existing subscriptions
                    var existingWorkflowSubscriptions = web.GetWorkflowSubscriptions();

                    foreach (var subscription in template.Workflows.WorkflowSubscriptions)
                    {
                        // Check if the subscription already exists before adding it, and
                        // if already exists a subscription with the same name and with the same DefinitionId,
                        // it is a duplicate
                        string subscriptionName;
                        if (subscription.PropertyDefinitions.TryGetValue("SharePointWorkflowContext.Subscription.Name", out subscriptionName) &&
                            existingWorkflowSubscriptions.Any(s => s.PropertyDefinitions["SharePointWorkflowContext.Subscription.Name"] == subscriptionName && s.DefinitionId == subscription.DefinitionId))
                            {
                                // Thus, skip it!
                                WriteWarning(string.Format("Workflow Subscription '{0}' already exists. Skipping...", subscription.Name), ProvisioningMessageType.Warning);
                                continue;
                            }
            #if CLIENTSDKV15
                    // Create the WorkflowDefinition instance
                    Microsoft.SharePoint.Client.WorkflowServices.WorkflowSubscription workflowSubscription =
                        new Microsoft.SharePoint.Client.WorkflowServices.WorkflowSubscription(web.Context)
                        {
                            DefinitionId = subscription.DefinitionId,
                            Enabled = subscription.Enabled,
                            EventSourceId = (!String.IsNullOrEmpty(subscription.EventSourceId)) ? Guid.Parse(parser.ParseString(subscription.EventSourceId)) : web.Id,
                            EventTypes = subscription.EventTypes,
                            ManualStartBypassesActivationLimit =  subscription.ManualStartBypassesActivationLimit,
                            Name =  subscription.Name,
                            StatusFieldName = subscription.StatusFieldName,
                        };
            #else
                        // Create the WorkflowDefinition instance
                        Microsoft.SharePoint.Client.WorkflowServices.WorkflowSubscription workflowSubscription =
                            new Microsoft.SharePoint.Client.WorkflowServices.WorkflowSubscription(web.Context)
                            {
                                DefinitionId = subscription.DefinitionId,
                                Enabled = subscription.Enabled,
                                EventSourceId = (!String.IsNullOrEmpty(subscription.EventSourceId)) ? Guid.Parse(parser.ParseString(subscription.EventSourceId)) : web.Id,
                                EventTypes = subscription.EventTypes,
                                ManualStartBypassesActivationLimit = subscription.ManualStartBypassesActivationLimit,
                                Name = subscription.Name,
                                ParentContentTypeId = subscription.ParentContentTypeId,
                                StatusFieldName = subscription.StatusFieldName,
                            };
            #endif
                        foreach (var propertyDefinition in subscription.PropertyDefinitions
                            .Where(d => d.Key == "TaskListId" ||
                                        d.Key == "HistoryListId" ||
                                        d.Key == "SharePointWorkflowContext.Subscription.Id" ||
                                        d.Key == "SharePointWorkflowContext.Subscription.Name" ||
                                        d.Key == "CreatedBySPD"))
                        {
                            workflowSubscription.SetProperty(propertyDefinition.Key, parser.ParseString(propertyDefinition.Value));
                        }
                        if (!String.IsNullOrEmpty(subscription.ListId))
                        {
                            // It is a List Workflow
                            Guid targetListId = Guid.Parse(parser.ParseString(subscription.ListId));
                            subscriptionService.PublishSubscriptionForList(workflowSubscription, targetListId);
                        }
                        else
                        {
                            // It is a Site Workflow
                            subscriptionService.PublishSubscription(workflowSubscription);
                        }
                        web.Context.ExecuteQueryRetry();
                    }
                }
            }

            return parser;
        }
        private static void AddListViewWebpart(
            ClientContext ctx,
            PublishingPageWebPart wp,
            Microsoft.SharePoint.Client.WebParts.WebPartDefinition definition,
            PropertyValues webPartProperties,
            TokenParser parser)
        {
            string defaultViewDisplayName = parser.ParseString(wp.DefaultViewDisplayName);

            if (!String.IsNullOrEmpty(defaultViewDisplayName))
            {
                string listUrl = webPartProperties.FieldValues["ListUrl"].ToString();

                ctx.Load(definition, d => d.Id); // Id of the hidden view which gets automatically created
                ctx.ExecuteQuery();

                Guid viewId = definition.Id;
                List list = ctx.Web.GetListByUrl(listUrl);

                Microsoft.SharePoint.Client.View viewCreatedFromWebpart = list.Views.GetById(viewId);
                ctx.Load(viewCreatedFromWebpart);

                Microsoft.SharePoint.Client.View viewCreatedFromList = list.Views.GetByTitle(defaultViewDisplayName);
                ctx.Load(
                    viewCreatedFromList,
                    v => v.ViewFields,
                    v => v.ListViewXml,
                    v => v.ViewQuery,
                    v => v.ViewData,
                    v => v.ViewJoins,
                    v => v.ViewProjectedFields,
                    v => v.Paged,
                    v => v.RowLimit);

                ctx.ExecuteQuery();

                //need to copy the same View definition to the new View added by the Webpart manager
                viewCreatedFromWebpart.ViewQuery = viewCreatedFromList.ViewQuery;
                viewCreatedFromWebpart.ViewData = viewCreatedFromList.ViewData;
                viewCreatedFromWebpart.ViewJoins = viewCreatedFromList.ViewJoins;
                viewCreatedFromWebpart.ViewProjectedFields = viewCreatedFromList.ViewProjectedFields;
                viewCreatedFromWebpart.Paged = viewCreatedFromList.Paged;
                viewCreatedFromWebpart.RowLimit = viewCreatedFromList.RowLimit;

                viewCreatedFromWebpart.ViewFields.RemoveAll();
                foreach (var field in viewCreatedFromList.ViewFields)
                {
                    viewCreatedFromWebpart.ViewFields.Add(field);
                }

                if (webPartProperties.FieldValues.ContainsKey("JSLink") && webPartProperties.FieldValues["JSLink"] != null)
                {
                    viewCreatedFromWebpart.JSLink = webPartProperties.FieldValues["JSLink"].ToString();
                }

                viewCreatedFromWebpart.Update();

                ctx.ExecuteQuery();
            }
        }
示例#13
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);
                            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 (page.WebParts != null & page.WebParts.Any())
                    {
                        var existingWebParts = web.GetWebParts(url);

                        foreach (var webpart in page.WebParts)
                        {
                            if (existingWebParts.FirstOrDefault(w => w.WebPart.Title == webpart.Title) == null)
                            {
                                WebPartEntity wpEntity = new WebPartEntity();
                                wpEntity.WebPartTitle = webpart.Title;
                                wpEntity.WebPartXml   = parser.ParseString(webpart.Contents.Trim(new[] { '\n', ' ' }));
                                web.AddWebPartToWikiPage(url, wpEntity, (int)webpart.Row, (int)webpart.Column, false);
                            }
                        }
                        var allWebParts = web.GetWebParts(url);
                        foreach (var webpart in allWebParts)
                        {
                            parser.AddToken(new WebPartIdToken(web, webpart.WebPart.Title, webpart.Id));
                        }
                    }

                    file = web.GetFileByServerRelativeUrl(url);
                    file.EnsureProperty(f => f.ListItemAllFields);

                    if (page.Fields.Any())
                    {
                        var item = file.ListItemAllFields;
                        foreach (var fieldValue in page.Fields)
                        {
                            item[fieldValue.Key] = parser.ParseString(fieldValue.Value);
                        }
                        item.Update();
                        web.Context.ExecuteQueryRetry();
                    }
                    if (page.Security != null && page.Security.RoleAssignments.Count != 0)
                    {
                        web.Context.Load(file.ListItemAllFields);
                        web.Context.ExecuteQuery();
                        file.ListItemAllFields.SetSecurity(parser, page.Security);
                    }
                }
            }
            return(parser);
        }
        private void CallWebHooks(ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateWebhookKind kind, String objectHandler = null, Exception exception = null)
        {
            if (template != null)
            {
                using (var scope = new PnPMonitoredScope("ProvisioningTemplate WebHook Call"))
                {
                    var webhooks = new List <ProvisioningWebhookBase>();

                    // Merge the webhooks at template level with those at global level
                    if (template.ProvisioningTemplateWebhooks != null && template.ProvisioningTemplateWebhooks.Any())
                    {
                        webhooks.AddRange(template.ProvisioningTemplateWebhooks);
                    }
                    if (template.ParentHierarchy?.ProvisioningWebhooks != null && template.ParentHierarchy.ProvisioningWebhooks.Any())
                    {
                        webhooks.AddRange(template.ParentHierarchy.ProvisioningWebhooks);
                    }

                    // If there is any webhook
                    if (webhooks.Count > 0)
                    {
                        foreach (var webhook in webhooks.Where(w => w.Kind == kind))
                        {
                            var requestParameters = new Dictionary <String, String>();

                            if (exception != null)
                            {
                                // For GET requests we limit the size of the exception to avoid issues
                                requestParameters["__exception"] =
                                    webhook.Method == ProvisioningTemplateWebhookMethod.GET ?
                                    exception.Message : exception.ToString();
                            }

                            SimpleTokenParser internalParser = new SimpleTokenParser();
                            foreach (var webhookparam in webhook.Parameters)
                            {
                                requestParameters.Add(webhookparam.Key, parser.ParseString(webhookparam.Value));
                                internalParser.AddToken(new WebhookParameter(webhookparam.Key, requestParameters[webhookparam.Key]));
                            }
                            var url = parser.ParseString(webhook.Url); // parse for template scoped parameters
                            url = internalParser.ParseString(url);     // parse for webhook scoped parameters

                            switch (webhook.Method)
                            {
                            case ProvisioningTemplateWebhookMethod.GET:
                            {
                                url += $"&__webhookKind={kind.ToString()}";         // add the webhook kind to the REST request URL

                                foreach (var k in requestParameters.Keys)
                                {
                                    url += $"&{HttpUtility.UrlEncode(k)}={HttpUtility.UrlEncode(requestParameters[k])}";
                                }

                                if (kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted ||
                                    kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted ||
                                    kind == ProvisioningTemplateWebhookKind.ExceptionOccurred)
                                {
                                    url += $"&__handler={HttpUtility.UrlEncode(objectHandler)}";         // add the handler name to the REST request URL
                                }
                                try
                                {
                                    if (webhook.Async)
                                    {
                                        Task.Factory.StartNew(async() =>
                                            {
                                                await httpClient.GetAsync(url);
                                            });
                                    }
                                    else
                                    {
                                        httpClient.GetAsync(url).GetAwaiter().GetResult();
                                    }
                                }
                                catch (HttpRequestException ex)
                                {
                                    scope.LogError(ex, "Error calling provisioning template webhook");
                                }
                                break;
                            }

                            case ProvisioningTemplateWebhookMethod.POST:
                            {
                                requestParameters.Add("__webhookKind", kind.ToString());         // add the webhook kind to the parameters of the request body

                                if (kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted ||
                                    kind == ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted ||
                                    kind == ProvisioningTemplateWebhookKind.ExceptionOccurred)
                                {
                                    requestParameters.Add("__handler", objectHandler);         // add the handler name to the parameters of the request body
                                }
                                try
                                {
                                    if (webhook.Async)
                                    {
                                        Task.Factory.StartNew(async() =>
                                            {
                                                switch (webhook.BodyFormat)
                                                {
                                                case ProvisioningTemplateWebhookBodyFormat.Json:
                                                    await httpClient.PostAsJsonAsync(url, requestParameters);
                                                    break;

                                                case ProvisioningTemplateWebhookBodyFormat.Xml:
                                                    await httpClient.PostAsXmlAsync(url, requestParameters);
                                                    break;

                                                case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                                                    var content = new FormUrlEncodedContent(requestParameters);
                                                    await httpClient.PostAsync(url, content);
                                                    break;
                                                }
                                            });
                                    }
                                    else
                                    {
                                        switch (webhook.BodyFormat)
                                        {
                                        case ProvisioningTemplateWebhookBodyFormat.Json:
                                            httpClient.PostAsJsonAsync(url, requestParameters).GetAwaiter().GetResult();
                                            break;

                                        case ProvisioningTemplateWebhookBodyFormat.Xml:
                                            httpClient.PostAsXmlAsync(url, requestParameters).GetAwaiter().GetResult();
                                            break;

                                        case ProvisioningTemplateWebhookBodyFormat.FormUrlEncoded:
                                            var content = new FormUrlEncodedContent(requestParameters);
                                            httpClient.PostAsync(url, content).GetAwaiter().GetResult();
                                            break;
                                        }
                                    }
                                }
                                catch (HttpRequestException ex)
                                {
                                    scope.LogError(ex, "Error calling provisioning template webhook");
                                }
                                break;
                            }
                            }
                        }
                    }
                }
            }
        }
示例#15
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);
                                    var wpd = web.AddWebPartToWikiPage(url, wpEntity, (int)webPart.Row, (int)webPart.Column, false);
#if !SP2013
                                    if (webPart.Title.ContainsResourceToken())
                                    {
                                        // update data based on where it was added - needed in order to localize wp title
#if !SP2016
                                        wpd.EnsureProperties(w => w.ZoneId, w => w.WebPart, w => w.WebPart.Properties);
                                        webPart.Zone = wpd.ZoneId;
#else
                                        wpd.EnsureProperties(w => w.WebPart, w => w.WebPart.Properties);
#endif
                                        webPart.Order            = (uint)wpd.WebPart.ZoneIndex;
                                        webPartsNeedLocalization = true;
                                    }
#endif
                                }
                            }

                            // Remove any existing WebPartIdToken tokens in the parser that were added by other pages. They won't apply to this page,
                            // and they'll cause issues if this page contains web parts with the same name as web parts on other pages.
                            parser.Tokens.RemoveAll(t => t is WebPartIdToken);

                            var allWebParts = web.GetWebParts(url);
                            foreach (var webpart in allWebParts)
                            {
                                parser.AddToken(new WebPartIdToken(web, webpart.WebPart.Title, webpart.Id));
                            }
                        }
                        else
                        {
                            scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_Pages_SkipAddingWebParts, page.Url);
                        }
                    }

#if !SP2013
                    if (webPartsNeedLocalization)
                    {
                        page.LocalizeWebParts(web, parser, scope);
                    }
#endif

                    file = web.GetFileByServerRelativeUrl(url);
                    file.EnsureProperty(f => f.ListItemAllFields);

                    if (page.Fields.Any())
                    {
                        var item = file.ListItemAllFields;
                        foreach (var fieldValue in page.Fields)
                        {
                            item[fieldValue.Key] = parser.ParseString(fieldValue.Value);
                        }
                        item.Update();
                        web.Context.ExecuteQueryRetry();
                    }
                    if (page.Security != null && page.Security.RoleAssignments.Count != 0)
                    {
                        web.Context.Load(file.ListItemAllFields);
                        web.Context.ExecuteQueryRetry();
                        file.ListItemAllFields.SetSecurity(parser, page.Security);
                    }
                }
            }
            return(parser);
        }
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                var systemPropertyBagEntriesExclusions = new List <string>(new[]
                {
                    "_",
                    "vti_",
                    "dlc_",
                    "ecm_",
                    "profileschemaversion",
                    "DesignPreview"
                });

                // 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();
                if (isNoScriptSite)
                {
                    return(parser);
                }

                // To handle situations where the propertybag is not updated fully when applying a theme,
                // we need to create a new context and use that one. Reloading the propertybag does not solve this.
                var webUrl     = web.EnsureProperty(w => w.Url);
                var newContext = web.Context.Clone(webUrl);

                web = newContext.Web;

                foreach (var propbagEntry in template.PropertyBagEntries)
                {
                    bool propExists = web.PropertyBagContainsKey(propbagEntry.Key);

                    if (propbagEntry.Overwrite)
                    {
                        var systemProp = systemPropertyBagEntriesExclusions.Any(k => propbagEntry.Key.StartsWith(k, StringComparison.OrdinalIgnoreCase));
                        if (!systemProp || (systemProp && applyingInformation.OverwriteSystemPropertyBagValues))
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_PropertyBagEntries_Overwriting_existing_propertybag_entry__0__with_value__1_, propbagEntry.Key, propbagEntry.Value);
                            web.SetPropertyBagValue(propbagEntry.Key, parser.ParseString(propbagEntry.Value));
                            if (propbagEntry.Indexed)
                            {
                                web.AddIndexedPropertyBagKey(propbagEntry.Key);
                            }
                        }
                    }
                    else
                    {
                        if (!propExists)
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_PropertyBagEntries_Creating_new_propertybag_entry__0__with_value__1__2_, propbagEntry.Key, propbagEntry.Value, propbagEntry.Indexed ? ",Indexed = true" : "");
                            web.SetPropertyBagValue(propbagEntry.Key, parser.ParseString(propbagEntry.Value));
                            if (propbagEntry.Indexed)
                            {
                                web.AddIndexedPropertyBagKey(propbagEntry.Key);
                            }
                        }
                    }
                }
            }
            return(parser);
        }
示例#17
0
        private void ProvisionStructuralNavigationNodes(Web web, TokenParser parser, Enums.NavigationType navigationType, Model.NavigationNodeCollection nodes, PnPMonitoredScope scope, string parentNodeTitle = null, string l1ParentNodeTitle = null)
        {
            foreach (var node in nodes)
            {
                try
                {
                    string fileUrl = ReplaceFileUniqueToken(web, parser.ParseString(node.Url));

                    var navNode = web.AddNavigationNode(
                        parser.ParseString(node.Title),
                        new Uri(fileUrl, UriKind.RelativeOrAbsolute),
                        parser.ParseString(parentNodeTitle),
                        navigationType,
                        node.IsExternal,
                        l1ParentNodeTitle: l1ParentNodeTitle
                        );

#if !SP2013
                    if (node.Title.ContainsResourceToken())
                    {
                        navNode.LocalizeNavigationNode(web, node.Title, parser, scope);
                    }
#endif
                }
                catch (ServerException ex)
                {
                    // If the SharePoint link doesn't exist, provision it as external link
                    // when we provision as external link, the server side URL validation won't kick-in
                    // This handles the "no such file or url found" error

                    WriteMessage(String.Format(CoreResources.Provisioning_ObjectHandlers_Navigation_Link_Provisioning_Failed_Retry, node.Title), ProvisioningMessageType.Warning);

                    if (ex.ServerErrorCode == -2130247147)
                    {
                        try
                        {
                            string fileUrl = ReplaceFileUniqueToken(web, parser.ParseString(node.Url));
                            var    navNode = web.AddNavigationNode(
                                parser.ParseString(node.Title),
                                new Uri(fileUrl, UriKind.RelativeOrAbsolute),
                                parser.ParseString(parentNodeTitle),
                                navigationType,
                                true,
                                l1ParentNodeTitle: l1ParentNodeTitle
                                );
                        }
                        catch (Exception innerEx)
                        {
                            WriteMessage(String.Format(CoreResources.Provisioning_ObjectHandlers_Navigation_Link_Provisioning_Failed, innerEx.Message), ProvisioningMessageType.Warning);
                        }
                    }
                    else
                    {
                        WriteMessage(String.Format(CoreResources.Provisioning_ObjectHandlers_Navigation_Link_Provisioning_Failed, ex.Message), ProvisioningMessageType.Warning);
                    }
                }

                ProvisionStructuralNavigationNodes(
                    web,
                    parser,
                    navigationType,
                    node.NavigationNodes,
                    scope,
                    parser.ParseString(node.Title),
                    parentNodeTitle
                    );
            }
        }
示例#18
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (template.Navigation != null)
                {
                    if (!WebSupportsProvisionNavigation(web, template))
                    {
                        scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Navigation_Context_web_is_not_publishing);
                        return(parser);
                    }

                    // Check if this is not a noscript site as navigation features are not supported
                    bool isNoScriptSite = web.IsNoScriptSite();

                    // Retrieve the current web navigation settings
                    var navigationSettings = new WebNavigationSettings(web.Context, web);
                    web.Context.Load(navigationSettings, ns => ns.CurrentNavigation, ns => ns.GlobalNavigation);
                    web.Context.ExecuteQueryRetry();

                    navigationSettings.AddNewPagesToNavigation       = template.Navigation.AddNewPagesToNavigation;
                    navigationSettings.CreateFriendlyUrlsForNewPages = template.Navigation.CreateFriendlyUrlsForNewPages;

                    if (!isNoScriptSite)
                    {
                        navigationSettings.Update(TaxonomySession.GetTaxonomySession(web.Context));
                        web.Context.ExecuteQueryRetry();
                    }

                    if (template.Navigation.GlobalNavigation != null)
                    {
                        switch (template.Navigation.GlobalNavigation.NavigationType)
                        {
                        case GlobalNavigationType.Inherit:
                            navigationSettings.GlobalNavigation.Source = StandardNavigationSource.InheritFromParentWeb;
                            web.Navigation.UseShared = true;
                            break;

                        case GlobalNavigationType.Managed:
                            if (template.Navigation.GlobalNavigation.ManagedNavigation == null)
                            {
                                throw new ApplicationException(CoreResources.Provisioning_ObjectHandlers_Navigation_missing_global_managed_navigation);
                            }
                            navigationSettings.GlobalNavigation.Source      = StandardNavigationSource.TaxonomyProvider;
                            navigationSettings.GlobalNavigation.TermStoreId = Guid.Parse(parser.ParseString(template.Navigation.GlobalNavigation.ManagedNavigation.TermStoreId));
                            navigationSettings.GlobalNavigation.TermSetId   = Guid.Parse(parser.ParseString(template.Navigation.GlobalNavigation.ManagedNavigation.TermSetId));
                            web.Navigation.UseShared = false;
                            break;

                        case GlobalNavigationType.Structural:
                        default:
                            if (template.Navigation.GlobalNavigation.StructuralNavigation == null)
                            {
                                throw new ApplicationException(CoreResources.Provisioning_ObjectHandlers_Navigation_missing_global_structural_navigation);
                            }
                            navigationSettings.GlobalNavigation.Source = StandardNavigationSource.PortalProvider;
                            web.Navigation.UseShared = false;

                            break;
                        }

                        if (!isNoScriptSite)
                        {
                            navigationSettings.Update(TaxonomySession.GetTaxonomySession(web.Context));
                            web.Context.ExecuteQueryRetry();
                        }

                        // Need to set navigation nodes after update navigation settings
                        if (template.Navigation.GlobalNavigation.NavigationType == GlobalNavigationType.Structural)
                        {
                            ProvisionGlobalStructuralNavigation(web,
                                                                template.Navigation.GlobalNavigation.StructuralNavigation, parser, applyingInformation.ClearNavigation, scope);
                        }
                    }

                    if (template.Navigation.CurrentNavigation != null)
                    {
                        switch (template.Navigation.CurrentNavigation.NavigationType)
                        {
                        case CurrentNavigationType.Inherit:
                            navigationSettings.CurrentNavigation.Source = StandardNavigationSource.InheritFromParentWeb;
                            break;

                        case CurrentNavigationType.Managed:
                            if (template.Navigation.CurrentNavigation.ManagedNavigation == null)
                            {
                                throw new ApplicationException(CoreResources.Provisioning_ObjectHandlers_Navigation_missing_current_managed_navigation);
                            }
                            navigationSettings.CurrentNavigation.Source      = StandardNavigationSource.TaxonomyProvider;
                            navigationSettings.CurrentNavigation.TermStoreId = Guid.Parse(parser.ParseString(template.Navigation.CurrentNavigation.ManagedNavigation.TermStoreId));
                            navigationSettings.CurrentNavigation.TermSetId   = Guid.Parse(parser.ParseString(template.Navigation.CurrentNavigation.ManagedNavigation.TermSetId));
                            break;

                        case CurrentNavigationType.StructuralLocal:
                            if (!isNoScriptSite)
                            {
                                web.SetPropertyBagValue(NavigationShowSiblings, "false");
                            }
                            if (template.Navigation.CurrentNavigation.StructuralNavigation == null)
                            {
                                throw new ApplicationException(CoreResources.Provisioning_ObjectHandlers_Navigation_missing_current_structural_navigation);
                            }
                            navigationSettings.CurrentNavigation.Source = StandardNavigationSource.PortalProvider;

                            break;

                        case CurrentNavigationType.Structural:
                        default:
                            if (!isNoScriptSite)
                            {
                                web.SetPropertyBagValue(NavigationShowSiblings, "true");
                            }
                            if (template.Navigation.CurrentNavigation.StructuralNavigation == null)
                            {
                                throw new ApplicationException(CoreResources.Provisioning_ObjectHandlers_Navigation_missing_current_structural_navigation);
                            }
                            navigationSettings.CurrentNavigation.Source = StandardNavigationSource.PortalProvider;

                            break;
                        }

                        if (!isNoScriptSite)
                        {
                            navigationSettings.Update(TaxonomySession.GetTaxonomySession(web.Context));
                            web.Context.ExecuteQueryRetry();
                        }

                        // Need to set navigation nodes after update navigation settings
                        if (template.Navigation.CurrentNavigation.NavigationType == CurrentNavigationType.Structural ||
                            template.Navigation.CurrentNavigation.NavigationType == CurrentNavigationType.StructuralLocal)
                        {
                            ProvisionCurrentStructuralNavigation(web,
                                                                 template.Navigation.CurrentNavigation.StructuralNavigation, parser, applyingInformation.ClearNavigation, scope);
                        }
                    }

                    if (template.Navigation.SearchNavigation != null)
                    {
                        var structuralNavigation = new StructuralNavigation();
                        structuralNavigation.NavigationNodes.AddRange(template.Navigation.SearchNavigation.NavigationNodes);
                        structuralNavigation.RemoveExistingNodes = template.Navigation.SearchNavigation.RemoveExistingNodes;
                        ProvisionSearchNavigation(web, structuralNavigation, parser, applyingInformation.ClearNavigation, scope);
                    }
                }
            }

            return(parser);
        }
示例#19
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (template.Navigation != null)
                {
                    // The Navigation handler works only for sites with Publishing Features enabled
                    if (!web.IsPublishingWeb())
                    {
                        scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Navigation_Context_web_is_not_publishing);
                        return(parser);
                    }

                    // Retrieve the current web navigation settings
                    var navigationSettings = new WebNavigationSettings(web.Context, web);
                    web.Context.Load(navigationSettings, ns => ns.CurrentNavigation, ns => ns.GlobalNavigation);
                    web.Context.ExecuteQueryRetry();

                    if (template.Navigation.GlobalNavigation != null)
                    {
                        switch (template.Navigation.GlobalNavigation.NavigationType)
                        {
                        case GlobalNavigationType.Inherit:
                            navigationSettings.GlobalNavigation.Source = StandardNavigationSource.InheritFromParentWeb;
                            break;

                        case GlobalNavigationType.Managed:
                            if (template.Navigation.GlobalNavigation.ManagedNavigation == null)
                            {
                                throw new ApplicationException(CoreResources.Provisioning_ObjectHandlers_Navigation_missing_global_managed_navigation);
                            }
                            navigationSettings.GlobalNavigation.Source      = StandardNavigationSource.TaxonomyProvider;
                            navigationSettings.GlobalNavigation.TermStoreId = Guid.Parse(parser.ParseString(template.Navigation.GlobalNavigation.ManagedNavigation.TermStoreId));
                            navigationSettings.GlobalNavigation.TermSetId   = Guid.Parse(parser.ParseString(template.Navigation.GlobalNavigation.ManagedNavigation.TermSetId));
                            break;

                        case GlobalNavigationType.Structural:
                        default:
                            if (template.Navigation.GlobalNavigation.StructuralNavigation == null)
                            {
                                throw new ApplicationException(CoreResources.Provisioning_ObjectHandlers_Navigation_missing_global_structural_navigation);
                            }
                            ProvisionGlobalStructuralNavigation(web,
                                                                template.Navigation.GlobalNavigation.StructuralNavigation, parser);
                            break;
                        }
                        web.Context.ExecuteQueryRetry();
                    }

                    if (template.Navigation.CurrentNavigation != null)
                    {
                        switch (template.Navigation.CurrentNavigation.NavigationType)
                        {
                        case CurrentNavigationType.Inherit:
                            navigationSettings.CurrentNavigation.Source = StandardNavigationSource.InheritFromParentWeb;
                            break;

                        case CurrentNavigationType.Managed:
                            if (template.Navigation.CurrentNavigation.ManagedNavigation == null)
                            {
                                throw new ApplicationException(CoreResources.Provisioning_ObjectHandlers_Navigation_missing_current_managed_navigation);
                            }
                            navigationSettings.CurrentNavigation.Source      = StandardNavigationSource.TaxonomyProvider;
                            navigationSettings.CurrentNavigation.TermStoreId = Guid.Parse(parser.ParseString(template.Navigation.CurrentNavigation.ManagedNavigation.TermStoreId));
                            navigationSettings.CurrentNavigation.TermSetId   = Guid.Parse(parser.ParseString(template.Navigation.CurrentNavigation.ManagedNavigation.TermSetId));
                            break;

                        case CurrentNavigationType.StructuralLocal:
                            web.SetPropertyBagValue(NavigationShowSiblings, "false");
                            if (template.Navigation.CurrentNavigation.StructuralNavigation == null)
                            {
                                throw new ApplicationException(CoreResources.Provisioning_ObjectHandlers_Navigation_missing_current_structural_navigation);
                            }
                            ProvisionCurrentStructuralNavigation(web,
                                                                 template.Navigation.CurrentNavigation.StructuralNavigation, parser);
                            break;

                        case CurrentNavigationType.Structural:
                        default:
                            if (template.Navigation.CurrentNavigation.StructuralNavigation == null)
                            {
                                throw new ApplicationException(CoreResources.Provisioning_ObjectHandlers_Navigation_missing_current_structural_navigation);
                            }
                            ProvisionCurrentStructuralNavigation(web,
                                                                 template.Navigation.CurrentNavigation.StructuralNavigation, parser);
                            break;
                        }
                        web.Context.ExecuteQueryRetry();
                    }
                }
            }

            return(parser);
        }
        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
            #if !CLIENTSDKV15
            , l => l.MajorWithMinorVersionsLimit
            #endif
            );
            web.Context.ExecuteQueryRetry();

            if (existingList.BaseTemplate == templateList.TemplateType)
            {
                var isDirty = false;
                if (parser.ParseString(templateList.Title) != existingList.Title)
                {
                    existingList.Title = parser.ParseString(templateList.Title);
                    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 (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.BaseTemplate == (int)ListTemplateType.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);
                    foreach (var ctb in bindingsToAdd)
                    {
                        existingList.AddContentTypeToListById(ctb.ContentTypeId, searchContentTypeInSiteHierarchy: 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)
                    {
                        existingList.SetDefaultContentTypeToList(defaultCtBinding.ContentTypeId);
                    }
                }
                if (templateList.Security != null)
                {
                    existingList.SetSecurity(parser, templateList.Security);
                }
                return Tuple.Create(existingList, parser);
            }
            else
            {
                scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstances_List__0____1____2___exists_but_is_of_a_different_type__Skipping_list_, templateList.Title, templateList.Url, existingList.Id);
                WriteWarning(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_List__0____1____2___exists_but_is_of_a_different_type__Skipping_list_, templateList.Title, templateList.Url, existingList.Id), ProvisioningMessageType.Warning);
                return null;
            }
        }
        private static void CreateField(XElement fieldElement, ListInfo listInfo, TokenParser parser)
        {
            fieldElement = PrepareField(fieldElement);

            var fieldXml = parser.ParseString(fieldElement.ToString(), "~sitecollection", "~site");
            listInfo.SiteList.Fields.AddFieldAsXml(fieldXml, false, AddFieldOptions.AddFieldInternalNameHint);
            listInfo.SiteList.Context.ExecuteQueryRetry();
        }
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (template.ComposedLook != null &&
                    !template.ComposedLook.Equals(ComposedLook.Empty))
                {
                    // Check if this is not a noscript site as themes and composed looks are not supported
                    if (web.IsNoScriptSite())
                    {
                        scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_NoSiteCheck);
                        return(parser);
                    }

                    bool executeQueryNeeded = false;
                    if (executeQueryNeeded)
                    {
                        web.Context.ExecuteQueryRetry();
                    }

                    if (String.IsNullOrEmpty(template.ComposedLook.ColorFile) &&
                        String.IsNullOrEmpty(template.ComposedLook.FontFile) &&
                        String.IsNullOrEmpty(template.ComposedLook.BackgroundFile))
                    {
                        // Apply OOB theme
                        web.SetComposedLookByUrl(template.ComposedLook.Name, "", "", "");
                    }
                    else
                    {
                        // Apply custom theme
                        string colorFile = null;
                        if (!string.IsNullOrEmpty(template.ComposedLook.ColorFile))
                        {
                            colorFile = parser.ParseString(template.ComposedLook.ColorFile);
                        }
                        string backgroundFile = null;
                        if (!string.IsNullOrEmpty(template.ComposedLook.BackgroundFile))
                        {
                            backgroundFile = parser.ParseString(template.ComposedLook.BackgroundFile);
                        }
                        string fontFile = null;
                        if (!string.IsNullOrEmpty(template.ComposedLook.FontFile))
                        {
                            fontFile = parser.ParseString(template.ComposedLook.FontFile);
                        }

                        string masterUrl = null;
                        if (template.WebSettings != null && !string.IsNullOrEmpty(template.WebSettings.MasterPageUrl))
                        {
                            masterUrl = parser.ParseString(template.WebSettings.MasterPageUrl);
                        }
                        web.CreateComposedLookByUrl(template.ComposedLook.Name, colorFile, fontFile, backgroundFile, masterUrl);
                        web.SetComposedLookByUrl(template.ComposedLook.Name, colorFile, fontFile, backgroundFile, masterUrl);
                    }

                    // Persist composed look info in property bag
                    var composedLookJson = JsonConvert.SerializeObject(template.ComposedLook);
                    web.SetPropertyBagValue("_PnP_ProvisioningTemplateComposedLookInfo", composedLookJson);
                }
            }
            return(parser);
        }
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser,
            ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                var context = web.Context as ClientContext;

                web.EnsureProperties(w => w.ServerRelativeUrl, w => w.Url);

                foreach (PublishingPage page in template.Publishing.PublishingPages)
                {
                    string parsedFileName = parser.ParseString(page.FileName);
                    string parsedFullFileName = parser.ParseString(page.FullFileName);

                    Microsoft.SharePoint.Client.Publishing.PublishingPage existingPage =
                        web.GetPublishingPage(parsedFileName + ".aspx");

                    if (!web.IsPropertyAvailable("RootFolder"))
                    {
                        web.Context.Load(web.RootFolder);
                        web.Context.ExecuteQueryRetry();
                    }

                    if (existingPage != null && existingPage.ServerObjectIsNull.Value == false)
                    {
                        if (!page.Overwrite)
                        {
                            scope.LogDebug(
                                CoreResources.Provisioning_ObjectHandlers_PublishingPages_Skipping_As_Overwrite_false,
                                parsedFileName);
                            continue;
                        }

                        if (page.WelcomePage && web.RootFolder.WelcomePage.Contains(parsedFullFileName))
                        {
                            //set the welcome page to a Temp page to allow page deletion
                            web.RootFolder.WelcomePage = "home.aspx";
                            web.RootFolder.Update();
                            web.Update();
                            context.ExecuteQueryRetry();
                        }
                        existingPage.ListItem.DeleteObject();
                        context.ExecuteQuery();
                    }

                    web.AddPublishingPage(
                        parsedFileName,
                        page.Layout,
                        parser.ParseString(page.Title)
                        );
                    Microsoft.SharePoint.Client.Publishing.PublishingPage publishingPage =
                        web.GetPublishingPage(parsedFullFileName);
                    Microsoft.SharePoint.Client.File pageFile = publishingPage.ListItem.File;
                    pageFile.CheckOut();

                    if (page.Properties != null && page.Properties.Count > 0)
                    {
                        context.Load(pageFile, p => p.Name, p => p.CheckOutType);
                        context.ExecuteQueryRetry();
                        var parsedProperties = page.Properties.ToDictionary(p => p.Key, p => parser.ParseString(p.Value));
                        pageFile.SetFileProperties(parsedProperties, false);
                    }

                    if (page.WebParts != null && page.WebParts.Count > 0)
                    {
                        Microsoft.SharePoint.Client.WebParts.LimitedWebPartManager mgr =
                            pageFile.GetLimitedWebPartManager(
                                Microsoft.SharePoint.Client.WebParts.PersonalizationScope.Shared);
                        context.Load(mgr);
                        context.ExecuteQueryRetry();

                        AddWebPartsToPublishingPage(page, context, mgr, parser);
                    }

                    List pagesLibrary = publishingPage.ListItem.ParentList;
                    context.Load(pagesLibrary);
                    context.ExecuteQueryRetry();

                    ListItem pageItem = publishingPage.ListItem;
                    web.Context.Load(pageItem, p => p.File.CheckOutType);
                    web.Context.ExecuteQueryRetry();

                    if (pageItem.File.CheckOutType != CheckOutType.None)
                    {
                        pageItem.File.CheckIn(String.Empty, CheckinType.MajorCheckIn);
                    }

                    if (page.Publish && pagesLibrary.EnableMinorVersions)
                    {
                        pageItem.File.Publish(String.Empty);
                        if (pagesLibrary.EnableModeration)
                        {
                            pageItem.File.Approve(String.Empty);
                        }
                    }

                    if (page.WelcomePage)
                    {
                        SetWelcomePage(web, pageFile);
                    }

                    context.ExecuteQueryRetry();
                }
            }
            return parser;
        }
        public override ProvisioningTemplate ExtractObjects(Web web, ProvisioningTemplate template, ProvisioningTemplateCreationInformation creationInfo)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                scope.LogInfo(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Retrieving_current_composed_look);

                // Ensure that we have URL property loaded for web and site
                web.EnsureProperty(w => w.Url);
                Site site = (web.Context as ClientContext).Site;
                site.EnsureProperty(s => s.Url);

                SharePointConnector spConnector = new SharePointConnector(web.Context, web.Url, "dummy");
                // to get files from theme catalog we need a connector linked to the root site
                SharePointConnector spConnectorRoot;
                if (!site.Url.Equals(web.Url, StringComparison.InvariantCultureIgnoreCase))
                {
                    spConnectorRoot = new SharePointConnector(web.Context.Clone(site.Url), site.Url, "dummy");
                }
                else
                {
                    spConnectorRoot = spConnector;
                }

                // Check if we have composed look info in the property bag, if so, use that, otherwise try to detect the current composed look
                if (web.PropertyBagContainsKey("_PnP_ProvisioningTemplateComposedLookInfo"))
                {
                    scope.LogInfo(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Using_ComposedLookInfoFromPropertyBag);

                    try
                    {
                        var composedLook = JsonConvert.DeserializeObject <ComposedLook>(web.GetPropertyBagValueString("_PnP_ProvisioningTemplateComposedLookInfo", ""));
                        if (composedLook.Name == null)
                        {
                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_ComposedLookInfoFailedToDeserialize);
                            throw new JsonSerializationException();
                        }

                        composedLook.BackgroundFile = Tokenize(composedLook.BackgroundFile, web.Url);
                        composedLook.FontFile       = Tokenize(composedLook.FontFile, web.Url);
                        composedLook.ColorFile      = Tokenize(composedLook.ColorFile, web.Url);
                        template.ComposedLook       = composedLook;

                        if (!web.IsSubSite() && creationInfo != null &&
                            creationInfo.PersistBrandingFiles && creationInfo.FileConnector != null)
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_ExtractObjects_Creating_SharePointConnector);
                            // Let's create a SharePoint connector since our files anyhow are in SharePoint at this moment
                            TokenParser parser = new TokenParser(web, template);
                            DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, parser.ParseString(composedLook.BackgroundFile), scope);
                            DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, parser.ParseString(composedLook.ColorFile), scope);
                            DownLoadFile(spConnector, spConnectorRoot, creationInfo.FileConnector, web.Url, parser.ParseString(composedLook.FontFile), scope);
                        }
                        // Create file entries for the custom theme files
                        if (!string.IsNullOrEmpty(template.ComposedLook.BackgroundFile))
                        {
                            var f = GetComposedLookFile(template.ComposedLook.BackgroundFile);
                            f.Folder = Tokenize(f.Folder, web.Url);
                            template.Files.Add(f);
                        }
                        if (!string.IsNullOrEmpty(template.ComposedLook.ColorFile))
                        {
                            var f = GetComposedLookFile(template.ComposedLook.ColorFile);
                            f.Folder = Tokenize(f.Folder, web.Url);
                            template.Files.Add(f);
                        }
                        if (!string.IsNullOrEmpty(template.ComposedLook.FontFile))
                        {
                            var f = GetComposedLookFile(template.ComposedLook.FontFile);
                            f.Folder = Tokenize(f.Folder, web.Url);
                            template.Files.Add(f);
                        }
                    }
                    catch (JsonSerializationException)
                    {
                        // cannot deserialize the object, fall back to composed look detection
                        template = DetectComposedLook(web, template, creationInfo, scope, spConnector, spConnectorRoot);
                    }
                }
                else
                {
                    template = DetectComposedLook(web, template, creationInfo, scope, spConnector, spConnectorRoot);
                }

                if (creationInfo != null && creationInfo.BaseTemplate != null)
                {
                    template = CleanupEntities(template, creationInfo.BaseTemplate);
                }
            }
            return(template);
        }
示例#25
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.Load(web, w => w.HasUniqueRoleAssignments);
                    web.Context.ExecuteQueryRetry();
                }

                var siteSecurity = template.Security;

                if (web.EnsureProperty(w => w.HasUniqueRoleAssignments))
                {
                    string parsedAssociatedOwnerGroupName   = parser.ParseString(template.Security.AssociatedOwnerGroup);
                    string parsedAssociatedMemberGroupName  = parser.ParseString(template.Security.AssociatedMemberGroup);
                    string parsedAssociatedVisitorGroupName = parser.ParseString(template.Security.AssociatedVisitorGroup);

                    bool webNeedsUpdate = false;

                    if (parsedAssociatedOwnerGroupName != null)
                    {
                        if (string.IsNullOrEmpty(parsedAssociatedOwnerGroupName))
                        {
                            web.AssociatedOwnerGroup = null;
                        }
                        else
                        {
                            web.AssociatedOwnerGroup = EnsureGroup(web, parsedAssociatedOwnerGroupName);
                        }

                        webNeedsUpdate = true;
                    }

                    if (parsedAssociatedMemberGroupName != null)
                    {
                        if (string.IsNullOrEmpty(parsedAssociatedMemberGroupName))
                        {
                            web.AssociatedMemberGroup = null;
                        }
                        else
                        {
                            web.AssociatedMemberGroup = EnsureGroup(web, parsedAssociatedMemberGroupName);
                        }

                        webNeedsUpdate = true;
                    }

                    if (parsedAssociatedVisitorGroupName != null)
                    {
                        if (string.IsNullOrEmpty(parsedAssociatedVisitorGroupName))
                        {
                            web.AssociatedVisitorGroup = null;
                        }
                        else
                        {
                            web.AssociatedVisitorGroup = EnsureGroup(web, parsedAssociatedVisitorGroupName);
                        }

                        webNeedsUpdate = true;
                    }

                    if (webNeedsUpdate)
                    {
                        // Trigger the creation and setting of the associated groups
                        web.Update();
                        web.Context.ExecuteQueryRetry();
                    }
                }

                var ownerGroup   = web.AssociatedOwnerGroup;
                var memberGroup  = web.AssociatedMemberGroup;
                var visitorGroup = web.AssociatedVisitorGroup;

                if (!ownerGroup.ServerObjectIsNull())
                {
                    web.Context.Load(ownerGroup, o => o.Title, o => o.Users);
                }
                if (!memberGroup.ServerObjectIsNull())
                {
                    web.Context.Load(memberGroup, o => o.Title, o => o.Users);
                }
                if (!visitorGroup.ServerObjectIsNull())
                {
                    web.Context.Load(visitorGroup, o => o.Title, o => o.Users);
                }

                web.Context.Load(web.SiteUsers);

                web.Context.ExecuteQueryRetry();

                IEnumerable <AssociatedGroupToken> associatedGroupTokens = parser.Tokens.Where(t => t.GetType() == typeof(AssociatedGroupToken)).Cast <AssociatedGroupToken>();
                foreach (AssociatedGroupToken associatedGroupToken in associatedGroupTokens)
                {
                    associatedGroupToken.ClearCache();
                }

                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
                         .Sort <SiteGroup>(
                             _grp => {
                    string groupOwner = _grp.Owner;
                    if (string.IsNullOrWhiteSpace(groupOwner) ||
                        "SHAREPOINT\\system".Equals(groupOwner, StringComparison.OrdinalIgnoreCase) ||
                        _grp.Title.Equals(groupOwner, StringComparison.OrdinalIgnoreCase) ||
                        (groupOwner.StartsWith("{{associated") && groupOwner.EndsWith("group}}")))
                    {
                        return(Enumerable.Empty <SiteGroup>());
                    }
                    return(siteSecurity.SiteGroups.Where(_item => _item.Title.Equals(groupOwner, StringComparison.OrdinalIgnoreCase)));
                }
                             ))
                {
                    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 (parsedGroupOwner != null && (parsedGroupTitle != parsedGroupOwner))
                        {
                            Principal ownerPrincipal = allGroups.FirstOrDefault(gr => gr.LoginName.Equals(parsedGroupOwner, StringComparison.OrdinalIgnoreCase));
                            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 (parsedGroupDescription != null)
                        {
                            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 (parsedGroupOwner != null && group.Owner.LoginName != parsedGroupOwner)
                        {
                            if (parsedGroupTitle != parsedGroupOwner)
                            {
                                Principal ownerPrincipal = allGroups.FirstOrDefault(gr => gr.LoginName.Equals(parsedGroupOwner, StringComparison.OrdinalIgnoreCase));
                                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();

                                // iterate over all possible PermissionKind values and set them on the new object
                                foreach (PermissionKind pk in Enum.GetValues(typeof(PermissionKind)))
                                {
                                    if (siteRoleDefinition.BasePermissions.Has(pk))
                                    {
                                        templateBasePermissions.Set(pk);
                                    }
                                }

                                // add the permissions that were specified in the template
                                templateRoleDefinition.Permissions.ForEach(p => templateBasePermissions.Set(p));

                                if (siteRoleDefinition.BasePermissions != templateBasePermissions)
                                {
                                    isDirty = true;
                                    siteRoleDefinition.BasePermissions = templateBasePermissions;
                                }

                                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);

                                if (principal != null)
                                {
                                    var assignmentsForPrincipal = webRoleAssignments.Where(t => t.PrincipalId == principal.Id);
                                    foreach (var assignmentForPrincipal in assignmentsForPrincipal)
                                    {
                                        var binding = assignmentForPrincipal.EnsureProperty(r => r.RoleDefinitionBindings).FirstOrDefault(b => b.Name == parsedRoleDefinition);
                                        if (binding != null)
                                        {
                                            assignmentForPrincipal.DeleteObject();
                                            web.Context.ExecuteQueryRetry();
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(parser);
        }
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                // Get a reference to infrastructural services
                WorkflowServicesManager servicesManager = null;

                try
                {
                    servicesManager = new WorkflowServicesManager(web.Context, web);
                }
                catch (ServerException)
                {
                    // If there is no workflow service present in the farm this method will throw an error.
                    // Swallow the exception
                }

                if (servicesManager != null)
                {
                    var deploymentService   = servicesManager.GetWorkflowDeploymentService();
                    var subscriptionService = servicesManager.GetWorkflowSubscriptionService();

                    // Pre-load useful properties
                    web.EnsureProperty(w => w.Id);

                    // Provision Workflow Definitions
                    foreach (var templateDefinition in template.Workflows.WorkflowDefinitions)
                    {
                        // Load the Workflow Definition XAML
                        Stream xamlStream             = template.Connector.GetFileStream(templateDefinition.XamlPath);
                        System.Xml.Linq.XElement xaml = System.Xml.Linq.XElement.Load(xamlStream);

                        int retryCount    = 5;
                        int retryAttempts = 1;
                        int delay         = 2000;

                        while (retryAttempts <= retryCount)
                        {
                            try
                            {
                                // Create the WorkflowDefinition instance
                                Microsoft.SharePoint.Client.WorkflowServices.WorkflowDefinition workflowDefinition =
                                    new Microsoft.SharePoint.Client.WorkflowServices.WorkflowDefinition(web.Context)
                                {
                                    AssociationUrl          = templateDefinition.AssociationUrl,
                                    Description             = templateDefinition.Description,
                                    DisplayName             = templateDefinition.DisplayName,
                                    FormField               = templateDefinition.FormField,
                                    DraftVersion            = templateDefinition.DraftVersion,
                                    Id                      = templateDefinition.Id,
                                    InitiationUrl           = templateDefinition.InitiationUrl,
                                    RequiresAssociationForm = templateDefinition.RequiresAssociationForm,
                                    RequiresInitiationForm  = templateDefinition.RequiresInitiationForm,
                                    RestrictToScope         = parser.ParseString(templateDefinition.RestrictToScope),
                                    RestrictToType          = templateDefinition.RestrictToType != "Universal" ? templateDefinition.RestrictToType : null,
                                    Xaml                    = parser.ParseString(xaml.ToString()),
                                };

                                //foreach (var p in definition.Properties)
                                //{
                                //    workflowDefinition.SetProperty(p.Key, parser.ParseString(p.Value));
                                //}

                                // Save the Workflow Definition
                                var newDefinition = deploymentService.SaveDefinition(workflowDefinition);
                                //web.Context.Load(workflowDefinition); //not needed
                                web.Context.ExecuteQueryRetry();

                                // Let's publish the Workflow Definition, if needed
                                if (templateDefinition.Published)
                                {
                                    deploymentService.PublishDefinition(newDefinition.Value);
                                    web.Context.ExecuteQueryRetry();
                                }

                                break; // no errors so exit loop
                            }
                            catch (Exception ex)
                            {
                                // check exception is due to connection closed issue
                                if (ex is ServerException && ((ServerException)ex).ServerErrorCode == -2130575223 &&
                                    ((ServerException)ex).ServerErrorTypeName.Equals("Microsoft.SharePoint.SPException", StringComparison.InvariantCultureIgnoreCase) &&
                                    ((ServerException)ex).Message.Contains("A connection that was expected to be kept alive was closed by the server.")
                                    )
                                {
                                    WriteMessage($"Connection closed whilst adding Workflow Definition, trying again in {delay}ms", ProvisioningMessageType.Warning);

                                    Thread.Sleep(delay);

                                    retryAttempts++;
                                    delay = delay * 2; // double delay for next retry
                                }
                                else
                                {
                                    throw;
                                }
                            }
                        }
                    }


                    // get existing subscriptions
                    var existingWorkflowSubscriptions = web.GetWorkflowSubscriptions();

                    foreach (var subscription in template.Workflows.WorkflowSubscriptions)
                    {
                        Microsoft.SharePoint.Client.WorkflowServices.WorkflowSubscription workflowSubscription = null;

                        // Check if the subscription already exists before adding it, and
                        // if already exists a subscription with the same name and with the same DefinitionId,
                        // it is a duplicate and we just need to update it
                        string subscriptionName;
                        if (subscription.PropertyDefinitions.TryGetValue("SharePointWorkflowContext.Subscription.Name", out subscriptionName) &&
                            existingWorkflowSubscriptions.Any(s => s.PropertyDefinitions["SharePointWorkflowContext.Subscription.Name"] == subscriptionName && s.DefinitionId == subscription.DefinitionId))
                        {
                            // Thus, delete it before adding it again!
                            WriteMessage($"Workflow Subscription '{subscription.Name}' already exists. It will be updated.", ProvisioningMessageType.Warning);
                            workflowSubscription = existingWorkflowSubscriptions.FirstOrDefault((s => s.PropertyDefinitions["SharePointWorkflowContext.Subscription.Name"] == subscriptionName && s.DefinitionId == subscription.DefinitionId));

                            if (workflowSubscription != null)
                            {
                                subscriptionService.DeleteSubscription(workflowSubscription.Id);
                                web.Context.ExecuteQueryRetry();
                            }
                        }

#if ONPREMISES
                        // Create the WorkflowDefinition instance
                        workflowSubscription =
                            new Microsoft.SharePoint.Client.WorkflowServices.WorkflowSubscription(web.Context)
                        {
                            DefinitionId  = subscription.DefinitionId,
                            Enabled       = subscription.Enabled,
                            EventSourceId = (!String.IsNullOrEmpty(subscription.EventSourceId)) ? Guid.Parse(parser.ParseString(subscription.EventSourceId)) : web.Id,
                            EventTypes    = subscription.EventTypes,
                            ManualStartBypassesActivationLimit = subscription.ManualStartBypassesActivationLimit,
                            Name            = subscription.Name,
                            StatusFieldName = subscription.StatusFieldName,
                        };
#else
                        // Create the WorkflowDefinition instance
                        workflowSubscription =
                            new Microsoft.SharePoint.Client.WorkflowServices.WorkflowSubscription(web.Context)
                        {
                            DefinitionId  = subscription.DefinitionId,
                            Enabled       = subscription.Enabled,
                            EventSourceId = (!String.IsNullOrEmpty(subscription.EventSourceId)) ? Guid.Parse(parser.ParseString(subscription.EventSourceId)) : web.Id,
                            EventTypes    = subscription.EventTypes,
                            ManualStartBypassesActivationLimit = subscription.ManualStartBypassesActivationLimit,
                            Name = subscription.Name,
                            ParentContentTypeId = subscription.ParentContentTypeId,
                            StatusFieldName     = subscription.StatusFieldName,
                        };
#endif

                        if (workflowSubscription != null)
                        {
                            foreach (var propertyDefinition in subscription.PropertyDefinitions
                                     .Where(d => d.Key == "TaskListId" ||
                                            d.Key == "HistoryListId" ||
                                            d.Key == "SharePointWorkflowContext.Subscription.Id" ||
                                            d.Key == "SharePointWorkflowContext.Subscription.Name" ||
                                            d.Key == "CreatedBySPD"))
                            {
                                workflowSubscription.SetProperty(propertyDefinition.Key, parser.ParseString(propertyDefinition.Value));
                            }
                            if (!String.IsNullOrEmpty(subscription.ListId))
                            {
                                // It is a List Workflow
                                Guid targetListId = Guid.Parse(parser.ParseString(subscription.ListId));
                                subscriptionService.PublishSubscriptionForList(workflowSubscription, targetListId);
                            }
                            else
                            {
                                // It is a Site Workflow
                                subscriptionService.PublishSubscription(workflowSubscription);
                            }
                            web.Context.ExecuteQueryRetry();
                        }
                    }
                }
            }

            return(parser);
        }
        private static Field CreateField(XElement fieldElement, ListInfo listInfo, TokenParser parser, string originalFieldXml, ClientRuntimeContext context, PnPMonitoredScope scope)
        {
            Field field = null;
            fieldElement = PrepareField(fieldElement);

            var fieldXml = parser.ParseString(fieldElement.ToString(), "~sitecollection", "~site");
            if (IsFieldXmlValid(parser.ParseString(originalFieldXml), parser, context))
            {
                field = listInfo.SiteList.Fields.AddFieldAsXml(fieldXml, false, AddFieldOptions.AddFieldInternalNameHint);
                listInfo.SiteList.Context.Load(field);
                listInfo.SiteList.Context.ExecuteQueryRetry();

                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())
                    {
                        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;
                        }
                    }
                }
            #endif
                if (isDirty)
                {
                    field.Update();
                    listInfo.SiteList.Context.ExecuteQueryRetry();
                }
            }
            else
            {
                // The field Xml was found invalid
                var tokenString = parser.GetLeftOverTokens(originalFieldXml).Aggregate(String.Empty, (acc, i) => acc + " " + i);
                scope.LogError("The field was found invalid: {0}", tokenString);
                throw new Exception(string.Format("The field was found invalid: {0}", tokenString));
            }
            return field;
        }
示例#28
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));
            }
        }
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                // Get a reference to infrastructural services
                var servicesManager = new WorkflowServicesManager(web.Context, web);
                var deploymentService = servicesManager.GetWorkflowDeploymentService();
                var subscriptionService = servicesManager.GetWorkflowSubscriptionService();

                // Provision Workflow Definitions
                foreach (var definition in template.Workflows.WorkflowDefinitions)
                {
                    // Load the Workflow Definition XAML
                    Stream xamlStream = template.Connector.GetFileStream(definition.XamlPath);
                    System.Xml.Linq.XElement xaml = System.Xml.Linq.XElement.Load(xamlStream);

                    // Create the WorkflowDefinition instance
                    Microsoft.SharePoint.Client.WorkflowServices.WorkflowDefinition workflowDefinition =
                        new Microsoft.SharePoint.Client.WorkflowServices.WorkflowDefinition(web.Context)
                        {
                            AssociationUrl = definition.AssociationUrl,
                            Description = definition.Description,
                            DisplayName = definition.DisplayName,
                            FormField = definition.FormField,
                            DraftVersion = definition.DraftVersion,
                            Id = definition.Id,
                            InitiationUrl = definition.InitiationUrl,
                            RequiresAssociationForm = definition.RequiresAssociationForm,
                            RequiresInitiationForm = definition.RequiresInitiationForm,
                            RestrictToScope = parser.ParseString(definition.RestrictToScope),
                            RestrictToType = definition.RestrictToType != "Universal" ? definition.RestrictToType : null,
                            Xaml = xaml.ToString(),
                        };

                    //foreach (var p in definition.Properties)
                    //{
                    //    workflowDefinition.SetProperty(p.Key, parser.ParseString(p.Value));
                    //}

                    // Save the Workflow Definition
                    var definitionId = deploymentService.SaveDefinition(workflowDefinition);
                    web.Context.Load(workflowDefinition);
                    web.Context.ExecuteQueryRetry();

                    // Let's publish the Workflow Definition, if needed
                    if (definition.Published)
                    {
                        deploymentService.PublishDefinition(definitionId.Value);
                    }
                }

                foreach (var subscription in template.Workflows.WorkflowSubscriptions)
                {
            #if CLIENTSDKV15
                    // Create the WorkflowDefinition instance
                    Microsoft.SharePoint.Client.WorkflowServices.WorkflowSubscription workflowSubscription =
                        new Microsoft.SharePoint.Client.WorkflowServices.WorkflowSubscription(web.Context)
                        {
                            DefinitionId = subscription.DefinitionId,
                            Enabled = subscription.Enabled,
                            EventSourceId = (!String.IsNullOrEmpty(subscription.EventSourceId)) ? Guid.Parse(parser.ParseString(subscription.EventSourceId)) : web.Id,
                            EventTypes = subscription.EventTypes,
                            ManualStartBypassesActivationLimit =  subscription.ManualStartBypassesActivationLimit,
                            Name =  subscription.Name,
                            StatusFieldName = subscription.StatusFieldName,
                        };
            #else
                    // Create the WorkflowDefinition instance
                    Microsoft.SharePoint.Client.WorkflowServices.WorkflowSubscription workflowSubscription =
                        new Microsoft.SharePoint.Client.WorkflowServices.WorkflowSubscription(web.Context)
                        {
                            DefinitionId = subscription.DefinitionId,
                            Enabled = subscription.Enabled,
                            EventSourceId = (!String.IsNullOrEmpty(subscription.EventSourceId)) ? Guid.Parse(parser.ParseString(subscription.EventSourceId)) : web.Id,
                            EventTypes = subscription.EventTypes,
                            ManualStartBypassesActivationLimit =  subscription.ManualStartBypassesActivationLimit,
                            Name =  subscription.Name,
                            ParentContentTypeId = subscription.ParentContentTypeId,
                            StatusFieldName = subscription.StatusFieldName,
                        };
            #endif
                    foreach (var p in subscription.PropertyDefinitions
                        .Where(d => d.Key == "TaskListId" || d.Key == "HistoryListId"))
                    {
                        workflowSubscription.SetProperty(p.Key, parser.ParseString(p.Value));
                    }

                    if (!String.IsNullOrEmpty(subscription.ListId))
                    {
                        // It is a List Workflow
                        Guid targetListId = Guid.Parse(parser.ParseString(subscription.ListId));
                        subscriptionService.PublishSubscriptionForList(workflowSubscription, targetListId);
                    }
                    else
                    {
                        // It is a Site Workflow
                        subscriptionService.PublishSubscription(workflowSubscription);
                    }
                    web.Context.ExecuteQueryRetry();
                }
            }

            return parser;
        }
示例#30
0
        private void UpdateField(Web web, string fieldId, XElement templateFieldElement, PnPMonitoredScope scope, TokenParser parser, string originalFieldXml)
        {
            var existingField = web.Fields.GetById(Guid.Parse(fieldId));

            web.Context.Load(existingField, f => f.SchemaXml);
            web.Context.ExecuteQueryRetry();

            XElement existingFieldElement = XElement.Parse(existingField.SchemaXml);

            XNodeEqualityComparer equalityComparer = new XNodeEqualityComparer();

            if (equalityComparer.GetHashCode(existingFieldElement) != equalityComparer.GetHashCode(templateFieldElement)) // Is field different in template?
            {
                if (existingFieldElement.Attribute("Type").Value == templateFieldElement.Attribute("Type").Value)         // Is existing field of the same type?
                {
                    if (IsFieldXmlValid(parser.ParseString(originalFieldXml), parser, web.Context))
                    {
                        var listIdentifier = templateFieldElement.Attribute("List") != null?templateFieldElement.Attribute("List").Value : null;

                        if (listIdentifier != null)
                        {
                            // Temporary remove list attribute from list
                            templateFieldElement.Attribute("List").Remove();
                        }

                        foreach (var attribute in templateFieldElement.Attributes())
                        {
                            if (existingFieldElement.Attribute(attribute.Name) != null)
                            {
                                existingFieldElement.Attribute(attribute.Name).Value = attribute.Value;
                            }
                            else
                            {
                                existingFieldElement.Add(attribute);
                            }
                        }
                        foreach (var element in templateFieldElement.Elements())
                        {
                            if (existingFieldElement.Element(element.Name) != null)
                            {
                                existingFieldElement.Element(element.Name).Remove();
                            }
                            existingFieldElement.Add(element);
                        }

                        if (existingFieldElement.Attribute("Version") != null)
                        {
                            existingFieldElement.Attributes("Version").Remove();
                        }
                        existingField.SchemaXml = parser.ParseString(existingFieldElement.ToString(), "~sitecollection", "~site");
                        existingField.UpdateAndPushChanges(true);
                        web.Context.Load(existingField, f => f.TypeAsString, f => f.DefaultValue);
                        web.Context.ExecuteQueryRetry();

                        bool isDirty = false;
#if !SP2013
                        if (originalFieldXml.ContainsResourceToken())
                        {
                            var originalFieldElement = XElement.Parse(originalFieldXml);
                            var nameAttributeValue   = originalFieldElement.Attribute("DisplayName") != null?originalFieldElement.Attribute("DisplayName").Value : "";

                            if (nameAttributeValue.ContainsResourceToken())
                            {
                                existingField.TitleResource.SetUserResourceValue(nameAttributeValue, parser);
                                isDirty = true;
                            }
                            var descriptionAttributeValue = originalFieldElement.Attribute("Description") != null?originalFieldElement.Attribute("Description").Value : "";

                            if (descriptionAttributeValue.ContainsResourceToken())
                            {
                                existingField.DescriptionResource.SetUserResourceValue(descriptionAttributeValue, parser);
                                isDirty = true;
                            }
                        }
#endif
                        if (isDirty)
                        {
                            existingField.Update();
                            web.Context.ExecuteQueryRetry();
                        }
                        if ((existingField.TypeAsString == "TaxonomyFieldType" || existingField.TypeAsString == "TaxonomyFieldTypeMulti") && !string.IsNullOrEmpty(existingField.DefaultValue))
                        {
                            var taxField = web.Context.CastTo <TaxonomyField>(existingField);
                            ValidateTaxonomyFieldDefaultValue(taxField);
                        }
                    }
                    else
                    {
                        // The field Xml was found invalid
                        var tokenString = parser.GetLeftOverTokens(originalFieldXml).Aggregate(String.Empty, (acc, i) => acc + " " + i);
                        scope.LogError("The field was found invalid: {0}", tokenString);
                        throw new Exception(string.Format("The field was found invalid: {0}", tokenString));
                    }
                }
                else
                {
                    var fieldName = existingFieldElement.Attribute("Name") != null?existingFieldElement.Attribute("Name").Value : existingFieldElement.Attribute("StaticName").Value;

                    WriteWarning(string.Format(CoreResources.Provisioning_ObjectHandlers_Fields_Field__0____1___exists_but_is_of_different_type__Skipping_field_, fieldName, fieldId), ProvisioningMessageType.Warning);
                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_Fields_Field__0____1___exists_but_is_of_different_type__Skipping_field_, fieldName, fieldId);
                }
            }
        }
示例#31
0
        private TokenParser ProcessLookupFields(Web web, ProvisioningTemplate template, TokenParser parser, PnPMonitoredScope scope)
        {
            var rootWeb = (web.Context as ClientContext).Site.RootWeb;

            rootWeb.Context.Load(rootWeb.Lists, lists => lists.Include(l => l.Id, l => l.RootFolder.ServerRelativeUrl, l => l.Fields).Where(l => l.Hidden == false));
            rootWeb.Context.ExecuteQueryRetry();

            foreach (var siteField in template.SiteFields)
            {
                var fieldElement = XElement.Parse(siteField.SchemaXml);

                if (fieldElement.Attribute("List") != null)
                {
                    var fieldId                    = Guid.Parse(fieldElement.Attribute("ID").Value);
                    var listIdentifier             = parser.ParseString(fieldElement.Attribute("List").Value);
                    var relationshipDeleteBehavior = fieldElement.Attribute("RelationshipDeleteBehavior") != null?fieldElement.Attribute("RelationshipDeleteBehavior").Value : string.Empty;

                    var webId = string.Empty;

                    var field = rootWeb.Fields.GetById(fieldId);
                    rootWeb.Context.Load(field, f => f.SchemaXmlWithResourceTokens);
                    rootWeb.Context.ExecuteQueryRetry();

                    List sourceList = FindSourceList(listIdentifier, web, rootWeb);

                    if (sourceList != null)
                    {
                        rootWeb.Context.Load(sourceList.ParentWeb);
                        rootWeb.Context.ExecuteQueryRetry();

                        webId = sourceList.ParentWeb.Id.ToString();

                        ProcessField(field, sourceList.Id, webId, relationshipDeleteBehavior);
                    }
                }
            }

            web.Context.Load(web.Lists, lists => lists.Include(l => l.Id, l => l.RootFolder.ServerRelativeUrl, l => l.Fields).Where(l => l.Hidden == false));
            web.Context.ExecuteQueryRetry();

            foreach (var listInstance in template.Lists)
            {
                foreach (var listField in listInstance.Fields)
                {
                    var fieldElement = XElement.Parse(listField.SchemaXml);
                    if (fieldElement.Attribute("List") == null)
                    {
                        continue;
                    }

                    var fieldId                    = Guid.Parse(fieldElement.Attribute("ID").Value);
                    var listIdentifier             = parser.ParseString(fieldElement.Attribute("List").Value);
                    var relationshipDeleteBehavior = fieldElement.Attribute("RelationshipDeleteBehavior") != null?fieldElement.Attribute("RelationshipDeleteBehavior").Value : string.Empty;

                    var webId = string.Empty;

                    var listUrl = UrlUtility.Combine(web.ServerRelativeUrl, parser.ParseString(listInstance.Url));

                    var createdList = web.Lists.FirstOrDefault(l => l.RootFolder.ServerRelativeUrl.Equals(listUrl, StringComparison.OrdinalIgnoreCase));
                    if (createdList != null)
                    {
                        try
                        {
                            var field = createdList.Fields.GetById(fieldId);
                            web.Context.Load(field, f => f.SchemaXmlWithResourceTokens);
                            web.Context.ExecuteQueryRetry();

                            List sourceList = FindSourceList(listIdentifier, web, rootWeb);

                            if (sourceList != null)
                            {
                                web.Context.Load(sourceList.ParentWeb);
                                web.Context.ExecuteQueryRetry();

                                webId = sourceList.ParentWeb.Id.ToString();
                                ProcessField(field, sourceList.Id, webId, relationshipDeleteBehavior);
                            }
                        }
                        catch (ArgumentException ex)
                        {
                            // We skip and log any issues related to not existing lookup fields
                            scope.LogError(String.Format("Exception searching for field! {0}", ex.Message));
                        }
                    }
                }
            }

            return(parser);
        }
示例#32
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.Url);

                foreach (var file in template.Files)
                {
                    var folderName = parser.ParseString(file.Folder);

                    if (folderName.ToLower().StartsWith((web.ServerRelativeUrl.ToLower())))
                    {
                        folderName = folderName.Substring(web.ServerRelativeUrl.Length);
                    }

                    var folder = web.EnsureFolderPath(folderName);

                    File targetFile = null;

                    var checkedOut = false;

                    targetFile = folder.GetFile(template.Connector.GetFilenamePart(file.Src));

                    if (targetFile != null)
                    {
                        if (file.Overwrite)
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Files_Uploading_and_overwriting_existing_file__0_, file.Src);
                            checkedOut = CheckOutIfNeeded(web, targetFile);

                            using (var stream = template.Connector.GetFileStream(file.Src))
                            {
                                targetFile = folder.UploadFile(template.Connector.GetFilenamePart(file.Src), stream, file.Overwrite);
                            }
                        }
                        else
                        {
                            checkedOut = CheckOutIfNeeded(web, targetFile);
                        }
                    }
                    else
                    {
                        using (var stream = template.Connector.GetFileStream(file.Src))
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Files_Uploading_file__0_, file.Src);
                            targetFile = folder.UploadFile(template.Connector.GetFilenamePart(file.Src), stream, file.Overwrite);
                        }

                        checkedOut = CheckOutIfNeeded(web, targetFile);
                    }

                    if (targetFile != null)
                    {
                        if (file.Properties != null && file.Properties.Any())
                        {
                            Dictionary <string, string> transformedProperties = file.Properties.ToDictionary(property => property.Key, property => parser.ParseString(property.Value));
                            SetFileProperties(targetFile, transformedProperties, false);
                        }

                        if (file.WebParts != null && file.WebParts.Any())
                        {
                            targetFile.EnsureProperties(f => f.ServerRelativeUrl);

                            var existingWebParts = web.GetWebParts(targetFile.ServerRelativeUrl);
                            foreach (var webpart in file.WebParts)
                            {
                                // check if the webpart is already set on the page
                                if (existingWebParts.FirstOrDefault(w => w.WebPart.Title == webpart.Title) == null)
                                {
                                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Files_Adding_webpart___0___to_page, webpart.Title);
                                    var wpEntity = new WebPartEntity();
                                    wpEntity.WebPartTitle = webpart.Title;
                                    wpEntity.WebPartXml   = parser.ParseString(webpart.Contents).Trim(new[] { '\n', ' ' });
                                    wpEntity.WebPartZone  = webpart.Zone;
                                    wpEntity.WebPartIndex = (int)webpart.Order;
                                    web.AddWebPartToWebPartPage(targetFile.ServerRelativeUrl, wpEntity);
                                }
                            }
                        }

                        if (checkedOut)
                        {
                            targetFile.CheckIn("", CheckinType.MajorCheckIn);
                            web.Context.ExecuteQueryRetry();
                        }

                        // 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);
                        }
                    }
                }
            }
            return(parser);
        }
示例#33
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (template.WebSettings != null)
                {
                    // Check if this is not a noscript site as we're not allowed to update some properties
                    bool isNoScriptSite = web.IsNoScriptSite();

                    web.EnsureProperties(
#if !SP2013 && !SP2016
                        w => w.NoCrawl,
                        w => w.CommentsOnSitePagesDisabled,
                        w => w.ExcludeFromOfflineClient,
                        w => w.MembersCanShare,
                        w => w.DisableFlows,
                        w => w.DisableAppViews,
                        w => w.HorizontalQuickLaunch,
#if !SP2019
                        w => w.SearchScope,
                        w => w.SearchBoxInNavBar,
#endif
#endif
                        w => w.RootFolder,
                        w => w.Title,
                        w => w.Description,
                        w => w.AlternateCssUrl,
                        w => w.WebTemplate,
                        w => w.HasUniqueRoleAssignments);

                    var webSettings = template.WebSettings;

                    // Since the IsSubSite function can trigger an executequery ensure it's called before any updates to the web object are done.
                    if (!web.IsSubSite() || (web.IsSubSite() && web.HasUniqueRoleAssignments))
                    {
                        String requestAccessEmailValue = parser.ParseString(webSettings.RequestAccessEmail);
                        if (!String.IsNullOrEmpty(requestAccessEmailValue) && requestAccessEmailValue.Length >= 255)
                        {
                            requestAccessEmailValue = requestAccessEmailValue.Substring(0, 255);
                        }
                        if (!String.IsNullOrEmpty(requestAccessEmailValue))
                        {
                            web.RequestAccessEmail = requestAccessEmailValue;

                            web.Update();
                            web.Context.ExecuteQueryRetry();
                        }
                    }

#if !SP2013 && !SP2016
                    if (!isNoScriptSite)
                    {
                        web.NoCrawl = webSettings.NoCrawl;
                    }
                    else
                    {
                        scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_WebSettings_SkipNoCrawlUpdate);
                    }

                    if (web.CommentsOnSitePagesDisabled != webSettings.CommentsOnSitePagesDisabled)
                    {
                        web.CommentsOnSitePagesDisabled = webSettings.CommentsOnSitePagesDisabled;
                    }

                    if (web.ExcludeFromOfflineClient != webSettings.ExcludeFromOfflineClient)
                    {
                        web.ExcludeFromOfflineClient = webSettings.ExcludeFromOfflineClient;
                    }

                    if (web.MembersCanShare != webSettings.MembersCanShare)
                    {
                        web.MembersCanShare = webSettings.MembersCanShare;
                    }

                    if (web.DisableFlows != webSettings.DisableFlows)
                    {
                        web.DisableFlows = webSettings.DisableFlows;
                    }

                    if (web.DisableAppViews != webSettings.DisableAppViews)
                    {
                        web.DisableAppViews = webSettings.DisableAppViews;
                    }

                    if (web.HorizontalQuickLaunch != webSettings.HorizontalQuickLaunch)
                    {
                        web.HorizontalQuickLaunch = webSettings.HorizontalQuickLaunch;
                    }

#if !SP2019
                    if (web.SearchScope.ToString() != webSettings.SearchScope.ToString())
                    {
                        web.SearchScope = (SearchScopeType)Enum.Parse(typeof(SearchScopeType), webSettings.SearchScope.ToString(), true);
                    }

                    if (web.SearchBoxInNavBar.ToString() != webSettings.SearchBoxInNavBar.ToString())
                    {
                        web.SearchBoxInNavBar = (SearchBoxInNavBarType)Enum.Parse(typeof(SearchBoxInNavBarType), webSettings.SearchBoxInNavBar.ToString(), true);
                    }

                    string searchCenterUrl = parser.ParseString(webSettings.SearchCenterUrl);
                    if (!string.IsNullOrEmpty(searchCenterUrl) &&
                        web.GetWebSearchCenterUrl(true) != webSettings.SearchCenterUrl)
                    {
                        web.SetWebSearchCenterUrl(webSettings.SearchCenterUrl);
                    }
#endif
#endif
                    var masterUrl = parser.ParseString(webSettings.MasterPageUrl);
                    if (!string.IsNullOrEmpty(masterUrl))
                    {
                        if (!isNoScriptSite)
                        {
                            web.MasterUrl = masterUrl;
                        }
                        else
                        {
                            scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_WebSettings_SkipMasterPageUpdate);
                        }
                    }
                    var customMasterUrl = parser.ParseString(webSettings.CustomMasterPageUrl);
                    if (!string.IsNullOrEmpty(customMasterUrl))
                    {
                        if (!isNoScriptSite)
                        {
                            web.CustomMasterUrl = customMasterUrl;
                        }
                        else
                        {
                            scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_WebSettings_SkipCustomMasterPageUpdate);
                        }
                    }
                    if (!String.IsNullOrEmpty(webSettings.Title))
                    {
                        var newTitle = parser.ParseString(webSettings.Title);
                        if (newTitle != web.Title)
                        {
                            web.Title = newTitle;
                        }
                    }
                    if (!String.IsNullOrEmpty(webSettings.Description))
                    {
                        var newDescription = parser.ParseString(webSettings.Description);
                        if (newDescription != web.Description)
                        {
                            web.Description = newDescription;
                        }
                    }
                    if (webSettings.SiteLogo != null)
                    {
                        var logoUrl = parser.ParseString(webSettings.SiteLogo);
                        if (template.BaseSiteTemplate == "SITEPAGEPUBLISHING#0" && web.WebTemplate == "GROUP")
                        {
                            // logo provisioning throws when applying across base template IDs; provisioning fails in this case
                            // this is the error that is already (rightly so) shown beforehand in the console: WARNING: The source site from which the template was generated had a base template ID value of SITEPAGEPUBLISHING#0, while the current target site has a base template ID value of GROUP#0. This could cause potential issues while applying the template.
                            WriteMessage("Applying site logo across base template IDs is not possible. Skipping site logo provisioning.", ProvisioningMessageType.Warning);
                        }
                        else
                        {
                            // Modern site? Then we assume the SiteLogo is actually a filepath
                            if (web.WebTemplate == "GROUP")
                            {
#if !ONPREMISES
                                if (!string.IsNullOrEmpty(logoUrl) && !logoUrl.ToLower().Contains("_api/groupservice/getgroupimage"))
                                {
                                    var fileBytes = ConnectorFileHelper.GetFileBytes(template.Connector, logoUrl);
                                    if (fileBytes != null && fileBytes.Length > 0)
                                    {
#if !NETSTANDARD2_0
                                        var mimeType = MimeMapping.GetMimeMapping(logoUrl);
#else
                                        var mimeType = "";
                                        var imgUrl   = logoUrl;
                                        if (imgUrl.Contains("?"))
                                        {
                                            imgUrl = imgUrl.Split(new[] { '?' })[0];
                                        }
                                        if (imgUrl.EndsWith(".gif", StringComparison.InvariantCultureIgnoreCase))
                                        {
                                            mimeType = "image/gif";
                                        }
                                        if (imgUrl.EndsWith(".png", StringComparison.InvariantCultureIgnoreCase))
                                        {
                                            mimeType = "image/png";
                                        }
                                        if (imgUrl.EndsWith(".jpg", StringComparison.InvariantCultureIgnoreCase))
                                        {
                                            mimeType = "image/jpeg";
                                        }
#endif
                                        Sites.SiteCollection.SetGroupImageAsync((ClientContext)web.Context, fileBytes, mimeType).GetAwaiter().GetResult();
                                    }
                                }
#endif
                            }
                            else
                            {
                                web.SiteLogoUrl = logoUrl;
                            }
                        }
                    }
                    var welcomePage = parser.ParseString(webSettings.WelcomePage);
                    if (!string.IsNullOrEmpty(welcomePage))
                    {
                        if (welcomePage != web.RootFolder.WelcomePage)
                        {
                            web.RootFolder.WelcomePage = welcomePage;
                            web.RootFolder.Update();
                        }
                    }
                    if (!string.IsNullOrEmpty(webSettings.AlternateCSS))
                    {
                        var newAlternateCssUrl = parser.ParseString(webSettings.AlternateCSS);
                        if (newAlternateCssUrl != web.AlternateCssUrl)
                        {
                            web.AlternateCssUrl = newAlternateCssUrl;
                        }
                    }

                    // Temporary disabled as this change is a breaking change for folks that have not set this property in their provisioning templates
                    //web.QuickLaunchEnabled = webSettings.QuickLaunchEnabled;

                    web.Update();
                    web.Context.ExecuteQueryRetry();

#if !ONPREMISES
                    if (webSettings.HubSiteUrl != null)
                    {
                        var hubsiteUrl = parser.ParseString(webSettings.HubSiteUrl);
                        try
                        {
                            using (var tenantContext = web.Context.Clone(web.GetTenantAdministrationUrl(), applyingInformation.AccessTokens))
                            {
                                var tenant = new Tenant(tenantContext);
                                tenant.ConnectSiteToHubSite(web.Url, hubsiteUrl);
                                tenantContext.ExecuteQueryRetry();
                            }
                        }
                        catch (Exception ex)
                        {
                            WriteMessage($"Hub site association failed: {ex.Message}", ProvisioningMessageType.Warning);
                        }
                    }
#endif
                }
            }

            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 <List>().Select(existingList => existingList.RootFolder.ServerRelativeUrl).ToList();
                    var serverRelativeUrl = web.ServerRelativeUrl;

                    #region DataRows

                    foreach (var listInstance in template.Lists)
                    {
                        if (listInstance.DataRows != null && listInstance.DataRows.Any())
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Processing_data_rows_for__0_, listInstance.Title);
                            // Retrieve the target list
                            var list = web.Lists.GetByTitle(parser.ParseString(listInstance.Title));
                            web.Context.Load(list);

                            // Retrieve the fields' types from the list
                            Microsoft.SharePoint.Client.FieldCollection fields = list.Fields;
                            web.Context.Load(fields, fs => fs.Include(f => f.InternalName, f => f.FieldTypeKind));
                            web.Context.ExecuteQueryRetry();

                            foreach (var dataRow in listInstance.DataRows)
                            {
                                try
                                {
                                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_list_item__0_, listInstance.DataRows.IndexOf(dataRow) + 1);
                                    var listitemCI = new ListItemCreationInformation();
                                    var listitem   = list.AddItem(listitemCI);

                                    foreach (var dataValue in dataRow.Values)
                                    {
                                        Field dataField = fields.FirstOrDefault(
                                            f => f.InternalName == parser.ParseString(dataValue.Key));

                                        if (dataField != null)
                                        {
                                            String fieldValue = parser.ParseString(dataValue.Value);

                                            switch (dataField.FieldTypeKind)
                                            {
                                            case FieldType.Geolocation:
                                                // FieldGeolocationValue - Expected format: Altitude,Latitude,Longitude,Measure
                                                var geolocationArray = fieldValue.Split(',');
                                                if (geolocationArray.Length == 4)
                                                {
                                                    var geolocationValue = new FieldGeolocationValue
                                                    {
                                                        Altitude  = Double.Parse(geolocationArray[0]),
                                                        Latitude  = Double.Parse(geolocationArray[1]),
                                                        Longitude = Double.Parse(geolocationArray[2]),
                                                        Measure   = Double.Parse(geolocationArray[3]),
                                                    };
                                                    listitem[parser.ParseString(dataValue.Key)] = geolocationValue;
                                                }
                                                else
                                                {
                                                    listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                }
                                                break;

                                            case FieldType.Lookup:
                                                // FieldLookupValue - Expected format: LookupID or LookupID,LookupID,LookupID...
                                                if (fieldValue.Contains(","))
                                                {
                                                    var lookupValues = new List <FieldLookupValue>();
                                                    fieldValue.Split(',').All(value =>
                                                    {
                                                        lookupValues.Add(new FieldLookupValue
                                                        {
                                                            LookupId = int.Parse(value),
                                                        });
                                                        return(true);
                                                    });
                                                    listitem[parser.ParseString(dataValue.Key)] = lookupValues.ToArray();
                                                }
                                                else
                                                {
                                                    var lookupValue = new FieldLookupValue
                                                    {
                                                        LookupId = int.Parse(fieldValue),
                                                    };
                                                    listitem[parser.ParseString(dataValue.Key)] = lookupValue;
                                                }
                                                break;

                                            case FieldType.URL:
                                                // FieldUrlValue - Expected format: URL,Description
                                                var urlArray  = fieldValue.Split(',');
                                                var linkValue = new FieldUrlValue();
                                                if (urlArray.Length == 2)
                                                {
                                                    linkValue.Url         = urlArray[0];
                                                    linkValue.Description = urlArray[1];
                                                }
                                                else
                                                {
                                                    linkValue.Url         = urlArray[0];
                                                    linkValue.Description = urlArray[0];
                                                }
                                                listitem[parser.ParseString(dataValue.Key)] = linkValue;
                                                break;

                                            case FieldType.User:
                                                // FieldUserValue - Expected format: loginName or loginName,loginName,loginName...
                                                if (fieldValue.Contains(","))
                                                {
                                                    var userValues = new List <FieldUserValue>();
                                                    fieldValue.Split(',').All(value =>
                                                    {
                                                        var user = web.EnsureUser(value);
                                                        web.Context.Load(user);
                                                        web.Context.ExecuteQueryRetry();
                                                        if (user != null)
                                                        {
                                                            userValues.Add(new FieldUserValue
                                                            {
                                                                LookupId = user.Id,
                                                            });;
                                                        }
                                                        return(true);
                                                    });
                                                    listitem[parser.ParseString(dataValue.Key)] = userValues.ToArray();
                                                }
                                                else
                                                {
                                                    var user = web.EnsureUser(fieldValue);
                                                    web.Context.Load(user);
                                                    web.Context.ExecuteQueryRetry();
                                                    if (user != null)
                                                    {
                                                        var userValue = new FieldUserValue
                                                        {
                                                            LookupId = user.Id,
                                                        };
                                                        listitem[parser.ParseString(dataValue.Key)] = userValue;
                                                    }
                                                    else
                                                    {
                                                        listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                    }
                                                }
                                                break;

                                            case FieldType.DateTime:
                                                var dateTime = DateTime.MinValue;
                                                if (DateTime.TryParse(fieldValue, out dateTime))
                                                {
                                                    listitem[parser.ParseString(dataValue.Key)] = dateTime;
                                                }
                                                break;

                                            default:
                                                listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                break;
                                            }
                                        }
                                    }
                                    listitem.Update();
                                    web.Context.ExecuteQueryRetry(); // TODO: Run in batches?

                                    if (dataRow.Security != null && dataRow.Security.RoleAssignments.Count != 0)
                                    {
                                        listitem.SetSecurity(parser, dataRow.Security);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    if (ex.GetType().Equals(typeof(ServerException)) &&
                                        (ex as ServerException).ServerErrorTypeName.Equals("Microsoft.SharePoint.SPDuplicateValuesFoundException", StringComparison.InvariantCultureIgnoreCase) &&
                                        applyingInformation.IgnoreDuplicateDataRowErrors)
                                    {
                                        scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_duplicate);
                                        continue;
                                    }
                                    else
                                    {
                                        scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_failed___0_____1_, ex.Message, ex.StackTrace);
                                        throw;
                                    }
                                }
                            }
                        }
                    }

                    #endregion
                }
            }

            return(parser);
        }
        private void UpdateField(ClientObject web, ListInfo listInfo, Guid fieldId, XElement templateFieldElement, Field existingField, PnPMonitoredScope scope, TokenParser parser)
        {
            web.Context.Load(existingField, f => f.SchemaXml);
            web.Context.ExecuteQueryRetry();

            var existingFieldElement = XElement.Parse(existingField.SchemaXml);

            var equalityComparer = new XNodeEqualityComparer();

            // Is field different in template?
            if (equalityComparer.GetHashCode(existingFieldElement) != equalityComparer.GetHashCode(templateFieldElement))
            {
                // Is existing field of the same type?
                if (existingFieldElement.Attribute("Type").Value == templateFieldElement.Attribute("Type").Value)
                {
                    templateFieldElement = PrepareField(templateFieldElement);

                    foreach (var attribute in templateFieldElement.Attributes())
                    {
                        if (existingFieldElement.Attribute(attribute.Name) != null)
                        {
                            existingFieldElement.Attribute(attribute.Name).Value = attribute.Value;
                        }
                        else
                        {
                            existingFieldElement.Add(attribute);
                        }
                    }
                    foreach (var element in templateFieldElement.Elements())
                    {
                        if (existingFieldElement.Element(element.Name) != null)
                        {
                            existingFieldElement.Element(element.Name).Remove();
                        }
                        existingFieldElement.Add(element);
                    }

                    if (existingFieldElement.Attribute("Version") != null)
                    {
                        existingFieldElement.Attributes("Version").Remove();
                    }
                    existingField.SchemaXml = parser.ParseString(existingFieldElement.ToString(), "~sitecollection", "~site");
                    existingField.UpdateAndPushChanges(true);
                    web.Context.ExecuteQueryRetry();
                }
                else
                {
                    var fieldName = existingFieldElement.Attribute("Name") != null ? existingFieldElement.Attribute("Name").Value : existingFieldElement.Attribute("StaticName").Value;
                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field__0____1___exists_in_list__2____3___but_is_of_different_type__Skipping_field_, fieldName, fieldId, listInfo.TemplateList.Title, listInfo.SiteList.Id);
                    WriteWarning(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field__0____1___exists_in_list__2____3___but_is_of_different_type__Skipping_field_, fieldName, fieldId, listInfo.TemplateList.Title, listInfo.SiteList.Id), ProvisioningMessageType.Warning);
                }
            }
        }
        private static Microsoft.SharePoint.Client.ContentType CreateContentType(Web web, ContentType templateContentType, TokenParser parser, FileConnectorBase connector,
                                                                                 List <Microsoft.SharePoint.Client.ContentType> existingCTs = null, List <Microsoft.SharePoint.Client.Field> existingFields = null)
        {
            var name        = parser.ParseString(templateContentType.Name);
            var description = parser.ParseString(templateContentType.Description);
            var id          = parser.ParseString(templateContentType.Id);
            var group       = parser.ParseString(templateContentType.Group);

            var createdCT = web.CreateContentType(name, description, id, group);

            foreach (var fieldRef in templateContentType.FieldRefs)
            {
                var field = web.Fields.GetById(fieldRef.Id);
                web.AddFieldToContentType(createdCT, field, fieldRef.Required, fieldRef.Hidden);
            }

            // Add new CTs
            parser.AddToken(new ContentTypeIdToken(web, name, id));

#if !CLIENTSDKV15
            // Set resources
            if (templateContentType.Name.ContainsResourceToken())
            {
                createdCT.NameResource.SetUserResourceValue(templateContentType.Name, parser);
            }
            if (templateContentType.Description.ContainsResourceToken())
            {
                createdCT.DescriptionResource.SetUserResourceValue(templateContentType.Description, parser);
            }
#endif
            //Reorder the elements so that the new created Content Type has the same order as defined in the
            //template. The order can be different if the new Content Type inherits from another Content Type.
            //In this case the new Content Type has all field of the original Content Type and missing fields
            //will be added at the end. To fix this issue we ordering the fields once more.
            createdCT.FieldLinks.Reorder(templateContentType.FieldRefs.Select(fld => fld.Name).ToArray());

            createdCT.ReadOnly = templateContentType.ReadOnly;
            createdCT.Hidden   = templateContentType.Hidden;
            createdCT.Sealed   = templateContentType.Sealed;
            if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DocumentTemplate)))
            {
                createdCT.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate);
            }
            if (!String.IsNullOrEmpty(templateContentType.NewFormUrl))
            {
                createdCT.NewFormUrl = templateContentType.NewFormUrl;
            }
            if (!String.IsNullOrEmpty(templateContentType.EditFormUrl))
            {
                createdCT.EditFormUrl = templateContentType.EditFormUrl;
            }
            if (!String.IsNullOrEmpty(templateContentType.DisplayFormUrl))
            {
                createdCT.DisplayFormUrl = templateContentType.DisplayFormUrl;
            }

            createdCT.Update(true);
            web.Context.ExecuteQueryRetry();

            // If the CT is a DocumentSet
            if (templateContentType.DocumentSetTemplate != null)
            {
                // Retrieve a reference to the DocumentSet Content Type
                Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate documentSetTemplate =
                    Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.GetDocumentSetTemplate(web.Context, createdCT);

                if (!String.IsNullOrEmpty(templateContentType.DocumentSetTemplate.WelcomePage))
                {
                    // TODO: Customize the WelcomePage of the DocumentSet
                }

                foreach (String ctId in templateContentType.DocumentSetTemplate.AllowedContentTypes)
                {
                    Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == ctId);
                    if (ct != null)
                    {
                        documentSetTemplate.AllowedContentTypes.Add(ct.Id);
                    }
                }

                foreach (var doc in templateContentType.DocumentSetTemplate.DefaultDocuments)
                {
                    Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == doc.ContentTypeId);
                    if (ct != null)
                    {
                        using (Stream fileStream = connector.GetFileStream(doc.FileSourcePath))
                        {
                            documentSetTemplate.DefaultDocuments.Add(doc.Name, ct.Id, ReadFullStream(fileStream));
                        }
                    }
                }

                foreach (var sharedField in templateContentType.DocumentSetTemplate.SharedFields)
                {
                    Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == sharedField);
                    if (field != null)
                    {
                        documentSetTemplate.SharedFields.Add(field);
                    }
                }

                foreach (var welcomePageField in templateContentType.DocumentSetTemplate.WelcomePageFields)
                {
                    Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == welcomePageField);
                    if (field != null)
                    {
                        documentSetTemplate.WelcomePageFields.Add(field);
                    }
                }

                documentSetTemplate.Update(true);
                web.Context.ExecuteQueryRetry();
            }

            web.Context.Load(createdCT);
            web.Context.ExecuteQueryRetry();

            return(createdCT);
        }
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                if (template.Lists.Any())
                {
                    var rootWeb = (web.Context as ClientContext).Site.RootWeb;

                    web.EnsureProperties(w => w.ServerRelativeUrl);

                    web.Context.Load(web.Lists, lc => lc.IncludeWithDefaultProperties(l => l.RootFolder.ServerRelativeUrl));
                    web.Context.ExecuteQueryRetry();
                    var existingLists = web.Lists.AsEnumerable().Select(existingList => existingList.RootFolder.ServerRelativeUrl).ToList();
                    var serverRelativeUrl = web.ServerRelativeUrl;

                    var processedLists = new List<ListInfo>();

                    #region Lists

                    foreach (var templateList in template.Lists)
                    {
                        // Check for the presence of the references content types and throw an exception if not present or in template
                        if (templateList.ContentTypesEnabled)
                        {
                            var existingCts = web.Context.LoadQuery(web.AvailableContentTypes);
                            web.Context.ExecuteQueryRetry();
                            foreach (var ct in templateList.ContentTypeBindings)
                            {
                                var found = template.ContentTypes.Any(t => t.Id.ToUpperInvariant() == ct.ContentTypeId.ToUpperInvariant());
                                if (found == false)
                                {
                                    found = existingCts.Any(t => t.StringId.ToUpperInvariant() == ct.ContentTypeId.ToUpperInvariant());
                                }
                                if (!found)
                                {
                                    scope.LogError("Referenced content type {0} not available in site or in template", ct.ContentTypeId);
                                    throw new Exception(string.Format("Referenced content type {0} not available in site or in template", ct.ContentTypeId));
                                }
                            }
                        }
                        var index = existingLists.FindIndex(x => x.Equals(UrlUtility.Combine(serverRelativeUrl, templateList.Url), StringComparison.OrdinalIgnoreCase));
                        if (index == -1)
                        {
                            try
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_list__0_, templateList.Title);
                                var returnTuple = CreateList(web, templateList, parser, scope);
                                var createdList = returnTuple.Item1;
                                parser = returnTuple.Item2;
                                processedLists.Add(new ListInfo { SiteList = createdList, TemplateList = templateList });

                                parser.AddToken(new ListIdToken(web, templateList.Title, createdList.Id));

                                parser.AddToken(new ListUrlToken(web, templateList.Title, createdList.RootFolder.ServerRelativeUrl.Substring(web.ServerRelativeUrl.Length + 1)));
                            }
                            catch (Exception ex)
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_list__0__failed___1_____2_, templateList.Title, ex.Message, ex.StackTrace);
                                throw;
                            }
                        }
                        else
                        {
                            try
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_list__0_, templateList.Title);
                                var existingList = web.Lists[index];
                                var returnTuple = UpdateList(web, existingList, templateList, parser, scope);
                                var updatedList = returnTuple.Item1;
                                parser = returnTuple.Item2;
                                if (updatedList != null)
                                {
                                    processedLists.Add(new ListInfo { SiteList = updatedList, TemplateList = templateList });
                                }
                            }
                            catch (Exception ex)
                            {
                                scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_list__0__failed___1_____2_, templateList.Title, ex.Message, ex.StackTrace);
                                throw;
                            }
                        }
                    }

                    #endregion

                    #region FieldRefs

                    foreach (var listInfo in processedLists)
                    {

                        if (listInfo.TemplateList.FieldRefs.Any())
                        {

                            foreach (var fieldRef in listInfo.TemplateList.FieldRefs)
                            {
                                var field = rootWeb.GetFieldById<Field>(fieldRef.Id);
                                if (field != null)
                                {
                                    if (!listInfo.SiteList.FieldExistsById(fieldRef.Id))
                                    {
                                        CreateFieldRef(listInfo, field, fieldRef);
                                    }
                                    else
                                    {
                                        UpdateFieldRef(listInfo.SiteList, field.Id, fieldRef);
                                    }
                                }

                            }
                            listInfo.SiteList.Update();
                            web.Context.ExecuteQueryRetry();
                        }
                    }

                    #endregion

                    #region Fields

                    foreach (var listInfo in processedLists)
                    {
                        if (listInfo.TemplateList.Fields.Any())
                        {
                            foreach (var field in listInfo.TemplateList.Fields)
                            {
                                var fieldElement = XElement.Parse(parser.ParseString(field.SchemaXml, "~sitecollection", "~site"));
                                if (fieldElement.Attribute("ID") == null)
                                {
                                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field_schema_has_no_ID_attribute___0_, field.SchemaXml);
                                    throw new Exception(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field_schema_has_no_ID_attribute___0_, field.SchemaXml));
                                }
                                var id = fieldElement.Attribute("ID").Value;

                                Guid fieldGuid;
                                if (!Guid.TryParse(id, out fieldGuid))
                                {
                                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_ID_for_field_is_not_a_valid_Guid___0_, field.SchemaXml);
                                    throw new Exception(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_ID_for_field_is_not_a_valid_Guid___0_, id));
                                }
                                else
                                {
                                    var fieldFromList = listInfo.SiteList.GetFieldById<Field>(fieldGuid);
                                    if (fieldFromList == null)
                                    {
                                        try
                                        {
                                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_field__0_, fieldGuid);
                                            CreateField(fieldElement, listInfo, parser);
                                        }
                                        catch (Exception ex)
                                        {
                                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_field__0__failed___1_____2_, fieldGuid, ex.Message, ex.StackTrace);
                                            throw;
                                        }
                                    }
                                    else
                                    {
                                        try
                                        {
                                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_field__0_, fieldGuid);
                                            UpdateField(web, listInfo, fieldGuid, fieldElement, fieldFromList, scope, parser);
                                        }
                                        catch (Exception ex)
                                        {
                                            scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Updating_field__0__failed___1_____2_, fieldGuid, ex.Message, ex.StackTrace);
                                            throw;
                                        }

                                    }
                                }
                            }
                        }
                        listInfo.SiteList.Update();
                        web.Context.ExecuteQueryRetry();
                    }

                    #endregion

                    #region Default Field Values
                    foreach (var listInfo in processedLists)
                    {
                        if (listInfo.TemplateList.FieldDefaults.Any())
                        {
                            foreach (var fieldDefault in listInfo.TemplateList.FieldDefaults)
                            {
                                var field = listInfo.SiteList.Fields.GetByInternalNameOrTitle(fieldDefault.Key);
                                field.DefaultValue = fieldDefault.Value;
                                field.Update();
                                web.Context.ExecuteQueryRetry();
                            }
                        }
                    }
                    #endregion

                    #region Views

                    foreach (var listInfo in processedLists)
                    {
                        var list = listInfo.TemplateList;
                        var createdList = listInfo.SiteList;

                        if (list.Views.Any() && list.RemoveExistingViews)
                        {
                            while (createdList.Views.Any())
                            {
                                createdList.Views[0].DeleteObject();
                            }
                            web.Context.ExecuteQueryRetry();
                        }

                        var existingViews = createdList.Views;
                        web.Context.Load(existingViews, vs => vs.Include(v => v.Title, v => v.Id));
                        web.Context.ExecuteQueryRetry();
                        foreach (var view in list.Views)
                        {

                            CreateView(web, view, existingViews, createdList, scope);

                        }

                        //// Removing existing views set the OnQuickLaunch option to false and need to be re-set.
                        //if (list.OnQuickLaunch && list.RemoveExistingViews && list.Views.Count > 0)
                        //{
                        //    createdList.RefreshLoad();
                        //    web.Context.ExecuteQueryRetry();
                        //    createdList.OnQuickLaunch = list.OnQuickLaunch;
                        //    createdList.Update();
                        //    web.Context.ExecuteQueryRetry();
                        //}
                    }

                    #endregion

                    // If an existing view is updated, and the list is to be listed on the QuickLaunch, it is removed because the existing view will be deleted and recreated from scratch.
                    foreach (var listInfo in processedLists)
                    {
                        listInfo.SiteList.OnQuickLaunch = listInfo.TemplateList.OnQuickLaunch;
                        listInfo.SiteList.Update();
                    }
                    web.Context.ExecuteQueryRetry();

                }
            }
            return parser;
        }
        private static void UpdateContentType(Web web, Microsoft.SharePoint.Client.ContentType existingContentType, ContentType templateContentType, TokenParser parser, PnPMonitoredScope scope)
        {
            var isDirty = false;

            if (existingContentType.Hidden != templateContentType.Hidden)
            {
                scope.LogPropertyUpdate("Hidden");
                existingContentType.Hidden = templateContentType.Hidden;
                isDirty = true;
            }
            if (existingContentType.ReadOnly != templateContentType.ReadOnly)
            {
                scope.LogPropertyUpdate("ReadOnly");
                existingContentType.ReadOnly = templateContentType.ReadOnly;
                isDirty = true;
            }
            if (existingContentType.Sealed != templateContentType.Sealed)
            {
                scope.LogPropertyUpdate("Sealed");
                existingContentType.Sealed = templateContentType.Sealed;
                isDirty = true;
            }
            if (templateContentType.Description != null && existingContentType.Description != parser.ParseString(templateContentType.Description))
            {
                scope.LogPropertyUpdate("Description");
                existingContentType.Description = parser.ParseString(templateContentType.Description);
                isDirty = true;
            }
            if (templateContentType.DocumentTemplate != null && existingContentType.DocumentTemplate != parser.ParseString(templateContentType.DocumentTemplate))
            {
                scope.LogPropertyUpdate("DocumentTemplate");
                existingContentType.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate);
                isDirty = true;
            }
            if (existingContentType.Name != parser.ParseString(templateContentType.Name))
            {
                scope.LogPropertyUpdate("Name");
                existingContentType.Name = parser.ParseString(templateContentType.Name);
                isDirty = true;
                // CT is being renamed, add an extra token to the tokenparser
                parser.AddToken(new ContentTypeIdToken(web, existingContentType.Name, existingContentType.StringId));
            }
            if (templateContentType.Group != null && existingContentType.Group != parser.ParseString(templateContentType.Group))
            {
                scope.LogPropertyUpdate("Group");
                existingContentType.Group = parser.ParseString(templateContentType.Group);
                isDirty = true;
            }
            if (templateContentType.DisplayFormUrl != null && existingContentType.DisplayFormUrl != parser.ParseString(templateContentType.DisplayFormUrl))
            {
                scope.LogPropertyUpdate("DisplayFormUrl");
                existingContentType.DisplayFormUrl = parser.ParseString(templateContentType.DisplayFormUrl);
                isDirty = true;
            }
            if (templateContentType.EditFormUrl != null && existingContentType.EditFormUrl != parser.ParseString(templateContentType.EditFormUrl))
            {
                scope.LogPropertyUpdate("EditFormUrl");
                existingContentType.EditFormUrl = parser.ParseString(templateContentType.EditFormUrl);
                isDirty = true;
            }
            if (templateContentType.NewFormUrl != null && existingContentType.NewFormUrl != parser.ParseString(templateContentType.NewFormUrl))
            {
                scope.LogPropertyUpdate("NewFormUrl");
                existingContentType.NewFormUrl = parser.ParseString(templateContentType.NewFormUrl);
                isDirty = true;
            }
#if !CLIENTSDKV15
            if (templateContentType.Name.ContainsResourceToken())
            {
                existingContentType.NameResource.SetUserResourceValue(templateContentType.Name, parser);
                isDirty = true;
            }
            if (templateContentType.Description.ContainsResourceToken())
            {
                existingContentType.DescriptionResource.SetUserResourceValue(templateContentType.Description, parser);
                isDirty = true;
            }
#endif
            if (isDirty)
            {
                existingContentType.Update(true);
                web.Context.ExecuteQueryRetry();
            }
            // Delta handling
            existingContentType.EnsureProperty(c => c.FieldLinks);
            List <Guid> targetIds = existingContentType.FieldLinks.AsEnumerable().Select(c1 => c1.Id).ToList();
            List <Guid> sourceIds = templateContentType.FieldRefs.Select(c1 => c1.Id).ToList();

            var fieldsNotPresentInTarget = sourceIds.Except(targetIds).ToArray();

            if (fieldsNotPresentInTarget.Any())
            {
                foreach (var fieldId in fieldsNotPresentInTarget)
                {
                    var fieldRef = templateContentType.FieldRefs.Find(fr => fr.Id == fieldId);
                    var field    = web.Fields.GetById(fieldId);
                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ContentTypes_Adding_field__0__to_content_type, fieldId);
                    web.AddFieldToContentType(existingContentType, field, fieldRef.Required, fieldRef.Hidden);
                }
            }

            isDirty = false;
            foreach (var fieldId in targetIds.Intersect(sourceIds))
            {
                var fieldLink = existingContentType.FieldLinks.FirstOrDefault(fl => fl.Id == fieldId);
                var fieldRef  = templateContentType.FieldRefs.Find(fr => fr.Id == fieldId);
                if (fieldRef != null)
                {
                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ContentTypes_Field__0__exists_in_content_type, fieldId);
                    if (fieldLink.Required != fieldRef.Required)
                    {
                        scope.LogPropertyUpdate("Required");
                        fieldLink.Required = fieldRef.Required;
                        isDirty            = true;
                    }
                    if (fieldLink.Hidden != fieldRef.Hidden)
                    {
                        scope.LogPropertyUpdate("Hidden");
                        fieldLink.Hidden = fieldRef.Hidden;
                        isDirty          = true;
                    }
                }
            }

            // The new CT is a DocumentSet, and the target should be, as well
            if (templateContentType.DocumentSetTemplate != null)
            {
                if (!Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.IsChildOfDocumentSetContentType(web.Context, existingContentType).Value)
                {
                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_ContentTypes_InvalidDocumentSet_Update_Request, existingContentType.Id, existingContentType.Name);
                }
                else
                {
                    Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate templateToUpdate =
                        Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.GetDocumentSetTemplate(web.Context, existingContentType);

                    // TODO: Implement Delta Handling
                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_DocumentSet_DeltaHandling_OnHold, existingContentType.Id, existingContentType.Name);
                }
            }

            if (isDirty)
            {
                existingContentType.Update(true);
                web.Context.ExecuteQueryRetry();
            }
        }
        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);
            web.Context.ExecuteQueryRetry();

            if (!String.IsNullOrEmpty(list.DocumentTemplate))
            {
                createdList.DocumentTemplateUrl = parser.ParseString(list.DocumentTemplate);
            }

            // 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.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
            var contentTypesToRemove = new List<ContentType>();
            if (list.RemoveExistingContentTypes && list.ContentTypeBindings.Count > 0)
            {
                contentTypesToRemove.AddRange(createdList.ContentTypes);
            }

            ContentTypeBinding defaultCtBinding = null;
            foreach (var ctBinding in list.ContentTypeBindings)
            {
                var tempCT = web.GetContentTypeById(ctBinding.ContentTypeId, searchInSiteHierarchy: true);
                if (tempCT != null)
                {
                    // Check if CT is already available
                    var name = tempCT.EnsureProperty(ct => ct.Name);
                    if (!createdList.ContentTypeExistsByName(name))
                    {
                        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();
            }

            if (list.Security != null)
            {
                createdList.SetSecurity(parser, list.Security);
            }
            return Tuple.Create(createdList, parser);
        }
示例#40
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;
        }
        private static void AddWebPartsToPublishingPage(PublishingPage page, ClientContext ctx, Microsoft.SharePoint.Client.WebParts.LimitedWebPartManager mgr, TokenParser parser)
        {
            foreach (var wp in page.WebParts)
            {
                string wpContentsTokenResolved = parser.ParseString(wp.Contents).Replace("<property name=\"JSLink\" type=\"string\">" + ctx.Site.ServerRelativeUrl,"<property name=\"JSLink\" type=\"string\">~sitecollection");
                Microsoft.SharePoint.Client.WebParts.WebPart webPart = mgr.ImportWebPart(wpContentsTokenResolved).WebPart;
                Microsoft.SharePoint.Client.WebParts.WebPartDefinition definition = mgr.AddWebPart(
                                                                                            webPart,
                                                                                            wp.Zone,
                                                                                            (int)wp.Order
                                                                                        );
                var webPartProperties = definition.WebPart.Properties;
                ctx.Load(definition.WebPart);
                ctx.Load(webPartProperties);
                ctx.ExecuteQuery();

                if (wp.IsListViewWebPart)
                {
                    AddListViewWebpart(ctx, wp, definition, webPartProperties, parser);
                }
            }
        }
示例#42
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(CoreResources.Provisioning_ObjectHandlers_Pages))
            {

                var context = web.Context as ClientContext;

                if (!web.IsPropertyAvailable("ServerRelativeUrl"))
                {
                    context.Load(web, w => w.ServerRelativeUrl);
                    context.ExecuteQueryRetry();
                }

                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);
                                file.DeleteObject();
                                web.Context.ExecuteQueryRetry();
                                web.AddWikiPageByUrl(url);
                                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)
                    {
                        if (!web.IsPropertyAvailable("RootFolder"))
                        {
                            web.Context.Load(web.RootFolder);
                            web.Context.ExecuteQueryRetry();
                        }

                        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);
                            }
                        }
                    }
                }
            }
            return parser;
        }
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {

                // if this is a sub site then we're not provisioning security as by default security is inherited from the root site
                if (web.IsSubSite())
                {
                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_SiteSecurity_Context_web_is_subweb__skipping_site_security_provisioning);
                    return parser;
                }

                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);
                }
                if (!memberGroup.ServerObjectIsNull.Value)
                {
                    AddUserToGroup(web, memberGroup, siteSecurity.AdditionalMembers, scope);
                }
                if (!visitorGroup.ServerObjectIsNull.Value)
                {
                    AddUserToGroup(web, visitorGroup, siteSecurity.AdditionalVisitors, scope);
                }

                foreach (var siteGroup in siteSecurity.SiteGroups)
                {
                    Group group = null;
                    var allGroups = web.Context.LoadQuery(web.SiteGroups.Include(gr => gr.LoginName));
                    web.Context.ExecuteQueryRetry();

                    if (!web.GroupExists(siteGroup.Title))
                    {
                        scope.LogDebug("Creating group {0}", siteGroup.Title);
                        group = web.AddGroup(
                            parser.ParseString(siteGroup.Title),
                            parser.ParseString(siteGroup.Description),
                            parser.ParseString(siteGroup.Title) == parser.ParseString(siteGroup.Owner));
                        group.AllowMembersEditMembership = siteGroup.AllowMembersEditMembership;
                        group.AllowRequestToJoinLeave = siteGroup.AllowRequestToJoinLeave;
                        group.AutoAcceptRequestToJoinLeave = siteGroup.AutoAcceptRequestToJoinLeave;

                        if (parser.ParseString(siteGroup.Title) != parser.ParseString(siteGroup.Owner))
                        {
                            Principal ownerPrincipal = allGroups.FirstOrDefault(gr => gr.LoginName == parser.ParseString(siteGroup.Owner));
                            if (ownerPrincipal == null)
                            {
                                ownerPrincipal = web.EnsureUser(parser.ParseString(siteGroup.Owner));
                            }
                            group.Owner = ownerPrincipal;

                        }
                        group.Update();
                        web.Context.ExecuteQueryRetry();
                    }
                    else
                    {
                        group = web.SiteGroups.GetByName(parser.ParseString(siteGroup.Title));
                        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 (group.Description != parser.ParseString(siteGroup.Description))
                        {
                            group.Description = parser.ParseString(siteGroup.Description);
                            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 != parser.ParseString(siteGroup.Owner))
                        {
                            if (parser.ParseString(siteGroup.Title) != parser.ParseString(siteGroup.Owner))
                            {
                                Principal ownerPrincipal = allGroups.FirstOrDefault(gr => gr.LoginName == parser.ParseString(siteGroup.Owner));
                                if (ownerPrincipal == null)
                                {
                                    ownerPrincipal = web.EnsureUser(parser.ParseString(siteGroup.Owner));
                                }
                                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);
                    }
                }

                foreach (var admin in siteSecurity.AdditionalAdministrators)
                {
                    var user = web.EnsureUser(admin.Name);
                    user.IsSiteAdmin = true;
                    user.Update();
                    web.Context.ExecuteQueryRetry();
                }

                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 siteRoleDefinition = existingRoleDefinitions.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 == roleAssignment.RoleDefinition);

                            if (roleDefinition != null)
                            {
                                roleDefinitionBindingCollection.Add(roleDefinition);
                            }
                            web.RoleAssignments.Add(principal, roleDefinitionBindingCollection);
                            web.Context.ExecuteQueryRetry();
                        }
                    }
                }
            }
            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<List>().Select(existingList => existingList.RootFolder.ServerRelativeUrl).ToList();
                    var serverRelativeUrl = web.ServerRelativeUrl;

                    #region DataRows

                    foreach (var listInstance in template.Lists)
                    {
                        if (listInstance.DataRows != null && listInstance.DataRows.Any())
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Processing_data_rows_for__0_, listInstance.Title);
                            // Retrieve the target list
                            var list = web.Lists.GetByTitle(listInstance.Title);
                            web.Context.Load(list);

                            // Retrieve the fields' types from the list
                            FieldCollection fields = list.Fields;
                            web.Context.Load(fields, fs => fs.Include(f => f.InternalName, f => f.FieldTypeKind));
                            web.Context.ExecuteQueryRetry();

                            foreach (var dataRow in listInstance.DataRows)
                            {
                                try
                                {
                                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_list_item__0_, listInstance.DataRows.IndexOf(dataRow) + 1);
                                    var listitemCI = new ListItemCreationInformation();
                                    var listitem = list.AddItem(listitemCI);

                                    foreach (var dataValue in dataRow.Values)
                                    {
                                        Field dataField = fields.FirstOrDefault(
                                            f => f.InternalName == parser.ParseString(dataValue.Key));

                                        if (dataField != null)
                                        {
                                            String fieldValue = parser.ParseString(dataValue.Value);

                                            switch (dataField.FieldTypeKind)
                                            {
                                                case FieldType.Geolocation:
                                                    // FieldGeolocationValue - Expected format: Altitude,Latitude,Longitude,Measure
                                                    var geolocationArray = fieldValue.Split(',');
                                                    if (geolocationArray.Length == 4)
                                                    {
                                                        var geolocationValue = new FieldGeolocationValue
                                                        {
                                                            Altitude = Double.Parse(geolocationArray[0]),
                                                            Latitude = Double.Parse(geolocationArray[1]),
                                                            Longitude = Double.Parse(geolocationArray[2]),
                                                            Measure = Double.Parse(geolocationArray[3]),
                                                        };
                                                        listitem[parser.ParseString(dataValue.Key)] = geolocationValue;
                                                    }
                                                    else
                                                    {
                                                        listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                    }
                                                    break;
                                                case FieldType.Lookup:
                                                    // FieldLookupValue - Expected format: LookupID
                                                    var lookupValue = new FieldLookupValue
                                                    {
                                                        LookupId = Int32.Parse(fieldValue),
                                                    };
                                                    listitem[parser.ParseString(dataValue.Key)] = lookupValue;
                                                    break;
                                                case FieldType.URL:
                                                    // FieldUrlValue - Expected format: URL,Description
                                                    var urlArray = fieldValue.Split(',');
                                                    var linkValue = new FieldUrlValue();
                                                    if (urlArray.Length == 2)
                                                    {
                                                        linkValue.Url = urlArray[0];
                                                        linkValue.Description = urlArray[1];
                                                    }
                                                    else
                                                    {
                                                        linkValue.Url = urlArray[0];
                                                        linkValue.Description = urlArray[0];
                                                    }
                                                    listitem[parser.ParseString(dataValue.Key)] = linkValue;
                                                    break;
                                                case FieldType.User:
                                                    // FieldUserValue - Expected format: loginName
                                                    var user = web.EnsureUser(fieldValue);
                                                    web.Context.Load(user);
                                                    web.Context.ExecuteQueryRetry();

                                                    if (user != null)
                                                    {
                                                        var userValue = new FieldUserValue
                                                        {
                                                            LookupId = user.Id,
                                                        };
                                                        listitem[parser.ParseString(dataValue.Key)] = userValue;
                                                    }
                                                    else
                                                    {
                                                        listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                    }
                                                    break;
                                                default:
                                                    listitem[parser.ParseString(dataValue.Key)] = fieldValue;
                                                    break;
                                            }
                                        }
                                        listitem.Update();
                                    }
                                    web.Context.ExecuteQueryRetry(); // TODO: Run in batches?

                                    if (dataRow.Security != null)
                                    {
                                        listitem.SetSecurity(parser, dataRow.Security);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    scope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstancesDataRows_Creating_listitem_failed___0_____1_, ex.Message, ex.StackTrace);
                                    throw;
                                }
                            }
                        }
                    }

                    #endregion
                }
            }

            return parser;
        }
示例#45
0
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                web.EnsureProperties(w => w.ServerRelativeUrl);

                // determine pages library
                string pagesLibrary = "SitePages";

                List <string> preCreatedPages = new List <string>();

                var currentPageIndex = 0;
                // pre create the needed pages so we can fill the needed tokens which might be used later on when we put web parts on those pages
                foreach (var clientSidePage in template.ClientSidePages)
                {
                    string pageName = $"{System.IO.Path.GetFileNameWithoutExtension(parser.ParseString(clientSidePage.PageName))}.aspx";
                    string url      = $"{pagesLibrary}/{pageName}";

                    // Write page level status messages, needed in case many pages are provisioned
                    currentPageIndex++;
                    WriteMessage($"ClientSidePage|Create {pageName}|{currentPageIndex}|{template.ClientSidePages.Count}", ProvisioningMessageType.Progress);

                    url = UrlUtility.Combine(web.ServerRelativeUrl, url);

                    var exists = true;
                    try
                    {
                        var file = web.GetFileByServerRelativePath(ResourcePath.FromDecodedUrl(url));
                        web.Context.Load(file, f => f.UniqueId, f => f.ServerRelativePath);
                        web.Context.ExecuteQueryRetry();

                        // Fill token
                        parser.AddToken(new PageUniqueIdToken(web, file.ServerRelativePath.DecodedUrl.Substring(web.ServerRelativeUrl.Length).TrimStart("/".ToCharArray()), file.UniqueId));
                        parser.AddToken(new PageUniqueIdEncodedToken(web, file.ServerRelativePath.DecodedUrl.Substring(web.ServerRelativeUrl.Length).TrimStart("/".ToCharArray()), file.UniqueId));
                    }
                    catch (ServerException ex)
                    {
                        if (ex.ServerErrorTypeName == "System.IO.FileNotFoundException")
                        {
                            exists = false;
                        }
                    }

                    if (!exists)
                    {
                        // Pre-create the page
                        Pages.ClientSidePage page = web.AddClientSidePage(pageName);

                        // Set page layout now, because once it's set, it can't be changed.
                        if (!string.IsNullOrEmpty(clientSidePage.Layout))
                        {
                            if (clientSidePage.Layout.Equals("Article", StringComparison.InvariantCultureIgnoreCase))
                            {
                                page.LayoutType = Pages.ClientSidePageLayoutType.Article;
                            }
                            else if (clientSidePage.Layout.Equals("Home", StringComparison.InvariantCultureIgnoreCase))
                            {
                                page.LayoutType = Pages.ClientSidePageLayoutType.Home;
                            }
                            else if (clientSidePage.Layout.Equals("SingleWebPartAppPage", StringComparison.InvariantCultureIgnoreCase))
                            {
                                page.LayoutType = Pages.ClientSidePageLayoutType.SingleWebPartAppPage;
                            }
                        }

                        page.Save(pageName);

                        var file = web.GetFileByServerRelativePath(ResourcePath.FromDecodedUrl(url));
                        web.Context.Load(file, f => f.UniqueId, f => f.ServerRelativePath);
                        web.Context.ExecuteQueryRetry();

                        // Fill token
                        parser.AddToken(new PageUniqueIdToken(web, file.ServerRelativePath.DecodedUrl.Substring(web.ServerRelativeUrl.Length).TrimStart("/".ToCharArray()), file.UniqueId));
                        parser.AddToken(new PageUniqueIdEncodedToken(web, file.ServerRelativePath.DecodedUrl.Substring(web.ServerRelativeUrl.Length).TrimStart("/".ToCharArray()), file.UniqueId));

                        // Track that we pre-added this page
                        preCreatedPages.Add(url);
                    }
                }

                currentPageIndex = 0;
                // Iterate over the pages and create/update them
                foreach (var clientSidePage in template.ClientSidePages)
                {
                    string pageName = $"{System.IO.Path.GetFileNameWithoutExtension(parser.ParseString(clientSidePage.PageName))}.aspx";
                    string url      = $"{pagesLibrary}/{pageName}";
                    // Write page level status messages, needed in case many pages are provisioned
                    currentPageIndex++;
                    WriteMessage($"ClientSidePage|{pageName}|{currentPageIndex}|{template.ClientSidePages.Count}", ProvisioningMessageType.Progress);

                    url = UrlUtility.Combine(web.ServerRelativeUrl, url);

                    var exists = true;
                    try
                    {
                        var file = web.GetFileByServerRelativePath(ResourcePath.FromDecodedUrl(url));
                        web.Context.Load(file);
                        web.Context.ExecuteQueryRetry();
                    }
                    catch (ServerException ex)
                    {
                        if (ex.ServerErrorTypeName == "System.IO.FileNotFoundException")
                        {
                            exists = false;
                        }
                    }

                    Pages.ClientSidePage page = null;
                    if (exists)
                    {
                        if (clientSidePage.Overwrite || preCreatedPages.Contains(url))
                        {
                            // Get the existing page
                            page = web.LoadClientSidePage(pageName);
                            // Clear the page
                            page.ClearPage();
                        }
                        else
                        {
                            scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ClientSidePages_NoOverWrite, pageName);
                            continue;
                        }
                    }
                    else
                    {
                        // Create new client side page
                        page = web.AddClientSidePage(pageName);
                    }

                    // Set page title
                    string newTitle = parser.ParseString(clientSidePage.Title);
                    if (page.PageTitle != newTitle)
                    {
                        page.PageTitle = newTitle;
                    }

                    // Page Header
                    if (clientSidePage.Header != null)
                    {
                        switch (clientSidePage.Header.Type)
                        {
                        case ClientSidePageHeaderType.None:
                        {
                            page.RemovePageHeader();
                            break;
                        }

                        case ClientSidePageHeaderType.Default:
                        {
                            page.SetDefaultPageHeader();
                            break;
                        }

                        case ClientSidePageHeaderType.Custom:
                        {
                            var serverRelativeImageUrl = parser.ParseString(clientSidePage.Header.ServerRelativeImageUrl);
                            if (clientSidePage.Header.TranslateX.HasValue && clientSidePage.Header.TranslateY.HasValue)
                            {
                                page.SetCustomPageHeader(serverRelativeImageUrl, clientSidePage.Header.TranslateX.Value, clientSidePage.Header.TranslateY.Value);
                            }
                            else
                            {
                                page.SetCustomPageHeader(serverRelativeImageUrl);
                            }
                            break;
                        }
                        }
                    }

                    // Set page layout
                    if (!string.IsNullOrEmpty(clientSidePage.Layout))
                    {
                        if (clientSidePage.Layout.Equals("Article", StringComparison.InvariantCultureIgnoreCase))
                        {
                            page.LayoutType = Pages.ClientSidePageLayoutType.Article;
                        }
                        else if (clientSidePage.Layout.Equals("Home", StringComparison.InvariantCultureIgnoreCase))
                        {
                            page.LayoutType = Pages.ClientSidePageLayoutType.Home;
                        }
                        else if (clientSidePage.Layout.Equals("SingleWebPartAppPage", StringComparison.InvariantCultureIgnoreCase))
                        {
                            page.LayoutType = Pages.ClientSidePageLayoutType.SingleWebPartAppPage;
                        }
                    }

                    // Load existing available controls
                    var componentsToAdd = page.AvailableClientSideComponents().ToList();

                    // if no section specified then add a default single column section
                    if (!clientSidePage.Sections.Any())
                    {
                        clientSidePage.Sections.Add(new CanvasSection()
                        {
                            Type = CanvasSectionType.OneColumn, Order = 10
                        });
                    }

                    int sectionCount = -1;
                    // Apply the "layout" and content
                    foreach (var section in clientSidePage.Sections)
                    {
                        sectionCount++;
                        switch (section.Type)
                        {
                        case CanvasSectionType.OneColumn:
                            page.AddSection(Pages.CanvasSectionTemplate.OneColumn, section.Order);
                            break;

                        case CanvasSectionType.OneColumnFullWidth:
                            page.AddSection(Pages.CanvasSectionTemplate.OneColumnFullWidth, section.Order);
                            break;

                        case CanvasSectionType.TwoColumn:
                            page.AddSection(Pages.CanvasSectionTemplate.TwoColumn, section.Order);
                            break;

                        case CanvasSectionType.ThreeColumn:
                            page.AddSection(Pages.CanvasSectionTemplate.ThreeColumn, section.Order);
                            break;

                        case CanvasSectionType.TwoColumnLeft:
                            page.AddSection(Pages.CanvasSectionTemplate.TwoColumnLeft, section.Order);
                            break;

                        case CanvasSectionType.TwoColumnRight:
                            page.AddSection(Pages.CanvasSectionTemplate.TwoColumnRight, section.Order);
                            break;

                        default:
                            page.AddSection(Pages.CanvasSectionTemplate.OneColumn, section.Order);
                            break;
                        }

                        // Add controls to the section
                        if (section.Controls.Any())
                        {
                            // Safety measure: reset column order to 1 for columns marked with 0 or lower
                            foreach (var control in section.Controls.Where(p => p.Column <= 0).ToList())
                            {
                                control.Column = 1;
                            }

                            foreach (CanvasControl control in section.Controls)
                            {
                                Pages.ClientSideComponent baseControl = null;

                                // Is it a text control?
                                if (control.Type == WebPartType.Text)
                                {
                                    Pages.ClientSideText textControl = new Pages.ClientSideText();
                                    if (control.ControlProperties.Any())
                                    {
                                        var textProperty = control.ControlProperties.First();
                                        textControl.Text = parser.ParseString(textProperty.Value);
                                    }
                                    else
                                    {
                                        if (!string.IsNullOrEmpty(control.JsonControlData))
                                        {
                                            var json = JsonConvert.DeserializeObject <Dictionary <string, string> >(control.JsonControlData);

                                            if (json.Count > 0)
                                            {
                                                textControl.Text = parser.ParseString(json.First().Value);
                                            }
                                        }
                                    }
                                    // Reduce column number by 1 due 0 start indexing
                                    page.AddControl(textControl, page.Sections[sectionCount].Columns[control.Column - 1], control.Order);
                                }
                                // It is a web part
                                else
                                {
                                    // apply token parsing on the web part properties
                                    control.JsonControlData = parser.ParseString(control.JsonControlData);

                                    // perform processing of web part properties (e.g. include listid property based list title property)
                                    var webPartPostProcessor = CanvasControlPostProcessorFactory.Resolve(control);
                                    webPartPostProcessor.Process(control, page);

                                    // Is a custom developed client side web part (3rd party)
                                    if (control.Type == WebPartType.Custom)
                                    {
                                        if (!string.IsNullOrEmpty(control.CustomWebPartName))
                                        {
                                            baseControl = componentsToAdd.FirstOrDefault(p => p.Name.Equals(control.CustomWebPartName, StringComparison.InvariantCultureIgnoreCase));
                                        }
                                        else if (control.ControlId != Guid.Empty)
                                        {
                                            baseControl = componentsToAdd.FirstOrDefault(p => p.Id.Equals($"{{{control.ControlId.ToString()}}}", StringComparison.CurrentCultureIgnoreCase));

                                            if (baseControl == null)
                                            {
                                                baseControl = componentsToAdd.FirstOrDefault(p => p.Id.Equals(control.ControlId.ToString(), StringComparison.InvariantCultureIgnoreCase));
                                            }
                                        }
                                    }
                                    // Is an OOB client side web part (1st party)
                                    else
                                    {
                                        string webPartName = "";
                                        switch (control.Type)
                                        {
                                        case WebPartType.Image:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.Image);
                                            break;

                                        case WebPartType.BingMap:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.BingMap);
                                            break;

                                        case WebPartType.ContentEmbed:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.ContentEmbed);
                                            break;

                                        case WebPartType.ContentRollup:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.ContentRollup);
                                            break;

                                        case WebPartType.DocumentEmbed:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.DocumentEmbed);
                                            break;

                                        case WebPartType.Events:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.Events);
                                            break;

                                        case WebPartType.GroupCalendar:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.GroupCalendar);
                                            break;

                                        case WebPartType.Hero:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.Hero);
                                            break;

                                        case WebPartType.ImageGallery:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.ImageGallery);
                                            break;

                                        case WebPartType.LinkPreview:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.LinkPreview);
                                            break;

                                        case WebPartType.List:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.List);
                                            break;

                                        case WebPartType.NewsFeed:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.NewsFeed);
                                            break;

                                        case WebPartType.NewsReel:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.NewsReel);
                                            break;

                                        case WebPartType.PageTitle:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.PageTitle);
                                            break;

                                        case WebPartType.People:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.People);
                                            break;

                                        case WebPartType.PowerBIReportEmbed:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.PowerBIReportEmbed);
                                            break;

                                        case WebPartType.QuickChart:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.QuickChart);
                                            break;

                                        case WebPartType.QuickLinks:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.QuickLinks);
                                            break;

                                        case WebPartType.SiteActivity:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.SiteActivity);
                                            break;

                                        case WebPartType.VideoEmbed:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.VideoEmbed);
                                            break;

                                        case WebPartType.YammerEmbed:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.YammerEmbed);
                                            break;

                                        case WebPartType.CustomMessageRegion:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.CustomMessageRegion);
                                            break;

                                        case WebPartType.Divider:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.Divider);
                                            break;

                                        case WebPartType.MicrosoftForms:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.MicrosoftForms);
                                            break;

                                        case WebPartType.Spacer:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.Spacer);
                                            break;

                                        case WebPartType.ClientWebPart:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.ClientWebPart);
                                            break;
                                        }

                                        baseControl = componentsToAdd.FirstOrDefault(p => p.Name.Equals(webPartName, StringComparison.InvariantCultureIgnoreCase));
                                    }

                                    if (baseControl != null)
                                    {
                                        Pages.ClientSideWebPart myWebPart = new Pages.ClientSideWebPart(baseControl)
                                        {
                                            Order = control.Order
                                        };

                                        // Reduce column number by 1 due 0 start indexing
                                        page.AddControl(myWebPart, page.Sections[sectionCount].Columns[control.Column - 1], control.Order);

                                        // set properties using json string
                                        if (!String.IsNullOrEmpty(control.JsonControlData))
                                        {
                                            myWebPart.PropertiesJson = control.JsonControlData;
                                        }

                                        // set using property collection
                                        if (control.ControlProperties.Any())
                                        {
                                            // grab the "default" properties so we can deduct their types, needed to correctly apply the set properties
                                            var    controlManifest   = JObject.Parse(baseControl.Manifest);
                                            JToken controlProperties = null;
                                            if (controlManifest != null)
                                            {
                                                controlProperties = controlManifest.SelectToken("preconfiguredEntries[0].properties");
                                            }

                                            foreach (var property in control.ControlProperties)
                                            {
                                                Type propertyType = typeof(string);

                                                if (controlProperties != null)
                                                {
                                                    var defaultProperty = controlProperties.SelectToken(property.Key, false);
                                                    if (defaultProperty != null)
                                                    {
                                                        propertyType = Type.GetType($"System.{defaultProperty.Type.ToString()}");

                                                        if (propertyType == null)
                                                        {
                                                            if (defaultProperty.Type.ToString().Equals("integer", StringComparison.InvariantCultureIgnoreCase))
                                                            {
                                                                propertyType = typeof(int);
                                                            }
                                                        }
                                                    }
                                                }

                                                myWebPart.Properties[property.Key] = JToken.FromObject(Convert.ChangeType(parser.ParseString(property.Value), propertyType));
                                            }
                                        }
                                    }
                                    else
                                    {
                                        scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ClientSidePages_BaseControlNotFound, control.ControlId, control.CustomWebPartName);
                                    }
                                }
                            }
                        }
                    }

                    // Persist the page
                    page.Save(pageName);

                    if (page.LayoutType != Pages.ClientSidePageLayoutType.SingleWebPartAppPage)
                    {
                        // Set commenting, ignore on pages of the type Home
                        if (page.LayoutType != Pages.ClientSidePageLayoutType.Home)
                        {
                            // Make it a news page if requested
                            if (clientSidePage.PromoteAsNewsArticle)
                            {
                                page.PromoteAsNewsArticle();
                            }
                        }

                        if (clientSidePage.EnableComments)
                        {
                            page.EnableComments();
                        }
                        else
                        {
                            page.DisableComments();
                        }
                    }

                    // Publish page
                    if (clientSidePage.Publish)
                    {
                        page.Publish();
                    }

                    // Set any security on the page
                    if (clientSidePage.Security != null && clientSidePage.Security.RoleAssignments.Count != 0)
                    {
                        web.Context.Load(page.PageListItem);
                        web.Context.ExecuteQueryRetry();
                        page.PageListItem.SetSecurity(parser, clientSidePage.Security);
                    }
                }
            }

            WriteMessage("Done processing Client Side Pages", ProvisioningMessageType.Completed);
            return(parser);
        }
        private Tuple <Guid, TokenParser> CreateTerm <T>(Web web, Model.Term modelTerm, TaxonomyItem parent,
                                                         TermStore termStore, TokenParser parser, PnPMonitoredScope scope) where T : TaxonomyItem
        {
            // If the term is a re-used term and the term is not a source term, skip for now and create later
            if (modelTerm.IsReused && !modelTerm.IsSourceTerm)
            {
                this.reusedTerms.Add(new ReusedTerm()
                {
                    ModelTerm = modelTerm,
                    Parent    = parent,
                    TermStore = termStore
                });
                return(null);
            }

            // Create new term
            Term term;

            if (modelTerm.Id == Guid.Empty)
            {
                modelTerm.Id = Guid.NewGuid();
            }

            if (parent is Term)
            {
                term = ((Term)parent).CreateTerm(parser.ParseString(modelTerm.Name), modelTerm.Language ?? termStore.DefaultLanguage, modelTerm.Id);
            }
            else
            {
                term = ((TermSet)parent).CreateTerm(parser.ParseString(modelTerm.Name), modelTerm.Language ?? termStore.DefaultLanguage, modelTerm.Id);
            }
            if (!string.IsNullOrEmpty(modelTerm.Description))
            {
                term.SetDescription(parser.ParseString(modelTerm.Description), modelTerm.Language ?? termStore.DefaultLanguage);
            }
            if (!string.IsNullOrEmpty(modelTerm.Owner))
            {
                term.Owner = modelTerm.Owner;
            }

            term.IsAvailableForTagging = modelTerm.IsAvailableForTagging;

            if (modelTerm.Properties.Any() || modelTerm.Labels.Any() || modelTerm.LocalProperties.Any())
            {
                if (modelTerm.Labels.Any())
                {
                    CreateTermLabels(modelTerm, termStore, parser, scope, term);
                    //foreach (var label in modelTerm.Labels)
                    //{
                    //    if ((label.IsDefaultForLanguage && label.Language != termStore.DefaultLanguage) || label.IsDefaultForLanguage == false)
                    //    {
                    //        term.CreateLabel(parser.ParseString(label.Value), label.Language, label.IsDefaultForLanguage);
                    //    }
                    //    else
                    //    {
                    //        scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_TermGroups_Skipping_label__0___label_is_to_set_to_default_for_language__1__while_the_default_termstore_language_is_also__1_, label.Value, label.Language);
                    //        WriteWarning(string.Format(CoreResources.Provisioning_ObjectHandlers_TermGroups_Skipping_label__0___label_is_to_set_to_default_for_language__1__while_the_default_termstore_language_is_also__1_, label.Value, label.Language), ProvisioningMessageType.Warning);
                    //    }
                    //}
                }

                if (modelTerm.Properties.Any())
                {
                    SetTermCustomProperties(modelTerm, parser, term);
                    //foreach (var property in modelTerm.Properties)
                    //{
                    //    term.SetCustomProperty(parser.ParseString(property.Key), parser.ParseString(property.Value));
                    //}
                }
                if (modelTerm.LocalProperties.Any())
                {
                    SetTermLocalCustomProperties(modelTerm, parser, term);
                    //foreach (var property in modelTerm.LocalProperties)
                    //{
                    //    term.SetLocalCustomProperty(parser.ParseString(property.Key), parser.ParseString(property.Value));
                    //}
                }
            }

            termStore.CommitAll();

            web.Context.Load(term);
            web.Context.ExecuteQueryRetry();

            // Deprecate term if needed
            if (modelTerm.IsDeprecated != term.IsDeprecated)
            {
                term.Deprecate(modelTerm.IsDeprecated);
                web.Context.ExecuteQueryRetry();
            }


            parser = this.CreateChildTerms(web, modelTerm, term, termStore, parser, scope);
            return(Tuple.Create(modelTerm.Id, parser));
        }
示例#47
0
        public void TokenProviderCanBeDisabled()
        {
            using (var ctx = TestCommon.CreateClientContext())
            {
                var _mockProvider = new Provider
                {
                    Assembly = "OfficeDevPnP.Core.Tests",
                    Type = "OfficeDevPnP.Core.Tests.Framework.ExtensibilityCallOut.ExtensibilityMockTokenProvider",
                    Configuration = ExtensibilityTestConstants.PROVIDER_MOCK_DATA,
                    Enabled = false
                };               

                var _mockTemplate = new ProvisioningTemplate();
                _mockTemplate.Id = ExtensibilityTestConstants.PROVISIONINGTEMPLATE_ID;
                _mockTemplate.Providers.Add(_mockProvider);

                var extensibilityHandler = new ObjectExtensibilityProviders();
                var parser = new TokenParser(ctx.Web, _mockTemplate);
                extensibilityHandler.AddExtendedTokens(ctx.Web, _mockTemplate, parser, null);

                var parsedValue = parser.ParseString(MockToken.MockTokenKey);
                Assert.AreEqual(MockToken.MockTokenKey, parsedValue, "Disabled tokenprovider should not have provided tokens!");
            }
        }
        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 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 = !String.IsNullOrEmpty(file.TargetFileName) ? file.TargetFileName : file.Src;

                    currentFileIndex++;
                    WriteMessage($"File|{targetFileName}|{currentFileIndex}|{filesToProcess.Length}", ProvisioningMessageType.Progress);
                    var folderName = parser.ParseString(file.Folder);

                    if (folderName.ToLower().Contains("/_catalogs/"))
                    {
                        // Edge case where you have files in the template which should be provisioned to the site collection
                        // master page gallery and not to a connected subsite
                        web = web.Context.GetSiteCollectionContext().Web;
                        web.EnsureProperties(w => w.ServerRelativeUrl, w => w.Url);
                    }

                    if (folderName.ToLower().StartsWith((web.ServerRelativeUrl.ToLower())))
                    {
                        folderName = folderName.Substring(web.ServerRelativeUrl.Length);
                    }

                    if (SkipFile(isNoScriptSite, targetFileName, folderName))
                    {
                        // add log message
                        scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_Files_SkipFileUpload, targetFileName, folderName);
                        continue;
                    }

                    var folder = web.EnsureFolderPath(folderName);

                    var checkedOut = false;

                    var targetFile = folder.GetFile(template.Connector.GetFilenamePart(targetFileName));

                    if (targetFile != null)
                    {
                        if (file.Overwrite)
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Files_Uploading_and_overwriting_existing_file__0_, targetFileName);
                            checkedOut = CheckOutIfNeeded(web, targetFile);

                            using (var stream = GetFileStream(template, file))
                            {
                                targetFile = UploadFile(template, file, folder, stream);
                            }
                        }
                        else
                        {
                            checkedOut = CheckOutIfNeeded(web, targetFile);
                        }
                    }
                    else
                    {
                        using (var stream = GetFileStream(template, file))
                        {
                            scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Files_Uploading_file__0_, targetFileName);
                            targetFile = UploadFile(template, file, folder, stream);
                        }

                        checkedOut = CheckOutIfNeeded(web, targetFile);
                    }

                    if (targetFile != null)
                    {
                        // 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 (file.Properties != null && file.Properties.Any())
                        {
                            Dictionary <string, string> transformedProperties = file.Properties.ToDictionary(property => property.Key, property => parser.ParseString(property.Value));
                            SetFileProperties(targetFile, transformedProperties, false);
                        }

#if !SP2013
                        bool webPartsNeedLocalization = false;
#endif
                        if (file.WebParts != null && file.WebParts.Any())
                        {
                            targetFile.EnsureProperties(f => f.ServerRelativeUrl);

                            var existingWebParts = web.GetWebParts(targetFile.ServerRelativeUrl).ToList();
                            foreach (var webPart in file.WebParts)
                            {
                                // check if the webpart is already set on the page
                                if (existingWebParts.FirstOrDefault(w => w.WebPart.Title == parser.ParseString(webPart.Title)) == null)
                                {
                                    scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_Files_Adding_webpart___0___to_page, webPart.Title);
                                    var wpEntity = new WebPartEntity();
                                    wpEntity.WebPartTitle = parser.ParseString(webPart.Title);
                                    wpEntity.WebPartXml   = parser.ParseXmlString(webPart.Contents).Trim(new[] { '\n', ' ' });
                                    wpEntity.WebPartZone  = webPart.Zone;
                                    wpEntity.WebPartIndex = (int)webPart.Order;
                                    var wpd = web.AddWebPartToWebPartPage(targetFile.ServerRelativeUrl, wpEntity);
#if !SP2013
                                    if (webPart.Title.ContainsResourceToken())
                                    {
                                        // update data based on where it was added - needed in order to localize wp title
#if !SP2016
                                        wpd.EnsureProperties(w => w.ZoneId, w => w.WebPart, w => w.WebPart.Properties);
                                        webPart.Zone = wpd.ZoneId;
#else
                                        wpd.EnsureProperties(w => w.WebPart, w => w.WebPart.Properties);
#endif
                                        webPart.Order            = (uint)wpd.WebPart.ZoneIndex;
                                        webPartsNeedLocalization = true;
                                    }
#endif
                                }
                            }
                        }

#if !SP2013
                        if (webPartsNeedLocalization)
                        {
                            file.LocalizeWebParts(web, parser, targetFile, scope);
                        }
#endif

                        switch (file.Level)
                        {
                        case Model.FileLevel.Published:
                        {
                            targetFile.PublishFileToLevel(Microsoft.SharePoint.Client.FileLevel.Published);
                            break;
                        }

                        case Model.FileLevel.Draft:
                        {
                            targetFile.PublishFileToLevel(Microsoft.SharePoint.Client.FileLevel.Draft);
                            break;
                        }

                        default:
                        {
                            if (checkedOut)
                            {
                                targetFile.CheckIn("", CheckinType.MajorCheckIn);
                                web.Context.ExecuteQueryRetry();
                            }
                            break;
                        }
                        }

                        // Don't set security when nothing is defined. This otherwise breaks on files set outside of a list
                        if (file.Security != null &&
                            (file.Security.ClearSubscopes == true || file.Security.CopyRoleAssignments == true || file.Security.RoleAssignments.Count > 0))
                        {
                            targetFile.ListItemAllFields.SetSecurity(parser, file.Security);
                        }
                    }

                    web = originalWeb; // restore context in case files are provisioned to the master page gallery #1059
                }
            }
            WriteMessage("Done processing files", ProvisioningMessageType.Completed);
            return(parser);
        }
        private void CreateView(Web web, View view, Microsoft.SharePoint.Client.ViewCollection existingViews, List createdList, PnPMonitoredScope monitoredScope, TokenParser parser)
        {
            try
            {

                var viewElement = XElement.Parse(view.SchemaXml);
                var displayNameElement = viewElement.Attribute("DisplayName");
                if (displayNameElement == null)
                {
                    throw new ApplicationException("Invalid View element, missing a valid value for the attribute DisplayName.");
                }

                var viewTitle = parser.ParseString(displayNameElement.Value);
                monitoredScope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_view__0_, displayNameElement.Value);
                var existingView = existingViews.FirstOrDefault(v => v.Title == viewTitle);

                if (existingView != null)
                {
                    existingView.DeleteObject();
                    web.Context.ExecuteQueryRetry();
                }

                // Type
                var viewTypeString = viewElement.Attribute("Type") != null ? viewElement.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 = viewElement.Descendants("ViewFields").FirstOrDefault();
                if (viewFieldsElement != null)
                {
                    viewFields = (from field in viewElement.Descendants("ViewFields").Descendants("FieldRef") select field.Attribute("Name").Value).ToArray();
                }

                // Default view
                var viewDefault = viewElement.Attribute("DefaultView") != null && Boolean.Parse(viewElement.Attribute("DefaultView").Value);

                // Row limit
                var viewPaged = true;
                uint viewRowLimit = 30;
                var rowLimitElement = viewElement.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 viewElement.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,
                };

                // Allow to specify a custom view url. View url is taken from title, so we first set title to the view url value we need,
                // create the view and then set title back to the original value
                var urlAttribute = viewElement.Attribute("Url");
                var urlHasValue = urlAttribute != null && !string.IsNullOrEmpty(urlAttribute.Value);
                if (urlHasValue)
                {
                    //set Title to be equal to url (in order to generate desired url)
                    viewCI.Title = Path.GetFileNameWithoutExtension(urlAttribute.Value);
                }

                var createdView = createdList.Views.Add(viewCI);
                web.Context.Load(createdView, v => v.Scope, v => v.JSLink, v => v.Title);
                web.Context.ExecuteQueryRetry();

                if (urlHasValue)
                {
                    //restore original title
                    createdView.Title = viewTitle;
                    createdView.Update();
                }

                // ContentTypeID
                var contentTypeID = viewElement.Attribute("ContentTypeID") != null ? viewElement.Attribute("ContentTypeID").Value : null;
                if (!string.IsNullOrEmpty(contentTypeID) && (contentTypeID != BuiltInContentTypeId.System))
                {
                    ContentTypeId childContentTypeId = null;
                    if (contentTypeID == BuiltInContentTypeId.RootOfList)
                    {
                        var childContentType = web.GetContentTypeById(contentTypeID);
                        childContentTypeId = childContentType != null ? childContentType.Id : null;
                    }
                    else
                    {
                        childContentTypeId = createdList.ContentTypes.BestMatch(contentTypeID);
                    }
                    if (childContentTypeId != null)
                    {
                        createdView.ContentTypeId = childContentTypeId;
                        createdView.Update();
                    }
                }

                // Default for content type
                bool parsedDefaultViewForContentType;
                var defaultViewForContentType = viewElement.Attribute("DefaultViewForContentType") != null ? viewElement.Attribute("DefaultViewForContentType").Value : null;
                if (!string.IsNullOrEmpty(defaultViewForContentType) && bool.TryParse(defaultViewForContentType, out parsedDefaultViewForContentType))
                {
                    createdView.DefaultViewForContentType = parsedDefaultViewForContentType;
                    createdView.Update();
                }

                // Scope
                var scope = viewElement.Attribute("Scope") != null ? viewElement.Attribute("Scope").Value : null;
                ViewScope parsedScope = ViewScope.DefaultValue;
                if (!string.IsNullOrEmpty(scope) && Enum.TryParse<ViewScope>(scope, out parsedScope))
                {
                    createdView.Scope = parsedScope;
                    createdView.Update();
                }

                // JSLink
                var jslinkElement = viewElement.Descendants("JSLink").FirstOrDefault();
                if (jslinkElement != null)
                {
                    var jslink = jslinkElement.Value;
                    if (createdView.JSLink != jslink)
                    {
                        createdView.JSLink = jslink;
                        createdView.Update();
                    }
                }

                createdList.Update();
                web.Context.ExecuteQueryRetry();
            }
            catch (Exception ex)
            {
                monitoredScope.LogError(CoreResources.Provisioning_ObjectHandlers_ListInstances_Creating_view_failed___0_____1_, ex.Message, ex.StackTrace);
                throw;
            }
        }
        public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate template, TokenParser parser, ProvisioningTemplateApplyingInformation applyingInformation)
        {
            using (var scope = new PnPMonitoredScope(this.Name))
            {
                web.EnsureProperties(w => w.ServerRelativeUrl);

                foreach (var clientSidePage in template.ClientSidePages)
                {
                    // determine pages library
                    string pagesLibrary = "SitePages";
                    string pageName     = $"{System.IO.Path.GetFileNameWithoutExtension(clientSidePage.PageName)}.aspx";

                    string url = $"{pagesLibrary}/{pageName}";

                    url = UrlUtility.Combine(web.ServerRelativeUrl, url);

                    var exists = true;
                    try
                    {
                        var file = web.GetFileByServerRelativeUrl(url);
                        web.Context.Load(file);
                        web.Context.ExecuteQueryRetry();
                    }
                    catch (ServerException ex)
                    {
                        if (ex.ServerErrorTypeName == "System.IO.FileNotFoundException")
                        {
                            exists = false;
                        }
                    }

                    Pages.ClientSidePage page = null;
                    if (exists)
                    {
                        if (clientSidePage.Overwrite)
                        {
                            // Get the existing page
                            page = web.LoadClientSidePage(pageName);
                            // Clear the page
                            page.ClearPage();
                        }
                        else
                        {
                            scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ClientSidePages_NoOverWrite, pageName);
                            continue;
                        }
                    }
                    else
                    {
                        // Create new client side page
                        page = web.AddClientSidePage(pageName);
                    }

                    // Load existing available controls
                    var componentsToAdd = page.AvailableClientSideComponents().ToList();

                    // if no section specified then add a default single column section
                    if (!clientSidePage.Sections.Any())
                    {
                        clientSidePage.Sections.Add(new CanvasSection()
                        {
                            Type = CanvasSectionType.OneColumn, Order = 10
                        });
                    }

                    int sectionCount = -1;
                    // Apply the "layout" and content
                    foreach (var section in clientSidePage.Sections)
                    {
                        sectionCount++;
                        switch (section.Type)
                        {
                        case CanvasSectionType.OneColumn:
                            page.AddSection(Pages.CanvasSectionTemplate.OneColumn, section.Order);
                            break;

                        case CanvasSectionType.OneColumnFullWidth:
                            page.AddSection(Pages.CanvasSectionTemplate.OneColumnFullWidth, section.Order);
                            break;

                        case CanvasSectionType.TwoColumn:
                            page.AddSection(Pages.CanvasSectionTemplate.TwoColumn, section.Order);
                            break;

                        case CanvasSectionType.ThreeColumn:
                            page.AddSection(Pages.CanvasSectionTemplate.ThreeColumn, section.Order);
                            break;

                        case CanvasSectionType.TwoColumnLeft:
                            page.AddSection(Pages.CanvasSectionTemplate.TwoColumnLeft, section.Order);
                            break;

                        case CanvasSectionType.TwoColumnRight:
                            page.AddSection(Pages.CanvasSectionTemplate.TwoColumnRight, section.Order);
                            break;

                        default:
                            page.AddSection(Pages.CanvasSectionTemplate.OneColumn, section.Order);
                            break;
                        }

                        // Add controls to the section
                        if (section.Controls.Any())
                        {
                            // Safety measure: reset column order to 1 for columns marked with 0 or lower
                            foreach (var control in section.Controls.Where(p => p.Column <= 0).ToList())
                            {
                                control.Column = 1;
                            }

                            foreach (CanvasControl control in section.Controls)
                            {
                                Pages.ClientSideComponent baseControl = null;

                                // Is it a text control?
                                if (control.Type == WebPartType.Text)
                                {
                                    Pages.ClientSideText textControl = new Pages.ClientSideText();
                                    if (control.ControlProperties.Any())
                                    {
                                        var textProperty = control.ControlProperties.First();
                                        textControl.Text = textProperty.Value;
                                        // Reduce column number by 1 due 0 start indexing
                                        page.AddControl(textControl, page.Sections[sectionCount].Columns[control.Column - 1], control.Order);
                                    }
                                }
                                // It is a web part
                                else
                                {
                                    // apply token parsing on the web part properties
                                    control.JsonControlData = parser.ParseString(control.JsonControlData);

                                    // perform processing of web part properties (e.g. include listid property based list title property)
                                    var webPartPostProcessor = CanvasControlPostProcessorFactory.Resolve(control);
                                    webPartPostProcessor.Process(control, page);

                                    // Is a custom developed client side web part (3rd party)
                                    if (control.Type == WebPartType.Custom)
                                    {
                                        if (!string.IsNullOrEmpty(control.CustomWebPartName))
                                        {
                                            baseControl = componentsToAdd.FirstOrDefault(p => p.Name.Equals(control.CustomWebPartName, StringComparison.InvariantCultureIgnoreCase));
                                        }
                                        else if (control.ControlId != Guid.Empty)
                                        {
                                            baseControl = componentsToAdd.FirstOrDefault(p => p.Id.Equals($"{{{control.ControlId.ToString()}}}", StringComparison.CurrentCultureIgnoreCase));
                                        }
                                    }
                                    // Is an OOB client side web part (1st party)
                                    else
                                    {
                                        string webPartName = "";
                                        switch (control.Type)
                                        {
                                        case WebPartType.Image:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.Image);
                                            break;

                                        case WebPartType.BingMap:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.BingMap);
                                            break;

                                        case WebPartType.ContentEmbed:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.ContentEmbed);
                                            break;

                                        case WebPartType.ContentRollup:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.ContentRollup);
                                            break;

                                        case WebPartType.DocumentEmbed:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.DocumentEmbed);
                                            break;

                                        case WebPartType.Events:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.Events);
                                            break;

                                        case WebPartType.GroupCalendar:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.GroupCalendar);
                                            break;

                                        case WebPartType.Hero:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.Hero);
                                            break;

                                        case WebPartType.ImageGallery:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.ImageGallery);
                                            break;

                                        case WebPartType.LinkPreview:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.LinkPreview);
                                            break;

                                        case WebPartType.List:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.List);
                                            break;

                                        case WebPartType.NewsFeed:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.NewsFeed);
                                            break;

                                        case WebPartType.NewsReel:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.NewsReel);
                                            break;

                                        case WebPartType.PageTitle:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.PageTitle);
                                            break;

                                        case WebPartType.People:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.People);
                                            break;

                                        case WebPartType.PowerBIReportEmbed:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.PowerBIReportEmbed);
                                            break;

                                        case WebPartType.QuickChart:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.QuickChart);
                                            break;

                                        case WebPartType.QuickLinks:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.QuickLinks);
                                            break;

                                        case WebPartType.SiteActivity:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.SiteActivity);
                                            break;

                                        case WebPartType.VideoEmbed:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.VideoEmbed);
                                            break;

                                        case WebPartType.YammerEmbed:
                                            webPartName = Pages.ClientSidePage.ClientSideWebPartEnumToName(Pages.DefaultClientSideWebParts.YammerEmbed);
                                            break;
                                        }

                                        baseControl = componentsToAdd.FirstOrDefault(p => p.Name.Equals(webPartName, StringComparison.InvariantCultureIgnoreCase));
                                    }

                                    if (baseControl != null)
                                    {
                                        Pages.ClientSideWebPart myWebPart = new Pages.ClientSideWebPart(baseControl)
                                        {
                                            Order = control.Order
                                        };

                                        // Reduce column number by 1 due 0 start indexing
                                        page.AddControl(myWebPart, page.Sections[sectionCount].Columns[control.Column - 1], control.Order);

                                        // set properties using json string
                                        if (!String.IsNullOrEmpty(control.JsonControlData))
                                        {
                                            myWebPart.PropertiesJson = control.JsonControlData;
                                        }

                                        // set using property collection
                                        if (control.ControlProperties.Any())
                                        {
                                            // grab the "default" properties so we can deduct their types, needed to correctly apply the set properties
                                            var    controlManifest   = JObject.Parse(baseControl.Manifest);
                                            JToken controlProperties = null;
                                            if (controlManifest != null)
                                            {
                                                controlProperties = controlManifest.SelectToken("preconfiguredEntries[0].properties");
                                            }

                                            foreach (var property in control.ControlProperties)
                                            {
                                                Type propertyType = typeof(string);

                                                if (controlProperties != null)
                                                {
                                                    var defaultProperty = controlProperties.SelectToken(property.Key, false);
                                                    if (defaultProperty != null)
                                                    {
                                                        propertyType = Type.GetType($"System.{defaultProperty.Type.ToString()}");

                                                        if (propertyType == null)
                                                        {
                                                            if (defaultProperty.Type.ToString().Equals("integer", StringComparison.InvariantCultureIgnoreCase))
                                                            {
                                                                propertyType = typeof(int);
                                                            }
                                                        }
                                                    }
                                                }

                                                myWebPart.Properties[property.Key] = JToken.FromObject(Convert.ChangeType(parser.ParseString(property.Value), propertyType));
                                            }
                                        }
                                    }
                                    else
                                    {
                                        scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ClientSidePages_BaseControlNotFound, control.ControlId, control.CustomWebPartName);
                                    }
                                }
                            }
                        }
                    }

                    // Persist the page
                    page.Save(pageName);

                    // Make it a news page if requested
                    if (clientSidePage.PromoteAsNewsArticle)
                    {
                        page.PromoteAsNewsArticle();
                    }
                }
            }
            return(parser);
        }
        private Field UpdateField(ClientObject web, ListInfo listInfo, Guid fieldId, XElement templateFieldElement, Field existingField, PnPMonitoredScope scope, TokenParser parser, string originalFieldXml)
        {
            Field field = null;
            web.Context.Load(existingField, f => f.SchemaXmlWithResourceTokens);
            web.Context.ExecuteQueryRetry();

            var existingFieldElement = XElement.Parse(existingField.SchemaXmlWithResourceTokens);

            var equalityComparer = new XNodeEqualityComparer();

            // Is field different in template?
            if (equalityComparer.GetHashCode(existingFieldElement) != equalityComparer.GetHashCode(templateFieldElement))
            {
                // Is existing field of the same type?
                if (existingFieldElement.Attribute("Type").Value == templateFieldElement.Attribute("Type").Value)
                {
                    templateFieldElement = PrepareField(templateFieldElement);
                    if (IsFieldXmlValid(parser.ParseString(templateFieldElement.ToString()), parser, web.Context))
                    {
                        foreach (var attribute in templateFieldElement.Attributes())
                        {
                            if (existingFieldElement.Attribute(attribute.Name) != null)
                            {
                                existingFieldElement.Attribute(attribute.Name).Value = attribute.Value;
                            }
                            else
                            {
                                existingFieldElement.Add(attribute);
                            }
                        }
                        foreach (var element in templateFieldElement.Elements())
                        {
                            if (existingFieldElement.Element(element.Name) != null)
                            {
                                existingFieldElement.Element(element.Name).Remove();
                            }
                            existingFieldElement.Add(element);
                        }

                        if (existingFieldElement.Attribute("Version") != null)
                        {
                            existingFieldElement.Attributes("Version").Remove();
                        }
                        existingField.SchemaXml = parser.ParseString(existingFieldElement.ToString(), "~sitecollection", "~site");
                        existingField.UpdateAndPushChanges(true);
                        web.Context.ExecuteQueryRetry();
                        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())
                            {
                                if (existingField.TitleResource.SetUserResourceValue(nameAttributeValue, parser))
                                {
                                    isDirty = true;
                                }
                            }
                            var descriptionAttributeValue = originalFieldElement.Attribute("Description") != null ? originalFieldElement.Attribute("Description").Value : "";
                            if (descriptionAttributeValue.ContainsResourceToken())
                            {
                                if (existingField.DescriptionResource.SetUserResourceValue(descriptionAttributeValue, parser))
                                {
                                    isDirty = true;
                                }
                            }
                        }
            #endif
                        if (isDirty)
                        {
                            existingField.Update();
                            web.Context.ExecuteQueryRetry();
                            field = existingField;
                        }
                    }
                    else
                    {
                        // The field Xml was found invalid
                        var tokenString = parser.GetLeftOverTokens(originalFieldXml).Aggregate(String.Empty, (acc, i) => acc + " " + i);
                        scope.LogError("The field was found invalid: {0}", tokenString);
                        throw new Exception(string.Format("The field was found invalid: {0}", tokenString));
                    }
                }
                else
                {
                    var fieldName = existingFieldElement.Attribute("Name") != null ? existingFieldElement.Attribute("Name").Value : existingFieldElement.Attribute("StaticName").Value;
                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field__0____1___exists_in_list__2____3___but_is_of_different_type__Skipping_field_, fieldName, fieldId, listInfo.TemplateList.Title, listInfo.SiteList.Id);
                    WriteWarning(string.Format(CoreResources.Provisioning_ObjectHandlers_ListInstances_Field__0____1___exists_in_list__2____3___but_is_of_different_type__Skipping_field_, fieldName, fieldId, listInfo.TemplateList.Title, listInfo.SiteList.Id), ProvisioningMessageType.Warning);
                }
            }
            return field;
        }
示例#52
0
        internal static void UpdateCustomAction(TokenParser parser, PnPMonitoredScope scope, CustomAction customAction, UserCustomAction existingCustomAction, bool isNoScriptSite = false)
        {
            var isDirty = false;

            if (isNoScriptSite)
            {
                scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_CustomActions_SkippingAddUpdateDueToNoScript, customAction.Name);
                return;
            }

            // Otherwise we update it
            if (customAction.CommandUIExtension != null)
            {
                if (existingCustomAction.CommandUIExtension != parser.ParseString(customAction.CommandUIExtension.ToString()))
                {
                    scope.LogPropertyUpdate("CommandUIExtension");
                    existingCustomAction.CommandUIExtension = parser.ParseString(customAction.CommandUIExtension.ToString());
                    isDirty = true;
                }
            }
            else
            {
                // Required to allow for a delta action to blank out the CommandUIExtension attribute
                if (existingCustomAction.CommandUIExtension != null)
                {
                    scope.LogPropertyUpdate("CommandUIExtension");
                    existingCustomAction.CommandUIExtension = null;
                    isDirty = true;
                }
            }

#if !ONPREMISES
            if (customAction.ClientSideComponentId != null && customAction.ClientSideComponentId != Guid.Empty)
            {
                if (existingCustomAction.ClientSideComponentId != customAction.ClientSideComponentId)
                {
                    existingCustomAction.ClientSideComponentId = customAction.ClientSideComponentId;
                    isDirty = true;
                }
            }

            if (!String.IsNullOrEmpty(customAction.ClientSideComponentProperties))
            {
                if (existingCustomAction.ClientSideComponentProperties != parser.ParseString(customAction.ClientSideComponentProperties))
                {
                    existingCustomAction.ClientSideComponentProperties = parser.ParseString(customAction.ClientSideComponentProperties);
                    isDirty = true;
                }
            }
#endif

            if (existingCustomAction.Description != customAction.Description)
            {
                scope.LogPropertyUpdate("Description");
                existingCustomAction.Description = customAction.Description;
                isDirty = true;
            }
#if !ONPREMISES
            if (customAction.Description.ContainsResourceToken())
            {
                if (existingCustomAction.DescriptionResource.SetUserResourceValue(customAction.Description, parser))
                {
                    isDirty = true;
                }
            }
#endif
            if (existingCustomAction.Group != customAction.Group)
            {
                scope.LogPropertyUpdate("Group");
                existingCustomAction.Group = customAction.Group;
                isDirty = true;
            }
            if (existingCustomAction.ImageUrl != parser.ParseString(customAction.ImageUrl))
            {
                scope.LogPropertyUpdate("ImageUrl");
                existingCustomAction.ImageUrl = parser.ParseString(customAction.ImageUrl);
                isDirty = true;
            }
            if (existingCustomAction.Location != customAction.Location)
            {
                scope.LogPropertyUpdate("Location");
                existingCustomAction.Location = customAction.Location;
                isDirty = true;
            }
            if (existingCustomAction.RegistrationId != parser.ParseString(customAction.RegistrationId))
            {
                scope.LogPropertyUpdate("RegistrationId");
                existingCustomAction.RegistrationId = parser.ParseString(customAction.RegistrationId);
                isDirty = true;
            }
            if (existingCustomAction.RegistrationType != customAction.RegistrationType)
            {
                scope.LogPropertyUpdate("RegistrationType");
                existingCustomAction.RegistrationType = customAction.RegistrationType;
                isDirty = true;
            }
            if (existingCustomAction.ScriptBlock != parser.ParseString(customAction.ScriptBlock))
            {
                scope.LogPropertyUpdate("ScriptBlock");
                existingCustomAction.ScriptBlock = parser.ParseString(customAction.ScriptBlock);
                isDirty = true;
            }
            if (existingCustomAction.ScriptSrc != parser.ParseString(customAction.ScriptSrc, "~site", "~sitecollection"))
            {
                scope.LogPropertyUpdate("ScriptSrc");
                existingCustomAction.ScriptSrc = parser.ParseString(customAction.ScriptSrc, "~site", "~sitecollection");
                isDirty = true;
            }
            if (existingCustomAction.Sequence != customAction.Sequence)
            {
                scope.LogPropertyUpdate("Sequence");
                existingCustomAction.Sequence = customAction.Sequence;
                isDirty = true;
            }
            if (existingCustomAction.Title != parser.ParseString(customAction.Title))
            {
                scope.LogPropertyUpdate("Title");
                existingCustomAction.Title = parser.ParseString(customAction.Title);
                isDirty = true;
            }
#if !ONPREMISES
            if (customAction.Title.ContainsResourceToken())
            {
                if (existingCustomAction.TitleResource.SetUserResourceValue(customAction.Title, parser))
                {
                    isDirty = true;
                }
            }
#endif
            if (existingCustomAction.Url != parser.ParseString(customAction.Url))
            {
                scope.LogPropertyUpdate("Url");
                existingCustomAction.Url = parser.ParseString(customAction.Url);
                isDirty = true;
            }

            if (isDirty)
            {
                existingCustomAction.Update();
                existingCustomAction.Context.ExecuteQueryRetry();
            }
        }
        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;
        }
示例#54
0
        private void ProvisionCustomActionImplementation(object parent, CustomActionCollection customActions, TokenParser parser, PnPMonitoredScope scope, bool isNoScriptSite = false)
        {
            Web  web  = null;
            Site site = null;

            if (parent is Site)
            {
                site = parent as Site;

                // Switch parser context;
                parser.Rebase(site.RootWeb);
            }
            else
            {
                web = parent as Web;

                // Switch parser context
                parser.Rebase(web);
            }
            foreach (var customAction in customActions)
            {
                if (isNoScriptSite && Guid.Empty == customAction.ClientSideComponentId)
                {
                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_CustomActions_SkippingAddUpdateDueToNoScript, customAction.Name);
                    continue;
                }

                var caExists = false;
                if (site != null)
                {
                    caExists = site.CustomActionExists(customAction.Name);
                }
                else
                {
                    caExists = web.CustomActionExists(customAction.Name);
                }

                // If the CustomAction does not exist, we don't have to remove it, and it is enabled
                if (!caExists && !customAction.Remove && customAction.Enabled)
                {
                    // Then we add it to the target
                    var customActionEntity = new CustomActionEntity()
                    {
#if !ONPREMISES
                        ClientSideComponentId         = customAction.ClientSideComponentId,
                        ClientSideComponentProperties = customAction.ClientSideComponentProperties != null?parser.ParseString(customAction.ClientSideComponentProperties) : customAction.ClientSideComponentProperties,
#endif
                        CommandUIExtension = customAction.CommandUIExtension != null?parser.ParseString(customAction.CommandUIExtension.ToString()) : string.Empty,
                                                 Description      = parser.ParseString(customAction.Description),
                                                 Group            = customAction.Group,
                                                 ImageUrl         = parser.ParseString(customAction.ImageUrl),
                                                 Location         = customAction.Location,
                                                 Name             = customAction.Name,
                                                 RegistrationId   = parser.ParseString(customAction.RegistrationId),
                                                 RegistrationType = customAction.RegistrationType,
                                                 Remove           = customAction.Remove,
                                                 Rights           = customAction.Rights,
                                                 ScriptBlock      = parser.ParseString(customAction.ScriptBlock),
                                                 ScriptSrc        = parser.ParseString(customAction.ScriptSrc, "~site", "~sitecollection"),
                                                 Sequence         = customAction.Sequence,
                                                 Title            = parser.ParseString(customAction.Title),
                                                 Url = parser.ParseString(customAction.Url)
                    };


                    if (site != null)
                    {
                        scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_CustomActions_Adding_custom_action___0___to_scope_Site, customActionEntity.Name);
                        site.AddCustomAction(customActionEntity);
#if !ONPREMISES
                        if ((!string.IsNullOrEmpty(customAction.Title) && customAction.Title.ContainsResourceToken()) ||
                            (!string.IsNullOrEmpty(customAction.Description) && customAction.Description.ContainsResourceToken()))
                        {
                            var uca = site.GetCustomActions().FirstOrDefault(uc => uc.Name == customAction.Name);
                            SetCustomActionResourceValues(parser, customAction, uca);
                        }
#endif
                    }
                    else
                    {
                        scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_CustomActions_Adding_custom_action___0___to_scope_Web, customActionEntity.Name);
                        web.AddCustomAction(customActionEntity);
#if !ONPREMISES
                        if (customAction.Title.ContainsResourceToken() || customAction.Description.ContainsResourceToken())
                        {
                            var uca = web.GetCustomActions().FirstOrDefault(uc => uc.Name == customAction.Name);
                            SetCustomActionResourceValues(parser, customAction, uca);
                        }
#endif
                    }
                }
                else
                {
                    UserCustomAction existingCustomAction;
                    if (site != null)
                    {
                        existingCustomAction = site.GetCustomActions().FirstOrDefault(c => c.Name == customAction.Name);
                    }
                    else
                    {
                        existingCustomAction = web.GetCustomActions().FirstOrDefault(c => c.Name == customAction.Name);
                    }
                    if (existingCustomAction != null)
                    {
                        // If we have to remove the existing CustomAction
                        if (customAction.Remove)
                        {
                            // We simply remove it
                            existingCustomAction.DeleteObject();
                            existingCustomAction.Context.ExecuteQueryRetry();
                        }
                        else
                        {
                            UpdateCustomAction(parser, scope, customAction, existingCustomAction, isNoScriptSite);
                        }
                    }
                }
            }
        }
        private static void CreateListCustomAction(List existingList, TokenParser parser, CustomAction userCustomAction)
        {
            UserCustomAction newUserCustomAction = existingList.UserCustomActions.Add();

            newUserCustomAction.Title = userCustomAction.Title;
            newUserCustomAction.Description = userCustomAction.Description;

            #if !ONPREMISES
            if (!string.IsNullOrEmpty(userCustomAction.Title) && userCustomAction.Title.ContainsResourceToken())
            {
                newUserCustomAction.TitleResource.SetUserResourceValue(userCustomAction.Title, parser);
            }
            if (!string.IsNullOrEmpty(userCustomAction.Description) && userCustomAction.Description.ContainsResourceToken())
            {
                newUserCustomAction.DescriptionResource.SetUserResourceValue(userCustomAction.Description, parser);
            }
            #endif

            newUserCustomAction.Name = userCustomAction.Name;
            newUserCustomAction.ImageUrl = userCustomAction.ImageUrl;
            newUserCustomAction.Rights = userCustomAction.Rights;
            newUserCustomAction.Sequence = userCustomAction.Sequence;
            newUserCustomAction.Group = userCustomAction.Group;
            newUserCustomAction.Location = userCustomAction.Location;
            //newUserCustomAction.RegistrationId = userCustomAction.RegistrationId;
            //newUserCustomAction.RegistrationType = userCustomAction.RegistrationType;
            newUserCustomAction.CommandUIExtension =
                userCustomAction.CommandUIExtension != null ?
                    parser.ParseString(userCustomAction.CommandUIExtension.ToString()) :
                    string.Empty;
            newUserCustomAction.ScriptBlock = userCustomAction.ScriptBlock;
            newUserCustomAction.ScriptSrc = userCustomAction.ScriptSrc;
            newUserCustomAction.Url = userCustomAction.Url;

            newUserCustomAction.Update();
        }
示例#56
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.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);
                    var user            = web.EnsureUser(parsedAdminName);
                    user.IsSiteAdmin = true;
                    user.Update();
                    web.Context.ExecuteQueryRetry();
                }

                // 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)
                                {
                                    principal = web.EnsureUser(parser.ParseString(roleAssignment.Principal));
                                }

                                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);
        }
        private Tuple<List, TokenParser> CreateList(Web web, ListInstance list, TokenParser parser, PnPMonitoredScope scope, bool isNoScriptSite = false)
        {
            List createdList;
            if (list.Url.Equals("SiteAssets") && list.TemplateType == (int)ListTemplateType.DocumentLibrary)
            {
                //Ensure that the Site Assets library is created using the out of the box creation mechanism
                //Site Assets that are created using the EnsureSiteAssetsLibrary method slightly differ from
                //default Document Libraries. See issue 512 (https://github.com/OfficeDev/PnP-Sites-Core/issues/512)
                //for details about the issue fixed by this approach.
                createdList = web.Lists.EnsureSiteAssetsLibrary();
                //Check that Title and Description have the correct values
                web.Context.Load(createdList, l => l.Title,
                                              l => l.Description);
                web.Context.ExecuteQueryRetry();
                var isDirty = false;
                if (!string.Equals(createdList.Description, list.Description))
                {
                    createdList.Description = list.Description;
                    isDirty = true;
                }
                if (!string.Equals(createdList.Title, list.Title))
                {
                    createdList.Title = list.Title;
                    isDirty = true;
                }
                if (isDirty)
                {
                    createdList.Update();
                    web.Context.ExecuteQueryRetry();
                }

            }
            else
            {
                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;

                createdList = web.Lists.Add(listCreate);
                createdList.Update();
            }
            web.Context.Load(createdList, l => l.BaseTemplate);
            web.Context.ExecuteQueryRetry();

            #if !SP2013
            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))
            {
                createdList.DocumentTemplateUrl = parser.ParseString(list.DocumentTemplate);
            }

            // EnableAttachments are not supported for DocumentLibraries, Survey and PictureLibraries
            // TODO: the user should be warned
            if (createdList.BaseTemplate != (int)ListTemplateType.DocumentLibrary &&
                createdList.BaseTemplate != (int)ListTemplateType.Survey &&
                createdList.BaseTemplate != (int)ListTemplateType.PictureLibrary)
            {
                createdList.EnableAttachments = list.EnableAttachments;
            }

            createdList.EnableModeration = list.EnableModeration;
            createdList.ForceCheckout = list.ForceCheckout;

            // 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 !SP2013
                    createdList.MajorVersionLimit = list.MaxVersionLimit;
            #endif
                    // 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;
                    }

                    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.
                        }
                    }
                }
            }

            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, l => l.Id);
            web.Context.Load(createdList, l => l.RootFolder.ServerRelativeUrl);
            web.Context.Load(createdList.ContentTypes);
            web.Context.ExecuteQueryRetry();

            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);
                }

                ContentTypeBinding defaultCtBinding = null;
                foreach (var ctBinding in list.ContentTypeBindings)
                {
                    var tempCT = web.GetContentTypeById(ctBinding.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 (!createdList.ContentTypeExistsByName(name) && !ctBinding.Remove)
                        {
                            // Then add it to the target list
                            createdList.AddContentTypeToListById(ctBinding.ContentTypeId, searchContentTypeInSiteHierarchy: true);
                        }
                        // Else if the CT exists in the target list, and we have to remove it
                        else if (createdList.ContentTypeExistsByName(name) && ctBinding.Remove)
                        {
                            // Then remove it from the target list
                            createdList.RemoveContentTypeByName(name);
                        }

                        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)
                {
                    var shouldDelete = true;
                    shouldDelete &= (createdList.BaseTemplate != (int)ListTemplateType.DocumentLibrary || !ct.StringId.StartsWith(BuiltInContentTypeId.Folder + "00"));

                    if (shouldDelete)
                    {
                        ct.DeleteObject();
                        web.Context.ExecuteQueryRetry();
                    }
                }
            }

            // Add any custom action
            if (list.UserCustomActions.Any())
            {
                if (!isNoScriptSite)
                {
                    foreach (var userCustomAction in list.UserCustomActions)
                    {
                        CreateListCustomAction(createdList, parser, userCustomAction);
                    }

                    web.Context.ExecuteQueryRetry();
                }
                else
                {
                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ListInstances_SkipAddingOrUpdatingCustomActions);
                }
            }

            if (list.Security != null)
            {
                createdList.SetSecurity(parser, list.Security);
            }
            return Tuple.Create(createdList, parser);
        }
示例#58
0
        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 || g.Name == modelTermGroup.Name);
                    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 || 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);
        }
示例#59
0
        private TokenParser ProcessLookupFields(Web web, ProvisioningTemplate template, TokenParser parser, PnPMonitoredScope scope)
        {
            var rootWeb = (web.Context as ClientContext).Site.RootWeb;
            rootWeb.Context.Load(rootWeb.Lists, lists => lists.Include(l => l.Id, l => l.RootFolder.ServerRelativeUrl, l => l.Fields).Where(l => l.Hidden == false));
            rootWeb.Context.ExecuteQueryRetry();

            foreach (var siteField in template.SiteFields)
            {
                var fieldElement = XElement.Parse(siteField.SchemaXml);

                if (fieldElement.Attribute("List") != null)
                {
                    var fieldId = Guid.Parse(fieldElement.Attribute("ID").Value);
                    var listIdentifier = parser.ParseString(fieldElement.Attribute("List").Value);
                    var relationshipDeleteBehavior = fieldElement.Attribute("RelationshipDeleteBehavior") != null ? fieldElement.Attribute("RelationshipDeleteBehavior").Value : string.Empty;
                    var webId = string.Empty;

                    var field = rootWeb.Fields.GetById(fieldId);
                    rootWeb.Context.Load(field, f => f.SchemaXmlWithResourceTokens);
                    rootWeb.Context.ExecuteQueryRetry();

                    List sourceList = FindSourceList(listIdentifier, web, rootWeb);

                    if (sourceList != null)
                    {
                        rootWeb.Context.Load(sourceList.ParentWeb);
                        rootWeb.Context.ExecuteQueryRetry();

                        webId = sourceList.ParentWeb.Id.ToString();

                        ProcessField(field, sourceList.Id, webId, relationshipDeleteBehavior);
                    }
                }
            }

            web.Context.Load(web.Lists, lists => lists.Include(l => l.Id, l => l.RootFolder.ServerRelativeUrl, l => l.Fields).Where(l => l.Hidden == false));
            web.Context.ExecuteQueryRetry();

            foreach (var listInstance in template.Lists)
            {
                foreach (var listField in listInstance.Fields)
                {
                    var fieldElement = XElement.Parse(listField.SchemaXml);
                    if (fieldElement.Attribute("List") == null) continue;

                    var fieldId = Guid.Parse(fieldElement.Attribute("ID").Value);
                    var listIdentifier = parser.ParseString(fieldElement.Attribute("List").Value);
                    var relationshipDeleteBehavior = fieldElement.Attribute("RelationshipDeleteBehavior") != null ? fieldElement.Attribute("RelationshipDeleteBehavior").Value : string.Empty;
                    var webId = string.Empty;

                    var listUrl = UrlUtility.Combine(web.ServerRelativeUrl, parser.ParseString(listInstance.Url));

                    var createdList = web.Lists.FirstOrDefault(l => l.RootFolder.ServerRelativeUrl.Equals(listUrl, StringComparison.OrdinalIgnoreCase));
                    if (createdList != null)
                    {
                        try
                        {
                            var field = createdList.Fields.GetById(fieldId);
                            web.Context.Load(field, f => f.SchemaXmlWithResourceTokens);
                            web.Context.ExecuteQueryRetry();

                            List sourceList = FindSourceList(listIdentifier, web, rootWeb);

                            if (sourceList != null)
                            {
                                web.Context.Load(sourceList.ParentWeb);
                                web.Context.ExecuteQueryRetry();

                                webId = sourceList.ParentWeb.Id.ToString();
                                ProcessField(field, sourceList.Id, webId, relationshipDeleteBehavior);
                            }
                        }
                        catch (ArgumentException ex)
                        {
                            // We skip and log any issues related to not existing lookup fields
                            scope.LogError(String.Format("Exception searching for field! {0}", ex.Message));
                        }
                    }
                }
            }

            return parser;
        }
示例#60
0
        private Tuple <Guid, TokenParser> CreateTerm <T>(Web web, Model.Term modelTerm, TaxonomyItem parent, TermStore termStore, TokenParser parser, PnPMonitoredScope scope) where T : TaxonomyItem
        {
            Term term;

            if (modelTerm.Id == Guid.Empty)
            {
                modelTerm.Id = Guid.NewGuid();
            }

            if (parent is Term)
            {
                var languages = termStore.DefaultLanguage;
                term = ((Term)parent).CreateTerm(parser.ParseString(modelTerm.Name), modelTerm.Language ?? termStore.DefaultLanguage, modelTerm.Id);
            }
            else
            {
                term = ((TermSet)parent).CreateTerm(parser.ParseString(modelTerm.Name), modelTerm.Language ?? termStore.DefaultLanguage, modelTerm.Id);
            }
            if (!String.IsNullOrEmpty(modelTerm.Description))
            {
                term.SetDescription(modelTerm.Description, modelTerm.Language ?? termStore.DefaultLanguage);
            }
            if (!String.IsNullOrEmpty(modelTerm.Owner))
            {
                term.Owner = modelTerm.Owner;
            }

            term.IsAvailableForTagging = modelTerm.IsAvailableForTagging;

            if (modelTerm.Properties.Any() || modelTerm.Labels.Any() || modelTerm.LocalProperties.Any())
            {
                if (modelTerm.Labels.Any())
                {
                    foreach (var label in modelTerm.Labels)
                    {
                        if ((label.IsDefaultForLanguage && label.Language != termStore.DefaultLanguage) || label.IsDefaultForLanguage == false)
                        {
                            var l = term.CreateLabel(parser.ParseString(label.Value), label.Language, label.IsDefaultForLanguage);
                        }
                        else
                        {
                            scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_TermGroups_Skipping_label__0___label_is_to_set_to_default_for_language__1__while_the_default_termstore_language_is_also__1_, label.Value, label.Language);
                            WriteWarning(string.Format(CoreResources.Provisioning_ObjectHandlers_TermGroups_Skipping_label__0___label_is_to_set_to_default_for_language__1__while_the_default_termstore_language_is_also__1_, label.Value, label.Language), ProvisioningMessageType.Warning);
                        }
                    }
                }

                if (modelTerm.Properties.Any())
                {
                    foreach (var property in modelTerm.Properties)
                    {
                        term.SetCustomProperty(parser.ParseString(property.Key), parser.ParseString(property.Value));
                    }
                }
                if (modelTerm.LocalProperties.Any())
                {
                    foreach (var property in modelTerm.LocalProperties)
                    {
                        term.SetLocalCustomProperty(parser.ParseString(property.Key), parser.ParseString(property.Value));
                    }
                }
            }
            termStore.CommitAll();

            web.Context.Load(term);
            web.Context.ExecuteQueryRetry();

            if (modelTerm.Terms.Any())
            {
                foreach (var modelTermTerm in modelTerm.Terms)
                {
                    web.Context.Load(term.Terms);
                    web.Context.ExecuteQueryRetry();
                    var termTerms = term.Terms;
                    if (termTerms.Any())
                    {
                        var termTerm = termTerms.FirstOrDefault(t => t.Id == modelTermTerm.Id);
                        if (termTerm == null)
                        {
                            termTerm = termTerms.FirstOrDefault(t => t.Name == modelTermTerm.Name);
                            if (termTerm == null)
                            {
                                var returnTuple = CreateTerm <Term>(web, modelTermTerm, term, termStore, parser, scope);
                                modelTermTerm.Id = returnTuple.Item1;
                                parser           = returnTuple.Item2;
                            }
                            else
                            {
                                modelTermTerm.Id = termTerm.Id;
                            }
                        }
                        else
                        {
                            modelTermTerm.Id = termTerm.Id;
                        }
                    }
                    else
                    {
                        var returnTuple = CreateTerm <Term>(web, modelTermTerm, term, termStore, parser, scope);
                        modelTermTerm.Id = returnTuple.Item1;
                        parser           = returnTuple.Item2;
                    }
                }
                if (modelTerm.Terms.Any(t => t.CustomSortOrder > -1))
                {
                    var sortedTerms = modelTerm.Terms.OrderBy(t => t.CustomSortOrder);

                    var customSortString = sortedTerms.Aggregate(string.Empty, (a, i) => a + i.Id.ToString() + ":");
                    customSortString = customSortString.TrimEnd(new[] { ':' });

                    term.CustomSortOrder = customSortString;
                    termStore.CommitAll();
                }
            }
            return(Tuple.Create(modelTerm.Id, parser));
        }