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

Commit d8635bc

Browse files
Merge pull request #383 from OfficeDev/dev
June 2016 Intermediate Release 3
2 parents d141016 + d7ec3ed commit d8635bc

20 files changed

+470
-143
lines changed
4 KB
Binary file not shown.
8 KB
Binary file not shown.
4 KB
Binary file not shown.

Commands/Branding/ApplyProvisioningTemplate.cs

Lines changed: 105 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,27 @@ namespace SharePointPnP.PowerShell.Commands.Branding
3838
Remarks = @"Applies a provisioning template in XML format to the current web. It will only apply the lists and site security part of the template.",
3939
SortOrder = 4)]
4040

41+
[CmdletExample(
42+
Code = @"PS:> Apply-SPOProvisioningTemplate -Path template.pnp",
43+
Remarks = @"Applies a provisioning template from a pnp package to the current web.",
44+
SortOrder = 5)]
45+
46+
[CmdletExample(
47+
Code = @"PS:> Apply-SPOProvisioningTemplate -Path https://tenant.sharepoint.com/sites/templatestorage/Documents/template.pnp",
48+
Remarks = @"Applies a provisioning template from a pnp package stored in a library to the current web.",
49+
SortOrder = 6)]
50+
4151
[CmdletExample(
4252
Code = @"
4353
PS:> $handler1 = New-SPOExtensibilityHandlerObject -Assembly Contoso.Core.Handlers -Type Contoso.Core.Handlers.MyExtensibilityHandler1
4454
PS:> $handler2 = New-SPOExtensibilityHandlerObject -Assembly Contoso.Core.Handlers -Type Contoso.Core.Handlers.MyExtensibilityHandler1
4555
PS:> Apply-SPOProvisioningTemplate -Path NewTemplate.xml -ExtensibilityHandlers $handler1,$handler2",
4656
Remarks = @"This will create two new ExtensibilityHandler objects that are run while provisioning the template",
47-
SortOrder = 5)]
57+
SortOrder = 7)]
4858

4959
public class ApplyProvisioningTemplate : SPOWebCmdlet
5060
{
51-
[Parameter(Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true, ValueFromPipeline = true, HelpMessage = "Path to the xml file containing the provisioning template.")]
61+
[Parameter(Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true, ValueFromPipeline = true, HelpMessage = "Path to the xml or pnp file containing the provisioning template.")]
5262
public string Path;
5363

5464
[Parameter(Mandatory = false, HelpMessage = "Root folder where resources/files that are being referenced in the template are located. If not specified the same folder as where the provisioning template is located will be used.")]
@@ -72,89 +82,110 @@ public class ApplyProvisioningTemplate : SPOWebCmdlet
7282
protected override void ExecuteCmdlet()
7383
{
7484
SelectedWeb.EnsureProperty(w => w.Url);
75-
76-
if (!System.IO.Path.IsPathRooted(Path))
77-
{
78-
Path = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Path);
79-
}
80-
if (!string.IsNullOrEmpty(ResourceFolder))
85+
bool templateFromFileSystem = !Path.ToLower().StartsWith("http");
86+
FileConnectorBase fileConnector;
87+
string templateFileName = System.IO.Path.GetFileName(Path);
88+
if (templateFromFileSystem)
8189
{
82-
if (!System.IO.Path.IsPathRooted(ResourceFolder))
90+
if (!System.IO.Path.IsPathRooted(Path))
8391
{
84-
ResourceFolder = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, ResourceFolder);
92+
Path = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Path);
8593
}
94+
if (!string.IsNullOrEmpty(ResourceFolder))
95+
{
96+
if (!System.IO.Path.IsPathRooted(ResourceFolder))
97+
{
98+
ResourceFolder = System.IO.Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path,
99+
ResourceFolder);
100+
}
101+
}
102+
FileInfo fileInfo = new FileInfo(Path);
103+
fileConnector = new FileSystemConnector(fileInfo.DirectoryName, "");
104+
}
105+
else
106+
{
107+
Uri fileUri = new Uri(Path);
108+
var webUrl = Microsoft.SharePoint.Client.Web.WebUrlFromFolderUrlDirect(this.ClientContext, fileUri);
109+
var templateContext = this.ClientContext.Clone(webUrl.ToString());
110+
111+
string library = Path.ToLower().Replace(templateContext.Url.ToLower(), "").TrimStart('/');
112+
int idx = library.IndexOf("/");
113+
library = library.Substring(0, idx);
114+
fileConnector = new SharePointConnector(templateContext, templateContext.Url, library);
86115
}
87-
88-
FileInfo fileInfo = new FileInfo(Path);
89-
90116
XMLTemplateProvider provider = null;
91117
ProvisioningTemplate provisioningTemplate = null;
92-
var isOpenOfficeFile = IsOpenOfficeFile(Path);
118+
Stream stream = fileConnector.GetFileStream(templateFileName);
119+
var isOpenOfficeFile = IsOpenOfficeFile(stream);
93120
if (isOpenOfficeFile)
94121
{
95-
var fileSystemconnector = new FileSystemConnector(fileInfo.DirectoryName, "");
96-
provider = new XMLOpenXMLTemplateProvider(new OpenXMLConnector(fileInfo.Name, fileSystemconnector));
97-
var fileName = fileInfo.Name.Substring(0, fileInfo.Name.LastIndexOf(".")) + ".xml";
98-
provisioningTemplate = provider.GetTemplate(fileName);
122+
provider = new XMLOpenXMLTemplateProvider(new OpenXMLConnector(templateFileName, fileConnector));
123+
templateFileName = templateFileName.Substring(0, templateFileName.LastIndexOf(".")) + ".xml";
99124
}
100125
else
101126
{
102-
provider = new XMLFileSystemTemplateProvider(fileInfo.DirectoryName, "");
103-
provisioningTemplate = provider.GetTemplate(fileInfo.Name);
127+
if (templateFromFileSystem)
128+
{
129+
provider = new XMLFileSystemTemplateProvider(fileConnector.Parameters[FileConnectorBase.CONNECTIONSTRING] + "", "");
130+
}
131+
else
132+
{
133+
throw new NotSupportedException("Only .pnp package files are supported from a SharePoint library");
134+
}
104135
}
136+
provisioningTemplate = provider.GetTemplate(templateFileName);
137+
138+
if (provisioningTemplate == null) return;
105139

