Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b3cc5f9183 | |||
| ce99ec6d31 | |||
| 88d61a4d37 | |||
| 75f4535157 | |||
| 78bf75615f | |||
| 51649879cd | |||
| ab050eb7ac | |||
| 2461924a89 |
+6
-12
@@ -1,16 +1,10 @@
|
||||
# editorconfig.org
|
||||
root=true
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Default settings:
|
||||
# A newline ending every file
|
||||
# Use 4 spaces as indentation
|
||||
[*]
|
||||
insert_final_newline = true
|
||||
end_of_line = lf
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# Trim trailing whitespace, limited support.
|
||||
# https://github.com/editorconfig/editorconfig/wiki/Property-research:-Trim-trailing-spaces
|
||||
trim_trailing_whitespace = true
|
||||
[*.{cs,cshtml,csx,vb,vbx,vbhtml,fs,fsx,txt,ps1,sql}]
|
||||
indent_size = 4
|
||||
@@ -1,49 +0,0 @@
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
||||
|
||||
*.jpg binary
|
||||
*.png binary
|
||||
*.gif binary
|
||||
|
||||
*.cs text=auto diff=csharp
|
||||
*.vb text=auto
|
||||
*.c text=auto
|
||||
*.cpp text=auto
|
||||
*.cxx text=auto
|
||||
*.h text=auto
|
||||
*.hxx text=auto
|
||||
*.py text=auto
|
||||
*.rb text=auto
|
||||
*.java text=auto
|
||||
*.html text=auto
|
||||
*.htm text=auto
|
||||
*.css text=auto
|
||||
*.scss text=auto
|
||||
*.sass text=auto
|
||||
*.less text=auto
|
||||
*.js text=auto
|
||||
*.lisp text=auto
|
||||
*.clj text=auto
|
||||
*.sql text=auto
|
||||
*.php text=auto
|
||||
*.lua text=auto
|
||||
*.m text=auto
|
||||
*.asm text=auto
|
||||
*.erl text=auto
|
||||
*.fs text=auto
|
||||
*.fsx text=auto
|
||||
*.hs text=auto
|
||||
|
||||
*.csproj text=auto merge=union
|
||||
*.vbproj text=auto merge=union
|
||||
*.fsproj text=auto merge=union
|
||||
*.dbproj text=auto merge=union
|
||||
*.sln text=auto eol=crlf merge=union
|
||||
+1
-2
@@ -139,5 +139,4 @@ src/PrecompiledWeb/*
|
||||
|
||||
build.out/
|
||||
build.tmp/
|
||||
build/Modules/*/temp/
|
||||
/src/.idea/*
|
||||
build/Modules/*/temp/
|
||||
@@ -14,43 +14,6 @@ By default, this builds the current version. It is possible to specify a differe
|
||||
|
||||
Valid version strings are defined in the `Set-UmbracoVersion` documentation below.
|
||||
|
||||
## PowerShell Quirks
|
||||
|
||||
There is a good chance that running `build.ps1` ends up in error, with messages such as
|
||||
|
||||
>The file ...\build\build.ps1 is not digitally signed. You cannot run this script on the current system. For more information about running scripts and setting execution policy, see about_Execution_Policies.
|
||||
|
||||
PowerShell has *Execution Policies* that may prevent the script from running. You can check the current policies with:
|
||||
|
||||
PS> Get-ExecutionPolicy -List
|
||||
|
||||
Scope ExecutionPolicy
|
||||
----- ---------------
|
||||
MachinePolicy Undefined
|
||||
UserPolicy Undefined
|
||||
Process Undefined
|
||||
CurrentUser Undefined
|
||||
LocalMachine RemoteSigned
|
||||
|
||||
Policies can be `Restricted`, `AllSigned`, `RemoteSigned`, `Unrestricted` and `Bypass`. Scopes can be `MachinePolicy`, `UserPolicy`, `Process`, `CurrentUser`, `LocalMachine`. You need the current policy to be `RemoteSigned`—as long as it is `Undefined`, the script cannot run. You can change the current user policy with:
|
||||
|
||||
PS> Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
|
||||
|
||||
Alternatively, you can do it at machine level, from within an elevated PowerShell session:
|
||||
|
||||
PS> Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy RemoteSigned
|
||||
|
||||
And *then* the script should run. It *might* however still complain about executing scripts, with messages such as:
|
||||
|
||||
>Security warning - Run only scripts that you trust. While scripts from the internet can be useful, this script can potentially harm your computer. If you trust this script, use the Unblock-File cmdlet to allow the script to run without this warning message. Do you want to run ...\build\build.ps1?
|
||||
[D] Do not run [R] Run once [S] Suspend [?] Help (default is "D"):
|
||||
|
||||
This is usually caused by the scripts being *blocked*. And that usually happens when the source code has been downloaded as a Zip file. When Windows downloads Zip files, they are marked as *blocked* (technically, they have a Zone.Identifier alternate data stream, with a value of "3" to indicate that they were downloaded from the Internet). And when such a Zip file is un-zipped, each and every single file is also marked as blocked.
|
||||
|
||||
The best solution is to unblock the Zip file before un-zipping: right-click the files, open *Properties*, and there should be a *Unblock* checkbox at the bottom of the dialog. If, however, the Zip file has already been un-zipped, it is possible to recursively unblock all files from PowerShell with:
|
||||
|
||||
PS> Get-ChildItem -Recurse *.* | Unblock-File
|
||||
|
||||
## Notes
|
||||
|
||||
Git might have issues dealing with long file paths during build. You may want/need to enable `core.longpaths` support (see [this page](https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path) for details).
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
[](https://ci.appveyor.com/project/Umbraco/umbraco-cms-b2cri/branch/dev-v7)
|
||||
[](https://ci.appveyor.com/project/Umbraco/umbraco-cms-hs8dx/branch/dev-v7)
|
||||
|
||||
Umbraco CMS
|
||||
===========
|
||||
The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 443,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
|
||||
The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 390,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
|
||||
|
||||
[](https://vimeo.com/172382998/)
|
||||
|
||||
@@ -12,7 +12,7 @@ Umbraco is a free open source Content Management System built on the ASP.NET pla
|
||||
|
||||
## Building Umbraco from source ##
|
||||
|
||||
The easiest way to get started is to run `build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `gulp dev` in `src\Umbraco.Web.UI.Client`. See [this page](BUILD.md) for more details.
|
||||
The easiest way to get started is to run `build/build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `gulp dev` in `src\Umbraco.Web.UI.Client`.
|
||||
|
||||
Note that you can always [download a nightly build](http://nightly.umbraco.org/?container=umbraco-750) so you don't have to build the code yourself.
|
||||
|
||||
@@ -26,7 +26,7 @@ For the first time on the Microsoft platform, there is a free user and developer
|
||||
|
||||
Umbraco is not only loved by developers, but is a content editors dream. Enjoy intuitive editing tools, media management, responsive views and approval workflows to send your content live.
|
||||
|
||||
Used by more than 443,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scales. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 220,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
|
||||
Used by more than 350,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scales. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 200,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
|
||||
|
||||
To view more examples, please visit [https://umbraco.com/why-umbraco/#caseStudies](https://umbraco.com/why-umbraco/#caseStudies)
|
||||
|
||||
|
||||
@@ -10,5 +10,6 @@ IF ERRORLEVEL 1 (
|
||||
:error
|
||||
ECHO.
|
||||
ECHO Can not run build\build.ps1.
|
||||
ECHO If this is due to a SecurityError then please refer to BUILD.md for help!
|
||||
ECHO If this is due to a SecurityError then make sure to run the following command from an administrator command prompt:
|
||||
ECHO.
|
||||
ECHO powershell Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
|
||||
@@ -44,7 +44,7 @@ function Build-UmbracoDocs
|
||||
# change baseUrl
|
||||
$baseUrl = "https://our.umbraco.org/apidocs/ui/"
|
||||
$indexPath = "$src/Umbraco.Web.UI.Client/docs/api/index.html"
|
||||
(Get-Content $indexPath).Replace("origin + location.href.substr(origin.length).replace(rUrl, indexFile)", "'$baseUrl'") `
|
||||
(Get-Content $indexPath).Replace("location.href.replace(rUrl, indexFile)", "'$baseUrl'") `
|
||||
| Set-Content $indexPath
|
||||
|
||||
# restore
|
||||
@@ -100,9 +100,8 @@ function Get-DocFx($uenv, $buildTemp)
|
||||
$docFx = "$buildTemp\docfx"
|
||||
if (-not (test-path $docFx))
|
||||
{
|
||||
Write-Host "Download DocFx..."
|
||||
$source = "https://github.com/dotnet/docfx/releases/download/v2.19.2/docfx.zip"
|
||||
Write-Host "Download DocFx from $source"
|
||||
|
||||
Invoke-WebRequest $source -OutFile "$buildTemp\docfx.zip"
|
||||
|
||||
&$uenv.Zip x "$buildTemp\docfx.zip" -o"$buildTemp\docfx" -aos > $nul
|
||||
|
||||
@@ -239,18 +239,18 @@ function Prepare-Tests
|
||||
|
||||
# data
|
||||
Write-Host "Copy data files"
|
||||
if (-Not (Test-Path -Path "$tmp\tests\Packaging" ) )
|
||||
if( -Not (Test-Path -Path "$tmp\tests\Packaging" ) )
|
||||
{
|
||||
Write-Host "Create packaging directory"
|
||||
mkdir "$tmp\tests\Packaging" > $null
|
||||
New-Item -ItemType directory -Path "$tmp\tests\Packaging"
|
||||
}
|
||||
Copy-Files "$src\Umbraco.Tests\Packaging\Packages" "*" "$tmp\tests\Packaging\Packages"
|
||||
|
||||
# required for package install tests
|
||||
if (-Not (Test-Path -Path "$tmp\tests\bin" ) )
|
||||
if( -Not (Test-Path -Path "$tmp\tests\bin" ) )
|
||||
{
|
||||
Write-Host "Create bin directory"
|
||||
mkdir "$tmp\tests\bin" > $null
|
||||
New-Item -ItemType directory -Path "$tmp\tests\bin"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,6 +377,14 @@ function Prepare-Packages
|
||||
Copy-Files "$src\Umbraco.Web.UI\umbraco\lib" "*" "$tmp\WebApp\umbraco\lib"
|
||||
Copy-Files "$src\Umbraco.Web.UI\umbraco\views" "*" "$tmp\WebApp\umbraco\views"
|
||||
Copy-Files "$src\Umbraco.Web.UI\umbraco\preview" "*" "$tmp\WebApp\umbraco\preview"
|
||||
|
||||
# prepare WebPI
|
||||
Write-Host "Prepare WebPI"
|
||||
Remove-Directory "$tmp\WebPi"
|
||||
mkdir "$tmp\WebPi" > $null
|
||||
mkdir "$tmp\WebPi\umbraco" > $null
|
||||
Copy-Files "$tmp\WebApp" "*" "$tmp\WebPi\umbraco"
|
||||
Copy-Files "$src\WebPi" "*" "$tmp\WebPi"
|
||||
}
|
||||
|
||||
#
|
||||
@@ -405,6 +413,17 @@ function Package-Zip
|
||||
"$tmp\WebApp\*" `
|
||||
"-x!dotless.Core.*" "-x!Content_Types.xml" "-x!*.pdb"`
|
||||
> $null
|
||||
|
||||
Write-Host "Zip WebPI"
|
||||
&$uenv.Zip a -r "$out\UmbracoCms.WebPI.$($version.Semver).zip" "-x!*.pdb"`
|
||||
"$tmp\WebPi\*" `
|
||||
"-x!dotless.Core.*" `
|
||||
> $null
|
||||
|
||||
# hash the webpi file
|
||||
Write-Host "Hash WebPI"
|
||||
$hash = Get-FileHash "$out\UmbracoCms.WebPI.$($version.Semver).zip"
|
||||
Write $hash | out-file "$out\webpihash.txt" -encoding ascii
|
||||
}
|
||||
|
||||
#
|
||||
@@ -448,24 +467,6 @@ function Restore-NuGet
|
||||
&$uenv.NuGet restore "$src\Umbraco.sln" > "$tmp\nuget.restore.log"
|
||||
}
|
||||
|
||||
#
|
||||
# Copies the Azure Gallery script to output
|
||||
#
|
||||
function Prepare-AzureGallery
|
||||
{
|
||||
param (
|
||||
$uenv # an Umbraco build environment (see Get-UmbracoBuildEnv)
|
||||
)
|
||||
|
||||
$src = "$($uenv.SolutionRoot)\src"
|
||||
$tmp = "$($uenv.SolutionRoot)\build.tmp"
|
||||
$out = "$($uenv.SolutionRoot)\build.out"
|
||||
$psScript = "$($uenv.SolutionRoot)\build\azuregalleryrelease.ps1"
|
||||
|
||||
Write-Host ">> Copy azuregalleryrelease.ps1 to output folder"
|
||||
Copy-Item $psScript $out
|
||||
}
|
||||
|
||||
#
|
||||
# Creates the NuGet packages
|
||||
#
|
||||
@@ -575,10 +576,6 @@ function Build-Umbraco
|
||||
{
|
||||
Compile-Belle $uenv $version
|
||||
}
|
||||
elseif ($target -eq "prepare-azuregallery")
|
||||
{
|
||||
Prepare-AzureGallery $uenv
|
||||
}
|
||||
elseif ($target -eq "all")
|
||||
{
|
||||
Prepare-Build $uenv
|
||||
@@ -593,7 +590,6 @@ function Build-Umbraco
|
||||
Verify-NuGet $uenv
|
||||
Prepare-NuGet $uenv
|
||||
Package-NuGet $uenv $version
|
||||
Prepare-AzureGallery $uenv
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,3 +1,28 @@
|
||||
# returns a string containing the hash of $file
|
||||
function Get-FileHash($file)
|
||||
{
|
||||
try
|
||||
{
|
||||
$crypto = new-object System.Security.Cryptography.SHA1CryptoServiceProvider
|
||||
$stream = [System.IO.File]::OpenRead($file)
|
||||
$hash = $crypto.ComputeHash($stream)
|
||||
$text = ""
|
||||
$hash | foreach `
|
||||
{
|
||||
$text = $text + $_.ToString("x2")
|
||||
}
|
||||
return $text
|
||||
}
|
||||
finally
|
||||
{
|
||||
if ($stream)
|
||||
{
|
||||
$stream.Dispose()
|
||||
}
|
||||
$crypto.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
# returns the full path if $file is relative to $pwd
|
||||
function Get-FullPath($file)
|
||||
{
|
||||
|
||||
@@ -21,18 +21,20 @@
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.3,6.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.1, 3.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Security.Cookies" version="[3.1.0, 4.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Security.OAuth" version="[3.1.0, 4.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[3.1.0, 4.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Security.Cookies" version="[3.0.1, 4.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Security.OAuth" version="[3.0.1, 4.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[3.0.1, 4.0.0)" />
|
||||
<dependency id="MiniProfiler" version="[2.1.0, 3.0.0)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.4.9.5, 2.0.0)" />
|
||||
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
|
||||
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.9.9, 7.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.9.6, 2.0.0)" />
|
||||
<dependency id="xmlrpcnet" version="[2.5.0, 3.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.9.2, 2.0.0)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
|
||||
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
|
||||
<dependency id="Examine" version="[0.1.89, 1.0.0)" />
|
||||
<dependency id="Examine" version="[0.1.88, 1.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[2.5.6, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.8.7, 5.0.0)" />
|
||||
<dependency id="semver" version="[1.1.2, 3.0.0)" />
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<dependencies>
|
||||
<dependency id="UmbracoCms.Core" version="[$version$]" />
|
||||
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
|
||||
<dependency id="Umbraco.ModelsBuilder" version="[3.0.10, 4.0.0)" />
|
||||
<dependency id="Umbraco.ModelsBuilder" version="[3.0.7, 4.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.3.1, 3.0.0)" />
|
||||
</dependencies>
|
||||
@@ -32,7 +32,6 @@
|
||||
<file src="$BuildTmp$\WebApp\bin\amd64\**" target="UmbracoFiles\bin\amd64" />
|
||||
<file src="$BuildTmp$\WebApp\bin\x86\**" target="UmbracoFiles\bin\x86" />
|
||||
<file src="$BuildTmp$\WebApp\config\splashes\**" target="UmbracoFiles\Config\splashes" />
|
||||
<file src="$BuildTmp$\WebApp\config\BackOfficeTours\**" target="Content\Config\BackOfficeTours" />
|
||||
<file src="$BuildTmp$\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
|
||||
<file src="$BuildTmp$\WebApp\umbraco_client\**" target="UmbracoFiles\umbraco_client" />
|
||||
<file src="$BuildTmp$\WebApp\Media\Web.config" target="Content\Media\Web.config" />
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
*** IMPORTANT NOTICE FOR 7.7 UPGRADES ***
|
||||
*** IMPORTANT NOTICE FOR 7.6 UPGRADES ***
|
||||
|
||||
Be sure to read the version specific upgrade information before proceeding:
|
||||
https://our.umbraco.org/documentation/Getting-Started/Setup/Upgrading/version-specific#version-7-7-0
|
||||
https://our.umbraco.org/documentation/Getting-Started/Setup/Upgrading/version-specific#version-7-6-0
|
||||
|
||||
Depending on the version you are upgrading from, you may need to make some changes to your web.config
|
||||
and you will need to be aware of the breaking changes listed there to see if these affect your installation.
|
||||
You will most likely need to make some changes to your web.config and you will need to be
|
||||
aware of the breaking changes listed there to see if these affect your installation.
|
||||
|
||||
|
||||
Don't forget to build!
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
<section name="BaseRestExtensions" type="Umbraco.Core.Configuration.BaseRest.BaseRestSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="FileSystemProviders" type="Umbraco.Core.Configuration.FileSystemProvidersSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="dashBoard" type="Umbraco.Core.Configuration.Dashboard.DashboardSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="HealthChecks" type="Umbraco.Core.Configuration.HealthChecks.HealthChecksSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
|
||||
@@ -24,7 +23,6 @@
|
||||
<add key="owin:appStartup" value="UmbracoDefaultOwinStartup" xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" />
|
||||
<add key="Umbraco.ModelsBuilder.Enable" value="false" xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" />
|
||||
<add key="Umbraco.ModelsBuilder.ModelsMode" value="Nothing" xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" />
|
||||
<add key="umbracoDefaultUILanguage" value="en-US" xdt:Locator="Match(key)" xdt:Transform="SetAttributes(value)" />
|
||||
</appSettings>
|
||||
|
||||
<umbracoConfiguration xdt:Transform="InsertIfMissing">
|
||||
@@ -32,7 +30,6 @@
|
||||
<BaseRestExtensions configSource="config\BaseRestExtensions.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
|
||||
<FileSystemProviders configSource="config\FileSystemProviders.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
|
||||
<dashBoard configSource="config\Dashboard.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
|
||||
<HealthChecks configSource="config\HealthChecks.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
|
||||
</umbracoConfiguration>
|
||||
|
||||
<FileSystemProviders xdt:Transform="Remove" />
|
||||
@@ -371,19 +368,19 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
|
||||
@@ -98,51 +98,10 @@ if ($project) {
|
||||
$umbracoUIXMLDestination = Join-Path $projectPath "Umbraco\Config\Create\UI.xml"
|
||||
Copy-Item $umbracoUIXMLSource $umbracoUIXMLDestination -Force
|
||||
} else {
|
||||
# This part only runs for upgrades
|
||||
|
||||
$upgradeViewSource = Join-Path $umbracoFolderSource "Views\install\*"
|
||||
$upgradeView = Join-Path $umbracoFolder "Views\install\"
|
||||
Write-Host "Copying2 ${upgradeViewSource} to ${upgradeView}"
|
||||
Copy-Item $upgradeViewSource $upgradeView -Force
|
||||
|
||||
Try
|
||||
{
|
||||
# Disable tours for upgrades, presumably Umbraco experience is already available
|
||||
$umbracoSettingsConfigPath = Join-Path $configFolder "umbracoSettings.config"
|
||||
$content = (Get-Content $umbracoSettingsConfigPath).Replace('<tours enable="true">','<tours enable="false">')
|
||||
# Saves with UTF-8 encoding without BOM which makes sure Umbraco can still read it
|
||||
# Reference: https://stackoverflow.com/a/32951824/5018
|
||||
[IO.File]::WriteAllLines($umbracoSettingsConfigPath, $content)
|
||||
}
|
||||
Catch
|
||||
{
|
||||
# Not a big problem if this fails, let it go
|
||||
}
|
||||
|
||||
Try
|
||||
{
|
||||
$uiXmlConfigPath = Join-Path $umbracoFolder -ChildPath "Config" | Join-Path -ChildPath "create" | Join-Path -ChildPath "UI.xml"
|
||||
$uiXmlFile = Join-Path $umbracoFolder -ChildPath "Config" | Join-Path -ChildPath "create" | Join-Path -ChildPath "UI.xml"
|
||||
|
||||
$uiXml = New-Object System.Xml.XmlDocument
|
||||
$uiXml.PreserveWhitespace = $true
|
||||
|
||||
$uiXml.Load($uiXmlFile)
|
||||
$createExists = $uiXml.SelectNodes("//nodeType[@alias='macros']/tasks/create")
|
||||
|
||||
if($createExists.Count -eq 0)
|
||||
{
|
||||
$macrosTasksNode = $uiXml.SelectNodes("//nodeType[@alias='macros']/tasks")
|
||||
|
||||
#Creating: <create assembly="umbraco" type="macroTasks" />
|
||||
$createNode = $uiXml.CreateElement("create")
|
||||
$createNode.SetAttribute("assembly", "umbraco")
|
||||
$createNode.SetAttribute("type", "macroTasks")
|
||||
$macrosTasksNode.AppendChild($createNode)
|
||||
$uiXml.Save($uiXmlFile)
|
||||
}
|
||||
}
|
||||
Catch { }
|
||||
}
|
||||
|
||||
$installFolder = Join-Path $projectPath "Install"
|
||||
|
||||
@@ -79,14 +79,14 @@
|
||||
<add sortOrder="1" alias="dataTypes" application="developer"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes(sortOrder)" />
|
||||
|
||||
<add initialize="true" sortOrder="2" alias="macros" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MacroTreeController, umbraco"
|
||||
|
||||
<add application="developer" alias="macros" title="Macros" type="umbraco.loadMacros, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="2"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add application="developer" alias="relationTypes" title="Relation Types" type="umbraco.loadRelationTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add initialize="true" sortOrder="5" alias="xslt" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.XsltTreeController, umbraco"
|
||||
<add application="developer" alias="xslt" title="XSLT Files" type="umbraco.loadXslt, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="5"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
|
||||
@@ -102,16 +102,15 @@
|
||||
xdt:Transform="Remove" />
|
||||
|
||||
<!--Users-->
|
||||
<add initialize="true" sortOrder="0" alias="users" application="users" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.UserTreeController, umbraco"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
|
||||
<add application="users" alias="userTypes"
|
||||
<add application="users" alias="users" title="Users" type="umbraco.loadUsers, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="0"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="Remove" />
|
||||
<add application="users" alias="userPermissions"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add application="users" alias="userTypes" title="User Types" type="umbraco.cms.presentation.Trees.UserTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="1"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="Remove" />
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add application="users" alias="userPermissions" title="User Permissions" type="umbraco.cms.presentation.Trees.UserPermissions, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="2"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
|
||||
<!--Members-->
|
||||
<add initialize="true" sortOrder="0" alias="member" application="member" title="Members" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MemberTreeController, umbraco"
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
Param(
|
||||
[string]$GitHubPersonalAccessToken,
|
||||
[string]$Directory
|
||||
)
|
||||
$workingDirectory = $Directory
|
||||
CD $workingDirectory
|
||||
|
||||
# Clone repo
|
||||
$fullGitUrl = "https://$env:GIT_URL/$env:GIT_REPOSITORYNAME.git"
|
||||
git clone $fullGitUrl 2>&1 | % { $_.ToString() }
|
||||
|
||||
# Remove everything so that unzipping the release later will update everything
|
||||
# Don't remove the readme file nor the git directory
|
||||
Write-Host "Cleaning up git directory before adding new version"
|
||||
Remove-Item -Recurse $workingDirectory\$env:GIT_REPOSITORYNAME\* -Exclude README.md,.git
|
||||
|
||||
# Find release zip
|
||||
$zipsDir = "$workingDirectory\$env:BUILD_DEFINITIONNAME\zips"
|
||||
$pattern = "UmbracoCms.([0-9]{1,2}.[0-9]{1,3}.[0-9]{1,3}).zip"
|
||||
Write-Host "Searching for Umbraco release files in $workingDirectory\$zipsDir for a file with pattern $pattern"
|
||||
$file = (Get-ChildItem $zipsDir | Where-Object { $_.Name -match "$pattern" })
|
||||
|
||||
if($file)
|
||||
{
|
||||
# Get release name
|
||||
$version = [regex]::Match($file.Name, $pattern).captures.groups[1].value
|
||||
$releaseName = "Umbraco $version"
|
||||
Write-Host "Found $releaseName"
|
||||
|
||||
# Unzip into repository to update release
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
Write-Host "Unzipping $($file.FullName) to $workingDirectory\$env:GIT_REPOSITORYNAME"
|
||||
[System.IO.Compression.ZipFile]::ExtractToDirectory("$($file.FullName)", "$workingDirectory\$env:GIT_REPOSITORYNAME")
|
||||
|
||||
# Telling git who we are
|
||||
git config --global user.email "coffee@umbraco.com" 2>&1 | % { $_.ToString() }
|
||||
git config --global user.name "Umbraco HQ" 2>&1 | % { $_.ToString() }
|
||||
|
||||
# Commit
|
||||
CD $env:GIT_REPOSITORYNAME
|
||||
Write-Host "Committing Umbraco $version Release from Build Output"
|
||||
|
||||
git add . 2>&1 | % { $_.ToString() }
|
||||
git commit -m " Release $releaseName from Build Output" 2>&1 | % { $_.ToString() }
|
||||
|
||||
# Tag the release
|
||||
git tag -a "v$version" -m "v$version"
|
||||
|
||||
# Push release to master
|
||||
$fullGitAuthUrl = "https://$($env:GIT_USERNAME):$GitHubPersonalAccessToken@$env:GIT_URL/$env:GIT_REPOSITORYNAME.git"
|
||||
git push $fullGitAuthUrl 2>&1 | % { $_.ToString() }
|
||||
|
||||
#Push tag to master
|
||||
git push $fullGitAuthUrl --tags 2>&1 | % { $_.ToString() }
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Error "Umbraco release file not found, searched in $workingDirectory\$zipsDir for a file with pattern $pattern - cancelling"
|
||||
}
|
||||
@@ -49,9 +49,11 @@
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
|
||||
@@ -16,19 +16,19 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
|
||||
|
||||
+2
-2
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.8.2")]
|
||||
[assembly: AssemblyInformationalVersion("7.8.2")]
|
||||
[assembly: AssemblyFileVersion("7.6.12")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.12")]
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Umbraco.Core.Logging;
|
||||
@@ -35,31 +34,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
return Values;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method will return a list of IAction's based on a string (letter) list. Each character in the list may represent
|
||||
/// an IAction. This will associate any found IActions based on the Letter property of the IAction with the character being referenced.
|
||||
/// </summary>
|
||||
/// <param name="actions"></param>
|
||||
/// <returns>returns a list of actions that have an associated letter found in the action string list</returns>
|
||||
public IEnumerable<IAction> FromActionSymbols(IEnumerable<string> actions)
|
||||
{
|
||||
var allActions = Actions.ToArray();
|
||||
return actions
|
||||
.Select(c => allActions.FirstOrDefault(a => a.Letter.ToString(CultureInfo.InvariantCulture) == c))
|
||||
.WhereNotNull()
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the string (letter) representation of the actions that make up the actions collection
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<string> ToActionSymbols(IEnumerable<IAction> actions)
|
||||
{
|
||||
return actions.Select(x => x.Letter.ToString(CultureInfo.InvariantCulture)).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an Action if it exists.
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Threading;
|
||||
using Semver;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
@@ -262,7 +260,7 @@ namespace Umbraco.Core
|
||||
/// - http://issues.umbraco.org/issue/U4-5728
|
||||
/// - http://issues.umbraco.org/issue/U4-5391
|
||||
/// </remarks>
|
||||
public string UmbracoApplicationUrl
|
||||
internal string UmbracoApplicationUrl
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -270,21 +268,9 @@ namespace Umbraco.Core
|
||||
return _umbracoApplicationUrl;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the url.
|
||||
/// </summary>
|
||||
public void ResetUmbracoApplicationUrl()
|
||||
{
|
||||
_umbracoApplicationUrl = null;
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal string _umbracoApplicationUrl;
|
||||
|
||||
internal List<string> _umbracoApplicationDomains = new List<string>();
|
||||
|
||||
internal string _umbracoApplicationDeploymentId;
|
||||
internal string _umbracoApplicationUrl;
|
||||
|
||||
private Lazy<bool> _configured;
|
||||
internal MainDom MainDom { get; private set; }
|
||||
@@ -355,52 +341,6 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Current Version of the Umbraco Site before an upgrade
|
||||
/// by using the last/most recent Umbraco Migration that has been run
|
||||
/// </summary>
|
||||
/// <returns>A SemVersion of the latest Umbraco DB Migration run</returns>
|
||||
/// <remarks>
|
||||
/// NOTE: This existed in the InstallHelper previously but should really be here so it can be re-used if necessary
|
||||
/// </remarks>
|
||||
internal SemVersion CurrentVersion()
|
||||
{
|
||||
//Set a default version of 0.0.0
|
||||
var version = new SemVersion(0);
|
||||
|
||||
//If we have a db context available, if we don't then we are not installed anyways
|
||||
if (DatabaseContext.IsDatabaseConfigured && DatabaseContext.CanConnect)
|
||||
version = DatabaseContext.ValidateDatabaseSchema().DetermineInstalledVersionByMigrations(Services.MigrationEntryService);
|
||||
|
||||
if (version != new SemVersion(0))
|
||||
return version;
|
||||
|
||||
// If we aren't able to get a result from the umbracoMigrations table then use the version in web.config, if it's available
|
||||
if (string.IsNullOrWhiteSpace(GlobalSettings.ConfigurationStatus))
|
||||
return version;
|
||||
|
||||
var configuredVersion = GlobalSettings.ConfigurationStatus;
|
||||
|
||||
string currentComment = null;
|
||||
|
||||
var current = configuredVersion.Split('-');
|
||||
if (current.Length > 1)
|
||||
currentComment = current[1];
|
||||
|
||||
Version currentVersion;
|
||||
if (Version.TryParse(current[0], out currentVersion))
|
||||
{
|
||||
version = new SemVersion(
|
||||
currentVersion.Major,
|
||||
currentVersion.Minor,
|
||||
currentVersion.Build,
|
||||
string.IsNullOrWhiteSpace(currentComment) ? null : currentComment,
|
||||
currentVersion.Revision > 0 ? currentVersion.Revision.ToString() : null);
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
private void AssertIsNotReady()
|
||||
{
|
||||
if (this.IsReady)
|
||||
|
||||
@@ -55,10 +55,8 @@ namespace Umbraco.Core.Cache
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string UserCacheKey = "UmbracoUser";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string UserGroupPermissionsCacheKey = "UmbracoUserGroupPermissions";
|
||||
|
||||
public const string UserPermissionsCacheKey = "UmbracoUserPermissions";
|
||||
|
||||
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
|
||||
public const string ContentTypeCacheKey = "UmbracoContentType";
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace Umbraco.Core.Cache
|
||||
#region Insert
|
||||
#endregion
|
||||
|
||||
private class NoopLocker : DisposableObjectSlim
|
||||
private class NoopLocker : DisposableObject
|
||||
{
|
||||
protected override void DisposeResources()
|
||||
{ }
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
|
||||
internal class ActionMetadataAttribute : Attribute
|
||||
{
|
||||
public string Category { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor used to assign a Category, since no name is assigned it will try to be translated from the language files based on the action's alias
|
||||
/// </summary>
|
||||
/// <param name="category"></param>
|
||||
public ActionMetadataAttribute(string category)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(category)) throw new ArgumentException("Value cannot be null or whitespace.", "category");
|
||||
Category = category;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor used to assign an explicit name and category
|
||||
/// </summary>
|
||||
/// <param name="category"></param>
|
||||
/// <param name="name"></param>
|
||||
public ActionMetadataAttribute(string category, string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(category)) throw new ArgumentException("Value cannot be null or whitespace.", "category");
|
||||
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", "name");
|
||||
Category = category;
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a composite key of (Type, Type) for fast dictionaries.
|
||||
/// </summary>
|
||||
internal struct CompositeTypeTypeKey : IEquatable<CompositeTypeTypeKey>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CompositeTypeTypeKey"/> struct.
|
||||
/// </summary>
|
||||
public CompositeTypeTypeKey(Type type1, Type type2) : this()
|
||||
{
|
||||
Type1 = type1;
|
||||
Type2 = type2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the first type.
|
||||
/// </summary>
|
||||
public Type Type1 { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the second type.
|
||||
/// </summary>
|
||||
public Type Type2 { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(CompositeTypeTypeKey other)
|
||||
{
|
||||
return Type1 == other.Type1 && Type2 == other.Type2;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var other = obj is CompositeTypeTypeKey ? (CompositeTypeTypeKey)obj : default(CompositeTypeTypeKey);
|
||||
return Type1 == other.Type1 && Type2 == other.Type2;
|
||||
}
|
||||
|
||||
public static bool operator ==(CompositeTypeTypeKey key1, CompositeTypeTypeKey key2)
|
||||
{
|
||||
return key1.Type1 == key2.Type1 && key1.Type2 == key2.Type2;
|
||||
}
|
||||
|
||||
public static bool operator !=(CompositeTypeTypeKey key1, CompositeTypeTypeKey key2)
|
||||
{
|
||||
return key1.Type1 != key2.Type1 || key1.Type2 != key2.Type2;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (Type1.GetHashCode() * 397) ^ Type2.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a list of types.
|
||||
/// </summary>
|
||||
/// <remarks>Types in the list are, or derive from, or implement, the base type.</remarks>
|
||||
/// <typeparam name="TBase">The base type.</typeparam>
|
||||
internal class TypeList<TBase>
|
||||
{
|
||||
private readonly List<Type> _list = new List<Type>();
|
||||
|
||||
/// <summary>
|
||||
/// Adds a type to the list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to add.</typeparam>
|
||||
public void Add<T>()
|
||||
where T : TBase
|
||||
{
|
||||
_list.Add(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a type is in the list.
|
||||
/// </summary>
|
||||
public bool Contains(Type type)
|
||||
{
|
||||
return _list.Contains(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class FileSystemProviderElement : ConfigurationElement, IFileSystemProviderElement
|
||||
public class FileSystemProviderElement : ConfigurationElement
|
||||
{
|
||||
private const string ALIAS_KEY = "alias";
|
||||
private const string TYPE_KEY = "type";
|
||||
@@ -38,30 +38,5 @@ namespace Umbraco.Core.Configuration
|
||||
return ((KeyValueConfigurationCollection)(base[PARAMETERS_KEY]));
|
||||
}
|
||||
}
|
||||
|
||||
string IFileSystemProviderElement.Alias
|
||||
{
|
||||
get { return Alias; }
|
||||
}
|
||||
|
||||
string IFileSystemProviderElement.Type
|
||||
{
|
||||
get { return Type; }
|
||||
}
|
||||
|
||||
private IDictionary<string, string> _params;
|
||||
IDictionary<string, string> IFileSystemProviderElement.Parameters
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_params != null) return _params;
|
||||
_params = new Dictionary<string, string>();
|
||||
foreach (KeyValueConfigurationElement element in Parameters)
|
||||
{
|
||||
_params.Add(element.Key, element.Value);
|
||||
}
|
||||
return _params;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ using System.Text;
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
[ConfigurationCollection(typeof(FileSystemProviderElement), AddItemName = "Provider")]
|
||||
public class FileSystemProviderElementCollection : ConfigurationElementCollection, IEnumerable<IFileSystemProviderElement>
|
||||
public class FileSystemProviderElementCollection : ConfigurationElementCollection
|
||||
{
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
{
|
||||
@@ -19,25 +19,12 @@ namespace Umbraco.Core.Configuration
|
||||
return ((FileSystemProviderElement)(element)).Alias;
|
||||
}
|
||||
|
||||
public new FileSystemProviderElement this[string key]
|
||||
new public FileSystemProviderElement this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return (FileSystemProviderElement)BaseGet(key);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator<IFileSystemProviderElement> IEnumerable<IFileSystemProviderElement>.GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return BaseGet(i) as IFileSystemProviderElement;
|
||||
}
|
||||
}
|
||||
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class FileSystemProvidersSection : ConfigurationSection, IFileSystemProvidersSection
|
||||
public class FileSystemProvidersSection : ConfigurationSection
|
||||
{
|
||||
|
||||
[ConfigurationProperty("", IsDefaultCollection = true, IsRequired = true)]
|
||||
@@ -14,17 +14,5 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
get { return ((FileSystemProviderElementCollection)(base[""])); }
|
||||
}
|
||||
|
||||
private IDictionary<string, IFileSystemProviderElement> _providers;
|
||||
|
||||
IDictionary<string, IFileSystemProviderElement> IFileSystemProvidersSection.Providers
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_providers != null) return _providers;
|
||||
_providers = Providers.ToDictionary(x => x.Alias, x => x);
|
||||
return _providers;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Net.Configuration;
|
||||
using System.Web;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Hosting;
|
||||
@@ -43,6 +42,7 @@ namespace Umbraco.Core.Configuration
|
||||
//ensure the built on (non-changeable) reserved paths are there at all times
|
||||
private const string StaticReservedPaths = "~/app_plugins/,~/install/,";
|
||||
private const string StaticReservedUrls = "~/config/splashes/booting.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd,";
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -53,7 +53,6 @@ namespace Umbraco.Core.Configuration
|
||||
_reservedUrlsCache = null;
|
||||
_reservedPaths = null;
|
||||
_reservedUrls = null;
|
||||
HasSmtpServer = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -65,26 +64,7 @@ namespace Umbraco.Core.Configuration
|
||||
ResetInternal();
|
||||
}
|
||||
|
||||
public static bool HasSmtpServerConfigured(string appPath)
|
||||
{
|
||||
if (HasSmtpServer.HasValue) return HasSmtpServer.Value;
|
||||
|
||||
var config = WebConfigurationManager.OpenWebConfiguration(appPath);
|
||||
var settings = (MailSettingsSectionGroup)config.GetSectionGroup("system.net/mailSettings");
|
||||
if (settings == null || settings.Smtp == null) return false;
|
||||
if (settings.Smtp.SpecifiedPickupDirectory != null && string.IsNullOrEmpty(settings.Smtp.SpecifiedPickupDirectory.PickupDirectoryLocation) == false)
|
||||
return true;
|
||||
if (settings.Smtp.Network != null && string.IsNullOrEmpty(settings.Smtp.Network.Host) == false)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For testing only
|
||||
/// </summary>
|
||||
internal static bool? HasSmtpServer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Gets the reserved urls from web.config.
|
||||
/// </summary>
|
||||
/// <value>The reserved urls.</value>
|
||||
|
||||
@@ -9,7 +9,7 @@ using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Grid
|
||||
{
|
||||
internal class GridEditorsConfig : IGridEditorsConfig
|
||||
class GridEditorsConfig : IGridEditorsConfig
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IRuntimeCacheProvider _runtimeCache;
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public class DisabledHealthCheckElement : ConfigurationElement, IDisabledHealthCheck
|
||||
{
|
||||
private const string IdKey = "id";
|
||||
private const string DisabledOnKey = "disabledOn";
|
||||
private const string DisabledByKey = "disabledBy";
|
||||
|
||||
[ConfigurationProperty(IdKey, IsKey = true, IsRequired = true)]
|
||||
public Guid Id
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((Guid)(base[IdKey]));
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(DisabledOnKey, IsKey = false, IsRequired = false)]
|
||||
public DateTime DisabledOn
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((DateTime)(base[DisabledOnKey]));
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(DisabledByKey, IsKey = false, IsRequired = false)]
|
||||
public int DisabledBy
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((int)(base[DisabledByKey]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
[ConfigurationCollection(typeof(DisabledHealthCheckElement), AddItemName = "check")]
|
||||
public class DisabledHealthChecksElementCollection : ConfigurationElementCollection, IEnumerable<IDisabledHealthCheck>
|
||||
{
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
{
|
||||
return new DisabledHealthCheckElement();
|
||||
}
|
||||
|
||||
protected override object GetElementKey(ConfigurationElement element)
|
||||
{
|
||||
return ((DisabledHealthCheckElement)(element)).Id;
|
||||
}
|
||||
|
||||
public new DisabledHealthCheckElement this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return (DisabledHealthCheckElement)BaseGet(key);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator<IDisabledHealthCheck> IEnumerable<IDisabledHealthCheck>.GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return BaseGet(i) as DisabledHealthCheckElement;
|
||||
}
|
||||
}
|
||||
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public class HealthCheckNotificationSettingsElement : ConfigurationElement, IHealthCheckNotificationSettings
|
||||
{
|
||||
private const string EnabledKey = "enabled";
|
||||
private const string FirstRunTimeKey = "firstRunTime";
|
||||
private const string PeriodKey = "periodInHours";
|
||||
private const string NotificationMethodsKey = "notificationMethods";
|
||||
private const string DisabledChecksKey = "disabledChecks";
|
||||
|
||||
[ConfigurationProperty(EnabledKey, IsRequired = true)]
|
||||
public bool Enabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return (bool)base[EnabledKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(FirstRunTimeKey, IsRequired = false)]
|
||||
public string FirstRunTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return (string)base[FirstRunTimeKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(PeriodKey, IsRequired = true)]
|
||||
public int PeriodInHours
|
||||
{
|
||||
get
|
||||
{
|
||||
return (int)base[PeriodKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(NotificationMethodsKey, IsDefaultCollection = true, IsRequired = false)]
|
||||
public NotificationMethodsElementCollection NotificationMethods
|
||||
{
|
||||
get
|
||||
{
|
||||
return (NotificationMethodsElementCollection)base[NotificationMethodsKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(DisabledChecksKey, IsDefaultCollection = false, IsRequired = false)]
|
||||
public DisabledHealthChecksElementCollection DisabledChecks
|
||||
{
|
||||
get
|
||||
{
|
||||
return (DisabledHealthChecksElementCollection)base[DisabledChecksKey];
|
||||
}
|
||||
}
|
||||
|
||||
bool IHealthCheckNotificationSettings.Enabled
|
||||
{
|
||||
get { return Enabled; }
|
||||
}
|
||||
|
||||
string IHealthCheckNotificationSettings.FirstRunTime
|
||||
{
|
||||
get { return FirstRunTime; }
|
||||
}
|
||||
|
||||
int IHealthCheckNotificationSettings.PeriodInHours
|
||||
{
|
||||
get { return PeriodInHours; }
|
||||
}
|
||||
|
||||
IReadOnlyDictionary<string, INotificationMethod> IHealthCheckNotificationSettings.NotificationMethods
|
||||
{
|
||||
get { return NotificationMethods; }
|
||||
}
|
||||
|
||||
IEnumerable<IDisabledHealthCheck> IHealthCheckNotificationSettings.DisabledChecks
|
||||
{
|
||||
get { return DisabledChecks; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public enum HealthCheckNotificationVerbosity
|
||||
{
|
||||
Summary,
|
||||
Detailed
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public class HealthChecksSection : ConfigurationSection, IHealthChecks
|
||||
{
|
||||
private const string DisabledChecksKey = "disabledChecks";
|
||||
private const string NotificationSettingsKey = "notificationSettings";
|
||||
|
||||
[ConfigurationProperty(DisabledChecksKey)]
|
||||
public DisabledHealthChecksElementCollection DisabledChecks
|
||||
{
|
||||
get { return ((DisabledHealthChecksElementCollection)(base[DisabledChecksKey])); }
|
||||
}
|
||||
|
||||
[ConfigurationProperty(NotificationSettingsKey, IsRequired = true)]
|
||||
public HealthCheckNotificationSettingsElement NotificationSettings
|
||||
{
|
||||
get { return ((HealthCheckNotificationSettingsElement)(base[NotificationSettingsKey])); }
|
||||
}
|
||||
|
||||
IEnumerable<IDisabledHealthCheck> IHealthChecks.DisabledChecks
|
||||
{
|
||||
get { return DisabledChecks; }
|
||||
}
|
||||
|
||||
IHealthCheckNotificationSettings IHealthChecks.NotificationSettings
|
||||
{
|
||||
get { return NotificationSettings; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public interface IDisabledHealthCheck
|
||||
{
|
||||
Guid Id { get; }
|
||||
DateTime DisabledOn { get; }
|
||||
int DisabledBy { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public interface IHealthCheckNotificationSettings
|
||||
{
|
||||
bool Enabled { get; }
|
||||
string FirstRunTime { get; }
|
||||
int PeriodInHours { get; }
|
||||
IReadOnlyDictionary<string, INotificationMethod> NotificationMethods { get; }
|
||||
IEnumerable<IDisabledHealthCheck> DisabledChecks { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public interface IHealthChecks
|
||||
{
|
||||
IEnumerable<IDisabledHealthCheck> DisabledChecks { get; }
|
||||
IHealthCheckNotificationSettings NotificationSettings { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public interface INotificationMethod
|
||||
{
|
||||
string Alias { get; }
|
||||
bool Enabled { get; }
|
||||
HealthCheckNotificationVerbosity Verbosity { get; }
|
||||
bool FailureOnly { get; }
|
||||
IReadOnlyDictionary<string, INotificationMethodSettings> Settings { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public interface INotificationMethodSettings
|
||||
{
|
||||
string Key { get; }
|
||||
string Value { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public class NotificationMethodElement : ConfigurationElement, INotificationMethod
|
||||
{
|
||||
private const string AliasKey = "alias";
|
||||
private const string EnabledKey = "enabled";
|
||||
private const string VerbosityKey = "verbosity";
|
||||
private const string FailureonlyKey = "failureOnly";
|
||||
private const string SettingsKey = "settings";
|
||||
|
||||
[ConfigurationProperty(AliasKey, IsKey = true, IsRequired = true)]
|
||||
public string Alias
|
||||
{
|
||||
get
|
||||
{
|
||||
return (string)base[AliasKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(EnabledKey, IsKey = true, IsRequired = true)]
|
||||
public bool Enabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return (bool)base[EnabledKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(VerbosityKey, IsRequired = true)]
|
||||
public HealthCheckNotificationVerbosity Verbosity
|
||||
{
|
||||
get
|
||||
{
|
||||
return (HealthCheckNotificationVerbosity)base[VerbosityKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(FailureonlyKey, IsRequired = false)]
|
||||
public bool FailureOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return (bool)base[FailureonlyKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(SettingsKey, IsDefaultCollection = true, IsRequired = false)]
|
||||
public NotificationMethodSettingsElementCollection Settings
|
||||
{
|
||||
get
|
||||
{
|
||||
return (NotificationMethodSettingsElementCollection)base[SettingsKey];
|
||||
}
|
||||
}
|
||||
|
||||
string INotificationMethod.Alias
|
||||
{
|
||||
get { return Alias; }
|
||||
}
|
||||
|
||||
bool INotificationMethod.Enabled
|
||||
{
|
||||
get { return Enabled; }
|
||||
}
|
||||
|
||||
HealthCheckNotificationVerbosity INotificationMethod.Verbosity
|
||||
{
|
||||
get { return Verbosity; }
|
||||
}
|
||||
|
||||
bool INotificationMethod.FailureOnly
|
||||
{
|
||||
get { return FailureOnly; }
|
||||
}
|
||||
|
||||
IReadOnlyDictionary<string, INotificationMethodSettings> INotificationMethod.Settings
|
||||
{
|
||||
get { return Settings; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
public class NotificationMethodSettingsElement : ConfigurationElement, INotificationMethodSettings
|
||||
{
|
||||
private const string KeyKey = "key";
|
||||
private const string ValueKey = "value";
|
||||
|
||||
[ConfigurationProperty(KeyKey, IsKey = true, IsRequired = true)]
|
||||
public string Key
|
||||
{
|
||||
get
|
||||
{
|
||||
return (string)base[KeyKey];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty(ValueKey, IsRequired = true)]
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return (string)base[ValueKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
[ConfigurationCollection(typeof(NotificationMethodSettingsElement), AddItemName = "add")]
|
||||
public class NotificationMethodSettingsElementCollection : ConfigurationElementCollection, IEnumerable<INotificationMethodSettings>, IReadOnlyDictionary<string, INotificationMethodSettings>
|
||||
{
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
{
|
||||
return new NotificationMethodSettingsElement();
|
||||
}
|
||||
|
||||
protected override object GetElementKey(ConfigurationElement element)
|
||||
{
|
||||
return ((NotificationMethodSettingsElement)(element)).Key;
|
||||
}
|
||||
|
||||
IEnumerator<KeyValuePair<string, INotificationMethodSettings>> IEnumerable<KeyValuePair<string, INotificationMethodSettings>>.GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
var val = (NotificationMethodSettingsElement)BaseGet(i);
|
||||
var key = (string)BaseGetKey(i);
|
||||
yield return new KeyValuePair<string, INotificationMethodSettings>(key, val);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator<INotificationMethodSettings> IEnumerable<INotificationMethodSettings>.GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return (NotificationMethodSettingsElement)BaseGet(i);
|
||||
}
|
||||
}
|
||||
|
||||
bool IReadOnlyDictionary<string, INotificationMethodSettings>.ContainsKey(string key)
|
||||
{
|
||||
return ((IReadOnlyDictionary<string, INotificationMethodSettings>)this).Keys.Any(x => x == key);
|
||||
}
|
||||
|
||||
bool IReadOnlyDictionary<string, INotificationMethodSettings>.TryGetValue(string key, out INotificationMethodSettings value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var val = (NotificationMethodSettingsElement)BaseGet(key);
|
||||
value = val;
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
INotificationMethodSettings IReadOnlyDictionary<string, INotificationMethodSettings>.this[string key]
|
||||
{
|
||||
get { return (NotificationMethodSettingsElement)BaseGet(key); }
|
||||
}
|
||||
|
||||
IEnumerable<string> IReadOnlyDictionary<string, INotificationMethodSettings>.Keys
|
||||
{
|
||||
get { return BaseGetAllKeys().Cast<string>(); }
|
||||
}
|
||||
|
||||
IEnumerable<INotificationMethodSettings> IReadOnlyDictionary<string, INotificationMethodSettings>.Values
|
||||
{
|
||||
get
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return (NotificationMethodSettingsElement)BaseGet(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Configuration.HealthChecks
|
||||
{
|
||||
[ConfigurationCollection(typeof(NotificationMethodElement), AddItemName = "notificationMethod")]
|
||||
public class NotificationMethodsElementCollection : ConfigurationElementCollection, IEnumerable<INotificationMethod>, IReadOnlyDictionary<string, INotificationMethod>
|
||||
{
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
{
|
||||
return new NotificationMethodElement();
|
||||
}
|
||||
|
||||
protected override object GetElementKey(ConfigurationElement element)
|
||||
{
|
||||
return ((NotificationMethodElement)(element)).Alias;
|
||||
}
|
||||
|
||||
IEnumerator<KeyValuePair<string, INotificationMethod>> IEnumerable<KeyValuePair<string, INotificationMethod>>.GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
var val = (NotificationMethodElement)BaseGet(i);
|
||||
var key = (string)BaseGetKey(i);
|
||||
yield return new KeyValuePair<string, INotificationMethod>(key, val);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator<INotificationMethod> IEnumerable<INotificationMethod>.GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return (NotificationMethodElement)BaseGet(i);
|
||||
}
|
||||
}
|
||||
|
||||
bool IReadOnlyDictionary<string, INotificationMethod>.ContainsKey(string key)
|
||||
{
|
||||
return ((IReadOnlyDictionary<string, INotificationMethod>) this).Keys.Any(x => x == key);
|
||||
}
|
||||
|
||||
bool IReadOnlyDictionary<string, INotificationMethod>.TryGetValue(string key, out INotificationMethod value)
|
||||
{
|
||||
try
|
||||
{
|
||||
var val = (NotificationMethodElement)BaseGet(key);
|
||||
value = val;
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
INotificationMethod IReadOnlyDictionary<string, INotificationMethod>.this[string key]
|
||||
{
|
||||
get { return (NotificationMethodElement)BaseGet(key); }
|
||||
}
|
||||
|
||||
IEnumerable<string> IReadOnlyDictionary<string, INotificationMethod>.Keys
|
||||
{
|
||||
get { return BaseGetAllKeys().Cast<string>(); }
|
||||
}
|
||||
|
||||
IEnumerable<INotificationMethod> IReadOnlyDictionary<string, INotificationMethod>.Values
|
||||
{
|
||||
get
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return (NotificationMethodElement)BaseGet(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public interface IFileSystemProviderElement
|
||||
{
|
||||
string Alias { get; }
|
||||
string Type { get; }
|
||||
IDictionary<string, string> Parameters { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public interface IFileSystemProvidersSection
|
||||
{
|
||||
IDictionary<string, IFileSystemProviderElement> Providers { get; }
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration.BaseRest;
|
||||
using Umbraco.Core.Configuration.Dashboard;
|
||||
using Umbraco.Core.Configuration.Grid;
|
||||
using Umbraco.Core.Configuration.HealthChecks;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
@@ -53,12 +52,6 @@ namespace Umbraco.Core.Configuration
|
||||
var dashboardConfig = ConfigurationManager.GetSection("umbracoConfiguration/dashBoard") as IDashboardSection;
|
||||
SetDashboardSettings(dashboardConfig);
|
||||
}
|
||||
|
||||
if (_healthChecks == null)
|
||||
{
|
||||
var healthCheckConfig = ConfigurationManager.GetSection("umbracoConfiguration/HealthChecks") as IHealthChecks;
|
||||
SetHealthCheckSettings(healthCheckConfig);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -67,36 +60,18 @@ namespace Umbraco.Core.Configuration
|
||||
/// <param name="umbracoSettings"></param>
|
||||
/// <param name="baseRestSettings"></param>
|
||||
/// <param name="dashboardSettings"></param>
|
||||
/// <param name="healthChecks"></param>
|
||||
public UmbracoConfig(IUmbracoSettingsSection umbracoSettings, IBaseRestSection baseRestSettings, IDashboardSection dashboardSettings, IHealthChecks healthChecks)
|
||||
public UmbracoConfig(IUmbracoSettingsSection umbracoSettings, IBaseRestSection baseRestSettings, IDashboardSection dashboardSettings)
|
||||
{
|
||||
SetHealthCheckSettings(healthChecks);
|
||||
SetUmbracoSettings(umbracoSettings);
|
||||
SetBaseRestExtensions(baseRestSettings);
|
||||
SetDashboardSettings(dashboardSettings);
|
||||
}
|
||||
|
||||
private IHealthChecks _healthChecks;
|
||||
private IDashboardSection _dashboardSection;
|
||||
private IUmbracoSettingsSection _umbracoSettings;
|
||||
private IBaseRestSection _baseRestExtensions;
|
||||
private IGridConfig _gridConfig;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the IHealthCheck config
|
||||
/// </summary>
|
||||
public IHealthChecks HealthCheck()
|
||||
{
|
||||
if (_healthChecks == null)
|
||||
{
|
||||
var ex = new ConfigurationErrorsException("Could not load the " + typeof(IHealthChecks) + " from config file, ensure the web.config and healthchecks.config files are formatted correctly");
|
||||
LogHelper.Error<UmbracoConfig>("Config error", ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
return _healthChecks;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the IDashboardSection
|
||||
/// </summary>
|
||||
@@ -111,23 +86,14 @@ namespace Umbraco.Core.Configuration
|
||||
|
||||
return _dashboardSection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only for testing
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void SetDashboardSettings(IDashboardSection value)
|
||||
{
|
||||
_dashboardSection = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only for testing
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void SetHealthCheckSettings(IHealthChecks value)
|
||||
internal void SetDashboardSettings(IDashboardSection value)
|
||||
{
|
||||
_healthChecks = value;
|
||||
_dashboardSection = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class BackOfficeElement : UmbracoConfigurationElement, IBackOfficeSection
|
||||
{
|
||||
[ConfigurationProperty("tours")]
|
||||
internal TourConfigElement Tours
|
||||
{
|
||||
get { return (TourConfigElement)this["tours"]; }
|
||||
}
|
||||
|
||||
ITourSection IBackOfficeSection.Tours
|
||||
{
|
||||
get { return Tours; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -357,7 +357,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
string IContentSection.LoginBackgroundImage
|
||||
{
|
||||
get { return LoginBackgroundImage; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("This is no longer used and will be removed in future versions")]
|
||||
internal class HelpElement : ConfigurationElement, IHelpSection
|
||||
{
|
||||
[ConfigurationProperty("defaultUrl", DefaultValue = "http://our.umbraco.org/wiki/umbraco-help/{0}/{1}")]
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
public interface IBackOfficeSection
|
||||
{
|
||||
ITourSection Tours { get; }
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
bool EnablePropertyValueConverters { get; }
|
||||
|
||||
string LoginBackgroundImage { get; }
|
||||
|
||||
string LoginBackgroundImage { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("This is no longer used and will be removed in future versions")]
|
||||
{
|
||||
public interface IHelpSection : IUmbracoConfigurationSection
|
||||
{
|
||||
string DefaultUrl { get; }
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("This is no longer used and will be removed in future versions")]
|
||||
public interface ILink
|
||||
{
|
||||
string Application { get; }
|
||||
|
||||
@@ -5,23 +5,11 @@
|
||||
bool KeepUserLoggedIn { get; }
|
||||
|
||||
bool HideDisabledUsersInBackoffice { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to enable/disable the forgot password functionality on the back office login screen
|
||||
/// </summary>
|
||||
|
||||
bool AllowPasswordReset { get; }
|
||||
|
||||
string AuthCookieName { get; }
|
||||
|
||||
string AuthCookieDomain { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A boolean indicating that by default the email address will be the username
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Even if this is true and the username is different from the email in the database, the username field will still be shown.
|
||||
/// When this is false, the username and email fields will be shown in the user section.
|
||||
/// </remarks>
|
||||
bool UsernameIsEmail { get; }
|
||||
string AuthCookieDomain { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
public interface ITourSection
|
||||
{
|
||||
bool EnableTours { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,7 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
public interface IUmbracoSettingsSection : IUmbracoConfigurationSection
|
||||
{
|
||||
IBackOfficeSection BackOffice { get; }
|
||||
|
||||
IContentSection Content { get; }
|
||||
|
||||
ISecuritySection Security { get; }
|
||||
@@ -29,8 +24,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
IProvidersSection Providers { get; }
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("This is no longer used and will be removed in future versions")]
|
||||
IHelpSection Help { get; }
|
||||
|
||||
IWebRoutingSection WebRouting { get; }
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Configuration;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("This is no longer used and will be removed in future versions")]
|
||||
internal class LinkElement : ConfigurationElement, ILink
|
||||
{
|
||||
[ConfigurationProperty("application")]
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("This is no longer used and will be removed in future versions")]
|
||||
internal class LinksCollection : ConfigurationElementCollection, IEnumerable<ILink>
|
||||
{
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
|
||||
@@ -16,28 +16,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return GetOptionalTextElement("hideDisabledUsersInBackoffice", false); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to enable/disable the forgot password functionality on the back office login screen
|
||||
/// </summary>
|
||||
[ConfigurationProperty("allowPasswordReset")]
|
||||
internal InnerTextConfigurationElement<bool> AllowPasswordReset
|
||||
{
|
||||
get { return GetOptionalTextElement("allowPasswordReset", true); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A boolean indicating that by default the email address will be the username
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Even if this is true and the username is different from the email in the database, the username field will still be shown.
|
||||
/// When this is false, the username and email fields will be shown in the user section.
|
||||
/// </remarks>
|
||||
[ConfigurationProperty("usernameIsEmail")]
|
||||
internal InnerTextConfigurationElement<bool> UsernameIsEmail
|
||||
{
|
||||
get { return GetOptionalTextElement("usernameIsEmail", true); }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("authCookieName")]
|
||||
internal InnerTextConfigurationElement<string> AuthCookieName
|
||||
{
|
||||
@@ -60,26 +44,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return HideDisabledUsersInBackoffice; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to enable/disable the forgot password functionality on the back office login screen
|
||||
/// </summary>
|
||||
bool ISecuritySection.AllowPasswordReset
|
||||
{
|
||||
get { return AllowPasswordReset; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A boolean indicating that by default the email address will be the username
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Even if this is true and the username is different from the email in the database, the username field will still be shown.
|
||||
/// When this is false, the username and email fields will be shown in the user section.
|
||||
/// </remarks>
|
||||
bool ISecuritySection.UsernameIsEmail
|
||||
{
|
||||
get { return UsernameIsEmail; }
|
||||
}
|
||||
|
||||
string ISecuritySection.AuthCookieName
|
||||
{
|
||||
get { return AuthCookieName; }
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class TourConfigElement : UmbracoConfigurationElement, ITourSection
|
||||
{
|
||||
//disabled by default so that upgraders don't get it enabled by default
|
||||
//TODO: we probably just want to disable the initial one from automatically loading ?
|
||||
[ConfigurationProperty("enable", DefaultValue = false)]
|
||||
public bool EnableTours
|
||||
{
|
||||
get { return (bool)this["enable"]; }
|
||||
}
|
||||
|
||||
//TODO: We could have additional filters, etc... defined here
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
|
||||
@@ -8,12 +7,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
public class UmbracoSettingsSection : ConfigurationSection, IUmbracoSettingsSection
|
||||
{
|
||||
[ConfigurationProperty("backOffice")]
|
||||
internal BackOfficeElement BackOffice
|
||||
{
|
||||
get { return (BackOfficeElement)this["backOffice"]; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("content")]
|
||||
internal ContentElement Content
|
||||
{
|
||||
@@ -155,11 +148,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return Templates; }
|
||||
}
|
||||
|
||||
IBackOfficeSection IUmbracoSettingsSection.BackOffice
|
||||
{
|
||||
get { return BackOffice; }
|
||||
}
|
||||
|
||||
IDeveloperSection IUmbracoSettingsSection.Developer
|
||||
{
|
||||
get { return Developer; }
|
||||
@@ -195,8 +183,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return Providers; }
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("This is no longer used and will be removed in future versions")]
|
||||
IHelpSection IUmbracoSettingsSection.Help
|
||||
{
|
||||
get { return Help; }
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.8.2");
|
||||
private static readonly Version Version = new Version("7.6.12");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -56,12 +56,7 @@
|
||||
/// <summary>
|
||||
/// alias for the content tree.
|
||||
/// </summary>
|
||||
public const string Content = "content";
|
||||
|
||||
/// <summary>
|
||||
/// alias for the content blueprint tree.
|
||||
/// </summary>
|
||||
public const string ContentBlueprints = "contentBlueprints";
|
||||
public const string Content = "content";
|
||||
|
||||
/// <summary>
|
||||
/// alias for the member tree.
|
||||
@@ -73,11 +68,6 @@
|
||||
/// </summary>
|
||||
public const string Media = "media";
|
||||
|
||||
/// <summary>
|
||||
/// alias for the macro tree.
|
||||
/// </summary>
|
||||
public const string Macros = "macros";
|
||||
|
||||
/// <summary>
|
||||
/// alias for the datatype tree.
|
||||
/// </summary>
|
||||
@@ -128,8 +118,6 @@
|
||||
|
||||
public const string Scripts = "scripts";
|
||||
|
||||
public const string Users = "users";
|
||||
|
||||
//TODO: Fill in the rest!
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,14 +12,6 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public static class Conventions
|
||||
{
|
||||
internal static class PermissionCategories
|
||||
{
|
||||
public const string ContentCategory = "content";
|
||||
public const string AdministrationCategory = "administration";
|
||||
public const string StructureCategory = "structure";
|
||||
public const string OtherCategory = "other";
|
||||
}
|
||||
|
||||
public static class PublicAccess
|
||||
{
|
||||
public const string MemberUsernameRuleType = "MemberUsername";
|
||||
|
||||
@@ -68,22 +68,12 @@ namespace Umbraco.Core
|
||||
/// Guid for a Document object.
|
||||
/// </summary>
|
||||
public const string Document = "C66BA18E-EAF3-4CFF-8A22-41B16D66A972";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Document object.
|
||||
/// </summary>
|
||||
public static readonly Guid DocumentGuid = new Guid(Document);
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Document Blueprint object.
|
||||
/// </summary>
|
||||
public const string DocumentBlueprint = "6EBEF410-03AA-48CF-A792-E1C1CB087ACA";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Document object.
|
||||
/// </summary>
|
||||
public static readonly Guid DocumentBlueprintGuid = new Guid(DocumentBlueprint);
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Document Type object.
|
||||
/// </summary>
|
||||
|
||||
@@ -437,11 +437,6 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string EmailAddressAlias = "Umbraco.EmailAddress";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the nested content property editor.
|
||||
/// </summary>
|
||||
public const string NestedContentAlias = "Umbraco.NestedContent";
|
||||
|
||||
public static class PreValueKeys
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -8,9 +8,6 @@ namespace Umbraco.Core
|
||||
public static class Security
|
||||
{
|
||||
|
||||
public const string AdminGroupAlias = "admin";
|
||||
public const string TranslatorGroupAlias = "translator";
|
||||
|
||||
public const string BackOfficeAuthenticationType = "UmbracoBackOffice";
|
||||
public const string BackOfficeExternalAuthenticationType = "UmbracoExternalCookie";
|
||||
public const string BackOfficeExternalCookieName = "UMB_EXTLOGIN";
|
||||
@@ -18,8 +15,7 @@ namespace Umbraco.Core
|
||||
public const string BackOfficeTwoFactorAuthenticationType = "UmbracoTwoFactorCookie";
|
||||
|
||||
internal const string EmptyPasswordPrefix = "___UIDEMPTYPWORD__";
|
||||
internal const string ForceReAuthFlag = "umbraco-force-auth";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The prefix used for external identity providers for their authentication type
|
||||
/// </summary>
|
||||
|
||||
@@ -11,53 +11,17 @@
|
||||
/// The integer identifier for global system root node.
|
||||
/// </summary>
|
||||
public const int Root = -1;
|
||||
|
||||
/// <summary>
|
||||
/// The string identifier for global system root node.
|
||||
/// </summary>
|
||||
/// <remarks>Use this instead of re-creating the string everywhere.</remarks>
|
||||
public const string RootString = "-1";
|
||||
|
||||
/// <summary>
|
||||
/// The integer identifier for content's recycle bin.
|
||||
/// </summary>
|
||||
public const int RecycleBinContent = -20;
|
||||
|
||||
/// <summary>
|
||||
/// The string identifier for content's recycle bin.
|
||||
/// </summary>
|
||||
/// <remarks>Use this instead of re-creating the string everywhere.</remarks>
|
||||
public const string RecycleBinContentString = "-20";
|
||||
|
||||
/// <summary>
|
||||
/// The string path prefix of the content's recycle bin.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Everything that is in the content recycle bin, has a path that starts with the prefix.</para>
|
||||
/// <para>Use this instead of re-creating the string everywhere.</para>
|
||||
/// </remarks>
|
||||
public const string RecycleBinContentPathPrefix = "-1,-20,";
|
||||
|
||||
/// <summary>
|
||||
/// The integer identifier for media's recycle bin.
|
||||
/// </summary>
|
||||
public const int RecycleBinMedia = -21;
|
||||
|
||||
/// <summary>
|
||||
/// The string identifier for media's recycle bin.
|
||||
/// </summary>
|
||||
/// <remarks>Use this instead of re-creating the string everywhere.</remarks>
|
||||
public const string RecycleBinMediaString = "-21";
|
||||
|
||||
/// <summary>
|
||||
/// The string path prefix of the media's recycle bin.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Everything that is in the media recycle bin, has a path that starts with the prefix.</para>
|
||||
/// <para>Use this instead of re-creating the string everywhere.</para>
|
||||
/// </remarks>
|
||||
public const string RecycleBinMediaPathPrefix = "-1,-21,";
|
||||
|
||||
public const int DefaultContentListViewDataTypeId = -95;
|
||||
public const int DefaultMediaListViewDataTypeId = -96;
|
||||
public const int DefaultMembersListViewDataTypeId = -97;
|
||||
@@ -65,6 +29,6 @@
|
||||
public const string UmbracoConnectionName = "umbracoDbDSN";
|
||||
public const string UmbracoMigrationName = "Umbraco";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,9 @@ namespace Umbraco.Core
|
||||
public static DateTime TruncateTo(this DateTime dt, DateTruncate truncateTo)
|
||||
{
|
||||
if (truncateTo == DateTruncate.Year)
|
||||
return new DateTime(dt.Year, 1, 1);
|
||||
return new DateTime(dt.Year, 0, 0);
|
||||
if (truncateTo == DateTruncate.Month)
|
||||
return new DateTime(dt.Year, dt.Month, 1);
|
||||
return new DateTime(dt.Year, dt.Month, 0);
|
||||
if (truncateTo == DateTruncate.Day)
|
||||
return new DateTime(dt.Year, dt.Month, dt.Day);
|
||||
if (truncateTo == DateTruncate.Hour)
|
||||
@@ -43,41 +43,5 @@ namespace Umbraco.Core
|
||||
Second
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the number of minutes from a date time, on a rolling daily basis (so if
|
||||
/// date time is before the time, calculate onto next day)
|
||||
/// </summary>
|
||||
/// <param name="fromDateTime">Date to start from</param>
|
||||
/// <param name="scheduledTime">Time to compare against (in Hmm form, e.g. 330, 2200)</param>
|
||||
/// <returns></returns>
|
||||
public static int PeriodicMinutesFrom(this DateTime fromDateTime, string scheduledTime)
|
||||
{
|
||||
// Ensure time provided is 4 digits long
|
||||
if (scheduledTime.Length == 3)
|
||||
{
|
||||
scheduledTime = "0" + scheduledTime;
|
||||
}
|
||||
|
||||
var scheduledHour = int.Parse(scheduledTime.Substring(0, 2));
|
||||
var scheduledMinute = int.Parse(scheduledTime.Substring(2));
|
||||
|
||||
DateTime scheduledDateTime;
|
||||
if (IsScheduledInRemainingDay(fromDateTime, scheduledHour, scheduledMinute))
|
||||
{
|
||||
scheduledDateTime = new DateTime(fromDateTime.Year, fromDateTime.Month, fromDateTime.Day, scheduledHour, scheduledMinute, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var nextDay = fromDateTime.AddDays(1);
|
||||
scheduledDateTime = new DateTime(nextDay.Year, nextDay.Month, nextDay.Day, scheduledHour, scheduledMinute, 0);
|
||||
}
|
||||
|
||||
return (int)(scheduledDateTime - fromDateTime).TotalMinutes;
|
||||
}
|
||||
|
||||
private static bool IsScheduledInRemainingDay(DateTime fromDateTime, int scheduledHour, int scheduledMinute)
|
||||
{
|
||||
return scheduledHour > fromDateTime.Hour || (scheduledHour == fromDateTime.Hour && scheduledMinute >= fromDateTime.Minute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
namespace Umbraco.Core.Deploy
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a method to retrieve an artifact's unique identifier.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Artifacts are uniquely identified by their <see cref="Udi"/>, however they represent
|
||||
/// elements in Umbraco that may be uniquely identified by another value. For example,
|
||||
/// a content type is uniquely identified by its alias. If someone creates a new content
|
||||
/// type, and tries to deploy it to a remote environment where a content type with the
|
||||
/// same alias already exists, both content types end up having different <see cref="Udi"/>
|
||||
/// but the same alias. By default, Deploy would fail and throw when trying to save the
|
||||
/// new content type (duplicate alias). However, if the connector also implements this
|
||||
/// interface, the situation can be detected beforehand and reported in a nicer way.
|
||||
/// </remarks>
|
||||
public interface IUniqueIdentifyingServiceConnector
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the unique identifier of the specified artifact.
|
||||
/// </summary>
|
||||
/// <param name="artifact">The artifact.</param>
|
||||
/// <returns>The unique identifier.</returns>
|
||||
string GetUniqueIdentifier(IArtifact artifact);
|
||||
}
|
||||
}
|
||||
@@ -2,60 +2,60 @@ using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract implementation of IDisposable.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Can also be used as a pattern for when inheriting is not possible.
|
||||
///
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract implementation of IDisposable.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Can also be used as a pattern for when inheriting is not possible.
|
||||
///
|
||||
/// See also: https://msdn.microsoft.com/en-us/library/b1yfkh5e%28v=vs.110%29.aspx
|
||||
/// See also: https://lostechies.com/chrispatterson/2012/11/29/idisposable-done-right/
|
||||
///
|
||||
/// Note: if an object's ctor throws, it will never be disposed, and so if that ctor
|
||||
/// has allocated disposable objects, it should take care of disposing them.
|
||||
/// </remarks>
|
||||
public abstract class DisposableObject : IDisposable
|
||||
{
|
||||
private bool _disposed;
|
||||
private readonly object _locko = new object();
|
||||
|
||||
// gets a value indicating whether this instance is disposed.
|
||||
/// </remarks>
|
||||
public abstract class DisposableObject : IDisposable
|
||||
{
|
||||
private bool _disposed;
|
||||
private readonly object _locko = new object();
|
||||
|
||||
// gets a value indicating whether this instance is disposed.
|
||||
// for internal tests only (not thread safe)
|
||||
//TODO make this internal + rename "Disposed" when we can break compatibility
|
||||
public bool IsDisposed { get { return _disposed; } }
|
||||
|
||||
// implements IDisposable
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
// finalizer
|
||||
~DisposableObject()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
public bool IsDisposed { get { return _disposed; } }
|
||||
|
||||
// implements IDisposable
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
// finalizer
|
||||
~DisposableObject()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
//TODO make this private, non-virtual when we can break compatibility
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
lock (_locko)
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
}
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
lock (_locko)
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
DisposeUnmanagedResources();
|
||||
|
||||
if (disposing)
|
||||
DisposeResources();
|
||||
}
|
||||
|
||||
protected abstract void DisposeResources();
|
||||
|
||||
protected virtual void DisposeUnmanagedResources()
|
||||
{ }
|
||||
}
|
||||
DisposeResources();
|
||||
}
|
||||
|
||||
protected abstract void DisposeResources();
|
||||
|
||||
protected virtual void DisposeUnmanagedResources()
|
||||
{ }
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// This should not be use if there are ubmanaged resources to be disposed, use DisposableObject instead
|
||||
/// </summary>
|
||||
public abstract class DisposableObjectSlim : IDisposable
|
||||
{
|
||||
private bool _disposed;
|
||||
private readonly object _locko = new object();
|
||||
|
||||
// gets a value indicating whether this instance is disposed.
|
||||
// for internal tests only (not thread safe)
|
||||
internal bool Disposed { get { return _disposed; } }
|
||||
|
||||
// implements IDisposable
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
lock (_locko)
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
if (disposing)
|
||||
DisposeResources();
|
||||
}
|
||||
|
||||
protected abstract void DisposeResources();
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,8 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Starts the timer and invokes a callback upon disposal. Provides a simple way of timing an operation by wrapping it in a <code>using</code> (C#) statement.
|
||||
/// </summary>
|
||||
public class DisposableTimer : DisposableObjectSlim
|
||||
{
|
||||
public class DisposableTimer : DisposableObject
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly LogType? _logType;
|
||||
private readonly IProfiler _profiler;
|
||||
@@ -209,13 +209,13 @@ namespace Umbraco.Core
|
||||
loggerType,
|
||||
startMessage(),
|
||||
completeMessage());
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Handles the disposal of resources. Derived from abstract class <see cref="DisposableObjectSlim"/> which handles common required locking logic.
|
||||
/// </summary>
|
||||
protected override void DisposeResources()
|
||||
|
||||
/// <summary>
|
||||
/// Handles the disposal of resources. Derived from abstract class <see cref="DisposableObject"/> which handles common required locking logic.
|
||||
/// </summary>
|
||||
protected override void DisposeResources()
|
||||
{
|
||||
if (_profiler != null)
|
||||
{
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Mail;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Routing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Events;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// A utility class for sending emails
|
||||
/// </summary>
|
||||
public class EmailSender : IEmailSender
|
||||
{
|
||||
//TODO: This should encapsulate a BackgroundTaskRunner with a queue to send these emails!
|
||||
|
||||
private readonly bool _enableEvents;
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
/// </summary>
|
||||
public EmailSender() : this(false)
|
||||
{
|
||||
}
|
||||
|
||||
internal EmailSender(bool enableEvents)
|
||||
{
|
||||
_enableEvents = enableEvents;
|
||||
}
|
||||
|
||||
private static readonly Lazy<bool> SmtpConfigured = new Lazy<bool>(() => GlobalSettings.HasSmtpServerConfigured(HttpRuntime.AppDomainAppVirtualPath));
|
||||
|
||||
/// <summary>
|
||||
/// Sends the message non-async
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
public void Send(MailMessage message)
|
||||
{
|
||||
if (SmtpConfigured.Value == false && _enableEvents)
|
||||
{
|
||||
OnSendEmail(new SendEmailEventArgs(message));
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var client = new SmtpClient())
|
||||
{
|
||||
client.Send(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the message async
|
||||
/// </summary>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public async Task SendAsync(MailMessage message)
|
||||
{
|
||||
if (SmtpConfigured.Value == false && _enableEvents)
|
||||
{
|
||||
OnSendEmail(new SendEmailEventArgs(message));
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var client = new SmtpClient())
|
||||
{
|
||||
if (client.DeliveryMethod == SmtpDeliveryMethod.Network)
|
||||
{
|
||||
await client.SendMailAsync(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
client.Send(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the application should be able to send a required application email
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We assume this is possible if either an event handler is registered or an smtp server is configured
|
||||
/// </remarks>
|
||||
internal static bool CanSendRequiredEmail
|
||||
{
|
||||
get { return EventHandlerRegistered || SmtpConfigured.Value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns true if an event handler has been registered
|
||||
/// </summary>
|
||||
internal static bool EventHandlerRegistered
|
||||
{
|
||||
get { return SendEmail != null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An event that is raised when no smtp server is configured if events are enabled
|
||||
/// </summary>
|
||||
internal static event EventHandler<SendEmailEventArgs> SendEmail;
|
||||
|
||||
private static void OnSendEmail(SendEmailEventArgs e)
|
||||
{
|
||||
var handler = SendEmail;
|
||||
if (handler != null) handler(null, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,9 +111,6 @@ namespace Umbraco.Core
|
||||
/// <returns></returns>
|
||||
public static bool ContainsAll<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> other)
|
||||
{
|
||||
if (source == null) throw new ArgumentNullException("source");
|
||||
if (other == null) throw new ArgumentNullException("other");
|
||||
|
||||
return other.Except(source).Any() == false;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Events
|
||||
/// <summary>
|
||||
/// Event messages collection
|
||||
/// </summary>
|
||||
public sealed class EventMessages : DisposableObjectSlim
|
||||
public sealed class EventMessages : DisposableObject
|
||||
{
|
||||
private readonly List<EventMessage> _msgs = new List<EventMessage>();
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Umbraco.Core.Packaging.Models;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
@@ -8,25 +7,16 @@ namespace Umbraco.Core.Events
|
||||
public class ImportPackageEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportPackageEventArgs<TEntity>>
|
||||
{
|
||||
private readonly MetaData _packageMetaData;
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use the overload specifying packageMetaData instead")]
|
||||
|
||||
public ImportPackageEventArgs(TEntity eventObject, bool canCancel)
|
||||
: base(new[] { eventObject }, canCancel)
|
||||
{
|
||||
}
|
||||
|
||||
public ImportPackageEventArgs(TEntity eventObject, MetaData packageMetaData, bool canCancel)
|
||||
: base(new[] { eventObject }, canCancel)
|
||||
{
|
||||
if (packageMetaData == null) throw new ArgumentNullException("packageMetaData");
|
||||
_packageMetaData = packageMetaData;
|
||||
}
|
||||
|
||||
public ImportPackageEventArgs(TEntity eventObject, MetaData packageMetaData)
|
||||
: this(eventObject, packageMetaData, true)
|
||||
: base(new[] { eventObject })
|
||||
{
|
||||
|
||||
_packageMetaData = packageMetaData;
|
||||
}
|
||||
|
||||
public MetaData PackageMetaData
|
||||
|
||||
@@ -76,257 +76,260 @@ namespace Umbraco.Core.Events
|
||||
{
|
||||
if (_events == null)
|
||||
return Enumerable.Empty<IEventDefinition>();
|
||||
|
||||
IReadOnlyList<IEventDefinition> events;
|
||||
|
||||
switch (filter)
|
||||
{
|
||||
case EventDefinitionFilter.All:
|
||||
events = _events;
|
||||
break;
|
||||
return FilterSupersededAndUpdateToLatestEntity(_events);
|
||||
case EventDefinitionFilter.FirstIn:
|
||||
var l1 = new OrderedHashSet<IEventDefinition>();
|
||||
foreach (var e in _events)
|
||||
{
|
||||
l1.Add(e);
|
||||
events = l1;
|
||||
break;
|
||||
}
|
||||
return FilterSupersededAndUpdateToLatestEntity(l1);
|
||||
case EventDefinitionFilter.LastIn:
|
||||
var l2 = new OrderedHashSet<IEventDefinition>(keepOldest: false);
|
||||
foreach (var e in _events)
|
||||
{
|
||||
l2.Add(e);
|
||||
events = l2;
|
||||
break;
|
||||
}
|
||||
return FilterSupersededAndUpdateToLatestEntity(l2);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("filter", filter, null);
|
||||
}
|
||||
|
||||
return FilterSupersededAndUpdateToLatestEntity(events);
|
||||
}
|
||||
|
||||
private class EventDefinitionInfos
|
||||
|
||||
private class EventDefinitionTypeData
|
||||
{
|
||||
public IEventDefinition EventDefinition { get; set; }
|
||||
public Type[] SupersedeTypes { get; set; }
|
||||
public Type EventArgType { get; set; }
|
||||
public SupersedeEventAttribute[] SupersedeAttributes { get; set; }
|
||||
}
|
||||
|
||||
// fixme
|
||||
// this is way too convoluted, the superceede attribute is used only on DeleteEventargs to specify
|
||||
// that it superceeds save, publish, move and copy - BUT - publish event args is also used for
|
||||
// unpublishing and should NOT be superceeded - so really it should not be managed at event args
|
||||
// level but at event level
|
||||
//
|
||||
// what we want is:
|
||||
// if an entity is deleted, then all Saved, Moved, Copied, Published events prior to this should
|
||||
// not trigger for the entity - and even though, does it make any sense? making a copy of an entity
|
||||
// should ... trigger?
|
||||
//
|
||||
// not going to refactor it all - we probably want to *always* trigger event but tell people that
|
||||
// due to scopes, they should not expected eg a saved entity to still be around - however, now,
|
||||
// going to write a ugly condition to deal with U4-10764
|
||||
|
||||
// iterates over the events (latest first) and filter out any events or entities in event args that are included
|
||||
// in more recent events that Supersede previous ones. For example, If an Entity has been Saved and then Deleted, we don't want
|
||||
// to raise the Saved event (well actually we just don't want to include it in the args for that saved event)
|
||||
internal static IEnumerable<IEventDefinition> FilterSupersededAndUpdateToLatestEntity(IReadOnlyList<IEventDefinition> events)
|
||||
|
||||
/// <summary>
|
||||
/// This will iterate over the events (latest first) and filter out any events or entities in event args that are included
|
||||
/// in more recent events that Supersede previous ones. For example, If an Entity has been Saved and then Deleted, we don't want
|
||||
/// to raise the Saved event (well actually we just don't want to include it in the args for that saved event)
|
||||
/// </summary>
|
||||
/// <param name="events"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<IEventDefinition> FilterSupersededAndUpdateToLatestEntity(IReadOnlyList<IEventDefinition> events)
|
||||
{
|
||||
// keeps the 'latest' entity and associated event data
|
||||
var entities = new List<Tuple<IEntity, EventDefinitionInfos>>();
|
||||
//used to keep the 'latest' entity and associated event definition data
|
||||
var allEntities = new List<Tuple<IEntity, EventDefinitionTypeData>>();
|
||||
|
||||
//tracks all CancellableObjectEventArgs instances in the events which is the only type of args we can work with
|
||||
var cancelableArgs = new List<CancellableObjectEventArgs>();
|
||||
|
||||
// collects the event definitions
|
||||
// collects the arguments in result, that require their entities to be updated
|
||||
var result = new List<IEventDefinition>();
|
||||
var resultArgs = new List<CancellableObjectEventArgs>();
|
||||
|
||||
// eagerly fetch superceeded arg types for each arg type
|
||||
var argTypeSuperceeding = events.Select(x => x.Args.GetType())
|
||||
//This will eagerly load all of the event arg types and their attributes so we don't have to continuously look this data up
|
||||
var allArgTypesWithAttributes = events.Select(x => x.Args.GetType())
|
||||
.Distinct()
|
||||
.ToDictionary(x => x, x => x.GetCustomAttributes<SupersedeEventAttribute>(false).Select(y => y.SupersededEventArgsType).ToArray());
|
||||
|
||||
// iterate over all events and filter
|
||||
//
|
||||
// process the list in reverse, because events are added in the order they are raised and we want to keep
|
||||
// the latest (most recent) entities and filter out what is not relevant anymore (too old), eg if an entity
|
||||
// is Deleted after being Saved, we want to filter out the Saved event
|
||||
.ToDictionary(x => x, x => x.GetCustomAttributes<SupersedeEventAttribute>(false).ToArray());
|
||||
|
||||
//Iterate all events and collect the actual entities in them and relates them to their corresponding EventDefinitionTypeData
|
||||
//we'll process the list in reverse because events are added in the order they are raised and we want to filter out
|
||||
//any entities from event args that are not longer relevant
|
||||
//(i.e. if an item is Deleted after it's Saved, we won't include the item in the Saved args)
|
||||
for (var index = events.Count - 1; index >= 0; index--)
|
||||
{
|
||||
var def = events[index];
|
||||
var eventDefinition = events[index];
|
||||
|
||||
var infos = new EventDefinitionInfos
|
||||
var argType = eventDefinition.Args.GetType();
|
||||
var attributes = allArgTypesWithAttributes[eventDefinition.Args.GetType()];
|
||||
|
||||
var meta = new EventDefinitionTypeData
|
||||
{
|
||||
EventDefinition = def,
|
||||
SupersedeTypes = argTypeSuperceeding[def.Args.GetType()]
|
||||
EventDefinition = eventDefinition,
|
||||
EventArgType = argType,
|
||||
SupersedeAttributes = attributes
|
||||
};
|
||||
|
||||
var args = def.Args as CancellableObjectEventArgs;
|
||||
if (args == null)
|
||||
var args = eventDefinition.Args as CancellableObjectEventArgs;
|
||||
if (args != null)
|
||||
{
|
||||
// not a cancellable event arg, include event definition in result
|
||||
result.Add(def);
|
||||
}
|
||||
else
|
||||
{
|
||||
// event object can either be a single object or an enumerable of objects
|
||||
// try to get as an enumerable, get null if it's not
|
||||
var eventObjects = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject);
|
||||
if (eventObjects == null)
|
||||
var list = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject);
|
||||
|
||||
if (list == null)
|
||||
{
|
||||
// single object, cast as an IEntity
|
||||
// if cannot cast, cannot filter, nothing - just include event definition in result
|
||||
var eventEntity = args.EventObject as IEntity;
|
||||
if (eventEntity == null)
|
||||
//extract the event object
|
||||
var obj = args.EventObject as IEntity;
|
||||
if (obj != null)
|
||||
{
|
||||
result.Add(def);
|
||||
continue;
|
||||
//Now check if this entity already exists in other event args that supersede this current event arg type
|
||||
if (IsFiltered(obj, meta, allEntities) == false)
|
||||
{
|
||||
//if it's not filtered we can adde these args to the response
|
||||
cancelableArgs.Add(args);
|
||||
result.Add(eventDefinition);
|
||||
//track the entity
|
||||
allEntities.Add(Tuple.Create(obj, meta));
|
||||
}
|
||||
}
|
||||
|
||||
// look for this entity in superceding event args
|
||||
// found = must be removed (ie not added), else track
|
||||
if (IsSuperceeded(eventEntity, infos, entities) == false)
|
||||
else
|
||||
{
|
||||
// track
|
||||
entities.Add(Tuple.Create(eventEntity, infos));
|
||||
|
||||
// track result arguments
|
||||
// include event definition in result
|
||||
resultArgs.Add(args);
|
||||
result.Add(def);
|
||||
//Can't retrieve the entity so cant' filter or inspect, just add to the output
|
||||
result.Add(eventDefinition);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// enumerable of objects
|
||||
var toRemove = new List<IEntity>();
|
||||
foreach (var eventObject in eventObjects)
|
||||
foreach (var entity in list)
|
||||
{
|
||||
// extract the event object, cast as an IEntity
|
||||
// if cannot cast, cannot filter, nothing to do - just leave it in the list & continue
|
||||
var eventEntity = eventObject as IEntity;
|
||||
if (eventEntity == null)
|
||||
continue;
|
||||
|
||||
// look for this entity in superceding event args
|
||||
// found = must be removed, else track
|
||||
if (IsSuperceeded(eventEntity, infos, entities))
|
||||
toRemove.Add(eventEntity);
|
||||
//extract the event object
|
||||
var obj = entity as IEntity;
|
||||
if (obj != null)
|
||||
{
|
||||
//Now check if this entity already exists in other event args that supersede this current event arg type
|
||||
if (IsFiltered(obj, meta, allEntities))
|
||||
{
|
||||
//track it to be removed
|
||||
toRemove.Add(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
//track the entity, it's not filtered
|
||||
allEntities.Add(Tuple.Create(obj, meta));
|
||||
}
|
||||
}
|
||||
else
|
||||
entities.Add(Tuple.Create(eventEntity, infos));
|
||||
{
|
||||
//we don't need to do anything here, we can't cast to IEntity so we cannot filter, so it will just remain in the list
|
||||
}
|
||||
}
|
||||
|
||||
// remove superceded entities
|
||||
//remove anything that has been filtered
|
||||
foreach (var entity in toRemove)
|
||||
eventObjects.Remove(entity);
|
||||
{
|
||||
list.Remove(entity);
|
||||
}
|
||||
|
||||
// if there are still entities in the list, keep the event definition
|
||||
if (eventObjects.Count > 0)
|
||||
//track the event and include in the response if there's still entities remaining in the list
|
||||
if (list.Count > 0)
|
||||
{
|
||||
if (toRemove.Count > 0)
|
||||
{
|
||||
// re-assign if changed
|
||||
args.EventObject = eventObjects;
|
||||
//re-assign if the items have changed
|
||||
args.EventObject = list;
|
||||
}
|
||||
|
||||
// track result arguments
|
||||
// include event definition in result
|
||||
resultArgs.Add(args);
|
||||
result.Add(def);
|
||||
cancelableArgs.Add(args);
|
||||
result.Add(eventDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//it's not a cancelable event arg so we just include it in the result
|
||||
result.Add(eventDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
// go over all args in result, and update them with the latest instanceof each entity
|
||||
UpdateToLatestEntities(entities, resultArgs);
|
||||
//Now we'll deal with ensuring that only the latest(non stale) entities are used throughout all event args
|
||||
UpdateToLatestEntities(allEntities, cancelableArgs);
|
||||
|
||||
// reverse, since we processed the list in reverse
|
||||
//we need to reverse the result since we've been adding by latest added events first!
|
||||
result.Reverse();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// edits event args to use the latest instance of each entity
|
||||
private static void UpdateToLatestEntities(IEnumerable<Tuple<IEntity, EventDefinitionInfos>> entities, IEnumerable<CancellableObjectEventArgs> args)
|
||||
private static void UpdateToLatestEntities(IEnumerable<Tuple<IEntity, EventDefinitionTypeData>> allEntities, IEnumerable<CancellableObjectEventArgs> cancelableArgs)
|
||||
{
|
||||
// get the latest entities
|
||||
// ordered hash set + keepOldest will keep the latest inserted entity (in case of duplicates)
|
||||
var latestEntities = new OrderedHashSet<IEntity>(keepOldest: true);
|
||||
foreach (var entity in entities.OrderByDescending(entity => entity.Item1.UpdateDate))
|
||||
latestEntities.Add(entity.Item1);
|
||||
//Now we'll deal with ensuring that only the latest(non stale) entities are used throughout all event args
|
||||
|
||||
foreach (var arg in args)
|
||||
var latestEntities = new OrderedHashSet<IEntity>(keepOldest: true);
|
||||
foreach (var entity in allEntities.OrderByDescending(entity => entity.Item1.UpdateDate))
|
||||
{
|
||||
// event object can either be a single object or an enumerable of objects
|
||||
// try to get as an enumerable, get null if it's not
|
||||
var eventObjects = TypeHelper.CreateGenericEnumerableFromObject(arg.EventObject);
|
||||
if (eventObjects == null)
|
||||
latestEntities.Add(entity.Item1);
|
||||
}
|
||||
|
||||
foreach (var args in cancelableArgs)
|
||||
{
|
||||
var list = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject);
|
||||
if (list == null)
|
||||
{
|
||||
// single object
|
||||
// look for a more recent entity for that object, and replace if any
|
||||
// works by "equalling" entities ie the more recent one "equals" this one (though different object)
|
||||
var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, arg.EventObject));
|
||||
//try to find the args entity in the latest entity - based on the equality operators, this will
|
||||
//match by Id since that is the default equality checker for IEntity. If one is found, than it is
|
||||
//the most recent entity instance so update the args with that instance so we don't emit a stale instance.
|
||||
var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, args.EventObject));
|
||||
if (foundEntity != null)
|
||||
arg.EventObject = foundEntity;
|
||||
{
|
||||
args.EventObject = foundEntity;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// enumerable of objects
|
||||
// same as above but for each object
|
||||
var updated = false;
|
||||
for (var i = 0; i < eventObjects.Count; i++)
|
||||
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, eventObjects[i]));
|
||||
if (foundEntity == null) continue;
|
||||
eventObjects[i] = foundEntity;
|
||||
updated = true;
|
||||
//try to find the args entity in the latest entity - based on the equality operators, this will
|
||||
//match by Id since that is the default equality checker for IEntity. If one is found, than it is
|
||||
//the most recent entity instance so update the args with that instance so we don't emit a stale instance.
|
||||
var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, list[i]));
|
||||
if (foundEntity != null)
|
||||
{
|
||||
list[i] = foundEntity;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (updated)
|
||||
arg.EventObject = eventObjects;
|
||||
{
|
||||
args.EventObject = list;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// determines if a given entity, appearing in a given event definition, should be filtered out,
|
||||
// considering the entities that have already been visited - an entity is filtered out if it
|
||||
// appears in another even definition, which superceedes this event definition.
|
||||
private static bool IsSuperceeded(IEntity entity, EventDefinitionInfos infos, List<Tuple<IEntity, EventDefinitionInfos>> entities)
|
||||
/// <summary>
|
||||
/// This will check against all of the processed entity/events (allEntities) to see if this entity already exists in
|
||||
/// event args that supersede the event args being passed in and if so returns true.
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="eventDef"></param>
|
||||
/// <param name="allEntities"></param>
|
||||
/// <returns></returns>
|
||||
private static bool IsFiltered(
|
||||
IEntity entity,
|
||||
EventDefinitionTypeData eventDef,
|
||||
List<Tuple<IEntity, EventDefinitionTypeData>> allEntities)
|
||||
{
|
||||
//var argType = meta.EventArgsType;
|
||||
var argType = infos.EventDefinition.Args.GetType();
|
||||
var argType = eventDef.EventDefinition.Args.GetType();
|
||||
|
||||
// look for other instances of the same entity, coming from an event args that supercedes 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
|
||||
&& Equals(x.Item1, entity)) // same entity
|
||||
//check if the entity is found in any processed event data that could possible supersede this one
|
||||
var foundByEntity = allEntities
|
||||
.Where(x => x.Item2.SupersedeAttributes.Length > 0
|
||||
//if it's the same arg type than it cannot supersede
|
||||
&& x.Item2.EventArgType != argType
|
||||
&& Equals(x.Item1, entity))
|
||||
.ToArray();
|
||||
|
||||
// first time we see this entity = not filtered
|
||||
if (superceeding.Length == 0)
|
||||
//no args have been processed with this entity so it should not be filtered
|
||||
if (foundByEntity.Length == 0)
|
||||
return false;
|
||||
|
||||
// fixme see notes above
|
||||
// delete event args does NOT superceedes 'unpublished' event
|
||||
if (argType.IsGenericType && argType.GetGenericTypeDefinition() == typeof(PublishEventArgs<>) && infos.EventDefinition.EventName == "UnPublished")
|
||||
return false;
|
||||
|
||||
// found occurences, need to determine if this event args is superceded
|
||||
if (argType.IsGenericType)
|
||||
{
|
||||
// generic, must compare type arguments
|
||||
var supercededBy = superceeding.FirstOrDefault(x =>
|
||||
x.Item2.SupersedeTypes.Any(y =>
|
||||
// superceeding a generic type which has the same generic type definition
|
||||
// fixme no matter the generic type parameters? could be different?
|
||||
y.IsGenericTypeDefinition && y == argType.GetGenericTypeDefinition()
|
||||
// or superceeding a non-generic type which is ... fixme how is this ever possible? argType *is* generic?
|
||||
|| y.IsGenericTypeDefinition == false && y == argType));
|
||||
var supercededBy = foundByEntity
|
||||
.FirstOrDefault(x =>
|
||||
x.Item2.SupersedeAttributes.Any(y =>
|
||||
//if the attribute type is a generic type def then compare with the generic type def of the event arg
|
||||
(y.SupersededEventArgsType.IsGenericTypeDefinition && y.SupersededEventArgsType == argType.GetGenericTypeDefinition())
|
||||
//if the attribute type is not a generic type def then compare with the normal type of the event arg
|
||||
|| (y.SupersededEventArgsType.IsGenericTypeDefinition == false && y.SupersededEventArgsType == argType)));
|
||||
return supercededBy != null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// non-generic, can compare types 1:1
|
||||
var supercededBy = superceeding.FirstOrDefault(x =>
|
||||
x.Item2.SupersedeTypes.Any(y => y == argType));
|
||||
var supercededBy = foundByEntity
|
||||
.FirstOrDefault(x =>
|
||||
x.Item2.SupersedeAttributes.Any(y =>
|
||||
//since the event arg type is not a generic type, then we just compare type 1:1
|
||||
y.SupersededEventArgsType == argType));
|
||||
return supercededBy != null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
using System;
|
||||
using System.Net.Mail;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
internal class SendEmailEventArgs : EventArgs
|
||||
{
|
||||
public MailMessage Message { get; private set; }
|
||||
|
||||
public SendEmailEventArgs(MailMessage message)
|
||||
{
|
||||
Message = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -217,21 +217,8 @@ namespace Umbraco.Core
|
||||
public static MemberInfo GetMemberInfo<T, TReturn>(Expression<Func<T, TReturn>> fromExpression)
|
||||
{
|
||||
if (fromExpression == null) return null;
|
||||
|
||||
MemberExpression me;
|
||||
switch (fromExpression.Body.NodeType)
|
||||
{
|
||||
case ExpressionType.Convert:
|
||||
case ExpressionType.ConvertChecked:
|
||||
var ue = fromExpression.Body as UnaryExpression;
|
||||
me = ((ue != null) ? ue.Operand : null) as MemberExpression;
|
||||
break;
|
||||
default:
|
||||
me = fromExpression.Body as MemberExpression;
|
||||
break;
|
||||
}
|
||||
|
||||
return me != null ? me.Member : null;
|
||||
var body = fromExpression.Body as MemberExpression;
|
||||
return body != null ? body.Member : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Umbraco.Core
|
||||
/// This will use the crypto libs to generate the hash and will try to ensure that
|
||||
/// strings, etc... are not re-allocated so it's not consuming much memory.
|
||||
/// </remarks>
|
||||
internal class HashGenerator : DisposableObjectSlim
|
||||
internal class HashGenerator : DisposableObject
|
||||
{
|
||||
public HashGenerator()
|
||||
{
|
||||
|
||||
@@ -26,13 +26,13 @@ namespace Umbraco.Core
|
||||
var ipAddress = httpContext.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
|
||||
|
||||
if (string.IsNullOrEmpty(ipAddress))
|
||||
return httpContext.Request.UserHostAddress;
|
||||
return httpContext.Request.ServerVariables["REMOTE_ADDR"];
|
||||
|
||||
var addresses = ipAddress.Split(',');
|
||||
if (addresses.Length != 0)
|
||||
return addresses[0];
|
||||
|
||||
return httpContext.Request.UserHostAddress;
|
||||
return httpContext.Request.ServerVariables["REMOTE_ADDR"];
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using System.Net.Mail;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple abstraction to send an email message
|
||||
/// </summary>
|
||||
public interface IEmailSender
|
||||
{
|
||||
Task SendAsync(MailMessage message);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
public class FileSystemProviderManager
|
||||
{
|
||||
private readonly IFileSystemProvidersSection _config;
|
||||
private readonly FileSystemProvidersSection _config;
|
||||
private readonly ConcurrentSet<ShadowWrapper> _wrappers = new ConcurrentSet<ShadowWrapper>();
|
||||
|
||||
private readonly ConcurrentDictionary<string, ProviderConstructionInfo> _providerLookup = new ConcurrentDictionary<string, ProviderConstructionInfo>();
|
||||
@@ -28,45 +28,16 @@ namespace Umbraco.Core.IO
|
||||
private ShadowWrapper _mvcViewsFileSystem;
|
||||
|
||||
#region Singleton & Constructor
|
||||
|
||||
private static volatile FileSystemProviderManager _instance;
|
||||
private static readonly object _instanceLocker = new object();
|
||||
|
||||
private static readonly FileSystemProviderManager Instance = new FileSystemProviderManager();
|
||||
|
||||
public static FileSystemProviderManager Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance != null) return _instance;
|
||||
lock (_instanceLocker)
|
||||
{
|
||||
return _instance ?? (_instance = new FileSystemProviderManager());
|
||||
}
|
||||
}
|
||||
get { return Instance; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For tests only, allows setting the value of the singleton "Current" property
|
||||
/// </summary>
|
||||
/// <param name="instance"></param>
|
||||
public static void SetCurrent(FileSystemProviderManager instance)
|
||||
{
|
||||
lock (_instanceLocker)
|
||||
{
|
||||
_instance = instance;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void ResetCurrent()
|
||||
{
|
||||
lock (_instanceLocker)
|
||||
{
|
||||
if (_instance != null)
|
||||
_instance.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
// for tests only, totally unsafe
|
||||
private void Reset()
|
||||
internal void Reset()
|
||||
{
|
||||
_wrappers.Clear();
|
||||
_providerLookup.Clear();
|
||||
@@ -81,24 +52,10 @@ namespace Umbraco.Core.IO
|
||||
// beware: means that we capture the "current" scope provider - take care in tests!
|
||||
get { return ApplicationContext.Current == null ? null : ApplicationContext.Current.ScopeProvider as IScopeProviderInternal; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that can be used for tests
|
||||
/// </summary>
|
||||
/// <param name="configSection"></param>
|
||||
public FileSystemProviderManager(IFileSystemProvidersSection configSection)
|
||||
|
||||
internal FileSystemProviderManager()
|
||||
{
|
||||
if (configSection == null) throw new ArgumentNullException("configSection");
|
||||
_config = configSection;
|
||||
CreateWellKnownFileSystems();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor that will read the config from the locally found config section
|
||||
/// </summary>
|
||||
public FileSystemProviderManager()
|
||||
{
|
||||
_config = (FileSystemProvidersSection)ConfigurationManager.GetSection("umbracoConfiguration/FileSystemProviders");
|
||||
_config = (FileSystemProvidersSection) ConfigurationManager.GetSection("umbracoConfiguration/FileSystemProviders");
|
||||
CreateWellKnownFileSystems();
|
||||
}
|
||||
|
||||
@@ -193,9 +150,8 @@ namespace Umbraco.Core.IO
|
||||
private ProviderConstructionInfo GetUnderlyingFileSystemCtor(string alias, Func<IFileSystem> fallback)
|
||||
{
|
||||
// get config
|
||||
IFileSystemProviderElement providerConfig;
|
||||
|
||||
if (_config.Providers.TryGetValue(alias, out providerConfig) == false)
|
||||
var providerConfig = _config.Providers[alias];
|
||||
if (providerConfig == null)
|
||||
{
|
||||
if (fallback != null) return null;
|
||||
throw new ArgumentException(string.Format("No provider found with alias {0}.", alias));
|
||||
@@ -210,21 +166,17 @@ namespace Umbraco.Core.IO
|
||||
if (providerType.IsAssignableFrom(typeof(IFileSystem)))
|
||||
throw new InvalidOperationException(string.Format("Type {0} does not implement IFileSystem.", providerType.FullName));
|
||||
|
||||
// find a ctor matching the config parameters
|
||||
// find a ctor matching the config parameters
|
||||
var paramCount = providerConfig.Parameters != null ? providerConfig.Parameters.Count : 0;
|
||||
var constructor = providerType.GetConstructors().SingleOrDefault(x
|
||||
=> x.GetParameters().Length == paramCount && x.GetParameters().All(y => providerConfig.Parameters.Keys.Contains(y.Name)));
|
||||
=> x.GetParameters().Length == paramCount && x.GetParameters().All(y => providerConfig.Parameters.AllKeys.Contains(y.Name)));
|
||||
if (constructor == null)
|
||||
throw new InvalidOperationException(string.Format("Type {0} has no ctor matching the {1} configuration parameter(s).", providerType.FullName, paramCount));
|
||||
|
||||
var parameters = new object[paramCount];
|
||||
|
||||
if (providerConfig.Parameters != null)
|
||||
{
|
||||
var allKeys = providerConfig.Parameters.Keys.ToArray();
|
||||
if (providerConfig.Parameters != null) // keeps ReSharper happy
|
||||
for (var i = 0; i < paramCount; i++)
|
||||
parameters[i] = providerConfig.Parameters[allKeys[i]];
|
||||
}
|
||||
parameters[i] = providerConfig.Parameters[providerConfig.Parameters.AllKeys[i]].Value;
|
||||
|
||||
return new ProviderConstructionInfo
|
||||
{
|
||||
|
||||
@@ -13,28 +13,11 @@ using Umbraco.Core.Configuration;
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
public static class IOHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value forcing Umbraco to consider it is non-hosted.
|
||||
/// </summary>
|
||||
/// <remarks>This should always be false, unless unit testing.</remarks>
|
||||
public static bool ForceNotHosted { get; set; }
|
||||
|
||||
{
|
||||
private static string _rootDir = "";
|
||||
|
||||
// static compiled regex for faster performance
|
||||
private readonly static Regex ResolveUrlPattern = new Regex("(=[\"\']?)(\\W?\\~(?:.(?![\"\']?\\s+(?:\\S+)=|[>\"\']))+.)[\"\']?", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether Umbraco is hosted.
|
||||
/// </summary>
|
||||
public static bool IsHosted
|
||||
{
|
||||
get
|
||||
{
|
||||
return ForceNotHosted == false && (HttpContext.Current != null || HostingEnvironment.IsHosted);
|
||||
}
|
||||
}
|
||||
|
||||
public static char DirSepChar
|
||||
{
|
||||
@@ -89,14 +72,14 @@ namespace Umbraco.Core.IO
|
||||
internal static string ResolveUrlsFromTextString(string text)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.ResolveUrlsFromTextString)
|
||||
{
|
||||
{
|
||||
using (DisposableTimer.DebugDuration(typeof(IOHelper), "ResolveUrlsFromTextString starting", "ResolveUrlsFromTextString complete"))
|
||||
{
|
||||
// find all relative urls (ie. urls that contain ~)
|
||||
var tags = ResolveUrlPattern.Matches(text);
|
||||
|
||||
|
||||
foreach (Match tag in tags)
|
||||
{
|
||||
{
|
||||
string url = "";
|
||||
if (tag.Groups[1].Success)
|
||||
url = tag.Groups[1].Value;
|
||||
@@ -114,8 +97,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public static string MapPath(string path, bool useHttpContext)
|
||||
{
|
||||
if (path == null) throw new ArgumentNullException("path");
|
||||
useHttpContext = useHttpContext && IsHosted;
|
||||
if (path == null) throw new ArgumentNullException("path");
|
||||
|
||||
// Check if the path is already mapped
|
||||
if ((path.Length >= 2 && path[1] == Path.VolumeSeparatorChar)
|
||||
@@ -321,7 +303,7 @@ namespace Umbraco.Core.IO
|
||||
var debugFolder = Path.Combine(binFolder, "debug");
|
||||
if (Directory.Exists(debugFolder))
|
||||
return debugFolder;
|
||||
#endif
|
||||
#endif
|
||||
var releaseFolder = Path.Combine(binFolder, "release");
|
||||
if (Directory.Exists(releaseFolder))
|
||||
return releaseFolder;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
@@ -108,7 +107,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
try
|
||||
{
|
||||
WithRetry(() => Directory.Delete(fullPath, recursive));
|
||||
Directory.Delete(fullPath, recursive);
|
||||
}
|
||||
catch (DirectoryNotFoundException ex)
|
||||
{
|
||||
@@ -226,8 +225,8 @@ namespace Umbraco.Core.IO
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
WithRetry(() => File.Delete(fullPath));
|
||||
{
|
||||
File.Delete(fullPath);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
@@ -379,7 +378,7 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
if (overrideIfExists == false)
|
||||
throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", path));
|
||||
WithRetry(() => File.Delete(fullPath));
|
||||
File.Delete(fullPath);
|
||||
}
|
||||
|
||||
var directory = Path.GetDirectoryName(fullPath);
|
||||
@@ -387,9 +386,9 @@ namespace Umbraco.Core.IO
|
||||
Directory.CreateDirectory(directory); // ensure it exists
|
||||
|
||||
if (copy)
|
||||
WithRetry(() => File.Copy(physicalPath, fullPath));
|
||||
File.Copy(physicalPath, fullPath);
|
||||
else
|
||||
WithRetry(() => File.Move(physicalPath, fullPath));
|
||||
File.Move(physicalPath, fullPath);
|
||||
}
|
||||
|
||||
#region Helper Methods
|
||||
@@ -418,35 +417,6 @@ namespace Umbraco.Core.IO
|
||||
return path;
|
||||
}
|
||||
|
||||
protected void WithRetry(Action action)
|
||||
{
|
||||
// 10 times 100ms is 1s
|
||||
const int count = 10;
|
||||
const int pausems = 100;
|
||||
|
||||
for (var i = 0;; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
action();
|
||||
break; // done
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// if it's not *exactly* IOException then it could be
|
||||
// some inherited exception such as FileNotFoundException,
|
||||
// and then we don't want to retry
|
||||
if (e.GetType() != typeof(IOException)) throw;
|
||||
|
||||
// if we have tried enough, throw, else swallow
|
||||
// the exception and retry after a pause
|
||||
if (i == count) throw;
|
||||
}
|
||||
|
||||
Thread.Sleep(pausems);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,10 +79,10 @@ namespace Umbraco.Core.IO
|
||||
return Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData\umbraco.config");
|
||||
case LocalTempStorage.EnvironmentTemp:
|
||||
var appDomainHash = HttpRuntime.AppDomainAppId.ToSHA1();
|
||||
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData",
|
||||
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
|
||||
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
|
||||
// utilizing an old path
|
||||
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoXml",
|
||||
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
|
||||
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
|
||||
// utilizing an old path
|
||||
appDomainHash);
|
||||
return Path.Combine(cachePath, "umbraco.config");
|
||||
case LocalTempStorage.Default:
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using log4net.Appender;
|
||||
using log4net.Util;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// This class will do the exact same thing as the RollingFileAppender that comes from log4net
|
||||
/// With the extension, that it is able to do automatic cleanup of the logfiles in the directory where logging happens
|
||||
///
|
||||
/// By specifying the properties MaxLogFileDays and BaseFilePattern, the files will automaticly get deleted when
|
||||
/// the logger is configured(typically when the app starts). To utilize this appender swap out the type of the rollingFile appender
|
||||
/// that ships with Umbraco, to be Umbraco.Core.Logging.RollingFileCleanupAppender, and add the maxLogFileDays and baseFilePattern elements
|
||||
/// to the configuration i.e.:
|
||||
///
|
||||
/// <example>
|
||||
/// <appender name="rollingFile" type="Log4netAwesomeness.CustomRollingFileAppender, Log4netAwesomeness">
|
||||
/// <file type="log4net.Util.PatternString" value="App_Data\Logs\UmbracoTraceLog.%property{log4net:HostName}.txt" />
|
||||
/// <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
|
||||
/// <appendToFile value="true" />
|
||||
/// <rollingStyle value="Date" />
|
||||
/// <maximumFileSize value="5MB" />
|
||||
/// <maxLogFileDays value="5"/>
|
||||
/// <basefilePattern value="UmbracoTraceLog.*.txt.*"/>
|
||||
/// <layout type="log4net.Layout.PatternLayout">
|
||||
/// <conversionPattern value=" %date [P%property{processId}/D%property{appDomainId}/T%thread] %-5level %logger - %message%newline" />
|
||||
/// </layout>
|
||||
/// <layout type="log4net.Layout.PatternLayout">
|
||||
/// <conversionPattern value=" %date [P%property{processId}/D%property{appDomainId}/T%thread] %-5level %logger - %message%newline" />
|
||||
/// </layout>
|
||||
/// <encoding value="utf-8" />
|
||||
/// </appender>
|
||||
/// </example>
|
||||
/// </summary>
|
||||
public class RollingFileCleanupAppender : RollingFileAppender
|
||||
{
|
||||
public int MaxLogFileDays { get; set; }
|
||||
public string BaseFilePattern { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This override will delete logs older than the specified amount of days
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="append"></param>
|
||||
protected override void OpenFile(string fileName, bool append)
|
||||
{
|
||||
bool cleanup = true;
|
||||
// Validate settings and input
|
||||
if (MaxLogFileDays <= 0)
|
||||
{
|
||||
LogLog.Warn(typeof(RollingFileCleanupAppender), "Parameter 'MaxLogFileDays' needs to be a positive integer, aborting cleanup");
|
||||
cleanup = false;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(BaseFilePattern))
|
||||
{
|
||||
LogLog.Warn(typeof(RollingFileCleanupAppender), "Parameter 'BaseFilePattern' is empty, aborting cleanup");
|
||||
cleanup = false;
|
||||
}
|
||||
// grab the directory we are logging to, as this is were we will search for older logfiles
|
||||
var logFolder = Path.GetDirectoryName(fileName);
|
||||
if (Directory.Exists(logFolder) == false)
|
||||
{
|
||||
LogLog.Warn(typeof(RollingFileCleanupAppender), string.Format("Directory '{0}' for logfiles does not exist, aborting cleanup", logFolder));
|
||||
cleanup = false;
|
||||
}
|
||||
// If everything is validated, we can do the actual cleanup
|
||||
if (cleanup)
|
||||
{
|
||||
Cleanup(logFolder);
|
||||
}
|
||||
|
||||
base.OpenFile(fileName, append);
|
||||
}
|
||||
|
||||
private void Cleanup(string directoryPath)
|
||||
{
|
||||
// only take files that matches the pattern we are using i.e. UmbracoTraceLog.*.txt.*
|
||||
string[] logFiles = Directory.GetFiles(directoryPath, BaseFilePattern);
|
||||
LogLog.Debug(typeof(RollingFileCleanupAppender), string.Format("Found {0} files that matches the baseFilePattern: '{1}'", logFiles.Length, BaseFilePattern));
|
||||
|
||||
foreach (var logFile in logFiles)
|
||||
{
|
||||
DateTime lastAccessTime = System.IO.File.GetLastWriteTimeUtc(logFile);
|
||||
// take the value from the config file
|
||||
if (lastAccessTime < DateTime.Now.AddDays(-MaxLogFileDays))
|
||||
{
|
||||
LogLog.Debug(typeof(RollingFileCleanupAppender), string.Format("Deleting file {0} as its lastAccessTime is older than {1} days speficied by MaxLogFileDays", logFile, MaxLogFileDays));
|
||||
base.DeleteFile(logFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Manifest
|
||||
{
|
||||
internal class ManifestWatcher : DisposableObjectSlim
|
||||
internal class ManifestWatcher : DisposableObject
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly List<FileSystemWatcher> _fws = new List<FileSystemWatcher>();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
|
||||
@@ -2,30 +2,18 @@
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public sealed class AuditItem : Entity, IAuditItem
|
||||
public sealed class AuditItem : Entity, IAggregateRoot
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor for creating an item to be created
|
||||
/// </summary>
|
||||
/// <param name="objectId"></param>
|
||||
/// <param name="comment"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="userId"></param>
|
||||
public AuditItem(int objectId, string comment, AuditType type, int userId)
|
||||
{
|
||||
DisableChangeTracking();
|
||||
|
||||
Id = objectId;
|
||||
Comment = comment;
|
||||
AuditType = type;
|
||||
UserId = userId;
|
||||
|
||||
EnableChangeTracking();
|
||||
}
|
||||
|
||||
public string Comment { get; private set; }
|
||||
public AuditType AuditType { get; private set; }
|
||||
public int UserId { get; private set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Core.Models
|
||||
private DateTime? _expireDate;
|
||||
private int _writer;
|
||||
private string _nodeName;//NOTE Once localization is introduced this will be the non-localized Node Name.
|
||||
|
||||
private bool _permissionsChanged;
|
||||
/// <summary>
|
||||
/// Constructor for creating a Content object
|
||||
/// </summary>
|
||||
@@ -29,7 +29,7 @@ namespace Umbraco.Core.Models
|
||||
/// <param name="contentType">ContentType for the current Content object</param>
|
||||
public Content(string name, IContent parent, IContentType contentType)
|
||||
: this(name, parent, contentType, new PropertyCollection())
|
||||
{
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -65,7 +65,7 @@ namespace Umbraco.Core.Models
|
||||
/// <param name="parentId">Id of the Parent content</param>
|
||||
/// <param name="contentType">ContentType for the current Content object</param>
|
||||
/// <param name="properties">Collection of properties</param>
|
||||
public Content(string name, int parentId, IContentType contentType, PropertyCollection properties)
|
||||
public Content(string name, int parentId, IContentType contentType, PropertyCollection properties)
|
||||
: base(name, parentId, contentType, properties)
|
||||
{
|
||||
Mandate.ParameterNotNull(contentType, "contentType");
|
||||
@@ -84,6 +84,7 @@ namespace Umbraco.Core.Models
|
||||
public readonly PropertyInfo ExpireDateSelector = ExpressionHelper.GetPropertyInfo<Content, DateTime?>(x => x.ExpireDate);
|
||||
public readonly PropertyInfo WriterSelector = ExpressionHelper.GetPropertyInfo<Content, int>(x => x.WriterId);
|
||||
public readonly PropertyInfo NodeNameSelector = ExpressionHelper.GetPropertyInfo<Content, string>(x => x.NodeName);
|
||||
public readonly PropertyInfo PermissionsChangedSelector = ExpressionHelper.GetPropertyInfo<Content, bool>(x => x.PermissionsChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -91,7 +92,7 @@ namespace Umbraco.Core.Models
|
||||
/// This is used to override the default one from the ContentType.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If no template is explicitly set on the Content object,
|
||||
/// If no template is explicitly set on the Content object,
|
||||
/// the Default template from the ContentType will be returned.
|
||||
/// </remarks>
|
||||
[DataMember]
|
||||
@@ -193,6 +194,15 @@ namespace Umbraco.Core.Models
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _nodeName, Ps.Value.NodeNameSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to track if permissions have been changed during the saving process for this entity
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
internal bool PermissionsChanged
|
||||
{
|
||||
get { return _permissionsChanged; }
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _permissionsChanged, Ps.Value.PermissionsChangedSelector); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ContentType used by this content object
|
||||
@@ -264,9 +274,6 @@ namespace Umbraco.Core.Models
|
||||
[IgnoreDataMember]
|
||||
internal DateTime PublishedDate { get; set; }
|
||||
|
||||
[DataMember]
|
||||
public bool IsBlueprint { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Changes the Trashed state of the content object
|
||||
/// </summary>
|
||||
@@ -283,7 +290,7 @@ namespace Umbraco.Core.Models
|
||||
ChangePublishedState(PublishedState.Unpublished);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Method to call when Entity is being updated
|
||||
/// </summary>
|
||||
|
||||
@@ -54,11 +54,6 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
public readonly PropertyInfo DefaultTemplateSelector = ExpressionHelper.GetPropertyInfo<ContentType, int>(x => x.DefaultTemplateId);
|
||||
public readonly PropertyInfo AllowedTemplatesSelector = ExpressionHelper.GetPropertyInfo<ContentType, IEnumerable<ITemplate>>(x => x.AllowedTemplates);
|
||||
|
||||
//Custom comparer for enumerable
|
||||
public readonly DelegateEqualityComparer<IEnumerable<ITemplate>> TemplateComparer = new DelegateEqualityComparer<IEnumerable<ITemplate>>(
|
||||
(templates, enumerable) => templates.UnsortedSequenceEqual(enumerable),
|
||||
templates => templates.GetHashCode());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -95,10 +90,11 @@ namespace Umbraco.Core.Models
|
||||
get { return _allowedTemplates; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(value, ref _allowedTemplates, Ps.Value.AllowedTemplatesSelector, Ps.Value.TemplateComparer);
|
||||
|
||||
if (_allowedTemplates.Any(x => x.Id == _defaultTemplate) == false)
|
||||
DefaultTemplateId = 0;
|
||||
SetPropertyValueAndDetectChanges(value, ref _allowedTemplates, Ps.Value.AllowedTemplatesSelector,
|
||||
//Custom comparer for enumerable
|
||||
new DelegateEqualityComparer<IEnumerable<ITemplate>>(
|
||||
(templates, enumerable) => templates.UnsortedSequenceEqual(enumerable),
|
||||
templates => templates.GetHashCode()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,12 +88,6 @@ namespace Umbraco.Core.Models
|
||||
public readonly PropertyInfo PropertyGroupCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, PropertyGroupCollection>(x => x.PropertyGroups);
|
||||
public readonly PropertyInfo PropertyTypeCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, IEnumerable<PropertyType>>(x => x.PropertyTypes);
|
||||
public readonly PropertyInfo HasPropertyTypeBeenRemovedSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.HasPropertyTypeBeenRemoved);
|
||||
|
||||
//Custom comparer for enumerable
|
||||
public readonly DelegateEqualityComparer<IEnumerable<ContentTypeSort>> ContentTypeSortComparer =
|
||||
new DelegateEqualityComparer<IEnumerable<ContentTypeSort>>(
|
||||
(sorts, enumerable) => sorts.UnsortedSequenceEqual(enumerable),
|
||||
sorts => sorts.GetHashCode());
|
||||
}
|
||||
|
||||
|
||||
@@ -260,7 +254,7 @@ namespace Umbraco.Core.Models
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _trashed, Ps.Value.TrashedSelector); }
|
||||
}
|
||||
|
||||
private readonly IDictionary<string, object> _additionalData;
|
||||
private IDictionary<string, object> _additionalData;
|
||||
/// <summary>
|
||||
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
|
||||
/// </summary>
|
||||
@@ -279,8 +273,11 @@ namespace Umbraco.Core.Models
|
||||
get { return _allowedContentTypes; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(value, ref _allowedContentTypes, Ps.Value.AllowedContentTypesSelector,
|
||||
Ps.Value.ContentTypeSortComparer);
|
||||
SetPropertyValueAndDetectChanges(value, ref _allowedContentTypes, Ps.Value.AllowedContentTypesSelector,
|
||||
//Custom comparer for enumerable
|
||||
new DelegateEqualityComparer<IEnumerable<ContentTypeSort>>(
|
||||
(sorts, enumerable) => sorts.UnsortedSequenceEqual(enumerable),
|
||||
sorts => sorts.GetHashCode()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,12 +37,6 @@ namespace Umbraco.Core.Models
|
||||
public readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<DictionaryItem, Guid?>(x => x.ParentId);
|
||||
public readonly PropertyInfo ItemKeySelector = ExpressionHelper.GetPropertyInfo<DictionaryItem, string>(x => x.ItemKey);
|
||||
public readonly PropertyInfo TranslationsSelector = ExpressionHelper.GetPropertyInfo<DictionaryItem, IEnumerable<IDictionaryTranslation>>(x => x.Translations);
|
||||
|
||||
//Custom comparer for enumerable
|
||||
public readonly DelegateEqualityComparer<IEnumerable<IDictionaryTranslation>> DictionaryTranslationComparer =
|
||||
new DelegateEqualityComparer<IEnumerable<IDictionaryTranslation>>(
|
||||
(enumerable, translations) => enumerable.UnsortedSequenceEqual(translations),
|
||||
enumerable => enumerable.GetHashCode());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -85,7 +79,10 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
SetPropertyValueAndDetectChanges(asArray, ref _translations, Ps.Value.TranslationsSelector,
|
||||
Ps.Value.DictionaryTranslationComparer);
|
||||
//Custom comparer for enumerable
|
||||
new DelegateEqualityComparer<IEnumerable<IDictionaryTranslation>>(
|
||||
(enumerable, translations) => enumerable.UnsortedSequenceEqual(translations),
|
||||
enumerable => enumerable.GetHashCode()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
if (IsPropertyDirty("CreateDate") == false || _createDate == default(DateTime))
|
||||
CreateDate = DateTime.Now;
|
||||
if (IsPropertyDirty("UpdateDate") == false || _updateDate == default(DateTime))
|
||||
UpdateDate = DateTime.Now;
|
||||
UpdateDate = CreateDate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -126,10 +126,6 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
{
|
||||
if (IsPropertyDirty("UpdateDate") == false || _updateDate == default(DateTime))
|
||||
UpdateDate = DateTime.Now;
|
||||
|
||||
//this is just in case
|
||||
if (_createDate == default(DateTime))
|
||||
CreateDate = DateTime.Now;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Umbraco.Core.Models.EntityBase
|
||||
{
|
||||
public class EntityPath
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Path { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public interface IAuditItem : IAggregateRoot
|
||||
{
|
||||
string Comment { get; }
|
||||
AuditType AuditType { get; }
|
||||
int UserId { get; }
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user