/// <summary> /// Instantiates the function processor. Also loads the defined add-ons /// </summary> /// <param name="page">Client side page for which we're executing the functions/selectors as part of the mapping</param> /// <param name="pageTransformation">Webpart mapping information</param> public FunctionProcessor(ClientContext sourceClientContext, ClientSidePage page, PageTransformation pageTransformation, BaseTransformationInformation baseTransformationInformation, IList <ILogObserver> logObservers = null) { this.page = page; this.pageTransformation = pageTransformation; //Register any existing observers if (logObservers != null) { foreach (var observer in logObservers) { base.RegisterObserver(observer); } } // instantiate default built in functions class this.addOnTypes = new List <AddOnType>(); this.builtInFunctions = Activator.CreateInstance(typeof(BuiltIn), baseTransformationInformation, this.page.Context, sourceClientContext, this.page, base.RegisteredLogObservers); // instantiate the custom function classes (if there are) foreach (var addOn in this.pageTransformation.AddOns) { try { string path = ""; if (addOn.Assembly.Contains("\\") && System.IO.File.Exists(addOn.Assembly)) { path = addOn.Assembly; } else { path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, addOn.Assembly); } var assembly = Assembly.LoadFile(path); var customType = assembly.GetType(addOn.Type); var instance = Activator.CreateInstance(customType, this.page.Context); this.addOnTypes.Add(new AddOnType() { Name = addOn.Name, Assembly = assembly, Instance = instance, Type = customType, }); } catch (Exception ex) { LogError(LogStrings.Error_FailedToInitiateCustomFunctionClasses, LogStrings.Heading_FunctionProcessor, ex); throw; } } }
/// <summary> /// Creates a page transformator instance /// </summary> /// <param name="sourceClientContext">ClientContext of the site holding the page</param> /// <param name="targetClientContext">ClientContext of the site that will receive the modernized page</param> /// <param name="pageTransformationModel">Page transformation model</param> public DelvePageTransformator(ClientContext sourceClientContext, ClientContext targetClientContext, PageTransformation pageTransformationModel) { this.sourceClientContext = sourceClientContext; this.targetClientContext = targetClientContext; this.version = GetVersion(); this.pageTelemetry = new PageTelemetry(version); this.pageTransformation = pageTransformationModel; }
/// <summary> /// Instantiates a web part page object /// </summary> /// <param name="page">ListItem holding the page to analyze</param> /// <param name="pageTransformation">Page transformation information</param> public WebPartPage(ListItem page, PageTransformation pageTransformation) : base(page, pageTransformation) { }
public WikiPage(ListItem page, PageTransformation pageTransformation) : base(page, pageTransformation) { this.parser = new HtmlParser(); }
/// <summary> /// Instantiates the content transformator /// </summary> /// <param name="page">Client side page that will be updates</param> /// <param name="pageTransformation">Transformation information</param> public ContentTransformator(ClientContext sourceClientContext, ClientSidePage page, PageTransformation pageTransformation, Dictionary <string, string> mappingProperties, IList <ILogObserver> logObservers = null) : base() { //Register any existing observers if (logObservers != null) { foreach (var observer in logObservers) { base.RegisterObserver(observer); } } this.page = page ?? throw new ArgumentException("Page cannot be null"); this.pageTransformation = pageTransformation ?? throw new ArgumentException("pageTransformation cannot be null"); this.globalTokens = CreateGlobalTokenList(page.Context, mappingProperties); this.functionProcessor = new FunctionProcessor(sourceClientContext, this.page, this.pageTransformation, base.RegisteredLogObservers); this.sourceClientContext = sourceClientContext; this.isCrossSiteTransfer = IsCrossSiteTransfer(); }
/// <summary> /// Page scan results log /// </summary> /// <param name="scannedSites">Scanned sites</param> /// <param name="scannedWebs">Scanned webs</param> /// <param name="pageScanResults">Scanned page results</param> /// <param name="pageTransformation">Page transformation data</param> public void LogPageScan(int scannedSites, int scannedWebs, ConcurrentDictionary <string, PageScanResult> pageScanResults, PageTransformation pageTransformation) { if (this.telemetryClient == null) { return; } try { Dictionary <string, string> properties = new Dictionary <string, string>(); Dictionary <string, double> metrics = new Dictionary <string, double>(); // Populate properties // Page transformation engine version properties.Add(EngineVersion, this.version); properties.Add(PagesResults.Sites.ToString(), scannedSites.ToString()); properties.Add(PagesResults.Webs.ToString(), scannedWebs.ToString()); properties.Add(PagesResults.Pages.ToString(), pageScanResults.Count.ToString()); // Azure AD tenant properties.Add(AADTenantId, this.aadTenantId.ToString()); // Send the event this.telemetryClient.TrackEvent(TelemetryEvents.Pages.ToString(), properties, metrics); this.telemetryClient.GetMetric($"Pages.{PagesResults.Sites.ToString()}").TrackValue(scannedSites); this.telemetryClient.GetMetric($"Pages.{PagesResults.Webs.ToString()}").TrackValue(scannedWebs); this.telemetryClient.GetMetric($"Pages.{PagesResults.Pages.ToString()}").TrackValue(pageScanResults.Count); Metric pageType = this.telemetryClient.GetMetric($"Pages.{PagesResults.PageType.ToString()}", "Pages.PageType"); Metric pageLayout = this.telemetryClient.GetMetric($"Pages.{PagesResults.PageLayout.ToString()}", "Pages.PageLayout"); Metric isHomePage = this.telemetryClient.GetMetric($"Pages.{PagesResults.IsHomePage.ToString()}", "Pages.IsHomePage"); Metric webPartMapping = this.telemetryClient.GetMetric($"Pages.{PagesResults.WebPartMapping.ToString()}", "Pages.WebPartMapping"); Metric unMappedWebParts = this.telemetryClient.GetMetric($"Pages.{PagesResults.UnMappedWebParts.ToString()}", "Pages.UnMappedWebParts"); foreach (var item in pageScanResults) { WriteMetric(pageType, item.Value.PageType); WriteMetric(pageLayout, item.Value.Layout); WriteMetric(isHomePage, item.Value.HomePage); if (item.Value.WebParts != null) { int webPartsOnPage = item.Value.WebParts.Count(); int webPartsOnPageMapped = 0; List <string> nonMappedWebParts = new List <string>(); foreach (var webPart in item.Value.WebParts.OrderBy(p => p.Row).ThenBy(p => p.Column).ThenBy(p => p.Order)) { var found = pageTransformation.WebParts.Where(p => p.Type.Equals(webPart.Type, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); if (found != null && found.Mappings != null) { webPartsOnPageMapped++; } else { var t = webPart.Type.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)[0]; if (!nonMappedWebParts.Contains(t)) { nonMappedWebParts.Add(t); } } } WriteMetric(webPartMapping, String.Format("{0:0}", (((double)webPartsOnPageMapped / (double)webPartsOnPage) * 100))); foreach (var w in nonMappedWebParts) { WriteMetric(unMappedWebParts, w); } } } } catch { // Eat all exceptions } finally { this.telemetryClient.Flush(); } }
/// <summary> /// Instantiates a wiki page object /// </summary> /// <param name="page">ListItem holding the page to analyze</param> /// <param name="pageTransformation">Page transformation information</param> public WikiPage(ListItem page, PageTransformation pageTransformation) : base(page, null, pageTransformation) { }
protected override void ExecuteCmdlet() { //Fix loading of modernization framework FixLocalAssemblyResolving(); // Load the page to transform Identity.Library = this.Library; Identity.Folder = this.Folder; ListItem page = null; if (this.PublishingPage) { this.ClientContext.Web.EnsureProperty(p => p.ServerRelativeUrl); page = Identity.GetPage(this.ClientContext.Web, CacheManager.Instance.GetPublishingPagesLibraryName(this.ClientContext)); } else { if (this.Folder == null || !this.Folder.Equals(rootFolder, StringComparison.InvariantCultureIgnoreCase)) { page = Identity.GetPage(this.ClientContext.Web, "sitepages"); } } if (page == null && !this.Folder.Equals(rootFolder, StringComparison.InvariantCultureIgnoreCase)) { throw new Exception($"Page '{Identity?.Name}' does not exist"); } // Publishing specific validation if (this.PublishingPage && string.IsNullOrEmpty(this.TargetWebUrl) && TargetConnection == null) { throw new Exception($"Publishing page transformation is only supported when transformating into another site collection. Use the -TargetWebUrl to specify a modern target site."); } // Load transformation models PageTransformation webPartMappingModel = null; if (string.IsNullOrEmpty(this.WebPartMappingFile)) { // Load xml mapping data XmlSerializer xmlMapping = new XmlSerializer(typeof(PageTransformation)); // Load the default one from resources into a model, no need for persisting this file string webpartMappingFileContents = WebPartMappingLoader.LoadFile("SharePointPnP.PowerShell.Commands.ClientSidePages.webpartmapping.xml"); using (var stream = GenerateStreamFromString(webpartMappingFileContents)) { webPartMappingModel = (PageTransformation)xmlMapping.Deserialize(stream); } this.WriteVerbose("Using embedded webpartmapping file. Use Export-PnPClientSidePageMapping to get that file in case you want to base your version of the embedded version."); } // Validate webpartmappingfile if (!string.IsNullOrEmpty(this.WebPartMappingFile)) { if (!System.IO.File.Exists(this.WebPartMappingFile)) { throw new Exception($"Provided webpartmapping file {this.WebPartMappingFile} does not exist"); } } if (this.PublishingPage && !string.IsNullOrEmpty(this.PageLayoutMapping) && !System.IO.File.Exists(this.PageLayoutMapping)) { throw new Exception($"Provided pagelayout mapping file {this.PageLayoutMapping} does not exist"); } // Create target client context (when needed) ClientContext targetContext = null; if (TargetConnection == null) { if (!string.IsNullOrEmpty(TargetWebUrl)) { targetContext = this.ClientContext.Clone(TargetWebUrl); } } else { targetContext = TargetConnection.Context; } // Create transformator instance PageTransformator pageTransformator = null; PublishingPageTransformator publishingPageTransformator = null; if (!string.IsNullOrEmpty(this.WebPartMappingFile)) { // Using custom web part mapping file if (this.PublishingPage) { if (!string.IsNullOrEmpty(this.PageLayoutMapping)) { // Using custom page layout mapping file + default one (they're merged together) publishingPageTransformator = new PublishingPageTransformator(this.ClientContext, targetContext, this.WebPartMappingFile, this.PageLayoutMapping); } else { // Using default page layout mapping file publishingPageTransformator = new PublishingPageTransformator(this.ClientContext, targetContext, this.WebPartMappingFile, null); } } else { // Use web part mapping file pageTransformator = new PageTransformator(this.ClientContext, targetContext, this.WebPartMappingFile); } } else { // Using default web part mapping file if (this.PublishingPage) { if (!string.IsNullOrEmpty(this.PageLayoutMapping)) { // Load and validate the custom mapping file PageLayoutManager pageLayoutManager = new PageLayoutManager(); var pageLayoutMappingModel = pageLayoutManager.LoadPageLayoutMappingFile(this.PageLayoutMapping); // Using custom page layout mapping file + default one (they're merged together) publishingPageTransformator = new PublishingPageTransformator(this.ClientContext, targetContext, webPartMappingModel, pageLayoutMappingModel); } else { // Using default page layout mapping file publishingPageTransformator = new PublishingPageTransformator(this.ClientContext, targetContext, webPartMappingModel, null); } } else { // Use web part mapping model loaded from embedded mapping file pageTransformator = new PageTransformator(this.ClientContext, targetContext, webPartMappingModel); } } // Setup logging if (this.LogType == ClientSidePageTransformatorLogType.File) { if (this.PublishingPage) { publishingPageTransformator.RegisterObserver(new MarkdownObserver(folder: this.LogFolder, includeVerbose: this.LogVerbose, includeDebugEntries: this.LogVerbose)); } else { pageTransformator.RegisterObserver(new MarkdownObserver(folder: this.LogFolder, includeVerbose: this.LogVerbose, includeDebugEntries: this.LogVerbose)); } } else if (this.LogType == ClientSidePageTransformatorLogType.SharePoint) { if (this.PublishingPage) { publishingPageTransformator.RegisterObserver(new MarkdownToSharePointObserver(targetContext ?? this.ClientContext, includeVerbose: this.LogVerbose, includeDebugEntries: this.LogVerbose)); } else { pageTransformator.RegisterObserver(new MarkdownToSharePointObserver(targetContext ?? this.ClientContext, includeVerbose: this.LogVerbose, includeDebugEntries: this.LogVerbose)); } } // Clear the client side component cache if (this.ClearCache) { CacheManager.Instance.ClearAllCaches(); } string serverRelativeClientPageUrl = ""; if (this.PublishingPage) { // Setup Transformation information PublishingPageTransformationInformation pti = new PublishingPageTransformationInformation(page) { Overwrite = this.Overwrite, KeepPageSpecificPermissions = !this.SkipItemLevelPermissionCopyToClientSidePage, PublishCreatedPage = !this.DontPublish, DisablePageComments = this.DisablePageComments, TargetPageName = this.PublishingTargetPageName, SkipUrlRewrite = this.SkipUrlRewriting, UrlMappingFile = this.UrlMappingFile, }; // Set mapping properties pti.MappingProperties["SummaryLinksToQuickLinks"] = (!SummaryLinksToHtml).ToString().ToLower(); pti.MappingProperties["UseCommunityScriptEditor"] = UseCommunityScriptEditor.ToString().ToLower(); serverRelativeClientPageUrl = publishingPageTransformator.Transform(pti); } else { Microsoft.SharePoint.Client.File fileToModernize = null; if (this.Folder != null && this.Folder.Equals(rootFolder, StringComparison.InvariantCultureIgnoreCase)) { // Load the page file from the site root folder var webServerRelativeUrl = this.ClientContext.Web.EnsureProperty(p => p.ServerRelativeUrl); fileToModernize = this.ClientContext.Web.GetFileByServerRelativeUrl($"{webServerRelativeUrl}/{this.Identity.Name}"); this.ClientContext.Load(fileToModernize); this.ClientContext.ExecuteQueryRetry(); } // Setup Transformation information PageTransformationInformation pti = new PageTransformationInformation(page) { SourceFile = fileToModernize, Overwrite = this.Overwrite, TargetPageTakesSourcePageName = this.TakeSourcePageName, ReplaceHomePageWithDefaultHomePage = this.ReplaceHomePageWithDefault, KeepPageSpecificPermissions = !this.SkipItemLevelPermissionCopyToClientSidePage, CopyPageMetadata = this.CopyPageMetadata, PublishCreatedPage = !this.DontPublish, DisablePageComments = this.DisablePageComments, SkipUrlRewrite = this.SkipUrlRewriting, UrlMappingFile = this.UrlMappingFile, ModernizationCenterInformation = new ModernizationCenterInformation() { AddPageAcceptBanner = this.AddPageAcceptBanner }, }; // Set mapping properties pti.MappingProperties["SummaryLinksToQuickLinks"] = (!SummaryLinksToHtml).ToString().ToLower(); pti.MappingProperties["UseCommunityScriptEditor"] = UseCommunityScriptEditor.ToString().ToLower(); serverRelativeClientPageUrl = pageTransformator.Transform(pti); } // Flush log if (this.LogType != ClientSidePageTransformatorLogType.None) { if (!this.LogSkipFlush) { if (this.PublishingPage) { publishingPageTransformator.FlushObservers(); } else { pageTransformator.FlushObservers(); } } } // Output the server relative url to the newly created page if (!string.IsNullOrEmpty(serverRelativeClientPageUrl)) { WriteObject(serverRelativeClientPageUrl); } }
/// <summary> /// Instantiates the content transformator /// </summary> /// <param name="page">Client side page that will be updates</param> /// <param name="pageTransformation">Transformation information</param> public ContentTransformator(ClientContext sourceClientContext, ClientSidePage page, PageTransformation pageTransformation, Dictionary <string, string> mappingProperties) { this.page = page ?? throw new ArgumentException("Page cannot be null"); this.pageTransformation = pageTransformation ?? throw new ArgumentException("pageTransformation cannot be null"); this.globalTokens = CreateGlobalTokenList(page.Context, mappingProperties); this.functionProcessor = new FunctionProcessor(sourceClientContext, this.page, this.pageTransformation); this.sourceClientContext = sourceClientContext; this.isCrossSiteTransfer = IsCrossSiteTransfer(); }
/// <summary> /// Instantiates a web part page object for on-premises environments /// </summary> /// <param name="page">ListItem holding the page to analyze</param> /// <param name="pageFile">File holding the page (for pages living outside of a library)</param> /// <param name="pageTransformation">Page transformation information</param> public WebPartPageOnPremises(ListItem page, File pageFile, PageTransformation pageTransformation, IList <ILogObserver> logObservers = null) : base(page, pageFile, pageTransformation, logObservers) { }
/// <summary> /// Instantiates a publishing page object /// </summary> /// <param name="page">ListItem holding the page to analyze</param> /// <param name="pageTransformation">Page transformation information</param> public PublishingPage(ListItem page, PageTransformation pageTransformation, PublishingPageTransformation publishingPageTransformation, IList <ILogObserver> logObservers = null) : base(page, pageTransformation, logObservers) { this.publishingPageTransformation = publishingPageTransformation; this.functionProcessor = new PublishingFunctionProcessor(page, cc, null, this.publishingPageTransformation, base.RegisteredLogObservers); }
/// <summary> /// Instantiates a publishing page object /// </summary> /// <param name="page">ListItem holding the page to analyze</param> /// <param name="pageTransformation">Page transformation information</param> public PublishingPage(ListItem page, PageTransformation pageTransformation, IList <ILogObserver> logObservers = null) : base(page, pageTransformation, logObservers) { // no PublishingPageTransformation specified, fall back to default this.publishingPageTransformation = new PageLayoutManager(cc, base.RegisteredLogObservers).LoadDefaultPageLayoutMappingFile(); this.functionProcessor = new PublishingFunctionProcessor(page, cc, null, this.publishingPageTransformation, base.RegisteredLogObservers); }
/// <summary> /// Creates a page transformator instance /// </summary> /// <param name="sourceClientContext">ClientContext of the site holding the page</param> /// <param name="pageTransformationModel">Page transformation model</param> public DelvePageTransformator(ClientContext sourceClientContext, PageTransformation pageTransformationModel) : this(sourceClientContext, null, pageTransformationModel) { }
public PublishingPageTransformator(ClientContext sourceClientContext, ClientContext targetClientContext, PageTransformation pageTransformationModel, PublishingPageTransformation customPublishingPageTransformationModel) { #if DEBUG && MEASURE InitMeasurement(); #endif this.sourceClientContext = sourceClientContext ?? throw new ArgumentException("sourceClientContext must be provided."); this.targetClientContext = targetClientContext ?? throw new ArgumentException("targetClientContext must be provided.");; this.version = GetVersion(); this.pageTelemetry = new PageTelemetry(version); this.pageLayoutManager = new PageLayoutManager(base.RegisteredLogObservers); this.pageTransformation = pageTransformationModel; // Load the page layout mapping data this.publishingPageTransformation = this.pageLayoutManager.LoadDefaultPageLayoutMappingFile(); // Merge these custom layout mappings with the default ones if (customPublishingPageTransformationModel != null) { this.publishingPageTransformation = this.pageLayoutManager.MergePageLayoutMappingFiles(this.publishingPageTransformation, customPublishingPageTransformationModel); } }
/// <summary> /// Instantiates the content transformator /// </summary> /// <param name="sourceClientContext"></param> /// <param name="targetClientContext"></param> /// <param name="page">Client side page that will be updates</param> /// <param name="pageTransformation">Transformation information</param> /// <param name="transformationInformation"></param> /// <param name="logObservers"></param> public ContentTransformator(ClientContext sourceClientContext, ClientContext targetClientContext, PnPCore.IPage page, PageTransformation pageTransformation, BaseTransformationInformation transformationInformation, IList <ILogObserver> logObservers = null) : base() { //Register any existing observers if (logObservers != null) { foreach (var observer in logObservers) { base.RegisterObserver(observer); } } this.page = page ?? throw new ArgumentException("Page cannot be null"); this.pageTransformation = pageTransformation ?? throw new ArgumentException("pageTransformation cannot be null"); this.globalTokens = CreateGlobalTokenList(targetClientContext, transformationInformation.MappingProperties); this.functionProcessor = new FunctionProcessor(sourceClientContext, targetClientContext, this.page, this.pageTransformation, transformationInformation, base.RegisteredLogObservers); this.transformationInformation = transformationInformation; this.sourceClientContext = sourceClientContext; this.targetClientContext = targetClientContext; this.isCrossSiteTransfer = IsCrossSiteTransfer(); }
/// <summary> /// Instantiates a publishing page object /// </summary> /// <param name="page">ListItem holding the page to analyze</param> /// <param name="pageTransformation">Page transformation information</param> public PublishingPage(ListItem page, PageTransformation pageTransformation) : base(page, pageTransformation) { }
public ContentTransformator(ClientSidePage page, PageTransformation pageTransformation) { this.page = page ?? throw new ArgumentException("Page cannot be null"); this.pageTransformation = pageTransformation ?? throw new ArgumentException("pageTransformation cannot be null"); }
/// <summary> /// Instantiates a web part page object /// </summary> /// <param name="page">ListItem holding the page to analyze</param> /// <param name="pageTransformation">Page transformation information</param> public DelvePage(ListItem page, PageTransformation pageTransformation, IList <ILogObserver> logObservers = null) : base(page, null, pageTransformation, logObservers) { }
/// <summary> /// Instantiates the function processor. Also loads the defined add-ons /// </summary> /// <param name="page">Client side page for which we're executing the functions/selectors as part of the mapping</param> /// <param name="pageTransformation">Webpart mapping information</param> public FunctionProcessor(ClientContext sourceClientContext, ClientSidePage page, PageTransformation pageTransformation) { this.page = page; this.pageTransformation = pageTransformation; // instantiate default built in functions class this.addOnTypes = new List <AddOnType>(); this.builtInFunctions = Activator.CreateInstance(typeof(BuiltIn), this.page.Context, sourceClientContext, this.page); // instantiate the custom function classes (if there are) foreach (var addOn in this.pageTransformation.AddOns) { try { string path = ""; if (addOn.Assembly.Contains("\\") && System.IO.File.Exists(addOn.Assembly)) { path = addOn.Assembly; } else { path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, addOn.Assembly); } var assembly = Assembly.LoadFile(path); var customType = assembly.GetType(addOn.Type); var instance = Activator.CreateInstance(customType, this.page.Context); this.addOnTypes.Add(new AddOnType() { Name = addOn.Name, Assembly = assembly, Instance = instance, Type = customType, }); } catch (Exception ex) { // TODO: Add logging throw; } } }
/// <summary> /// Gets the web part information from the page /// </summary> /// <param name="item">Page list item</param> /// <param name="pageTransformation">PageTransformation model loaded from XML</param> /// <returns>Page layout + collection of web parts on the page</returns> public static Tuple <PageLayout, List <WebPartEntity> > WebParts(this ListItem item, PageTransformation pageTransformation) { string pageType = item.PageType(); if (pageType.Equals("WikiPage", StringComparison.InvariantCultureIgnoreCase)) { return(new WikiPage(item, pageTransformation).Analyze()); } else if (pageType.Equals("WebPartPage", StringComparison.InvariantCultureIgnoreCase)) { return(new WebPartPage(item, null, pageTransformation).Analyze()); } else if (pageType.Equals("PublishingPage", StringComparison.InvariantCultureIgnoreCase)) { return(new PublishingPage(item, pageTransformation, null).Analyze(null)); } return(null); }
/// <summary> /// Instantiates a web part page object for on-premises environments /// </summary> /// <param name="page">ListItem holding the page to analyze</param> /// <param name="pageFile">File holding the page (for pages living outside of a library)</param> /// <param name="pageTransformation">Page transformation information</param> public WebPartPageOnPremises(ListItem page, File pageFile, PageTransformation pageTransformation) : base(page, pageFile, pageTransformation) { }
/// <summary> /// Log publishing portal scan /// </summary> /// <param name="publishingSiteScanResults">Scanned publishing portals</param> /// <param name="publishingWebScanResults">Scanned publishing webs</param> /// <param name="publishingPageScanResults">Scanned publishing pages</param> /// <param name="pageTransformation">Page transformation data</param> public void LogPublishingScan(Dictionary <string, PublishingSiteScanResult> publishingSiteScanResults, ConcurrentDictionary <string, PublishingWebScanResult> publishingWebScanResults, ConcurrentDictionary <string, PublishingPageScanResult> publishingPageScanResults, PageTransformation pageTransformation) { if (this.telemetryClient == null) { return; } try { // Prepare event data Dictionary <string, string> properties = new Dictionary <string, string>(); Dictionary <string, double> metrics = new Dictionary <string, double>(); // Populate properties // Page transformation engine version properties.Add(EngineVersion, this.version); properties.Add(PublishingResults.Sites.ToString(), publishingSiteScanResults.Count.ToString()); properties.Add(PublishingResults.Webs.ToString(), publishingWebScanResults.Count.ToString()); properties.Add(PublishingResults.Pages.ToString(), (publishingSiteScanResults != null ? publishingPageScanResults.Count : 0).ToString()); // Azure AD tenant properties.Add(AADTenantId, this.aadTenantId.ToString()); // Send the event this.telemetryClient.TrackEvent(TelemetryEvents.PublishingPortals.ToString(), properties, metrics); this.telemetryClient.GetMetric($"Publishing.{PublishingResults.Sites.ToString()}").TrackValue(publishingSiteScanResults.Count); this.telemetryClient.GetMetric($"Publishing.{PublishingResults.Webs.ToString()}").TrackValue(publishingWebScanResults.Count); this.telemetryClient.GetMetric($"Publishing.{PublishingResults.Pages.ToString()}").TrackValue(publishingSiteScanResults != null ? publishingPageScanResults.Count : 0); Metric siteLevel = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.SiteLevel.ToString()}", "Publishing.SiteLevel"); Metric complexity = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.Complexity.ToString()}", "Publishing.Complexity"); Metric webTemplates = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.WebTemplates.ToString()}", "Publishing.WebTemplates"); Metric globalNavigation = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.GlobalNavigation.ToString()}", "Publishing.GlobalNavigation"); Metric currentNavigation = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.CurrentNavigation.ToString()}", "Publishing.CurrentNavigation"); Metric customSiteMasterPage = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.CustomSiteMasterPage.ToString()}", "Publishing.CustomSiteMasterPage"); Metric customSystemMasterPage = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.CustomSystemMasterPage.ToString()}", "Publishing.CustomSystemMasterPage"); Metric alternateCSS = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.AlternateCSS.ToString()}", "Publishing.AlternateCSS"); Metric incompatibleUserCustomActions = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.IncompatibleUserCustomActions.ToString()}", "Publishing.IncompatibleUserCustomActions"); Metric customPageLayouts = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.CustomPageLayouts.ToString()}", "Publishing.CustomPageLayouts"); Metric pageApproval = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.PageApproval.ToString()}", "Publishing.PageApproval"); Metric pageApprovalWorkflow = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.PageApprovalWorkflow.ToString()}", "Publishing.PageApprovalWorkflow"); Metric scheduledPublishing = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.ScheduledPublishing.ToString()}", "Publishing.ScheduledPublishing"); Metric audienceTargeting = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.AudienceTargeting.ToString()}", "Publishing.AudienceTargeting"); Metric languages = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.Languages.ToString()}", "Publishing.Languages"); Metric variationLabels = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.VariationLabels.ToString()}", "Publishing.VariationLabels"); Metric webPartMapping = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.WebPartMapping.ToString()}", "Publishing.WebPartMapping"); Metric unMappedWebParts = this.telemetryClient.GetMetric($"Publishing.{PublishingResults.UnMappedWebParts.ToString()}", "Publishing.UnMappedWebParts"); // The metrics automatically aggregate and only send once a minute to app insights...so this approach does not result in extra traffic foreach (var item in publishingWebScanResults) { WriteMetric(siteLevel, item.Value.Level); WriteMetric(complexity, item.Value.WebClassification.ToString()); WriteMetric(webTemplates, item.Value.WebTemplate); WriteMetric(globalNavigation, item.Value.GlobalNavigationType); WriteMetric(currentNavigation, item.Value.CurrentNavigationType); WriteMetric(customSiteMasterPage, string.IsNullOrEmpty(item.Value.SiteMasterPage) ? true.ToString() : false.ToString()); WriteMetric(customSystemMasterPage, string.IsNullOrEmpty(item.Value.SystemMasterPage) ? true.ToString() : false.ToString()); WriteMetric(alternateCSS, string.IsNullOrEmpty(item.Value.AlternateCSS) ? true.ToString() : false.ToString()); WriteMetric(incompatibleUserCustomActions, item.Value.UserCustomActions); WriteMetric(pageApproval, item.Value.LibraryEnableModeration); WriteMetric(pageApprovalWorkflow, item.Value.LibraryApprovalWorkflowDefined); WriteMetric(scheduledPublishing, item.Value.LibraryItemScheduling); WriteMetric(languages, item.Value.Language); WriteMetric(variationLabels, item.Value.VariationSourceLabel); } if (publishingSiteScanResults != null) { foreach (var item in publishingPageScanResults) { WriteMetric(customPageLayouts, item.Value.PageLayoutWasCustomized); WriteMetric(audienceTargeting, (item.Value.SecurityGroupAudiences != null && item.Value.SecurityGroupAudiences.Count > 0) || (item.Value.SharePointGroupAudiences != null && item.Value.SharePointGroupAudiences.Count > 0) || (item.Value.GlobalAudiences != null && item.Value.GlobalAudiences.Count > 0)); if (item.Value.WebParts != null) { int webPartsOnPage = item.Value.WebParts.Count(); int webPartsOnPageMapped = 0; List <string> nonMappedWebParts = new List <string>(); foreach (var webPart in item.Value.WebParts.OrderBy(p => p.Row).ThenBy(p => p.Column).ThenBy(p => p.Order)) { var found = pageTransformation.WebParts.Where(p => p.Type.Equals(webPart.Type, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault(); if (found != null && found.Mappings != null) { webPartsOnPageMapped++; } else { var t = webPart.Type.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)[0]; if (!nonMappedWebParts.Contains(t)) { nonMappedWebParts.Add(t); } } } WriteMetric(webPartMapping, String.Format("{0:0}", (((double)webPartsOnPageMapped / (double)webPartsOnPage) * 100))); foreach (var w in nonMappedWebParts) { WriteMetric(unMappedWebParts, w); } } } } } catch { // Eat all exceptions } finally { this.telemetryClient.Flush(); } }
/// <summary> /// Creates a page transformator instance /// </summary> /// <param name="clientContext">ClientContext of the site holding the page</param> /// <param name="pageTransformationModel">Page transformation model</param> public PageTransformator(ClientContext clientContext, PageTransformation pageTransformationModel) { this.clientContext = clientContext; this.pageTransformation = pageTransformationModel; }
public TestBasePage(ListItem item, File file, PageTransformation pt, IList <ILogObserver> logObservers) : base(item, file, pt, logObservers) { }
/// <summary> /// Instantiates a publishing page object /// </summary> /// <param name="page">ListItem holding the page to analyze</param> /// <param name="pageTransformation">Page transformation information</param> public PublishingPageOnPremises(ListItem page, PageTransformation pageTransformation, BaseTransformationInformation baseTransformationInformation, IList <ILogObserver> logObservers = null) : base(page, pageTransformation, baseTransformationInformation, logObservers) { }
/// <summary> /// Grab the number of sites that need to be scanned...will be needed to show progress when we're having a long run /// </summary> /// <param name="addedSites">List of sites found to scan</param> /// <returns>Updated list of sites to scan</returns> public override List <string> ResolveAddedSites(List <string> addedSites) { var sites = base.ResolveAddedSites(addedSites); this.SitesToScan = sites.Count; //Perform global initialization tasks, things you only want to do once per run if (sites.Count > 0) { try { using (ClientContext cc = this.CreateClientContext(sites[0])) { // The everyone except external users claim is different per tenant, so grab the correct value this.EveryoneExceptExternalUsersClaim = cc.Web.GetEveryoneExceptExternalUsersClaim(); } } catch (Exception) { // Catch exceptions here, typical case is if the used site collection was locked. Do one more try with the root site var uri = new Uri(sites[0]); using (ClientContext cc = this.CreateClientContext($"{uri.Scheme}://{uri.DnsSafeHost}/")) { // The everyone except external users claim is different per tenant, so grab the correct value this.EveryoneExceptExternalUsersClaim = cc.Web.GetEveryoneExceptExternalUsersClaim(); } } } // Setup tenant context string tenantAdmin = ""; if (!string.IsNullOrEmpty(this.TenantAdminSite)) { tenantAdmin = this.TenantAdminSite; } else { if (string.IsNullOrEmpty(this.Tenant)) { this.Tenant = new Uri(addedSites[0]).DnsSafeHost.Split(new string[] { "." }, StringSplitOptions.RemoveEmptyEntries)[0]; } tenantAdmin = $"https://{this.Tenant}-admin.sharepoint.com"; } this.Realm = GetRealmFromTargetUrl(new Uri(tenantAdmin)); using (ClientContext ccAdmin = this.CreateClientContext(tenantAdmin)) { this.SPOTenant = new Tenant(ccAdmin); } // Load xml mapping data XmlSerializer xmlMapping = new XmlSerializer(typeof(PageTransformation)); using (var stream = new FileStream("webpartmapping.xml", FileMode.Open)) { this.PageTransformation = (PageTransformation)xmlMapping.Deserialize(stream); } return(sites); }
/// <summary> /// Instantiates a publishing page object /// </summary> /// <param name="page">ListItem holding the page to analyze</param> /// <param name="pageTransformation">Page transformation information</param> public PublishingPageOnPremises(ListItem page, PageTransformation pageTransformation, PublishingPageTransformation publishingPageTransformation, BaseTransformationInformation baseTransformationInformation, ClientContext targetContext = null, IList <ILogObserver> logObservers = null) : base(page, pageTransformation, publishingPageTransformation, baseTransformationInformation, targetContext, logObservers) { }
protected override void ExecuteCmdlet() { //Fix loading of modernization framework FixLocalAssemblyResolving(); // Load the page to transform Identity.Library = this.Library; Identity.Folder = this.Folder; Identity.BlogPage = this.BlogPage; Identity.DelveBlogPage = this.DelveBlogPage; if ((this.PublishingPage && this.BlogPage) || (this.PublishingPage && this.DelveBlogPage) || (this.BlogPage && this.DelveBlogPage)) { throw new Exception($"The page is either a blog page, a publishing page or a Delve blog page. Setting PublishingPage, BlogPage and DelveBlogPage to true is not valid."); } ListItem page = null; if (this.PublishingPage) { page = Identity.GetPage(this.ClientContext.Web, CacheManager.Instance.GetPublishingPagesLibraryName(this.ClientContext)); } else if (this.BlogPage) { // Blogs don't live in other libraries or sub folders Identity.Library = null; Identity.Folder = null; page = Identity.GetPage(this.ClientContext.Web, CacheManager.Instance.GetBlogListName(this.ClientContext)); } else if (this.DelveBlogPage) { // Blogs don't live in other libraries or sub folders Identity.Library = null; Identity.Folder = null; page = Identity.GetPage(this.ClientContext.Web, "pPg"); } else { if (this.Folder == null || !this.Folder.Equals(rootFolder, StringComparison.InvariantCultureIgnoreCase)) { page = Identity.GetPage(this.ClientContext.Web, "sitepages"); } } if (page == null && (Folder == null || !this.Folder.Equals(rootFolder, StringComparison.InvariantCultureIgnoreCase))) { throw new Exception($"Page '{Identity?.Name}' does not exist"); } // Publishing specific validation if (this.PublishingPage && string.IsNullOrEmpty(this.TargetWebUrl) && TargetConnection == null) { throw new Exception($"Publishing page transformation is only supported when transformating into another site collection. Use the -TargetWebUrl to specify a modern target site."); } // Blog specific validation if ((this.BlogPage || this.DelveBlogPage) && string.IsNullOrEmpty(this.TargetWebUrl) && TargetConnection == null) { throw new Exception($"Blog and Delve blog page transformation is only supported when transformating into another site collection. Use the -TargetWebUrl to specify a modern target site."); } // Load transformation models PageTransformation webPartMappingModel = null; if (string.IsNullOrEmpty(this.WebPartMappingFile)) { webPartMappingModel = PageTransformator.LoadDefaultWebPartMapping(); this.WriteVerbose("Using embedded webpartmapping file. Use Export-PnPClientSidePageMapping to get that file in case you want to base your version of the embedded version."); } // Validate webpartmappingfile if (!string.IsNullOrEmpty(this.WebPartMappingFile)) { if (!System.IO.File.Exists(this.WebPartMappingFile)) { throw new Exception($"Provided webpartmapping file {this.WebPartMappingFile} does not exist"); } } if (this.PublishingPage && !string.IsNullOrEmpty(this.PageLayoutMapping) && !System.IO.File.Exists(this.PageLayoutMapping)) { throw new Exception($"Provided pagelayout mapping file {this.PageLayoutMapping} does not exist"); } bool crossSiteTransformation = TargetConnection != null || !string.IsNullOrEmpty(TargetWebUrl); // Create target client context (when needed) ClientContext targetContext = null; if (TargetConnection == null) { if (!string.IsNullOrEmpty(TargetWebUrl)) { targetContext = this.ClientContext.Clone(TargetWebUrl); } } else { targetContext = TargetConnection.Context; } // Create transformator instance PageTransformator pageTransformator = null; PublishingPageTransformator publishingPageTransformator = null; if (!string.IsNullOrEmpty(this.WebPartMappingFile)) { // Using custom web part mapping file if (this.PublishingPage) { if (!string.IsNullOrEmpty(this.PageLayoutMapping)) { // Using custom page layout mapping file + default one (they're merged together) publishingPageTransformator = new PublishingPageTransformator(this.ClientContext, targetContext, this.WebPartMappingFile, this.PageLayoutMapping); } else { // Using default page layout mapping file publishingPageTransformator = new PublishingPageTransformator(this.ClientContext, targetContext, this.WebPartMappingFile, null); } } else { // Use web part mapping file pageTransformator = new PageTransformator(this.ClientContext, targetContext, this.WebPartMappingFile); } } else { // Using default web part mapping file if (this.PublishingPage) { if (!string.IsNullOrEmpty(this.PageLayoutMapping)) { // Load and validate the custom mapping file PageLayoutManager pageLayoutManager = new PageLayoutManager(); var pageLayoutMappingModel = pageLayoutManager.LoadPageLayoutMappingFile(this.PageLayoutMapping); // Using custom page layout mapping file + default one (they're merged together) publishingPageTransformator = new PublishingPageTransformator(this.ClientContext, targetContext, webPartMappingModel, pageLayoutMappingModel); } else { // Using default page layout mapping file publishingPageTransformator = new PublishingPageTransformator(this.ClientContext, targetContext, webPartMappingModel, null); } } else { // Use web part mapping model loaded from embedded mapping file pageTransformator = new PageTransformator(this.ClientContext, targetContext, webPartMappingModel); } } // Setup logging if (this.LogType == PageTransformatorLogType.File) { if (this.PublishingPage) { publishingPageTransformator.RegisterObserver(new MarkdownObserver(folder: this.LogFolder, includeVerbose: this.LogVerbose, includeDebugEntries: this.LogVerbose)); } else { pageTransformator.RegisterObserver(new MarkdownObserver(folder: this.LogFolder, includeVerbose: this.LogVerbose, includeDebugEntries: this.LogVerbose)); } } else if (this.LogType == PageTransformatorLogType.SharePoint) { if (this.PublishingPage) { publishingPageTransformator.RegisterObserver(new MarkdownToSharePointObserver(targetContext ?? this.ClientContext, includeVerbose: this.LogVerbose, includeDebugEntries: this.LogVerbose)); } else { pageTransformator.RegisterObserver(new MarkdownToSharePointObserver(targetContext ?? this.ClientContext, includeVerbose: this.LogVerbose, includeDebugEntries: this.LogVerbose)); } } else if (this.LogType == PageTransformatorLogType.Console) { if (this.PublishingPage) { publishingPageTransformator.RegisterObserver(new ConsoleObserver(includeDebugEntries: this.LogVerbose)); } else { pageTransformator.RegisterObserver(new ConsoleObserver(includeDebugEntries: this.LogVerbose)); } } // Clear the client side component cache if (this.ClearCache) { CacheManager.Instance.ClearAllCaches(); } string serverRelativeClientPageUrl = ""; if (this.PublishingPage) { // Setup Transformation information PublishingPageTransformationInformation pti = new PublishingPageTransformationInformation(page) { Overwrite = this.Overwrite, KeepPageSpecificPermissions = !this.SkipItemLevelPermissionCopyToClientSidePage, PublishCreatedPage = !this.DontPublish, KeepPageCreationModificationInformation = this.KeepPageCreationModificationInformation, PostAsNews = this.PostAsNews, DisablePageComments = this.DisablePageComments, TargetPageName = !string.IsNullOrEmpty(this.PublishingTargetPageName) ? this.PublishingTargetPageName : this.TargetPageName, SkipUrlRewrite = this.SkipUrlRewriting, SkipDefaultUrlRewrite = this.SkipDefaultUrlRewriting, UrlMappingFile = this.UrlMappingFile, AddTableListImageAsImageWebPart = this.AddTableListImageAsImageWebPart, SkipUserMapping = this.SkipUserMapping, UserMappingFile = this.UserMappingFile, LDAPConnectionString = this.LDAPConnectionString, TargetPageFolder = this.TargetPageFolder, TargetPageFolderOverridesDefaultFolder = this.TargetPageFolderOverridesDefaultFolder, TermMappingFile = TermMappingFile, SkipTermStoreMapping = SkipTermStoreMapping, RemoveEmptySectionsAndColumns = this.RemoveEmptySectionsAndColumns, SkipHiddenWebParts = this.SkipHiddenWebParts, }; // Set mapping properties pti.MappingProperties["SummaryLinksToQuickLinks"] = (!SummaryLinksToHtml).ToString().ToLower(); pti.MappingProperties["UseCommunityScriptEditor"] = UseCommunityScriptEditor.ToString().ToLower(); try { serverRelativeClientPageUrl = publishingPageTransformator.Transform(pti); } finally { // Flush log if (this.LogType != PageTransformatorLogType.None && this.LogType != PageTransformatorLogType.Console && !this.LogSkipFlush) { publishingPageTransformator.FlushObservers(); } } } else { Microsoft.SharePoint.Client.File fileToModernize = null; if (this.Folder != null && this.Folder.Equals(rootFolder, StringComparison.InvariantCultureIgnoreCase)) { // Load the page file from the site root folder var webServerRelativeUrl = this.ClientContext.Web.EnsureProperty(p => p.ServerRelativeUrl); fileToModernize = this.ClientContext.Web.GetFileByServerRelativeUrl($"{webServerRelativeUrl}/{this.Identity.Name}"); this.ClientContext.Load(fileToModernize); this.ClientContext.ExecuteQueryRetry(); } // Setup Transformation information PageTransformationInformation pti = new PageTransformationInformation(page) { SourceFile = fileToModernize, Overwrite = this.Overwrite, TargetPageTakesSourcePageName = this.TakeSourcePageName, ReplaceHomePageWithDefaultHomePage = this.ReplaceHomePageWithDefault, KeepPageSpecificPermissions = !this.SkipItemLevelPermissionCopyToClientSidePage, CopyPageMetadata = this.CopyPageMetadata, PublishCreatedPage = !this.DontPublish, KeepPageCreationModificationInformation = this.KeepPageCreationModificationInformation, SetAuthorInPageHeader = this.SetAuthorInPageHeader, PostAsNews = this.PostAsNews, DisablePageComments = this.DisablePageComments, TargetPageName = crossSiteTransformation ? this.TargetPageName : "", SkipUrlRewrite = this.SkipUrlRewriting, SkipDefaultUrlRewrite = this.SkipDefaultUrlRewriting, UrlMappingFile = this.UrlMappingFile, AddTableListImageAsImageWebPart = this.AddTableListImageAsImageWebPart, SkipUserMapping = this.SkipUserMapping, UserMappingFile = this.UserMappingFile, LDAPConnectionString = this.LDAPConnectionString, TargetPageFolder = this.TargetPageFolder, TargetPageFolderOverridesDefaultFolder = this.TargetPageFolderOverridesDefaultFolder, ModernizationCenterInformation = new ModernizationCenterInformation() { AddPageAcceptBanner = this.AddPageAcceptBanner }, TermMappingFile = TermMappingFile, SkipTermStoreMapping = SkipTermStoreMapping, RemoveEmptySectionsAndColumns = this.RemoveEmptySectionsAndColumns, SkipHiddenWebParts = this.SkipHiddenWebParts, }; // Set mapping properties pti.MappingProperties["SummaryLinksToQuickLinks"] = (!SummaryLinksToHtml).ToString().ToLower(); pti.MappingProperties["UseCommunityScriptEditor"] = UseCommunityScriptEditor.ToString().ToLower(); try { serverRelativeClientPageUrl = pageTransformator.Transform(pti); } finally { // Flush log if (this.LogType != PageTransformatorLogType.None && this.LogType != PageTransformatorLogType.Console && !this.LogSkipFlush) { pageTransformator.FlushObservers(); } } } // Output the server relative url to the newly created page if (!string.IsNullOrEmpty(serverRelativeClientPageUrl)) { WriteObject(serverRelativeClientPageUrl); } }
/// <summary> /// Instantiates a publishing page object /// </summary> /// <param name="page">ListItem holding the page to analyze</param> /// <param name="pageTransformation">Page transformation information</param> public PublishingPage(ListItem page, PageTransformation pageTransformation, PublishingPageTransformation publishingPageTransformation, BaseTransformationInformation baseTransformationInformation, ClientContext targetContext = null, IList <ILogObserver> logObservers = null) : base(page, pageTransformation, logObservers) { this.publishingPageTransformation = publishingPageTransformation; this.functionProcessor = new PublishingFunctionProcessor(page, cc, targetContext, this.publishingPageTransformation, baseTransformationInformation, base.RegisteredLogObservers); }