106-
if (provisioningTemplate != null)
140+
if (isOpenOfficeFile)
107141
{
108-
if (isOpenOfficeFile)
142+
provisioningTemplate.Connector = provider.Connector;
143+
}
144+
else
145+
{
146+
if (ResourceFolder != null)
109147
{
110-
provisioningTemplate.Connector = provider.Connector;
148+
var fileSystemConnector = new FileSystemConnector(ResourceFolder, "");
149+
provisioningTemplate.Connector = fileSystemConnector;
111150
}
112151
else
113152
{
114-
FileSystemConnector fileSystemConnector = null;
115-
if (ResourceFolder != null)
116-
{
117-
fileSystemConnector = new FileSystemConnector(ResourceFolder, "");
118-
provisioningTemplate.Connector = fileSystemConnector;
119-
}
120-
else
121-
{
122-
provisioningTemplate.Connector = provider.Connector;
123-
}
153+
provisioningTemplate.Connector = provider.Connector;
124154
}
155+
}
125156

126-
if (Parameters != null)
157+
if (Parameters != null)
158+
{
159+
foreach (var parameter in Parameters.Keys)
127160
{
128-
foreach (var parameter in Parameters.Keys)
161+
if (provisioningTemplate.Parameters.ContainsKey(parameter.ToString()))
129162
{
130-
if (provisioningTemplate.Parameters.ContainsKey(parameter.ToString()))
131-
{
132-
provisioningTemplate.Parameters[parameter.ToString()] = Parameters[parameter].ToString();
133-
}
134-
else
135-
{
136-
provisioningTemplate.Parameters.Add(parameter.ToString(), Parameters[parameter].ToString());
137-
}
163+
provisioningTemplate.Parameters[parameter.ToString()] = Parameters[parameter].ToString();
164+
}
165+
else
166+
{
167+
provisioningTemplate.Parameters.Add(parameter.ToString(), Parameters[parameter].ToString());
138168
}
139169
}
170+
}
140171

141-
var applyingInformation = new ProvisioningTemplateApplyingInformation();
172+
var applyingInformation = new ProvisioningTemplateApplyingInformation();
142173

