Skip to content
This repository was archived by the owner on Jan 19, 2021. It is now read-only.

Commit fe88730

Browse files
committed
Merge branch 'dev' of https://github.com/sharepoint/pnp-powershell into dev
2 parents 4a9fc4e + 4fcc7c1 commit fe88730

12 files changed

+3345
-781
lines changed
Binary file not shown.

Binaries/SharePointPnP.Modernization.Framework.xml

Lines changed: 1350 additions & 359 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Binary file not shown.

Binaries/release/SharePointPnP.Modernization.Framework.xml

Lines changed: 1350 additions & 359 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
1010
### Added
1111

1212
- Added Sync-PnPAppToTeams to synchronize an app from the tenant app catalog to the Microsoft Teams App Catalog
13+
- Added Export-PnPClientSidePageMapping to export the mapping files needed during publishing page transformation
1314

1415
### Changed
1516

@@ -21,6 +22,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
2122
- Added -ContentType parameter to Add-PnPClientSidePage and Set-PnPClientSidePage
2223
- ConvertTo-PnPClientSidePage: added -Library and -Folder parameters to support modernization of pages living outside of the SitePages folder
2324
- ConvertTo-PnPClientSidePage: added -LogType, -LogFolder, -LogSkipFlush and -LogVerbose parameters to support log generation to an md file or SharePoint page
25+
- ConvertTo-PnPClientSidePage: added -DontPublish and -DisablePageComments parameters to control the page publishing and commenting
26+
- ConvertTo-PnPClientSidePage: added -PublishingPage and -PageLayoutMapping to support publishing page transformation
2427

2528
### Contributors
2629

Commands/Base/PipeBinds/PagePipeBind.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,8 @@ public PagePipeBind(string name)
4747

4848
public string Folder { get; set; }
4949

50-
internal ListItem GetPage(Web web)
50+
internal ListItem GetPage(Web web, string listToLoad)
5151
{
52-
// Get pages library
53-
string listToLoad = "sitepages";
54-
5552
if (!string.IsNullOrEmpty(this.Library))
5653
{
5754
listToLoad = this.Library;
@@ -91,6 +88,11 @@ internal ListItem GetPage(Web web)
9188
return null;
9289
}
9390

91+
internal ListItem GetPublishingPage(Web web)
92+
{
93+
return null;
94+
}
95+
9496
}
9597
}
9698
#endif

