-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHelix.ProjectCreator.psm1
More file actions
1549 lines (1438 loc) · 53.3 KB
/
Copy pathHelix.ProjectCreator.psm1
File metadata and controls
1549 lines (1438 loc) · 53.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Set-StrictMode -Version 2.0
## PRIVATE METHODS - start ##
##############################
#.SYNOPSIS
# Writes a message in the following formatt to the screen, useful for delinating major steps taken. This will span the entire screen width.
# [ ------------- $TASKNAME : $TASKTYPE ------------]
#
#.DESCRIPTION
# Writes a message in the following formatt to the screen, useful for delinating major steps taken. This will span the entire screen width.
# [ ------------- $TASKNAME : $TASKTYPE ------------]
#
#.PARAMETER TaskName
# Name/Short description of the task/action being performed
#
# REQUIRED
#
#.PARAMETER TaskType
# Categorization value, to help indentify type of task/action being performed.
#
# REQUIRED
#
#.PARAMETER TextColor
# Foreground color of the text
# Default is 'Green'
#
# OPTIONAL
#
#.EXAMPLE
# > Write-StepHeader -TaskName "Create the World" -TaskType "Creation"
#
#.NOTES
# Private Method
##############################
function Write-StepHeader {
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '')]
param(
[Parameter(Mandatory = $true)]
[string]$TaskName,
[Parameter(Mandatory = $true)]
[string]$TaskType,
[Parameter(Mandatory = $false)]
[string]$TextColor = 'Green'
)
function StringFormat {
param(
[int]$length,
[string]$value,
[string]$prefix = '',
[string]$postfix = '',
[switch]$padright
)
# wraps string in spaces so we reduce length by two
$length = $length - 2 #- $postfix.Length - $prefix.Length
if ($value.Length -gt $length) {
# Reduce to length - 4 for elipsis
$value = $value.Substring(0, $length - 4) + '...'
}
$value = " $value "
if ($padright) {
$value = $value.PadRight($length, '-')
}
else {
$value = $value.PadLeft($length, '-')
}
return $prefix + $value + $postfix
}
$actualWidth = (Get-Host).UI.RawUI.BufferSize.Width
$width = $actualWidth - ($actualWidth % 2)
$half = $width / 2
$leftString = StringFormat -length $half -value $TaskName -prefix '[' -postfix ':'
$rightString = StringFormat -length $half -value $TaskType -postfix ']' -padright
$message = ($leftString + $rightString)
Write-Host ''
Write-Host $message -ForegroundColor $TextColor
}
##############################
#.SYNOPSIS
# Saves the current Visual Studio Solution based on $dte.Solution.FullName
#
#.DESCRIPTION
# Saves the current Visual Studio Solution based on $dte.Solution.FullName
#
#.EXAMPLE
#
# #To Run
# > Save-VisualStudioSolution
#
#.NOTES
# Private Method
##############################
function Save-VisualStudioSolution {
try {
$dte.Solution.SaveAs($dte.Solution.FullName)
Write-Host "$($dte.Solution.FullName) Successfully saved."
}
catch {
# Write the error information then rethrow
# We need the error information in the log
# The rethrow is for any calling script
Write-Error $_ -ErrorAction Continue
throw
}
}
##############################
#.SYNOPSIS
# Adds a folder to the Visual Studio Project Item if the folder does not already exist.
# Folders added this way also are added to the file system.
# The created folder is then returned for usage in other scripts.
#
#.DESCRIPTION
# Adds a folder to the Visual Studio Project Item if the folder does not already exist.
# Folders added this way also are added to the file system.
# The created folder is then returned for usage in other scripts.
#
#.PARAMETER ProjectItem
# Visual Studio Project Item (could be a folder, soltuion, or project) that the new folder is to be added to
#
# REQUIRED
#
#.PARAMETER FolderName
# Name of the new folder to be added
#
# REQUIRED
#
#.EXAMPLE
# > $project = Get-Project 'Coffeehouse.Feature.CouponCode'
# > Add-FolderToProjectItem -ProjectItem $proj -FolderName 'Controllers'
#
#.NOTES
# Private Method
##############################
function Add-FolderToProjectItem {
Param(
[Parameter(Position = 0, Mandatory = $True)]
[object]$ProjectItem,
[Parameter(Position = 1, Mandatory = $True)]
[string]$FolderName
)
try {
$folderItem = Get-ProjectItem -ProjectItem $ProjectItem -ItemName $FolderName
if ($folderItem -eq $null) {
$folderItem = $ProjectItem.ProjectItems.AddFolder($FolderName)
}
else {
Write-Host "$FolderName already existed"
}
return $folderItem
}
catch {
Write-Error $_ -ErrorAction Continue
throw
}
}
##############################
#.SYNOPSIS
# Creates a folder on the file system and then a parallel Solution folder.
#
#.DESCRIPTION
# Creates a folder on the file system and then a parallel Solution folder.
#
# .PARAMETER SourceFolderPath
# The fully qualified path(on the file system) to parent of the directory that is to be created
#
# REQUIRED
#
# .PARAMETER FolderName
# Name of the folder that will be created on the file system as well as have a solution folder added.
#
# REQUIRED
#
#.EXAMPLE
#
# #To Run
# > Add-SolutionFolder -SourceFolderPath 'C:\Repo\Helix.Sample\src' -FolderName Foundation
#
#.NOTES
# Private Method
##############################
function Add-SolutionFolder {
param(
[parameter(Mandatory = $true)]
[string]$SourceFolderPath,
[parameter(Mandatory = $true)]
[string]$FolderName
)
#CHECK DIRECTORY, CREATE IF NEEDED
if (-NOT (Test-path -Path $SourceFolderPath)) {
Write-Host "$SourceFolderPath directory does not exist, going to create it"
New-Item -Path $SourceFolderPath -ItemType Directory
}
Write-Host 'Create $FolderName folder in solution and on file system'
New-Item -Path $SourceFolderPath -Name $FolderName -ItemType Directory
return $dte.Solution.AddSolutionFolder($FolderName)
}
##############################
#.SYNOPSIS
# Performs a NuGet Package Install (ie Install-Package) to the given project ($ProjectName).
# If no $PackageVersion is given the latest version is installed.
#
#.DESCRIPTION
# Performs a NuGet Package Install (ie Install-Package) to the given project ($ProjectName).
# If no $PackageVersion is given the latest version is installed.
#
#.PARAMETER ProjectName
# Name of the project the NuGet package should be installed against
#
# REQUIRED
#
#.PARAMETER PackageName
# Name of NuGet Package to be installed
#
# REQUIRED
#
#.PARAMETER PackageVersion
# Version number of the package that should be installed
# If NO version is provided then the latest version will be isntalled of the package
#
# OPTIONAL
#
#.EXAMPLE 1
# > Add-PackageToModule -ProjectName 'Coffeehouse.Feature.CouponCode' -PackageName 'Sitecore.Kernel.NoReference'
#
#.EXAMPLE 2
# > Add-PackageToModule -ProjectName 'Coffeehouse.Feature.CouponCode' -PackageName 'Microsoft.Extensions.DependencyInjection.Abstraction' -PackageVersion '1.0.0'
#
#.NOTES
# Private Method
##############################
function Add-PackageToModule {
Param(
[Parameter(Mandatory = $true)]
[string]$ProjectName,
[Parameter(Mandatory = $true)]
[string]$PackageName,
[Parameter( Mandatory = $false)]
[string]$PackageVersion
)
try {
if ($PackageVersion) {
Install-Package $PackageName -ProjectName $ProjectName $PackageVersion
}
else {
Install-Package $PackageName -ProjectName $ProjectName
}
}
catch {
Write-Error $_ -ErrorAction Continue
}
}
##############################
#.SYNOPSIS
# For the given project ($ProjectName) performs some basic setup of the project for use.
# Elements that are configured for the project are:
# * Web.config build action is set to NONE
# * Set Target .NET Framework to given value or default of 4.7.2
# * NuGet Install of - Sitecore.Kernel
# * NuGet Install of - Sitecore.Mvc
# * Set all Reference DLLs to be Copy Local = False
#
#.DESCRIPTION
# For the given project (ProjectName) performs some basic setup of the project for use.
# Elements that are configured for the project are:
# * Web.config build action is set to NONE
# * Set Target .NET Framework to given value or default of 4.7.2
# * NuGet Install of - Sitecore.Kernel
# * NuGet Install of - Sitecore.Mvc
# * Set all Reference DLLs to be Copy Local = False
#
#.PARAMETER ProjectName
# Name of the project to be updated
#
# REQUIRED
#
#.PARAMETER SitecoreVersion
# Optional parameter, that identifies which version of Sitecore NuGet Packages will be installed.
# If no value is provided the latest version will be installed.
#
# Parameter validation will force proper formatt of #.#.#### for example 9.0.171219
# Regex is: ^[7-9]{1}\.\d{1}\.\d{6}$|\s*
#
#
# DEAULT VALUE: 9.3.0
#
# OPTIONAL
#
#.PARAMETER DotNETTargetFramework
# Enter the version of the .NET Framwork that the project should build as.
#
# For reference: 262662 - representing 4.6.2
# For reference: 262407 - representing 4.7.1
# DEFAULT VALUE: 262663 - representing 4.7.2
#
# OPTIONAL
#
#.EXAMPLE 1
# > Set-ModuleFiles -ProjectName 'Coffeehouse.Feature.CouponCode'
#
#.EXAMPLE 2
# > Set-ModuleFiles -ProjectName 'Coffeehouse.Feature.CouponCode' -SitecoreVersion '8.2.161115'
#
#.EXAMPLE 3
# > Set-ModuleFiles -ProjectName 'Coffeehouse.Feature.CouponCode' -SitecoreVersion '8.2.161115' -DotNETTargetFramework '25023'
#
#.NOTES
# Private Method
##############################
function Set-ModuleFiles {
Param(
[Parameter(Position = 0, Mandatory = $True)]
[string]$ProjectName,
[Parameter(Position = 1, Mandatory = $false)]
[ValidatePattern("^[7-9]{1}\.\d{1}\.\d{6}$|\s*")]
[string] $SitecoreVersion = "9.3.0",
[Parameter(Position = 2, Mandatory = $false)]
[string] $DotNETTargetFramework = '262663'
)
try {
Write-Host "Set Module Files: Save Solution to ensure clean start"
Save-VisualStudioSolution
#Get Module Project
Write-Host "Set Module Files: Get $ProjectName from Solution"
$moduleProj = Get-Project $ProjectName
if ($moduleProj -eq $null) {
Write-Host "Set Module Files: Project named $ProjectName not found" -ForegroundColor Red
Write-Host "Set Module Files: Canceled - no file setup can happen" -ForegroundColor Red
return
}
#Get Web.config and set to BUILD ACTION = NONE
$webConfig = $moduleProj.ProjectItems | Where-Object { $_.Name -eq 'Web.config' }
if ($webConfig -ne $null) {
Write-Host "Set Module Files: Setting web.config build action to none"
($webConfig.Properties | Where-Object { $_.Name -eq 'BuildAction' }).Value = 0
Save-VisualStudioSolution
}
$moduleProj = Get-Project -Name $ProjectName
if ($moduleProj -eq $null) {
Write-Host "Set Module Files: Project named $ProjectName not found" -ForegroundColor Red
Write-Host "Set Module Files: Canceled - no file setup can happen" -ForegroundColor Red
return
}
# #Set Target Framework
Write-Host "Set Module Files: Set Target Framework to $DotNETTargetFramework"
$moduleProj.Properties["TargetFramework"].Value = $DotNETTargetFramework
Save-VisualStudioSolution
##Need to reload object for additional work.
$moduleProj = Get-Project -Name $ProjectName
if ($moduleProj -eq $null) {
Write-Host "Set Module Files: Project named $ProjectName not found" -ForegroundColor Red
Write-Host "Set Module Files: Canceled - no file setup can happen" -ForegroundColor Red
return
}
#Install Sitecore.Kernel
Write-Host "Set Module Files: Add Sitecore.Kernel version $SitecoreVersion"
Add-PackageToModule -ProjectName $ProjectName -PackageName "Sitecore.Kernel" -PackageVersion $SitecoreVersion
$moduleProj.Save()
#Install Sitecore.MVC.NoReference
Write-Host "Set Module Files: Add Sitecore.MVC version $SitecoreVersion"
Add-PackageToModule -ProjectName $ProjectName -PackageName "Sitecore.Mvc" -PackageVersion $SitecoreVersion
$moduleProj.Save()
$appStartPath = $moduleProj.ProjectItems["App_Start"].Properties["FullPath"].Value
$moduleProj.ProjectItems["App_Start"].Remove()
Remove-Item $appStartPath -Recurse
$moduleProj.Save()
#Set All Assemblies as CopyLocal = False
Write-Host "Set Module Files: Setting all references to Copy Local = False"
$moduleProj.Object.References | ForEach-Object { try { $_.CopyLocal = $false }catch { } }
$moduleProj.Save()
#SAVE SOLUTION - not sure if it is needed but just feels right to do a save after this work.
Write-Host "Set Module Files: Save Solution"
Save-VisualStudioSolution
}
catch {
Write-Error $_ -ErrorAction Continue
throw
}
}
##############################
#.SYNOPSIS
# Adds a Module specific config file to App_Config -> Include -> $Layer
# The config is then updated to be a proper Sitecore patch file with the Dependecy Registar already added.
#
#.DESCRIPTION
# Adds a Module specific config file to App_Config -> Include -> $Layer
# The config is then updated to be a proper Sitecore patch file with the Dependecy Registar already added.
#
#.PARAMETER ProjectName
# Name of the project (module) to be add the config file to
#
# REQUIRED
#
#.PARAMETER Layer
# Type of project (module), should follow the naming convention of the solution.
# Default Helix naming would be Feature, Foundation, Project
#
# REQUIRED
#
#.PARAMETER TemplatePath
# Path to the configuration template to be used.
# In most instances this will be generated from a previous step call to Get-VisualStudioTemplate
#
# REQUIRED
#
#.EXAMPLE
# > Add-ModuleConfigFile -ProjectName 'Coffeehouse.Feature.CouponCode' -Layer 'Feature' -TemplatePath "C:\Programs\VS\webconfig.vstemplate"
#
#.NOTES
# Private Method
##############################
function Add-ModuleConfigFile {
Param(
[Parameter(Position = 0, Mandatory = $True)]
[string]$ProjectName,
[Parameter(Position = 1, Mandatory = $True)]
[ValidateSet("Feature", "Foundation", "Project")]
[string]$Layer,
[Parameter(Position = 2, Mandatory = $True)]
[string]$TemplatePath,
[Parameter(Position = 3, Mandatory = $false)]
[switch]$IncludeUnicorn
)
try {
Save-VisualStudioSolution
#Load Project
$moduleProj = Get-Project -Name $ProjectName
if ($moduleProj -eq $null) {
Write-Host "Add Module Config Files: Project named $ProjectName not found" -ForegroundColor Red
Write-Host "Add Module Config Files: No file setup can happen" -ForegroundColor Red
return
}
$namespace = $moduleProj.Properties["DefaultNamespace"].Value
# App_Config
$appConfigFolderObj = Get-ProjectItem -ProjectItem $moduleProj -ItemName "App_Config"
if (-Not $appConfigFolderObj) {
Write-Host "Add Module Config Files: Create App_Config"
$appConfigFolderObj = $moduleProj.ProjectItems.AddFolder("App_Config")
}
$includeConfigFolderObj = Get-ProjectItem -ProjectItem $moduleProj -ItemName "Include"
if (-Not $includeConfigFolderObj) {
Write-Host "Add Module Config Files: Create App_Config\Include"
$includeConfigFolderObj = $appConfigFolderObj.ProjectItems.AddFolder("Include")
}
$layerFolderObj = Get-ProjectItem -ProjectItem $moduleProj -ItemName $Layer
if (-Not $layerFolderObj) {
Write-Host "Add Module Config Files: Create App_Config\Include\$Layer"
$layerFolderObj = $includeConfigFolderObj.ProjectItems.AddFolder($Layer)
}
$moduleProj.Save()
Save-VisualStudioSolution
$layerFolderObj = Get-ProjectItem -ProjectItem $moduleProj -ItemName $Layer
$layerFolderPath = $layerFolderObj.Properties["LocalPath"].Value
Write-Host "Add Module Config Files: Create DI Config"
#Create Default Configurations
$configTemplate = @"
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<services>
<configurator type="{0}.DI.RegisterContainer, {0}" />
</services>
<settings>
</settings>
</sitecore>
</configuration>
"@
Write-Host " Add Module Config Files: DI Config Set content"
Set-Content -Path "$layerFolderPath\$namespace.config" -Value $($configTemplate -f $namespace)
Write-Host "Create DI Config: Add to Project"
$configPath = $layerFolderPath + "$namespace.config"
Write-Host "Create DI Config: $configPath"
$layerFolderObj.ProjectItems.AddFromFile($configPath)
if ($IncludeUnicorn) {
Write-Host "Add Unicorn config"
$configTemplate = @"
<!--See Unicorn.config for commentary on how configurations operate, or https://github.com/kamsar/Unicorn/blob/master/README.md-->
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<unicorn>
<configurations>
<configuration name="{1}" description="{0} {1}" dependencies="Foundation.*" extends="Helix.Base">
<predicate>
<include name="Templates" database="master" path="/sitecore/templates/{0}/{1}"/>
<include name="Renderings" database="master" path="/sitecore/layout/Renderings/{0}/{1}"/>
</predicate>
</configuration>
</configurations>
</unicorn>
</sitecore>
</configuration>
"@
$configFileName = "{0}.Serialization.config" -f $namespace
Write-Host "Unicorn Config: Set content"
Set-Content -Path "$layerFolderPath\$configFileName" -Value $($configTemplate -f $Layer, $ModuleName)
Write-Host "Unicorn Config: Add to Project"
$configPath = $layerFolderPath + $configFileName
Write-Host "Unicorn Config: $configPath"
$layerFolderObj.ProjectItems.AddFromFile($configPath)
}
Write-Host "Add Module Config Files: $projModuleName Saving module (project)"
$moduleProj.Save()
Save-VisualStudioSolution
Write-Host "Add Module Config Files: $projModuleName Module specific config update complete"
}
catch {
Write-Error $_ -ErrorAction Continue
throw
}
}
##############################
#.SYNOPSIS
# Adds default folders to a Helix based project for
# * DI
# * Views
# * Views\<ModuleName>
# * Repositories
# * Constants
# * Controllers
# * Models
#
# Folders are created via a call to Add-FolderToProjectItem, which creates the folder both in the solution and on the file system
#
#.DESCRIPTION
# Adds default folders to a Helix based project for
# * DI
# * Views
# * Views\<ModuleName>
# * Repositories
# * Constants
# * Controllers
# * Models
#
# Folders are created via a call to Add-FolderToProjectItem, which creates the folder both in the solution and on the file system
#
#.PARAMETER ProjectName
# Name of the project being updated
#
#.EXAMPLE
# > Add-ModuleDefaultFolders -ProjectName 'Coffeehouse.Feature.CouponCode'
#
#.NOTES
#Private Method
##############################
function Add-ModuleDefaultFolders {
Param(
[Parameter(Mandatory = $true)]
[string]$ProjectName
)
try {
Write-Host "Add Module Default Folders: $ProjectName Begin"
Save-VisualStudioSolution
#Load Project
$moduleProj = Get-Project -Name $ProjectName
if ($moduleProj -eq $null) {
Write-Host "Add Module Default Folders: Project ProjectName not found"
Write-Host "Add Module Default Folders: $ProjectName no setup can happen"
return
}
#Create Folders
## DI Folder
Add-FolderToProjectItem -ProjectItem $moduleProj -FolderName 'DI'
## Views Folder
$viewFolder = Add-FolderToProjectItem -ProjectItem $moduleProj -FolderName 'Views'
Add-FolderToProjectItem -ProjectItem $viewFolder -FolderName $($ProjectName.Split(".") | Select-Object -Last 1)
## Repositories Folder
Add-FolderToProjectItem -ProjectItem $moduleProj -FolderName 'Repositories'
## Constants Folder
Add-FolderToProjectItem -ProjectItem $moduleProj -FolderName 'Constants'
## Models Folder
Add-FolderToProjectItem -ProjectItem $moduleProj -FolderName 'Models'
## Controllers Folder
Add-FolderToProjectItem -ProjectItem $moduleProj -FolderName 'Controllers'
Write-Host "Add Module Default Folders: $ProjectName Saving module (project)"
$moduleProj.Save()
Write-Host "Add Module Default Folders: $ProjectName Save Solution"
Save-VisualStudioSolution
Write-Host "Add Module Default Folders: $ProjectName Completed"
}
catch {
Write-Error $_ -ErrorAction Continue
throw
}
}
##############################
#.SYNOPSIS
# Creates a RegisterContainer.cs file inside the folder 'DI' with the following logic
#
#using Microsoft.Extensions.DependencyInjection;
#using Sitecore.DependencyInjection;
#
#namespace {0}.DI
#{
# public class RegisterContainer : IServicesConfigurator
# {
# public void Configure(IServiceCollection serviceCollection)
# {
# //serviceCollection.AddTransient<ContentController>();
# //serviceCollection.AddTransient<IAccountRepository, AccountRepository>();
# }
# }
#}
#
#.DESCRIPTION
# Creates a RegisterContainer.cs file inside the folder 'DI'
#
#.PARAMETER ProjectName
# Name of project (module) that the register container should be created for
# Example: Coffeehouse.Feature.CouponCode
#
# REQUIRED
#
#.PARAMETER ClassTemplatePath
# Path to the C# class template
#
# REQUIRED
#
#.EXAMPLE
# > Add-RegisterContainerClass 'Coffeehouse.Feature.CouponCode' 'C:\Programs\VS\class.vstemplate'
#
#.NOTES
#Private Method
##############################
function Add-RegisterContainerClass {
Param(
[Parameter(Position = 0, Mandatory = $True)]
[string]$ProjectName,
[Parameter(Position = 1, Mandatory = $True)]
[string]$ClassTemplatePath
)
try {
Write-Host "Add Register Container Class: $ProjectName Begin"
Save-VisualStudioSolution
#Load Project
$moduleProj = Get-Project -Name $ProjectName
if ($moduleProj -eq $null) {
Write-Host "Add Register Container Class: Project $ProjectName not found"
Write-Host "Add Register Container Class: No setup can happen"
return
}
$DIFolder = Get-ProjectItem -ProjectItem $moduleProj -ItemName 'DI'
if ($DIFolder -ne $null) {
Write-Host "Add Register Container Class: $ProjectName Creating RegisterContainer.cs in solution"
$ModuleFileSystemPath = Split-Path $moduleProj.FullName
$DIFolder.ProjectItems.AddFromTemplate($ClassTemplatePath, "RegisterContainer.cs")
$moduleProj.Save()
Save-VisualStudioSolution
Write-Host "Add Register Container Class: $ProjectName Begin content update"
$RegisterTemplate = @"
using Microsoft.Extensions.DependencyInjection;
using Sitecore.DependencyInjection;
namespace MODULENAME.DI
{
public class RegisterContainer : IServicesConfigurator
{
public void Configure(IServiceCollection serviceCollection)
{
//serviceCollection.AddTransient<ContentController>();
//serviceCollection.AddTransient<IAccountRepository, AccountRepository>();
}
}
}
"@
$rt = $RegisterTemplate.Replace("MODULENAME", $($moduleProj.Properties["DefaultNamespace"].Value))
Write-Host "Add Register Container Class: Updating contents of RegisterContainer.cs"
Set-Content -Path $($ModuleFileSystemPath + '\DI\RegisterContainer.cs') -Value $rt
Write-Host "Add Register Container Class: Content update for $($ModuleFileSystemPath+'\DI\RegisterContainer.cs')"
}
}
catch {
Write-Error $_ -ErrorAction Continue
throw
}
}
##############################
#.SYNOPSIS
# Performs a number of differnt steps in setting up and configuring the Module Web project.
#
# STEP 1: Configures the following for the project:
# * Web.config build action is set to NONE
# * Set Target .NET Framework to given value or default of 4.7.2
# * NuGet Install of - Sitecore.Kernel version 9.3.0
# * NuGet Install of - Sitecore.Mvc version 9.3.0
# * Set all Reference DLLs to be Copy Local = False
#
# STEP 2: Adds a Module specific config file to App_Config -> Include -> $Layer, which is then configured for Dependecny Register class
#
# STEP 3: Adds default folders to a Helix based project for
# * DI
# * Views
# * Views\$ModuleName
# * Repositories
# * Constants
# * Controllers
# * Models
#
# STEP 4: Creates a RegisterContainer.cs file inside the folder 'DI' with the default logic
#
#.DESCRIPTION
# Performs a number of differnt steps in setting up and configuring the Module Web project.
#
# STEP 1: Configures the following for the project:
# * Web.config build action is set to NONE
# * Set Target .NET Framework to given value or default of 4.7.2
# * NuGet Install of - Sitecore.Kernel version 9.3.0
# * NuGet Install of - Sitecore.Mvc version 9.3.0
# * Set all Reference DLLs to be Copy Local = False
#
# STEP 2: Adds a Module specific config file to App_Config -> Include -> $Layer, which is then configured for Dependecny Register class
#
# STEP 3: Adds default folders to a Helix based project for
# * DI
# * Views
# * Views\$ModuleName
# * Repositories
# * Constants
# * Controllers
# * Models
#
# STEP 4: Creates a RegisterContainer.cs file inside the folder 'DI' with the default logic
#
#.PARAMETER ModuleName
# Name of the Module, this should NOT include the namespace
# Example, correct: PageContent
# Example, not correct: Coffeehouse.Feature.PageContent
#
# REQUIRED
#
#.PARAMETER Layer
# Which layer will the module be created under.
# Parameter validation will limit to "Feature", "Foundation", or "Project"
#
# REQUIRED
#
#.PARAMETER SitecoreVersion
# Optional parameter, that identifies which version of Sitecore NuGet Packages will be installed.
# If no value is provided the latest version will be installed. (9.3.0)
#
# Parameter validation will force proper formatt of #.#.#### for example 9.0.171219
# Regex is: ^[7-9]{1}\.\d{1}\.\d{6}$|\s*
#
# OPTIONAL
#
#.PARAMETER TemplateName
# Name with extension of the Visual Studio Template that is used to create a Class file (ex: .cs) type file.
#
# DEFAULT: Class.vstemplate
#
# OPTIONAL
#
#.PARAMETER TemplateFilter
# String representing a filter for the path the above TemplateName would exist at. This is used to locate the correct template, when the name is re-used
#
# DEFAULT: '*Web\CSharp\*'
#
# OPTIONAL
#
#.PARAMETER UseUnicorn
# Switch (flag) parameter.
# Include flag to setup Unicorn serialization config files.
#
# OPTIONAL
#
#.EXAMPLE 1
# > Invoke-ModuleFileSetup -ModuleName "ShoppingHistory" -Layer "Feature" -UseUnicorn
#
#.EXAMPLE 2
# > Invoke-ModuleFileSetup -ModuleName "ShoppingHistory" -Layer "Feature" -SitecoreVersion 9.2.0
#
#.NOTES
# Priavte Method
##############################
function Invoke-ModuleFileSetup {
[CmdletBinding(SupportsShouldProcess = $true)]
param(
[parameter(Mandatory = $true)]
[string]$ModuleName,
[parameter(Mandatory = $true)]
[ValidateSet("Feature", "Foundation", "Project")]
[string]$Layer,
[parameter(Mandatory = $false)]
[ValidatePattern("^[7-9]{1}\.\d{1}\.\d{6}$|\s*")]
[string]$SitecoreVersion = "9.3.0",
[parameter(Mandatory = $false)]
[string]$TemplateName = "Class.vstemplate",
[parameter(Mandatory = $false)]
[string]$TemplateFilter = '*Web\CSharp\*',
[parameter(Mandatory = $false)]
[switch]$UseUnicorn
)
PROCESS {
Write-StepHeader "$ModuleName - File Setup" -TaskType "Module"
$projModuleName = "$($dte.Solution.Properties["Name"].Value).$Layer.$ModuleName"
if ($pscmdlet.ShouldProcess("$ModuleName", "Begin file setup of new Module")) {
##STEP 1: Install NuGet Packages, Set References to not copy
Write-Host "Setup: $ModuleName 1. Set Module Files"
Set-ModuleFiles -ProjectName $projModuleName -SitecoreVersion $SitecoreVersion
##STEP 2: Added Module Config File
$webConfigTemplate = Get-VisualStudioTemplate -TemplateName 'WebConfig.vstemplate' -FilterValue '*CSharp\Web*'
Write-Host "Setup: $ModuleName 2. Create Module Config File"
Add-ModuleConfigFile -ProjectName $projModuleName -Layer $Layer -TemplatePath $webConfigTemplate -IncludeUnicorn:$UseUnicorn
##STEP 3: Created Default folders: DI, Views, Repositories, Constants, Controllers, Models
Write-Host "Setup: $ModuleName 3. Begin Module Default File Creation (DI, Views, Repositories, Constants, Controllers, Models"
Add-ModuleDefaultFolders -ProjectName $projModuleName
##STEP 4:
Write-Host "Setup: $ModuleName 4. Create and update RegisterContainer.cs"
$classTemplatePath = Get-VisualStudioTemplate -TemplateName $TemplateName -FilterValue $TemplateFilter
Add-RegisterContainerClass -ProjectName $projModuleName -ClassTemplatePath $classTemplatePath
}
}
}
## PRIVATE METHODS - end ##
## PUBLIC METHODS - start ##
##############################
#.SYNOPSIS
# Returns the file name and path of a given Visual Studio Template as requested.
# An additional filter value can be supplied to check that the path of the template matches a specific location/type
#
#.DESCRIPTION
# Returns the file name and path of a given Visual Studio Template as requested.
# An additional filter value can be supplied to check that the path of the template matches a specific location/type
#
#.PARAMETER TemplateName
# Name of the Template to be found
#
# REQUIRED
#
# ex: webconfig.vstemplate
#
#.PARAMETER DefaultVisualStudioInstall
# Path to where Templates have been installed.
# Default is to a 2019 Visual Studio Installation
# DEFAULT VALUE: 'C:\Program Files (x86)\Microsoft Visual Studio\2019'
#
# OPTIONAL
#
# ex: 'C:\Program Files (x86)\Microsoft Visual Studio\2019'
#
#.PARAMETER FilterValue
# Value of filter that the path should include.
# Used to limit similar named templates to a specific version
#
# OPTIONAL
#
# ex: '*Web\CSharp\*'
#
#.EXAMPLE
# > $DefaultVisualStudioInstall = 'C:\Program\VS'
# > Get-VisualStudioTemplate -TemplateName 'TDS Project.vstemplate'
# > 'C:\Program\VS\Templates\TDSProject.vstemplate'
#
# > Get-VisualStudioTemplate -TemplateName 'Class.vstemplate' -FilterValue '*Web\CSharp*
# > 'C:\Program\VS\Templates\Custom\Web\cSharp\Class.vstemplate'
#
#.NOTES
# Private Method
##############################
function Get-VisualStudioTemplate {
param(
[parameter(Position = 0, Mandatory = $true)]
[string]$TemplateName,
[parameter(Mandatory = $false)]
[string]$DefaultVisualStudioInstall = 'C:\Program Files (x86)\Microsoft Visual Studio\2019',
[parameter(Mandatory = $false)]
[string]$FilterValue
)
try {
if ($FilterValue) {
return (Get-ChildItem -Path $DefaultVisualStudioInstall -Filter $TemplateName -Recurse -ErrorAction SilentlyContinue -Force | Where-Object { $_.FullName -like $FilterValue } | Select-Object -First 1).FullName
}
else {
return (Get-ChildItem -Path $DefaultVisualStudioInstall -Filter $TemplateName -Recurse -ErrorAction SilentlyContinue -Force | Select-Object -First 1).FullName
}
}
catch {
# Write the error information then rethrow
# We need the error information in the log
# The rethrow is for any calling script
Write-Error $_ -ErrorAction Continue
throw
}
}
##############################
#.SYNOPSIS
# Recursively loops through the current Solution as defined by $dte.Solution object for a project itme of type 'Solution Folder' with the given name.
# The found folder is returned as a [nvDTE80.SolutionFolder] object
#
#.DESCRIPTION
# Recursively loops through the current Solution as defined by $dte.Solution object for a project itme of type 'Solution Folder' with the given name.
# The found folder is returned as a [nvDTE80.SolutionFolder] object
#
#.PARAMETER ItemName
# Name of the Solution Folder to be returned
#
# REQUIRED
#
#.EXAMPLE
# > Get-SolutionFolder 'Feature'
#
#.NOTES
# Public Method
##############################
function Get-SolutionFolder {
param( [parameter(Mandatory = $true)]
[string]$ItemName)
try {
return $dte.Solution.Projects | Where-Object { $_.Name -eq $ItemName } | Select-Object -First 1
}
catch {
# Write the error information then rethrow
# We need the error information in the log
# The rethrow is for any calling script
Write-Error $_ -ErrorAction Continue
throw
}
}
##############################
#.SYNOPSIS
# Performs a recursive search through a Visual Studio Project Item's ProjectItems collection for the given item name.
# All branches are searched looking for the first return of the item
# If no item is found then $null is returned.
#
#.DESCRIPTION
# Performs a recursive search through a Visual Studio Project Item's ProjectItems collection for the given item name.
# All branches are searched looking for the first return of the item
# If no item is found then $null is returned.
#
#.PARAMETER ProjectItem
# Visual Studio Project Item object whose children should be searched
#
# REQUIRED
#
#.PARAMETER ItemName
# Name of the item to be found
#
# REQUIRED
#