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

            if (!String.IsNullOrEmpty(customAction.ClientSideComponentProperties))
            {
                if (existingCustomAction.ClientSideComponentProperties != parser.ParseString(customAction.ClientSideComponentProperties))
                {
                    existingCustomAction.ClientSideComponentProperties = parser.ParseString(customAction.ClientSideComponentProperties);
                }
            }
#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 != customAction.RegistrationId)
            {
                scope.LogPropertyUpdate("RegistrationId");
                existingCustomAction.RegistrationId = 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();
            }
        }
        private void ProvisionCustomActionImplementation(object parent, List <CustomAction> customActions, TokenParser parser, PnPMonitoredScope scope)
        {
            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)
            {
                var caExists = false;
                if (site != null)
                {
                    caExists = site.CustomActionExists(customAction.Name);
                }
                else
                {
                    caExists = web.CustomActionExists(customAction.Name);
                }
                if (!caExists)
                {
                    var customActionEntity = new CustomActionEntity()
                    {
                        CommandUIExtension = customAction.CommandUIExtension != null?parser.ParseString(customAction.CommandUIExtension.ToString()) : string.Empty,
                                                 Description      = customAction.Description,
                                                 Group            = customAction.Group,
                                                 ImageUrl         = parser.ParseString(customAction.ImageUrl),
                                                 Location         = customAction.Location,
                                                 Name             = customAction.Name,
                                                 RegistrationId   = 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            = 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);
                    }
                    else
                    {
                        scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_CustomActions_Adding_custom_action___0___to_scope_Web, customActionEntity.Name);
                        web.AddCustomAction(customActionEntity);
                    }
                }
                else
                {
                    UserCustomAction existingCustomAction = null;
                    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)
                    {
                        var isDirty = false;

                        if (customAction.CommandUIExtension != null)
                        {
                            if (existingCustomAction.CommandUIExtension != parser.ParseString(customAction.CommandUIExtension.ToString()))
                            {
                                scope.LogPropertyUpdate("CommandUIExtension");
                                existingCustomAction.CommandUIExtension = parser.ParseString(customAction.CommandUIExtension.ToString());
                                isDirty = true;
                            }
                        }

                        if (existingCustomAction.Description != customAction.Description)
                        {
                            scope.LogPropertyUpdate("Description");
                            existingCustomAction.Description = customAction.Description;
                            isDirty = true;
                        }
                        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 != customAction.RegistrationId)
                        {
                            scope.LogPropertyUpdate("RegistrationId");
                            existingCustomAction.RegistrationId = 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.Title != parser.ParseString(customAction.Title))
                        {
                            scope.LogPropertyUpdate("Title");
                            existingCustomAction.Title = parser.ParseString(customAction.Title);
                            isDirty = true;
                        }
                        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();
                        }
                    }
                }
            }
        }
        private void ProvisionCustomActionImplementation(object parent, List<CustomAction> customActions, TokenParser parser, PnPMonitoredScope scope)
        {
            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)
            {
                var caExists = false;
                if (site != null)
                {
                    caExists = site.CustomActionExists(customAction.Name);
                }
                else
                {
                    caExists = web.CustomActionExists(customAction.Name);
                }
                if (!caExists)
                {
                    var customActionEntity = new CustomActionEntity()
                    {
                        CommandUIExtension = customAction.CommandUIExtension != null ? parser.ParseString(customAction.CommandUIExtension.ToString()) : string.Empty,
                        Description = customAction.Description,
                        Group = customAction.Group,
                        ImageUrl = parser.ParseString(customAction.ImageUrl),
                        Location = customAction.Location,
                        Name = customAction.Name,
                        RegistrationId = 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 = 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);
                    }
                    else
                    {
                        scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_CustomActions_Adding_custom_action___0___to_scope_Web, customActionEntity.Name);
                        web.AddCustomAction(customActionEntity);
                    }
                }
                else
                {
                    UserCustomAction existingCustomAction = null;
                    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)
                    {
                        var isDirty = false;

                        if (customAction.CommandUIExtension != null)
                        {
                            if (existingCustomAction.CommandUIExtension != parser.ParseString(customAction.CommandUIExtension.ToString()))
                            {
                                scope.LogPropertyUpdate("CommandUIExtension");
                                existingCustomAction.CommandUIExtension = parser.ParseString(customAction.CommandUIExtension.ToString());
                                isDirty = true;
                            }
                        }

                        if (existingCustomAction.Description != customAction.Description)
                        {
                            scope.LogPropertyUpdate("Description");
                            existingCustomAction.Description = customAction.Description;
                            isDirty = true;
                        }
                        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 != customAction.RegistrationId)
                        {
                            scope.LogPropertyUpdate("RegistrationId");
                            existingCustomAction.RegistrationId = 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.Title != parser.ParseString(customAction.Title))
                        {
                            scope.LogPropertyUpdate("Title");
                            existingCustomAction.Title = parser.ParseString(customAction.Title);
                            isDirty = true;
                        }
                        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();
                        }
                    }
                }
            }
        }
        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;
            }
            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 (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();
            }
        }
        internal static void UpdateCustomAction(TokenParser parser, PnPMonitoredScope scope, CustomAction customAction, UserCustomAction existingCustomAction)
        {
            var isDirty = false;

            // 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
                existingCustomAction.CommandUIExtension = null;
            }

            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 != customAction.RegistrationId)
            {
                scope.LogPropertyUpdate("RegistrationId");
                existingCustomAction.RegistrationId = 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();
            }
        }
        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;
            }
            if (templateContentType.Group != null && existingContentType.Group != parser.ParseString(templateContentType.Group))
            {
                scope.LogPropertyUpdate("Group");
                existingContentType.Group = parser.ParseString(templateContentType.Group);
                isDirty = true;
            }
            if (isDirty)
            {
                existingContentType.Update(true);
                web.Context.ExecuteQueryRetry();
            }
            // Delta handling
            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, field.Id);
                    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;
                    }
                }
            }
            if (isDirty)
            {
                existingContentType.Update(true);
                web.Context.ExecuteQueryRetry();
            }
        }
