Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -350,4 +350,6 @@ MigrationBackup/
.ionide/

# mac OS
.ds_store
.ds_store

.idea/
114 changes: 114 additions & 0 deletions src/PnP.Scanning/PnP.Scanning.Core/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,119 @@ internal static class Constants
#region PnPContext properties
internal const string PnPContextPropertyScanId = "ScanId";
#endregion

#region Classic WebParts Without Proper Property Mappings
/// <summary>
/// Classic SharePoint web part types that do not have proper property mappings to modern client side web parts
/// </summary>
internal static readonly string[] ClassicWebPartsWithoutProperMappings = new[]
{
// Search Web Parts (minimal or no property mappings)
"Microsoft.Office.Server.Search.WebControls.SearchNavigationWebPart",
"Microsoft.Office.Server.Search.WebControls.CatalogItemReuseWebPart",
"Microsoft.Office.Server.Search.WebControls.TaxonomyRefinementScriptWebPart",
"Microsoft.Office.Server.Search.WebControls.AdvancedSearchBox",
"Microsoft.Office.Server.Search.WebControls.SearchBoxScriptWebPart",
"Microsoft.Office.Server.Search.WebControls.RefinementScriptWebPart",

// SharePoint Portal WebControls (no mappings)
"Microsoft.SharePoint.Portal.WebControls.SiteDocuments",
"Microsoft.SharePoint.Portal.WebControls.RSSAggregatorWebPart",
"Microsoft.SharePoint.Portal.WebControls.SocialCommentWebPart",
"Microsoft.SharePoint.Portal.WebControls.ProfileBrowser",
"Microsoft.SharePoint.Portal.WebControls.TagCloudWebPart",

// Project Site Web Parts (no mappings)
"Microsoft.SharePoint.Portal.WebControls.ProjectSummaryWebPart",

// KPI Web Parts (no mappings)
"Microsoft.SharePoint.Portal.WebControls.IndicatorWebpart",
"Microsoft.SharePoint.Portal.WebControls.KPIListWebPart",

// Community Site Web Parts (no mappings)
"Microsoft.SharePoint.Portal.WebControls.CommunityAdminWebPart",
"Microsoft.SharePoint.Portal.WebControls.CommunityJoinWebPart",
"Microsoft.SharePoint.Portal.WebControls.DashboardWebPart",
"Microsoft.SharePoint.Portal.WebControls.AboutUsWebPart",
"Microsoft.SharePoint.Portal.WebControls.MyMembershipWebPart",

// OWA Web Parts (no mappings)
"Microsoft.SharePoint.Portal.WebControls.OWAInboxPart",
"Microsoft.SharePoint.Portal.WebControls.OWACalendarPart",
"Microsoft.SharePoint.Portal.WebControls.OWAContactsPart",
"Microsoft.SharePoint.Portal.WebControls.OWATasksPart",

// Category Web Parts (no mappings)
"Microsoft.SharePoint.Portal.WebControls.CategoryWebPart",
"Microsoft.SharePoint.Portal.WebControls.CategoryResultsWebPart",

// Announcements Web Parts (no mappings)
"Microsoft.SharePoint.Portal.WebControls.AnnouncementTilesWebPart",

// Tasks and Tools Web Parts (no mappings)
"Microsoft.SharePoint.Portal.WebControls.TasksAndToolsWebPart",

// Week in Pictures Web Parts (no mappings)
"Microsoft.SharePoint.Portal.WebControls.ThisWeekInPicturesWebPart",

// User Tasks Web Parts (no mappings)
"Microsoft.SharePoint.WebPartPages.UserTasksWebPart",

// Timeline Web Parts (no mappings)
"Microsoft.SharePoint.WebPartPages.SPTimelineWebPart",

// Taxonomy Web Parts (no mappings)
"Microsoft.SharePoint.Taxonomy.TermProperty",

// Business Data Web Parts (no mappings)
"Microsoft.SharePoint.Portal.WebControls.BusinessDataListWebPart",
"Microsoft.SharePoint.Portal.WebControls.BusinessDataFilterWebPart",
"Microsoft.SharePoint.Portal.WebControls.BusinessDataDetailsWebPart",
"Microsoft.SharePoint.Portal.WebControls.BusinessDataAssociationWebPart",
"Microsoft.SharePoint.Portal.WebControls.BusinessDataActionsWebPart",
"Microsoft.SharePoint.Portal.WebControls.BusinessDataItemBuilder",

// Filter Web Parts (no mappings)
"Microsoft.SharePoint.Portal.WebControls.ScorecardFilterWebPart",
"Microsoft.SharePoint.Portal.WebControls.ApplyFiltersWebPart",
"Microsoft.SharePoint.Portal.WebControls.DateFilterWebPart",
"Microsoft.SharePoint.Portal.WebControls.UserContextFilterWebPart",
"Microsoft.SharePoint.Portal.WebControls.SPSlicerTextWebPart",
"Microsoft.SharePoint.Portal.WebControls.SpListFilterWebPart",
"Microsoft.SharePoint.Portal.WebControls.QueryStringFilterWebPart",
"Microsoft.SharePoint.Portal.WebControls.PageContextFilterWebPart",
"Microsoft.SharePoint.Portal.WebControls.SPSlicerChoicesWebPart",

// Blog Site Web Parts (no mappings)
"Microsoft.SharePoint.WebPartPages.BlogLinksWebPart",
"Microsoft.SharePoint.WebPartPages.BlogAdminWebPart",
"Microsoft.SharePoint.WebPartPages.BlogMonthQuickLaunch",
"Microsoft.SharePoint.WebPartPages.BlogYearArchive",

// Error Web Parts (no mappings)
"Microsoft.SharePoint.WebPartPages.ErrorWebPart",

// App Catalog Web Parts (no mappings)
"Microsoft.SharePoint.WebPartPages.GettingStartedWithAppCatalogSiteWebPart",

// Document Set Web Parts (no mappings)
"Microsoft.Office.Server.WebControls.DocIdSearchWebPart",
"Microsoft.Office.Server.WebControls.DocumentSetPropertiesWebPart",
"Microsoft.Office.Server.WebControls.DocumentSetContentsWebPart",

// Analytics Web Parts (no mappings)
"Microsoft.Office.Server.WebAnalytics.Reporting.WhatsPopularWebPart",

// Chart Web Parts (no mappings)
"Microsoft.Office.Server.WebControls.ChartWebPart",

// Web Parts with empty mappings (drop without transformation)
"Microsoft.SharePoint.WebPartPages.GettingStartedWebPart",
"Microsoft.Office.InfoPath.Server.Controls.WebUI.BrowserFormWebPart",
"Microsoft.SharePoint.WebPartPages.SPUserCodeWebPart",
"Microsoft.SharePoint.WebPartPages.TitleBarWebPart",
"Microsoft.SharePoint.Publishing.WebControls.TableOfContentsWebPart"
};
#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ internal static async Task ExecuteAsync(ScannerBase scannerBase, PnPContext cont
CurrentWebId = addIn.CurrentWebId,
CurrentWebName = addIn.CurrentWebName,
InstalledBy = addIn.InstalledBy,
InstalledSiteId = addIn.InstalledSiteId,
InstalledSiteId = addIn.InstalledSiteId,
InstalledWebFullUrl = addIn.InstalledWebFullUrl,
InstalledWebId = addIn.InstalledWebId,
InstalledWebName = addIn.InstalledWebName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
using PnP.Core.Model.SharePoint;
using PnP.Core.QueryModel;
using PnP.Core.Services;
using PnP.Scanning.Core.Scanners.Classic;
using PnP.Scanning.Core.Storage;
using Serilog;

