@@ -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 = @"
4353PS:> $handler1 = New-SPOExtensibilityHandlerObject -Assembly Contoso.Core.Handlers -Type Contoso.Core.Handlers.MyExtensibilityHandler1
4454PS:> $handler2 = New-SPOExtensibilityHandlerObject -Assembly Contoso.Core.Handlers -Type Contoso.Core.Handlers.MyExtensibilityHandler1
4555PS:> 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 }
0 commit comments