143-
if (this.MyInvocation.BoundParameters.ContainsKey("Handlers"))
144-
{
145-
applyingInformation.HandlersToProcess = Handlers;
146-
}
147-
if (this.MyInvocation.BoundParameters.ContainsKey("ExcludeHandlers"))
174+
if (this.MyInvocation.BoundParameters.ContainsKey("Handlers"))
175+
{
176+
applyingInformation.HandlersToProcess = Handlers;
177+
}
178+
if (this.MyInvocation.BoundParameters.ContainsKey("ExcludeHandlers"))
179+
{
180+
foreach (var handler in (OfficeDevPnP.Core.Framework.Provisioning.Model.Handlers[])Enum.GetValues(typeof(Handlers)))
148181
{
149-
foreach (var handler in (OfficeDevPnP.Core.Framework.Provisioning.Model.Handlers[])Enum.GetValues(typeof(Handlers)))
182+
if (!ExcludeHandlers.Has(handler) && handler != Handlers.All)
150183
{
151-
if (!ExcludeHandlers.Has(handler) && handler != Handlers.All)
152-
{
153-
Handlers = Handlers | handler;
154-
}
184+
Handlers = Handlers | handler;
155185
}
156-
applyingInformation.HandlersToProcess = Handlers;
157186
}
187+
applyingInformation.HandlersToProcess = Handlers;
188+
}
158189

159190
if (ExtensibilityHandlers != null)
160191
{
@@ -166,39 +197,33 @@ protected override void ExecuteCmdlet()
166197
WriteProgress(new ProgressRecord(0, string.Format("Applying template to {0}", SelectedWeb.Url), message) { PercentComplete = (100 / total) * step });
167198
};
168199

169-
applyingInformation.MessagesDelegate = (message, type) =>
200+
applyingInformation.MessagesDelegate = (message, type) =>
201+
{
202+
if (type == ProvisioningMessageType.Warning)
170203
{
171-
if (type == ProvisioningMessageType.Warning)
172-
{
173-
WriteWarning(message);
174-
}
175-
};
204+
WriteWarning(message);
205+
}
206+
};
176207

177-
applyingInformation.OverwriteSystemPropertyBagValues = OverwriteSystemPropertyBagValues;
178-
SelectedWeb.ApplyProvisioningTemplate(provisioningTemplate, applyingInformation);
179-
}
208+
applyingInformation.OverwriteSystemPropertyBagValues = OverwriteSystemPropertyBagValues;
209+
SelectedWeb.ApplyProvisioningTemplate(provisioningTemplate, applyingInformation);
180210
}
181211