Commands/Base/SPOnlineConnectionHelper.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,11 +563,16 @@ internal static SPOnlineConnection InstantiateSPOnlineConnection(Uri url, PSCred
563563
context.Credentials = new NetworkCredential(credentials.UserName, credentials.Password);
564564
}
565565
}
566+
#if SP2013 || SP2016 || SP2019
566567
var connectionType = ConnectionType.OnPrem;
568+
#else
569+
var connectionType = ConnectionType.O365;
570+
#endif
567571
if (url.Host.ToUpperInvariant().EndsWith("SHAREPOINT.COM"))
568572
{
569573
connectionType = ConnectionType.O365;
570574
}
575+
571576
if (skipAdminCheck == false)
572577
{
573578
if (IsTenantAdminSite(context))

Commands/ClientSidePages/ConvertToClientSidePage.cs

Lines changed: 156 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using SharePointPnP.Modernization.Framework;
1313
using System.IO;
1414
using SharePointPnP.Modernization.Framework.Telemetry.Observers;
15+
using SharePointPnP.Modernization.Framework.Publishing;
1516

1617
namespace SharePointPnP.PowerShell.Commands.ClientSidePages
1718
{
@@ -36,21 +37,25 @@ namespace SharePointPnP.PowerShell.Commands.ClientSidePages
3637
Remarks = "Converts a wiki page named 'somepage' to a client side page, including the copying of the page metadata (if any)",
3738
SortOrder = 4)]
3839
[CmdletExample(
40+
Code = @"PS:> ConvertTo-PnPClientSidePage -Identity ""somepage.aspx"" -PublishingPage -Overwrite -TargetWebUrl https://contoso.sharepoint.com/sites/targetmodernsite",
41+
Remarks = "Converts a publishing page named 'somepage' to a client side pagein the https://contoso.sharepoint.com/sites/targetmodernsite site",
42+
SortOrder = 5)]
43+
[CmdletExample(
3944
Code = @"PS:> ConvertTo-PnPClientSidePage -Identity ""somepage.aspx"" -Library ""SiteAssets"" -Folder ""Folder1"" -Overwrite",
4045
Remarks = "Converts a web part page named 'somepage' living inside the SiteAssets library in a folder named folder1 into a client side page",
41-
SortOrder = 5)]
46+
SortOrder = 6)]
4247
[CmdletExample(
4348
Code = @"PS:> ConvertTo-PnPClientSidePage -Identity ""somepage.aspx"" -Overwrite -TargetWebUrl https://contoso.sharepoint.com/sites/targetmodernsite",
4449
Remarks = "Converts a wiki page named 'somepage' to a client side page in the https://contoso.sharepoint.com/sites/targetmodernsite site",
45-
SortOrder = 6)]
50+
SortOrder = 7)]
4651
[CmdletExample(
4752
Code = @"PS:> ConvertTo-PnPClientSidePage -Identity ""somepage.aspx"" -LogType File -LogFolder c:\temp -LogVerbose -Overwrite",
4853
Remarks = "Converts a web part page named 'somepage' and creates a log file in c:\temp using verbose logging",
49-
SortOrder = 7)]
54+
SortOrder = 8)]
5055
[CmdletExample(
5156
Code = @"PS:> ConvertTo-PnPClientSidePage -Identity ""somepage.aspx"" -LogType SharePoint -LogSkipFlush",
5257
Remarks = "Converts a web part page named 'somepage' and creates a log file in SharePoint but skip the actual write. Use this option to make multiple ConvertTo-PnPClientSidePage invocations create a single log",
53-
SortOrder = 8)]
58+
SortOrder = 9)]
5459
public class ConvertToClientSidePage : PnPWebCmdlet
5560
{
5661
private Assembly modernizationAssembly;
@@ -66,7 +71,7 @@ public class ConvertToClientSidePage : PnPWebCmdlet
6671
[Parameter(Mandatory = false, ValueFromPipeline = true, Position = 0, HelpMessage = "The folder to load the provided page from. If not provided all folders are searched")]
6772
public string Folder;
6873

69-
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, ValueFromPipeline = true, HelpMessage = "Path and name of the web part mapping file driving the transformation", ParameterSetName = "WebPartMappingFile")]
74+
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, ValueFromPipeline = true, HelpMessage = "Path and name of the web part mapping file driving the transformation")]
7075
public string WebPartMappingFile;
7176

7277
[Parameter(Mandatory = false, HelpMessage = "Overwrites page if already existing")]
@@ -111,21 +116,50 @@ public class ConvertToClientSidePage : PnPWebCmdlet
111116
[Parameter(Mandatory = false, HelpMessage = "Configure logging to include verbose log entries")]
112117
public SwitchParameter LogVerbose = false;
113118

119+
[Parameter(Mandatory = false, HelpMessage = "Don't publish the created modern page")]
120+
public SwitchParameter DontPublish = false;
121+
122+
[Parameter(Mandatory = false, HelpMessage = "Disable comments for the created modern page")]
123+
public SwitchParameter DisablePageComments = false;
124+
125+
[Parameter(Mandatory = false, HelpMessage = "I'm transforming a publishing page")]
126+
public SwitchParameter PublishingPage = false;
127+
128+
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, ValueFromPipeline = true, HelpMessage = "Path and name of the page layout mapping file driving the publishing page transformation")]
129+
public string PageLayoutMapping;
130+
131+
114132
protected override void ExecuteCmdlet()
115133
{
116134
//Fix loading of modernization framework
117135
FixAssemblyResolving();
118-
136+
119137
// Load the page to transform
120138
Identity.Library = this.Library;
121139
Identity.Folder = this.Folder;
122-
var page = Identity.GetPage(this.ClientContext.Web);
140+
141+
ListItem page = null;
142+
if (this.PublishingPage)
143+
{
144+
page = Identity.GetPage(this.ClientContext.Web, CacheManager.Instance.GetPublishingPagesLibraryName(this.ClientContext));
145+
}
146+
else
147+
{
148+
page = Identity.GetPage(this.ClientContext.Web, "sitepages");
149+
}
123150

124151
if (page == null)
125152
{
126153
throw new Exception($"Page '{Identity?.Name}' does not exist");
127154
}
128155

156+
// Publishing specific validation
157+
if (this.PublishingPage && string.IsNullOrEmpty(this.TargetWebUrl))
158+
{
159+
throw new Exception($"Publishing page transformation is only supported when transformating into another site collection. Use the -TargetWebUrl to specify a modern target site.");
160+
}
161+
162+
// Load transformation models
129163
PageTransformation webPartMappingModel = null;
130164
if (string.IsNullOrEmpty(this.WebPartMappingFile))
131165
{
@@ -140,7 +174,7 @@ protected override void ExecuteCmdlet()
140174
webPartMappingModel = (PageTransformation)xmlMapping.Deserialize(stream);
141175
}
142176

143-
this.WriteVerbose("Using embedded webpartmapping file (https://github.com/SharePoint/PnP-PowerShell/blob/master/Commands/ClientSidePages/webpartmapping.xml)");
177+
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.");
144178
}
145179

