Compare commits
166
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93badabcb1 | ||
|
|
181a7cb27d | ||
|
|
0418be4318 | ||
|
|
037580b305 | ||
|
|
4fffb9f7a7 | ||
|
|
78cfb29908 | ||
|
|
20f0ceeda6 | ||
|
|
0d836875c7 | ||
|
|
04c292f167 | ||
|
|
b97d016c13 | ||
|
|
0aa4d1956a | ||
|
|
cde312b6d4 | ||
|
|
a9daab5a15 | ||
|
|
c7e45ae13a | ||
|
|
1ab0bb9254 | ||
|
|
8746d4c13d | ||
|
|
5d9e2b0bb8 | ||
|
|
c20f45dcfc | ||
|
|
fff3e5e9d4 | ||
|
|
413a278373 | ||
|
|
5d6fc6005c | ||
|
|
d9d5dc5626 | ||
|
|
2ff2ae3f0a | ||
|
|
cfacf4e150 | ||
|
|
d8551e4640 | ||
|
|
373138d70f | ||
|
|
10d252819d | ||
|
|
ca5c85e656 | ||
|
|
a6aaf4b0b1 | ||
|
|
44e8808079 | ||
|
|
59b0224eff | ||
|
|
65723ea9ec | ||
|
|
50a239a016 | ||
|
|
5ef013ca62 | ||
|
|
ff477c3930 | ||
|
|
1cdc6f0fd2 | ||
|
|
49e0e6c1c9 | ||
|
|
7e9def9df4 | ||
|
|
009b36b49e | ||
|
|
44ddf7acef | ||
|
|
6b3a589aa0 | ||
|
|
95f1ed33ec | ||
|
|
993c582bd9 | ||
|
|
a72698e1a9 | ||
|
|
c905fdd9b5 | ||
|
|
34bfd3a8f3 | ||
|
|
dfbb182a94 | ||
|
|
aba4f02bad | ||
|
|
a27da0fced | ||
|
|
0c7ef06031 | ||
|
|
e6d6dce3a8 | ||
|
|
24d2dcf363 | ||
|
|
25ea5cdb1b | ||
|
|
cf3d697bc5 | ||
|
|
6fd45f653c | ||
|
|
d97d0040c2 | ||
|
|
aa62417916 | ||
|
|
62e3286c71 | ||
|
|
d433991b61 | ||
|
|
bc24efa812 | ||
|
|
6d52a2f3da | ||
|
|
66961d18dc | ||
|
|
fa0027d4f1 | ||
|
|
a24b099831 | ||
|
|
6860d0b27d | ||
|
|
dad1c190fc | ||
|
|
36faff6917 | ||
|
|
7ddddb7500 | ||
|
|
b56f0f7062 | ||
|
|
9121879e1a | ||
|
|
69132faffa | ||
|
|
4a6c409a1f | ||
|
|
4351ce6ee4 | ||
|
|
1b56a260b8 | ||
|
|
de4b3af28f | ||
|
|
321d5b49bd | ||
|
|
366d7c0fce | ||
|
|
860c8e8ae2 | ||
|
|
15bedfbc76 | ||
|
|
fe0ec420eb | ||
|
|
860792ff3f | ||
|
|
169d07b0cc | ||
|
|
8c5a5af41b | ||
|
|
411fb0c120 | ||
|
|
27c60277f2 | ||
|
|
dafd7f298d | ||
|
|
e67da0b198 | ||
|
|
4f0a837e20 | ||
|
|
864fd2a45a | ||
|
|
8877c9c73d | ||
|
|
ab870347ed | ||
|
|
06f2408ebc | ||
|
|
a53d28310f | ||
|
|
9568d0cd6d | ||
|
|
aba5edce02 | ||
|
|
791e4f92a1 | ||
|
|
566648de3f | ||
|
|
a13e66d559 | ||
|
|
3a269ed329 | ||
|
|
7f762df952 | ||
|
|
27a3431e76 | ||
|
|
7cc495dc65 | ||
|
|
b581a45e05 | ||
|
|
76fc3f8201 | ||
|
|
555b4fadf1 | ||
|
|
79817f5463 | ||
|
|
ff6a8d781d | ||
|
|
789a908a31 | ||
|
|
336f2c2d5b | ||
|
|
8b6c844a55 | ||
|
|
f1c83fbd80 | ||
|
|
0f4020dc7b | ||
|
|
62fa1695df | ||
|
|
de2668a621 | ||
|
|
a34e278a40 | ||
|
|
461043bd82 | ||
|
|
7f9b143e1a | ||
|
|
91c4c77676 | ||
|
|
d1f1817744 | ||
|
|
8393a5ba04 | ||
|
|
cf410ab91e | ||
|
|
df6c8a4ecc | ||
|
|
be6e0879e4 | ||
|
|
731b06a987 | ||
|
|
6f89bf2a45 | ||
|
|
4eda091fdb | ||
|
|
b63aa4b19c | ||
|
|
8c780573f4 | ||
|
|
0b0182f550 | ||
|
|
158f4d29f6 | ||
|
|
139c5791a5 | ||
|
|
27ef97bf34 | ||
|
|
d6f968eee4 | ||
|
|
a6ce7bcdf6 | ||
|
|
0200434227 | ||
|
|
9a5bcf290d | ||
|
|
ec183e481c | ||
|
|
924a819baa | ||
|
|
3af6645ad8 | ||
|
|
824bc2ac28 | ||
|
|
febdac5713 | ||
|
|
22dd3a214c | ||
|
|
4382868f82 | ||
|
|
5c019a1557 | ||
|
|
bdcb5d859e | ||
|
|
1810cec80a | ||
|
|
472cc716c4 | ||
|
|
3167c8b213 | ||
|
|
2abf455abf | ||
|
|
f2450fb539 | ||
|
|
c0dfb33916 | ||
|
|
477697a70c | ||
|
|
5de36f5669 | ||
|
|
a71529a058 | ||
|
|
deff17e622 | ||
|
|
8c822c59ac | ||
|
|
c79380191b | ||
|
|
a779803763 | ||
|
|
1b98f8985e | ||
|
|
56d54d441f | ||
|
|
9dbe2d211c | ||
|
|
aae8694618 | ||
|
|
6a95ff366f | ||
|
|
c3b619fbbf | ||
|
|
366a8ba565 | ||
|
|
50da4a77de |
@@ -306,48 +306,6 @@ dotnet_naming_rule.other_public_protected_fields_disallowed_rule.symbols
|
||||
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.style = disallowed_style
|
||||
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.severity = error
|
||||
|
||||
##########################################
|
||||
# StyleCop Field Naming Rules
|
||||
# Naming rules for fields follow the StyleCop analyzers
|
||||
# This does not override any rules using disallowed_style above
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers
|
||||
##########################################
|
||||
|
||||
# All constant fields must be PascalCase
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1303.md
|
||||
dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
|
||||
dotnet_naming_symbols.stylecop_constant_fields_group.required_modifiers = const
|
||||
dotnet_naming_symbols.stylecop_constant_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.symbols = stylecop_constant_fields_group
|
||||
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.style = pascal_case_style
|
||||
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.severity = warning
|
||||
|
||||
# All static readonly fields must be PascalCase
|
||||
# Ajusted to ignore private fields.
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md
|
||||
dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected
|
||||
dotnet_naming_symbols.stylecop_static_readonly_fields_group.required_modifiers = static, readonly
|
||||
dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.symbols = stylecop_static_readonly_fields_group
|
||||
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style
|
||||
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.severity = warning
|
||||
|
||||
# No non-private instance fields are allowed
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1401.md
|
||||
dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected
|
||||
dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_kinds = field
|
||||
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.symbols = stylecop_fields_must_be_private_group
|
||||
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.style = disallowed_style
|
||||
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.severity = error
|
||||
|
||||
# Local variables must be camelCase
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md
|
||||
dotnet_naming_symbols.stylecop_local_fields_group.applicable_accessibilities = local
|
||||
dotnet_naming_symbols.stylecop_local_fields_group.applicable_kinds = local
|
||||
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.symbols = stylecop_local_fields_group
|
||||
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.style = camel_case_style
|
||||
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.severity = silent
|
||||
|
||||
# This rule should never fire. However, it's included for at least two purposes:
|
||||
# First, it helps to understand, reason about, and root-case certain types of issues, such as bugs in .editorconfig parsers.
|
||||
# Second, it helps to raise immediate awareness if a new field type is added (as occurred recently in C#).
|
||||
@@ -357,7 +315,6 @@ dotnet_naming_rule.sanity_check_uncovered_field_case_rule.symbols = sanity_chec
|
||||
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.style = internal_error_style
|
||||
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.severity = error
|
||||
|
||||
|
||||
##########################################
|
||||
# Other Naming Rules
|
||||
##########################################
|
||||
|
||||
@@ -57,6 +57,7 @@ Or alternatively, you can reach out directly to any of the team members behind t
|
||||
* Sebastiaan Janssen (He, Him - Languages spoken: English, Dutch, Danish(Read)) [sebastiaan@umbraco.com](mailto:sebastiaan@umbraco.com)
|
||||
* Ilham Boulghallat (She, Her - Languages spoken: English, French, Arabic) [ilham@umbraco.com](mailto:ilham@umbraco.com)
|
||||
* Arnold Visser (He, Him - Languages spoken: English, Dutch) [arnold@umbraco.com](mailto:arnold@umbraco.com)
|
||||
* Emma Burstow (She, Her - Languages spoken: English) [ema@umbraco.com](mailto:ema@umbraco.com)
|
||||
|
||||
The review process is done with full respect for the privacy and security of the reporter of any incident.
|
||||
|
||||
@@ -89,4 +90,4 @@ Consequence: A permanent ban from any sort of public interaction within the comm
|
||||
## Attribution
|
||||
This Code of Conduct is adapted from the Contributor Covenant, version 2.0, available at [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html).
|
||||
|
||||
This Code of Conduct will be maintained and reviewed by the team listed above.
|
||||
This Code of Conduct will be maintained and reviewed by the team listed above.
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
is_global = true
|
||||
|
||||
##########################################
|
||||
# StyleCopAnalyzers Settings
|
||||
##########################################
|
||||
|
||||
# All constant fields must be PascalCase
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1303.md
|
||||
dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
|
||||
dotnet_naming_symbols.stylecop_constant_fields_group.required_modifiers = const
|
||||
dotnet_naming_symbols.stylecop_constant_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.symbols = stylecop_constant_fields_group
|
||||
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.style = pascal_case_style
|
||||
|
||||
# All static readonly fields must be PascalCase
|
||||
# Ajusted to ignore private fields.
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md
|
||||
dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected
|
||||
dotnet_naming_symbols.stylecop_static_readonly_fields_group.required_modifiers = static, readonly
|
||||
dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_kinds = field
|
||||
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.symbols = stylecop_static_readonly_fields_group
|
||||
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style
|
||||
|
||||
# No non-private instance fields are allowed
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1401.md
|
||||
dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected
|
||||
dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_kinds = field
|
||||
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.symbols = stylecop_fields_must_be_private_group
|
||||
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.style = disallowed_style
|
||||
|
||||
# Local variables must be camelCase
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md
|
||||
dotnet_naming_symbols.stylecop_local_fields_group.applicable_accessibilities = local
|
||||
dotnet_naming_symbols.stylecop_local_fields_group.applicable_kinds = local
|
||||
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.symbols = stylecop_local_fields_group
|
||||
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.style = camel_case_style
|
||||
|
||||
##########################################
|
||||
# StyleCopAnalyzers rule severity
|
||||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers
|
||||
##########################################
|
||||
|
||||
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.DocumentationRules.severity = suggestion
|
||||
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.ReadabilityRules.severity = suggestion
|
||||
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.NamingRules.severity = suggestion
|
||||
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.SpacingRules.severity = suggestion
|
||||
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.OrderingRules.severity = suggestion
|
||||
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.MaintainabilityRules.severity = suggestion
|
||||
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.LayoutRules.severity = suggestion
|
||||
|
||||
dotnet_diagnostic.SA1636.severity = none # SA1636: File header copyright text should match
|
||||
dotnet_diagnostic.SA1101.severity = none # PrefixLocalCallsWithThis - stylecop appears to be ignoring dotnet_style_qualification_for_*
|
||||
|
||||
dotnet_diagnostic.SA1503.severity = warning # BracesMustNotBeOmitted
|
||||
dotnet_diagnostic.SA1117.severity = warning # ParametersMustBeOnSameLineOrSeparateLines
|
||||
dotnet_diagnostic.SA1116.severity = warning # SplitParametersMustStartOnLineAfterDeclaration
|
||||
dotnet_diagnostic.SA1122.severity = warning # UseStringEmptyForEmptyStrings
|
||||
dotnet_diagnostic.SA1028.severity = warning # CodeMustNotContainTrailingWhitespace
|
||||
dotnet_diagnostic.SA1500.severity = warning # BracesForMultiLineStatementsMustNotShareLine
|
||||
dotnet_diagnostic.SA1401.severity = warning # FieldsMustBePrivate
|
||||
dotnet_diagnostic.SA1519.severity = warning # BracesMustNotBeOmittedFromMultiLineChildStatement
|
||||
dotnet_diagnostic.SA1111.severity = warning # ClosingParenthesisMustBeOnLineOfLastParameter
|
||||
dotnet_diagnostic.SA1520.severity = warning # UseBracesConsistently
|
||||
dotnet_diagnostic.SA1407.severity = warning # ArithmeticExpressionsMustDeclarePrecedence
|
||||
dotnet_diagnostic.SA1400.severity = warning # AccessModifierMustBeDeclared
|
||||
dotnet_diagnostic.SA1119.severity = warning # StatementMustNotUseUnnecessaryParenthesis
|
||||
dotnet_diagnostic.SA1649.severity = warning # FileNameMustMatchTypeName
|
||||
dotnet_diagnostic.SA1121.severity = warning # UseBuiltInTypeAlias
|
||||
dotnet_diagnostic.SA1132.severity = warning # DoNotCombineFields
|
||||
dotnet_diagnostic.SA1134.severity = warning # AttributesMustNotShareLine
|
||||
dotnet_diagnostic.SA1106.severity = warning # CodeMustNotContainEmptyStatements
|
||||
dotnet_diagnostic.SA1312.severity = warning # VariableNamesMustBeginWithLowerCaseLetter
|
||||
dotnet_diagnostic.SA1303.severity = warning # ConstFieldNamesMustBeginWithUpperCaseLetter
|
||||
dotnet_diagnostic.SA1310.severity = warning # FieldNamesMustNotContainUnderscore
|
||||
dotnet_diagnostic.SA1130.severity = warning # UseLambdaSyntax
|
||||
dotnet_diagnostic.SA1405.severity = warning # DebugAssertMustProvideMessageText
|
||||
dotnet_diagnostic.SA1205.severity = warning # PartialElementsMustDeclareAccess
|
||||
dotnet_diagnostic.SA1306.severity = warning # FieldNamesMustBeginWithLowerCaseLetter
|
||||
dotnet_diagnostic.SA1209.severity = warning # UsingAliasDirectivesMustBePlacedAfterOtherUsingDirectives
|
||||
dotnet_diagnostic.SA1216.severity = warning # UsingStaticDirectivesMustBePlacedAtTheCorrectLocation
|
||||
dotnet_diagnostic.SA1133.severity = warning # DoNotCombineAttributes
|
||||
dotnet_diagnostic.SA1135.severity = warning # UsingDirectivesMustBeQualified
|
||||
@@ -2,12 +2,6 @@
|
||||
<Project>
|
||||
<!-- Package references and additional files which are consumed by all projects -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="all" IsImplicitlyDefined="true" />
|
||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)stylecop.json" Link="stylecop.json" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406" PrivateAssets="all" IsImplicitlyDefined="true" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Specify rule set for all projects -->
|
||||
<PropertyGroup>
|
||||
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)codeanalysis.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
||||
@@ -538,7 +538,7 @@ stages:
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
choco install docfx --version=2.58.5 -y
|
||||
choco install docfx --version=2.59.0 -y
|
||||
if ($lastexitcode -ne 0){
|
||||
throw ("Error installing DocFX")
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"version": {
|
||||
"type": "parameter",
|
||||
"datatype": "string",
|
||||
"defaultValue": "9.3.0",
|
||||
"defaultValue": "9.4.2",
|
||||
"description": "The version of Umbraco to load using NuGet",
|
||||
"replaces": "UMBRACO_VERSION_FROM_TEMPLATE"
|
||||
},
|
||||
|
||||
@@ -461,6 +461,9 @@ $RECYCLE.BIN/
|
||||
# Dont commit Umbraco TEMP folder containing Examine Indexes, NuCache etc
|
||||
**/umbraco/Data/TEMP/
|
||||
|
||||
# Umbraco log files
|
||||
**/umbraco/Logs/
|
||||
|
||||
# Dont commit files that are generated and cached from the default ImageSharp location
|
||||
**/umbraco/mediacache/
|
||||
|
||||
@@ -484,4 +487,4 @@ $RECYCLE.BIN/
|
||||
|
||||
# Umbraco Static Assets of Backoffice
|
||||
# Nuget package Umbraco.Cms.StaticAssets will copy them in during dotnet build
|
||||
**/wwwroot/umbraco/
|
||||
**/wwwroot/umbraco/
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
"version": {
|
||||
"type": "parameter",
|
||||
"datatype": "string",
|
||||
"defaultValue": "9.3.0",
|
||||
"defaultValue": "9.4.2",
|
||||
"description": "The version of Umbraco to load using NuGet",
|
||||
"replaces": "UMBRACO_VERSION_FROM_TEMPLATE"
|
||||
},
|
||||
|
||||
@@ -12,9 +12,13 @@
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Force windows to use ICU. Otherwise Windows 10 2019H1+ will do it, but older windows 10 and most if not all winodws servers will run NLS -->
|
||||
<ItemGroup Condition="'$(OS)' == 'Windows_NT'">
|
||||
<PackageReference Include="Microsoft.ICU.ICU4C.Runtime" Version="68.2.0.9" />
|
||||
<RuntimeHostConfigurationOption Include="System.Globalization.AppLocalIcu" Value="68.2" />
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.ICU.ICU4C.Runtime" Version="68.2.0.9" />
|
||||
|
||||
<RuntimeHostConfigurationOption
|
||||
Condition="$(RuntimeIdentifier.StartsWith('linux')) Or $(RuntimeIdentifier.StartsWith('win')) Or ('$(RuntimeIdentifier)' == '' And !$([MSBuild]::IsOSPlatform('osx')))"
|
||||
Include="System.Globalization.AppLocalIcu"
|
||||
Value="68.2.0.9" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\PackageTestSiteName\build\PackageTestSiteName.targets" Condition="'$(PackageTestSiteName)' != ''" />
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RuleSet Name="CodeAnalysis" ToolsVersion="16.0">
|
||||
<Rules AnalyzerId="Roslynator.CSharp.Analyzers" RuleNamespace="Roslynator.CSharp">
|
||||
<Rule Id="RCS1090" Action="None" />
|
||||
</Rules>
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
|
||||
<Rule Id="SA1101" Action="None" />
|
||||
<Rule Id="SA1200" Action="None" />
|
||||
<Rule Id="SA1308" Action="None" />
|
||||
<Rule Id="SA1309" Action="None" />
|
||||
<Rule Id="SA1311" Action="None" />
|
||||
<Rule Id="SA1402" Action="None" />
|
||||
<Rule Id="SA1413" Action="None" />
|
||||
<Rule Id="SA1611" Action="None" />
|
||||
<Rule Id="SA1615" Action="None" />
|
||||
<Rule Id="SA1629" Action="None" />
|
||||
</Rules>
|
||||
</RuleSet>
|
||||
@@ -15,8 +15,8 @@
|
||||
<div class="level{{item.level}}"><span class="xref">{{item.name.0.value}}</span></div>
|
||||
</div>
|
||||
{{/inheritance.0}}
|
||||
<h6><strong>{{__global.namespace}}</strong>:{{namespace}}</h6>
|
||||
<h6><strong>{{__global.assembly}}</strong>:{{assemblies.0}}.dll</h6>
|
||||
<h6><strong>{{__global.namespace}}</strong>: {{{namespace.specName.0.value}}}</h6>
|
||||
<h6><strong>{{__global.assembly}}</strong>: {{assemblies.0}}.dll</h6>
|
||||
<h5 id="{{id}}_syntax">{{__global.syntax}}</h5>
|
||||
<div class="codewrapper">
|
||||
<pre><code class="lang-{{_lang}} hljs">{{syntax.content.0.value}}</code></pre>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<Project>
|
||||
<Project>
|
||||
<!-- Enable multi-level merging -->
|
||||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>9.3.0</Version>
|
||||
<AssemblyVersion>9.3.0</AssemblyVersion>
|
||||
<InformationalVersion>9.3.0</InformationalVersion>
|
||||
<FileVersion>9.3.0</FileVersion>
|
||||
<Version>9.4.2</Version>
|
||||
<AssemblyVersion>9.4.2</AssemblyVersion>
|
||||
<InformationalVersion>9.4.2</InformationalVersion>
|
||||
<FileVersion>9.4.2</FileVersion>
|
||||
<LangVersion Condition="'$(LangVersion)' == ''">9.0</LangVersion>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<Company>Umbraco CMS</Company>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using Umbraco.Cms.Core.Configuration;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Deploy.Core.Configuration.DebugConfiguration;
|
||||
using Umbraco.Deploy.Core.Configuration.DeployConfiguration;
|
||||
using Umbraco.Deploy.Core.Configuration.DeployProjectConfiguration;
|
||||
using Umbraco.Forms.Core.Configuration;
|
||||
@@ -127,6 +128,8 @@ namespace JsonSchema
|
||||
public DeploySettings Settings { get; set; }
|
||||
|
||||
public DeployProjectConfig Project { get; set; }
|
||||
|
||||
public DebugSettings Debug { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
<PackageReference Include="CommandLineParser" Version="2.8.0" />
|
||||
<PackageReference Include="NJsonSchema" Version="10.5.2" />
|
||||
<PackageReference Include="System.Xml.XPath.XmlDocument" Version="4.3.0" />
|
||||
<PackageReference Include="Umbraco.Deploy.Core" Version="9.2.0" />
|
||||
<PackageReference Include="Umbraco.Forms.Core" Version="9.2.0" />
|
||||
<PackageReference Include="Umbraco.Deploy.Core" Version="9.3.0" />
|
||||
<PackageReference Include="Umbraco.Forms.Core" Version="9.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -46,6 +46,11 @@ namespace Umbraco.Cms.Core.Cache
|
||||
{
|
||||
var payloads = Deserialize(json);
|
||||
|
||||
Refresh(payloads);
|
||||
}
|
||||
|
||||
public override void Refresh(JsonPayload[] payloads)
|
||||
{
|
||||
foreach (var payload in payloads)
|
||||
{
|
||||
foreach (var alias in GetCacheKeysForAlias(payload.Alias))
|
||||
@@ -55,11 +60,13 @@ namespace Umbraco.Cms.Core.Cache
|
||||
if (macroRepoCache)
|
||||
{
|
||||
macroRepoCache.Result.Clear(RepositoryCacheKeys.GetKey<IMacro, int>(payload.Id));
|
||||
macroRepoCache.Result.Clear(RepositoryCacheKeys.GetKey<IMacro, string>(payload.Alias)); // Repository caching of macro definition by alias
|
||||
}
|
||||
}
|
||||
|
||||
base.Refresh(json);
|
||||
base.Refresh(payloads);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Json
|
||||
|
||||
@@ -156,6 +156,9 @@ namespace Umbraco.Cms.Core.Configuration.Models
|
||||
internal const bool StaticShowDeprecatedPropertyEditors = false;
|
||||
internal const string StaticLoginBackgroundImage = "assets/img/login.jpg";
|
||||
internal const string StaticLoginLogoImage = "assets/img/application/umbraco_logo_white.svg";
|
||||
internal const bool StaticHideBackOfficeLogo = false;
|
||||
internal const bool StaticDisableDeleteWhenReferenced = false;
|
||||
internal const bool StaticDisableUnpublishWhenReferenced = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value for the content notification settings.
|
||||
@@ -219,6 +222,24 @@ namespace Umbraco.Cms.Core.Configuration.Models
|
||||
[DefaultValue(StaticLoginLogoImage)]
|
||||
public string LoginLogoImage { get; set; } = StaticLoginLogoImage;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to hide the backoffice umbraco logo or not.
|
||||
/// </summary>
|
||||
[DefaultValue(StaticHideBackOfficeLogo)]
|
||||
public bool HideBackOfficeLogo { get; set; } = StaticHideBackOfficeLogo;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to disable the deletion of items referenced by other items.
|
||||
/// </summary>
|
||||
[DefaultValue(StaticDisableDeleteWhenReferenced)]
|
||||
public bool DisableDeleteWhenReferenced { get; set; } = StaticDisableDeleteWhenReferenced;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to disable the unpublishing of items referenced by other items.
|
||||
/// </summary>
|
||||
[DefaultValue(StaticDisableUnpublishWhenReferenced)]
|
||||
public bool DisableUnpublishWhenReferenced { get; set; } = StaticDisableUnpublishWhenReferenced;
|
||||
|
||||
/// <summary>
|
||||
/// Get or sets the model representing the global content version cleanup policy
|
||||
/// </summary>
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace Umbraco.Cms.Core.Configuration.Models
|
||||
internal const string StaticNoNodesViewPath = "~/umbraco/UmbracoWebsite/NoNodes.cshtml";
|
||||
internal const string StaticSqlWriteLockTimeOut = "00:00:05";
|
||||
internal const bool StaticSanitizeTinyMce = false;
|
||||
internal const int StaticMainDomReleaseSignalPollingInterval = 2000;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value for the reserved URLs (must end with a comma).
|
||||
@@ -137,6 +138,26 @@ namespace Umbraco.Cms.Core.Configuration.Models
|
||||
/// </summary>
|
||||
public string MainDomLock { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value to discriminate MainDom boundaries.
|
||||
/// <para>
|
||||
/// Generally the default should suffice but useful for advanced scenarios e.g. azure deployment slot based zero downtime deployments.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public string MainDomKeyDiscriminator { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the duration (in milliseconds) for which the MainDomLock release signal polling task should sleep.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Doesn't apply to MainDomSemaphoreLock.
|
||||
/// <para>
|
||||
/// The default value is 2000ms.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[DefaultValue(StaticMainDomReleaseSignalPollingInterval)]
|
||||
public int MainDomReleaseSignalPollingInterval { get; set; } = StaticMainDomReleaseSignalPollingInterval;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the telemetry ID.
|
||||
/// </summary>
|
||||
@@ -174,18 +195,18 @@ namespace Umbraco.Cms.Core.Configuration.Models
|
||||
public bool IsPickupDirectoryLocationConfigured => !string.IsNullOrWhiteSpace(Smtp?.PickupDirectoryLocation);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether TinyMCE scripting sanitization should be applied.
|
||||
/// Gets or sets a value indicating whether TinyMCE scripting sanitization should be applied.
|
||||
/// </summary>
|
||||
[DefaultValue(StaticSanitizeTinyMce)]
|
||||
public bool SanitizeTinyMce => StaticSanitizeTinyMce;
|
||||
public bool SanitizeTinyMce { get; set; } = StaticSanitizeTinyMce;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value representing the time in milliseconds to lock the database for a write operation.
|
||||
/// An int value representing the time in milliseconds to lock the database for a write operation
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default value is 5000 milliseconds.
|
||||
/// </remarks>
|
||||
[DefaultValue(StaticSqlWriteLockTimeOut)]
|
||||
public TimeSpan SqlWriteLockTimeOut { get; } = TimeSpan.Parse(StaticSqlWriteLockTimeOut);
|
||||
public TimeSpan SqlWriteLockTimeOut { get; set; } = TimeSpan.Parse(StaticSqlWriteLockTimeOut);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Umbraco.Cms.Core.Configuration.Models
|
||||
/// <summary>
|
||||
/// Gets or sets a value for the location of temporary files.
|
||||
/// </summary>
|
||||
[DefaultValue(StaticLocalTempStorageLocation)]
|
||||
[DefaultValue(StaticLocalTempStorageLocation)]
|
||||
public LocalTempStorage LocalTempStorageLocation { get; set; } = Enum<LocalTempStorage>.Parse(StaticLocalTempStorageLocation);
|
||||
|
||||
/// <summary>
|
||||
@@ -31,5 +31,10 @@ namespace Umbraco.Cms.Core.Configuration.Models
|
||||
/// <value><c>true</c> if [debug mode]; otherwise, <c>false</c>.</value>
|
||||
[DefaultValue(StaticDebug)]
|
||||
public bool Debug { get; set; } = StaticDebug;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value specifying the name of the site.
|
||||
/// </summary>
|
||||
public string SiteName { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ namespace Umbraco.Cms.Core.Configuration.Models
|
||||
if (!ModelsMode.IsAuto())
|
||||
{
|
||||
_flagOutOfDateModels = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_flagOutOfDateModels = value;
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Umbraco.Cms.Core.Configuration.Models
|
||||
[UmbracoOptions(Constants.Configuration.ConfigRichTextEditor)]
|
||||
public class RichTextEditorSettings
|
||||
{
|
||||
internal const string StaticValidElements = "+a[id|style|rel|data-id|data-udi|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],-strike[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|reversed|start|style|type],-ul[class|style],-li[class|style],br[class],img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align|umbracoorgwidth|umbracoorgheight|onresize|onresizestart|onresizeend|rel|data-id],-sub[style|class],-sup[style|class],-blockquote[dir|style|class],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[class|align|style],-pre[class|align|style],address[class|align|style],-h1[id|dir|class|align|style],-h2[id|dir|class|align|style],-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],small[class|style],dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*]";
|
||||
internal const string StaticValidElements = "+a[id|style|rel|data-id|data-udi|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],-strike[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|reversed|start|style|type],-ul[class|style],-li[class|style],br[class],img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align|umbracoorgwidth|umbracoorgheight|onresize|onresizestart|onresizeend|rel|data-id],-sub[style|class],-sup[style|class],-blockquote[dir|style|class],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[class|align|style],-pre[class|align|style],address[class|align|style],-h1[id|dir|class|align|style],-h2[id|dir|class|align|style],-h3[id|dir|class|align|style],-h4[id|dir|class|align|style],-h5[id|dir|class|align|style],-h6[id|style|dir|class|align|style],hr[class|style],small[class|style],dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],object[class|id|width|height|codebase|*],param[name|value|_value|class],embed[type|width|height|src|class|*],map[name|class],area[shape|coords|href|alt|target|class],bdo[class],button[class],iframe[*],figure,figcaption";
|
||||
internal const string StaticInvalidElements = "font";
|
||||
|
||||
private static readonly string[] s_default_plugins = new[]
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace Umbraco.Cms.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines constants.
|
||||
/// </summary>
|
||||
public static partial class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines constants for named http clients.
|
||||
/// </summary>
|
||||
public static class HttpClients
|
||||
{
|
||||
/// <summary>
|
||||
/// Name for http client which ignores certificate errors.
|
||||
/// </summary>
|
||||
public const string IgnoreCertificateErrors = "Umbraco:HttpClients:IgnoreCertificateErrors";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Umbraco.Cms.Core
|
||||
namespace Umbraco.Cms.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
{
|
||||
@@ -9,6 +9,11 @@
|
||||
/// </summary>
|
||||
public const string DefaultIcon = Content;
|
||||
|
||||
/// <summary>
|
||||
/// System blueprint icon
|
||||
/// </summary>
|
||||
public const string Blueprint = "icon-blueprint";
|
||||
|
||||
/// <summary>
|
||||
/// System content icon
|
||||
/// </summary>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Cms.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
@@ -42,7 +44,13 @@ namespace Umbraco.Cms.Core
|
||||
public const string Install = "~/install";
|
||||
|
||||
public const string AppPlugins = "/App_Plugins";
|
||||
|
||||
|
||||
[Obsolete("Use PluginIcons instead")]
|
||||
public static string AppPluginIcons => "/Backoffice/Icons";
|
||||
|
||||
public const string PluginIcons = "/backoffice/icons";
|
||||
|
||||
public const string CreatedPackages = "/created-packages";
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.ContentEditing;
|
||||
using Umbraco.Cms.Core.Models.Membership;
|
||||
|
||||
namespace Umbraco.Cms.Core.ContentApps
|
||||
{
|
||||
internal class DictionaryContentAppFactory : IContentAppFactory
|
||||
{
|
||||
private const int Weight = -100;
|
||||
|
||||
private ContentApp _dictionaryApp;
|
||||
|
||||
public ContentApp GetContentAppFor(object source, IEnumerable<IReadOnlyUserGroup> userGroups)
|
||||
{
|
||||
switch (source)
|
||||
{
|
||||
case IDictionaryItem _:
|
||||
return _dictionaryApp ??= new ContentApp
|
||||
{
|
||||
Alias = "dictionaryContent",
|
||||
Name = "Content",
|
||||
Icon = "icon-document",
|
||||
View = "views/dictionary/views/content/content.html",
|
||||
Weight = Weight
|
||||
};
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,8 @@ namespace Umbraco.Cms.Core.DependencyInjection
|
||||
.Append<ContentTypeListViewContentAppFactory>()
|
||||
.Append<ContentTypePermissionsContentAppFactory>()
|
||||
.Append<ContentTypeTemplatesContentAppFactory>()
|
||||
.Append<MemberEditorContentAppFactory>();
|
||||
.Append<MemberEditorContentAppFactory>()
|
||||
.Append<DictionaryContentAppFactory>();
|
||||
|
||||
// all built-in finders in the correct order,
|
||||
// devs can then modify this list on application startup
|
||||
|
||||
@@ -262,6 +262,7 @@ namespace Umbraco.Cms.Core.DependencyInjection
|
||||
Services.AddSingleton<IValueEditorCache, ValueEditorCache>();
|
||||
|
||||
// Register telemetry service used to gather data about installed packages
|
||||
Services.AddUnique<ISiteIdentifierService, SiteIdentifierService>();
|
||||
Services.AddUnique<ITelemetryService, TelemetryService>();
|
||||
|
||||
// Register a noop IHtmlSanitizer to be replaced
|
||||
|
||||
@@ -33,7 +33,8 @@ namespace Umbraco.Cms.Core.Events
|
||||
Constants.Conventions.RelationTypes.RelateDocumentOnCopyName,
|
||||
true,
|
||||
Constants.ObjectTypes.Document,
|
||||
Constants.ObjectTypes.Document);
|
||||
Constants.ObjectTypes.Document,
|
||||
false);
|
||||
|
||||
_relationService.Save(relationType);
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Umbraco.Extensions
|
||||
}
|
||||
}
|
||||
|
||||
verifiedIdentity = identity.AuthenticationType == Constants.Security.BackOfficeAuthenticationType ? identity : new ClaimsIdentity(identity.Claims, Constants.Security.BackOfficeAuthenticationType);
|
||||
verifiedIdentity = identity.AuthenticationType == Constants.Security.BackOfficeAuthenticationType ? identity : new ClaimsIdentity(identity.Claims, Constants.Security.BackOfficeAuthenticationType);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -626,7 +626,6 @@ namespace Umbraco.Extensions
|
||||
if (type == typeof(sbyte)) return XmlConvert.ToString((sbyte)value);
|
||||
if (type == typeof(short)) return XmlConvert.ToString((short)value);
|
||||
if (type == typeof(TimeSpan)) return XmlConvert.ToString((TimeSpan)value);
|
||||
if (type == typeof(bool)) return XmlConvert.ToString((bool)value);
|
||||
if (type == typeof(uint)) return XmlConvert.ToString((uint)value);
|
||||
if (type == typeof(ulong)) return XmlConvert.ToString((ulong)value);
|
||||
if (type == typeof(ushort)) return XmlConvert.ToString((ushort)value);
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Install.Models;
|
||||
using Umbraco.Cms.Core.Telemetry;
|
||||
using Umbraco.Cms.Web.Common.DependencyInjection;
|
||||
|
||||
namespace Umbraco.Cms.Core.Install.InstallSteps
|
||||
{
|
||||
@@ -13,31 +16,29 @@ namespace Umbraco.Cms.Core.Install.InstallSteps
|
||||
PerformsAppRestart = false)]
|
||||
public class TelemetryIdentifierStep : InstallSetupStep<object>
|
||||
{
|
||||
private readonly ILogger<TelemetryIdentifierStep> _logger;
|
||||
private readonly IOptions<GlobalSettings> _globalSettings;
|
||||
private readonly IConfigManipulator _configManipulator;
|
||||
private readonly ISiteIdentifierService _siteIdentifierService;
|
||||
|
||||
public TelemetryIdentifierStep(ILogger<TelemetryIdentifierStep> logger, IOptions<GlobalSettings> globalSettings, IConfigManipulator configManipulator)
|
||||
public TelemetryIdentifierStep(
|
||||
IOptions<GlobalSettings> globalSettings,
|
||||
ISiteIdentifierService siteIdentifierService)
|
||||
{
|
||||
_logger = logger;
|
||||
_globalSettings = globalSettings;
|
||||
_configManipulator = configManipulator;
|
||||
_siteIdentifierService = siteIdentifierService;
|
||||
}
|
||||
|
||||
[Obsolete("Use constructor that takes GlobalSettings and ISiteIdentifierService")]
|
||||
public TelemetryIdentifierStep(
|
||||
ILogger<TelemetryIdentifierStep> logger,
|
||||
IOptions<GlobalSettings> globalSettings,
|
||||
IConfigManipulator configManipulator)
|
||||
: this(globalSettings, StaticServiceProvider.Instance.GetRequiredService<ISiteIdentifierService>())
|
||||
{
|
||||
}
|
||||
|
||||
public override Task<InstallSetupResult> ExecuteAsync(object model)
|
||||
{
|
||||
// Generate GUID
|
||||
var telemetrySiteIdentifier = Guid.NewGuid();
|
||||
|
||||
try
|
||||
{
|
||||
_configManipulator.SetGlobalId(telemetrySiteIdentifier.ToString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Couldn't update config files with a telemetry site identifier");
|
||||
}
|
||||
|
||||
_siteIdentifierService.TryCreateSiteIdentifier(out _);
|
||||
return Task.FromResult<InstallSetupResult>(null);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -70,6 +70,10 @@ namespace Umbraco.Cms.Core.Manifest
|
||||
partA = "contentType";
|
||||
partB = contentType.Alias;
|
||||
break;
|
||||
case IDictionaryItem _:
|
||||
partA = "dictionary";
|
||||
partB = "*"; //Not really a different type for dictionary items
|
||||
break;
|
||||
|
||||
default:
|
||||
return null;
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace Umbraco.Cms.Core.Models
|
||||
public bool IsCulturePublished(string culture)
|
||||
// just check _publishInfos
|
||||
// a non-available culture could not become published anyways
|
||||
=> _publishInfos != null && _publishInfos.ContainsKey(culture);
|
||||
=> !culture.IsNullOrWhiteSpace() && _publishInfos != null && _publishInfos.ContainsKey(culture);
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsCultureEdited(string culture)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace Umbraco.Cms.Core.Models.ContentEditing
|
||||
{
|
||||
Notifications = new List<BackOfficeNotification>();
|
||||
Translations = new List<DictionaryTranslationDisplay>();
|
||||
ContentApps = new List<ContentApp>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -37,5 +38,11 @@ namespace Umbraco.Cms.Core.Models.ContentEditing
|
||||
/// </summary>
|
||||
[DataMember(Name = "translations")]
|
||||
public List<DictionaryTranslationDisplay> Translations { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Apps for the dictionary item
|
||||
/// </summary>
|
||||
[DataMember(Name = "apps")]
|
||||
public List<ContentApp> ContentApps { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,34 @@
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models.ContentEditing
|
||||
{
|
||||
[DataContract(Name = "historyCleanup", Namespace = "")]
|
||||
public class HistoryCleanup
|
||||
public class HistoryCleanup : BeingDirtyBase
|
||||
{
|
||||
private bool _preventCleanup;
|
||||
private int? _keepAllVersionsNewerThanDays;
|
||||
private int? _keepLatestVersionPerDayForDays;
|
||||
|
||||
[DataMember(Name = "preventCleanup")]
|
||||
public bool PreventCleanup { get; set; }
|
||||
public bool PreventCleanup
|
||||
{
|
||||
get => _preventCleanup;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _preventCleanup, nameof(PreventCleanup));
|
||||
}
|
||||
|
||||
[DataMember(Name = "keepAllVersionsNewerThanDays")]
|
||||
public int? KeepAllVersionsNewerThanDays { get; set; }
|
||||
public int? KeepAllVersionsNewerThanDays
|
||||
{
|
||||
get => _keepAllVersionsNewerThanDays;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _keepAllVersionsNewerThanDays, nameof(KeepAllVersionsNewerThanDays));
|
||||
}
|
||||
|
||||
[DataMember(Name = "keepLatestVersionPerDayForDays")]
|
||||
public int? KeepLatestVersionPerDayForDays { get; set; }
|
||||
public int? KeepLatestVersionPerDayForDays
|
||||
{
|
||||
get => _keepLatestVersionPerDayForDays;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _keepLatestVersionPerDayForDays, nameof(KeepLatestVersionPerDayForDays));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,5 +55,11 @@ namespace Umbraco.Cms.Core.Models.ContentEditing
|
||||
/// </summary>
|
||||
[DataMember(Name = "notifications")]
|
||||
public List<BackOfficeNotification> Notifications { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the RelationType should be returned in "Used by"-queries.
|
||||
/// </summary>
|
||||
[DataMember(Name = "isDependency", IsRequired = true)]
|
||||
public bool IsDependency { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,5 +23,11 @@ namespace Umbraco.Cms.Core.Models.ContentEditing
|
||||
/// </summary>
|
||||
[DataMember(Name = "childObjectType", IsRequired = false)]
|
||||
public Guid? ChildObjectType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the RelationType should be returned in "Used by"-queries.
|
||||
/// </summary>
|
||||
[DataMember(Name = "isDependency", IsRequired = true)]
|
||||
public bool IsDependency { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,13 @@ namespace Umbraco.Cms.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
public HistoryCleanup HistoryCleanup { get; set; }
|
||||
private HistoryCleanup _historyCleanup;
|
||||
|
||||
public HistoryCleanup HistoryCleanup
|
||||
{
|
||||
get => _historyCleanup;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _historyCleanup, nameof(HistoryCleanup));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if AllowedTemplates contains templateId
|
||||
@@ -162,5 +168,8 @@ namespace Umbraco.Cms.Core.Models
|
||||
/// <inheritdoc />
|
||||
IContentType IContentType.DeepCloneWithResetIdentities(string newAlias) =>
|
||||
(IContentType)DeepCloneWithResetIdentities(newAlias);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool IsDirty() => base.IsDirty() || HistoryCleanup.IsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,15 @@ using Umbraco.Cms.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models
|
||||
{
|
||||
public interface IRelationTypeWithIsDependency : IRelationType
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the RelationType should be returned in "Used by"-queries.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
bool IsDependency { get; set; }
|
||||
}
|
||||
|
||||
public interface IRelationType : IEntity, IRememberBeingDirty
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Cms.Core.ContentApps;
|
||||
@@ -48,6 +48,11 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
}
|
||||
|
||||
public IEnumerable<ContentApp> GetContentApps(IUmbracoEntity source)
|
||||
{
|
||||
return GetContentAppsForEntity(source);
|
||||
}
|
||||
|
||||
public IEnumerable<ContentApp> GetContentAppsForEntity(IEntity source)
|
||||
{
|
||||
var apps = _contentAppDefinitions.GetContentAppsFor(source).ToArray();
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
|
||||
if (target is IContentTypeWithHistoryCleanup targetWithHistoryCleanup)
|
||||
{
|
||||
targetWithHistoryCleanup.HistoryCleanup = source.HistoryCleanup;
|
||||
MapHistoryCleanup(source, targetWithHistoryCleanup);
|
||||
}
|
||||
|
||||
target.AllowedTemplates = source.AllowedTemplates
|
||||
@@ -147,6 +147,34 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
: _fileService.GetTemplate(source.DefaultTemplate));
|
||||
}
|
||||
|
||||
private static void MapHistoryCleanup(DocumentTypeSave source, IContentTypeWithHistoryCleanup target)
|
||||
{
|
||||
// If source history cleanup is null we don't have to map all properties
|
||||
if (source.HistoryCleanup is null)
|
||||
{
|
||||
target.HistoryCleanup = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to reset the dirty properties, because it is otherwise true, just because the json serializer has set properties
|
||||
target.HistoryCleanup.ResetDirtyProperties(false);
|
||||
if (target.HistoryCleanup.PreventCleanup != source.HistoryCleanup.PreventCleanup)
|
||||
{
|
||||
target.HistoryCleanup.PreventCleanup = source.HistoryCleanup.PreventCleanup;
|
||||
}
|
||||
|
||||
if (target.HistoryCleanup.KeepAllVersionsNewerThanDays != source.HistoryCleanup.KeepAllVersionsNewerThanDays)
|
||||
{
|
||||
target.HistoryCleanup.KeepAllVersionsNewerThanDays = source.HistoryCleanup.KeepAllVersionsNewerThanDays;
|
||||
}
|
||||
|
||||
if (target.HistoryCleanup.KeepLatestVersionPerDayForDays !=
|
||||
source.HistoryCleanup.KeepLatestVersionPerDayForDays)
|
||||
{
|
||||
target.HistoryCleanup.KeepLatestVersionPerDayForDays = source.HistoryCleanup.KeepLatestVersionPerDayForDays;
|
||||
}
|
||||
}
|
||||
|
||||
// no MapAll - take care
|
||||
private void Map(MediaTypeSave source, IMediaType target, MapperContext context)
|
||||
{
|
||||
@@ -196,7 +224,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
|
||||
target.AllowCultureVariant = source.VariesByCulture();
|
||||
target.AllowSegmentVariant = source.VariesBySegment();
|
||||
target.ContentApps = _commonMapper.GetContentApps(source);
|
||||
target.ContentApps = _commonMapper.GetContentAppsForEntity(source);
|
||||
|
||||
//sync templates
|
||||
target.AllowedTemplates = context.MapEnumerable<ITemplate, EntityBasic>(source.AllowedTemplates);
|
||||
@@ -328,7 +356,10 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
|
||||
if (source.GroupId > 0)
|
||||
{
|
||||
target.PropertyGroupId = new Lazy<int>(() => source.GroupId, false);
|
||||
if (target.PropertyGroupId?.Value != source.GroupId)
|
||||
{
|
||||
target.PropertyGroupId = new Lazy<int>(() => source.GroupId, false);
|
||||
}
|
||||
}
|
||||
|
||||
target.Alias = source.Alias;
|
||||
@@ -523,7 +554,15 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
target.Thumbnail = source.Thumbnail;
|
||||
|
||||
target.AllowedAsRoot = source.AllowAsRoot;
|
||||
target.AllowedContentTypes = source.AllowedContentTypes.Select((t, i) => new ContentTypeSort(t, i));
|
||||
|
||||
bool allowedContentTypesUnchanged = target.AllowedContentTypes.Select(x => x.Id.Value)
|
||||
.SequenceEqual(source.AllowedContentTypes);
|
||||
|
||||
if (allowedContentTypesUnchanged is false)
|
||||
{
|
||||
target.AllowedContentTypes = source.AllowedContentTypes.Select((t, i) => new ContentTypeSort(t, i));
|
||||
}
|
||||
|
||||
|
||||
if (!(target is IMemberType))
|
||||
{
|
||||
@@ -574,13 +613,21 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
|
||||
// ensure no duplicate alias, then assign the group properties collection
|
||||
EnsureUniqueAliases(destProperties);
|
||||
destGroup.PropertyTypes = new PropertyTypeCollection(isPublishing, destProperties);
|
||||
if (destGroup.PropertyTypes.SupportsPublishing != isPublishing || destGroup.PropertyTypes.SequenceEqual(destProperties) is false)
|
||||
{
|
||||
destGroup.PropertyTypes = new PropertyTypeCollection(isPublishing, destProperties);
|
||||
}
|
||||
|
||||
destGroups.Add(destGroup);
|
||||
}
|
||||
|
||||
// ensure no duplicate name, then assign the groups collection
|
||||
EnsureUniqueAliases(destGroups);
|
||||
target.PropertyGroups = new PropertyGroupCollection(destGroups);
|
||||
|
||||
if (target.PropertyGroups.SequenceEqual(destGroups) is false)
|
||||
{
|
||||
target.PropertyGroups = new PropertyGroupCollection(destGroups);
|
||||
}
|
||||
|
||||
// because the property groups collection was rebuilt, there is no need to remove
|
||||
// the old groups - they are just gone and will be cleared by the repository
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Mapping;
|
||||
using Umbraco.Cms.Core.Models.ContentEditing;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
@@ -14,12 +15,20 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
public class DictionaryMapDefinition : IMapDefinition
|
||||
{
|
||||
private readonly ILocalizationService _localizationService;
|
||||
private readonly CommonMapper _commonMapper;
|
||||
|
||||
[Obsolete("Use the constructor with the CommonMapper")]
|
||||
public DictionaryMapDefinition(ILocalizationService localizationService)
|
||||
{
|
||||
_localizationService = localizationService;
|
||||
}
|
||||
|
||||
public DictionaryMapDefinition(ILocalizationService localizationService, CommonMapper commonMapper)
|
||||
{
|
||||
_localizationService = localizationService;
|
||||
_commonMapper = commonMapper;
|
||||
}
|
||||
|
||||
public void DefineMaps(IUmbracoMapper mapper)
|
||||
{
|
||||
mapper.Define<IDictionaryItem, EntityBasic>((source, context) => new EntityBasic(), Map);
|
||||
@@ -44,6 +53,10 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
target.Name = source.ItemKey;
|
||||
target.ParentId = source.ParentId ?? Guid.Empty;
|
||||
target.Udi = Udi.Create(Constants.UdiEntityType.DictionaryItem, source.Key);
|
||||
if (_commonMapper != null)
|
||||
{
|
||||
target.ContentApps.AddRange(_commonMapper.GetContentAppsForEntity(source));
|
||||
}
|
||||
|
||||
// build up the path to make it possible to set active item in tree
|
||||
// TODO: check if there is a better way
|
||||
|
||||
@@ -30,6 +30,11 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
target.ChildObjectType = source.ChildObjectType;
|
||||
target.Id = source.Id;
|
||||
target.IsBidirectional = source.IsBidirectional;
|
||||
|
||||
if (source is IRelationTypeWithIsDependency sourceWithIsDependency)
|
||||
{
|
||||
target.IsDependency = sourceWithIsDependency.IsDependency;
|
||||
}
|
||||
target.Key = source.Key;
|
||||
target.Name = source.Name;
|
||||
target.Alias = source.Alias;
|
||||
@@ -74,6 +79,11 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
target.ChildObjectType = source.ChildObjectType;
|
||||
target.Id = source.Id.TryConvertTo<int>().Result;
|
||||
target.IsBidirectional = source.IsBidirectional;
|
||||
if (target is IRelationTypeWithIsDependency targetWithIsDependency)
|
||||
{
|
||||
targetWithIsDependency.IsDependency = source.IsDependency;
|
||||
}
|
||||
|
||||
target.Key = source.Key;
|
||||
target.Name = source.Name;
|
||||
target.ParentObjectType = source.ParentObjectType;
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models
|
||||
{
|
||||
[DataContract(Name = "relationItem", Namespace = "")]
|
||||
public class RelationItem
|
||||
{
|
||||
[DataMember(Name = "id")]
|
||||
public int NodeId { get; set; }
|
||||
|
||||
[DataMember(Name = "key")]
|
||||
public Guid NodeKey { get; set; }
|
||||
|
||||
[DataMember(Name = "name")]
|
||||
public string NodeName { get; set; }
|
||||
|
||||
[DataMember(Name = "type")]
|
||||
public string NodeType { get; set; }
|
||||
|
||||
[DataMember(Name = "udi")]
|
||||
public Udi NodeUdi => Udi.Create(NodeType, NodeKey);
|
||||
|
||||
[DataMember(Name = "icon")]
|
||||
public string ContentTypeIcon { get; set; }
|
||||
|
||||
[DataMember(Name = "alias")]
|
||||
public string ContentTypeAlias { get; set; }
|
||||
|
||||
[DataMember(Name = "contentTypeName")]
|
||||
public string ContentTypeName { get; set; }
|
||||
|
||||
[DataMember(Name = "relationTypeName")]
|
||||
public string RelationTypeName { get; set; }
|
||||
|
||||
[DataMember(Name = "relationTypeIsBidirectional")]
|
||||
public bool RelationTypeIsBidirectional { get; set; }
|
||||
|
||||
[DataMember(Name = "relationTypeIsDependency")]
|
||||
public bool RelationTypeIsDependency { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -9,20 +9,28 @@ namespace Umbraco.Cms.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
public class RelationType : EntityBase, IRelationType
|
||||
public class RelationType : EntityBase, IRelationType, IRelationTypeWithIsDependency
|
||||
{
|
||||
private string _name;
|
||||
private string _alias;
|
||||
private bool _isBidirectional;
|
||||
private bool _isDependency;
|
||||
private Guid? _parentObjectType;
|
||||
private Guid? _childObjectType;
|
||||
|
||||
public RelationType(string alias, string name)
|
||||
: this(name: name, alias: alias, false, null, null)
|
||||
: this(name: name, alias: alias, false, null, null, false)
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete("Use ctor with isDependency parameter")]
|
||||
public RelationType(string name, string alias, bool isBidrectional, Guid? parentObjectType, Guid? childObjectType)
|
||||
:this(name,alias,isBidrectional, parentObjectType, childObjectType, false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public RelationType(string name, string alias, bool isBidrectional, Guid? parentObjectType, Guid? childObjectType, bool isDependency)
|
||||
{
|
||||
if (name == null) throw new ArgumentNullException(nameof(name));
|
||||
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
|
||||
@@ -32,6 +40,7 @@ namespace Umbraco.Cms.Core.Models
|
||||
_name = name;
|
||||
_alias = alias;
|
||||
_isBidirectional = isBidrectional;
|
||||
_isDependency = isDependency;
|
||||
_parentObjectType = parentObjectType;
|
||||
_childObjectType = childObjectType;
|
||||
}
|
||||
@@ -88,5 +97,11 @@ namespace Umbraco.Cms.Core.Models
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _childObjectType, nameof(ChildObjectType));
|
||||
}
|
||||
|
||||
|
||||
public bool IsDependency
|
||||
{
|
||||
get => _isDependency;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _isDependency, nameof(IsDependency));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,11 @@ namespace Umbraco.Cms.Core
|
||||
/// All languages.
|
||||
/// </summary>
|
||||
public const int Languages = -340;
|
||||
|
||||
/// <summary>
|
||||
/// ScheduledPublishing job.
|
||||
/// </summary>
|
||||
public const int ScheduledPublishing = -341;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
|
||||
namespace Umbraco.Cms.Core.Persistence.Repositories
|
||||
{
|
||||
[Obsolete("This interface will be merged with IMacroRepository in Umbraco 11")]
|
||||
public interface IMacroWithAliasRepository : IMacroRepository
|
||||
{
|
||||
IMacro GetByAlias(string alias);
|
||||
|
||||
IEnumerable<IMacro> GetAllByAlias(string[] aliases);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
|
||||
namespace Umbraco.Cms.Core.Persistence.Repositories
|
||||
{
|
||||
public interface ITrackedReferencesRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a page of items which are in relation with the current item.
|
||||
/// Basically, shows the items which depend on the current item.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier of the entity to retrieve relations for.</param>
|
||||
/// <param name="pageIndex">The page index.</param>
|
||||
/// <param name="pageSize">The page size.</param>
|
||||
/// <param name="filterMustBeIsDependency">A boolean indicating whether to filter only the RelationTypes which are dependencies (isDependency field is set to true).</param>
|
||||
/// <param name="totalRecords">The total count of the items with reference to the current item.</param>
|
||||
/// <returns>An enumerable list of <see cref="RelationItem"/> objects.</returns>
|
||||
IEnumerable<RelationItem> GetPagedRelationsForItem(int id, long pageIndex, int pageSize, bool filterMustBeIsDependency, out long totalRecords);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a page of items used in any kind of relation from selected integer ids.
|
||||
/// </summary>
|
||||
/// <param name="ids">The identifiers of the entities to check for relations.</param>
|
||||
/// <param name="pageIndex">The page index.</param>
|
||||
/// <param name="pageSize">The page size.</param>
|
||||
/// <param name="filterMustBeIsDependency">A boolean indicating whether to filter only the RelationTypes which are dependencies (isDependency field is set to true).</param>
|
||||
/// <param name="totalRecords">The total count of the items in any kind of relation.</param>
|
||||
/// <returns>An enumerable list of <see cref="RelationItem"/> objects.</returns>
|
||||
IEnumerable<RelationItem> GetPagedItemsWithRelations(int[] ids, long pageIndex, int pageSize, bool filterMustBeIsDependency, out long totalRecords);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a page of the descending items that have any references, given a parent id.
|
||||
/// </summary>
|
||||
/// <param name="parentId">The unique identifier of the parent to retrieve descendants for.</param>
|
||||
/// <param name="pageIndex">The page index.</param>
|
||||
/// <param name="pageSize">The page size.</param>
|
||||
/// <param name="filterMustBeIsDependency">A boolean indicating whether to filter only the RelationTypes which are dependencies (isDependency field is set to true).</param>
|
||||
/// <param name="totalRecords">The total count of descending items.</param>
|
||||
/// <returns>An enumerable list of <see cref="RelationItem"/> objects.</returns>
|
||||
IEnumerable<RelationItem> GetPagedDescendantsInReferences(int parentId, long pageIndex, int pageSize, bool filterMustBeIsDependency, out long totalRecords);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core.Hosting;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Editors;
|
||||
@@ -158,17 +157,15 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
/// <exception cref="System.ArgumentOutOfRangeException">ValueType was out of range.</exception>
|
||||
internal Attempt<object> TryConvertValueToCrlType(object value)
|
||||
{
|
||||
// Ensure empty string values are converted to null
|
||||
if (value is string s && string.IsNullOrWhiteSpace(s))
|
||||
// Ensure empty string and JSON values are converted to null
|
||||
if (value is string stringValue && string.IsNullOrWhiteSpace(stringValue))
|
||||
{
|
||||
value = null;
|
||||
}
|
||||
|
||||
// Ensure JSON is serialized properly (without indentation or converted to null when empty)
|
||||
if (value is not null && ValueType.InvariantEquals(ValueTypes.Json))
|
||||
else if (value is not string && ValueType.InvariantEquals(ValueTypes.Json))
|
||||
{
|
||||
// Only serialize value when it's not already a string
|
||||
var jsonValue = _jsonSerializer.Serialize(value);
|
||||
|
||||
if (jsonValue.DetectIsEmptyJson())
|
||||
{
|
||||
value = null;
|
||||
|
||||
+14
-2
@@ -1,5 +1,5 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core.Hosting;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Strings;
|
||||
@@ -28,5 +28,17 @@ namespace Umbraco.Cms.Core.PropertyEditors.ParameterEditors
|
||||
DefaultConfiguration.Add("minNumber",0 );
|
||||
DefaultConfiguration.Add("maxNumber", 0);
|
||||
}
|
||||
|
||||
protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create<MultipleContentPickerParameterEditor.MultipleContentPickerParamateterValueEditor>(Attribute);
|
||||
|
||||
internal class MultipleContentPickerParamateterValueEditor : MultiplePickerParamateterValueEditorBase
|
||||
{
|
||||
public MultipleContentPickerParamateterValueEditor(ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer, IIOHelper ioHelper, DataEditorAttribute attribute, IEntityService entityService) : base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute, entityService)
|
||||
{
|
||||
}
|
||||
|
||||
public override string UdiEntityType { get; } = Constants.UdiEntityType.Document;
|
||||
public override UmbracoObjectTypes UmbracoObjectType { get; } = UmbracoObjectTypes.Document;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-2
@@ -1,5 +1,9 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core.Hosting;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Metadata;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Editors;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Strings;
|
||||
@@ -26,5 +30,17 @@ namespace Umbraco.Cms.Core.PropertyEditors.ParameterEditors
|
||||
{
|
||||
DefaultConfiguration.Add("multiPicker", "1");
|
||||
}
|
||||
|
||||
protected override IDataValueEditor CreateValueEditor() => DataValueEditorFactory.Create<MultipleMediaPickerPropertyValueEditor>(Attribute);
|
||||
|
||||
internal class MultipleMediaPickerPropertyValueEditor : MultiplePickerParamateterValueEditorBase
|
||||
{
|
||||
public MultipleMediaPickerPropertyValueEditor(ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, IJsonSerializer jsonSerializer, IIOHelper ioHelper, DataEditorAttribute attribute, IEntityService entityService) : base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute, entityService)
|
||||
{
|
||||
}
|
||||
|
||||
public override string UdiEntityType { get; } = Constants.UdiEntityType.Media;
|
||||
public override UmbracoObjectTypes UmbracoObjectType { get; } = UmbracoObjectTypes.Media;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Editors;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Strings;
|
||||
|
||||
namespace Umbraco.Cms.Core.PropertyEditors.ParameterEditors
|
||||
{
|
||||
internal abstract class MultiplePickerParamateterValueEditorBase : DataValueEditor, IDataValueReference
|
||||
{
|
||||
private readonly IEntityService _entityService;
|
||||
|
||||
public MultiplePickerParamateterValueEditorBase(
|
||||
ILocalizedTextService localizedTextService,
|
||||
IShortStringHelper shortStringHelper,
|
||||
IJsonSerializer jsonSerializer,
|
||||
IIOHelper ioHelper,
|
||||
DataEditorAttribute attribute,
|
||||
IEntityService entityService)
|
||||
: base(localizedTextService, shortStringHelper, jsonSerializer, ioHelper, attribute)
|
||||
{
|
||||
_entityService = entityService;
|
||||
}
|
||||
|
||||
public abstract string UdiEntityType { get; }
|
||||
public abstract UmbracoObjectTypes UmbracoObjectType { get; }
|
||||
public IEnumerable<UmbracoEntityReference> GetReferences(object value)
|
||||
{
|
||||
var asString = value is string str ? str : value?.ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(asString))
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var udiStr in asString.Split(','))
|
||||
{
|
||||
if (UdiParser.TryParse(udiStr, out Udi udi))
|
||||
{
|
||||
yield return new UmbracoEntityReference(udi);
|
||||
}
|
||||
|
||||
// this is needed to support the legacy case when the multiple media picker parameter editor stores ints not udis
|
||||
if (int.TryParse(udiStr, out var id))
|
||||
{
|
||||
Attempt<Guid> guidAttempt = _entityService.GetKey(id, UmbracoObjectType);
|
||||
Guid guid = guidAttempt.Success ? guidAttempt.Result : Guid.Empty;
|
||||
|
||||
if (guid != Guid.Empty)
|
||||
{
|
||||
yield return new UmbracoEntityReference(new GuidUdi(Constants.UdiEntityType.Media, guid));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,8 +134,13 @@ namespace Umbraco.Cms.Core.Routing
|
||||
return GetUrlFromRoute(route, umbracoContext, content.Id, current, mode, culture);
|
||||
}
|
||||
|
||||
internal UrlInfo GetUrlFromRoute(string route, IUmbracoContext umbracoContext, int id, Uri current,
|
||||
UrlMode mode, string culture)
|
||||
internal UrlInfo GetUrlFromRoute(
|
||||
string route,
|
||||
IUmbracoContext umbracoContext,
|
||||
int id,
|
||||
Uri current,
|
||||
UrlMode mode,
|
||||
string culture)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(route))
|
||||
{
|
||||
@@ -149,12 +154,12 @@ namespace Umbraco.Cms.Core.Routing
|
||||
// route is /<path> or <domainRootId>/<path>
|
||||
var pos = route.IndexOf('/');
|
||||
var path = pos == 0 ? route : route.Substring(pos);
|
||||
var domainUri = pos == 0
|
||||
DomainAndUri domainUri = pos == 0
|
||||
? null
|
||||
: DomainUtilities.DomainForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainMapper, int.Parse(route.Substring(0, pos), CultureInfo.InvariantCulture), current, culture);
|
||||
|
||||
var defaultCulture = _localizationService.GetDefaultLanguageIsoCode();
|
||||
if (domainUri is not null || culture == defaultCulture || string.IsNullOrEmpty(culture))
|
||||
if (domainUri is not null || string.IsNullOrEmpty(culture) || culture.Equals(defaultCulture, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var url = AssembleUrl(domainUri, path, current, mode).ToString();
|
||||
return UrlInfo.Url(url, culture);
|
||||
|
||||
@@ -269,16 +269,10 @@ namespace Umbraco.Extensions
|
||||
|
||||
if (!pcr.HasPublishedContent())
|
||||
{
|
||||
var logMsg = nameof(DetectCollisionAsync) +
|
||||
const string logMsg = nameof(DetectCollisionAsync) +
|
||||
" did not resolve a content item for original url: {Url}, translated to {TranslatedUrl} and culture: {Culture}";
|
||||
if (pcr.IgnorePublishedContentCollisions)
|
||||
{
|
||||
logger.LogDebug(logMsg, url, uri, culture);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogDebug(logMsg, url, uri, culture);
|
||||
}
|
||||
|
||||
logger.LogDebug(logMsg, url, uri, culture);
|
||||
|
||||
var urlInfo = UrlInfo.Message(textService.Localize("content", "routeErrorCannotRoute"), culture);
|
||||
return Attempt.Succeed(urlInfo);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Umbraco.Cms.Core.Runtime
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a class which can generate a distinct key for a MainDom boundary.
|
||||
/// </summary>
|
||||
public interface IMainDomKeyGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a key that signifies a MainDom boundary.
|
||||
/// </summary>
|
||||
string GenerateKey();
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ namespace Umbraco.Cms.Core.Runtime
|
||||
|
||||
if (_isMainDom.HasValue == false)
|
||||
{
|
||||
throw new InvalidOperationException("Register called when MainDom has not been acquired");
|
||||
throw new InvalidOperationException("Register called before IsMainDom has been established");
|
||||
}
|
||||
else if (_isMainDom == false)
|
||||
{
|
||||
@@ -225,7 +225,7 @@ namespace Umbraco.Cms.Core.Runtime
|
||||
{
|
||||
if (!_isMainDom.HasValue)
|
||||
{
|
||||
throw new InvalidOperationException("MainDom has not been acquired yet");
|
||||
throw new InvalidOperationException("IsMainDom has not been established yet");
|
||||
}
|
||||
return _isMainDom.Value;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
@@ -144,7 +144,7 @@ namespace Umbraco.Cms.Core.Security
|
||||
var saltBytes = Convert.FromBase64String(salt);
|
||||
byte[] inArray;
|
||||
|
||||
var hashAlgorithm = GetHashAlgorithm(algorithmType);
|
||||
using var hashAlgorithm = GetHashAlgorithm(algorithmType);
|
||||
var algorithm = hashAlgorithm as KeyedHashAlgorithm;
|
||||
if (algorithm != null)
|
||||
{
|
||||
@@ -209,11 +209,21 @@ namespace Umbraco.Cms.Core.Security
|
||||
{
|
||||
// This is for the v6-v8 hashing algorithm
|
||||
if (algorithm.InvariantEquals(Constants.Security.AspNetUmbraco8PasswordHashAlgorithmName))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Default validation value for old machine keys (switched to HMACSHA256 aspnet 4 https://docs.microsoft.com/en-us/aspnet/whitepapers/aspnet4/breaking-changes)
|
||||
if (algorithm.InvariantEquals("SHA1"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is for the <= v4 hashing algorithm
|
||||
if (IsLegacySHA1Algorithm(algorithm))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -227,7 +237,7 @@ namespace Umbraco.Cms.Core.Security
|
||||
/// <returns>The encoded password.</returns>
|
||||
private string HashLegacySHA1Password(string password)
|
||||
{
|
||||
var hashAlgorithm = GetLegacySHA1Algorithm(password);
|
||||
using var hashAlgorithm = GetLegacySHA1Algorithm(password);
|
||||
var hash = Convert.ToBase64String(hashAlgorithm.ComputeHash(Encoding.Unicode.GetBytes(password)));
|
||||
return hash;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
|
||||
@@ -17,13 +17,6 @@ namespace Umbraco.Cms.Core.Services
|
||||
/// <returns>An <see cref="IMacro"/> object</returns>
|
||||
IMacro GetByAlias(string alias);
|
||||
|
||||
///// <summary>
|
||||
///// Gets a list all available <see cref="IMacro"/> objects
|
||||
///// </summary>
|
||||
///// <param name="aliases">Optional array of aliases to limit the results</param>
|
||||
///// <returns>An enumerable list of <see cref="IMacro"/> objects</returns>
|
||||
//IEnumerable<IMacro> GetAll(params string[] aliases);
|
||||
|
||||
IEnumerable<IMacro> GetAll();
|
||||
|
||||
IEnumerable<IMacro> GetAll(params int[] ids);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
|
||||
namespace Umbraco.Cms.Core.Services
|
||||
{
|
||||
[Obsolete("This interface will be merged with IMacroService in Umbraco 11")]
|
||||
public interface IMacroWithAliasService : IMacroService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a list of available <see cref="IMacro"/> objects by alias.
|
||||
/// </summary>
|
||||
/// <param name="aliases">Optional array of aliases to limit the results</param>
|
||||
/// <returns>An enumerable list of <see cref="IMacro"/> objects</returns>
|
||||
IEnumerable<IMacro> GetAll(params string[] aliases);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
@@ -215,7 +215,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalChildren"></param>
|
||||
/// <returns></returns>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/></returns>
|
||||
IEnumerable<IUmbracoEntity> GetPagedParentEntitiesByChildId(int id, long pageIndex, int pageSize, out long totalChildren, params UmbracoObjectTypes[] entityTypes);
|
||||
|
||||
/// <summary>
|
||||
@@ -225,7 +225,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalChildren"></param>
|
||||
/// <returns></returns>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/></returns>
|
||||
IEnumerable<IUmbracoEntity> GetPagedChildEntitiesByParentId(int id, long pageIndex, int pageSize, out long totalChildren, params UmbracoObjectTypes[] entityTypes);
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using Umbraco.Cms.Core.Models;
|
||||
|
||||
namespace Umbraco.Cms.Core.Services
|
||||
{
|
||||
public interface ITrackedReferencesService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a paged result of items which are in relation with the current item.
|
||||
/// Basically, shows the items which depend on the current item.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier of the entity to retrieve relations for.</param>
|
||||
/// <param name="pageIndex">The page index.</param>
|
||||
/// <param name="pageSize">The page size.</param>
|
||||
/// <param name="filterMustBeIsDependency">A boolean indicating whether to filter only the RelationTypes which are dependencies (isDependency field is set to true).</param>
|
||||
/// <returns>A paged result of <see cref="RelationItem"/> objects.</returns>
|
||||
PagedResult<RelationItem> GetPagedRelationsForItem(int id, long pageIndex, int pageSize, bool filterMustBeIsDependency);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a paged result of the descending items that have any references, given a parent id.
|
||||
/// </summary>
|
||||
/// <param name="parentId">The unique identifier of the parent to retrieve descendants for.</param>
|
||||
/// <param name="pageIndex">The page index.</param>
|
||||
/// <param name="pageSize">The page size.</param>
|
||||
/// <param name="filterMustBeIsDependency">A boolean indicating whether to filter only the RelationTypes which are dependencies (isDependency field is set to true).</param>
|
||||
/// <returns>A paged result of <see cref="RelationItem"/> objects.</returns>
|
||||
PagedResult<RelationItem> GetPagedDescendantsInReferences(int parentId, long pageIndex, int pageSize, bool filterMustBeIsDependency);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a paged result of items used in any kind of relation from selected integer ids.
|
||||
/// </summary>
|
||||
/// <param name="ids">The identifiers of the entities to check for relations.</param>
|
||||
/// <param name="pageIndex">The page index.</param>
|
||||
/// <param name="pageSize">The page size.</param>
|
||||
/// <param name="filterMustBeIsDependency">A boolean indicating whether to filter only the RelationTypes which are dependencies (isDependency field is set to true).</param>
|
||||
/// <returns>A paged result of <see cref="RelationItem"/> objects.</returns>
|
||||
PagedResult<RelationItem> GetPagedItemsWithRelations(int[] ids, long pageIndex, int pageSize, bool filterMustBeIsDependency);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
|
||||
@@ -5,18 +6,14 @@ namespace Umbraco.Cms.Core
|
||||
{
|
||||
public static class StaticApplicationLogging
|
||||
{
|
||||
private static ILoggerFactory _loggerFactory;
|
||||
private static ILoggerFactory s_loggerFactory;
|
||||
|
||||
public static void Initialize(ILoggerFactory loggerFactory)
|
||||
{
|
||||
_loggerFactory = loggerFactory;
|
||||
}
|
||||
public static void Initialize(ILoggerFactory loggerFactory) => s_loggerFactory = loggerFactory;
|
||||
|
||||
public static ILogger<object> Logger => CreateLogger<object>();
|
||||
|
||||
public static ILogger<T> CreateLogger<T>()
|
||||
{
|
||||
return _loggerFactory?.CreateLogger<T>() ?? NullLoggerFactory.Instance.CreateLogger<T>();
|
||||
}
|
||||
public static ILogger<T> CreateLogger<T>() => s_loggerFactory?.CreateLogger<T>() ?? NullLoggerFactory.Instance.CreateLogger<T>();
|
||||
|
||||
public static ILogger CreateLogger(Type type) => s_loggerFactory?.CreateLogger(type) ?? NullLogger.Instance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Cms.Core.Telemetry
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to get and create the site identifier
|
||||
/// </summary>
|
||||
public interface ISiteIdentifierService
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the site identifier
|
||||
/// </summary>
|
||||
/// <returns>True if success.</returns>
|
||||
bool TryGetSiteIdentifier(out Guid siteIdentifier);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the site identifier and writes it to config.
|
||||
/// </summary>
|
||||
/// <param name="createdGuid">asd.</param>
|
||||
/// <returns>True if success.</returns>
|
||||
bool TryCreateSiteIdentifier(out Guid createdGuid);
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the site identifier or otherwise create it if it doesn't exist.
|
||||
/// </summary>
|
||||
/// <param name="siteIdentifier">The out parameter for the existing or create site identifier.</param>
|
||||
/// <returns>True if success.</returns>
|
||||
bool TryGetOrCreateSiteIdentifier(out Guid siteIdentifier);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
|
||||
namespace Umbraco.Cms.Core.Telemetry
|
||||
{
|
||||
/// <inheritdoc />
|
||||
internal class SiteIdentifierService : ISiteIdentifierService
|
||||
{
|
||||
private GlobalSettings _globalSettings;
|
||||
private readonly IConfigManipulator _configManipulator;
|
||||
private readonly ILogger<SiteIdentifierService> _logger;
|
||||
|
||||
public SiteIdentifierService(
|
||||
IOptionsMonitor<GlobalSettings> optionsMonitor,
|
||||
IConfigManipulator configManipulator,
|
||||
ILogger<SiteIdentifierService> logger)
|
||||
{
|
||||
_globalSettings = optionsMonitor.CurrentValue;
|
||||
optionsMonitor.OnChange(globalSettings => _globalSettings = globalSettings);
|
||||
_configManipulator = configManipulator;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetSiteIdentifier(out Guid siteIdentifier)
|
||||
{
|
||||
// Parse telemetry string as a GUID & verify its a GUID and not some random string
|
||||
// since users may have messed with or decided to empty the app setting or put in something random
|
||||
if (Guid.TryParse(_globalSettings.Id, out var parsedTelemetryId) is false
|
||||
|| parsedTelemetryId == Guid.Empty)
|
||||
{
|
||||
siteIdentifier = Guid.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
siteIdentifier = parsedTelemetryId;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetOrCreateSiteIdentifier(out Guid siteIdentifier)
|
||||
{
|
||||
if (TryGetSiteIdentifier(out Guid existingId))
|
||||
{
|
||||
siteIdentifier = existingId;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (TryCreateSiteIdentifier(out Guid createdId))
|
||||
{
|
||||
siteIdentifier = createdId;
|
||||
return true;
|
||||
}
|
||||
|
||||
siteIdentifier = Guid.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryCreateSiteIdentifier(out Guid createdGuid)
|
||||
{
|
||||
createdGuid = Guid.NewGuid();
|
||||
|
||||
try
|
||||
{
|
||||
_configManipulator.SetGlobalId(createdGuid.ToString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Couldn't update config files with a telemetry site identifier");
|
||||
createdGuid = Guid.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Manifest;
|
||||
using Umbraco.Cms.Core.Telemetry.Models;
|
||||
using Umbraco.Extensions;
|
||||
@@ -12,27 +10,27 @@ namespace Umbraco.Cms.Core.Telemetry
|
||||
/// <inheritdoc/>
|
||||
internal class TelemetryService : ITelemetryService
|
||||
{
|
||||
private readonly IOptionsMonitor<GlobalSettings> _globalSettings;
|
||||
private readonly IManifestParser _manifestParser;
|
||||
private readonly IUmbracoVersion _umbracoVersion;
|
||||
private readonly ISiteIdentifierService _siteIdentifierService;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TelemetryService"/> class.
|
||||
/// </summary>
|
||||
public TelemetryService(
|
||||
IOptionsMonitor<GlobalSettings> globalSettings,
|
||||
IManifestParser manifestParser,
|
||||
IUmbracoVersion umbracoVersion)
|
||||
IUmbracoVersion umbracoVersion,
|
||||
ISiteIdentifierService siteIdentifierService)
|
||||
{
|
||||
_manifestParser = manifestParser;
|
||||
_umbracoVersion = umbracoVersion;
|
||||
_globalSettings = globalSettings;
|
||||
_siteIdentifierService = siteIdentifierService;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool TryGetTelemetryReportData(out TelemetryReportData telemetryReportData)
|
||||
{
|
||||
if (TryGetTelemetryId(out Guid telemetryId) is false)
|
||||
if (_siteIdentifierService.TryGetOrCreateSiteIdentifier(out Guid telemetryId) is false)
|
||||
{
|
||||
telemetryReportData = null;
|
||||
return false;
|
||||
@@ -42,28 +40,14 @@ namespace Umbraco.Cms.Core.Telemetry
|
||||
{
|
||||
Id = telemetryId,
|
||||
Version = _umbracoVersion.SemanticVersion.ToSemanticStringWithoutBuild(),
|
||||
Packages = GetPackageTelemetry()
|
||||
Packages = GetPackageTelemetry(),
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryGetTelemetryId(out Guid telemetryId)
|
||||
{
|
||||
// Parse telemetry string as a GUID & verify its a GUID and not some random string
|
||||
// since users may have messed with or decided to empty the app setting or put in something random
|
||||
if (Guid.TryParse(_globalSettings.CurrentValue.Id, out var parsedTelemetryId) is false)
|
||||
{
|
||||
telemetryId = Guid.Empty;
|
||||
return false;
|
||||
}
|
||||
|
||||
telemetryId = parsedTelemetryId;
|
||||
return true;
|
||||
}
|
||||
|
||||
private IEnumerable<PackageTelemetry> GetPackageTelemetry()
|
||||
{
|
||||
List<PackageTelemetry> packages = new ();
|
||||
List<PackageTelemetry> packages = new();
|
||||
IEnumerable<PackageManifest> manifests = _manifestParser.GetManifests();
|
||||
|
||||
foreach (PackageManifest manifest in manifests)
|
||||
@@ -76,7 +60,7 @@ namespace Umbraco.Cms.Core.Telemetry
|
||||
packages.Add(new PackageTelemetry
|
||||
{
|
||||
Name = manifest.PackageName,
|
||||
Version = manifest.Version ?? string.Empty
|
||||
Version = manifest.Version ?? string.Empty,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,11 @@ namespace Umbraco.Cms.Infrastructure.Examine
|
||||
IOptionsMonitor<LuceneDirectoryIndexOptions> indexOptions)
|
||||
{
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_indexOptions = indexOptions.Get(index.Name);
|
||||
if (indexOptions != null)
|
||||
{
|
||||
_indexOptions = indexOptions.Get(index.Name);
|
||||
|
||||
}
|
||||
Index = index;
|
||||
Logger = logger;
|
||||
}
|
||||
@@ -35,7 +39,7 @@ namespace Umbraco.Cms.Infrastructure.Examine
|
||||
public LuceneIndex Index { get; }
|
||||
public ILogger<LuceneIndexDiagnostics> Logger { get; }
|
||||
|
||||
|
||||
|
||||
|
||||
public Attempt<string> IsHealthy()
|
||||
{
|
||||
@@ -72,12 +76,12 @@ namespace Umbraco.Cms.Infrastructure.Examine
|
||||
{
|
||||
d[nameof(LuceneDirectoryIndexOptions.DirectoryFactory)] = _indexOptions.DirectoryFactory.GetType();
|
||||
}
|
||||
|
||||
|
||||
if (_indexOptions.IndexDeletionPolicy != null)
|
||||
{
|
||||
d[nameof(LuceneDirectoryIndexOptions.IndexDeletionPolicy)] = _indexOptions.IndexDeletionPolicy.GetType();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return d;
|
||||
|
||||
@@ -2,26 +2,45 @@ using System;
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Configuration.Json;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Cms.Core.Configuration;
|
||||
using Umbraco.Cms.Web.Common.DependencyInjection;
|
||||
|
||||
namespace Umbraco.Cms.Core.Configuration
|
||||
{
|
||||
public class JsonConfigManipulator : IConfigManipulator
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger<JsonConfigManipulator> _logger;
|
||||
private readonly object _locker = new object();
|
||||
|
||||
public JsonConfigManipulator(IConfiguration configuration) => _configuration = configuration;
|
||||
[Obsolete]
|
||||
public JsonConfigManipulator(IConfiguration configuration)
|
||||
: this(configuration, StaticServiceProvider.Instance.GetRequiredService<ILogger<JsonConfigManipulator>>())
|
||||
{ }
|
||||
|
||||
public string UmbracoConnectionPath { get; } = $"ConnectionStrings:{ Cms.Core.Constants.System.UmbracoConnectionName}";
|
||||
public JsonConfigManipulator(
|
||||
IConfiguration configuration,
|
||||
ILogger<JsonConfigManipulator> logger)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string UmbracoConnectionPath { get; } = $"ConnectionStrings:{Cms.Core.Constants.System.UmbracoConnectionName}";
|
||||
public void RemoveConnectionString()
|
||||
{
|
||||
var provider = GetJsonConfigurationProvider(UmbracoConnectionPath);
|
||||
|
||||
var json = GetJson(provider);
|
||||
if (json is null)
|
||||
{
|
||||
_logger.LogWarning("Failed to remove connection string from JSON configuration.");
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveJsonKey(json, UmbracoConnectionPath);
|
||||
|
||||
@@ -33,6 +52,11 @@ namespace Umbraco.Cms.Core.Configuration
|
||||
var provider = GetJsonConfigurationProvider();
|
||||
|
||||
var json = GetJson(provider);
|
||||
if (json is null)
|
||||
{
|
||||
_logger.LogWarning("Failed to save connection string in JSON configuration.");
|
||||
return;
|
||||
}
|
||||
|
||||
var item = GetConnectionItem(connectionString, providerName);
|
||||
|
||||
@@ -47,6 +71,11 @@ namespace Umbraco.Cms.Core.Configuration
|
||||
var provider = GetJsonConfigurationProvider();
|
||||
|
||||
var json = GetJson(provider);
|
||||
if (json is null)
|
||||
{
|
||||
_logger.LogWarning("Failed to save configuration key \"{Key}\" in JSON configuration.", key);
|
||||
return;
|
||||
}
|
||||
|
||||
JToken token = json;
|
||||
foreach (var propertyName in key.Split(new[] { ':' }))
|
||||
@@ -73,6 +102,11 @@ namespace Umbraco.Cms.Core.Configuration
|
||||
var provider = GetJsonConfigurationProvider();
|
||||
|
||||
var json = GetJson(provider);
|
||||
if (json is null)
|
||||
{
|
||||
_logger.LogWarning("Failed to save enabled/disabled state for redirect URL tracking in JSON configuration.");
|
||||
return;
|
||||
}
|
||||
|
||||
var item = GetDisableRedirectUrlItem(disable);
|
||||
|
||||
@@ -86,6 +120,11 @@ namespace Umbraco.Cms.Core.Configuration
|
||||
var provider = GetJsonConfigurationProvider();
|
||||
|
||||
var json = GetJson(provider);
|
||||
if (json is null)
|
||||
{
|
||||
_logger.LogWarning("Failed to save global identifier in JSON configuration.");
|
||||
return;
|
||||
}
|
||||
|
||||
var item = GetGlobalIdItem(id);
|
||||
|
||||
@@ -170,13 +209,20 @@ namespace Umbraco.Cms.Core.Configuration
|
||||
{
|
||||
var jsonFilePath = Path.Combine(physicalFileProvider.Root, provider.Source.Path);
|
||||
|
||||
using (var sw = new StreamWriter(jsonFilePath, false))
|
||||
using (var jsonTextWriter = new JsonTextWriter(sw)
|
||||
try
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
})
|
||||
using (var sw = new StreamWriter(jsonFilePath, false))
|
||||
using (var jsonTextWriter = new JsonTextWriter(sw)
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
})
|
||||
{
|
||||
json?.WriteTo(jsonTextWriter);
|
||||
}
|
||||
}
|
||||
catch (IOException exception)
|
||||
{
|
||||
json?.WriteTo(jsonTextWriter);
|
||||
_logger.LogWarning(exception, "JSON configuration could not be written: {path}", jsonFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,19 +232,25 @@ namespace Umbraco.Cms.Core.Configuration
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
if (provider.Source.FileProvider is PhysicalFileProvider physicalFileProvider)
|
||||
if (provider.Source.FileProvider is not PhysicalFileProvider physicalFileProvider)
|
||||
{
|
||||
var jsonFilePath = Path.Combine(physicalFileProvider.Root, provider.Source.Path);
|
||||
|
||||
var serializer = new JsonSerializer();
|
||||
using (var sr = new StreamReader(jsonFilePath))
|
||||
using (var jsonTextReader = new JsonTextReader(sr))
|
||||
{
|
||||
return serializer.Deserialize<JObject>(jsonTextReader);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
var jsonFilePath = Path.Combine(physicalFileProvider.Root, provider.Source.Path);
|
||||
|
||||
try
|
||||
{
|
||||
var serializer = new JsonSerializer();
|
||||
using var sr = new StreamReader(jsonFilePath);
|
||||
using var jsonTextReader = new JsonTextReader(sr);
|
||||
return serializer.Deserialize<JObject>(jsonTextReader);
|
||||
}
|
||||
catch (IOException exception)
|
||||
{
|
||||
_logger.LogWarning(exception, "JSON configuration could not be read: {path}", jsonFilePath);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -218,6 +218,7 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection
|
||||
|
||||
private static IUmbracoBuilder AddMainDom(this IUmbracoBuilder builder)
|
||||
{
|
||||
builder.Services.AddSingleton<IMainDomKeyGenerator, DefaultMainDomKeyGenerator>();
|
||||
builder.Services.AddSingleton<IMainDomLock>(factory =>
|
||||
{
|
||||
var globalSettings = factory.GetRequiredService<IOptions<GlobalSettings>>();
|
||||
@@ -229,15 +230,20 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection
|
||||
var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
||||
var loggerFactory = factory.GetRequiredService<ILoggerFactory>();
|
||||
var npocoMappers = factory.GetRequiredService<NPocoMapperCollection>();
|
||||
var mainDomKeyGenerator = factory.GetRequiredService<IMainDomKeyGenerator>();
|
||||
|
||||
if (globalSettings.Value.MainDomLock == "FileSystemMainDomLock")
|
||||
{
|
||||
return new FileSystemMainDomLock(loggerFactory.CreateLogger<FileSystemMainDomLock>(), mainDomKeyGenerator, hostingEnvironment, factory.GetRequiredService<IOptionsMonitor<GlobalSettings>>());
|
||||
}
|
||||
|
||||
return globalSettings.Value.MainDomLock.Equals("SqlMainDomLock") || isWindows == false
|
||||
? (IMainDomLock)new SqlMainDomLock(
|
||||
loggerFactory.CreateLogger<SqlMainDomLock>(),
|
||||
loggerFactory,
|
||||
globalSettings,
|
||||
connectionStrings,
|
||||
dbCreator,
|
||||
hostingEnvironment,
|
||||
mainDomKeyGenerator,
|
||||
databaseSchemaCreatorFactory,
|
||||
npocoMappers)
|
||||
: new MainDomSemaphoreLock(loggerFactory.CreateLogger<MainDomSemaphoreLock>(), hostingEnvironment);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.IO;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
@@ -49,7 +50,7 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection
|
||||
ILogger<PhysicalFileSystem> logger = factory.GetRequiredService<ILogger<PhysicalFileSystem>>();
|
||||
GlobalSettings globalSettings = factory.GetRequiredService<IOptions<GlobalSettings>>().Value;
|
||||
|
||||
var rootPath = hostingEnvironment.MapPathWebRoot(globalSettings.UmbracoMediaPhysicalRootPath);
|
||||
var rootPath = Path.IsPathRooted(globalSettings.UmbracoMediaPhysicalRootPath) ? globalSettings.UmbracoMediaPhysicalRootPath : hostingEnvironment.MapPathWebRoot(globalSettings.UmbracoMediaPhysicalRootPath);
|
||||
var rootUrl = hostingEnvironment.ToAbsolute(globalSettings.UmbracoMediaPath);
|
||||
return new PhysicalFileSystem(ioHelper, hostingEnvironment, logger, rootPath, rootUrl);
|
||||
});
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Install.InstallSteps;
|
||||
using Umbraco.Cms.Core.Install.Models;
|
||||
using Umbraco.Cms.Core.Telemetry;
|
||||
using Umbraco.Cms.Infrastructure.Install;
|
||||
using Umbraco.Cms.Infrastructure.Install.InstallSteps;
|
||||
using Umbraco.Extensions;
|
||||
@@ -19,7 +22,12 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection
|
||||
builder.Services.AddScoped<InstallSetupStep, NewInstallStep>();
|
||||
builder.Services.AddScoped<InstallSetupStep, UpgradeStep>();
|
||||
builder.Services.AddScoped<InstallSetupStep, FilePermissionsStep>();
|
||||
builder.Services.AddScoped<InstallSetupStep, TelemetryIdentifierStep>();
|
||||
builder.Services.AddScoped<InstallSetupStep, TelemetryIdentifierStep>(provider =>
|
||||
{
|
||||
return new TelemetryIdentifierStep(
|
||||
provider.GetRequiredService<IOptions<GlobalSettings>>(),
|
||||
provider.GetRequiredService<ISiteIdentifierService>());
|
||||
});
|
||||
builder.Services.AddScoped<InstallSetupStep, DatabaseConfigureStep>();
|
||||
builder.Services.AddScoped<InstallSetupStep, DatabaseInstallStep>();
|
||||
builder.Services.AddScoped<InstallSetupStep, DatabaseUpgradeStep>();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Persistence.Repositories;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
@@ -47,6 +46,7 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection
|
||||
builder.Services.AddUnique<IPublicAccessRepository, PublicAccessRepository>();
|
||||
builder.Services.AddUnique<IRedirectUrlRepository, RedirectUrlRepository>();
|
||||
builder.Services.AddUnique<IRelationRepository, RelationRepository>();
|
||||
builder.Services.AddUnique<ITrackedReferencesRepository, TrackedReferencesRepository>();
|
||||
builder.Services.AddUnique<IRelationTypeRepository, RelationTypeRepository>();
|
||||
builder.Services.AddUnique<IServerRegistrationRepository, ServerRegistrationRepository>();
|
||||
builder.Services.AddUnique<ITagRepository, TagRepository>();
|
||||
|
||||
@@ -18,9 +18,9 @@ using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Services.Implement;
|
||||
using Umbraco.Cms.Infrastructure.Packaging;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement;
|
||||
using Umbraco.Cms.Infrastructure.Services.Implement;
|
||||
using Umbraco.Cms.Infrastructure.Templates;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.DependencyInjection
|
||||
@@ -63,6 +63,7 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection
|
||||
builder.Services.AddUnique<IServerRegistrationService, ServerRegistrationService>();
|
||||
builder.Services.AddUnique<IEntityService, EntityService>();
|
||||
builder.Services.AddUnique<IRelationService, RelationService>();
|
||||
builder.Services.AddUnique<ITrackedReferencesService, TrackedReferencesService>();
|
||||
builder.Services.AddUnique<IMacroService, MacroService>();
|
||||
builder.Services.AddUnique<IMemberTypeService, MemberTypeService>();
|
||||
builder.Services.AddUnique<IMemberGroupService, MemberGroupService>();
|
||||
@@ -91,6 +92,7 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection
|
||||
builder.Services.AddUnique<ICreatedPackagesRepository, CreatedPackageSchemaRepository>();
|
||||
builder.Services.AddSingleton<PackageDataInstallation>();
|
||||
builder.Services.AddUnique<IPackageInstallation, PackageInstallation>();
|
||||
builder.Services.AddUnique<IHtmlMacroParameterParser, HtmlMacroParameterParser>();
|
||||
|
||||
return builder;
|
||||
}
|
||||
@@ -123,7 +125,8 @@ namespace Umbraco.Cms.Infrastructure.DependencyInjection
|
||||
var pluginLangFolders = appPlugins.Exists == false
|
||||
? Enumerable.Empty<LocalizedTextServiceSupplementaryFileSource>()
|
||||
: appPlugins.GetDirectories()
|
||||
.SelectMany(x => x.GetDirectories("Lang", SearchOption.AllDirectories))
|
||||
// Check for both Lang & lang to support case sensitive file systems.
|
||||
.SelectMany(x => x.GetDirectories("?ang", SearchOption.AllDirectories).Where(x => x.Name.InvariantEquals("lang")))
|
||||
.SelectMany(x => x.GetFiles("*.xml", SearchOption.TopDirectoryOnly))
|
||||
.Select(x => new LocalizedTextServiceSupplementaryFileSource(x, false));
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace Umbraco.Cms.Core.Events
|
||||
var documentObjectType = Constants.ObjectTypes.Document;
|
||||
const string relationTypeName = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteName;
|
||||
|
||||
relationType = new RelationType(relationTypeName, relationTypeAlias, false, documentObjectType, documentObjectType);
|
||||
relationType = new RelationType(relationTypeName, relationTypeAlias, false, documentObjectType, documentObjectType, false);
|
||||
_relationService.Save(relationType);
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace Umbraco.Cms.Core.Events
|
||||
{
|
||||
var documentObjectType = Constants.ObjectTypes.Document;
|
||||
const string relationTypeName = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName;
|
||||
relationType = new RelationType(relationTypeName, relationTypeAlias, false, documentObjectType, documentObjectType);
|
||||
relationType = new RelationType(relationTypeName, relationTypeAlias, false, documentObjectType, documentObjectType, false);
|
||||
_relationService.Save(relationType);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
IContentVersionService service,
|
||||
IMainDom mainDom,
|
||||
IServerRoleAccessor serverRoleAccessor)
|
||||
: base(TimeSpan.FromHours(1), TimeSpan.FromMinutes(3))
|
||||
: base(logger, TimeSpan.FromHours(1), TimeSpan.FromMinutes(3))
|
||||
{
|
||||
_runtimeState = runtimeState;
|
||||
_logger = logger;
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
IProfilingLogger profilingLogger,
|
||||
ICronTabParser cronTabParser)
|
||||
: base(
|
||||
logger,
|
||||
healthChecksSettings.Value.Notification.Period,
|
||||
healthChecksSettings.Value.GetNotificationDelay(cronTabParser, DateTime.Now, DefaultDelay))
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Hosting;
|
||||
using Umbraco.Cms.Core.Logging;
|
||||
@@ -48,7 +49,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
IProfilingLogger profilingLogger,
|
||||
IServerRoleAccessor serverRegistrar,
|
||||
IHttpClientFactory httpClientFactory)
|
||||
: base(TimeSpan.FromMinutes(5), DefaultDelay)
|
||||
: base(logger, TimeSpan.FromMinutes(5), DefaultDelay)
|
||||
{
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_mainDom = mainDom;
|
||||
@@ -99,7 +100,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
try
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, keepAlivePingUrl);
|
||||
HttpClient httpClient = _httpClientFactory.CreateClient();
|
||||
HttpClient httpClient = _httpClientFactory.CreateClient(Constants.HttpClients.IgnoreCertificateErrors);
|
||||
_ = await httpClient.SendAsync(request);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
IScopeProvider scopeProvider,
|
||||
ILogger<LogScrubber> logger,
|
||||
IProfilingLogger profilingLogger)
|
||||
: base(TimeSpan.FromHours(4), DefaultDelay)
|
||||
: base(logger, TimeSpan.FromHours(4), DefaultDelay)
|
||||
{
|
||||
_mainDom = mainDom;
|
||||
_serverRegistrar = serverRegistrar;
|
||||
|
||||
@@ -5,6 +5,8 @@ using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
{
|
||||
@@ -21,25 +23,39 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
/// </summary>
|
||||
protected static readonly TimeSpan DefaultDelay = TimeSpan.FromMinutes(3);
|
||||
|
||||
private readonly TimeSpan _period;
|
||||
private readonly ILogger _logger;
|
||||
private TimeSpan _period;
|
||||
private readonly TimeSpan _delay;
|
||||
private Timer _timer;
|
||||
private bool _disposedValue;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RecurringHostedServiceBase"/> class.
|
||||
/// </summary>
|
||||
/// <param name="period">Timepsan representing how often the task should recur.</param>
|
||||
/// <param name="delay">Timespan represeting the initial delay after application start-up before the first run of the task occurs.</param>
|
||||
protected RecurringHostedServiceBase(TimeSpan period, TimeSpan delay)
|
||||
/// <param name="logger">Logger.</param>
|
||||
/// <param name="period">Timespan representing how often the task should recur.</param>
|
||||
/// <param name="delay">Timespan representing the initial delay after application start-up before the first run of the task occurs.</param>
|
||||
protected RecurringHostedServiceBase(ILogger logger, TimeSpan period, TimeSpan delay)
|
||||
{
|
||||
_logger = logger;
|
||||
_period = period;
|
||||
_delay = delay;
|
||||
}
|
||||
|
||||
// Scheduled for removal in V11
|
||||
[Obsolete("Please use constructor that takes an ILogger instead")]
|
||||
protected RecurringHostedServiceBase(TimeSpan period, TimeSpan delay)
|
||||
: this(null, period, delay)
|
||||
{ }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_timer = new Timer(ExecuteAsync, null, (int)_delay.TotalMilliseconds, (int)_period.TotalMilliseconds);
|
||||
using (!ExecutionContext.IsFlowSuppressed() ? (IDisposable)ExecutionContext.SuppressFlow() : null)
|
||||
{
|
||||
_timer = new Timer(ExecuteAsync, null, (int)_delay.TotalMilliseconds, (int)_period.TotalMilliseconds);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -60,6 +76,11 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
// Hat-tip: https://stackoverflow.com/a/14207615/489433
|
||||
await PerformExecuteAsync(state);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ILogger logger = _logger ?? StaticApplicationLogging.CreateLogger(GetType());
|
||||
logger.LogError(ex, "Unhandled exception in recurring hosted service.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Resume now that the task is complete - Note we use period in both because we don't want to execute again after the delay.
|
||||
@@ -73,11 +94,29 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
/// <inheritdoc/>
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_period = Timeout.InfiniteTimeSpan;
|
||||
_timer?.Change(Timeout.Infinite, 0);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_timer?.Dispose();
|
||||
}
|
||||
|
||||
_disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose() => _timer?.Dispose();
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
public ReportSiteTask(
|
||||
ILogger<ReportSiteTask> logger,
|
||||
ITelemetryService telemetryService)
|
||||
: base(TimeSpan.FromDays(1), TimeSpan.FromMinutes(1))
|
||||
: base(logger, TimeSpan.FromDays(1), TimeSpan.FromMinutes(1))
|
||||
{
|
||||
_logger = logger;
|
||||
_telemetryService = telemetryService;
|
||||
@@ -59,9 +59,6 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
// Send data to LIVE telemetry
|
||||
s_httpClient.BaseAddress = new Uri("https://telemetry.umbraco.com/");
|
||||
|
||||
// Set a low timeout - no need to use a larger default timeout for this POST request
|
||||
s_httpClient.Timeout = new TimeSpan(0, 0, 1);
|
||||
|
||||
#if DEBUG
|
||||
// Send data to DEBUG telemetry service
|
||||
s_httpClient.BaseAddress = new Uri("https://telemetry.rainbowsrock.net/");
|
||||
|
||||
@@ -5,13 +5,15 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Runtime;
|
||||
using Umbraco.Cms.Core.Security;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Sync;
|
||||
using Umbraco.Cms.Core.Web;
|
||||
using Umbraco.Cms.Web.Common.DependencyInjection;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
{
|
||||
@@ -27,20 +29,16 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
private readonly IMainDom _mainDom;
|
||||
private readonly IRuntimeState _runtimeState;
|
||||
private readonly IServerMessenger _serverMessenger;
|
||||
private readonly IScopeProvider _scopeProvider;
|
||||
private readonly IServerRoleAccessor _serverRegistrar;
|
||||
private readonly IUmbracoContextFactory _umbracoContextFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ScheduledPublishing"/> class.
|
||||
/// </summary>
|
||||
/// <param name="runtimeState">Representation of the state of the Umbraco runtime.</param>
|
||||
/// <param name="mainDom">Representation of the main application domain.</param>
|
||||
/// <param name="serverRegistrar">Provider of server registrations to the distributed cache.</param>
|
||||
/// <param name="contentService">Service for handling content operations.</param>
|
||||
/// <param name="umbracoContextFactory">Service for creating and managing Umbraco context.</param>
|
||||
/// <param name="logger">The typed logger.</param>
|
||||
/// <param name="serverMessenger">Service broadcasting cache notifications to registered servers.</param>
|
||||
/// <param name="backofficeSecurityFactory">Creates and manages <see cref="IBackOfficeSecurity"/> instances.</param>
|
||||
// Note: Ignoring the two version notice rule as this class should probably be internal.
|
||||
// We don't expect anyone downstream to be instantiating a HostedService
|
||||
[Obsolete("This constructor will be removed in version 10, please use an alternative constructor.")]
|
||||
public ScheduledPublishing(
|
||||
IRuntimeState runtimeState,
|
||||
IMainDom mainDom,
|
||||
@@ -49,7 +47,31 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
IUmbracoContextFactory umbracoContextFactory,
|
||||
ILogger<ScheduledPublishing> logger,
|
||||
IServerMessenger serverMessenger)
|
||||
: base(TimeSpan.FromMinutes(1), DefaultDelay)
|
||||
: this(
|
||||
runtimeState,
|
||||
mainDom,
|
||||
serverRegistrar,
|
||||
contentService,
|
||||
umbracoContextFactory,
|
||||
logger,
|
||||
serverMessenger,
|
||||
StaticServiceProvider.Instance.GetRequiredService<IScopeProvider>())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ScheduledPublishing"/> class.
|
||||
/// </summary>
|
||||
public ScheduledPublishing(
|
||||
IRuntimeState runtimeState,
|
||||
IMainDom mainDom,
|
||||
IServerRoleAccessor serverRegistrar,
|
||||
IContentService contentService,
|
||||
IUmbracoContextFactory umbracoContextFactory,
|
||||
ILogger<ScheduledPublishing> logger,
|
||||
IServerMessenger serverMessenger,
|
||||
IScopeProvider scopeProvider)
|
||||
: base(logger, TimeSpan.FromMinutes(1), DefaultDelay)
|
||||
{
|
||||
_runtimeState = runtimeState;
|
||||
_mainDom = mainDom;
|
||||
@@ -58,6 +80,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
_umbracoContextFactory = umbracoContextFactory;
|
||||
_logger = logger;
|
||||
_serverMessenger = serverMessenger;
|
||||
_scopeProvider = scopeProvider;
|
||||
}
|
||||
|
||||
public override Task PerformExecuteAsync(object state)
|
||||
@@ -93,8 +116,6 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
|
||||
try
|
||||
{
|
||||
// We don't need an explicit scope here because PerformScheduledPublish creates it's own scope
|
||||
// so it's safe as it will create it's own ambient scope.
|
||||
// Ensure we run with an UmbracoContext, because this will run in a background task,
|
||||
// and developers may be using the UmbracoContext in the event handlers.
|
||||
|
||||
@@ -105,6 +126,14 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
// - and we should definitively *not* have to flush it here (should be auto)
|
||||
|
||||
using UmbracoContextReference contextReference = _umbracoContextFactory.EnsureUmbracoContext();
|
||||
using IScope scope = _scopeProvider.CreateScope(autoComplete: true);
|
||||
|
||||
/* We used to assume that there will never be two instances running concurrently where (IsMainDom && ServerRole == SchedulingPublisher)
|
||||
* However this is possible during an azure deployment slot swap for the SchedulingPublisher instance when trying to achieve zero downtime deployments.
|
||||
* If we take a distributed write lock, we are certain that the multiple instances of the job will not run in parallel.
|
||||
* It's possible that during the swapping process we may run this job more frequently than intended but this is not of great concern and it's
|
||||
* only until the old SchedulingPublisher shuts down. */
|
||||
scope.EagerWriteLock(Constants.Locks.ScheduledPublishing);
|
||||
try
|
||||
{
|
||||
// Run
|
||||
|
||||
+17
-1
@@ -20,6 +20,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices.ServerRegistration
|
||||
private readonly IRuntimeState _runtimeState;
|
||||
private readonly IServerMessenger _messenger;
|
||||
private readonly ILogger<InstructionProcessTask> _logger;
|
||||
private bool _disposedValue;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InstructionProcessTask"/> class.
|
||||
@@ -29,7 +30,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices.ServerRegistration
|
||||
/// <param name="logger">The typed logger.</param>
|
||||
/// <param name="globalSettings">The configuration for global settings.</param>
|
||||
public InstructionProcessTask(IRuntimeState runtimeState, IServerMessenger messenger, ILogger<InstructionProcessTask> logger, IOptions<GlobalSettings> globalSettings)
|
||||
: base(globalSettings.Value.DatabaseServerMessenger.TimeBetweenSyncOperations, TimeSpan.FromMinutes(1))
|
||||
: base(logger, globalSettings.Value.DatabaseServerMessenger.TimeBetweenSyncOperations, TimeSpan.FromMinutes(1))
|
||||
{
|
||||
_runtimeState = runtimeState;
|
||||
_messenger = messenger;
|
||||
@@ -54,5 +55,20 @@ namespace Umbraco.Cms.Infrastructure.HostedServices.ServerRegistration
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposedValue)
|
||||
{
|
||||
if (disposing && _messenger is IDisposable disposable)
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
|
||||
_disposedValue = true;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,17 @@
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Hosting;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Sync;
|
||||
using Umbraco.Cms.Web.Common.DependencyInjection;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.HostedServices.ServerRegistration
|
||||
@@ -22,6 +26,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices.ServerRegistration
|
||||
private readonly IServerRegistrationService _serverRegistrationService;
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly ILogger<TouchServerTask> _logger;
|
||||
private readonly IServerRoleAccessor _serverRoleAccessor;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
|
||||
/// <summary>
|
||||
@@ -37,14 +42,33 @@ namespace Umbraco.Cms.Infrastructure.HostedServices.ServerRegistration
|
||||
IServerRegistrationService serverRegistrationService,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
ILogger<TouchServerTask> logger,
|
||||
IOptions<GlobalSettings> globalSettings)
|
||||
: base(globalSettings.Value.DatabaseServerRegistrar.WaitTimeBetweenCalls, TimeSpan.FromSeconds(15))
|
||||
IOptions<GlobalSettings> globalSettings,
|
||||
IServerRoleAccessor serverRoleAccessor)
|
||||
: base(logger, globalSettings.Value.DatabaseServerRegistrar.WaitTimeBetweenCalls, TimeSpan.FromSeconds(15))
|
||||
{
|
||||
_runtimeState = runtimeState;
|
||||
_serverRegistrationService = serverRegistrationService ?? throw new ArgumentNullException(nameof(serverRegistrationService));
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_logger = logger;
|
||||
_globalSettings = globalSettings.Value;
|
||||
_serverRoleAccessor = serverRoleAccessor;
|
||||
}
|
||||
|
||||
[Obsolete("Use constructor that takes an IServerRoleAccessor")]
|
||||
public TouchServerTask(
|
||||
IRuntimeState runtimeState,
|
||||
IServerRegistrationService serverRegistrationService,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
ILogger<TouchServerTask> logger,
|
||||
IOptions<GlobalSettings> globalSettings)
|
||||
: this(
|
||||
runtimeState,
|
||||
serverRegistrationService,
|
||||
hostingEnvironment,
|
||||
logger,
|
||||
globalSettings,
|
||||
StaticServiceProvider.Instance.GetRequiredService<IServerRoleAccessor>())
|
||||
{
|
||||
}
|
||||
|
||||
public override Task PerformExecuteAsync(object state)
|
||||
@@ -54,6 +78,14 @@ namespace Umbraco.Cms.Infrastructure.HostedServices.ServerRegistration
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// If the IServerRoleAccessor has been changed away from ElectedServerRoleAccessor this task no longer makes sense,
|
||||
// since all it's used for is to allow the ElectedServerRoleAccessor
|
||||
// to figure out what role a given server has, so we just stop this task.
|
||||
if (_serverRoleAccessor is not ElectedServerRoleAccessor)
|
||||
{
|
||||
return StopAsync(CancellationToken.None);
|
||||
}
|
||||
|
||||
var serverAddress = _hostingEnvironment.ApplicationMainUrl?.ToString();
|
||||
if (serverAddress.IsNullOrWhiteSpace())
|
||||
{
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Umbraco.Cms.Infrastructure.HostedServices
|
||||
/// <param name="mainDom">Representation of the main application domain.</param>
|
||||
/// <param name="logger">The typed logger.</param>
|
||||
public TempFileCleanup(IIOHelper ioHelper, IMainDom mainDom, ILogger<TempFileCleanup> logger)
|
||||
: base(TimeSpan.FromMinutes(60), DefaultDelay)
|
||||
: base(logger, TimeSpan.FromMinutes(60), DefaultDelay)
|
||||
{
|
||||
_ioHelper = ioHelper;
|
||||
_mainDom = mainDom;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.XPath;
|
||||
using Examine.Search;
|
||||
@@ -8,31 +8,46 @@ using Umbraco.Cms.Core.Xml;
|
||||
namespace Umbraco.Cms.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Query methods used for accessing strongly typed content in templates
|
||||
/// Query methods used for accessing strongly typed content in templates.
|
||||
/// </summary>
|
||||
public interface IPublishedContentQuery
|
||||
{
|
||||
IPublishedContent Content(int id);
|
||||
|
||||
IPublishedContent Content(Guid id);
|
||||
|
||||
IPublishedContent Content(Udi id);
|
||||
|
||||
IPublishedContent Content(object id);
|
||||
|
||||
IPublishedContent ContentSingleAtXPath(string xpath, params XPathVariable[] vars);
|
||||
|
||||
IEnumerable<IPublishedContent> Content(IEnumerable<int> ids);
|
||||
|
||||
IEnumerable<IPublishedContent> Content(IEnumerable<Guid> ids);
|
||||
|
||||
IEnumerable<IPublishedContent> Content(IEnumerable<object> ids);
|
||||
|
||||
IEnumerable<IPublishedContent> ContentAtXPath(string xpath, params XPathVariable[] vars);
|
||||
|
||||
IEnumerable<IPublishedContent> ContentAtXPath(XPathExpression xpath, params XPathVariable[] vars);
|
||||
|
||||
IEnumerable<IPublishedContent> ContentAtRoot();
|
||||
|
||||
IPublishedContent Media(int id);
|
||||
|
||||
IPublishedContent Media(Guid id);
|
||||
|
||||
IPublishedContent Media(Udi id);
|
||||
|
||||
IPublishedContent Media(object id);
|
||||
|
||||
IEnumerable<IPublishedContent> Media(IEnumerable<int> ids);
|
||||
|
||||
IEnumerable<IPublishedContent> Media(IEnumerable<object> ids);
|
||||
|
||||
IEnumerable<IPublishedContent> Media(IEnumerable<Guid> ids);
|
||||
|
||||
IEnumerable<IPublishedContent> MediaAtRoot();
|
||||
|
||||
/// <summary>
|
||||
@@ -44,7 +59,7 @@ namespace Umbraco.Cms.Core
|
||||
/// <param name="totalRecords">The total amount of records.</param>
|
||||
/// <param name="culture">The culture (defaults to a culture insensitive search).</param>
|
||||
/// <param name="indexName">The name of the index to search (defaults to <see cref="Constants.UmbracoIndexes.ExternalIndexName" />).</param>
|
||||
/// <param name="loadedFields">The fields to load in the results of the search (defaults to all fields loaded).</param>
|
||||
/// <param name="loadedFields">This parameter is no longer used, because the results are loaded from the published snapshot using the single item ID field.</param>
|
||||
/// <returns>
|
||||
/// The search results.
|
||||
/// </returns>
|
||||
|
||||
@@ -175,6 +175,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install
|
||||
_database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Cms.Core.Constants.Locks.Domains, Name = "Domains" });
|
||||
_database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Cms.Core.Constants.Locks.KeyValues, Name = "KeyValues" });
|
||||
_database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Cms.Core.Constants.Locks.Languages, Name = "Languages" });
|
||||
_database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Cms.Core.Constants.Locks.ScheduledPublishing, Name = "ScheduledPublishing" });
|
||||
|
||||
_database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Cms.Core.Constants.Locks.MainDom, Name = "MainDom" });
|
||||
}
|
||||
@@ -420,21 +421,21 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install
|
||||
|
||||
private void CreateRelationTypeData()
|
||||
{
|
||||
var relationType = new RelationTypeDto { Id = 1, Alias = Cms.Core.Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias, ChildObjectType = Cms.Core.Constants.ObjectTypes.Document, ParentObjectType = Cms.Core.Constants.ObjectTypes.Document, Dual = true, Name = Cms.Core.Constants.Conventions.RelationTypes.RelateDocumentOnCopyName };
|
||||
var relationType = new RelationTypeDto { Id = 1, Alias = Cms.Core.Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias, ChildObjectType = Cms.Core.Constants.ObjectTypes.Document, ParentObjectType = Cms.Core.Constants.ObjectTypes.Document, Dual = true, Name = Cms.Core.Constants.Conventions.RelationTypes.RelateDocumentOnCopyName, IsDependency = false};
|
||||
relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name);
|
||||
_database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);
|
||||
relationType = new RelationTypeDto { Id = 2, Alias = Cms.Core.Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias, ChildObjectType = Cms.Core.Constants.ObjectTypes.Document, ParentObjectType = Cms.Core.Constants.ObjectTypes.Document, Dual = false, Name = Cms.Core.Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteName };
|
||||
relationType = new RelationTypeDto { Id = 2, Alias = Cms.Core.Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias, ChildObjectType = Cms.Core.Constants.ObjectTypes.Document, ParentObjectType = Cms.Core.Constants.ObjectTypes.Document, Dual = false, Name = Cms.Core.Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteName, IsDependency = false };
|
||||
relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name);
|
||||
_database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);
|
||||
relationType = new RelationTypeDto { Id = 3, Alias = Cms.Core.Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias, ChildObjectType = Cms.Core.Constants.ObjectTypes.Media, ParentObjectType = Cms.Core.Constants.ObjectTypes.Media, Dual = false, Name = Cms.Core.Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName };
|
||||
relationType = new RelationTypeDto { Id = 3, Alias = Cms.Core.Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias, ChildObjectType = Cms.Core.Constants.ObjectTypes.Media, ParentObjectType = Cms.Core.Constants.ObjectTypes.Media, Dual = false, Name = Cms.Core.Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName, IsDependency = false };
|
||||
relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name);
|
||||
_database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);
|
||||
|
||||
relationType = new RelationTypeDto { Id = 4, Alias = Cms.Core.Constants.Conventions.RelationTypes.RelatedMediaAlias, ChildObjectType = null, ParentObjectType = null, Dual = false, Name = Cms.Core.Constants.Conventions.RelationTypes.RelatedMediaName };
|
||||
relationType = new RelationTypeDto { Id = 4, Alias = Cms.Core.Constants.Conventions.RelationTypes.RelatedMediaAlias, ChildObjectType = null, ParentObjectType = null, Dual = false, Name = Cms.Core.Constants.Conventions.RelationTypes.RelatedMediaName, IsDependency = true };
|
||||
relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name);
|
||||
_database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);
|
||||
|
||||
relationType = new RelationTypeDto { Id = 5, Alias = Cms.Core.Constants.Conventions.RelationTypes.RelatedDocumentAlias, ChildObjectType = null, ParentObjectType = null, Dual = false, Name = Cms.Core.Constants.Conventions.RelationTypes.RelatedDocumentName };
|
||||
relationType = new RelationTypeDto { Id = 5, Alias = Cms.Core.Constants.Conventions.RelationTypes.RelatedDocumentAlias, ChildObjectType = null, ParentObjectType = null, Dual = false, Name = Cms.Core.Constants.Conventions.RelationTypes.RelatedDocumentName, IsDependency = true };
|
||||
relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name);
|
||||
_database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_1_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_2_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_3_0;
|
||||
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_4_0;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade
|
||||
@@ -242,6 +243,9 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade
|
||||
// to 8.17.0
|
||||
To<AddPropertyTypeGroupColumns>("{153865E9-7332-4C2A-9F9D-F20AEE078EC7}");
|
||||
|
||||
// Hack to support migration from 8.18
|
||||
To<NoopMigration>("{03482BB0-CF13-475C-845E-ECB8319DBE3C}");
|
||||
|
||||
// This should be safe to execute again. We need it with a new name to ensure updates from all the following has executed this step.
|
||||
// - 8.15.0 RC - Current state: {4695D0C9-0729-4976-985B-048D503665D8}
|
||||
// - 8.15.0 Final - Current state: {5C424554-A32D-4852-8ED1-A13508187901}
|
||||
@@ -277,6 +281,9 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade
|
||||
To<UpdateExternalLoginToUseKeyInsteadOfId>("{CA7A1D9D-C9D4-4914-BC0A-459E7B9C3C8C}");
|
||||
To<AddTwoFactorLoginTable>("{0828F206-DCF7-4F73-ABBB-6792275532EB}");
|
||||
|
||||
// TO 9.4.0
|
||||
To<AddScheduledPublishingLock>("{DBBA1EA0-25A1-4863-90FB-5D306FB6F1E1}");
|
||||
To<UpdateRelationTypesToHandleDependencies>("{DED98755-4059-41BB-ADBD-3FEAB12D1D7B}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NPoco;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0
|
||||
@@ -20,14 +24,14 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0
|
||||
{
|
||||
// Before adding these indexes we need to remove duplicate data.
|
||||
// Get all logins by latest
|
||||
var logins = Database.Fetch<ExternalLoginDto>()
|
||||
var logins = Database.Fetch<ExternalLoginTokenTable.LegacyExternalLoginDto>()
|
||||
.OrderByDescending(x => x.CreateDate)
|
||||
.ToList();
|
||||
|
||||
var toDelete = new List<int>();
|
||||
// used to track duplicates so they can be removed
|
||||
var keys = new HashSet<(string, string)>();
|
||||
foreach(ExternalLoginDto login in logins)
|
||||
foreach(ExternalLoginTokenTable.LegacyExternalLoginDto login in logins)
|
||||
{
|
||||
if (!keys.Add((login.ProviderKey, login.LoginProvider)))
|
||||
{
|
||||
@@ -37,16 +41,16 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0
|
||||
}
|
||||
if (toDelete.Count > 0)
|
||||
{
|
||||
Database.DeleteMany<ExternalLoginDto>().Where(x => toDelete.Contains(x.Id)).Execute();
|
||||
}
|
||||
Database.DeleteMany<ExternalLoginTokenTable.LegacyExternalLoginDto>().Where(x => toDelete.Contains(x.Id)).Execute();
|
||||
}
|
||||
|
||||
var indexName1 = "IX_" + ExternalLoginDto.TableName + "_LoginProvider";
|
||||
var indexName1 = "IX_" + ExternalLoginTokenTable.LegacyExternalLoginDto.TableName + "_LoginProvider";
|
||||
|
||||
if (!IndexExists(indexName1))
|
||||
{
|
||||
Create
|
||||
.Index(indexName1)
|
||||
.OnTable(ExternalLoginDto.TableName)
|
||||
.OnTable(ExternalLoginTokenTable.LegacyExternalLoginDto.TableName)
|
||||
.OnColumn("loginProvider")
|
||||
.Ascending()
|
||||
.WithOptions()
|
||||
@@ -56,13 +60,13 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0
|
||||
.Do();
|
||||
}
|
||||
|
||||
var indexName2 = "IX_" + ExternalLoginDto.TableName + "_ProviderKey";
|
||||
var indexName2 = "IX_" + ExternalLoginTokenTable.LegacyExternalLoginDto.TableName + "_ProviderKey";
|
||||
|
||||
if (!IndexExists(indexName2))
|
||||
{
|
||||
Create
|
||||
.Index(indexName2)
|
||||
.OnTable(ExternalLoginDto.TableName)
|
||||
.OnTable(ExternalLoginTokenTable.LegacyExternalLoginDto.TableName)
|
||||
.OnColumn("loginProvider").Ascending()
|
||||
.OnColumn("providerKey").Ascending()
|
||||
.WithOptions()
|
||||
@@ -70,5 +74,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0
|
||||
.Do();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+8
-8
@@ -14,29 +14,29 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0
|
||||
|
||||
protected override void Migrate()
|
||||
{
|
||||
var indexName1 = "IX_" + ExternalLoginDto.TableName + "_LoginProvider";
|
||||
var indexName2 = "IX_" + ExternalLoginDto.TableName + "_ProviderKey";
|
||||
var indexName1 = "IX_" + ExternalLoginTokenTable.LegacyExternalLoginDto.TableName + "_LoginProvider";
|
||||
var indexName2 = "IX_" + ExternalLoginTokenTable.LegacyExternalLoginDto.TableName + "_ProviderKey";
|
||||
|
||||
if (IndexExists(indexName1))
|
||||
{
|
||||
// drop it since the previous migration index was wrong, and we
|
||||
// need to modify a column that belons to it
|
||||
Delete.Index(indexName1).OnTable(ExternalLoginDto.TableName).Do();
|
||||
Delete.Index(indexName1).OnTable(ExternalLoginTokenTable.LegacyExternalLoginDto.TableName).Do();
|
||||
}
|
||||
|
||||
if (IndexExists(indexName2))
|
||||
{
|
||||
// drop since it's using a column we're about to modify
|
||||
Delete.Index(indexName2).OnTable(ExternalLoginDto.TableName).Do();
|
||||
Delete.Index(indexName2).OnTable(ExternalLoginTokenTable.LegacyExternalLoginDto.TableName).Do();
|
||||
}
|
||||
|
||||
// then fixup the length of the loginProvider column
|
||||
AlterColumn<ExternalLoginDto>(ExternalLoginDto.TableName, "loginProvider");
|
||||
AlterColumn<ExternalLoginTokenTable.LegacyExternalLoginDto>(ExternalLoginTokenTable.LegacyExternalLoginDto.TableName, "loginProvider");
|
||||
|
||||
// create it with the correct definition
|
||||
Create
|
||||
.Index(indexName1)
|
||||
.OnTable(ExternalLoginDto.TableName)
|
||||
.OnTable(ExternalLoginTokenTable.LegacyExternalLoginDto.TableName)
|
||||
.OnColumn("loginProvider").Ascending()
|
||||
.OnColumn("userId").Ascending()
|
||||
.WithOptions()
|
||||
@@ -48,9 +48,9 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0
|
||||
// re-create the original
|
||||
Create
|
||||
.Index(indexName2)
|
||||
.OnTable(ExternalLoginDto.TableName)
|
||||
.OnTable(ExternalLoginTokenTable.LegacyExternalLoginDto.TableName)
|
||||
.OnColumn("loginProvider").Ascending()
|
||||
.OnColumn("providerKey").Ascending()
|
||||
.OnColumn("providerKey").Ascending()
|
||||
.WithOptions()
|
||||
.NonClustered()
|
||||
.Do();
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NPoco;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0
|
||||
{
|
||||
|
||||
public class ExternalLoginTokenTable : MigrationBase
|
||||
{
|
||||
public ExternalLoginTokenTable(IMigrationContext context)
|
||||
@@ -13,7 +17,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds new External Login token table
|
||||
/// Adds new External Login token table
|
||||
/// </summary>
|
||||
protected override void Migrate()
|
||||
{
|
||||
@@ -25,5 +29,53 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_0_0
|
||||
|
||||
Create.Table<ExternalLoginTokenDto>().Do();
|
||||
}
|
||||
|
||||
[TableName(TableName)]
|
||||
[ExplicitColumns]
|
||||
[PrimaryKey("Id")]
|
||||
internal class LegacyExternalLoginDto
|
||||
{
|
||||
public const string TableName = Constants.DatabaseSchema.Tables.ExternalLogin;
|
||||
|
||||
[Column("id")] [PrimaryKeyColumn] public int Id { get; set; }
|
||||
|
||||
[Obsolete(
|
||||
"This only exists to ensure you can upgrade using external logins from umbraco version where this was used to the new where it is not used")]
|
||||
[Column("userId")]
|
||||
public int? UserId { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Used to store the name of the provider (i.e. Facebook, Google)
|
||||
/// </summary>
|
||||
[Column("loginProvider")]
|
||||
[Length(400)]
|
||||
[NullSetting(NullSetting = NullSettings.NotNull)]
|
||||
[Index(IndexTypes.UniqueNonClustered, ForColumns = "loginProvider,userOrMemberKey",
|
||||
Name = "IX_" + TableName + "_LoginProvider")]
|
||||
public string LoginProvider { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stores the key the provider uses to lookup the login
|
||||
/// </summary>
|
||||
[Column("providerKey")]
|
||||
[Length(4000)]
|
||||
[NullSetting(NullSetting = NullSettings.NotNull)]
|
||||
[Index(IndexTypes.NonClustered, ForColumns = "loginProvider,providerKey",
|
||||
Name = "IX_" + TableName + "_ProviderKey")]
|
||||
public string ProviderKey { get; set; }
|
||||
|
||||
[Column("createDate")]
|
||||
[Constraint(Default = SystemMethods.CurrentDateTime)]
|
||||
public DateTime CreateDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to store any arbitrary data for the user and external provider - like user tokens returned from the provider
|
||||
/// </summary>
|
||||
[Column("userData")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[SpecialDbType(SpecialDbTypes.NTEXT)]
|
||||
public string UserData { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_4_0
|
||||
{
|
||||
internal class AddScheduledPublishingLock : MigrationBase
|
||||
{
|
||||
public AddScheduledPublishingLock(IMigrationContext context)
|
||||
: base(context)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Migrate() =>
|
||||
Database.Insert(Cms.Core.Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Cms.Core.Constants.Locks.ScheduledPublishing, Name = "ScheduledPublishing" });
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.Dtos;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_9_4_0
|
||||
{
|
||||
internal class UpdateRelationTypesToHandleDependencies : MigrationBase
|
||||
{
|
||||
public UpdateRelationTypesToHandleDependencies(IMigrationContext context)
|
||||
: base(context)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Migrate()
|
||||
{
|
||||
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToList();
|
||||
|
||||
AddColumnIfNotExists<RelationTypeDto>(columns, "isDependency");
|
||||
|
||||
var aliasesWithDependencies = new[]
|
||||
{
|
||||
Core.Constants.Conventions.RelationTypes.RelatedDocumentAlias,
|
||||
Core.Constants.Conventions.RelationTypes.RelatedMediaAlias
|
||||
};
|
||||
|
||||
Database.Execute(
|
||||
Sql()
|
||||
.Update<RelationTypeDto>(u => u.Set(x => x.IsDependency, true))
|
||||
.WhereIn<RelationTypeDto>(x => x.Alias, aliasesWithDependencies));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -575,21 +575,22 @@ namespace Umbraco.Cms.Infrastructure.Packaging
|
||||
{
|
||||
var importedFolders = new Dictionary<string, int>();
|
||||
var trackEntityContainersInstalled = new List<EntityContainer>();
|
||||
foreach (var documentType in unsortedDocumentTypes)
|
||||
|
||||
foreach (XElement documentType in unsortedDocumentTypes)
|
||||
{
|
||||
var foldersAttribute = documentType.Attribute("Folders");
|
||||
var infoElement = documentType.Element("Info");
|
||||
XAttribute foldersAttribute = documentType.Attribute("Folders");
|
||||
XElement infoElement = documentType.Element("Info");
|
||||
if (foldersAttribute != null && infoElement != null
|
||||
//don't import any folder if this is a child doc type - the parent doc type will need to
|
||||
//exist which contains it's folders
|
||||
// don't import any folder if this is a child doc type - the parent doc type will need to
|
||||
// exist which contains it's folders
|
||||
&& ((string)infoElement.Element("Master")).IsNullOrWhiteSpace())
|
||||
{
|
||||
var alias = documentType.Element("Info").Element("Alias").Value;
|
||||
var folders = foldersAttribute.Value.Split(Constants.CharArrays.ForwardSlash);
|
||||
|
||||
var folderKeysAttribute = documentType.Attribute("FolderKeys");
|
||||
XAttribute folderKeysAttribute = documentType.Attribute("FolderKeys");
|
||||
|
||||
var folderKeys = Array.Empty<Guid>();
|
||||
Guid[] folderKeys = Array.Empty<Guid>();
|
||||
if (folderKeysAttribute != null)
|
||||
{
|
||||
folderKeys = folderKeysAttribute.Value.Split(Constants.CharArrays.ForwardSlash).Select(x=>Guid.Parse(x)).ToArray();
|
||||
@@ -597,22 +598,22 @@ namespace Umbraco.Cms.Infrastructure.Packaging
|
||||
|
||||
var rootFolder = WebUtility.UrlDecode(folders[0]);
|
||||
|
||||
EntityContainer current;
|
||||
EntityContainer current = null;
|
||||
Guid? rootFolderKey = null;
|
||||
if (folderKeys.Length == folders.Length && folderKeys.Length > 0)
|
||||
{
|
||||
rootFolderKey = folderKeys[0];
|
||||
current = _contentTypeService.GetContainer(rootFolderKey.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
//level 1 = root level folders, there can only be one with the same name
|
||||
current = _contentTypeService.GetContainers(rootFolder, 1).FirstOrDefault();
|
||||
}
|
||||
|
||||
// The folder might already exist, but with a different key, so check if it exists, even if there is a key.
|
||||
// Level 1 = root level folders, there can only be one with the same name
|
||||
current ??= _contentTypeService.GetContainers(rootFolder, 1).FirstOrDefault();
|
||||
|
||||
if (current == null)
|
||||
{
|
||||
var tryCreateFolder = _contentTypeService.CreateContainer(-1, rootFolderKey ?? Guid.NewGuid(), rootFolder);
|
||||
Attempt<OperationResult<OperationResultType, EntityContainer>> tryCreateFolder = _contentTypeService.CreateContainer(-1, rootFolderKey ?? Guid.NewGuid(), rootFolder);
|
||||
|
||||
if (tryCreateFolder == false)
|
||||
{
|
||||
_logger.LogError(tryCreateFolder.Exception, "Could not create folder: {FolderName}", rootFolder);
|
||||
@@ -644,7 +645,7 @@ namespace Umbraco.Cms.Infrastructure.Packaging
|
||||
private EntityContainer CreateContentTypeChildFolder(string folderName, Guid folderKey, IUmbracoEntity current)
|
||||
{
|
||||
var children = _entityService.GetChildren(current.Id).ToArray();
|
||||
var found = children.Any(x => x.Name.InvariantEquals(folderName) ||x.Key.Equals(folderKey));
|
||||
var found = children.Any(x => x.Name.InvariantEquals(folderName) || x.Key.Equals(folderKey));
|
||||
if (found)
|
||||
{
|
||||
var containerId = children.Single(x => x.Name.InvariantEquals(folderName)).Id;
|
||||
|
||||
@@ -40,5 +40,9 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Dtos
|
||||
[Length(100)]
|
||||
[Index(IndexTypes.UniqueNonClustered, Name = "IX_umbracoRelationType_alias")]
|
||||
public string Alias { get; set; }
|
||||
|
||||
[Constraint(Default = "0")]
|
||||
[Column("isDependency")]
|
||||
public bool IsDependency { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Factories
|
||||
|
||||
public static IRelationType BuildEntity(RelationTypeDto dto)
|
||||
{
|
||||
var entity = new RelationType(dto.Name, dto.Alias, dto.Dual, dto.ParentObjectType, dto.ChildObjectType);
|
||||
var entity = new RelationType(dto.Name, dto.Alias, dto.Dual, dto.ParentObjectType, dto.ChildObjectType, dto.IsDependency);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -30,11 +30,17 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Factories
|
||||
|
||||
public static RelationTypeDto BuildDto(IRelationType entity)
|
||||
{
|
||||
var isDependency = false;
|
||||
if (entity is IRelationTypeWithIsDependency relationTypeWithIsDependency)
|
||||
{
|
||||
isDependency = relationTypeWithIsDependency.IsDependency;
|
||||
}
|
||||
var dto = new RelationTypeDto
|
||||
{
|
||||
Alias = entity.Alias,
|
||||
ChildObjectType = entity.ChildObjectType,
|
||||
Dual = entity.IsBidirectional,
|
||||
IsDependency = isDependency,
|
||||
Name = entity.Name,
|
||||
ParentObjectType = entity.ParentObjectType,
|
||||
UniqueId = entity.Key
|
||||
@@ -47,6 +53,8 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Factories
|
||||
return dto;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Mappers
|
||||
DefineMap<RelationType, RelationTypeDto>(nameof(RelationType.Alias), nameof(RelationTypeDto.Alias));
|
||||
DefineMap<RelationType, RelationTypeDto>(nameof(RelationType.ChildObjectType), nameof(RelationTypeDto.ChildObjectType));
|
||||
DefineMap<RelationType, RelationTypeDto>(nameof(RelationType.IsBidirectional), nameof(RelationTypeDto.Dual));
|
||||
DefineMap<RelationType, RelationTypeDto>(nameof(RelationType.IsDependency), nameof(RelationTypeDto.IsDependency));
|
||||
DefineMap<RelationType, RelationTypeDto>(nameof(RelationType.Name), nameof(RelationTypeDto.Name));
|
||||
DefineMap<RelationType, RelationTypeDto>(nameof(RelationType.ParentObjectType), nameof(RelationTypeDto.ParentObjectType));
|
||||
}
|
||||
|
||||
@@ -72,7 +72,27 @@ namespace Umbraco.Extensions
|
||||
/// <returns>The Sql statement.</returns>
|
||||
public static Sql<ISqlContext> WhereIn<TDto>(this Sql<ISqlContext> sql, Expression<Func<TDto, object>> field, Sql<ISqlContext> values)
|
||||
{
|
||||
return sql.WhereIn(field, values, false);
|
||||
return WhereIn(sql, field, values, false, null);
|
||||
}
|
||||
|
||||
public static Sql<ISqlContext> WhereIn<TDto>(this Sql<ISqlContext> sql, Expression<Func<TDto, object>> field, Sql<ISqlContext> values, string tableAlias)
|
||||
{
|
||||
return sql.WhereIn(field, values, false, tableAlias);
|
||||
}
|
||||
|
||||
|
||||
public static Sql<ISqlContext> WhereLike<TDto>(this Sql<ISqlContext> sql, Expression<Func<TDto, object>> fieldSelector, Sql<ISqlContext> valuesSql)
|
||||
{
|
||||
var fieldName = sql.SqlContext.SqlSyntax.GetFieldName(fieldSelector);
|
||||
sql.Where(fieldName + " LIKE (" + valuesSql.SQL + ")", valuesSql.Arguments);
|
||||
return sql;
|
||||
}
|
||||
|
||||
public static Sql<ISqlContext> WhereLike<TDto>(this Sql<ISqlContext> sql, Expression<Func<TDto, object>> fieldSelector, string likeValue)
|
||||
{
|
||||
var fieldName = sql.SqlContext.SqlSyntax.GetFieldName(fieldSelector);
|
||||
sql.Where(fieldName + " LIKE ('" + likeValue + "')");
|
||||
return sql;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -130,7 +150,12 @@ namespace Umbraco.Extensions
|
||||
|
||||
private static Sql<ISqlContext> WhereIn<T>(this Sql<ISqlContext> sql, Expression<Func<T, object>> fieldSelector, Sql valuesSql, bool not)
|
||||
{
|
||||
var fieldName = sql.SqlContext.SqlSyntax.GetFieldName(fieldSelector);
|
||||
return WhereIn(sql, fieldSelector, valuesSql, not, null);
|
||||
}
|
||||
|
||||
private static Sql<ISqlContext> WhereIn<T>(this Sql<ISqlContext> sql, Expression<Func<T, object>> fieldSelector, Sql valuesSql, bool not, string tableAlias)
|
||||
{
|
||||
var fieldName = sql.SqlContext.SqlSyntax.GetFieldName(fieldSelector, tableAlias);
|
||||
sql.Where(fieldName + (not ? " NOT" : "") +" IN (" + valuesSql.SQL + ")", valuesSql.Arguments);
|
||||
return sql;
|
||||
}
|
||||
@@ -252,7 +277,7 @@ namespace Umbraco.Extensions
|
||||
/// <returns>The Sql statement.</returns>
|
||||
public static Sql<ISqlContext> OrderByDescending<TDto>(this Sql<ISqlContext> sql, Expression<Func<TDto, object>> field)
|
||||
{
|
||||
return sql.OrderBy("(" + sql.SqlContext.SqlSyntax.GetFieldName(field) + ") DESC");
|
||||
return sql.OrderByDescending(sql.SqlContext.SqlSyntax.GetFieldName(field));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -268,7 +293,7 @@ namespace Umbraco.Extensions
|
||||
var columns = fields.Length == 0
|
||||
? sql.GetColumns<TDto>(withAlias: false)
|
||||
: fields.Select(x => sqlSyntax.GetFieldName(x)).ToArray();
|
||||
return sql.OrderBy(columns.Select(x => x + " DESC"));
|
||||
return sql.OrderByDescending(columns);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -634,6 +659,12 @@ namespace Umbraco.Extensions
|
||||
return sql;
|
||||
}
|
||||
|
||||
public static Sql<ISqlContext> SelectDistinct(this Sql<ISqlContext> sql, params object[] columns)
|
||||
{
|
||||
sql.Append("SELECT DISTINCT " + string.Join(", ", columns));
|
||||
return sql;
|
||||
}
|
||||
|
||||
//this.Append("SELECT " + string.Join(", ", columns), new object[0]);
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -468,7 +468,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Querying
|
||||
case nameof(StringExtensions.InvariantStartsWith):
|
||||
case nameof(StringExtensions.InvariantEndsWith):
|
||||
case nameof(StringExtensions.InvariantContains):
|
||||
case nameof(StringExtensions.InvariantEquals):
|
||||
case nameof(StringExtensions.InvariantEquals):
|
||||
|
||||
string compareValue;
|
||||
|
||||
@@ -629,7 +629,7 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Querying
|
||||
if (m.Arguments.Count == 2)
|
||||
{
|
||||
var n1 = Visit(m.Arguments[0]);
|
||||
var f = m.Arguments[2];
|
||||
var f = m.Arguments[1];
|
||||
if (!(f is Expression<Func<string, string>> fl))
|
||||
throw new NotSupportedException("Expression is not a proper lambda.");
|
||||
var ff = fl.Compile();
|
||||
|
||||
@@ -18,14 +18,16 @@ using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
{
|
||||
internal class MacroRepository : EntityRepositoryBase<int, IMacro>, IMacroRepository
|
||||
internal class MacroRepository : EntityRepositoryBase<int, IMacro>, IMacroWithAliasRepository
|
||||
{
|
||||
private readonly IShortStringHelper _shortStringHelper;
|
||||
private readonly IRepositoryCachePolicy<IMacro, string> _macroByAliasCachePolicy;
|
||||
|
||||
public MacroRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger<MacroRepository> logger, IShortStringHelper shortStringHelper)
|
||||
: base(scopeAccessor, cache, logger)
|
||||
{
|
||||
_shortStringHelper = shortStringHelper;
|
||||
_macroByAliasCachePolicy = new DefaultRepositoryCachePolicy<IMacro, string>(GlobalIsolatedCache, ScopeAccessor, DefaultOptions);
|
||||
}
|
||||
|
||||
protected override IMacro PerformGet(int id)
|
||||
@@ -68,6 +70,38 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
return Get(id) != null;
|
||||
}
|
||||
|
||||
public IMacro GetByAlias(string alias)
|
||||
{
|
||||
return _macroByAliasCachePolicy.Get(alias, PerformGetByAlias, PerformGetAllByAlias);
|
||||
}
|
||||
|
||||
public IEnumerable<IMacro> GetAllByAlias(string[] aliases)
|
||||
{
|
||||
if (aliases.Any() is false)
|
||||
{
|
||||
return base.GetMany();
|
||||
}
|
||||
|
||||
return _macroByAliasCachePolicy.GetAll(aliases, PerformGetAllByAlias);
|
||||
}
|
||||
|
||||
private IMacro PerformGetByAlias(string alias)
|
||||
{
|
||||
var query = Query<IMacro>().Where(x => x.Alias.Equals(alias));
|
||||
return PerformGetByQuery(query).FirstOrDefault();
|
||||
}
|
||||
|
||||
private IEnumerable<IMacro> PerformGetAllByAlias(params string[] aliases)
|
||||
{
|
||||
if (aliases.Any() is false)
|
||||
{
|
||||
return base.GetMany();
|
||||
}
|
||||
|
||||
var query = Query<IMacro>().Where(x => aliases.Contains(x.Alias));
|
||||
return PerformGetByQuery(query);
|
||||
}
|
||||
|
||||
protected override IEnumerable<IMacro> PerformGetAll(params int[] ids)
|
||||
{
|
||||
return ids.Length > 0 ? ids.Select(Get) : GetAllNoIds();
|
||||
|
||||
+2
-2
@@ -60,14 +60,14 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
var urlHash = url.GenerateHash<SHA1>();
|
||||
Sql<ISqlContext> sql = GetBaseQuery(false)
|
||||
.Where<RedirectUrlDto>(x => x.Url == url && x.UrlHash == urlHash &&
|
||||
(x.Culture == culture.ToLower() || x.Culture == string.Empty))
|
||||
(x.Culture == culture.ToLower() || x.Culture == null || x.Culture == string.Empty))
|
||||
.OrderByDescending<RedirectUrlDto>(x => x.CreateDateUtc);
|
||||
List<RedirectUrlDto> dtos = Database.Fetch<RedirectUrlDto>(sql);
|
||||
RedirectUrlDto dto = dtos.FirstOrDefault(f => f.Culture == culture.ToLower());
|
||||
|
||||
if (dto == null)
|
||||
{
|
||||
dto = dtos.FirstOrDefault(f => f.Culture == string.Empty);
|
||||
dto = dtos.FirstOrDefault(f => string.IsNullOrWhiteSpace(f.Culture));
|
||||
}
|
||||
|
||||
return dto == null ? null : Map(dto);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NPoco;
|
||||
using Umbraco.Cms.Core;
|
||||
@@ -171,6 +172,11 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
}
|
||||
|
||||
public IEnumerable<IUmbracoEntity> GetPagedParentEntitiesByChildId(int childId, long pageIndex, int pageSize, out long totalRecords, params Guid[] entityTypes)
|
||||
{
|
||||
return GetPagedParentEntitiesByChildId(childId, pageIndex, pageSize, out totalRecords, new int[0], entityTypes);
|
||||
}
|
||||
|
||||
public IEnumerable<IUmbracoEntity> GetPagedParentEntitiesByChildId(int childId, long pageIndex, int pageSize, out long totalRecords, int[] relationTypes, params Guid[] entityTypes)
|
||||
{
|
||||
// var contentObjectTypes = new[] { Constants.ObjectTypes.Document, Constants.ObjectTypes.Media, Constants.ObjectTypes.Member }
|
||||
// we could pass in the contentObjectTypes so that the entity repository sql is configured to do full entity lookups so that we get the full data
|
||||
@@ -184,10 +190,20 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
|
||||
sql.Where<RelationDto>(rel => rel.ChildId == childId);
|
||||
sql.Where<RelationDto, NodeDto>((rel, node) => rel.ParentId == childId || node.NodeId != childId);
|
||||
|
||||
if (relationTypes != null && relationTypes.Any())
|
||||
{
|
||||
sql.WhereIn<RelationDto>(rel => rel.RelationType, relationTypes);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public IEnumerable<IUmbracoEntity> GetPagedChildEntitiesByParentId(int parentId, long pageIndex, int pageSize, out long totalRecords, params Guid[] entityTypes)
|
||||
{
|
||||
return GetPagedChildEntitiesByParentId(parentId, pageIndex, pageSize, out totalRecords, new int[0], entityTypes);
|
||||
}
|
||||
|
||||
public IEnumerable<IUmbracoEntity> GetPagedChildEntitiesByParentId(int parentId, long pageIndex, int pageSize, out long totalRecords, int[] relationTypes, params Guid[] entityTypes)
|
||||
{
|
||||
// var contentObjectTypes = new[] { Constants.ObjectTypes.Document, Constants.ObjectTypes.Media, Constants.ObjectTypes.Member }
|
||||
// we could pass in the contentObjectTypes so that the entity repository sql is configured to do full entity lookups so that we get the full data
|
||||
@@ -201,6 +217,11 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
|
||||
sql.Where<RelationDto>(rel => rel.ParentId == parentId);
|
||||
sql.Where<RelationDto, NodeDto>((rel, node) => rel.ChildId == parentId || node.NodeId != parentId);
|
||||
|
||||
if (relationTypes != null && relationTypes.Any())
|
||||
{
|
||||
sql.WhereIn<RelationDto>(rel => rel.RelationType, relationTypes);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -399,4 +420,40 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement
|
||||
sql.OrderByDescending(orderBy);
|
||||
}
|
||||
}
|
||||
|
||||
internal class RelationItemDto
|
||||
{
|
||||
[Column(Name = "nodeId")]
|
||||
public int ChildNodeId { get; set; }
|
||||
|
||||
[Column(Name = "nodeKey")]
|
||||
public Guid ChildNodeKey { get; set; }
|
||||
|
||||
[Column(Name = "nodeName")]
|
||||
public string ChildNodeName { get; set; }
|
||||
|
||||
[Column(Name = "nodeObjectType")]
|
||||
public Guid ChildNodeObjectType { get; set; }
|
||||
|
||||
[Column(Name = "contentTypeIcon")]
|
||||
public string ChildContentTypeIcon { get; set; }
|
||||
|
||||
[Column(Name = "contentTypeAlias")]
|
||||
public string ChildContentTypeAlias { get; set; }
|
||||
|
||||
[Column(Name = "contentTypeName")]
|
||||
public string ChildContentTypeName { get; set; }
|
||||
|
||||
[Column(Name = "relationTypeName")]
|
||||
public string RelationTypeName { get; set; }
|
||||
|
||||
[Column(Name = "relationTypeAlias")]
|
||||
public string RelationTypeAlias { get; set; }
|
||||
|
||||
[Column(Name = "relationTypeIsDependency")]
|
||||
public bool RelationTypeIsDependency { get; set; }
|
||||
|
||||
[Column(Name = "relationTypeIsBidirectional")]
|
||||
public bool RelationTypeIsBidirectional { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user