/// <summary> /// Compares master page URL, theme URL and font URL values to current theme entity to check if they are the same. /// Handles also possible null values. Point is to figure out which theme is the one that is currently /// being selected as "Current" /// </summary> /// <param name="theme">Current theme entity to compare values to</param> /// <param name="masterPageUrl">Master page URL</param> /// <param name="themeUrl">Theme URL</param> /// <param name="fontUrl">Font URL</param> /// <returns></returns> private static bool IsMatchingTheme(ThemeEntity theme, string masterPageUrl, string themeUrl, string fontUrl) { bool themeUrlHasValue = false, fontUrlHasValue = false; //Is Masterpage Url meaningful for compare? var masterPageUrlHasValue = !string.IsNullOrEmpty(theme.MasterPage); // Is theme URL meaningful for compare? if (!string.IsNullOrEmpty(theme.Theme)) { themeUrlHasValue = true; } // Is font URL meaningful for compare? if (!string.IsNullOrEmpty(theme.Font)) { fontUrlHasValue = true; } // Should we compare all of the values? if (masterPageUrlHasValue && themeUrlHasValue && fontUrlHasValue) { if (!string.IsNullOrEmpty(theme.MasterPage) && theme.MasterPage.Equals(masterPageUrl, StringComparison.InvariantCultureIgnoreCase) && theme.Theme.Equals(themeUrl, StringComparison.InvariantCultureIgnoreCase) && theme.Font.Equals(fontUrl, StringComparison.InvariantCultureIgnoreCase)) { return true; } } // Should we compare only master page and theme URL? if (masterPageUrlHasValue && themeUrlHasValue && !fontUrlHasValue) { if (!string.IsNullOrEmpty(theme.MasterPage) && theme.MasterPage.Equals(masterPageUrl, StringComparison.InvariantCultureIgnoreCase) && theme.Theme.Equals(themeUrl, StringComparison.InvariantCultureIgnoreCase)) { return true; } } // Should we compare only master page and font value? if (masterPageUrlHasValue && !themeUrlHasValue && fontUrlHasValue) { if (!string.IsNullOrEmpty(theme.MasterPage) && theme.MasterPage.Equals(masterPageUrl, StringComparison.InvariantCultureIgnoreCase) && theme.Font.Equals(fontUrl, StringComparison.InvariantCultureIgnoreCase)) { return true; } } // Should we only compare master page if (masterPageUrlHasValue && !themeUrlHasValue && !fontUrlHasValue) { if (!string.IsNullOrEmpty(theme.MasterPage) && theme.MasterPage.Equals(masterPageUrl, StringComparison.InvariantCultureIgnoreCase)) { return true; } } return false; }
/// <summary> /// Returns the named composed look from the web gallery /// </summary> /// <param name="web">Web to check</param> /// <param name="composedLookName">Name of the composed look to retrieve</param> /// <returns>Entity with the attributes of the composed look, or null if the composed look does not exists or cannot be determined</returns> public static ThemeEntity GetComposedLook(this Web web, string composedLookName) { // List of OOB composed looks List<string> defaultComposedLooks = new List<string>(new string[] { "Orange", "Sea Monster", "Green", "Lime", "Nature", "Blossom", "Sketch", "City", "Orbit", "Grey", "Characters", "Office", "Breeze", "Immerse", "Red", "Purple", "Wood" }); // ThemeEntity object that will be ThemeEntity theme = null; List designCatalog = web.GetCatalog((int)ListTemplateType.DesignCatalog); const string camlString = @" <View> <Query> </Query> <OrderBy> <FieldRef Name='Modified' /> </OrderBy> <ViewFields> <FieldRef Name='Name' /> <FieldRef Name='ImageUrl' /> <FieldRef Name='MasterPageUrl' /> <FieldRef Name='FontSchemeUrl' /> <FieldRef Name='ThemeUrl' /> </ViewFields> </View>"; CamlQuery camlQuery = new CamlQuery(); camlQuery.ViewXml = camlString; ListItemCollection themes = designCatalog.GetItems(camlQuery); web.Context.Load(themes); web.Context.Load(web, w => w.Url); web.Context.ExecuteQueryRetry(); string siteCollectionUrl = ""; string subSitePath = ""; using (ClientContext cc = web.Context.Clone(web.Url)) { cc.Load(cc.Site, s => s.Url); cc.ExecuteQueryRetry(); siteCollectionUrl = cc.Site.Url; subSitePath = web.Url.Replace(siteCollectionUrl, ""); } if (themes.Count > 0) { List<string> customComposedLooks = new List<string>(); // Iterate over the existing composed looks to figure out the current composed look foreach (var themeItem in themes) { string masterPageUrl = null; string themeUrl = null; string imageUrl = null; string fontUrl = null; string name = null; if (themeItem["MasterPageUrl"] != null && themeItem["MasterPageUrl"].ToString().Length > 0) { masterPageUrl = (themeItem["MasterPageUrl"] as FieldUrlValue).Url; } if (themeItem["ImageUrl"] != null && themeItem["ImageUrl"].ToString().Length > 0) { imageUrl = (themeItem["ImageUrl"] as FieldUrlValue).Url; } if (themeItem["FontSchemeUrl"] != null && themeItem["FontSchemeUrl"].ToString().Length > 0) { fontUrl = (themeItem["FontSchemeUrl"] as FieldUrlValue).Url; } if (themeItem["ThemeUrl"] != null && themeItem["ThemeUrl"].ToString().Length > 0) { themeUrl = (themeItem["ThemeUrl"] as FieldUrlValue).Url; } if (themeItem["Name"] != null && themeItem["Name"].ToString().Length > 0) { name = themeItem["Name"] as String; } if (name != null) { if (!name.Equals(CurrentLookName, StringComparison.InvariantCultureIgnoreCase) && !defaultComposedLooks.Contains(name)) { customComposedLooks.Add(name); } if (name.Equals(composedLookName, StringComparison.InvariantCultureIgnoreCase)) { theme = new ThemeEntity(); if (themeItem["ThemeUrl"] != null && themeItem["ThemeUrl"].ToString().Length > 0) { theme.Theme = (themeItem["ThemeUrl"] as FieldUrlValue).Url; } if (themeItem["MasterPageUrl"] != null && themeItem["MasterPageUrl"].ToString().Length > 0) { theme.MasterPage = (themeItem["MasterPageUrl"] as FieldUrlValue).Url; } if (themeItem["FontSchemeUrl"] != null && themeItem["FontSchemeUrl"].ToString().Length > 0) { theme.Font = (themeItem["FontSchemeUrl"] as FieldUrlValue).Url; } if (themeItem["ImageUrl"] != null && themeItem["ImageUrl"].ToString().Length > 0) { theme.BackgroundImage = (themeItem["ImageUrl"] as FieldUrlValue).Url; } } } } // return here if we did not find the requested theme...it does not exist. if (theme == null) { return theme; } // For a brand new clean site everything is null. Once you apply another OOB composed look and then re-apply the default // Office composed look the theme information will be populated. if (theme.BackgroundImage == null && theme.Font == null && theme.MasterPage == null && theme.Theme == null && web.IsUsingOfficeTheme()) { theme.Name = "Office"; theme.MasterPage = String.Format("{0}/_catalogs/masterpage/seattle.master", subSitePath); theme.Theme = "/_catalogs/theme/15/palette001.spcolor"; theme.IsCustomComposedLook = false; } else { // Loop over the defined composed look and get the one that matches the information gathered from the "current" composed look foreach (var themeItem in themes) { string masterPageUrl = null; string themeUrl = null; string imageUrl = null; string fontUrl = null; string name = ""; if (themeItem["MasterPageUrl"] != null && themeItem["MasterPageUrl"].ToString().Length > 0) { masterPageUrl = (themeItem["MasterPageUrl"] as FieldUrlValue).Url; } if (themeItem["ImageUrl"] != null && themeItem["ImageUrl"].ToString().Length > 0) { imageUrl = (themeItem["ImageUrl"] as FieldUrlValue).Url; } if (themeItem["FontSchemeUrl"] != null && themeItem["FontSchemeUrl"].ToString().Length > 0) { fontUrl = (themeItem["FontSchemeUrl"] as FieldUrlValue).Url; } if (themeItem["ThemeUrl"] != null && themeItem["ThemeUrl"].ToString().Length > 0) { themeUrl = (themeItem["ThemeUrl"] as FieldUrlValue).Url; } if (themeItem["Name"] != null && themeItem["Name"].ToString().Length > 0) { name = themeItem["Name"] as String; } // Note: do not take in account the ImageUrl field as this will point to a copied image in case of a sub site if ((masterPageUrl == null || theme.MasterPage == null || theme.MasterPage.Equals(masterPageUrl, StringComparison.InvariantCultureIgnoreCase)) && (fontUrl == null || theme.Font == null || theme.Font.Equals(fontUrl, StringComparison.InvariantCultureIgnoreCase)) && (themeUrl == null || theme.Theme == null || theme.Theme.Equals(themeUrl, StringComparison.InvariantCultureIgnoreCase))) { theme.Name = name; theme.IsCustomComposedLook = !defaultComposedLooks.Contains(theme.Name); // Restore the default composed look image url if (imageUrl != null) { theme.BackgroundImage = imageUrl; } // We're taking the first matching composed look break; } } // special case, theme files have been deployed via api and when applying the proper theme the "current" was not set if (theme.Name.Equals(CurrentLookName, StringComparison.InvariantCultureIgnoreCase)) { if (!web.IsUsingOfficeTheme()) { // Assume the the last added custom theme is what the site is using for (int i = themes.Count; i-- > 0;) { var themeItem = themes[i]; if (themeItem["Name"] != null && customComposedLooks.Contains(themeItem["Name"] as string)) { if (themeItem["ThemeUrl"] != null && themeItem["ThemeUrl"].ToString().Length > 0) { theme.Theme = (themeItem["ThemeUrl"] as FieldUrlValue).Url; } if (themeItem["MasterPageUrl"] != null && themeItem["MasterPageUrl"].ToString().Length > 0) { theme.MasterPage = (themeItem["MasterPageUrl"] as FieldUrlValue).Url; } if (themeItem["FontSchemeUrl"] != null && themeItem["FontSchemeUrl"].ToString().Length > 0) { theme.Font = (themeItem["FontSchemeUrl"] as FieldUrlValue).Url; } if (themeItem["ImageUrl"] != null && themeItem["ImageUrl"].ToString().Length > 0) { theme.BackgroundImage = (themeItem["ImageUrl"] as FieldUrlValue).Url; } if (themeItem["Name"] != null && themeItem["Name"].ToString().Length > 0) { theme.Name = themeItem["Name"] as String; } theme.IsCustomComposedLook = true; break; } } } } } } if (theme == null) { return theme; } String designPreviewThemedCssFolderUrl = web.GetPropertyBagValueString("DesignPreviewThemedCssFolderUrl", null); // If name still is "Current" and there isn't a PreviewThemedCssFolderUrl // property in the property bag then we can't correctly determine the set // composed look...so return null if (theme.Name.Equals(CurrentLookName, StringComparison.InvariantCultureIgnoreCase) && String.IsNullOrEmpty(designPreviewThemedCssFolderUrl)) { return null; } // Clean up the fully qualified urls if (theme.BackgroundImage != null && theme.BackgroundImage.IndexOf(siteCollectionUrl, StringComparison.InvariantCultureIgnoreCase) > -1) { theme.BackgroundImage = theme.BackgroundImage.Replace(siteCollectionUrl, ""); } if (theme.Theme != null && theme.Theme.IndexOf(siteCollectionUrl, StringComparison.InvariantCultureIgnoreCase) > -1) { theme.Theme = theme.Theme.Replace(siteCollectionUrl, ""); } if (theme.Font != null && theme.Font.IndexOf(siteCollectionUrl, StringComparison.InvariantCultureIgnoreCase) > -1) { theme.Font = theme.Font.Replace(siteCollectionUrl, ""); } if (theme.MasterPage != null && theme.MasterPage.IndexOf(siteCollectionUrl, StringComparison.InvariantCultureIgnoreCase) > -1) { theme.MasterPage = theme.MasterPage.Replace(siteCollectionUrl, ""); } return theme; }
/// <summary> /// Returns the named composed look from the web gallery /// </summary> /// <param name="web">Web to check</param> /// <param name="composedLookName">Name of the composed look to retrieve</param> /// <returns>Entity with the attributes of the composed look, or null if it does not exist</returns> public static ThemeEntity GetComposedLook(this Web web, string composedLookName) { ThemeEntity theme = null; List designCatalog = web.GetCatalog((int)ListTemplateType.DesignCatalog); string camlString = @" <View> <Query> <Where><Eq><FieldRef Name='Name' /><Value Type='Text'>{0}</Value></Eq></Where> </Query> <ViewFields> <FieldRef Name='ImageUrl' /> <FieldRef Name='MasterPageUrl' /> <FieldRef Name='FontSchemeUrl' /> <FieldRef Name='ThemeUrl' /> </ViewFields> </View>"; CamlQuery camlQuery = new CamlQuery(); camlQuery.ViewXml = string.Format(camlString, composedLookName); ListItemCollection themes = designCatalog.GetItems(camlQuery); web.Context.Load(themes); web.Context.ExecuteQuery(); if (themes.Count > 0) { var themeItem = themes[0]; theme = new ThemeEntity(); if (themeItem["ThemeUrl"] != null && themeItem["ThemeUrl"].ToString().Length > 0) { theme.Theme = (themeItem["ThemeUrl"] as FieldUrlValue).Url; } if (themeItem["MasterPageUrl"] != null && themeItem["MasterPageUrl"].ToString().Length > 0) { theme.MasterPage = (themeItem["MasterPageUrl"] as FieldUrlValue).Url; } if (themeItem["FontSchemeUrl"] != null && themeItem["FontSchemeUrl"].ToString().Length > 0) { theme.Font = (themeItem["FontSchemeUrl"] as FieldUrlValue).Url; } if (themeItem["ImageUrl"] != null && themeItem["ImageUrl"].ToString().Length > 0) { theme.BackgroundImage = (themeItem["ImageUrl"] as FieldUrlValue).Url; } } return theme; }