146180
// Validate webpartmappingfile
@@ -152,6 +186,11 @@ protected override void ExecuteCmdlet()
152186
}
153187
}
154188

189+
if (this.PublishingPage && !string.IsNullOrEmpty(this.PageLayoutMapping) && !System.IO.File.Exists(this.PageLayoutMapping))
190+
{
191+
throw new Exception($"Provided pagelayout mapping file {this.PageLayoutMapping} does not exist");
192+
}
193+
155194
// Create target client context (when needed)
156195
ClientContext targetContext = null;
157196
if (!string.IsNullOrEmpty(TargetWebUrl))
@@ -161,60 +200,143 @@ protected override void ExecuteCmdlet()
161200

162201
// Create transformator instance
163202
PageTransformator pageTransformator = null;
203+
PublishingPageTransformator publishingPageTransformator = null;
164204

165205
if (!string.IsNullOrEmpty(this.WebPartMappingFile))
166206
{
167-
// Use web part mapping file
168-
pageTransformator = new PageTransformator(this.ClientContext, targetContext, this.WebPartMappingFile);
207+
// Using custom web part mapping file
208+
if (this.PublishingPage)
209+
{
210+
if (!string.IsNullOrEmpty(this.PageLayoutMapping))
211+
{
212+
// Using custom page layout mapping file + default one (they're merged together)
213+
publishingPageTransformator = new PublishingPageTransformator(this.ClientContext, targetContext, this.WebPartMappingFile, this.PageLayoutMapping);
214+
}
215+
else
216+
{
217+
// Using default page layout mapping file
218+
publishingPageTransformator = new PublishingPageTransformator(this.ClientContext, targetContext, this.WebPartMappingFile, null);
219+
}
220+
}
221+
else
222+
{
223+
// Use web part mapping file
224+
pageTransformator = new PageTransformator(this.ClientContext, targetContext, this.WebPartMappingFile);
225+
}
169226
}
170227
else
171228
{
172-
// Use web part mapping model loaded from embedded mapping file
173-
pageTransformator = new PageTransformator(this.ClientContext, targetContext, webPartMappingModel);
229+
// Using default web part mapping file
230+
if (this.PublishingPage)
231+
{
232+
if (!string.IsNullOrEmpty(this.PageLayoutMapping))
233+
{
234+
// Load and validate the custom mapping file
235+
PageLayoutManager pageLayoutManager = new PageLayoutManager(this.ClientContext);
236+
var pageLayoutMappingModel = pageLayoutManager.LoadPageLayoutMappingFile(this.PageLayoutMapping);
237+
238+
// Using custom page layout mapping file + default one (they're merged together)
239+
publishingPageTransformator = new PublishingPageTransformator(this.ClientContext, targetContext, webPartMappingModel, pageLayoutMappingModel);
240+
}
241+
else
242+
{
243+
// Using default page layout mapping file
244+
publishingPageTransformator = new PublishingPageTransformator(this.ClientContext, targetContext, webPartMappingModel, null);
245+
}
246+
}
247+
else
248+
{
249+
// Use web part mapping model loaded from embedded mapping file
250+
pageTransformator = new PageTransformator(this.ClientContext, targetContext, webPartMappingModel);
251+
}
174252
}
175253