182-
183-
private bool IsOpenOfficeFile(string path)
212+
private bool IsOpenOfficeFile(Stream stream)
184213
{
185214
bool istrue = false;
186215
// SIG 50 4B 03 04 14 00
187-
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
188-
{
189-
byte[] bytes = new byte[6];
190-
191-
int n = stream.Read(bytes, 0, 6);
192-
var signature = string.Empty;
193-
foreach (var b in bytes)
194-
{
195-
signature += b.ToString("X2");
196-
}
197-
if (signature == "504B03041400")
198-
{
199-
istrue = true;
200-
}
201216

217+
byte[] bytes = new byte[6];
218+
int n = stream.Read(bytes, 0, 6);
219+
var signature = string.Empty;
220+
foreach (var b in bytes)
221+
{
222+
signature += b.ToString("X2");
223+
}
224+
if (signature == "504B03041400")
225+
{
226+
istrue = true;
202227
}
203228
return istrue;
204229
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Management.Automation;
6+
using OfficeDevPnP.Core.Framework.Provisioning.Connectors.OpenXML;
7+
using OfficeDevPnP.Core.Framework.Provisioning.Connectors.OpenXML.Model;
8+
using SharePointPnP.PowerShell.CmdletHelpAttributes;
9+
10+
namespace SharePointPnP.PowerShell.Commands.Branding
11+
{
12+
[Cmdlet("Convert", "SPOFolderToProvisioningTemplate")]
13+
[CmdletExample(
14+
Code = @"PS:> Convert-SPOFolderToProvisioningTemplate -Out template.pnp",
15+
Remarks = "Creates a pnp package file of an existing template xml, and includes all files in the current folder",
16+
SortOrder = 1)]
17+
[CmdletExample(
18+
Code = @"PS:> Convert-SPOFolderToProvisioningTemplate -Out template.pnp -Folder c:\temp",
19+
Remarks = "Creates a pnp package file of an existing template xml, and includes all files in the c:\\temp folder",
20+
SortOrder = 2)]
21+
public class ConvertProvisioningTemplateFromFolder : PSCmdlet
22+
{
23+
[Parameter(Mandatory = true, Position = 0, HelpMessage = "Filename to write to, optionally including full path.")]
24+
public string Out;
25+
26+
[Parameter(Mandatory = false, Position = 1, HelpMessage = "Folder to process. If not specified the current folder will be used.")]
27+
public string Folder;
28+
29+
[Parameter(Mandatory = false, HelpMessage = "Overwrites the output file if it exists.")]
30+
public SwitchParameter Force;
31+
32+
protected override void ProcessRecord()
33+
{
34+
if (string.IsNullOrEmpty(Folder))
35+
{
36+
Folder = SessionState.Path.CurrentFileSystemLocation.Path;
37+
}
38+
else
39+
{
40+
if (!Path.IsPathRooted(Folder))
41+
{
42+
Folder = Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Folder);
43+
Folder = new DirectoryInfo(Folder).FullName; // normalize away relative ./ paths
44+
}
45+
}
46+
47+
if (!ShouldContinue()) return;
48+
49+
if (Path.GetExtension(Out).ToLower() == ".pnp")
50+
{
51+
byte[] pack = CreatePnPPackageFile();
52+
File.WriteAllBytes(Out, pack);
53+
}
54+
else
55+
{
56+
throw new NotSupportedException("Output filename has to end with .pnp");
57+
}
58+
}
59+
60+
private bool ShouldContinue()
61+
{
62+
if (!Path.IsPathRooted(Out))
63+
{
64+
Out = Path.Combine(SessionState.Path.CurrentFileSystemLocation.Path, Out);
65+
}
66+
67+
bool shouldContinue = true;
68+
if (System.IO.File.Exists(Out))
69+
{
70+
shouldContinue = (Force ||
71+
ShouldContinue(string.Format(Commands.Properties.Resources.File0ExistsOverwrite, Out),
72+
Commands.Properties.Resources.Confirm));
73+
}
74+
return shouldContinue;
75+
}
76+
77+
private byte[] CreatePnPPackageFile()
78+
{
79+
PnPInfo info = new PnPInfo
80+
{
81+
Manifest = new PnPManifest()
82+
{
83+
Type = PackageType.Full
84+
},
85+
Properties = new PnPProperties()
86+
{
87+
Generator = OfficeDevPnP.Core.Utilities.PnPCoreUtilities.PnPCoreVersionTag,
88+
Author = string.Empty,
89+
},
90+
Files = new List<PnPFileInfo>()
91+
};
92+
DirectoryInfo dirInfo = new DirectoryInfo(Path.GetFullPath(Folder));
93+
string templateFileName = Path.GetFileNameWithoutExtension(Out) + ".xml";
94+
bool templateFileMissing = dirInfo.GetFiles(templateFileName, SearchOption.TopDirectoryOnly).Length == 0;
95+
if (templateFileMissing) throw new InvalidOperationException("You need an xml template file (" + templateFileName + ") with the same name as the .pnp outfile in order to pack a folder to a .pnp package file.");
96+
97+
foreach (var currentFile in dirInfo.GetFiles("*.*", SearchOption.AllDirectories))
98+
{
99+
var folder = GetFolderName(currentFile, dirInfo);
100+
PnPFileInfo fileInfo = new PnPFileInfo
101+
{
102+
InternalName = currentFile.Name.AsInternalFilename(),
103+
OriginalName = currentFile.Name,
104+
Folder = folder,
105+
Content = File.ReadAllBytes(currentFile.FullName)
106+
};
107+
WriteVerbose("Adding file:" + currentFile.Name + " - " + folder);
108+
info.Files.Add(fileInfo);
109+
}
110+
byte[] pack = info.PackTemplate().ToArray();
111+
return pack;
112+
}
113+
114+
private string GetFolderName(FileInfo currentFile, DirectoryInfo rootFolderInfo)
115+
{
116+
var fileFolder = currentFile.DirectoryName ?? string.Empty;
117+
fileFolder = fileFolder.Replace('\\', '/').Replace(' ', '_');
118+
var rootFolder = rootFolderInfo.FullName.Replace('\\', '/').Replace(' ', '_').TrimEnd('/');
119+
return fileFolder.Replace(rootFolder, "");
120+
}
121+
}
122+
}

0 commit comments

Comments
 (0)