namespace PnP.Scanning.Core.Scanners
{
Expand Down Expand Up @@ -37,6 +39,7 @@ internal static async Task ExecuteAsync(ScannerBase scannerBase, PnPContext cont
{

List<ClassicPage> pagesList = new();
List<ClassicWebPart> webPartsList = new();
int modernPageCounter = 0;
HashSet<string> remediationCodes = new();

Expand Down Expand Up @@ -147,6 +150,45 @@ await QueryListAsync(sitePagesLibrary, PageQuery(new List<string> { HtmlFileType

if (pagesList.Count > 0)
{
// Extract web parts from each page
foreach (var page in pagesList)
{
try
{
var webParts = await WebPartExtractor.ExtractWebPartsFromPageAsync(
scannerBase.ScanId,
scannerBase.SiteUrl,
scannerBase.WebUrl,
page.PageUrl,
page.PageName,
page.ListId,
page.ModifiedAt,
csomContext);

webPartsList.AddRange(webParts);

// Add web part remediation codes to the overall set
foreach (var webPart in webParts)
{
if (!string.IsNullOrEmpty(webPart.RemediationCode))
{
remediationCodes.Add(webPart.RemediationCode);
}
}
}
catch (Exception ex)
{
// Log the error but continue processing other pages
Log.Warning("Failed to extract web parts from page {PageUrl}: {Error}", page.PageUrl, ex.Message);
}
}

// Store web parts if any were found
if (webPartsList.Count > 0)
{
await scannerBase.StorageManager.StoreWebPartInformationAsync(scannerBase.ScanId, webPartsList);
}

await scannerBase.StorageManager.StorePageInformationAsync(scannerBase.ScanId, pagesList);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,17 @@ internal enum RemediationCodes
/// Other ribbon/UI extensions via User Custom Actions
/// </summary>
CE9,


WP1,

/// <summary>
/// Web part without proper mapping
/// </summary>
WP2,
/// <summary>
/// Unknown web part type
/// </summary>
WP3,
}
}
Loading