Beispiel #7
0
        internal static void UpdateCustomAction(TokenParser parser, PnPMonitoredScope scope, CustomAction customAction, UserCustomAction existingCustomAction)
        {
            var isDirty = false;

            // 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 (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 != customAction.RegistrationId)
            {
                scope.LogPropertyUpdate("RegistrationId");
                existingCustomAction.RegistrationId = 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();
            }
        }
        private static void UpdateContentType(Web web, Microsoft.SharePoint.Client.ContentType existingContentType, ContentType templateContentType, TokenParser parser, PnPMonitoredScope scope, bool isNoScriptSite = false)
        {
            var isDirty       = false;
            var reOrderFields = false;

            if (existingContentType.Hidden != templateContentType.Hidden)
            {
                scope.LogPropertyUpdate("Hidden");
                existingContentType.Hidden = templateContentType.Hidden;
                isDirty = true;
            }
            if (existingContentType.ReadOnly != templateContentType.ReadOnly)
            {
                scope.LogPropertyUpdate("ReadOnly");
                existingContentType.ReadOnly = templateContentType.ReadOnly;
                isDirty = true;
            }
            if (existingContentType.Sealed != templateContentType.Sealed)
            {
                scope.LogPropertyUpdate("Sealed");
                existingContentType.Sealed = templateContentType.Sealed;
                isDirty = true;
            }
            if (templateContentType.Description != null && existingContentType.Description != parser.ParseString(templateContentType.Description))
            {
                scope.LogPropertyUpdate("Description");
                existingContentType.Description = parser.ParseString(templateContentType.Description);
                isDirty = true;
            }
            if (templateContentType.DocumentTemplate != null && existingContentType.DocumentTemplate != parser.ParseString(templateContentType.DocumentTemplate))
            {
                scope.LogPropertyUpdate("DocumentTemplate");
                existingContentType.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate);
                isDirty = true;
            }
            if (existingContentType.Name != parser.ParseString(templateContentType.Name))
            {
                scope.LogPropertyUpdate("Name");
                existingContentType.Name = parser.ParseString(templateContentType.Name);
                isDirty = true;
                // CT is being renamed, add an extra token to the tokenparser
                parser.AddToken(new ContentTypeIdToken(web, existingContentType.Name, existingContentType.StringId));
            }
            if (templateContentType.Group != null && existingContentType.Group != parser.ParseString(templateContentType.Group))
            {
                scope.LogPropertyUpdate("Group");
                existingContentType.Group = parser.ParseString(templateContentType.Group);
                isDirty = true;
            }


            if (!isNoScriptSite)
            {
                if (templateContentType.DisplayFormUrl != null && existingContentType.DisplayFormUrl != parser.ParseString(templateContentType.DisplayFormUrl))
                {
                    scope.LogPropertyUpdate("DisplayFormUrl");
                    existingContentType.DisplayFormUrl = parser.ParseString(templateContentType.DisplayFormUrl);
                    isDirty = true;
                }
                if (templateContentType.EditFormUrl != null && existingContentType.EditFormUrl != parser.ParseString(templateContentType.EditFormUrl))
                {
                    scope.LogPropertyUpdate("EditFormUrl");
                    existingContentType.EditFormUrl = parser.ParseString(templateContentType.EditFormUrl);
                    isDirty = true;
                }
                if (templateContentType.NewFormUrl != null && existingContentType.NewFormUrl != parser.ParseString(templateContentType.NewFormUrl))
                {
                    scope.LogPropertyUpdate("NewFormUrl");
                    existingContentType.NewFormUrl = parser.ParseString(templateContentType.NewFormUrl);
                    isDirty = true;
                }
            }
            else
            {
                if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DisplayFormUrl)) ||
                    !string.IsNullOrEmpty(parser.ParseString(templateContentType.EditFormUrl)) ||
                    !string.IsNullOrEmpty(parser.ParseString(templateContentType.NewFormUrl)))
                {
                    // log message
                    scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_SkipCustomFormUrls, existingContentType.Name);
                }
            }