176254
// Setup logging
177255
if (this.LogType == ClientSidePageTransformatorLogType.File)
178256
{
179-
pageTransformator.RegisterObserver(new MarkdownObserver(folder:this.LogFolder, includeDebugEntries:this.LogVerbose));
257+
if (this.PublishingPage)
258+
{
259+
publishingPageTransformator.RegisterObserver(new MarkdownObserver(folder: this.LogFolder, includeDebugEntries: this.LogVerbose));
260+
}
261+
else
262+
{
263+
pageTransformator.RegisterObserver(new MarkdownObserver(folder: this.LogFolder, includeDebugEntries: this.LogVerbose));
264+
}
180265
}
181266
else if (this.LogType == ClientSidePageTransformatorLogType.SharePoint)
182267
{
183-
pageTransformator.RegisterObserver(new MarkdownToSharePointObserver(targetContext ?? this.ClientContext, includeDebugEntries: this.LogVerbose));
184-
}
185-
186-
// Setup Transformation information
187-
PageTransformationInformation pti = new PageTransformationInformation(page)
188-
{
189-
Overwrite = this.Overwrite,
190-
TargetPageTakesSourcePageName = this.TakeSourcePageName,
191-
ReplaceHomePageWithDefaultHomePage = this.ReplaceHomePageWithDefault,
192-
KeepPageSpecificPermissions = !this.SkipItemLevelPermissionCopyToClientSidePage,
193-
CopyPageMetadata = this.CopyPageMetadata,
194-
ModernizationCenterInformation = new ModernizationCenterInformation()
268+
if (this.PublishingPage)
195269
{
196-
AddPageAcceptBanner = this.AddPageAcceptBanner
197-
},
198-
};
199-
200-
// Set mapping properties
201-
pti.MappingProperties["SummaryLinksToQuickLinks"] = (!SummaryLinksToHtml).ToString().ToLower();
202-
pti.MappingProperties["UseCommunityScriptEditor"] = UseCommunityScriptEditor.ToString().ToLower();
270+
publishingPageTransformator.RegisterObserver(new MarkdownToSharePointObserver(targetContext ?? this.ClientContext, includeDebugEntries: this.LogVerbose));
271+
}
272+
else
273+
{
274+
pageTransformator.RegisterObserver(new MarkdownToSharePointObserver(targetContext ?? this.ClientContext, includeDebugEntries: this.LogVerbose));
275+
}
276+
}
203277

204278
// Clear the client side component cache
205279
if (this.ClearCache)
206280
{
207281
CacheManager.Instance.ClearAllCaches();
208282
}
209283

210-
string serverRelativeClientPageUrl = pageTransformator.Transform(pti);
284+
string serverRelativeClientPageUrl = "";
285+
if (this.PublishingPage)
286+
{
287+
// Setup Transformation information
288+
PublishingPageTransformationInformation pti = new PublishingPageTransformationInformation(page)
289+
{
290+
Overwrite = this.Overwrite,
291+
KeepPageSpecificPermissions = !this.SkipItemLevelPermissionCopyToClientSidePage,
292+
PublishCreatedPage = !this.DontPublish,
293+
DisablePageComments = this.DisablePageComments,
294+
};
295+
296+
// Set mapping properties
297+
pti.MappingProperties["SummaryLinksToQuickLinks"] = (!SummaryLinksToHtml).ToString().ToLower();
298+
pti.MappingProperties["UseCommunityScriptEditor"] = UseCommunityScriptEditor.ToString().ToLower();
299+
300+
serverRelativeClientPageUrl = publishingPageTransformator.Transform(pti);
301+
}
302+
else
303+
{
304+
// Setup Transformation information
305+
PageTransformationInformation pti = new PageTransformationInformation(page)
306+
{
307+
Overwrite = this.Overwrite,
308+
TargetPageTakesSourcePageName = this.TakeSourcePageName,
309+
ReplaceHomePageWithDefaultHomePage = this.ReplaceHomePageWithDefault,
310+
KeepPageSpecificPermissions = !this.SkipItemLevelPermissionCopyToClientSidePage,
311+
CopyPageMetadata = this.CopyPageMetadata,
312+
PublishCreatedPage = !this.DontPublish,
313+
DisablePageComments = this.DisablePageComments,
314+
ModernizationCenterInformation = new ModernizationCenterInformation()
315+
{
316+
AddPageAcceptBanner = this.AddPageAcceptBanner
317+
},
318+
};
319+
320+
// Set mapping properties
321+
pti.MappingProperties["SummaryLinksToQuickLinks"] = (!SummaryLinksToHtml).ToString().ToLower();
322+
pti.MappingProperties["UseCommunityScriptEditor"] = UseCommunityScriptEditor.ToString().ToLower();
323+
324+
serverRelativeClientPageUrl = pageTransformator.Transform(pti);
325+
}
211326

212327
// Flush log
213328
if (this.LogType != ClientSidePageTransformatorLogType.None)
214329
{
215330
if (!this.LogSkipFlush)
216331
{
217-
pageTransformator.FlushObservers();
332+
if (this.PublishingPage)
333+
{
334+
publishingPageTransformator.FlushObservers();
335+
}
336+
else
337+
{
338+
pageTransformator.FlushObservers();
339+
}
218340
}
219341
}
220342

0 commit comments

Comments
 (0)