using System; using System.Globalization; using System.IO; using System.Linq; using System.Threading; using System.Web.UI.WebControls.WebParts; using System.Xml; using Microsoft.SharePoint; using Microsoft.SharePoint.Deployment; using Microsoft.SharePoint.Navigation; using Microsoft.SharePoint.Publishing; using Microsoft.SharePoint.Publishing.Navigation; using Microsoft.SharePoint.Utilities; using Microsoft.SharePoint.WebPartPages; using Taloyhtio.CondoUpdate.Common; using WebPart = System.Web.UI.WebControls.WebParts.WebPart; namespace CondoUpdate.AddPelsuPage { public class UpdaterImpl:ICondoUpdater { private readonly Guid PELSU_WEB_FEATURE_ID = new Guid("3cc89ee5-ef67-418d-a656-7c3c6925714f"); public event EventHandler OnNotify; public void Update(object args) { string url = args as string; if (string.IsNullOrEmpty(url)) { this.warn("Url is empty"); return; } try { this.updateImpl(url); } catch (Exception x) { this.error("Error occured during updating of Condo '{0}':\n{1}\n{2}", url, x.Message, x.StackTrace); } } private void updateImpl(string url) { try { using (var site = new SPSite(url)) { using (var web = site.OpenWeb()) { if (!web.Exists) { return; } if (!PublishingWeb.IsPublishingWeb(web)) { return; } Thread.CurrentThread.CurrentUICulture = new CultureInfo((int)web.Language); if (!web.Features.Cast().Any(f => f.DefinitionId == PELSU_WEB_FEATURE_ID)) { web.Features.Add(PELSU_WEB_FEATURE_ID); } } } } catch (Exception ex) { this.error("Error occured when update '{0}' site:\n{1}\n{2}", url, ex.Message, ex.StackTrace); } } // 2018-10-09: old approach /* private void updateImpl(string url) { string sourceSiteUrl = "http://taloyhtio.mobimus.com/demo/Ristijaakko"; string targetSiteUrl = url; string pageName = "pelsu.aspx"; string pageTitle = "Pelastussuunnitelma"; string fileToImport = "ExportedPage.cmp"; if (!this.import(sourceSiteUrl, targetSiteUrl, pageName, fileToImport)) { this.warn("Import was not performed. Web site will be skipped"); return; } this.fixPageLayout(url, pageName); this.changeGlobalNavigation(url, pageName, pageTitle); } private void fixPageLayout(string url, string pageName) { using (var site = new SPSite(url)) { using (var web = site.OpenWeb()) { var pweb = PublishingWeb.GetPublishingWeb(web); try { //this.info("Get start page"); var item = pweb.PagesList.Items.Cast().FirstOrDefault( i => { return (i.File != null && string.Compare(i.File.Name, pageName, true) == 0); }); if (item == null) { this.error("Page '{0}' not found on web '{1}'", pageName, pweb.Url); return; } var file = item.File; if (file == null) { this.error("Page is null. Site won't be updated"); return; } if (file.CheckOutStatus == SPFile.SPCheckOutStatus.None) { //this.info("Checkout start page"); file.CheckOut(); } else { // if file was checked out by another user, need undo check out and check in again in order to avoid errors // when add web part //this.info("Start page is already checked out. Undo previous check out and check out it again"); file.UndoCheckOut(); file.CheckOut(); } file.Item["PublishingPageLayout"] = SPUrlUtility.CombineUrl(site.ServerRelativeUrl, "_catalogs/masterpage/TaloyhtioLayout.aspx"); file.Item.Update(); //this.info("Checkin file"); file.Update(); file.CheckIn("Update web parts"); if (file.Item.ParentList.EnableMinorVersions) { file.Publish("Update web parts"); } //this.info("Web part was sucessfully updated"); } catch (Exception x) { this.error("Error occured when update web part on '{0}' site:\n{1}\n{2}", pweb.Web.Url, x.Message, x.StackTrace); var file = pweb.DefaultPage; if (file.CheckOutStatus != SPFile.SPCheckOutStatus.None) { file.UndoCheckOut(); } } } } } private void changeGlobalNavigation(string url, string pageName, string pageTitle) { using (var site = new SPSite(url)) { using (var web = site.OpenWeb()) { var pweb = PublishingWeb.GetPublishingWeb(web); var globalNavigation = pweb.Navigation.GlobalNavigationNodes; //string title = pageName.Replace(".aspx", ""); var nodePage = globalNavigation.Cast().FirstOrDefault(n => n.Title == pageTitle); if (nodePage != null) { this.warn("Navigation node already exists for page '{0}'", pageName); return; } var page = pweb.GetPublishingPages().FirstOrDefault(p => string.Compare(p.Name, pageName, true) == 0); if (page != null) { page.IncludeInGlobalNavigation = false; page.IncludeInCurrentNavigation = false; } var node = createNode(pageTitle, page.Url, globalNavigation, ""); SPNavigationNode previousNode = null; int akatemiaIdx = -1; var nodes = globalNavigation.Cast().ToArray(); for (int i = 0; i < nodes.Length; i++) { if (nodes[i].Title == "Taloyhtio.Info Akatemia") { akatemiaIdx = i; break; } } if (akatemiaIdx > 0) { previousNode = nodes[akatemiaIdx - 1]; } else if (akatemiaIdx == 0) { previousNode = nodes[akatemiaIdx]; } //var nodeSite = globalNavigation.Cast().FirstOrDefault(n => n.Title == "Taloyhtio.Info Akatemia"); if (previousNode != null) { node.Move(globalNavigation, previousNode); } else { this.warn("Navigation node for Taloyhtio.Info Akatemia not found for page '{0}'. Node position won't be changed", pageName); } } } } private SPNavigationNode createNode(string targetTitle, string targetUrl, SPNavigationNodeCollection globalNavigation, string target) { var node = SPNavigationSiteMapNode.CreateSPNavigationNode(targetTitle, targetUrl, NodeTypes.AuthoredLinkPlain, globalNavigation); var dt = DateTime.Now; node.Properties["CreatedDate"] = dt; node.Properties["LastModifiedDate"] = dt; node.Properties["Description"] = ""; node.Properties["Target"] = target; node.Update(); return node; } private bool import(string sourceSiteUrl, string targetSiteUrl, string pageName, string fileToImport) { using (var targetSite = new SPSite(targetSiteUrl)) { using (var targetWeb = targetSite.OpenWeb()) { var targetList = targetWeb.Lists.Cast().FirstOrDefault(l => l.Title == "Sivut"); var item = targetList.Items.Cast().FirstOrDefault( i => { return (i.File != null && string.Compare(i.File.Name, pageName, true) == 0); }); if (item != null) { this.warn("Page '{0}' already exists on web '{1}'", pageName, targetWeb.Url); return false; } using (var sourceSite = new SPSite(sourceSiteUrl)) { using (var sourceWeb = sourceSite.OpenWeb()) { var sourcePweb = PublishingWeb.GetPublishingWeb(sourceWeb); var targetPweb = PublishingWeb.GetPublishingWeb(targetWeb); return importImpl(targetWeb.Url, sourcePweb.PagesList.RootFolder.ServerRelativeUrl, targetPweb.PagesList.RootFolder.ServerRelativeUrl, pageName, fileToImport); } } } } } private bool importImpl(string fullTargetWebURL, string sourceItemParentUrl, string destinationItemParentUrl, string pageName, string fileToImport) { if (!File.Exists(fileToImport)) { this.error("File '{0}' not found", fileToImport); return false; } var importSettings = new SPImportSettings(); importSettings.BaseFileName = fileToImport; importSettings.FileLocation = Directory.GetCurrentDirectory(); importSettings.SiteUrl = fullTargetWebURL; importSettings.RetainObjectIdentity = false; importSettings.IncludeSecurity = SPIncludeSecurity.None; importSettings.UpdateVersions = SPUpdateVersions.Append; importSettings.UserInfoDateTime = SPImportUserInfoDateTimeOption.ImportAll; importSettings.FileCompression = true; importSettings.CommandLineVerbose = true; importSettings.Validate(); var import = new SPImport(importSettings); bool importCompeted = false; string importErrorMessage = ""; import.Started += (s, e) => { if (e.RootObjects == null) return; var rootObjects = e.RootObjects; foreach (SPImportObject item in rootObjects) { this.info(" Check import object: SourceUrl = {0}, TargetParentUrl = {1}", item.SourceUrl, item.TargetParentUrl); if (string.Compare(item.TargetParentUrl, sourceItemParentUrl + "/", true) == 0 || (item.SourceUrl.Contains("/" + pageName) && (item.Type == SPDeploymentObjectType.ListItem || item.Type == SPDeploymentObjectType.File))) { this.info(" Retarget item TargetParentUrl url from '{0}' to '{1}'", item.TargetParentUrl, destinationItemParentUrl + "/"); item.TargetParentUrl = destinationItemParentUrl + "/"; } } }; import.Error += (s, e) => { importErrorMessage = e.ErrorMessage; importCompeted = true; }; import.Completed += (s, e) => { importCompeted = true; }; //Log.Comment("Starting import to URL {0}", siteURL); importCompeted = false;//not thread safe but we dont need to be thread safe importErrorMessage = null; import.Run(); while (!importCompeted) { Thread.Sleep(1000); } if (importErrorMessage != null) { this.info("Problem occured during importing of " + sourceItemParentUrl + " and export file " + fileToImport + " " + importErrorMessage); return false; } return true; } */ private void info(string msg, params object[] args) { this.notify(LogLevel.Info, msg, args); } private void warn(string msg, params object[] args) { this.notify(LogLevel.Warn, msg, args); } private void error(string msg, params object[] args) { this.notify(LogLevel.Error, msg, args); } private void notify(LogLevel level, string msg, params object[] args) { this.notify(level, string.Format(msg, args)); } private void notify(LogLevel level, string msg) { if (this.OnNotify != null) { this.OnNotify(this, new LogEventArgs { LogLevel = level, Message = msg }); } } } }