#if !SP2013
            if (templateContentType.Name.ContainsResourceToken())
            {
                existingContentType.NameResource.SetUserResourceValue(templateContentType.Name, parser);
                isDirty = true;
            }
            if (templateContentType.Description.ContainsResourceToken())
            {
                existingContentType.DescriptionResource.SetUserResourceValue(templateContentType.Description, parser);
                isDirty = true;
            }
#endif
            if (isDirty)
            {
                existingContentType.Update(true);
                web.Context.ExecuteQueryRetry();
            }

            // Set flag to reorder fields CT fields are not equal to template fields
            var existingFieldNames = existingContentType.FieldLinks.AsEnumerable().Select(fld => fld.Name).ToArray();
            var ctFieldNames       = templateContentType.FieldRefs.Select(fld => parser.ParseString(fld.Name)).ToArray();
            reOrderFields = !existingFieldNames.SequenceEqual(ctFieldNames);

            // Delta handling
            existingContentType.EnsureProperty(c => c.FieldLinks);
            var targetIds = existingContentType.FieldLinks.AsEnumerable().Select(c1 => c1.Id).ToList();
            var sourceIds = templateContentType.FieldRefs.Select(c1 => c1.Id).ToList();

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

            if (fieldsNotPresentInTarget.Any())
            {
                // Set flag to reorder fields when new fields are added.
                reOrderFields = true;

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

            // Reorder fields
            if (reOrderFields)
            {
                existingContentType.FieldLinks.Reorder(ctFieldNames);
                isDirty = true;
            }

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

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

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

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