Merge remote-tracking branch 'origin/v10/10.0' into v10/contrib
This commit is contained in:
95
.gitignore
vendored
95
.gitignore
vendored
@@ -37,74 +37,69 @@ _NCrunch_*/
|
||||
tools/NDepend/
|
||||
[Tt]est[Rr]esult*
|
||||
[Bb]uild[Ll]og.*
|
||||
[sS]ource
|
||||
[sS]andbox
|
||||
[Ss]ource
|
||||
[Ss]andbox
|
||||
node_modules
|
||||
lib-bower
|
||||
*.psess
|
||||
*.vspx
|
||||
NDependOut/*
|
||||
NDependOut/
|
||||
QueryResult.htm
|
||||
tools/docfx/*
|
||||
tools/docfx/
|
||||
|
||||
# Ignore rule for clearing out Belle (avoid rebuilding all the time)
|
||||
preserve.belle
|
||||
|
||||
# Ignore rule for output of generated documentation files from grunt docserve
|
||||
src/Umbraco.Web.UI.Docs/api
|
||||
src/Umbraco.Web.UI.Docs/package-lock.json
|
||||
/src/Umbraco.Web.UI.Docs/api/
|
||||
/src/Umbraco.Web.UI.Docs/package-lock.json
|
||||
|
||||
# Build
|
||||
build.out/
|
||||
build.tmp/
|
||||
build/hooks/
|
||||
build/temp/
|
||||
/build.out/
|
||||
/build.tmp/
|
||||
/build/hooks/
|
||||
/build/temp/
|
||||
|
||||
# Build output
|
||||
build/docs.zip
|
||||
build/ui-docs.zip
|
||||
build/csharp-docs.zip
|
||||
build/ApiDocs/*
|
||||
build/ApiDocs/Output/*
|
||||
src/ApiDocs/api/*
|
||||
/build/docs.zip
|
||||
/build/ui-docs.zip
|
||||
/build/csharp-docs.zip
|
||||
/build/ApiDocs/
|
||||
/src/ApiDocs/api/
|
||||
/src/Umbraco.Cms.StaticAssets/wwwroot/umbraco/
|
||||
|
||||
# Environment specific data
|
||||
src/Umbraco.Web.UI.Client/[Bb]uild/*
|
||||
src/Umbraco.Web.UI.Client/[Bb]uild/[Bb]elle/
|
||||
src/Umbraco.Web.UI.Client/src/[Ll]ess/*.css
|
||||
src/Umbraco.Web.UI.Client/TESTS-*.xml
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Dd]ata/*
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Ll]ogs
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Mm]odels/*
|
||||
src/Umbraco.Web.UI/appsettings.Development.json
|
||||
src/Umbraco.Web.UI/appsettings.json
|
||||
src/Umbraco.Web.UI/appsettings.Local.json
|
||||
src/Umbraco.Web.UI/wwwroot/[Uu]mbraco/assets/*
|
||||
src/Umbraco.Web.UI/wwwroot/[Uu]mbraco/js/*
|
||||
src/Umbraco.Web.UI/wwwroot/[Uu]mbraco/lib/*
|
||||
src/Umbraco.Web.UI/wwwroot/[Uu]mbraco/views/*
|
||||
src/Umbraco.Web.UI/wwwroot/Media/*
|
||||
src/Umbraco.Web.UI/Smidge/
|
||||
src/Umbraco.Web.UI/App_Code/
|
||||
src/Umbraco.Web.UI/App_Plugins/
|
||||
src/Umbraco.Web.UI/Views/
|
||||
!src/Umbraco.Web.UI/Views/Partials/blocklist/
|
||||
!src/Umbraco.Web.UI/Views/Partials/grid/
|
||||
!src/Umbraco.Web.UI/Views/_ViewImports.cshtml
|
||||
/src/Umbraco.Web.UI.Client/[Bb]uild/
|
||||
/src/Umbraco.Web.UI.Client/[Bb]uild/[Bb]elle/
|
||||
/src/Umbraco.Web.UI.Client/src/[Ll]ess/*.css
|
||||
/src/Umbraco.Web.UI.Client/TESTS-*.xml
|
||||
/src/Umbraco.Web.UI/wwwroot/[Mm]edia/
|
||||
/src/Umbraco.Web.UI/App_Code/
|
||||
/src/Umbraco.Web.UI/App_Plugins/
|
||||
/src/Umbraco.Web.UI/[Uu]mbraco/[Dd]ata/
|
||||
/src/Umbraco.Web.UI/[Uu]mbraco/[Ll]ogs/
|
||||
/src/Umbraco.Web.UI/[Uu]mbraco/[Mm]odels/
|
||||
/src/Umbraco.Web.UI/Views/
|
||||
!/src/Umbraco.Web.UI/Views/Partials/blocklist/
|
||||
!/src/Umbraco.Web.UI/Views/Partials/grid/
|
||||
!/src/Umbraco.Web.UI/Views/_ViewImports.cshtml
|
||||
/src/Umbraco.Web.UI/appsettings.json
|
||||
/src/Umbraco.Web.UI/appsettings.Development.json
|
||||
/src/Umbraco.Web.UI/appsettings.Local.json
|
||||
|
||||
# Tests
|
||||
cypress.env.json
|
||||
tests/Umbraco.Tests.AcceptanceTest/cypress/screenshots/
|
||||
tests/Umbraco.Tests.AcceptanceTest/cypress/support/chainable.ts
|
||||
tests/Umbraco.Tests.AcceptanceTest/cypress/videos/
|
||||
tests/Umbraco.Tests.Integration.SqlCe/DatabaseContextTests.sdf
|
||||
tests/Umbraco.Tests.Integration.SqlCe/umbraco/Data/TEMP/
|
||||
tests/Umbraco.Tests.Integration/appsettings.Tests.Local.json
|
||||
tests/Umbraco.Tests.Integration/TEMP/*
|
||||
tests/Umbraco.Tests.Integration/umbraco/Data/
|
||||
tests/Umbraco.Tests.Integration/umbraco/logs/
|
||||
tests/Umbraco.Tests.Integration/Views/
|
||||
tests/Umbraco.Tests.UnitTests/umbraco/Data/TEMP/
|
||||
/tests/Umbraco.Tests.AcceptanceTest/cypress/screenshots/
|
||||
/tests/Umbraco.Tests.AcceptanceTest/cypress/support/chainable.ts
|
||||
/tests/Umbraco.Tests.AcceptanceTest/cypress/videos/
|
||||
/tests/Umbraco.Tests.Integration.SqlCe/DatabaseContextTests.sdf
|
||||
/tests/Umbraco.Tests.Integration.SqlCe/[Uu]mbraco/[Dd]ata/TEMP/
|
||||
/tests/Umbraco.Tests.Integration/appsettings.Tests.Local.json
|
||||
/tests/Umbraco.Tests.Integration/TEMP/
|
||||
/tests/Umbraco.Tests.Integration/[Uu]mbraco/[Dd]ata/
|
||||
/tests/Umbraco.Tests.Integration/[Uu]mbraco/[Ll]ogs/
|
||||
/tests/Umbraco.Tests.Integration/Views/
|
||||
/tests/Umbraco.Tests.UnitTests/[Uu]mbraco/[Dd]ata/TEMP/
|
||||
|
||||
# Ignore auto-generated schema
|
||||
src/Umbraco.Web.UI/umbraco/config/appsettings-schema.json
|
||||
/src/Umbraco.Web.UI/[Uu]mbraco/config/appsettings-schema.json
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata minClientVersion="4.1.0">
|
||||
<id>Umbraco.Cms.StaticAssets</id>
|
||||
<version>9.0.0</version>
|
||||
<title>Umbraco Cms Static Assets</title>
|
||||
<authors>Umbraco HQ</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
<license type="expression">MIT</license>
|
||||
<projectUrl>https://umbraco.com/</projectUrl>
|
||||
<iconUrl>https://umbraco.com/dist/nuget/logo-small.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Contains the static assets that is required to run Umbraco CMS.</description>
|
||||
<summary>Contains the static assets that is required to run Umbraco CMS.</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<repository type="git" url="https://github.com/umbraco/umbraco-cms" />
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<!-- Content -->
|
||||
<file src="$BuildTmp$\WebApp\wwwroot\umbraco\**\*.*" target="content\wwwroot\umbraco" />
|
||||
<file src="$BuildTmp$\WebApp\umbraco\**\*.*" target="content\umbraco" />
|
||||
|
||||
<!-- UmbracoCms props and targets used to copy the content into the solution -->
|
||||
<file src="buildTransitive\**" target="buildTransitive\" />
|
||||
</files>
|
||||
</package>
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata minClientVersion="4.1.0">
|
||||
<id>Umbraco.Cms</id>
|
||||
<version>9.0.0</version>
|
||||
<version>10.0.0</version>
|
||||
<title>Umbraco Cms</title>
|
||||
<authors>Umbraco HQ</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
@@ -24,12 +24,8 @@
|
||||
<dependency id="Umbraco.Cms.Persistence.Sqlite" version="[$version$]" />
|
||||
</group>
|
||||
</dependencies>
|
||||
<!--
|
||||
We can't use content files, as the files need to be copied into the solution, links/shortcuts to the files
|
||||
are not good enough
|
||||
-->
|
||||
<contentFiles />
|
||||
</metadata>
|
||||
<files>
|
||||
</files>
|
||||
<files>
|
||||
<file src="buildTransitive\Umbraco.Cms.props" target="buildTransitive" />
|
||||
</files>
|
||||
</package>
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<PropertyGroup>
|
||||
<ContentFilesPath>$(MSBuildThisFileDirectory)..\content\umbraco\**\*.*</ContentFilesPath>
|
||||
<ContentWwwrootFilesPath>$(MSBuildThisFileDirectory)..\content\wwwroot\umbraco\**\*.*</ContentWwwrootFilesPath>
|
||||
<UmbracoWwwrootName Condition="'$(UmbracoWwwrootName)' == ''">umbraco</UmbracoWwwrootName>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="CopyUmbracoAssets" BeforeTargets="BeforeBuild">
|
||||
<ItemGroup>
|
||||
<ContentFiles Include="$(ContentFilesPath)" />
|
||||
<ContentWwwrootFiles Include="$(ContentWwwrootFilesPath)" />
|
||||
</ItemGroup>
|
||||
<Message Text="Copying Umbraco content files: $(ContentFilesPath) - #@(ContentFiles->Count()) files" Importance="high" />
|
||||
<Message Text="Copying Umbraco wwwroot content files: $(ContentWwwrootFilesPath) - #@(ContentWwwrootFiles->Count()) files" Importance="high" />
|
||||
<Copy
|
||||
SourceFiles="@(ContentFiles)"
|
||||
DestinationFiles="@(ContentFiles->'$(MSBuildProjectDirectory)\umbraco\%(RecursiveDir)%(Filename)%(Extension)')"
|
||||
SkipUnchangedFiles="true" />
|
||||
<Copy
|
||||
SourceFiles="@(ContentWwwrootFiles)"
|
||||
DestinationFiles="@(ContentWwwrootFiles->'$(MSBuildProjectDirectory)\wwwroot\$(UmbracoWwwrootName)\%(RecursiveDir)%(Filename)%(Extension)')"
|
||||
SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
|
||||
<Target Name="IncludeAppPluginsContent" BeforeTargets="GetCopyToOutputDirectoryItems;GetCopyToPublishDirectoryItems;">
|
||||
<ItemGroup>
|
||||
<_AppPluginsFiles Include="App_Plugins\**" />
|
||||
|
||||
<ContentWithTargetPath
|
||||
Include="@(_AppPluginsFiles)"
|
||||
Exclude="@(ContentWithTargetPath)"
|
||||
TargetPath="%(Identity)"
|
||||
CopyToOutputDirectory="PreserveNewest"
|
||||
CopyToPublishDirectory="PreserveNewest"/>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
The set of files to publish is generated really early and doesn't currently account for files added by targets e.g. BeforeBuild.
|
||||
A fix was put in place in Web SDK to update for wwwwroot in case someone runs npm build etc in a target, we're borrowing their trick.
|
||||
https://github.com/dotnet/sdk/blob/e2b2b1a4ac56c955b84d62fe71cda3b6f258b42b/src/WebSdk/Publish/Targets/ComputeTargets/Microsoft.NET.Sdk.Publish.ComputeFiles.targets
|
||||
-->
|
||||
<Target Name="IncludeUmbracoFolderContent" BeforeTargets="GetCopyToOutputDirectoryItems;GetCopyToPublishDirectoryItems;">
|
||||
<ItemGroup>
|
||||
<_UmbracoFolderFiles Include="umbraco\config\**" />
|
||||
<_UmbracoFolderFiles Include="umbraco\PartialViewMacros\**" />
|
||||
<_UmbracoFolderFiles Include="umbraco\UmbracoBackOffice\**" />
|
||||
<_UmbracoFolderFiles Include="umbraco\UmbracoInstall\**" />
|
||||
<_UmbracoFolderFiles Include="umbraco\UmbracoWebsite\**" />
|
||||
<_UmbracoFolderFiles Include="umbraco\UmbracoWebsite\**" />
|
||||
<_UmbracoFolderFiles Include="umbraco\Licenses\**" />
|
||||
|
||||
<!-- This could be handled in deploy if it's not already -->
|
||||
<_UmbracoFolderFiles Include="umbraco\Deploy\**" />
|
||||
|
||||
<ContentWithTargetPath
|
||||
Include="@(_UmbracoFolderFiles)"
|
||||
Exclude="@(ContentWithTargetPath)"
|
||||
TargetPath="%(Identity)"
|
||||
CopyToOutputDirectory="PreserveNewest"
|
||||
CopyToPublishDirectory="PreserveNewest"/>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
<Target Name="ClearUmbracoAssets" BeforeTargets="Clean">
|
||||
<ItemGroup>
|
||||
<UmbracoConfigPackageDir Include="$(MSBuildProjectDirectory)\umbraco\config\" />
|
||||
<UmbracoPartialViewMacrosPackageDir Include="$(MSBuildProjectDirectory)\umbraco\PartialViewMacros\" />
|
||||
<UmbracoUmbracoBackOfficeMacrosDir Include="$(MSBuildProjectDirectory)\umbraco\UmbracoBackOffice\" />
|
||||
<UmbracoUmbracoInstallDir Include="$(MSBuildProjectDirectory)\umbraco\UmbracoInstall\" />
|
||||
<UmbracoUmbracoWebsiteMacrosDir Include="$(MSBuildProjectDirectory)\umbraco\UmbracoWebsite\" />
|
||||
<WwwrootUmbracoPackageDir Include="$(MSBuildProjectDirectory)\wwwroot\$(UmbracoWwwrootName)\" />
|
||||
</ItemGroup>
|
||||
<Message Text="Clear old umbraco data" Importance="high" />
|
||||
<RemoveDir Directories="@(UmbracoConfigPackageDir)" />
|
||||
<RemoveDir Directories="@(UmbracoPartialViewMacrosPackageDir)" />
|
||||
<RemoveDir Directories="@(UmbracoUmbracoBackOfficeMacrosDir)" />
|
||||
<RemoveDir Directories="@(UmbracoUmbracoInstallDir)" />
|
||||
<RemoveDir Directories="@(UmbracoUmbracoWebsiteMacrosDir)" />
|
||||
<RemoveDir Directories="@(WwwrootUmbracoPackageDir)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="IncludeUmbracoRazorFiles" BeforeTargets="ResolveRazorGenerateInputs">
|
||||
<ItemGroup>
|
||||
<Content Include="$(MSBuildProjectDirectory)\umbraco\**\*.cshtml" Exclude="@(Content)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
@@ -271,7 +271,7 @@ stages:
|
||||
gulpFile: src\Umbraco.Web.UI.Client\gulpfile.js
|
||||
targets: build
|
||||
workingDirectory: src\Umbraco.Web.UI.Client
|
||||
- powershell: Start-Process -FilePath "dotnet" -ArgumentList "run", "-p", "src\Umbraco.Web.UI\Umbraco.Web.UI.csproj"
|
||||
- powershell: Start-Process -FilePath "dotnet" -ArgumentList "run", "-p", "src\Umbraco.Web.UI\Umbraco.Web.UI.csproj /Umbraco:CMS:Global:Id=0000000-0000-0000-0000-000000000042"
|
||||
displayName: dotnet run
|
||||
# - powershell: dotnet run --no-build -p .\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj
|
||||
# displayName: dotnet run
|
||||
@@ -375,7 +375,7 @@ stages:
|
||||
displayName: dotnet run
|
||||
inputs:
|
||||
targetType: 'inline'
|
||||
script: 'nohup dotnet run --no-build -p ./src/Umbraco.Web.UI/ > $(Build.ArtifactStagingDirectory)/dotnet_run_log_linux.txt &'
|
||||
script: 'nohup dotnet run --no-build -p ./src/Umbraco.Web.UI/ /Umbraco:CMS:Global:Id=0000000-0000-0000-0000-000000000042 > $(Build.ArtifactStagingDirectory)/dotnet_run_log_linux.txt &'
|
||||
- task: Bash@3
|
||||
displayName: Generate Cypress.env.json
|
||||
inputs:
|
||||
|
||||
@@ -192,7 +192,6 @@
|
||||
$this.RemoveFile($excludeFiles)
|
||||
|
||||
# copy rest of the files into WebApp
|
||||
$this.CopyFiles("$($this.SolutionRoot)\src\Umbraco.Web.UI\umbraco", "*", "$($this.BuildTemp)\WebApp\umbraco")
|
||||
$excludeUmbracoDirs = @("$($this.BuildTemp)\WebApp\umbraco\lib","$($this.BuildTemp)\WebApp\umbraco\Data","$($this.BuildTemp)\WebApp\umbraco\Logs")
|
||||
$this.RemoveDirectory($excludeUmbracoDirs)
|
||||
$this.CopyFiles("$($this.SolutionRoot)\src\Umbraco.Web.UI\Views", "*", "$($this.BuildTemp)\WebApp\Views")
|
||||
@@ -301,13 +300,6 @@
|
||||
$_.CreationTime = $_.CreationTime.AddHours(-11)
|
||||
$_.LastWriteTime = $_.LastWriteTime.AddHours(-11)
|
||||
}
|
||||
|
||||
# copy Belle
|
||||
Write-Host "Copy Belle"
|
||||
$this.CopyFiles("$src\Umbraco.Web.UI\wwwroot\umbraco\assets", "*", "$tmp\WebApp\wwwroot\umbraco\assets")
|
||||
$this.CopyFiles("$src\Umbraco.Web.UI\wwwroot\umbraco\js", "*", "$tmp\WebApp\wwwroot\umbraco\js")
|
||||
$this.CopyFiles("$src\Umbraco.Web.UI\wwwroot\umbraco\lib", "*", "$tmp\WebApp\wwwroot\umbraco\lib")
|
||||
$this.CopyFiles("$src\Umbraco.Web.UI\wwwroot\umbraco\views", "*", "$tmp\WebApp\wwwroot\umbraco\views")
|
||||
})
|
||||
|
||||
|
||||
@@ -365,12 +357,6 @@
|
||||
-Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cms.log"
|
||||
if (-not $?) { throw "Failed to pack NuGet UmbracoCms." }
|
||||
|
||||
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.StaticAssets.nuspec" `
|
||||
-Properties BuildTmp="$($this.BuildTemp)" `
|
||||
-Version "$($this.Version.Semver.ToString())" `
|
||||
-Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmsstaticassets.log"
|
||||
if (-not $?) { throw "Failed to pack NuGet UmbracoCms.StaticAssets." }
|
||||
|
||||
&$this.BuildEnv.NuGet Pack "$templates\Umbraco.Templates.nuspec" `
|
||||
-Properties BuildTmp="$($this.BuildTemp)" `
|
||||
-Version "$($this.Version.Semver.ToString())" `
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<PropertyGroup>
|
||||
<Version>10.0.0</Version>
|
||||
<AssemblyVersion>10.0.0</AssemblyVersion>
|
||||
<InformationalVersion>10.0.0-rc</InformationalVersion>
|
||||
<InformationalVersion>10.0.0-rc1</InformationalVersion>
|
||||
<FileVersion>10.0.0</FileVersion>
|
||||
<LangVersion Condition="'$(LangVersion)' == ''">10.0</LangVersion>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
@@ -19,6 +19,9 @@
|
||||
<PackageTags>umbraco</PackageTags>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/umbraco/umbraco-cms</RepositoryUrl>
|
||||
<Nullable>enable</Nullable>
|
||||
<WarningsAsErrors>Nullable</WarningsAsErrors>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace JsonSchema
|
||||
/// <summary>
|
||||
/// Gets or sets the Umbraco
|
||||
/// </summary>
|
||||
public UmbracoDefinition Umbraco { get; set; }
|
||||
public UmbracoDefinition? Umbraco { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configuration of Umbraco CMS and packages
|
||||
@@ -24,76 +24,76 @@ namespace JsonSchema
|
||||
internal class UmbracoDefinition
|
||||
{
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public CmsDefinition CMS { get; set; }
|
||||
public CmsDefinition? CMS { get; set; }
|
||||
|
||||
public FormsDefinition Forms { get; set; }
|
||||
public FormsDefinition? Forms { get; set; }
|
||||
|
||||
public DeployDefinition Deploy { get; set; }
|
||||
public DeployDefinition? Deploy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configurations for the Umbraco CMS
|
||||
/// </summary>
|
||||
public class CmsDefinition
|
||||
{
|
||||
public ActiveDirectorySettings ActiveDirectory { get; set; }
|
||||
public ActiveDirectorySettings? ActiveDirectory { get; set; }
|
||||
|
||||
public ContentSettings Content { get; set; }
|
||||
public ContentSettings? Content { get; set; }
|
||||
|
||||
public ExceptionFilterSettings ExceptionFilter { get; set; }
|
||||
public ExceptionFilterSettings? ExceptionFilter { get; set; }
|
||||
|
||||
public ModelsBuilderSettings ModelsBuilder { get; set; }
|
||||
public ModelsBuilderSettings? ModelsBuilder { get; set; }
|
||||
|
||||
public GlobalSettings Global { get; set; }
|
||||
public GlobalSettings? Global { get; set; }
|
||||
|
||||
public HealthChecksSettings HealthChecks { get; set; }
|
||||
public HealthChecksSettings? HealthChecks { get; set; }
|
||||
|
||||
public HostingSettings Hosting { get; set; }
|
||||
public HostingSettings? Hosting { get; set; }
|
||||
|
||||
public ImagingSettings Imaging { get; set; }
|
||||
public ImagingSettings? Imaging { get; set; }
|
||||
|
||||
public IndexCreatorSettings Examine { get; set; }
|
||||
public IndexCreatorSettings? Examine { get; set; }
|
||||
|
||||
public KeepAliveSettings KeepAlive { get; set; }
|
||||
public KeepAliveSettings? KeepAlive { get; set; }
|
||||
|
||||
public LoggingSettings Logging { get; set; }
|
||||
public LoggingSettings? Logging { get; set; }
|
||||
|
||||
public MemberPasswordConfigurationSettings MemberPassword { get; set; }
|
||||
public MemberPasswordConfigurationSettings? MemberPassword { get; set; }
|
||||
|
||||
public NuCacheSettings NuCache { get; set; }
|
||||
public NuCacheSettings? NuCache { get; set; }
|
||||
|
||||
public RequestHandlerSettings RequestHandler { get; set; }
|
||||
public RequestHandlerSettings? RequestHandler { get; set; }
|
||||
|
||||
public RuntimeSettings Runtime { get; set; }
|
||||
public RuntimeSettings? Runtime { get; set; }
|
||||
|
||||
public SecuritySettings Security { get; set; }
|
||||
public SecuritySettings? Security { get; set; }
|
||||
|
||||
public TourSettings Tours { get; set; }
|
||||
public TourSettings? Tours { get; set; }
|
||||
|
||||
public TypeFinderSettings TypeFinder { get; set; }
|
||||
public TypeFinderSettings? TypeFinder { get; set; }
|
||||
|
||||
public UserPasswordConfigurationSettings UserPassword { get; set; }
|
||||
public UserPasswordConfigurationSettings? UserPassword { get; set; }
|
||||
|
||||
public WebRoutingSettings WebRouting { get; set; }
|
||||
public WebRoutingSettings? WebRouting { get; set; }
|
||||
|
||||
public UmbracoPluginSettings Plugins { get; set; }
|
||||
public UmbracoPluginSettings? Plugins { get; set; }
|
||||
|
||||
public UnattendedSettings Unattended { get; set; }
|
||||
public UnattendedSettings? Unattended { get; set; }
|
||||
|
||||
public RichTextEditorSettings RichTextEditor { get; set; }
|
||||
public RichTextEditorSettings? RichTextEditor { get; set; }
|
||||
|
||||
public RuntimeMinificationSettings RuntimeMinification { get; set; }
|
||||
public RuntimeMinificationSettings? RuntimeMinification { get; set; }
|
||||
|
||||
public BasicAuthSettings BasicAuth { get; set; }
|
||||
public BasicAuthSettings? BasicAuth { get; set; }
|
||||
|
||||
public PackageMigrationSettings PackageMigration { get; set; }
|
||||
public PackageMigrationSettings? PackageMigration { get; set; }
|
||||
|
||||
public LegacyPasswordMigrationSettings LegacyPasswordMigration { get; set; }
|
||||
public LegacyPasswordMigrationSettings? LegacyPasswordMigration { get; set; }
|
||||
|
||||
public ContentDashboardSettings ContentDashboard { get; set; }
|
||||
public ContentDashboardSettings? ContentDashboard { get; set; }
|
||||
|
||||
public HelpPageSettings HelpPage { get; set; }
|
||||
public HelpPageSettings? HelpPage { get; set; }
|
||||
|
||||
public InstallDefaultDataSettings DefaultDataCreation { get; set; }
|
||||
public InstallDefaultDataSettings? DefaultDataCreation { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -101,24 +101,24 @@ namespace JsonSchema
|
||||
/// </summary>
|
||||
public class FormsDefinition
|
||||
{
|
||||
public FormDesignSettings FormDesign { get; set; }
|
||||
public FormDesignSettings? FormDesign { get; set; }
|
||||
|
||||
public PackageOptionSettings Options { get; set; }
|
||||
public PackageOptionSettings? Options { get; set; }
|
||||
|
||||
public Umbraco.Forms.Core.Configuration.SecuritySettings Security { get; set; }
|
||||
public Umbraco.Forms.Core.Configuration.SecuritySettings? Security { get; set; }
|
||||
|
||||
public FieldTypesDefinition FieldTypes { get; set; }
|
||||
public FieldTypesDefinition? FieldTypes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configurations for the Umbraco Forms Field Types
|
||||
/// </summary>
|
||||
public class FieldTypesDefinition
|
||||
{
|
||||
public DatePickerSettings DatePicker { get; set; }
|
||||
public DatePickerSettings? DatePicker { get; set; }
|
||||
|
||||
public Recaptcha2Settings Recaptcha2 { get; set; }
|
||||
public Recaptcha2Settings? Recaptcha2 { get; set; }
|
||||
|
||||
public Recaptcha3Settings Recaptcha3 { get; set; }
|
||||
public Recaptcha3Settings? Recaptcha3 { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,11 +127,11 @@ namespace JsonSchema
|
||||
/// </summary>
|
||||
public class DeployDefinition
|
||||
{
|
||||
public DeploySettings Settings { get; set; }
|
||||
public DeploySettings? Settings { get; set; }
|
||||
|
||||
public DeployProjectConfig Project { get; set; }
|
||||
public DeployProjectConfig? Project { get; set; }
|
||||
|
||||
public DebugSettings Debug { get; set; }
|
||||
public DebugSettings? Debug { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@ namespace JsonSchema
|
||||
{
|
||||
internal class NamespacePrefixedSchemaNameGenerator : DefaultSchemaNameGenerator
|
||||
{
|
||||
public override string Generate(Type type) => type.Namespace.Replace(".", string.Empty) + base.Generate(type);
|
||||
public override string Generate(Type type) => type.Namespace?.Replace(".", string.Empty) + base.Generate(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@ namespace JsonSchema
|
||||
internal class Options
|
||||
{
|
||||
[Option('o', "outputFile", Required = false, HelpText = "Set path of the output file.", Default = "../../../../Umbraco.Web.UI/umbraco/config/appsettings-schema.json")]
|
||||
public string OutputFile { get; set; }
|
||||
public string OutputFile { get; set; } = null!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace JsonSchema
|
||||
|
||||
var path = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, options.OutputFile));
|
||||
Console.WriteLine("Path to use {0}", path);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
|
||||
Console.WriteLine("Ensured directory exists");
|
||||
await File.WriteAllTextAsync(path, schema);
|
||||
|
||||
|
||||
@@ -43,14 +43,14 @@ namespace JsonSchema
|
||||
|
||||
var result = await response.Content.ReadAsStringAsync();
|
||||
|
||||
return JsonConvert.DeserializeObject<JObject>(result);
|
||||
return JsonConvert.DeserializeObject<JObject>(result)!;
|
||||
}
|
||||
|
||||
private JObject GenerateUmbracoSchema()
|
||||
{
|
||||
NJsonSchema.JsonSchema schema = _innerGenerator.Generate(typeof(AppSettings));
|
||||
|
||||
return JsonConvert.DeserializeObject<JObject>(schema.ToJson());
|
||||
return JsonConvert.DeserializeObject<JObject>(schema.ToJson())!;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<PackageId>Umbraco.Cms.Persistence.SqlServer</PackageId>
|
||||
<Title>Umbraco.Cms.Persistence.SqlServer</Title>
|
||||
<Description>Adds support for SQL Server to Umbraco CMS.</Description>
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<PackageId>Umbraco.Cms.Persistence.Sqlite</PackageId>
|
||||
<Title>Umbraco.Cms.Persistence.Sqlite</Title>
|
||||
<Description>Adds support for SQLite to Umbraco CMS.</Description>
|
||||
|
||||
83
src/Umbraco.Cms.StaticAssets/Umbraco.Cms.StaticAssets.csproj
Normal file
83
src/Umbraco.Cms.StaticAssets/Umbraco.Cms.StaticAssets.csproj
Normal file
@@ -0,0 +1,83 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
|
||||
<PackageId>Umbraco.Cms.StaticAssets</PackageId>
|
||||
<Description>Contains the static assets that is required to run Umbraco CMS.</Description>
|
||||
<StaticWebAssetBasePath>/</StaticWebAssetBasePath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="buildTransitive\**\*.*">
|
||||
<Pack>true</Pack>
|
||||
<PackagePath>buildTransitive</PackagePath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Umbraco.Web.BackOffice\Umbraco.Web.BackOffice.csproj" PrivateAssets="All" />
|
||||
<ProjectReference Include="..\Umbraco.Web.Website\Umbraco.Web.Website.csproj" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<BellePath>$(ProjectDir)wwwroot/umbraco</BellePath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="CheckPreconditions" BeforeTargets="Build">
|
||||
<Message Text="-CheckPreconditions-" Importance="high" />
|
||||
<Message Text="BellePath: $(BellePath)" Importance="high" />
|
||||
|
||||
<!-- Build Belle, if building is Visual Studio and the build folder does not exist yet -->
|
||||
<Message Text="Skip Belle because UmbracoBuild is '$(UmbracoBuild)' (this is not Visual Studio)." Importance="High" Condition="'$(UmbracoBuild)' != ''" />
|
||||
<Message Text="Skip Belle because $(BellePath) exists." Importance="High" Condition="Exists('$(BellePath)')" />
|
||||
<Message Text="Build Belle because UmbracoBuild is empty (this is Visual Studio), and $(BellePath) does not exist." Importance="High" Condition="!Exists('$(BellePath)') and '$(UmbracoBuild)' == ''" />
|
||||
<CallTarget Targets="BelleBuild" Condition="!Exists('$(BellePath)') and '$(UmbracoBuild)' == ''" />
|
||||
<Message Text="Skip JsonSchema generation because $(JsonSchemaPath) exists." Importance="High" Condition="Exists('$(JsonSchemaPath)')" />
|
||||
<Message Text="Generate the appsettings json schema." Importance="High" Condition="!Exists('$(JsonSchemaPath)') and '$(UmbracoBuild)' == ''" />
|
||||
</Target>
|
||||
|
||||
|
||||
<Target Name="BelleBuild">
|
||||
<Exec WorkingDirectory="$(ProjectDir)/../Umbraco.Web.UI.Client/" Command="npm ci --no-fund --no-audit --prefer-offline" />
|
||||
<Exec WorkingDirectory="$(ProjectDir)/../Umbraco.Web.UI.Client/" Command="npm run build:skip-tests" />
|
||||
</Target>
|
||||
|
||||
<!-- Clean Belle when cleaning and rebuilding, but only in Visual Studio -->
|
||||
<Target Name="CleanPreconditions" AfterTargets="Clean" Condition="'$(UmbracoBuild)' == ''">
|
||||
<Message Text="-CleanPreconditions-" Importance="high" />
|
||||
<Message Text="Nothing to clean, as $(BellePath) does not exist." Importance="High" Condition="!Exists('$(BellePath)')" />
|
||||
<Message Text="Not cleaning (found src/preserve.belle)." Importance="High" Condition="Exists('$(BellePath)') and Exists('$(SolutionDir)preserve.belle')" />
|
||||
<Message Text="Remove $(BellePath)." Importance="High" Condition="Exists('$(BellePath)') and !Exists('$(SolutionDir)preserve.belle')" />
|
||||
<ItemGroup>
|
||||
<BelleLib Include="$(BellePath)" />
|
||||
</ItemGroup>
|
||||
<RemoveDir Directories="@(BelleLib)" Condition="Exists('$(BellePath)') and !Exists('$(SolutionDir)preserve.belle')" />
|
||||
<Message Text="Remove $(JsonSchemaPath)." Importance="High" Condition="Exists('$(JsonSchemaPath)') and !Exists('$(SolutionDir)preserve.jsonschema')" />
|
||||
<Delete Files="$(JsonSchemaPath)" Condition="Exists('$(JsonSchemaPath)') and !Exists('$(SolutionDir)preserve.jsonschema')" />
|
||||
</Target>
|
||||
|
||||
|
||||
<!--
|
||||
The set of files to publish is generated really early and doesn't currently account for files added by targets e.g. BeforeBuild.
|
||||
A fix was put in place in Web SDK to update for wwwwroot in case someone runs npm build etc in a target, we're borrowing their trick.
|
||||
https://github.com/dotnet/sdk/blob/e2b2b1a4ac56c955b84d62fe71cda3b6f258b42b/src/WebSdk/Publish/Targets/ComputeTargets/Microsoft.NET.Sdk.Publish.ComputeFiles.targets
|
||||
-->
|
||||
<Target Name="IncludeUmbracoFolderContent" BeforeTargets="GetCopyToOutputDirectoryItems;GetCopyToPublishDirectoryItems;">
|
||||
<ItemGroup>
|
||||
<_UmbracoFolderFiles Include="umbraco\config\**" />
|
||||
<_UmbracoFolderFiles Include="umbraco\PartialViewMacros\**" />
|
||||
<_UmbracoFolderFiles Include="umbraco\UmbracoBackOffice\**" />
|
||||
<_UmbracoFolderFiles Include="umbraco\UmbracoInstall\**" />
|
||||
<_UmbracoFolderFiles Include="umbraco\UmbracoWebsite\**" />
|
||||
<_UmbracoFolderFiles Include="umbraco\UmbracoWebsite\**" />
|
||||
<_UmbracoFolderFiles Include="umbraco\Licenses\**" />
|
||||
<ContentWithTargetPath Include="@(_UmbracoFolderFiles)" Exclude="@(ContentWithTargetPath)" TargetPath="%(Identity)" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
@@ -59,15 +59,15 @@
|
||||
<script type="text/javascript">
|
||||
document.angularReady = function (app) {
|
||||
|
||||
@await Html.AngularValueExternalLoginInfoScriptAsync(externalLogins, ViewData.GetExternalSignInProviderErrors())
|
||||
@Html.AngularValueResetPasswordCodeInfoScript(ViewData[ViewDataExtensions.TokenPasswordResetCode])
|
||||
@await Html.AngularValueExternalLoginInfoScriptAsync(externalLogins, ViewData.GetExternalSignInProviderErrors()!)
|
||||
@Html.AngularValueResetPasswordCodeInfoScript(ViewData[ViewDataExtensions.TokenPasswordResetCode]!)
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
@*And finally we can load in our angular app*@
|
||||
<script type="text/javascript" src="lib/lazyload-js/LazyLoad.min.js"></script>
|
||||
<script src="@Url.GetUrlWithCacheBust("Application", "BackOffice", null, hostingEnvironment, umbracoVersion, runtimeMinifier)"></script>
|
||||
<script src="@Url.GetUrlWithCacheBust("Application", "BackOffice", null!, hostingEnvironment, umbracoVersion, runtimeMinifier)"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -120,8 +120,8 @@
|
||||
|
||||
<script>
|
||||
document.angularReady = function(app) {
|
||||
@await Html.AngularValueExternalLoginInfoScriptAsync(externalLogins, ViewData.GetExternalSignInProviderErrors())
|
||||
@Html.AngularValueResetPasswordCodeInfoScript(ViewData[ViewDataExtensions.TokenPasswordResetCode])
|
||||
@await Html.AngularValueExternalLoginInfoScriptAsync(externalLogins, ViewData.GetExternalSignInProviderErrors()!)
|
||||
@Html.AngularValueResetPasswordCodeInfoScript(ViewData[ViewDataExtensions.TokenPasswordResetCode]!)
|
||||
@await Html.AngularValueTinyMceAssetsAsync(runtimeMinifier)
|
||||
//required for the noscript trick
|
||||
document.getElementById("mainwrapper").style.display = "inherit";
|
||||
@@ -129,7 +129,7 @@
|
||||
</script>
|
||||
|
||||
<script src="@WebPath.Combine(backOfficePath.TrimStart("~"), "/lib/lazyload-js/LazyLoad.min.js")"></script>
|
||||
<script src="@Url.GetUrlWithCacheBust("Application", "BackOffice", null, hostingEnvironment, umbracoVersion, runtimeMinifier)"></script>
|
||||
<script src="@Url.GetUrlWithCacheBust("Application", "BackOffice", null!, hostingEnvironment, umbracoVersion, runtimeMinifier)"></script>
|
||||
|
||||
@if (isDebug)
|
||||
{
|
||||
@@ -108,7 +108,7 @@
|
||||
@await Html.BareMinimumServerVariablesScriptAsync(BackOfficeServerVariables)
|
||||
|
||||
<script src="../lib/lazyload-js/LazyLoad.min.js"></script>
|
||||
<script src="@Url.GetUrlWithCacheBust("Application", "Preview", null, HostingEnvironment, UmbracoVersion, RuntimeMinifier)"></script>
|
||||
<script src="@Url.GetUrlWithCacheBust("Application", "Preview", null!, HostingEnvironment, UmbracoVersion, RuntimeMinifier)"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -69,7 +69,7 @@
|
||||
"installApiBaseUrl": "@ViewData.GetInstallApiBaseUrl()",
|
||||
"umbracoBaseUrl": "@ViewData.GetUmbracoBaseFolder()",
|
||||
"application": {
|
||||
version: "@ViewData.GetUmbracoVersion().Major"
|
||||
version: "@ViewData.GetUmbracoVersion()?.Major"
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -42,8 +42,8 @@
|
||||
@if (hostingEnvironment.IsDebugMode)
|
||||
{
|
||||
|
||||
var reason = (string)Context.Items["reason"];
|
||||
var message = (string)Context.Items["message"];
|
||||
var reason = (string?)Context.Items["reason"];
|
||||
var message = (string?)Context.Items["message"];
|
||||
|
||||
if (!reason.IsNullOrWhiteSpace())
|
||||
{
|
||||
@@ -42,9 +42,9 @@ namespace Umbraco.Cms.Core.Cache
|
||||
persistDeleted(entity);
|
||||
}
|
||||
|
||||
public TEntity[]? GetAll(TId[]? ids, Func<TId[]?, IEnumerable<TEntity>?> performGetAll)
|
||||
public TEntity[] GetAll(TId[]? ids, Func<TId[]?, IEnumerable<TEntity>?> performGetAll)
|
||||
{
|
||||
return performGetAll(ids)?.ToArray();
|
||||
return performGetAll(ids)?.ToArray() ?? Array.Empty<TEntity>();
|
||||
}
|
||||
|
||||
public void ClearAll()
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Collections
|
||||
namespace Umbraco.Cms.Core.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// Collection that can be both a queue and a stack.
|
||||
|
||||
@@ -29,8 +29,13 @@ namespace Umbraco.Cms.Core.Composing
|
||||
/// Based on a type we'll check if it is IEnumerable{T} (or similar) and if so we'll return a List{T}, this will also deal with array types and return List{T} for those too.
|
||||
/// If it cannot be done, null is returned.
|
||||
/// </summary>
|
||||
public static IList? CreateGenericEnumerableFromObject(object obj)
|
||||
public static IList? CreateGenericEnumerableFromObject(object? obj)
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var type = obj.GetType();
|
||||
|
||||
if (type.IsGenericType)
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Umbraco.Cms.Core.Composing
|
||||
private readonly Dictionary<CompositeTypeTypeKey, TypeList> _types = new ();
|
||||
private readonly object _locko = new ();
|
||||
|
||||
private IEnumerable<Assembly> _assemblies;
|
||||
private IEnumerable<Assembly>? _assemblies;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TypeLoader"/> class.
|
||||
@@ -121,11 +121,11 @@ namespace Umbraco.Cms.Core.Composing
|
||||
|
||||
// internal for tests
|
||||
[Obsolete("This will be removed in a future version.")]
|
||||
public Dictionary<(string, string), IEnumerable<string>> ReadCache() => null;
|
||||
public Dictionary<(string, string), IEnumerable<string>>? ReadCache() => null;
|
||||
|
||||
// internal for tests
|
||||
[Obsolete("This will be removed in a future version.")]
|
||||
public string GetTypesListFilePath() => null;
|
||||
public string? GetTypesListFilePath() => null;
|
||||
|
||||
// internal for tests
|
||||
[Obsolete("This will be removed in a future version.")]
|
||||
@@ -340,7 +340,7 @@ namespace Umbraco.Cms.Core.Composing
|
||||
// check if the TypeList already exists, if so return it, if not we'll create it
|
||||
var tobject = typeof(object); // CompositeTypeTypeKey does not support null values
|
||||
var listKey = new CompositeTypeTypeKey(baseType ?? tobject, attributeType ?? tobject);
|
||||
TypeList typeList = null;
|
||||
TypeList? typeList = null;
|
||||
|
||||
if (cache)
|
||||
{
|
||||
@@ -411,7 +411,7 @@ namespace Umbraco.Cms.Core.Composing
|
||||
/// </summary>
|
||||
public void Add(Type type)
|
||||
{
|
||||
if (BaseType.IsAssignableFrom(type) == false)
|
||||
if (BaseType?.IsAssignableFrom(type) == false)
|
||||
throw new ArgumentException("Base type " + BaseType + " is not assignable from type " + type + ".", nameof(type));
|
||||
_types.Add(type);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Cms.Core.Configuration.Models
|
||||
internal const bool StaticUseHttps = false;
|
||||
internal const int StaticVersionCheckPeriod = 7;
|
||||
internal const string StaticUmbracoPath = Constants.System.DefaultUmbracoPath;
|
||||
internal const string StaticIconsPath = "~/umbraco/assets/icons";
|
||||
internal const string StaticIconsPath = "umbraco/assets/icons";
|
||||
internal const string StaticUmbracoCssPath = "~/css";
|
||||
internal const string StaticUmbracoScriptsPath = "~/scripts";
|
||||
internal const string StaticUmbracoMediaPath = "~/media";
|
||||
|
||||
@@ -1865,6 +1865,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
|
||||
</area>
|
||||
<area alias="languages">
|
||||
<key alias="addLanguage">Add language</key>
|
||||
<key alias="culture">ISO code</key>
|
||||
<key alias="mandatoryLanguage">Mandatory language</key>
|
||||
<key alias="mandatoryLanguageHelp">Properties on this language have to be filled out before the node can be
|
||||
published.
|
||||
@@ -1928,6 +1928,7 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
|
||||
</area>
|
||||
<area alias="languages">
|
||||
<key alias="addLanguage">Add language</key>
|
||||
<key alias="culture">ISO code</key>
|
||||
<key alias="mandatoryLanguage">Mandatory language</key>
|
||||
<key alias="mandatoryLanguageHelp">Properties on this language have to be filled out before the node can be
|
||||
published.
|
||||
@@ -2870,5 +2871,29 @@ To manage your website, simply open the Umbraco backoffice and start adding cont
|
||||
<area alias="analytics">
|
||||
<key alias="consentForAnalytics">Consent for analytics</key>
|
||||
<key alias="analyticsLevelSavedSuccess">Analytics level saved!</key>
|
||||
<key alias="analyticsDescription">
|
||||
<![CDATA[
|
||||
In order to improve Umbraco and add new functionality based on as relevant information as possible,
|
||||
<br>we would like to collect system- and usage information from your installation.
|
||||
<br>Aggregate data will be shared on a regular basis as well as learnings from these metrics.
|
||||
<br>Hopefully, you will help us collect some valuable data.
|
||||
<br>
|
||||
<br>We <b>WILL NOT</b> collect any personal data such as content, code, user information, and all data will be fully anonymized.
|
||||
]]>
|
||||
</key>
|
||||
<key alias="minimalLevelDescription">We will only send an anonymized site ID to let us know that the site exists.</key>
|
||||
<key alias="basicLevelDescription">We will send an anonymized site ID, umbraco version, and packages installed</key>
|
||||
<key alias="detailedLevelDescription">
|
||||
<![CDATA[
|
||||
<br> We will send:
|
||||
<br>- Anonymized site ID, umbraco version, and packages installed.
|
||||
<br>- Number of: Root nodes, Content nodes, Macros, Media, Document Types, Templates, Languages, Domains, User Group, Users, Members, and Property Editors in use.
|
||||
<br>- System information: Webserver, server OS, server framework, server OS language, and database provider.
|
||||
<br>- Configuration settings: Modelsbuilder mode, if custom Umbraco path exists, ASP environment, and if you are in debug mode.
|
||||
<br>
|
||||
<br><i>We might change what we send on the Detailed level in the future. If so, it will be listed above.
|
||||
<br>By choosing "Detailed" you agree to current and future anonymized information being collected.</i>
|
||||
]]>
|
||||
</key>
|
||||
</area>
|
||||
</language>
|
||||
@@ -128,7 +128,7 @@ namespace Umbraco.Cms.Core.Events
|
||||
return AdditionalData != null ? AdditionalData.GetHashCode() : 0;
|
||||
}
|
||||
|
||||
public static bool operator ==(CancellableEventArgs left, CancellableEventArgs right)
|
||||
public static bool operator ==(CancellableEventArgs? left, CancellableEventArgs? right)
|
||||
{
|
||||
return Equals(left, right);
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace Umbraco.Cms.Core.Events
|
||||
/// </summary>
|
||||
public IEnumerable<TEntity> DeletedEntities
|
||||
{
|
||||
get => EventObject;
|
||||
get => EventObject ?? Enumerable.Empty<TEntity>();
|
||||
set => EventObject = value;
|
||||
}
|
||||
|
||||
@@ -108,14 +108,14 @@ namespace Umbraco.Cms.Core.Events
|
||||
/// </summary>
|
||||
public List<string> MediaFilesToDelete { get; private set; }
|
||||
|
||||
public bool Equals(DeleteEventArgs<TEntity> other)
|
||||
public bool Equals(DeleteEventArgs<TEntity>? other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return base.Equals(other) && MediaFilesToDelete.SequenceEqual(other.MediaFilesToDelete);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
@@ -166,14 +166,14 @@ namespace Umbraco.Cms.Core.Events
|
||||
/// </summary>
|
||||
public int Id { get; private set; }
|
||||
|
||||
public bool Equals(DeleteEventArgs other)
|
||||
public bool Equals(DeleteEventArgs? other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return base.Equals(other) && Id == other.Id;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
|
||||
@@ -27,11 +27,11 @@ namespace Umbraco.Cms.Core.Events
|
||||
|
||||
public class EventDefinition<TEventArgs> : EventDefinitionBase
|
||||
{
|
||||
private readonly EventHandler<TEventArgs?> _trackedEvent;
|
||||
private readonly EventHandler<TEventArgs> _trackedEvent;
|
||||
private readonly object _sender;
|
||||
private readonly TEventArgs? _args;
|
||||
private readonly TEventArgs _args;
|
||||
|
||||
public EventDefinition(EventHandler<TEventArgs?> trackedEvent, object sender, TEventArgs? args, string? eventName = null)
|
||||
public EventDefinition(EventHandler<TEventArgs> trackedEvent, object sender, TEventArgs args, string? eventName = null)
|
||||
: base(sender, args, eventName)
|
||||
{
|
||||
_trackedEvent = trackedEvent;
|
||||
@@ -50,11 +50,11 @@ namespace Umbraco.Cms.Core.Events
|
||||
|
||||
public class EventDefinition<TSender, TEventArgs> : EventDefinitionBase
|
||||
{
|
||||
private readonly TypedEventHandler<TSender?, TEventArgs> _trackedEvent;
|
||||
private readonly TSender? _sender;
|
||||
private readonly TypedEventHandler<TSender, TEventArgs> _trackedEvent;
|
||||
private readonly TSender _sender;
|
||||
private readonly TEventArgs _args;
|
||||
|
||||
public EventDefinition(TypedEventHandler<TSender?, TEventArgs> trackedEvent, TSender? sender, TEventArgs args, string? eventName = null)
|
||||
public EventDefinition(TypedEventHandler<TSender, TEventArgs> trackedEvent, TSender sender, TEventArgs args, string? eventName = null)
|
||||
: base(sender, args, eventName)
|
||||
{
|
||||
_trackedEvent = trackedEvent;
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Umbraco.Cms.Core.Events
|
||||
/// <param name="name">The optional name of the event.</param>
|
||||
/// <returns>A value indicating whether the cancelable event was cancelled.</returns>
|
||||
/// <remarks>See general remarks on the interface.</remarks>
|
||||
bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string name = null);
|
||||
bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string? name = null);
|
||||
|
||||
/// <summary>
|
||||
/// Dispatches a cancelable event.
|
||||
@@ -38,7 +38,7 @@ namespace Umbraco.Cms.Core.Events
|
||||
/// <param name="name">The optional name of the event.</param>
|
||||
/// <returns>A value indicating whether the cancelable event was cancelled.</returns>
|
||||
/// <remarks>See general remarks on the interface.</remarks>
|
||||
bool DispatchCancelable<TArgs>(EventHandler<TArgs> eventHandler, object sender, TArgs args, string name = null)
|
||||
bool DispatchCancelable<TArgs>(EventHandler<TArgs> eventHandler, object sender, TArgs args, string? name = null)
|
||||
where TArgs : CancellableEventArgs;
|
||||
|
||||
/// <summary>
|
||||
@@ -50,7 +50,7 @@ namespace Umbraco.Cms.Core.Events
|
||||
/// <param name="name">The optional name of the event.</param>
|
||||
/// <returns>A value indicating whether the cancelable event was cancelled.</returns>
|
||||
/// <remarks>See general remarks on the interface.</remarks>
|
||||
bool DispatchCancelable<TSender, TArgs>(TypedEventHandler<TSender, TArgs> eventHandler, TSender sender, TArgs args, string name = null)
|
||||
bool DispatchCancelable<TSender, TArgs>(TypedEventHandler<TSender, TArgs> eventHandler, TSender sender, TArgs args, string? name = null)
|
||||
where TArgs : CancellableEventArgs;
|
||||
|
||||
/// <summary>
|
||||
@@ -61,7 +61,7 @@ namespace Umbraco.Cms.Core.Events
|
||||
/// <param name="args">The event data.</param>
|
||||
/// <param name="name">The optional name of the event.</param>
|
||||
/// <remarks>See general remarks on the interface.</remarks>
|
||||
void Dispatch(EventHandler eventHandler, object sender, EventArgs args, string name = null);
|
||||
void Dispatch(EventHandler eventHandler, object sender, EventArgs args, string? name = null);
|
||||
|
||||
/// <summary>
|
||||
/// Dispatches an event.
|
||||
@@ -71,7 +71,7 @@ namespace Umbraco.Cms.Core.Events
|
||||
/// <param name="args">The event data.</param>
|
||||
/// <param name="name">The optional name of the event.</param>
|
||||
/// <remarks>See general remarks on the interface.</remarks>
|
||||
void Dispatch<TArgs>(EventHandler<TArgs> eventHandler, object sender, TArgs args, string name = null);
|
||||
void Dispatch<TArgs>(EventHandler<TArgs> eventHandler, object sender, TArgs args, string? name = null);
|
||||
|
||||
/// <summary>
|
||||
/// Dispatches an event.
|
||||
@@ -81,7 +81,7 @@ namespace Umbraco.Cms.Core.Events
|
||||
/// <param name="args">The event data.</param>
|
||||
/// <param name="name">The optional name of the event.</param>
|
||||
/// <remarks>See general remarks on the interface.</remarks>
|
||||
void Dispatch<TSender, TArgs>(TypedEventHandler<TSender, TArgs> eventHandler, TSender sender, TArgs args, string name = null);
|
||||
void Dispatch<TSender, TArgs>(TypedEventHandler<TSender, TArgs> eventHandler, TSender sender, TArgs args, string? name = null);
|
||||
|
||||
/// <summary>
|
||||
/// Notifies the dispatcher that the scope is exiting.
|
||||
|
||||
@@ -11,14 +11,14 @@ namespace Umbraco.Cms.Core.Events
|
||||
/// whatever happens, and the transaction could roll back in the end.</remarks>
|
||||
internal class PassThroughEventDispatcher : IEventDispatcher
|
||||
{
|
||||
public bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string eventName = null)
|
||||
public bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string? eventName = null)
|
||||
{
|
||||
if (eventHandler == null) return args.Cancel;
|
||||
eventHandler(sender, args);
|
||||
return args.Cancel;
|
||||
}
|
||||
|
||||
public bool DispatchCancelable<TArgs>(EventHandler<TArgs> eventHandler, object sender, TArgs args, string eventName = null)
|
||||
public bool DispatchCancelable<TArgs>(EventHandler<TArgs> eventHandler, object sender, TArgs args, string? eventName = null)
|
||||
where TArgs : CancellableEventArgs
|
||||
{
|
||||
if (eventHandler == null) return args.Cancel;
|
||||
@@ -26,7 +26,7 @@ namespace Umbraco.Cms.Core.Events
|
||||
return args.Cancel;
|
||||
}
|
||||
|
||||
public bool DispatchCancelable<TSender, TArgs>(TypedEventHandler<TSender, TArgs> eventHandler, TSender sender, TArgs args, string eventName = null)
|
||||
public bool DispatchCancelable<TSender, TArgs>(TypedEventHandler<TSender, TArgs> eventHandler, TSender sender, TArgs args, string? eventName = null)
|
||||
where TArgs : CancellableEventArgs
|
||||
{
|
||||
if (eventHandler == null) return args.Cancel;
|
||||
@@ -34,17 +34,17 @@ namespace Umbraco.Cms.Core.Events
|
||||
return args.Cancel;
|
||||
}
|
||||
|
||||
public void Dispatch(EventHandler eventHandler, object sender, EventArgs args, string eventName = null)
|
||||
public void Dispatch(EventHandler eventHandler, object sender, EventArgs args, string? eventName = null)
|
||||
{
|
||||
eventHandler?.Invoke(sender, args);
|
||||
}
|
||||
|
||||
public void Dispatch<TArgs>(EventHandler<TArgs> eventHandler, object sender, TArgs args, string eventName = null)
|
||||
public void Dispatch<TArgs>(EventHandler<TArgs> eventHandler, object sender, TArgs args, string? eventName = null)
|
||||
{
|
||||
eventHandler?.Invoke(sender, args);
|
||||
}
|
||||
|
||||
public void Dispatch<TSender, TArgs>(TypedEventHandler<TSender, TArgs> eventHandler, TSender sender, TArgs args, string eventName = null)
|
||||
public void Dispatch<TSender, TArgs>(TypedEventHandler<TSender, TArgs> eventHandler, TSender sender, TArgs args, string? eventName = null)
|
||||
{
|
||||
eventHandler?.Invoke(sender, args);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Cms.Core.Collections;
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Cms.Core.Events
|
||||
public abstract class QueuingEventDispatcherBase : IEventDispatcher
|
||||
{
|
||||
//events will be enlisted in the order they are raised
|
||||
private List<IEventDefinition> _events;
|
||||
private List<IEventDefinition>? _events;
|
||||
private readonly bool _raiseCancelable;
|
||||
|
||||
protected QueuingEventDispatcherBase(bool raiseCancelable)
|
||||
@@ -30,7 +30,7 @@ namespace Umbraco.Cms.Core.Events
|
||||
|
||||
private List<IEventDefinition> Events => _events ?? (_events = new List<IEventDefinition>());
|
||||
|
||||
public bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string eventName = null)
|
||||
public bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string? eventName = null)
|
||||
{
|
||||
if (eventHandler == null) return args.Cancel;
|
||||
if (_raiseCancelable == false) return args.Cancel;
|
||||
@@ -38,7 +38,7 @@ namespace Umbraco.Cms.Core.Events
|
||||
return args.Cancel;
|
||||
}
|
||||
|
||||
public bool DispatchCancelable<TArgs>(EventHandler<TArgs> eventHandler, object sender, TArgs args, string eventName = null)
|
||||
public bool DispatchCancelable<TArgs>(EventHandler<TArgs> eventHandler, object sender, TArgs args, string? eventName = null)
|
||||
where TArgs : CancellableEventArgs
|
||||
{
|
||||
if (eventHandler == null) return args.Cancel;
|
||||
@@ -47,7 +47,7 @@ namespace Umbraco.Cms.Core.Events
|
||||
return args.Cancel;
|
||||
}
|
||||
|
||||
public bool DispatchCancelable<TSender, TArgs>(TypedEventHandler<TSender, TArgs> eventHandler, TSender sender, TArgs args, string eventName = null)
|
||||
public bool DispatchCancelable<TSender, TArgs>(TypedEventHandler<TSender, TArgs> eventHandler, TSender sender, TArgs args, string? eventName = null)
|
||||
where TArgs : CancellableEventArgs
|
||||
{
|
||||
if (eventHandler == null) return args.Cancel;
|
||||
@@ -56,19 +56,19 @@ namespace Umbraco.Cms.Core.Events
|
||||
return args.Cancel;
|
||||
}
|
||||
|
||||
public void Dispatch(EventHandler eventHandler, object sender, EventArgs args, string eventName = null)
|
||||
public void Dispatch(EventHandler eventHandler, object sender, EventArgs args, string? eventName = null)
|
||||
{
|
||||
if (eventHandler == null) return;
|
||||
Events.Add(new EventDefinition(eventHandler, sender, args, eventName));
|
||||
}
|
||||
|
||||
public void Dispatch<TArgs>(EventHandler<TArgs> eventHandler, object sender, TArgs args, string eventName = null)
|
||||
public void Dispatch<TArgs>(EventHandler<TArgs> eventHandler, object sender, TArgs args, string? eventName = null)
|
||||
{
|
||||
if (eventHandler == null) return;
|
||||
Events.Add(new EventDefinition<TArgs>(eventHandler, sender, args, eventName));
|
||||
}
|
||||
|
||||
public void Dispatch<TSender, TArgs>(TypedEventHandler<TSender, TArgs> eventHandler, TSender sender, TArgs args, string eventName = null)
|
||||
public void Dispatch<TSender, TArgs>(TypedEventHandler<TSender, TArgs> eventHandler, TSender sender, TArgs args, string? eventName = null)
|
||||
{
|
||||
if (eventHandler == null) return;
|
||||
Events.Add(new EventDefinition<TSender, TArgs>(eventHandler, sender, args, eventName));
|
||||
@@ -106,8 +106,8 @@ namespace Umbraco.Cms.Core.Events
|
||||
|
||||
private class EventDefinitionInfos
|
||||
{
|
||||
public IEventDefinition EventDefinition { get; set; }
|
||||
public Type[] SupersedeTypes { get; set; }
|
||||
public IEventDefinition? EventDefinition { get; set; }
|
||||
public Type[]? SupersedeTypes { get; set; }
|
||||
}
|
||||
|
||||
// this is way too convoluted, the supersede attribute is used only on DeleteEventargs to specify
|
||||
@@ -291,13 +291,13 @@ namespace Umbraco.Cms.Core.Events
|
||||
private static bool IsSuperceeded(IEntity entity, EventDefinitionInfos infos, List<Tuple<IEntity, EventDefinitionInfos>> entities)
|
||||
{
|
||||
//var argType = meta.EventArgsType;
|
||||
var argType = infos.EventDefinition.Args.GetType();
|
||||
var argType = infos.EventDefinition?.Args.GetType();
|
||||
|
||||
// look for other instances of the same entity, coming from an event args that supersedes other event args,
|
||||
// ie is marked with the attribute, and is not this event args (cannot supersede itself)
|
||||
var superceeding = entities
|
||||
.Where(x => x.Item2.SupersedeTypes.Length > 0 // has the attribute
|
||||
&& x.Item2.EventDefinition.Args.GetType() != argType // is not the same
|
||||
.Where(x => x.Item2.SupersedeTypes?.Length > 0 // has the attribute
|
||||
&& x.Item2.EventDefinition?.Args.GetType() != argType // is not the same
|
||||
&& Equals(x.Item1, entity)) // same entity
|
||||
.ToArray();
|
||||
|
||||
@@ -306,27 +306,27 @@ namespace Umbraco.Cms.Core.Events
|
||||
return false;
|
||||
|
||||
// delete event args does NOT supersedes 'unpublished' event
|
||||
if (argType.IsGenericType && argType.GetGenericTypeDefinition() == typeof(PublishEventArgs<>) && infos.EventDefinition.EventName == "Unpublished")
|
||||
if ((argType?.IsGenericType ?? false) && argType.GetGenericTypeDefinition() == typeof(PublishEventArgs<>) && infos.EventDefinition?.EventName == "Unpublished")
|
||||
return false;
|
||||
|
||||
// found occurrences, need to determine if this event args is superseded
|
||||
if (argType.IsGenericType)
|
||||
if (argType?.IsGenericType ?? false)
|
||||
{
|
||||
// generic, must compare type arguments
|
||||
var supercededBy = superceeding.FirstOrDefault(x =>
|
||||
x.Item2.SupersedeTypes.Any(y =>
|
||||
x.Item2.SupersedeTypes?.Any(y =>
|
||||
// superseding a generic type which has the same generic type definition
|
||||
// (but ... no matter the generic type parameters? could be different?)
|
||||
y.IsGenericTypeDefinition && y == argType.GetGenericTypeDefinition()
|
||||
// or superceeding a non-generic type which is ... (but... how is this ever possible? argType *is* generic?
|
||||
|| y.IsGenericTypeDefinition == false && y == argType));
|
||||
|| y.IsGenericTypeDefinition == false && y == argType) ?? false);
|
||||
return supercededBy != null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-generic, can compare types 1:1
|
||||
var supercededBy = superceeding.FirstOrDefault(x =>
|
||||
x.Item2.SupersedeTypes.Any(y => y == argType));
|
||||
x.Item2.SupersedeTypes?.Any(y => y == argType) ?? false);
|
||||
return supercededBy != null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,18 +75,6 @@ namespace Umbraco.Extensions
|
||||
yield return result;
|
||||
}
|
||||
|
||||
/// <summary>The legacy distinct by.</summary>
|
||||
/// <param name="source">The source.</param>
|
||||
/// <param name="keySelector">The key selector.</param>
|
||||
/// <typeparam name="TSource">Source type</typeparam>
|
||||
/// <typeparam name="TKey">Key type</typeparam>
|
||||
/// <returns>the unique list</returns>
|
||||
public static IEnumerable<TSource> LegacyDistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource?, TKey> keySelector)
|
||||
where TKey : IEquatable<TKey>
|
||||
{
|
||||
return source.Distinct(DelegateEqualityComparer<TSource>.CompareMember(keySelector));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a sequence of length <paramref name="count"/> whose elements are the result of invoking <paramref name="factory"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Umbraco.Cms.Core.Extensions
|
||||
/// </summary>
|
||||
public static class HostEnvironmentExtensions
|
||||
{
|
||||
private static string s_temporaryApplicationId;
|
||||
private static string? s_temporaryApplicationId;
|
||||
|
||||
/// <summary>
|
||||
/// Maps a virtual path to a physical path to the application's content root.
|
||||
|
||||
@@ -365,7 +365,7 @@ namespace Umbraco.Extensions
|
||||
/// returns <see langword="false"/>.</returns>
|
||||
public static bool IsNullOrWhiteSpace(this string? value) => string.IsNullOrWhiteSpace(value);
|
||||
|
||||
public static string? IfNullOrWhiteSpace(this string str, string? defaultValue)
|
||||
public static string? IfNullOrWhiteSpace(this string? str, string? defaultValue)
|
||||
{
|
||||
return str.IsNullOrWhiteSpace() ? defaultValue : str;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Cms.Core.Mapping
|
||||
@@ -121,7 +121,7 @@ namespace Umbraco.Cms.Core.Mapping
|
||||
/// <returns>A list containing the target objects.</returns>
|
||||
public List<TTargetElement> MapEnumerable<TSourceElement, TTargetElement>(IEnumerable<TSourceElement> source)
|
||||
{
|
||||
return source.Select(Map<TSourceElement, TTargetElement>).ToList();
|
||||
return source.Select(Map<TSourceElement, TTargetElement>).Where(x => x is not null).ToList()!;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
@@ -12,10 +11,9 @@ namespace Umbraco.Cms.Core.Models.ContentEditing
|
||||
|
||||
[DataMember(Name = "culture", IsRequired = true)]
|
||||
[Required(AllowEmptyStrings = false)]
|
||||
public string? IsoCode { get; set; }
|
||||
public string IsoCode { get; set; } = null!;
|
||||
|
||||
[DataMember(Name = "name")]
|
||||
[ReadOnly(true)]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[DataMember(Name = "isDefault")]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Globalization;
|
||||
using System.Globalization;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Umbraco.Cms.Core.Models
|
||||
/// Gets or sets the culture name of the language.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
string? CultureName { get; set; }
|
||||
string CultureName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="CultureInfo"/> object for the language.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Models.Entities;
|
||||
|
||||
@@ -14,18 +12,28 @@ namespace Umbraco.Cms.Core.Models
|
||||
[DataContract(IsReference = true)]
|
||||
public class Language : EntityBase, ILanguage
|
||||
{
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
|
||||
private string _isoCode = null!;
|
||||
private string? _cultureName;
|
||||
private string _isoCode;
|
||||
private string _cultureName;
|
||||
private bool _isDefaultVariantLanguage;
|
||||
private bool _mandatory;
|
||||
private int? _fallbackLanguageId;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Language" /> class.
|
||||
/// </summary>
|
||||
/// <param name="isoCode">The ISO code of the language.</param>
|
||||
/// <param name="cultureName">The name of the language.</param>
|
||||
public Language(string isoCode, string cultureName)
|
||||
{
|
||||
_isoCode = isoCode ?? throw new ArgumentNullException(nameof(isoCode));
|
||||
_cultureName = cultureName ?? throw new ArgumentNullException(nameof(cultureName));
|
||||
}
|
||||
|
||||
[Obsolete("Use the constructor not requiring global settings and accepting an explicit name instead, scheduled for removal in V11.")]
|
||||
public Language(GlobalSettings globalSettings, string isoCode)
|
||||
{
|
||||
IsoCode = isoCode;
|
||||
_globalSettings = globalSettings;
|
||||
_isoCode = isoCode ?? throw new ArgumentNullException(nameof(isoCode));
|
||||
_cultureName = CultureInfo.GetCultureInfo(isoCode).EnglishName;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -33,64 +41,25 @@ namespace Umbraco.Cms.Core.Models
|
||||
public string IsoCode
|
||||
{
|
||||
get => _isoCode;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _isoCode!, nameof(IsoCode));
|
||||
set
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
|
||||
SetPropertyValueAndDetectChanges(value, ref _isoCode!, nameof(IsoCode));
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
public string? CultureName
|
||||
public string CultureName
|
||||
{
|
||||
// CultureInfo.DisplayName is the name in the installed .NET language
|
||||
// .NativeName is the name in culture info's language
|
||||
// .EnglishName is the name in English
|
||||
//
|
||||
// there is no easy way to get the name in a specified culture (which would need to be installed on the server)
|
||||
// this works:
|
||||
// var rm = new ResourceManager("mscorlib", typeof(int).Assembly);
|
||||
// var name = rm.GetString("Globalization.ci_" + culture.Name, displayCulture);
|
||||
// but can we rely on it?
|
||||
//
|
||||
// and... DisplayName is captured and cached in culture infos returned by GetCultureInfo(), using
|
||||
// the value for the current thread culture at the moment it is first retrieved - whereas creating
|
||||
// a new CultureInfo() creates a new instance, which _then_ can get DisplayName again in a different
|
||||
// culture
|
||||
//
|
||||
// I assume that, on a site, all language names should be in the SAME language, in DB,
|
||||
// and that would be the Umbraco.Core.DefaultUILanguage (app setting) - BUT if by accident
|
||||
// ANY culture has been retrieved with another current thread culture - it's now corrupt
|
||||
//
|
||||
// so, the logic below ensures that the name always end up being the correct name
|
||||
// see also LanguageController.GetAllCultures which is doing the same
|
||||
//
|
||||
// all this, including the ugly settings injection, because se store language names in db,
|
||||
// otherwise it would be ok to simply return new CultureInfo(IsoCode).DisplayName to get the name
|
||||
// in whatever culture is current - we should not do it, see task #3623
|
||||
//
|
||||
// but then, some tests that compare audit strings (for culture names) would need to be fixed
|
||||
|
||||
get
|
||||
get => _cultureName;
|
||||
set
|
||||
{
|
||||
if (_cultureName != null) return _cultureName;
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
|
||||
// capture
|
||||
var threadUiCulture = Thread.CurrentThread.CurrentUICulture;
|
||||
|
||||
try
|
||||
{
|
||||
var defaultUiCulture = CultureInfo.GetCultureInfo(_globalSettings.DefaultUILanguage);
|
||||
Thread.CurrentThread.CurrentUICulture = defaultUiCulture;
|
||||
|
||||
// get name - new-ing an instance to get proper display name
|
||||
return new CultureInfo(IsoCode).DisplayName;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// restore
|
||||
Thread.CurrentThread.CurrentUICulture = threadUiCulture;
|
||||
}
|
||||
SetPropertyValueAndDetectChanges(value, ref _cultureName!, nameof(CultureName));
|
||||
}
|
||||
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _cultureName, nameof(CultureName));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
target.Translations.Add(new DictionaryTranslationDisplay
|
||||
{
|
||||
IsoCode = lang.IsoCode,
|
||||
DisplayName = lang.CultureInfo?.DisplayName,
|
||||
DisplayName = lang.CultureName,
|
||||
Translation = translation?.Value ?? string.Empty,
|
||||
LanguageId = lang.Id
|
||||
});
|
||||
@@ -106,7 +106,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
target.Translations.Add(
|
||||
new DictionaryOverviewTranslationDisplay
|
||||
{
|
||||
DisplayName = lang.CultureInfo?.DisplayName,
|
||||
DisplayName = lang.CultureName,
|
||||
HasTranslation = translation != null && string.IsNullOrEmpty(translation.Value) == false
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Cms.Core.Mapping;
|
||||
@@ -31,7 +31,7 @@ namespace Umbraco.Cms.Core.Models.Mapping
|
||||
{
|
||||
target.Id = source.Id;
|
||||
target.IsoCode = source.IsoCode;
|
||||
target.Name = source.CultureInfo?.DisplayName;
|
||||
target.Name = source.CultureName;
|
||||
target.IsDefault = source.IsDefault;
|
||||
target.IsMandatory = source.IsMandatory;
|
||||
target.FallbackLanguageId = source.FallbackLanguageId;
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models.PublishedContent
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Provides the published model creation service.
|
||||
/// </summary>
|
||||
@@ -13,23 +11,40 @@ namespace Umbraco.Cms.Core.Models.PublishedContent
|
||||
/// Creates a strongly-typed model representing a published element.
|
||||
/// </summary>
|
||||
/// <param name="element">The original published element.</param>
|
||||
/// <returns>The strongly-typed model representing the published element, or the published element
|
||||
/// itself it the factory has no model for the corresponding element type.</returns>
|
||||
/// <returns>
|
||||
/// The strongly-typed model representing the published element,
|
||||
/// or the published element itself it the factory has no model for the corresponding element type.
|
||||
/// </returns>
|
||||
IPublishedElement CreateModel(IPublishedElement element);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a List{T} of a strongly-typed model for a model type alias.
|
||||
/// </summary>
|
||||
/// <param name="alias">The model type alias.</param>
|
||||
/// <returns>A List{T} of the strongly-typed model, exposed as an IList.</returns>
|
||||
/// <returns>
|
||||
/// A List{T} of the strongly-typed model, exposed as an IList.
|
||||
/// </returns>
|
||||
IList? CreateModelList(string? alias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Type of a strongly-typed model for a model type alias.
|
||||
/// </summary>
|
||||
/// <param name="alias">The model type alias.</param>
|
||||
/// <returns>
|
||||
/// The type of the strongly-typed model.
|
||||
/// </returns>
|
||||
Type GetModelType(string? alias);
|
||||
|
||||
/// <summary>
|
||||
/// Maps a CLR type that may contain model types, to an actual CLR type.
|
||||
/// </summary>
|
||||
/// <param name="type">The CLR type.</param>
|
||||
/// <returns>The actual CLR type.</returns>
|
||||
/// <remarks>See <seealso cref="ModelType"/> for more details.</remarks>
|
||||
/// <returns>
|
||||
/// The actual CLR type.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// See <seealso cref="ModelType" /> for more details.
|
||||
/// </remarks>
|
||||
Type MapModelType(Type type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models.PublishedContent
|
||||
{
|
||||
@@ -14,6 +12,9 @@ namespace Umbraco.Cms.Core.Models.PublishedContent
|
||||
/// <inheritdoc />
|
||||
public IList CreateModelList(string? alias) => new List<IPublishedElement>();
|
||||
|
||||
/// <inheritdoc />
|
||||
public Type GetModelType(string? alias) => typeof(IPublishedElement);
|
||||
|
||||
/// <inheritdoc />
|
||||
public Type MapModelType(Type type) => typeof(IPublishedElement);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
@@ -84,7 +84,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent
|
||||
if (_publishedDataTypes == null)
|
||||
{
|
||||
var dataTypes = _dataTypeService.GetAll();
|
||||
_publishedDataTypes = dataTypes?.ToDictionary(x => x.Id, CreatePublishedDataType);
|
||||
_publishedDataTypes = dataTypes.ToDictionary(x => x.Id, CreatePublishedDataType);
|
||||
}
|
||||
|
||||
publishedDataTypes = _publishedDataTypes;
|
||||
@@ -104,7 +104,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent
|
||||
if (_publishedDataTypes == null)
|
||||
{
|
||||
var dataTypes = _dataTypeService.GetAll();
|
||||
_publishedDataTypes = dataTypes?.ToDictionary(x => x.Id, CreatePublishedDataType);
|
||||
_publishedDataTypes = dataTypes.ToDictionary(x => x.Id, CreatePublishedDataType);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -112,11 +112,8 @@ namespace Umbraco.Cms.Core.Models.PublishedContent
|
||||
_publishedDataTypes.Remove(id);
|
||||
|
||||
var dataTypes = _dataTypeService.GetAll(ids);
|
||||
if (dataTypes is not null)
|
||||
{
|
||||
foreach (var dataType in dataTypes)
|
||||
_publishedDataTypes[dataType.Id] = CreatePublishedDataType(dataType);
|
||||
}
|
||||
foreach (var dataType in dataTypes)
|
||||
_publishedDataTypes[dataType.Id] = CreatePublishedDataType(dataType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Cms.Core.Models.PublishedContent
|
||||
@@ -59,20 +57,27 @@ namespace Umbraco.Cms.Core.Models.PublishedContent
|
||||
if (parms.Length == 2 && typeof(IPublishedElement).IsAssignableFrom(parms[0].ParameterType) && typeof(IPublishedValueFallback).IsAssignableFrom(parms[1].ParameterType))
|
||||
{
|
||||
if (constructor != null)
|
||||
{
|
||||
throw new InvalidOperationException($"Type {type.FullName} has more than one public constructor with one argument of type, or implementing, IPublishedElement.");
|
||||
}
|
||||
|
||||
constructor = ctor;
|
||||
parameterType = parms[0].ParameterType;
|
||||
}
|
||||
}
|
||||
|
||||
if (constructor == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Type {type.FullName} is missing a public constructor with one argument of type, or implementing, IPublishedElement.");
|
||||
}
|
||||
|
||||
var attribute = type.GetCustomAttribute<PublishedModelAttribute>(false);
|
||||
var typeName = attribute == null ? type.Name : attribute.ContentTypeAlias;
|
||||
|
||||
if (modelInfos.TryGetValue(typeName, out var modelInfo))
|
||||
{
|
||||
throw new InvalidOperationException($"Both types '{type.AssemblyQualifiedName}' and '{modelInfo.ModelType?.AssemblyQualifiedName}' want to be a model type for content type with alias \"{typeName}\".");
|
||||
}
|
||||
|
||||
// have to use an unsafe ctor because we don't know the types, really
|
||||
var modelCtor = ReflectionUtilities.EmitConstructorUnsafe<Func<object, IPublishedValueFallback, object>>(constructor);
|
||||
@@ -89,15 +94,16 @@ namespace Umbraco.Cms.Core.Models.PublishedContent
|
||||
public IPublishedElement CreateModel(IPublishedElement element)
|
||||
{
|
||||
// fail fast
|
||||
if (_modelInfos == null)
|
||||
return element;
|
||||
|
||||
if (element.ContentType.Alias is null || !_modelInfos.TryGetValue(element.ContentType.Alias, out var modelInfo))
|
||||
if (_modelInfos is null || element.ContentType.Alias is null || !_modelInfos.TryGetValue(element.ContentType.Alias, out var modelInfo))
|
||||
{
|
||||
return element;
|
||||
}
|
||||
|
||||
// ReSharper disable once UseMethodIsInstanceOfType
|
||||
if (modelInfo.ParameterType?.IsAssignableFrom(element.GetType()) == false)
|
||||
{
|
||||
throw new InvalidOperationException($"Model {modelInfo.ModelType} expects argument of type {modelInfo.ParameterType.FullName}, but got {element.GetType().FullName}.");
|
||||
}
|
||||
|
||||
// can cast, because we checked when creating the ctor
|
||||
return (IPublishedElement)modelInfo.Ctor!(element, _publishedValueFallback);
|
||||
@@ -107,21 +113,42 @@ namespace Umbraco.Cms.Core.Models.PublishedContent
|
||||
public IList? CreateModelList(string? alias)
|
||||
{
|
||||
// fail fast
|
||||
if (_modelInfos == null)
|
||||
return new List<IPublishedElement>();
|
||||
|
||||
if (alias is null || !_modelInfos.TryGetValue(alias, out var modelInfo) || modelInfo.ModelType is null)
|
||||
if (_modelInfos is null || alias is null || !_modelInfos.TryGetValue(alias, out var modelInfo) || modelInfo.ModelType is null)
|
||||
{
|
||||
return new List<IPublishedElement>();
|
||||
}
|
||||
|
||||
var ctor = modelInfo.ListCtor;
|
||||
if (ctor != null) return ctor();
|
||||
if (ctor != null)
|
||||
{
|
||||
return ctor();
|
||||
}
|
||||
|
||||
var listType = typeof(List<>).MakeGenericType(modelInfo.ModelType);
|
||||
ctor = modelInfo.ListCtor = ReflectionUtilities.EmitConstructor<Func<IList>>(declaring: listType);
|
||||
if(ctor is not null) return ctor();
|
||||
if (ctor is not null)
|
||||
{
|
||||
return ctor();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Type GetModelType(string? alias)
|
||||
{
|
||||
// fail fast
|
||||
if (_modelInfos is null ||
|
||||
alias is null ||
|
||||
!_modelInfos.TryGetValue(alias, out var modelInfo) ||
|
||||
modelInfo.ModelType is null)
|
||||
{
|
||||
return typeof(IPublishedElement);
|
||||
}
|
||||
|
||||
return modelInfo.ModelType;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Type MapModelType(Type type)
|
||||
=> ModelType.Map(type, _modelTypeMap);
|
||||
|
||||
@@ -4,6 +4,6 @@ namespace Umbraco.Cms.Core.Notifications
|
||||
{
|
||||
public interface IStatefulNotification : INotification
|
||||
{
|
||||
IDictionary<string, object> State { get; set; }
|
||||
IDictionary<string, object?> State { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Umbraco.Cms.Core.Notifications
|
||||
{
|
||||
public static class NotificationExtensions
|
||||
{
|
||||
public static T WithState<T>(this T notification, IDictionary<string, object>? state) where T : IStatefulNotification
|
||||
public static T WithState<T>(this T notification, IDictionary<string, object?>? state) where T : IStatefulNotification
|
||||
{
|
||||
notification.State = state!;
|
||||
return notification;
|
||||
|
||||
@@ -6,15 +6,15 @@ namespace Umbraco.Cms.Core.Notifications
|
||||
{
|
||||
public abstract class StatefulNotification : IStatefulNotification
|
||||
{
|
||||
private IDictionary<string, object>? _state;
|
||||
private IDictionary<string, object?>? _state;
|
||||
|
||||
/// <summary>
|
||||
/// This can be used by event subscribers to store state in the notification so they easily deal with custom state data between
|
||||
/// a starting ("ing") and an ending ("ed") notification
|
||||
/// </summary>
|
||||
public IDictionary<string, object> State
|
||||
public IDictionary<string, object?> State
|
||||
{
|
||||
get => _state ??= new Dictionary<string, object>();
|
||||
get => _state ??= new Dictionary<string, object?>();
|
||||
set => _state = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,7 +577,7 @@ namespace Umbraco.Cms.Core.Packaging
|
||||
|
||||
////Now, we have all property Ids/Aliases and their referenced document Ids and tags
|
||||
//var allExportedTaggedEntities = allTaggedEntities.Where(x => allExportedIds.Contains(x.EntityId))
|
||||
// .LegacyDistinctBy(x => x.EntityId)
|
||||
// .DistinctBy(x => x.EntityId)
|
||||
// .OrderBy(x => x.EntityId);
|
||||
|
||||
//foreach (var taggedEntity in allExportedTaggedEntities)
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
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;
|
||||
using Umbraco.Cms.Web.Common.DependencyInjection;
|
||||
|
||||
namespace Umbraco.Cms.Core.PropertyEditors
|
||||
{
|
||||
@@ -27,7 +29,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
|
||||
[Obsolete("Please use constructor that takes an IEditorConfigurationParser instead")]
|
||||
public LabelPropertyEditor(IDataValueEditorFactory dataValueEditorFactory,
|
||||
IIOHelper ioHelper)
|
||||
: base(dataValueEditorFactory)
|
||||
: this(dataValueEditorFactory, ioHelper, StaticServiceProvider.Instance.GetRequiredService<IEditorConfigurationParser>())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace Umbraco.Cms.Core.PublishedCache.Internal
|
||||
Version = Guid.Empty;
|
||||
Path = string.Empty;
|
||||
ContentType = contentType;
|
||||
Properties = Enumerable.Empty<IPublishedProperty>();
|
||||
}
|
||||
|
||||
private Dictionary<string, PublishedCultureInfo>? _cultures;
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
@@ -33,55 +29,16 @@ namespace Umbraco.Extensions
|
||||
UriUtility uriUtility,
|
||||
IPublishedUrlProvider publishedUrlProvider)
|
||||
{
|
||||
if (content == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(content));
|
||||
}
|
||||
|
||||
if (publishedRouter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(publishedRouter));
|
||||
}
|
||||
|
||||
if (umbracoContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(umbracoContext));
|
||||
}
|
||||
|
||||
if (localizationService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(localizationService));
|
||||
}
|
||||
|
||||
if (textService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textService));
|
||||
}
|
||||
|
||||
if (contentService == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(contentService));
|
||||
}
|
||||
|
||||
if (logger == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
if (publishedUrlProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(publishedUrlProvider));
|
||||
}
|
||||
|
||||
if (uriUtility == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(uriUtility));
|
||||
}
|
||||
|
||||
if (variationContextAccessor == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(variationContextAccessor));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(content);
|
||||
ArgumentNullException.ThrowIfNull(publishedRouter);
|
||||
ArgumentNullException.ThrowIfNull(umbracoContext);
|
||||
ArgumentNullException.ThrowIfNull(localizationService);
|
||||
ArgumentNullException.ThrowIfNull(textService);
|
||||
ArgumentNullException.ThrowIfNull(contentService);
|
||||
ArgumentNullException.ThrowIfNull(variationContextAccessor);
|
||||
ArgumentNullException.ThrowIfNull(logger);
|
||||
ArgumentNullException.ThrowIfNull(uriUtility);
|
||||
ArgumentNullException.ThrowIfNull(publishedUrlProvider);
|
||||
|
||||
var result = new List<UrlInfo>();
|
||||
|
||||
@@ -107,9 +64,7 @@ namespace Umbraco.Extensions
|
||||
|
||||
// get all URLs for all cultures
|
||||
// in a HashSet, so de-duplicates too
|
||||
foreach (UrlInfo cultureUrl in await GetContentUrlsByCultureAsync(content, cultures, publishedRouter,
|
||||
umbracoContext, contentService, textService, variationContextAccessor, logger, uriUtility,
|
||||
publishedUrlProvider))
|
||||
foreach (UrlInfo cultureUrl in await GetContentUrlsByCultureAsync(content, cultures, publishedRouter, umbracoContext, contentService, textService, variationContextAccessor, logger, uriUtility, publishedUrlProvider))
|
||||
{
|
||||
urls.Add(cultureUrl);
|
||||
}
|
||||
@@ -120,25 +75,19 @@ namespace Umbraco.Extensions
|
||||
// in some cases there will be the same URL for multiple cultures:
|
||||
// * The entire branch is invariant
|
||||
// * If there are less domain/cultures assigned to the branch than the number of cultures/languages installed
|
||||
|
||||
if (urlGroup.Key)
|
||||
{
|
||||
result.AddRange(urlGroup.LegacyDistinctBy(x => x!.Text.ToUpperInvariant())
|
||||
.OrderBy(x => x.Text).ThenBy(x => x.Culture));
|
||||
result.AddRange(urlGroup.DistinctBy(x => x.Text, StringComparer.OrdinalIgnoreCase).OrderBy(x => x.Text).ThenBy(x => x.Culture));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AddRange(urlGroup);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// get the 'other' URLs - ie not what you'd get with GetUrl() but URLs that would route to the document, nevertheless.
|
||||
// for these 'other' URLs, we don't check whether they are routable, collide, anything - we just report them.
|
||||
foreach (UrlInfo otherUrl in publishedUrlProvider.GetOtherUrls(content.Id).OrderBy(x => x.Text)
|
||||
.ThenBy(x => x.Culture))
|
||||
foreach (UrlInfo otherUrl in publishedUrlProvider.GetOtherUrls(content.Id).OrderBy(x => x.Text).ThenBy(x => x.Culture))
|
||||
{
|
||||
// avoid duplicates
|
||||
if (urls.Add(otherUrl))
|
||||
@@ -202,8 +151,7 @@ namespace Umbraco.Extensions
|
||||
// got a URL, deal with collisions, add URL
|
||||
default:
|
||||
// detect collisions, etc
|
||||
Attempt<UrlInfo?> hasCollision = await DetectCollisionAsync(logger, content, url, culture,
|
||||
umbracoContext, publishedRouter, textService, variationContextAccessor, uriUtility);
|
||||
Attempt<UrlInfo?> hasCollision = await DetectCollisionAsync(logger, content, url, culture, umbracoContext, publishedRouter, textService, variationContextAccessor, uriUtility);
|
||||
if (hasCollision.Success && hasCollision.Result is not null)
|
||||
{
|
||||
result.Add(hasCollision.Result);
|
||||
@@ -220,8 +168,7 @@ namespace Umbraco.Extensions
|
||||
return result;
|
||||
}
|
||||
|
||||
private static UrlInfo HandleCouldNotGetUrl(IContent content, string culture, IContentService contentService,
|
||||
ILocalizedTextService textService)
|
||||
private static UrlInfo HandleCouldNotGetUrl(IContent content, string culture, IContentService contentService, ILocalizedTextService textService)
|
||||
{
|
||||
// document has a published version yet its URL is "#" => a parent must be
|
||||
// unpublished, walk up the tree until we find it, and report.
|
||||
@@ -229,8 +176,8 @@ namespace Umbraco.Extensions
|
||||
do
|
||||
{
|
||||
parent = parent.ParentId > 0 ? contentService.GetParent(parent) : null;
|
||||
} while (parent != null && parent.Published &&
|
||||
(!parent.ContentType.VariesByCulture() || parent.IsCulturePublished(culture)));
|
||||
}
|
||||
while (parent != null && parent.Published && (!parent.ContentType.VariesByCulture() || parent.IsCulturePublished(culture)));
|
||||
|
||||
if (parent == null)
|
||||
{
|
||||
@@ -241,18 +188,22 @@ namespace Umbraco.Extensions
|
||||
if (!parent.Published)
|
||||
{
|
||||
// totally not published
|
||||
return UrlInfo.Message(textService.Localize("content", "parentNotPublished", new[] { parent.Name }),
|
||||
culture);
|
||||
return UrlInfo.Message(textService.Localize("content", "parentNotPublished", new[] { parent.Name }), culture);
|
||||
}
|
||||
|
||||
// culture not published
|
||||
return UrlInfo.Message(textService.Localize("content", "parentCultureNotPublished", new[] { parent.Name }),
|
||||
culture);
|
||||
return UrlInfo.Message(textService.Localize("content", "parentCultureNotPublished", new[] { parent.Name }), culture);
|
||||
}
|
||||
|
||||
private static async Task<Attempt<UrlInfo?>> DetectCollisionAsync(ILogger logger, IContent content, string url,
|
||||
string culture, IUmbracoContext umbracoContext, IPublishedRouter publishedRouter,
|
||||
ILocalizedTextService textService, IVariationContextAccessor variationContextAccessor,
|
||||
private static async Task<Attempt<UrlInfo?>> DetectCollisionAsync(
|
||||
ILogger logger,
|
||||
IContent content,
|
||||
string url,
|
||||
string culture,
|
||||
IUmbracoContext umbracoContext,
|
||||
IPublishedRouter publishedRouter,
|
||||
ILocalizedTextService textService,
|
||||
IVariationContextAccessor variationContextAccessor,
|
||||
UriUtility uriUtility)
|
||||
{
|
||||
// test for collisions on the 'main' URL
|
||||
@@ -264,14 +215,11 @@ namespace Umbraco.Extensions
|
||||
|
||||
uri = uriUtility.UriToUmbraco(uri);
|
||||
IPublishedRequestBuilder builder = await publishedRouter.CreateRequestAsync(uri);
|
||||
IPublishedRequest pcr =
|
||||
await publishedRouter.RouteRequestAsync(builder, new RouteRequestOptions(RouteDirection.Outbound));
|
||||
IPublishedRequest pcr = await publishedRouter.RouteRequestAsync(builder, new RouteRequestOptions(RouteDirection.Outbound));
|
||||
|
||||
if (!pcr.HasPublishedContent())
|
||||
{
|
||||
const string logMsg = nameof(DetectCollisionAsync) +
|
||||
" did not resolve a content item for original url: {Url}, translated to {TranslatedUrl} and culture: {Culture}";
|
||||
|
||||
const string logMsg = nameof(DetectCollisionAsync) + " did not resolve a content item for original url: {Url}, translated to {TranslatedUrl} and culture: {Culture}";
|
||||
logger.LogDebug(logMsg, url, uri, culture);
|
||||
|
||||
var urlInfo = UrlInfo.Message(textService.Localize("content", "routeErrorCannotRoute"), culture);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Web.Common.DependencyInjection;
|
||||
|
||||
namespace Umbraco.Cms.Core.Services.Implement
|
||||
{
|
||||
@@ -13,6 +15,7 @@ namespace Umbraco.Cms.Core.Services.Implement
|
||||
// Scheduled for removal in v12
|
||||
[Obsolete("Please use the contructor that takes an IIpadressUtilities instead")]
|
||||
public BasicAuthService(IOptionsMonitor<BasicAuthSettings> optionsMonitor)
|
||||
: this(optionsMonitor, StaticServiceProvider.Instance.GetRequiredService<IIpAddressUtilities>())
|
||||
{
|
||||
_basicAuthSettings = optionsMonitor.CurrentValue;
|
||||
|
||||
|
||||
@@ -1377,7 +1377,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
/// </remarks>
|
||||
private PublishResult CommitDocumentChangesInternal(ICoreScope scope, IContent content,
|
||||
EventMessages eventMessages, IReadOnlyCollection<ILanguage> allLangs,
|
||||
IDictionary<string, object>? notificationState,
|
||||
IDictionary<string, object?>? notificationState,
|
||||
int userId = Constants.Security.SuperUserId,
|
||||
bool branchOne = false, bool branchRoot = false)
|
||||
{
|
||||
@@ -3036,7 +3036,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
private PublishResult StrategyCanPublish(ICoreScope scope, IContent content, bool checkPath,
|
||||
IReadOnlyList<string>? culturesPublishing,
|
||||
IReadOnlyCollection<string>? culturesUnpublishing, EventMessages evtMsgs,
|
||||
IReadOnlyCollection<ILanguage> allLangs, IDictionary<string, object>? notificationState)
|
||||
IReadOnlyCollection<ILanguage> allLangs, IDictionary<string, object?>? notificationState)
|
||||
{
|
||||
// raise Publishing notification
|
||||
if (scope.Notifications.PublishCancelable(
|
||||
|
||||
@@ -304,7 +304,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
return Enumerable.Empty<TItem>();
|
||||
}
|
||||
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope())
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
|
||||
|
||||
{
|
||||
scope.ReadLock(ReadLockIds);
|
||||
@@ -623,7 +623,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
|
||||
scope.Notifications.Publish(GetContentTypeChangedNotification(changes, eventMessages));
|
||||
|
||||
DeletedNotification<TItem> deletedNotification = GetDeletedNotification(deleted.LegacyDistinctBy(x => x!.Id), eventMessages);
|
||||
DeletedNotification<TItem> deletedNotification = GetDeletedNotification(deleted.DistinctBy(x => x.Id), eventMessages);
|
||||
deletedNotification.WithStateFrom(deletingNotification);
|
||||
scope.Notifications.Publish(deletedNotification);
|
||||
|
||||
@@ -649,9 +649,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
scope.WriteLock(WriteLockIds);
|
||||
|
||||
// all descendants are going to be deleted
|
||||
TItem[] allDescendantsAndSelf = itemsA.SelectMany(xx => GetDescendants(xx.Id, true))
|
||||
.LegacyDistinctBy(x => x!.Id)
|
||||
.ToArray();
|
||||
TItem[] allDescendantsAndSelf = itemsA.SelectMany(xx => GetDescendants(xx.Id, true)).DistinctBy(x => x.Id).ToArray();
|
||||
TItem[] deleted = allDescendantsAndSelf;
|
||||
|
||||
// all impacted (through composition) probably lose some properties
|
||||
@@ -681,7 +679,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
|
||||
scope.Notifications.Publish(GetContentTypeChangedNotification(changes, eventMessages));
|
||||
|
||||
DeletedNotification<TItem> deletedNotification = GetDeletedNotification(deleted.LegacyDistinctBy(x => x!.Id), eventMessages);
|
||||
DeletedNotification<TItem> deletedNotification = GetDeletedNotification(deleted.DistinctBy(x => x.Id), eventMessages);
|
||||
deletedNotification.WithStateFrom(deletingNotification);
|
||||
scope.Notifications.Publish(deletedNotification);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Exceptions;
|
||||
@@ -12,6 +13,7 @@ using Umbraco.Cms.Core.PropertyEditors;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
using Umbraco.Cms.Core.Strings;
|
||||
using Umbraco.Cms.Web.Common.DependencyInjection;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Core.Services.Implement
|
||||
@@ -32,7 +34,9 @@ namespace Umbraco.Cms.Core.Services.Implement
|
||||
private readonly ILocalizationService _localizationService;
|
||||
private readonly IShortStringHelper _shortStringHelper;
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
private readonly IEditorConfigurationParser _editorConfigurationParser;
|
||||
|
||||
[Obsolete("Please use constructor that takes an ")]
|
||||
public DataTypeService(
|
||||
IDataValueEditorFactory dataValueEditorFactory,
|
||||
ICoreScopeProvider provider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory,
|
||||
@@ -41,6 +45,45 @@ namespace Umbraco.Cms.Core.Services.Implement
|
||||
IIOHelper ioHelper, ILocalizedTextService localizedTextService, ILocalizationService localizationService,
|
||||
IShortStringHelper shortStringHelper,
|
||||
IJsonSerializer jsonSerializer)
|
||||
: this(
|
||||
dataValueEditorFactory,
|
||||
provider,
|
||||
loggerFactory,
|
||||
eventMessagesFactory,
|
||||
dataTypeRepository,
|
||||
dataTypeContainerRepository,
|
||||
auditRepository,
|
||||
entityRepository,
|
||||
contentTypeRepository,
|
||||
ioHelper,
|
||||
localizedTextService,
|
||||
localizationService,
|
||||
shortStringHelper,
|
||||
jsonSerializer,
|
||||
StaticServiceProvider.Instance.GetRequiredService<IEditorConfigurationParser>())
|
||||
{
|
||||
_dataValueEditorFactory = dataValueEditorFactory;
|
||||
_dataTypeRepository = dataTypeRepository;
|
||||
_dataTypeContainerRepository = dataTypeContainerRepository;
|
||||
_auditRepository = auditRepository;
|
||||
_entityRepository = entityRepository;
|
||||
_contentTypeRepository = contentTypeRepository;
|
||||
_ioHelper = ioHelper;
|
||||
_localizedTextService = localizedTextService;
|
||||
_localizationService = localizationService;
|
||||
_shortStringHelper = shortStringHelper;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
}
|
||||
|
||||
public DataTypeService(
|
||||
IDataValueEditorFactory dataValueEditorFactory,
|
||||
ICoreScopeProvider provider, ILoggerFactory loggerFactory, IEventMessagesFactory eventMessagesFactory,
|
||||
IDataTypeRepository dataTypeRepository, IDataTypeContainerRepository dataTypeContainerRepository,
|
||||
IAuditRepository auditRepository, IEntityRepository entityRepository, IContentTypeRepository contentTypeRepository,
|
||||
IIOHelper ioHelper, ILocalizedTextService localizedTextService, ILocalizationService localizationService,
|
||||
IShortStringHelper shortStringHelper,
|
||||
IJsonSerializer jsonSerializer,
|
||||
IEditorConfigurationParser editorConfigurationParser)
|
||||
: base(provider, loggerFactory, eventMessagesFactory)
|
||||
{
|
||||
_dataValueEditorFactory = dataValueEditorFactory;
|
||||
@@ -54,6 +97,7 @@ namespace Umbraco.Cms.Core.Services.Implement
|
||||
_localizationService = localizationService;
|
||||
_shortStringHelper = shortStringHelper;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
_editorConfigurationParser = editorConfigurationParser;
|
||||
}
|
||||
|
||||
#region Containers
|
||||
@@ -320,15 +364,11 @@ namespace Umbraco.Cms.Core.Services.Implement
|
||||
/// </summary>
|
||||
/// <param name="ids">Optional array of Ids</param>
|
||||
/// <returns>An enumerable list of <see cref="IDataType"/> objects</returns>
|
||||
public IEnumerable<IDataType>? GetAll(params int[] ids)
|
||||
public IEnumerable<IDataType> GetAll(params int[] ids)
|
||||
{
|
||||
using (var scope = ScopeProvider.CreateCoreScope(autoComplete: true))
|
||||
{
|
||||
var dataTypes = _dataTypeRepository.GetMany(ids);
|
||||
if (dataTypes is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ConvertMissingEditorsOfDataTypesToLabels(dataTypes);
|
||||
return dataTypes;
|
||||
@@ -353,7 +393,7 @@ namespace Umbraco.Cms.Core.Services.Implement
|
||||
.Where(x => x.Editor is MissingPropertyEditor);
|
||||
foreach (var dataType in dataTypesWithMissingEditors)
|
||||
{
|
||||
dataType.Editor = new LabelPropertyEditor(_dataValueEditorFactory, _ioHelper);
|
||||
dataType.Editor = new LabelPropertyEditor(_dataValueEditorFactory, _ioHelper, _editorConfigurationParser);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
@@ -642,9 +643,12 @@ namespace Umbraco.Cms.Core.Services
|
||||
|
||||
public IEnumerable<string> GetPartialViewSnippetNames(params string[] filterNames)
|
||||
{
|
||||
var snippetPath = _hostingEnvironment.MapPathContentRoot($"{Constants.SystemDirectories.Umbraco}/PartialViewMacros/Templates/");
|
||||
var files = Directory.GetFiles(snippetPath, "*.cshtml")
|
||||
.Select(Path.GetFileNameWithoutExtension)
|
||||
var snippetProvider =
|
||||
new EmbeddedFileProvider(this.GetType().Assembly, "Umbraco.Cms.Core.EmbeddedResources.Snippets");
|
||||
|
||||
var files = snippetProvider.GetDirectoryContents(string.Empty)
|
||||
.Where(x => !x.IsDirectory && x.Name.EndsWith(".cshtml"))
|
||||
.Select(x => Path.GetFileNameWithoutExtension(x.Name))
|
||||
.Except(filterNames, StringComparer.InvariantCultureIgnoreCase)
|
||||
.ToArray();
|
||||
|
||||
@@ -977,14 +981,18 @@ namespace Umbraco.Cms.Core.Services
|
||||
throw new ArgumentOutOfRangeException(nameof(partialViewType));
|
||||
}
|
||||
|
||||
var snippetProvider =
|
||||
new EmbeddedFileProvider(this.GetType().Assembly, "Umbraco.Cms.Core.EmbeddedResources.Snippets");
|
||||
|
||||
var file = snippetProvider.GetDirectoryContents(string.Empty).FirstOrDefault(x=>x.Exists && x.Name.Equals(snippetName + ".cshtml"));
|
||||
|
||||
// Try and get the snippet path
|
||||
Attempt<string> snippetPathAttempt = TryGetSnippetPath(snippetName);
|
||||
if (snippetPathAttempt.Success == false)
|
||||
if (file is null)
|
||||
{
|
||||
throw new InvalidOperationException("Could not load snippet with name " + snippetName);
|
||||
}
|
||||
|
||||
using (var snippetFile = new StreamReader(System.IO.File.OpenRead(snippetPathAttempt.Result!)))
|
||||
using (var snippetFile = new StreamReader(file.CreateReadStream()))
|
||||
{
|
||||
var snippetContent = snippetFile.ReadToEnd().Trim();
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
/// </summary>
|
||||
/// <param name="ids">Optional array of Ids</param>
|
||||
/// <returns>An enumerable list of <see cref="IDataType"/> objects</returns>
|
||||
IEnumerable<IDataType>? GetAll(params int[] ids);
|
||||
IEnumerable<IDataType> GetAll(params int[] ids);
|
||||
|
||||
/// <summary>
|
||||
/// Saves an <see cref="IDataType"/>
|
||||
|
||||
@@ -5,6 +5,8 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.Extensions.FileProviders.Internal;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
using Umbraco.Extensions;
|
||||
@@ -17,6 +19,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
public class LocalizedTextServiceFileSources
|
||||
{
|
||||
private readonly ILogger<LocalizedTextServiceFileSources> _logger;
|
||||
private readonly IDirectoryContents _directoryContents;
|
||||
private readonly IAppPolicyCache _cache;
|
||||
private readonly IEnumerable<LocalizedTextServiceSupplementaryFileSource>? _supplementFileSources;
|
||||
private readonly DirectoryInfo? _fileSourceFolder;
|
||||
@@ -26,6 +29,21 @@ namespace Umbraco.Cms.Core.Services
|
||||
|
||||
private readonly Lazy<Dictionary<CultureInfo, Lazy<XDocument>>> _xmlSources;
|
||||
|
||||
[Obsolete("Use ctor with all params. This will be removed in Umbraco 12")]
|
||||
public LocalizedTextServiceFileSources(
|
||||
ILogger<LocalizedTextServiceFileSources> logger,
|
||||
AppCaches appCaches,
|
||||
DirectoryInfo fileSourceFolder,
|
||||
IEnumerable<LocalizedTextServiceSupplementaryFileSource> supplementFileSources)
|
||||
:this(
|
||||
logger,
|
||||
appCaches,
|
||||
fileSourceFolder,
|
||||
supplementFileSources, new NotFoundDirectoryContents())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used to configure the file sources with the main file sources shipped with Umbraco and also including supplemental/plugin based
|
||||
/// localization files. The supplemental files will be loaded in and merged in after the primary files.
|
||||
@@ -39,36 +57,37 @@ namespace Umbraco.Cms.Core.Services
|
||||
ILogger<LocalizedTextServiceFileSources> logger,
|
||||
AppCaches appCaches,
|
||||
DirectoryInfo fileSourceFolder,
|
||||
IEnumerable<LocalizedTextServiceSupplementaryFileSource> supplementFileSources)
|
||||
IEnumerable<LocalizedTextServiceSupplementaryFileSource> supplementFileSources,
|
||||
IDirectoryContents directoryContents
|
||||
)
|
||||
{
|
||||
if (logger == null) throw new ArgumentNullException("logger");
|
||||
if (appCaches == null) throw new ArgumentNullException("cache");
|
||||
if (fileSourceFolder == null) throw new ArgumentNullException("fileSourceFolder");
|
||||
|
||||
_logger = logger;
|
||||
_directoryContents = directoryContents;
|
||||
_cache = appCaches.RuntimeCache;
|
||||
|
||||
if (fileSourceFolder.Exists == false)
|
||||
{
|
||||
_logger.LogWarning("The folder does not exist: {FileSourceFolder}, therefore no sources will be discovered", fileSourceFolder.FullName);
|
||||
}
|
||||
else
|
||||
{
|
||||
_fileSourceFolder = fileSourceFolder;
|
||||
_supplementFileSources = supplementFileSources;
|
||||
}
|
||||
_fileSourceFolder = fileSourceFolder;
|
||||
_supplementFileSources = supplementFileSources;
|
||||
|
||||
//Create the lazy source for the _xmlSources
|
||||
_xmlSources = new Lazy<Dictionary<CultureInfo, Lazy<XDocument>>>(() =>
|
||||
{
|
||||
var result = new Dictionary<CultureInfo, Lazy<XDocument>>();
|
||||
|
||||
if (_fileSourceFolder == null) return result;
|
||||
|
||||
foreach (var fileInfo in _fileSourceFolder.GetFiles("*.xml"))
|
||||
var files = GetLanguageFiles();
|
||||
|
||||
if (!files.Any())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (var fileInfo in files)
|
||||
{
|
||||
var localCopy = fileInfo;
|
||||
var filename = Path.GetFileNameWithoutExtension(localCopy.FullName).Replace("_", "-");
|
||||
var filename = Path.GetFileNameWithoutExtension(localCopy.Name).Replace("_", "-");
|
||||
|
||||
// TODO: Fix this nonsense... would have to wait until v8 to store the language files with their correct
|
||||
// names instead of storing them as 2 letters but actually having a 4 letter culture. So now, we
|
||||
@@ -80,7 +99,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
{
|
||||
//we need to open the file to see if we can read it's 'real' culture, we'll use XmlReader since we don't
|
||||
//want to load in the entire doc into mem just to read a single value
|
||||
using (var fs = fileInfo.OpenRead())
|
||||
using (var fs = fileInfo.CreateReadStream())
|
||||
using (var reader = XmlReader.Create(fs))
|
||||
{
|
||||
if (reader.IsStartElement())
|
||||
@@ -98,7 +117,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
}
|
||||
catch (CultureNotFoundException)
|
||||
{
|
||||
_logger.LogWarning("The culture {CultureValue} found in the file {CultureFile} is not a valid culture", cultureVal, fileInfo.FullName);
|
||||
_logger.LogWarning("The culture {CultureValue} found in the file {CultureFile} is not a valid culture", cultureVal, fileInfo.Name);
|
||||
//If the culture in the file is invalid, we'll just hope the file name is a valid culture below, otherwise
|
||||
// an exception will be thrown.
|
||||
}
|
||||
@@ -119,7 +138,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
XDocument xdoc;
|
||||
|
||||
//load in primary
|
||||
using (var fs = localCopy.OpenRead())
|
||||
using (var fs = localCopy.CreateReadStream())
|
||||
{
|
||||
xdoc = XDocument.Load(fs);
|
||||
}
|
||||
@@ -128,7 +147,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
MergeSupplementaryFiles(culture, xdoc);
|
||||
|
||||
return xdoc;
|
||||
}, isSliding: true, timeout: TimeSpan.FromMinutes(10), dependentFiles: new[] { localCopy.FullName })!);
|
||||
}, isSliding: true, timeout: TimeSpan.FromMinutes(10))!);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
@@ -136,6 +155,30 @@ namespace Umbraco.Cms.Core.Services
|
||||
|
||||
}
|
||||
|
||||
private IEnumerable<IFileInfo> GetLanguageFiles()
|
||||
{
|
||||
var result = new List<IFileInfo>();
|
||||
|
||||
if (_fileSourceFolder is not null && _fileSourceFolder.Exists)
|
||||
{
|
||||
|
||||
result.AddRange(
|
||||
new PhysicalDirectoryContents(_fileSourceFolder.FullName)
|
||||
.Where(x => !x.IsDirectory && x.Name.EndsWith(".xml"))
|
||||
);
|
||||
}
|
||||
|
||||
if (_directoryContents.Exists)
|
||||
{
|
||||
result.AddRange(
|
||||
_directoryContents
|
||||
.Where(x => !x.IsDirectory && x.Name.EndsWith(".xml"))
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user