Compare commits

..

1 Commits

Author SHA1 Message Date
mikkelhm 4377d9294e Bump version to 7.6-beta 2017-03-17 11:51:07 +01:00
2676 changed files with 97957 additions and 51526 deletions
-10
View File
@@ -1,10 +0,0 @@
root=true
[*]
end_of_line = lf
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.{cs,cshtml,csx,vb,vbx,vbhtml,fs,fsx,txt,ps1,sql}]
indent_size = 4
+1 -4
View File
@@ -142,7 +142,4 @@ build/ui-docs.zip
build/csharp-docs.zip
build/msbuild.log
.vs/
src/packages/
src/PrecompiledWeb/*
build/tools/
src/PrecompiledWeb/*
src/packages/
-2
View File
@@ -1,5 +1,3 @@
[![Build status](https://ci.appveyor.com/api/projects/status/ikpgqxiw9v8opltv/branch/dev-v7?svg=true)](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 390,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
+3 -36
View File
@@ -113,51 +113,18 @@ REM This is necessary because SETLOCAL is on in InstallGit.cmd so that one might
REM but the path setting is lost due to SETLOCAL
SET PATH="C:\Program Files (x86)\Git\cmd";"C:\Program Files\Git\cmd";%PATH%
SET toolsFolder=%CD%\tools\
IF NOT EXIST "%toolsFolder%" (
MD tools
)
SET nuGetExecutable=%CD%\tools\nuget.exe
IF NOT EXIST "%nuGetExecutable%" (
ECHO Getting NuGet so we can fetch some tools
ECHO Downloading https://dist.nuget.org/win-x86-commandline/latest/nuget.exe to %nuGetExecutable%
powershell -Command "(New-Object Net.WebClient).DownloadFile('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', '%nuGetExecutable%')"
)
:: We need vswhere.exe for VS2017+
IF NOT EXIST "%toolsFolder%vswhere.exe" (
ECHO vswhere not found - fetching now
"%nuGetExecutable%" install vswhere -OutputDirectory tools -Verbosity quiet
)
FOR /f "delims=" %%A in ('dir "%toolsFolder%vswhere.*" /b') DO SET "vswhereExePath=%toolsFolder%%%A\"
MOVE "%vswhereExePath%tools\vswhere.exe" "%toolsFolder%vswhere.exe"
ECHO.
ECHO Making sure we have a web.config
IF NOT EXIST "%CD%\..\src\Umbraco.Web.UI\web.config" COPY "%CD%\..\src\Umbraco.Web.UI\web.Template.config" "%CD%\..\src\Umbraco.Web.UI\web.config"
for /f "usebackq tokens=1* delims=: " %%i in (`"%CD%\tools\vswhere.exe" -latest -requires Microsoft.Component.MSBuild`) do (
if /i "%%i"=="installationPath" set InstallDir=%%j
)
SET VSWherePath="%InstallDir%\MSBuild"
ECHO.
ECHO Visual Studio is installed in: %InstallDir%
SET MSBUILDPATH=C:\Program Files (x86)\MSBuild\14.0\Bin
SET MSBUILD="%MSBUILDPATH%\MsBuild.exe"
ECHO.
ECHO Reporting NuGet version
"%nuGetExecutable%" help | findstr "^NuGet Version:"
"%CD%\..\src\.nuget\NuGet.exe" help | findstr "^NuGet Version:"
ECHO.
ECHO Restoring NuGet packages
ECHO Into %nuGetFolder%
"%nuGetExecutable%" restore "%CD%\..\src\umbraco.sln" -Verbosity Quiet -NonInteractive -PackagesDirectory "%nuGetFolder%"
"%CD%\..\src\.nuget\NuGet.exe" restore "%CD%\..\src\umbraco.sln" -Verbosity Quiet -NonInteractive -PackagesDirectory "%nuGetFolder%"
IF ERRORLEVEL 1 GOTO :error
ECHO.
@@ -167,7 +134,7 @@ ECHO This takes a few minutes and logging is set to report warnings
ECHO and errors only so it might seems like nothing is happening for a while.
ECHO You can check the msbuild.log file for progress.
ECHO.
%MSBUILD% "Build.proj" /p:BUILD_RELEASE=%RELEASE% /p:BUILD_COMMENT=%COMMENT% /p:NugetPackagesDirectory="%nuGetFolder%" /p:VSWherePath=%VSWherePath% /consoleloggerparameters:Summary;ErrorsOnly /fileLogger
%MSBUILD% "Build.proj" /p:BUILD_RELEASE=%RELEASE% /p:BUILD_COMMENT=%COMMENT% /p:NugetPackagesDirectory="%nuGetFolder%" /consoleloggerparameters:Summary;ErrorsOnly /fileLogger
IF ERRORLEVEL 1 GOTO error
ECHO.
+22 -57
View File
@@ -1,68 +1,33 @@
@ECHO OFF
SETLOCAL
:: SETLOCAL is on, so changes to the path not persist to the actual user's path
SET toolsFolder=%CD%\tools\
SET release=%1
ECHO Installing Npm NuGet Package
SET nuGetFolder=%CD%\..\src\packages\
ECHO Configured packages folder: %nuGetFolder%
ECHO Current folder: %CD%
SET nodeFileName=node-v6.9.1-win-x86.7z
SET nodeExtractFolder=%toolsFolder%node.js.691
%CD%\..\src\.nuget\NuGet.exe install Npm.js -OutputDirectory %nuGetFolder% -Verbosity quiet
SET nuGetExecutable=%CD%\tools\nuget.exe
IF NOT EXIST "%nuGetExecutable%" (
ECHO Downloading https://dist.nuget.org/win-x86-commandline/latest/nuget.exe to %nuGetExecutable%
powershell -Command "(New-Object Net.WebClient).DownloadFile('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', '%nuGetExecutable%')"
)
for /f "delims=" %%A in ('dir %nuGetFolder%node.js.* /b') do set "nodePath=%nuGetFolder%%%A\"
for /f "delims=" %%A in ('dir %nuGetFolder%npm.js.* /b') do set "npmPath=%nuGetFolder%%%A\tools\"
:: We need 7za.exe for BuildBelle.bat
IF NOT EXIST "%toolsFolder%7za.exe" (
ECHO 7zip not found - fetching now
"%nuGetExecutable%" install 7-Zip.CommandLine -OutputDirectory tools -Verbosity quiet
)
ECHO Adding Npm and Node to path
REM SETLOCAL is on, so changes to the path not persist to the actual user's path
PATH=%npmPath%;%nodePath%;%PATH%
:: Put 7za.exe and vswhere.exe in a predictable path (not version specific)
FOR /f "delims=" %%A in ('dir "%toolsFolder%7-Zip.CommandLine.*" /b') DO SET "sevenZipExePath=%toolsFolder%%%A\"
MOVE "%sevenZipExePath%tools\7za.exe" "%toolsFolder%7za.exe"
SET buildFolder=%CD%
IF NOT EXIST "%nodeExtractFolder%" (
ECHO Downloading http://nodejs.org/dist/v6.9.1/%nodeFileName% to %toolsFolder%%nodeFileName%
powershell -Command "(New-Object Net.WebClient).DownloadFile('http://nodejs.org/dist/v6.9.1/%nodeFileName%', '%toolsFolder%%nodeFileName%')"
ECHO Extracting %nodeFileName% to %nodeExtractFolder%
"%toolsFolder%\7za.exe" x "%toolsFolder%\%nodeFileName%" -o"%nodeExtractFolder%" -aos > nul
)
FOR /f "delims=" %%A in ('dir "%nodeExtractFolder%\node*" /b') DO SET "nodePath=%nodeExtractFolder%\%%A"
ECHO Change directory to %CD%\..\src\Umbraco.Web.UI.Client\
CD %CD%\..\src\Umbraco.Web.UI.Client\
SET drive=%CD:~0,2%
SET nuGetFolder=%drive%\packages\
FOR /f "delims=" %%A in ('dir "%nuGetFolder%npm.*" /b') DO SET "npmPath=%nuGetFolder%%%A\"
ECHO Do npm install and the grunt build of Belle
call npm cache clean --quiet
call npm install --quiet
call npm install -g grunt-cli --quiet
call npm install -g bower --quiet
call grunt build --buildversion=%release%
IF [%npmPath%] == [] GOTO :installnpm
IF NOT [%npmPath%] == [] GOTO :build
:installnpm
ECHO Downloading npm
ECHO Configured packages folder: %nuGetFolder%
ECHO Installing Npm NuGet Package
"%nuGetExecutable%" install Npm -OutputDirectory %nuGetFolder% -Verbosity detailed
REM Ensures that we look for the just downloaded NPM, not whatever the user has installed on their machine
FOR /f "delims=" %%A in ('dir %nuGetFolder%npm.* /b') DO SET "npmPath=%nuGetFolder%%%A\"
GOTO :build
:build
ECHO Adding Npm and Node to path
REM SETLOCAL is on, so changes to the path not persist to the actual user's path
PATH="%npmPath%";"%nodePath%";%PATH%
SET buildFolder=%CD%
ECHO Change directory to %CD%\..\src\Umbraco.Web.UI.Client\
CD %CD%\..\src\Umbraco.Web.UI.Client\
ECHO Do npm install and the grunt build of Belle
call npm cache clean --quiet
call npm install --quiet
call npm install -g grunt-cli --quiet
call npm install -g bower --quiet
call grunt build --buildversion=%release%
ECHO Move back to the build folder
CD "%buildFolder%"
ECHO Move back to the build folder
CD %buildFolder%
-14
View File
@@ -57,20 +57,6 @@ $IndexPath = "../src/umbraco.web.ui.client/docs/api/index.html"
# Build the solution in debug mode
$SolutionPath = Join-Path -Path $SolutionRoot -ChildPath "umbraco.sln"
# Go get nuget.exe if we don't hae it
$NuGet = "$ToolsRoot\nuget.exe"
$FileExists = Test-Path $NuGet
If ($FileExists -eq $False) {
Write-Host "Retrieving nuget.exe..."
$SourceNugetExe = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
Invoke-WebRequest $SourceNugetExe -OutFile $NuGet
}
#restore nuget packages
Write-Host "Restoring nuget packages..."
& $NuGet restore $SolutionPath
& $MSBuild "$SolutionPath" /p:Configuration=Debug /maxcpucount /t:Clean
if (-not $?)
{
+15 -16
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata minClientVersion="3.4.4">
<metadata>
<id>UmbracoCms.Core</id>
<version>7.0.0</version>
<title>Umbraco Cms Core Binaries</title>
@@ -14,33 +14,32 @@
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
<language>en-US</language>
<tags>umbraco</tags>
<dependencies>
<dependency id="log4net" version="[2.0.8,3.0.0)" />
<dependency id="Log4Net.Async" version="[2.0.4,3.0.0)" />
<dependencies>
<!--Must be this way because 2.0.5 is actually 1.2.15.0 and 2.0.6 is actually 2.0.6 !-->
<dependency id="log4net" version="[2.0.5,2.0.6)" />
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.3,6.0.0)" />
<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="MySql.Data" version="[6.9.8, 7.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.83, 1.0.0)" />
<dependency id="ImageProcessor" version="[2.5.3, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[4.8.3, 5.0.0)" />
<dependency id="semver" version="[1.1.2, 3.0.0)" />
<!-- Markdown can not be updated due to: https://github.com/hey-red/markdownsharp/issues/71#issuecomment-233585487 -->
<dependency id="Newtonsoft.Json" version="[9.0.1, 10.0.0)" />
<dependency id="Examine" version="[0.1.81, 1.0.0)" />
<dependency id="ImageProcessor" version="[2.5.2, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[4.8.2, 5.0.0)" />
<dependency id="semver" version="[2.0.4, 3.0.0)" />
<!-- Markdown can not be updated due to: https://github.com/hey-red/markdownsharp/issues/71#issuecomment-233585487 -->
<dependency id="Markdown" version="[1.14.7, 2.0.0)" />
<dependency id="System.Threading.Tasks.Dataflow" version="[4.7.0, 5.0.0)" />
<dependency id="System.Threading.Tasks.Dataflow" version="[4.6.0, 5.0.0)" />
</dependencies>
</metadata>
<files>
+4 -4
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata minClientVersion="3.4.4">
<metadata minClientVersion="2.8">
<id>UmbracoCms</id>
<version>7.0.0</version>
<title>Umbraco Cms</title>
@@ -16,10 +16,10 @@
<tags>umbraco</tags>
<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.7, 4.0.0)" />
<dependency id="Newtonsoft.Json" version="[9.0.1, 10.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.5, 4.0.0)" />
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
<dependency id="ImageProcessor.Web.Config" version="[2.3.0, 3.0.0)" />
<dependency id="ImageProcessor.Web.Config" version="[2.3.0, 3.0.0)" />
</dependencies>
</metadata>
<files>
+1 -9
View File
@@ -8,17 +8,9 @@
----------------------------------------------------
*** 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-6-0
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!
We've done our best to transform your configuration files but in case something is not quite right: remember we
backed up your files in App_Data\NuGetBackup so you can find the original files before they were transformed.
+7 -20
View File
@@ -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>
@@ -31,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" />
@@ -60,7 +58,7 @@
<httpRuntime xdt:Transform="InsertIfMissing" />
<httpRuntime maxRequestLength="51200" fcnMode="Single" xdt:Transform="SetAttributes(fcnMode,maxRequestLength)" />
<httpRuntime targetFramework="4.5" xdt:Locator="Condition(count(@targetFramework) != 1)" xdt:Transform="SetAttributes(targetFramework)" />
<membership defaultProvider="DefaultMembershipProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove" />
<roleManager defaultProvider="DefaultRoleProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>
<profile defaultProvider="DefaultProfileProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>>
@@ -332,9 +330,6 @@
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.Owin.Security')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.Owin.Security.Cookies')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http.Formatting')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.CodeAnalysis.CSharp')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='log4net')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Data.SqlServerCe')" xdt:Transform="Remove" />
</assemblyBinding>
</runtime>
@@ -342,7 +337,7 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.4.9.5" newVersion="1.4.9.5" />
<bindingRedirect oldVersion="0.0.0.0-1.4.9.0" newVersion="1.4.9.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
@@ -354,7 +349,7 @@
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
@@ -370,32 +365,24 @@
</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" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0"/>
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Data.SqlServerCe" publicKeyToken="89845DCD8080CC91" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
+14 -25
View File
@@ -34,15 +34,10 @@
xdt:Transform="SetAttributes()" />
<add application="settings" alias="templates" title="Templates" type="Umbraco.Web.Trees.TemplatesTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="1"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="settings" alias="partialViews" type="Umbraco.Web.Trees.PartialViewsTree, umbraco"
xdt:Locator="Match(application,alias,type)"
xdt:Transform="Remove()" />
<add application="settings" alias="partialViews" title="Partial Views" silent="false" initialize="true" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.PartialViewsTreeController, umbraco" sortOrder="2"
xdt:Locator="Match(application,alias)"
xdt:Transform="InsertIfMissing" />
xdt:Transform="SetAttributes()" />
<add application="settings" alias="partialViews" title="Partial Views" silent="false" initialize="true" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.PartialViewsTree, umbraco" sortOrder="2"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="settings" alias="scripts" title="Scripts" type="umbraco.loadScripts, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
@@ -89,29 +84,23 @@
<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()" />
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTree, umbraco"
xdt:Locator="Match(application,alias,type)"
xdt:Transform="Remove()" />
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTreeController, umbraco" silent="false" initialize="true" sortOrder="6" title="Partial View Macro Files" iconClosed="icon-folder" iconOpen="icon-folder"
xdt:Locator="Match(application,alias)"
xdt:Transform="InsertIfMissing" />
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTree, umbraco" silent="false" initialize="true" sortOrder="6" title="Partial View Macro Files" iconClosed="icon-folder" iconOpen="icon-folder"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="python"
xdt:Locator="Match(application,alias)"
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"
+2 -2
View File
@@ -1,3 +1,3 @@
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
7.7.0
beta
7.6.0
beta
+5 -9
View File
@@ -4,7 +4,7 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
@@ -16,23 +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" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.7.0")]
[assembly: AssemblyInformationalVersion("7.7.0-beta")]
[assembly: AssemblyFileVersion("7.6.0")]
[assembly: AssemblyInformationalVersion("7.6.0-beta")]
+6 -6
View File
@@ -23,12 +23,12 @@ namespace Umbraco.Core
: base(serviceProvider, logger, packageActions)
{
}
/// <summary>
/// Gets the <see cref="IAction"/> implementations.
/// </summary>
public IEnumerable<IAction> Actions
}
/// <summary>
/// Gets the <see cref="IPackageAction"/> implementations.
/// </summary>
public IEnumerable<IAction> Actions
{
get
{
+22 -22
View File
@@ -48,7 +48,7 @@ namespace Umbraco.Core
/// <param name="cache"></param>
[Obsolete("Use the other constructor specifying a ProfilingLogger instead")]
public ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache)
: this(dbContext, serviceContext, cache,
: this(dbContext, serviceContext, cache,
new ProfilingLogger(LoggerResolver.Current.Logger, ProfilerResolver.Current.Profiler))
{
}
@@ -89,7 +89,7 @@ namespace Umbraco.Core
/// <param name="replaceContext">If set to true and the singleton is already set, it will be replaced</param>
/// <returns></returns>
/// <remarks>
/// This is NOT thread safe
/// This is NOT thread safe
/// </remarks>
public static ApplicationContext EnsureContext(ApplicationContext appContext, bool replaceContext)
{
@@ -107,14 +107,14 @@ namespace Umbraco.Core
/// </summary>
/// <param name="cache"></param>
/// <param name="replaceContext">
/// If set to true will replace the current singleton instance - This should only be used for unit tests or on app
/// If set to true will replace the current singleton instance - This should only be used for unit tests or on app
/// startup if for some reason the boot manager is not the umbraco boot manager.
/// </param>
/// <param name="dbContext"></param>
/// <param name="serviceContext"></param>
/// <returns></returns>
/// <remarks>
/// This is NOT thread safe
/// This is NOT thread safe
/// </remarks>
[Obsolete("Use the other method specifying an ProfilingLogger instead")]
public static ApplicationContext EnsureContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, bool replaceContext)
@@ -135,14 +135,14 @@ namespace Umbraco.Core
/// <param name="cache"></param>
/// <param name="logger"></param>
/// <param name="replaceContext">
/// If set to true will replace the current singleton instance - This should only be used for unit tests or on app
/// If set to true will replace the current singleton instance - This should only be used for unit tests or on app
/// startup if for some reason the boot manager is not the umbraco boot manager.
/// </param>
/// <param name="dbContext"></param>
/// <param name="serviceContext"></param>
/// <returns></returns>
/// <remarks>
/// This is NOT thread safe
/// This is NOT thread safe
/// </remarks>
public static ApplicationContext EnsureContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, ProfilingLogger logger, bool replaceContext)
{
@@ -175,7 +175,7 @@ namespace Umbraco.Core
public CacheHelper ApplicationCache { get; private set; }
/// <summary>
/// Exposes the global ProfilingLogger - this should generally not be accessed via the UmbracoContext and should normally just be exposed
/// Exposes the global ProfilingLogger - this should generally not be accessed via the UmbracoContext and should normally just be exposed
/// on most base classes or injected with IoC
/// </summary>
public ProfilingLogger ProfilingLogger { get; private set; }
@@ -213,7 +213,7 @@ namespace Umbraco.Core
// GlobalSettings.CurrentVersion returns the hard-coded "current version"
// the system is configured if they match
// if they don't, install runs, updates web.config (presumably) and updates GlobalSettings.ConfiguredStatus
public bool IsConfigured
{
get { return _configured.Value; }
@@ -226,8 +226,8 @@ namespace Umbraco.Core
{
get
{
if (IsConfigured == false
&& DatabaseContext != null
if (IsConfigured == false
&& DatabaseContext != null
&& DatabaseContext.IsDatabaseConfigured)
{
var schemaresult = DatabaseContext.ValidateDatabaseSchema();
@@ -274,12 +274,12 @@ namespace Umbraco.Core
private Lazy<bool> _configured;
internal MainDom MainDom { get; private set; }
private void Init()
{
MainDom = new MainDom(ProfilingLogger.Logger);
MainDom.Acquire();
//Create the lazy value to resolve whether or not the application is 'configured'
_configured = new Lazy<bool>(() =>
{
@@ -289,7 +289,7 @@ namespace Umbraco.Core
var currentVersion = UmbracoVersion.GetSemanticVersion();
var ok =
//we are not configured if this is null
//we are not configured if this is null
string.IsNullOrWhiteSpace(configStatus) == false
//they must match
&& configStatus == currentVersion;
@@ -303,7 +303,7 @@ namespace Umbraco.Core
var found = Services.MigrationEntryService.FindEntry(Constants.System.UmbracoMigrationName, UmbracoVersion.GetSemanticVersion());
if (found == null)
{
//we haven't executed this migration in this environment, so even though the config versions match,
//we haven't executed this migration in this environment, so even though the config versions match,
// this db has not been updated.
ProfilingLogger.Logger.Debug<ApplicationContext>(string.Format("The migration for version: '{0} has not been executed, there is no record in the database", currentVersion.ToSemanticString()));
ok = false;
@@ -323,7 +323,7 @@ namespace Umbraco.Core
return false;
}
});
});
}
private string ConfigurationStatus
@@ -338,7 +338,7 @@ namespace Umbraco.Core
{
return String.Empty;
}
}
}
}
private void AssertIsNotReady()
@@ -363,7 +363,7 @@ namespace Umbraco.Core
}
internal set { _databaseContext = value; }
}
/// <summary>
/// Gets the current ServiceContext
/// </summary>
@@ -417,7 +417,7 @@ namespace Umbraco.Core
ResolverCollection.ResetAll();
//reset resolution itself (though this should be taken care of by resetting any of the resolvers above)
Resolution.Reset();
//reset the instance objects
this.ApplicationCache = null;
if (_databaseContext != null) //need to check the internal field here
@@ -430,14 +430,14 @@ namespace Umbraco.Core
/*
if (DatabaseContext.IsDatabaseConfigured && DatabaseContext.Database != null)
{
DatabaseContext.Database.Dispose();
}
*/
DatabaseContext.Database.Dispose();
}
*/
}
this.DatabaseContext = null;
this.Services = null;
this._isReady = false; //set the internal field
// Indicate that the instance has been disposed.
_disposed = true;
}
+7 -8
View File
@@ -4,14 +4,12 @@ using System.Text.RegularExpressions;
using System.Web;
using Umbraco.Core;
[assembly: PreApplicationStartMethod(typeof(BindingRedirects), "Initialize")]
namespace Umbraco.Core
{
/// <summary>
/// Manages any assembly binding redirects that cannot be done via config (i.e. unsigned --> signed assemblies)
/// Manages any assembly binding redirects that cannot be done via config
/// </summary>
public sealed class BindingRedirects
internal class BindingRedirects
{
public static void Initialize()
{
@@ -19,8 +17,8 @@ namespace Umbraco.Core
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
}
private static readonly Regex Log4NetAssemblyPattern = new Regex("log4net, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=\\w+$", RegexOptions.Compiled);
private const string Log4NetReplacement = "log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a";
private static readonly Regex Log4NetAssemblyPattern = new Regex("log4net, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=null", RegexOptions.Compiled);
private const string Log4NetReplacement = "log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a";
/// <summary>
/// This is used to do an assembly binding redirect via code - normally required due to signature changes in assemblies
@@ -30,12 +28,13 @@ namespace Umbraco.Core
/// <returns></returns>
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
//log4net:
//log4net:
// Use regex to match and replace
if (Log4NetAssemblyPattern.IsMatch(args.Name) && args.Name != Log4NetReplacement)
{
return Assembly.Load(Log4NetAssemblyPattern.Replace(args.Name, Log4NetReplacement));
}
//AutoMapper:
// ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again
// do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stackoverflow
+4 -6
View File
@@ -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";
@@ -91,7 +89,7 @@ namespace Umbraco.Core.Cache
public const string DataTypeCacheKey = "UmbracoDataTypeDefinition";
public const string DataTypePreValuesCacheKey = "UmbracoPreVal";
public const string IdToKeyCacheKey = "UI2K__";
public const string KeyToIdCacheKey = "UK2I__";
public const string IdToKeyCacheKey = "UI2K";
public const string KeyToIdCacheKey = "UK2I";
}
}
@@ -26,9 +26,6 @@ namespace Umbraco.Core.Cache
public DeepCloneRuntimeCacheProvider(IRuntimeCacheProvider innerProvider)
{
if (innerProvider.GetType() == typeof(DeepCloneRuntimeCacheProvider))
throw new InvalidOperationException("A " + typeof(DeepCloneRuntimeCacheProvider) + " cannot wrap another instance of " + typeof(DeepCloneRuntimeCacheProvider));
InnerProvider = innerProvider;
}
@@ -108,11 +105,9 @@ namespace Umbraco.Core.Cache
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
if (value == null) return null; // do not store null values (backward compat)
//Clone/reset to go into the cache
return CheckCloneableAndTracksChanges(value);
}, timeout, isSliding, priority, removedCallback, dependentFiles);
//Clone/reset to go out of the cache
return CheckCloneableAndTracksChanges(cached);
}
@@ -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;
}
}
}
@@ -18,14 +18,10 @@ namespace Umbraco.Core.Configuration
{
var appSettings = System.Configuration.ConfigurationManager.AppSettings;
LogUncompletedScopes = string.Equals("true", appSettings["Umbraco.CoreDebug.LogUncompletedScopes"], StringComparison.OrdinalIgnoreCase);
DumpOnTimeoutThreadAbort = string.Equals("true", appSettings["Umbraco.CoreDebug.DumpOnTimeoutThreadAbort"], StringComparison.OrdinalIgnoreCase);
}
// when true, Scope logs the stack trace for any scope that gets disposed without being completed.
// this helps troubleshooting rogue scopes that we forget to complete
public bool LogUncompletedScopes { get; private set; }
// when true, the Logger creates a minidump of w3wp in ~/App_Data/MiniDump whenever it logs
// an error due to a ThreadAbortException that is due to a timeout.
public bool DumpOnTimeoutThreadAbort { get; private set; }
}
}
@@ -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>
@@ -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];
}
}
}
}
@@ -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);
}
}
}
}
}
@@ -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>
@@ -139,12 +139,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
internal CommaDelimitedConfigurationElement DisallowedUploadFiles
{
get { return GetOptionalDelimitedElement("disallowedUploadFiles", new[] {"ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd"}); }
}
[ConfigurationProperty("allowedUploadFiles")]
internal CommaDelimitedConfigurationElement AllowedUploadFiles
{
get { return GetOptionalDelimitedElement("allowedUploadFiles", new string[0]); }
}
[ConfigurationProperty("cloneXmlContent")]
@@ -189,12 +183,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
get { return GetOptionalTextElement("EnablePropertyValueConverters", false); }
}
[ConfigurationProperty("loginBackgroundImage")]
internal InnerTextConfigurationElement<string> LoginBackgroundImage
{
get { return GetOptionalTextElement("loginBackgroundImage", string.Empty); }
}
string IContentSection.NotificationEmailAddress
{
get { return Notifications.NotificationEmailAddress; }
@@ -313,11 +301,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
IEnumerable<string> IContentSection.DisallowedUploadFiles
{
get { return DisallowedUploadFiles; }
}
IEnumerable<string> IContentSection.AllowedUploadFiles
{
get { return AllowedUploadFiles; }
}
bool IContentSection.CloneXmlContent
@@ -353,10 +336,5 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{
get { return EnablePropertyValueConverters; }
}
string IContentSection.LoginBackgroundImage
{
get { return LoginBackgroundImage; }
}
}
}
@@ -1,19 +0,0 @@
using System.Linq;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public static class ContentSectionExtensions
{
/// <summary>
/// Determines if file extension is allowed for upload based on (optional) white list and black list
/// held in settings.
/// Allow upload if extension is whitelisted OR if there is no whitelist and extension is NOT blacklisted.
/// </summary>
public static bool IsFileAllowedForUpload(this IContentSection contentSection, string extension)
{
return contentSection.AllowedUploadFiles.Any(x => x.InvariantEquals(extension)) ||
(contentSection.AllowedUploadFiles.Any() == false &&
contentSection.DisallowedUploadFiles.Any(x => x.InvariantEquals(extension)) == false);
}
}
}
@@ -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}")]
@@ -52,9 +52,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
MacroErrorBehaviour MacroErrorBehaviour { get; }
IEnumerable<string> DisallowedUploadFiles { get; }
IEnumerable<string> AllowedUploadFiles { get; }
IEnumerable<string> DisallowedUploadFiles { get; }
bool CloneXmlContent { get; }
@@ -74,6 +72,5 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
bool EnablePropertyValueConverters { 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; }
@@ -8,7 +8,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
Guid Id { get; }
string RepositoryUrl { get; }
string WebServiceUrl { get; }
bool HasCustomWebServiceUrl { get; }
string RestApiUrl { get; }
bool HasCustomWebServiceUrl { get; }
}
}
@@ -12,8 +12,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
bool ConvertUrlsToAscii { get; }
bool TryConvertUrlsToAscii { get; }
IEnumerable<IChar> CharCollection { get; }
}
}
@@ -1,7 +1,4 @@
using System;
using System.ComponentModel;
namespace Umbraco.Core.Configuration.UmbracoSettings
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public interface IUmbracoSettingsSection : IUmbracoConfigurationSection
{
@@ -27,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()
@@ -1,19 +0,0 @@
using System;
using System.Linq;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public static class RepositoryConfigExtensions
{
//Our package repo
private static readonly Guid RepoGuid = new Guid("65194810-1f85-11dd-bd0b-0800200c9a66");
public static IRepository GetDefault(this IRepositoriesSection repos)
{
var found = repos.Repositories.FirstOrDefault(x => x.Id == RepoGuid);
if (found == null)
throw new InvalidOperationException("No default package repository found with id " + RepoGuid);
return found;
}
}
}
@@ -38,16 +38,9 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
get
{
var prop = Properties["webserviceurl"];
return (string) prop.DefaultValue != (string) this[prop];
var repoUrl = this[prop] as ConfigurationElement;
return (repoUrl != null && repoUrl.ElementInformation.IsPresent);
}
}
[ConfigurationProperty("restapiurl", DefaultValue = "https://our.umbraco.org/webapi/packages/v1")]
public string RestApiUrl
{
get { return (string)base["restapiurl"]; }
set { base["restapiurl"] = value; }
}
}
}
@@ -111,12 +111,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
bool IRequestHandlerSection.ConvertUrlsToAscii
{
get { return UrlReplacing.ConvertUrlsToAscii.InvariantEquals("true"); }
}
bool IRequestHandlerSection.TryConvertUrlsToAscii
{
get { return UrlReplacing.ConvertUrlsToAscii.InvariantEquals("try"); }
get { return UrlReplacing.ConvertUrlsToAscii; }
}
IEnumerable<IChar> IRequestHandlerSection.CharCollection
@@ -1,5 +1,4 @@
using System;
using System.ComponentModel;
using System.Configuration;
using System.Linq;
@@ -184,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; }
@@ -11,10 +11,10 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
get { return (bool) base["removeDoubleDashes"]; }
}
[ConfigurationProperty("toAscii", DefaultValue = "false")]
internal string ConvertUrlsToAscii
[ConfigurationProperty("toAscii", DefaultValue = false)]
internal bool ConvertUrlsToAscii
{
get { return (string) base["toAscii"]; }
get { return (bool)base["toAscii"]; }
}
[ConfigurationCollection(typeof(CharCollection), AddItemName = "char")]
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.7.0");
private static readonly Version Version = new Version("7.6.0");
/// <summary>
/// Gets the current version of Umbraco.
@@ -33,9 +33,9 @@ namespace Umbraco.Core.Configuration
public static SemVersion GetSemanticVersion()
{
return new SemVersion(
Current.Major,
Current.Major,
Current.Minor,
Current.Build,
Current.Build,
CurrentComment.IsNullOrWhiteSpace() ? null : CurrentComment,
Current.Revision > 0 ? Current.Revision.ToInvariantString() : null);
}
+1 -8
View File
@@ -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.
@@ -123,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";
+1 -26
View File
@@ -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>
@@ -134,11 +124,6 @@ namespace Umbraco.Core
/// </summary>
public const string MemberGroup = "366E63B9-880F-4E13-A61C-98069B029728";
/// <summary>
/// Guid for a Member Group object.
/// </summary>
public static readonly Guid MemberGroupGuid = new Guid(MemberGroup);
/// <summary>
/// Guid for a Member Type object.
/// </summary>
@@ -222,16 +207,6 @@ namespace Umbraco.Core
/// Guid for a Forms DataSource.
/// </summary>
public static readonly Guid FormsDataSourceGuid = new Guid(FormsDataSource);
/// <summary>
/// Guid for a Language.
/// </summary>
public const string Language = "6B05D05B-EC78-49BE-A4E4-79E274F07A77";
/// <summary>
/// Guid for a Forms DataSource.
/// </summary>
public static readonly Guid LanguageGuid = new Guid(Language);
}
}
}
@@ -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>
-5
View File
@@ -8,17 +8,12 @@ namespace Umbraco.Core
public static class Security
{
public const string AdminGroupAlias = "admin";
public const string BackOfficeAuthenticationType = "UmbracoBackOffice";
public const string BackOfficeExternalAuthenticationType = "UmbracoExternalCookie";
public const string BackOfficeExternalCookieName = "UMB_EXTLOGIN";
public const string BackOfficeTokenAuthenticationType = "UmbracoBackOfficeToken";
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>
+1 -37
View File
@@ -41,43 +41,7 @@ namespace Umbraco.Core
Hour,
Minute,
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 -2
View File
@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using umbraco.interfaces;
using Umbraco.Core;
namespace Umbraco.Core.Deploy
@@ -9,7 +8,7 @@ namespace Umbraco.Core.Deploy
/// <summary>
/// Connects to an Umbraco service.
/// </summary>
public interface IServiceConnector : IDiscoverable
public interface IServiceConnector
{
/// <summary>
/// Gets an artifact.
-135
View File
@@ -1,135 +0,0 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using Umbraco.Core.IO;
namespace Umbraco.Core.Diagnostics
{
// taken from https://blogs.msdn.microsoft.com/dondu/2010/10/24/writing-minidumps-in-c/
// and https://blogs.msdn.microsoft.com/dondu/2010/10/31/writing-minidumps-from-exceptions-in-c/
// which itself got it from http://blog.kalmbach-software.de/2008/12/13/writing-minidumps-in-c/
internal static class MiniDump
{
private static readonly object LockO = new object();
[Flags]
public enum Option : uint
{
// From dbghelp.h:
Normal = 0x00000000,
WithDataSegs = 0x00000001,
WithFullMemory = 0x00000002,
WithHandleData = 0x00000004,
FilterMemory = 0x00000008,
ScanMemory = 0x00000010,
WithUnloadedModules = 0x00000020,
WithIndirectlyReferencedMemory = 0x00000040,
FilterModulePaths = 0x00000080,
WithProcessThreadData = 0x00000100,
WithPrivateReadWriteMemory = 0x00000200,
WithoutOptionalData = 0x00000400,
WithFullMemoryInfo = 0x00000800,
WithThreadInfo = 0x00001000,
WithCodeSegs = 0x00002000,
WithoutAuxiliaryState = 0x00004000,
WithFullAuxiliaryState = 0x00008000,
WithPrivateWriteCopyMemory = 0x00010000,
IgnoreInaccessibleMemory = 0x00020000,
ValidTypeFlags = 0x0003ffff,
}
//typedef struct _MINIDUMP_EXCEPTION_INFORMATION {
// DWORD ThreadId;
// PEXCEPTION_POINTERS ExceptionPointers;
// BOOL ClientPointers;
//} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;
[StructLayout(LayoutKind.Sequential, Pack = 4)] // Pack=4 is important! So it works also for x64!
public struct MiniDumpExceptionInformation
{
public uint ThreadId;
public IntPtr ExceptionPointers;
[MarshalAs(UnmanagedType.Bool)]
public bool ClientPointers;
}
//BOOL
//WINAPI
//MiniDumpWriteDump(
// __in HANDLE hProcess,
// __in DWORD ProcessId,
// __in HANDLE hFile,
// __in MINIDUMP_TYPE DumpType,
// __in_opt PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
// __in_opt PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
// __in_opt PMINIDUMP_CALLBACK_INFORMATION CallbackParam
// );
// Overload requiring MiniDumpExceptionInformation
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
private static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, ref MiniDumpExceptionInformation expParam, IntPtr userStreamParam, IntPtr callbackParam);
// Overload supporting MiniDumpExceptionInformation == NULL
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
private static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam);
[DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
private static extern uint GetCurrentThreadId();
private static bool Write(SafeHandle fileHandle, Option options, bool withException = false)
{
var currentProcess = Process.GetCurrentProcess();
var currentProcessHandle = currentProcess.Handle;
var currentProcessId = (uint)currentProcess.Id;
MiniDumpExceptionInformation exp;
exp.ThreadId = GetCurrentThreadId();
exp.ClientPointers = false;
exp.ExceptionPointers = IntPtr.Zero;
if (withException)
exp.ExceptionPointers = Marshal.GetExceptionPointers();
var bRet = exp.ExceptionPointers == IntPtr.Zero
? MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint) options, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)
: MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint) options, ref exp, IntPtr.Zero, IntPtr.Zero);
return bRet;
}
public static bool Dump(Option options = Option.WithFullMemory, bool withException = false)
{
lock (LockO)
{
// work around "stack trace is not available while minidump debugging",
// by making sure a local var (that we can inspect) contains the stack trace.
// getting the call stack before it is unwound would require a special exception
// filter everywhere in our code = not!
var stacktrace = withException ? Environment.StackTrace : string.Empty;
var filepath = IOHelper.MapPath("~/App_Data/MiniDump");
if (Directory.Exists(filepath) == false)
Directory.CreateDirectory(filepath);
var filename = Path.Combine(filepath, string.Format("{0:yyyyMMddTHHmmss}.{1}.dmp", DateTime.UtcNow, Guid.NewGuid().ToString("N").Substring(0, 4)));
using (var stream = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.Write))
{
return Write(stream.SafeFileHandle, options, withException);
}
}
}
public static bool OkToDump()
{
lock (LockO)
{
var filepath = IOHelper.MapPath("~/App_Data/MiniDump");
if (Directory.Exists(filepath) == false) return true;
var count = Directory.GetFiles(filepath, "*.dmp").Length;
return count < 8;
}
}
}
}
+17 -3
View File
@@ -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;
}
@@ -298,5 +295,22 @@ namespace Umbraco.Core
return list1Groups.Count == list2Groups.Count
&& list1Groups.All(g => g.Count() == list2Groups[g.Key].Count());
}
///<summary>
/// Returns the items of the given enumerable as a pure enumerable.
/// <remarks>
/// When quering lists using methods such as <see cref="M:List.Where"/>, the result, despite appearing to look like and quack like an
/// <see cref="T:Enumerable{T}"/> the type is actually an instance of <see cref="T:System.Linq.Enumerable.WhereEnumerableIterator"/>
/// </remarks>
/// </summary>
///<param name="source">The item to find.</param>
///<returns>The index of the first matching item, or -1 if the item was not found.</returns>
internal static IEnumerable<T> Yield<T>(this IEnumerable<T> source)
{
foreach (var element in source)
{
yield return element;
}
}
}
}
@@ -1,177 +1,85 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Events
{
/// <summary>
/// Used as a base class for the generic type CancellableObjectEventArgs{T} so that we can get direct 'object' access to the underlying EventObject
/// </summary>
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
public abstract class CancellableObjectEventArgs : CancellableEventArgs
{
protected CancellableObjectEventArgs(object eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
/// <summary>
/// Event args for a strongly typed object that can support cancellation
/// </summary>
/// <typeparam name="T"></typeparam>
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
public class CancellableObjectEventArgs<T> : CancellableEventArgs, IEquatable<CancellableObjectEventArgs<T>>
{
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
: base(canCancel, messages, additionalData)
{
{
EventObject = eventObject;
}
protected CancellableObjectEventArgs(object eventObject, bool canCancel, EventMessages eventMessages)
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages eventMessages)
: base(canCancel, eventMessages)
{
EventObject = eventObject;
}
protected CancellableObjectEventArgs(object eventObject, EventMessages eventMessages)
public CancellableObjectEventArgs(T eventObject, EventMessages eventMessages)
: this(eventObject, true, eventMessages)
{
}
protected CancellableObjectEventArgs(object eventObject, bool canCancel)
: base(canCancel)
{
EventObject = eventObject;
}
protected CancellableObjectEventArgs(object eventObject)
: this(eventObject, true)
{
}
/// <summary>
/// Returns the object relating to the event
/// </summary>
/// <remarks>
/// This is protected so that inheritors can expose it with their own name
/// </remarks>
internal object EventObject { get; set; }
}
/// <summary>
/// Event args for a strongly typed object that can support cancellation
/// </summary>
/// <typeparam name="T"></typeparam>
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
public class CancellableObjectEventArgs<T> : CancellableObjectEventArgs, IEquatable<CancellableObjectEventArgs<T>>
{
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
: base(eventObject, canCancel, messages, additionalData)
{
}
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages eventMessages)
: base(eventObject, canCancel, eventMessages)
{
}
public CancellableObjectEventArgs(T eventObject, EventMessages eventMessages)
: base(eventObject, eventMessages)
{
}
public CancellableObjectEventArgs(T eventObject, bool canCancel)
: base(eventObject, canCancel)
{
}
: base(canCancel)
{
EventObject = eventObject;
}
public CancellableObjectEventArgs(T eventObject)
: base(eventObject)
{
}
public CancellableObjectEventArgs(T eventObject)
: this(eventObject, true)
{
}
/// <summary>
/// Returns the object relating to the event
/// </summary>
/// <remarks>
/// This is protected so that inheritors can expose it with their own name
/// </remarks>
protected new T EventObject
{
get { return (T) base.EventObject; }
set { base.EventObject = value; }
}
/// <summary>
/// Returns the object relating to the event
/// </summary>
/// <remarks>
/// This is protected so that inheritors can expose it with their own name
/// </remarks>
protected T EventObject { get; set; }
public bool Equals(CancellableObjectEventArgs<T> other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return base.Equals(other) && EqualityComparer<T>.Default.Equals(EventObject, other.EventObject);
}
public bool Equals(CancellableObjectEventArgs<T> other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return base.Equals(other) && EqualityComparer<T>.Default.Equals(EventObject, other.EventObject);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((CancellableObjectEventArgs<T>)obj);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((CancellableObjectEventArgs<T>) obj);
}
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ EqualityComparer<T>.Default.GetHashCode(EventObject);
}
}
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ EqualityComparer<T>.Default.GetHashCode(EventObject);
}
}
public static bool operator ==(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
{
return Equals(left, right);
}
public static bool operator ==(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
{
return Equals(left, right);
}
public static bool operator !=(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
{
return !Equals(left, right);
}
}
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
public class CancellableEnumerableObjectEventArgs<T> : CancellableObjectEventArgs<IEnumerable<T>>, IEquatable<CancellableEnumerableObjectEventArgs<T>>
{
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
: base(eventObject, canCancel, messages, additionalData)
{ }
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, bool canCancel, EventMessages eventMessages)
: base(eventObject, canCancel, eventMessages)
{ }
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, EventMessages eventMessages)
: base(eventObject, eventMessages)
{ }
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, bool canCancel)
: base(eventObject, canCancel)
{ }
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject)
: base(eventObject)
{ }
public bool Equals(CancellableEnumerableObjectEventArgs<T> other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return EventObject.SequenceEqual(other.EventObject);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((CancellableEnumerableObjectEventArgs<T>)obj);
}
public override int GetHashCode()
{
return HashCodeHelper.GetHashCode(EventObject);
}
}
public static bool operator !=(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
{
return !Equals(left, right);
}
}
}
+2 -7
View File
@@ -1,14 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core.Events
{
[SupersedeEvent(typeof(SaveEventArgs<>))]
[SupersedeEvent(typeof(PublishEventArgs<>))]
[SupersedeEvent(typeof(MoveEventArgs<>))]
[SupersedeEvent(typeof(CopyEventArgs<>))]
public class DeleteEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<DeleteEventArgs<TEntity>>, IDeletingMediaFilesEventArgs
public class DeleteEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<DeleteEventArgs<TEntity>>, IDeletingMediaFilesEventArgs
{
/// <summary>
/// Constructor accepting multiple entities that are used in the delete operation
@@ -111,7 +106,7 @@ namespace Umbraco.Core.Events
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return base.Equals(other) && MediaFilesToDelete.SequenceEqual(other.MediaFilesToDelete);
return base.Equals(other) && MediaFilesToDelete.Equals(other.MediaFilesToDelete);
}
public override bool Equals(object obj)
+1 -1
View File
@@ -4,7 +4,7 @@ using System.Xml.Linq;
namespace Umbraco.Core.Events
{
public class ImportEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportEventArgs<TEntity>>
public class ImportEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<ImportEventArgs<TEntity>>
{
/// <summary>
/// Constructor accepting an XElement with the xml being imported
@@ -4,7 +4,7 @@ using Umbraco.Core.Packaging.Models;
namespace Umbraco.Core.Events
{
public class ImportPackageEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportPackageEventArgs<TEntity>>
internal class ImportPackageEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<ImportPackageEventArgs<TEntity>>
{
private readonly MetaData _packageMetaData;
@@ -33,7 +33,6 @@ namespace Umbraco.Core.Events
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
//TODO: MetaData for package metadata has no equality operators :/
return base.Equals(other) && _packageMetaData.Equals(other._packageMetaData);
}
@@ -5,10 +5,8 @@ using System.Linq;
namespace Umbraco.Core.Events
{
/// <summary>
/// An IEventDispatcher that immediately raise all events.
/// This event manager supports event cancellation and will raise the events as soon as they are tracked, it does not store tracked events
/// </summary>
/// <remarks>This means that events will be raised during the scope transaction,
/// whatever happens, and the transaction could roll back in the end.</remarks>
internal class PassThroughEventDispatcher : IEventDispatcher
{
public bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string eventName = null)
+1 -1
View File
@@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace Umbraco.Core.Events
{
public class PublishEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<PublishEventArgs<TEntity>>
public class PublishEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<PublishEventArgs<TEntity>>
{
/// <summary>
/// Constructor accepting multiple entities that are used in the publish operation
+3 -2
View File
@@ -1,9 +1,8 @@
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.Core.Events
{
public class SaveEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>
public class SaveEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>
{
/// <summary>
/// Constructor accepting multiple entities that are used in the saving operation
@@ -117,5 +116,7 @@ namespace Umbraco.Core.Events
{
get { return EventObject; }
}
}
}
@@ -3,9 +3,11 @@ using Umbraco.Core.IO;
namespace Umbraco.Core.Events
{
/// <summary>
/// An IEventDispatcher that queues events, and raise them when the scope
/// exits and has been completed.
/// This event manager is created for each scope and is aware of if it is nested in an outer scope
/// </summary>
/// <remarks>
/// The outer scope is the only scope that can raise events, the inner scope's will defer to the outer scope
/// </remarks>
internal class ScopeEventDispatcher : ScopeEventDispatcherBase
{
public ScopeEventDispatcher()
@@ -1,23 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Events
{
/// <summary>
/// An IEventDispatcher that queues events.
/// </summary>
/// <remarks>
/// <para>Can raise, or ignore, cancelable events, depending on option.</para>
/// <para>Implementations must override ScopeExitCompleted to define what
/// to do with the events when the scope exits and has been completed.</para>
/// <para>If the scope exits without being completed, events are ignored.</para>
/// </remarks>
public abstract class ScopeEventDispatcherBase : IEventDispatcher
{
//events will be enlisted in the order they are raised
private List<IEventDefinition> _events;
private readonly bool _raiseCancelable;
@@ -76,263 +64,29 @@ namespace Umbraco.Core.Events
{
if (_events == null)
return Enumerable.Empty<IEventDefinition>();
switch (filter)
{
case EventDefinitionFilter.All:
return FilterSupersededAndUpdateToLatestEntity(_events);
return _events;
case EventDefinitionFilter.FirstIn:
var l1 = new OrderedHashSet<IEventDefinition>();
foreach (var e in _events)
{
l1.Add(e);
}
return FilterSupersededAndUpdateToLatestEntity(l1);
return l1;
case EventDefinitionFilter.LastIn:
var l2 = new OrderedHashSet<IEventDefinition>(keepOldest: false);
foreach (var e in _events)
{
l2.Add(e);
}
return FilterSupersededAndUpdateToLatestEntity(l2);
return l2;
default:
throw new ArgumentOutOfRangeException("filter", filter, null);
}
}
private class EventDefinitionTypeData
{
public IEventDefinition EventDefinition { get; set; }
public Type EventArgType { get; set; }
public SupersedeEventAttribute[] SupersedeAttributes { get; set; }
}
/// <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)
{
//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>();
var result = new List<IEventDefinition>();
//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).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 eventDefinition = events[index];
var argType = eventDefinition.Args.GetType();
var attributes = allArgTypesWithAttributes[eventDefinition.Args.GetType()];
var meta = new EventDefinitionTypeData
{
EventDefinition = eventDefinition,
EventArgType = argType,
SupersedeAttributes = attributes
};
var args = eventDefinition.Args as CancellableObjectEventArgs;
if (args != null)
{
var list = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject);
if (list == null)
{
//extract the event object
var obj = args.EventObject 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) == 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));
}
}
else
{
//Can't retrieve the entity so cant' filter or inspect, just add to the output
result.Add(eventDefinition);
}
}
else
{
var toRemove = new List<IEntity>();
foreach (var entity in list)
{
//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
{
//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 anything that has been filtered
foreach (var entity in toRemove)
{
list.Remove(entity);
}
//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 the items have changed
args.EventObject = list;
}
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);
}
}
//Now we'll deal with ensuring that only the latest(non stale) entities are used throughout all event args
UpdateToLatestEntities(allEntities, cancelableArgs);
//we need to reverse the result since we've been adding by latest added events first!
result.Reverse();
return result;
}
private static void UpdateToLatestEntities(IEnumerable<Tuple<IEntity, EventDefinitionTypeData>> allEntities, IEnumerable<CancellableObjectEventArgs> cancelableArgs)
{
//Now we'll deal with ensuring that only the latest(non stale) entities are used throughout all event args
var latestEntities = new OrderedHashSet<IEntity>(keepOldest: true);
foreach (var entity in allEntities.OrderByDescending(entity => entity.Item1.UpdateDate))
{
latestEntities.Add(entity.Item1);
}
foreach (var args in cancelableArgs)
{
var list = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject);
if (list == null)
{
//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)
{
args.EventObject = foundEntity;
}
}
else
{
var updated = false;
for (int i = 0; i < list.Count; i++)
{
//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)
{
args.EventObject = list;
}
}
}
}
/// <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 = eventDef.EventDefinition.Args.GetType();
//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();
//no args have been processed with this entity so it should not be filtered
if (foundByEntity.Length == 0)
return false;
if (argType.IsGenericType)
{
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
{
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;
}
}
public void ScopeExit(bool completed)
{
@@ -1,20 +0,0 @@
using System;
namespace Umbraco.Core.Events
{
/// <summary>
/// This is used to know if the event arg attributed should supersede another event arg type when
/// tracking events for the same entity. If one event args supercedes another then the event args that have been superseded
/// will mean that the event will not be dispatched or the args will be filtered to exclude the entity.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
internal class SupersedeEventAttribute : Attribute
{
public Type SupersededEventArgsType { get; private set; }
public SupersedeEventAttribute(Type supersededEventArgsType)
{
SupersededEventArgsType = supersededEventArgsType;
}
}
}
@@ -3,7 +3,7 @@ using Umbraco.Core.Packaging.Models;
namespace Umbraco.Core.Events
{
public class UninstallPackageEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>
internal class UninstallPackageEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>
{
private readonly MetaData _packageMetaData;
@@ -1,12 +0,0 @@
using System;
namespace Umbraco.Core.Exceptions
{
internal class ConnectionException : Exception
{
public ConnectionException(string message, Exception innerException) : base(message, innerException)
{
}
}
}
@@ -7,7 +7,7 @@ namespace Umbraco.Core.Exceptions
public T Operation { get; private set; }
public DataOperationException(T operation, string message)
: base(message)
:base(message)
{
Operation = operation;
}
+2 -15
View File
@@ -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>
+75 -74
View File
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -6,32 +7,32 @@ using System.Text;
namespace Umbraco.Core
{
/// <summary>
/// Used to create a hash code from multiple objects.
/// </summary>
/// <remarks>
/// .Net has a class the same as this: System.Web.Util.HashCodeCombiner and of course it works for all sorts of things
/// which we've not included here as we just need a quick easy class for this in order to create a unique
/// hash of directories/files to see if they have changed.
/// </remarks>
internal class HashCodeCombiner
{
private long _combinedHash = 5381L;
/// <summary>
/// Used to create a hash code from multiple objects.
/// </summary>
/// <remarks>
/// .Net has a class the same as this: System.Web.Util.HashCodeCombiner and of course it works for all sorts of things
/// which we've not included here as we just need a quick easy class for this in order to create a unique
/// hash of directories/files to see if they have changed.
/// </remarks>
internal class HashCodeCombiner
{
private long _combinedHash = 5381L;
internal void AddInt(int i)
{
_combinedHash = ((_combinedHash << 5) + _combinedHash) ^ i;
}
internal void AddInt(int i)
{
_combinedHash = ((_combinedHash << 5) + _combinedHash) ^ i;
}
internal void AddObject(object o)
{
AddInt(o.GetHashCode());
}
internal void AddObject(object o)
{
AddInt(o.GetHashCode());
}
internal void AddDateTime(DateTime d)
{
AddInt(d.GetHashCode());
}
internal void AddDateTime(DateTime d)
{
AddInt(d.GetHashCode());
}
internal void AddString(string s)
{
@@ -39,61 +40,61 @@ namespace Umbraco.Core
AddInt((StringComparer.InvariantCulture).GetHashCode(s));
}
internal void AddCaseInsensitiveString(string s)
{
if (s != null)
AddInt((StringComparer.InvariantCultureIgnoreCase).GetHashCode(s));
}
internal void AddCaseInsensitiveString(string s)
{
if (s != null)
AddInt((StringComparer.InvariantCultureIgnoreCase).GetHashCode(s));
}
internal void AddFileSystemItem(FileSystemInfo f)
{
//if it doesn't exist, don't proceed.
if (!f.Exists)
return;
internal void AddFileSystemItem(FileSystemInfo f)
{
//if it doesn't exist, don't proceed.
if (!f.Exists)
return;
AddCaseInsensitiveString(f.FullName);
AddDateTime(f.CreationTimeUtc);
AddDateTime(f.LastWriteTimeUtc);
AddCaseInsensitiveString(f.FullName);
AddDateTime(f.CreationTimeUtc);
AddDateTime(f.LastWriteTimeUtc);
//check if it is a file or folder
var fileInfo = f as FileInfo;
if (fileInfo != null)
{
AddInt(fileInfo.Length.GetHashCode());
}
var dirInfo = f as DirectoryInfo;
if (dirInfo != null)
{
foreach (var d in dirInfo.GetFiles())
{
AddFile(d);
}
foreach (var s in dirInfo.GetDirectories())
{
AddFolder(s);
}
}
}
//check if it is a file or folder
var fileInfo = f as FileInfo;
if (fileInfo != null)
{
AddInt(fileInfo.Length.GetHashCode());
}
internal void AddFile(FileInfo f)
{
AddFileSystemItem(f);
}
var dirInfo = f as DirectoryInfo;
if (dirInfo != null)
{
foreach (var d in dirInfo.GetFiles())
{
AddFile(d);
}
foreach (var s in dirInfo.GetDirectories())
{
AddFolder(s);
}
}
}
internal void AddFolder(DirectoryInfo d)
{
AddFileSystemItem(d);
}
internal void AddFile(FileInfo f)
{
AddFileSystemItem(f);
}
/// <summary>
/// Returns the hex code of the combined hash code
/// </summary>
/// <returns></returns>
internal string GetCombinedHashCode()
{
return _combinedHash.ToString("x", CultureInfo.InvariantCulture);
}
internal void AddFolder(DirectoryInfo d)
{
AddFileSystemItem(d);
}
/// <summary>
/// Returns the hex code of the combined hash code
/// </summary>
/// <returns></returns>
internal string GetCombinedHashCode()
{
return _combinedHash.ToString("x", CultureInfo.InvariantCulture);
}
}
}
}
-104
View File
@@ -1,104 +0,0 @@
using System.Collections.Generic;
namespace Umbraco.Core
{
/// <summary>
/// Borrowed from http://stackoverflow.com/a/2575444/694494
/// </summary>
internal static class HashCodeHelper
{
public static int GetHashCode<T1, T2>(T1 arg1, T2 arg2)
{
unchecked
{
return 31 * arg1.GetHashCode() + arg2.GetHashCode();
}
}
public static int GetHashCode<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3)
{
unchecked
{
int hash = arg1.GetHashCode();
hash = 31 * hash + arg2.GetHashCode();
return 31 * hash + arg3.GetHashCode();
}
}
public static int GetHashCode<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3,
T4 arg4)
{
unchecked
{
int hash = arg1.GetHashCode();
hash = 31 * hash + arg2.GetHashCode();
hash = 31 * hash + arg3.GetHashCode();
return 31 * hash + arg4.GetHashCode();
}
}
public static int GetHashCode<T>(T[] list)
{
unchecked
{
int hash = 0;
foreach (var item in list)
{
if (item == null) continue;
hash = 31 * hash + item.GetHashCode();
}
return hash;
}
}
public static int GetHashCode<T>(IEnumerable<T> list)
{
unchecked
{
int hash = 0;
foreach (var item in list)
{
if (item == null) continue;
hash = 31 * hash + item.GetHashCode();
}
return hash;
}
}
/// <summary>
/// Gets a hashcode for a collection for that the order of items
/// does not matter.
/// So {1, 2, 3} and {3, 2, 1} will get same hash code.
/// </summary>
public static int GetHashCodeForOrderNoMatterCollection<T>(
IEnumerable<T> list)
{
unchecked
{
int hash = 0;
int count = 0;
foreach (var item in list)
{
if (item == null) continue;
hash += item.GetHashCode();
count++;
}
return 31 * hash + count.GetHashCode();
}
}
/// <summary>
/// Alternative way to get a hashcode is to use a fluent
/// interface like this:<br />
/// return 0.CombineHashCode(field1).CombineHashCode(field2).
/// CombineHashCode(field3);
/// </summary>
public static int CombineHashCode<T>(this int hashCode, T arg)
{
unchecked
{
return 31 * hashCode + arg.GetHashCode();
}
}
}
}
@@ -19,8 +19,6 @@ namespace Umbraco.Core.IO
private ShadowWrapper _macroPartialFileSystem;
private ShadowWrapper _partialViewsFileSystem;
private ShadowWrapper _macroScriptsFileSystem;
private ShadowWrapper _userControlsFileSystem;
private ShadowWrapper _stylesheetsFileSystem;
private ShadowWrapper _scriptsFileSystem;
private ShadowWrapper _xsltFileSystem;
@@ -63,8 +61,6 @@ namespace Umbraco.Core.IO
{
var macroPartialFileSystem = new PhysicalFileSystem(SystemDirectories.MacroPartials);
var partialViewsFileSystem = new PhysicalFileSystem(SystemDirectories.PartialViews);
var macroScriptsFileSystem = new PhysicalFileSystem(SystemDirectories.MacroScripts);
var userControlsFileSystem = new PhysicalFileSystem(SystemDirectories.UserControls);
var stylesheetsFileSystem = new PhysicalFileSystem(SystemDirectories.Css);
var scriptsFileSystem = new PhysicalFileSystem(SystemDirectories.Scripts);
var xsltFileSystem = new PhysicalFileSystem(SystemDirectories.Xslt);
@@ -73,8 +69,6 @@ namespace Umbraco.Core.IO
_macroPartialFileSystem = new ShadowWrapper(macroPartialFileSystem, "Views/MacroPartials", ScopeProvider);
_partialViewsFileSystem = new ShadowWrapper(partialViewsFileSystem, "Views/Partials", ScopeProvider);
_macroScriptsFileSystem = new ShadowWrapper(macroScriptsFileSystem, "macroScripts", ScopeProvider);
_userControlsFileSystem = new ShadowWrapper(userControlsFileSystem, "usercontrols", ScopeProvider);
_stylesheetsFileSystem = new ShadowWrapper(stylesheetsFileSystem, "css", ScopeProvider);
_scriptsFileSystem = new ShadowWrapper(scriptsFileSystem, "scripts", ScopeProvider);
_xsltFileSystem = new ShadowWrapper(xsltFileSystem, "xslt", ScopeProvider);
@@ -91,10 +85,6 @@ namespace Umbraco.Core.IO
public IFileSystem2 MacroPartialsFileSystem { get { return _macroPartialFileSystem; } }
public IFileSystem2 PartialViewsFileSystem { get { return _partialViewsFileSystem; } }
// Legacy /macroScripts folder
public IFileSystem2 MacroScriptsFileSystem { get { return _macroScriptsFileSystem; } }
// Legacy /usercontrols folder
public IFileSystem2 UserControlsFileSystem { get { return _userControlsFileSystem; } }
public IFileSystem2 StylesheetsFileSystem { get { return _stylesheetsFileSystem; } }
public IFileSystem2 ScriptsFileSystem { get { return _scriptsFileSystem; } }
public IFileSystem2 XsltFileSystem { get { return _xsltFileSystem; } }
@@ -262,15 +252,13 @@ namespace Umbraco.Core.IO
internal ICompletable Shadow(Guid id)
{
var typed = _wrappers.ToArray();
var wrappers = new ShadowWrapper[typed.Length + 9];
var wrappers = new ShadowWrapper[typed.Length + 7];
var i = 0;
while (i < typed.Length) wrappers[i] = typed[i++];
wrappers[i++] = _macroPartialFileSystem;
wrappers[i++] = _macroScriptsFileSystem;
wrappers[i++] = _partialViewsFileSystem;
wrappers[i++] = _stylesheetsFileSystem;
wrappers[i++] = _scriptsFileSystem;
wrappers[i++] = _userControlsFileSystem;
wrappers[i++] = _xsltFileSystem;
wrappers[i++] = _masterPagesFileSystem;
wrappers[i] = _mvcViewsFileSystem;
+1 -107
View File
@@ -4,144 +4,38 @@ using System.IO;
namespace Umbraco.Core.IO
{
/// <summary>
/// Provides methods allowing the manipulation of files within an Umbraco application.
/// </summary>
public interface IFileSystem
public interface IFileSystem
{
/// <summary>
/// Gets all directories matching the given path.
/// </summary>
/// <param name="path">The path to the directories.</param>
/// <returns>
/// The <see cref="IEnumerable{String}"/> representing the matched directories.
/// </returns>
IEnumerable<string> GetDirectories(string path);
/// <summary>
/// Deletes the specified directory.
/// </summary>
/// <param name="path">The name of the directory to remove.</param>
void DeleteDirectory(string path);
/// <summary>
/// Deletes the specified directory and, if indicated, any subdirectories and files in the directory.
/// </summary>
/// <remarks>Azure blob storage has no real concept of directories so deletion is always recursive.</remarks>
/// <param name="path">The name of the directory to remove.</param>
/// <param name="recursive">Whether to remove directories, subdirectories, and files in path.</param>
void DeleteDirectory(string path, bool recursive);
/// <summary>
/// Determines whether the specified directory exists.
/// </summary>
/// <param name="path">The directory to check.</param>
/// <returns>
/// <c>True</c> if the directory exists and the user has permission to view it; otherwise <c>false</c>.
/// </returns>
bool DirectoryExists(string path);
/// <summary>
/// Adds a file to the file system.
/// </summary>
/// <param name="path">The path to the given file.</param>
/// <param name="stream">The <see cref="Stream"/> containing the file contents.</param>
void AddFile(string path, Stream stream);
/// <summary>
/// Adds a file to the file system.
/// </summary>
/// <param name="path">The path to the given file.</param>
/// <param name="stream">The <see cref="Stream"/> containing the file contents.</param>
/// <param name="overrideIfExists">Whether to override the file if it already exists.</param>
void AddFile(string path, Stream stream, bool overrideIfExists);
/// <summary>
/// Gets all files matching the given path.
/// </summary>
/// <param name="path">The path to the files.</param>
/// <returns>
/// The <see cref="IEnumerable{String}"/> representing the matched files.
/// </returns>
IEnumerable<string> GetFiles(string path);
/// <summary>
/// Gets all files matching the given path and filter.
/// </summary>
/// <param name="path">The path to the files.</param>
/// <param name="filter">A filter that allows the querying of file extension. <example>*.jpg</example></param>
/// <returns>
/// The <see cref="IEnumerable{String}"/> representing the matched files.
/// </returns>
IEnumerable<string> GetFiles(string path, string filter);
/// <summary>
/// Gets a <see cref="Stream"/> representing the file at the gieven path.
/// </summary>
/// <param name="path">The path to the file.</param>
/// <returns>
/// <see cref="Stream"/>.
/// </returns>
Stream OpenFile(string path);
/// <summary>
/// Deletes the specified file.
/// </summary>
/// <param name="path">The name of the file to remove.</param>
void DeleteFile(string path);
/// <summary>
/// Determines whether the specified file exists.
/// </summary>
/// <param name="path">The file to check.</param>
/// <returns>
/// <c>True</c> if the file exists and the user has permission to view it; otherwise <c>false</c>.
/// </returns>
bool FileExists(string path);
/// <summary>
/// Returns the application relative path to the file.
/// </summary>
/// <param name="fullPathOrUrl">The full path or url.</param>
/// <returns>
/// The <see cref="string"/> representing the relative path.
/// </returns>
string GetRelativePath(string fullPathOrUrl);
/// <summary>
/// Gets the full qualified path to the file.
/// </summary>
/// <param name="path">The file to return the full path for.</param>
/// <returns>
/// The <see cref="string"/> representing the full path.
/// </returns>
string GetFullPath(string path);
/// <summary>
/// Returns the application relative url to the file.
/// </summary>
/// <param name="path">The path to return the url for.</param>
/// <returns>
/// <see cref="string"/> representing the relative url.
/// </returns>
string GetUrl(string path);
/// <summary>
/// Gets the last modified date/time of the file, expressed as a UTC value.
/// </summary>
/// <param name="path">The path to the file.</param>
/// <returns>
/// <see cref="DateTimeOffset"/>.
/// </returns>
DateTimeOffset GetLastModified(string path);
/// <summary>
/// Gets the created date/time of the file, expressed as a UTC value.
/// </summary>
/// <param name="path">The path to the file.</param>
/// <returns>
/// <see cref="DateTimeOffset"/>.
/// </returns>
DateTimeOffset GetCreated(string path);
}
-2
View File
@@ -97,8 +97,6 @@ namespace Umbraco.Core.IO
public static string MapPath(string path, bool useHttpContext)
{
if (path == null) throw new ArgumentNullException("path");
// Check if the path is already mapped
if ((path.Length >= 2 && path[1] == Path.VolumeSeparatorChar)
|| path.StartsWith(@"\\")) //UNC Paths start with "\\". If the site is running off a network drive mapped paths will look like "\\Whatever\Boo\Bar"
+24 -27
View File
@@ -31,7 +31,6 @@ namespace Umbraco.Core.IO
private long _folderCounter;
private bool _folderCounterInitialized;
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
private static readonly Dictionary<int, string> DefaultSizes = new Dictionary<int, string>
{
{ 100, "thumb" },
@@ -159,7 +158,7 @@ namespace Umbraco.Core.IO
// ReSharper disable once AssignNullToNotNullAttribute
var filepath = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories
? Path.Combine(folder, filename).Replace('\\', '/')
? Path.Combine(folder, filename)
: folder + "-" + filename;
return filepath;
@@ -264,7 +263,7 @@ namespace Umbraco.Core.IO
var filename = Path.GetFileName(sourcepath);
var filepath = GetMediaPath(filename, content.Key, propertyType.Key);
this.CopyFile(sourcepath, filepath);
CopyThumbnails(sourcepath, filepath);
return filepath;
}
@@ -313,17 +312,29 @@ namespace Umbraco.Core.IO
}
}
/// <summary>
/// Sets a file for the FileUpload property editor and populates autofill properties
/// </summary>
/// <param name="content"></param>
/// <param name="property"></param>
/// <param name="filepath"></param>
/// <param name="filestream"></param>
// sets a file for the FileUpload property editor
// ie generates thumbnails and populates autofill properties
private void SetUploadFile(IContentBase content, Property property, string filepath, Stream filestream)
{
// will use filepath for extension, and filestream for length
_uploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream);
{
// check if file is an image (and supports resizing and thumbnails etc)
var extension = Path.GetExtension(filepath);
var isImage = IsImageFile(extension);
// specific stuff for images (thumbnails etc)
if (isImage)
{
using (var image = Image.FromStream(filestream))
{
// use one image for all
GenerateThumbnails(image, filepath, property.PropertyType);
_uploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream, image);
}
}
else
{
// will use filepath for extension, and filestream for length
_uploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream);
}
}
#endregion
@@ -390,7 +401,6 @@ namespace Umbraco.Core.IO
// note: this does not find 'custom' thumbnails?
// will find _thumb and _big-thumb but NOT _custom?
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public IEnumerable<string> GetThumbnails(string path)
{
var parentDirectory = Path.GetDirectoryName(path);
@@ -411,14 +421,12 @@ namespace Umbraco.Core.IO
DeleteThumbnails(path);
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public void DeleteThumbnails(string path)
{
GetThumbnails(path)
.ForEach(x => base.DeleteFile(x));
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public void CopyThumbnails(string sourcePath, string targetPath)
{
var targetPathBase = Path.GetDirectoryName(targetPath) ?? "";
@@ -471,7 +479,6 @@ namespace Umbraco.Core.IO
#region GenerateThumbnails
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public IEnumerable<ResizedImage> GenerateThumbnails(
Image image,
string filepath,
@@ -493,7 +500,6 @@ namespace Umbraco.Core.IO
return GenerateThumbnails(image, filepath, additionalSizes);
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public IEnumerable<ResizedImage> GenerateThumbnails(
Image image,
string filepath,
@@ -516,7 +522,6 @@ namespace Umbraco.Core.IO
.ToList(); // now
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public IEnumerable<ResizedImage> GenerateThumbnails(
Stream filestream,
string filepath,
@@ -530,7 +535,6 @@ namespace Umbraco.Core.IO
}
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public IEnumerable<ResizedImage> GenerateThumbnails(
Image image,
string filepath,
@@ -552,19 +556,16 @@ namespace Umbraco.Core.IO
#region GenerateResized - Generate at resized filepath derived from origin filepath
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public ResizedImage GenerateResized(Image originImage, string originFilepath, string sizeName, int maxWidthHeight)
{
return GenerateResized(originImage, originFilepath, sizeName, maxWidthHeight, -1, -1);
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public ResizedImage GenerateResized(Image originImage, string originFilepath, string sizeName, int fixedWidth, int fixedHeight)
{
return GenerateResized(originImage, originFilepath, sizeName, -1, fixedWidth, fixedHeight);
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public ResizedImage GenerateResized(Image originImage, string originFilepath, string sizeName, int maxWidthHeight, int fixedWidth, int fixedHeight)
{
if (string.IsNullOrWhiteSpace(sizeName))
@@ -580,19 +581,16 @@ namespace Umbraco.Core.IO
#region GenerateResizedAt - Generate at specified resized filepath
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public ResizedImage GenerateResizedAt(Image originImage, string resizedFilepath, int maxWidthHeight)
{
return GenerateResizedAt(originImage, resizedFilepath, maxWidthHeight, -1, -1);
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public ResizedImage GenerateResizedAt(Image originImage, int fixedWidth, int fixedHeight, string resizedFilepath)
{
return GenerateResizedAt(originImage, resizedFilepath, -1, fixedWidth, fixedHeight);
}
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public ResizedImage GenerateResizedAt(Image originImage, string resizedFilepath, int maxWidthHeight, int fixedWidth, int fixedHeight)
{
// target dimensions
@@ -701,7 +699,6 @@ namespace Umbraco.Core.IO
#region Inner classes
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
public class ResizedImage
{
public ResizedImage()
+1 -1
View File
@@ -158,7 +158,7 @@ namespace Umbraco.Core.IO
// if can seek, be safe and go back to start, else...
// hope that the stream hasn't been read already
if (stream.CanSeek)
stream.Seek(0, SeekOrigin.Begin);
stream.Seek(0, 0);
using (var destination = (Stream) File.Create(fullPath))
stream.CopyTo(destination);
+26 -59
View File
@@ -218,11 +218,11 @@ namespace Umbraco.Core.IO
var normPath = NormPath(path);
var shadows = Nodes.Where(kvp => IsChild(normPath, kvp.Key)).ToArray();
var files = filter != null ? _fs.GetFiles(path, filter) : _fs.GetFiles(path);
var wildcard = filter == null ? null : new WildcardExpression(filter);
var regexFilter = FilterToRegex(filter);
return files
.Except(shadows.Where(kvp => (kvp.Value.IsFile && kvp.Value.IsDelete) || kvp.Value.IsDir)
.Select(kvp => kvp.Key))
.Union(shadows.Where(kvp => kvp.Value.IsFile && kvp.Value.IsExist && (wildcard == null || wildcard.IsMatch(kvp.Key))).Select(kvp => kvp.Key))
.Union(shadows.Where(kvp => kvp.Value.IsFile && kvp.Value.IsExist && FilterByRegex(kvp.Key, regexFilter)).Select(kvp => kvp.Key))
.Distinct();
}
@@ -326,65 +326,32 @@ namespace Umbraco.Core.IO
_sfs.AddFile(path, physicalPath, overrideIfExists, copy);
Nodes[normPath] = new ShadowNode(false, false);
}
// copied from System.Web.Util.Wildcard internal
internal class WildcardExpression
/// <summary>
/// Helper function for filtering keys by Regex if a filter is specified.
/// </summary>
/// <param name="input"></param>
/// <param name="regexFilter"></param>
/// <returns></returns>
internal static bool FilterByRegex(string input, string regexFilter)
{
private readonly string _pattern;
private readonly bool _caseInsensitive;
private Regex _regex;
if (regexFilter == null) return true;
return regexFilter != string.Empty && Regex.IsMatch(input, regexFilter);
}
private static Regex metaRegex = new Regex("[\\+\\{\\\\\\[\\|\\(\\)\\.\\^\\$]");
private static Regex questRegex = new Regex("\\?");
private static Regex starRegex = new Regex("\\*");
private static Regex commaRegex = new Regex(",");
private static Regex slashRegex = new Regex("(?=/)");
private static Regex backslashRegex = new Regex("(?=[\\\\:])");
public WildcardExpression(string pattern, bool caseInsensitive = true)
{
_pattern = pattern;
_caseInsensitive = caseInsensitive;
}
private void EnsureRegex(string pattern)
{
if (_regex != null) return;
var options = RegexOptions.None;
// match right-to-left (for speed) if the pattern starts with a *
if (pattern.Length > 0 && pattern[0] == '*')
options = RegexOptions.RightToLeft | RegexOptions.Singleline;
else
options = RegexOptions.Singleline;
// case insensitivity
if (_caseInsensitive)
options |= RegexOptions.IgnoreCase | RegexOptions.CultureInvariant;
// Remove regex metacharacters
pattern = metaRegex.Replace(pattern, "\\$0");
// Replace wildcard metacharacters with regex codes
pattern = questRegex.Replace(pattern, ".");
pattern = starRegex.Replace(pattern, ".*");
pattern = commaRegex.Replace(pattern, "\\z|\\A");
// anchor the pattern at beginning and end, and return the regex
_regex = new Regex("\\A" + pattern + "\\z", options);
}
public bool IsMatch(string input)
{
EnsureRegex(_pattern);
return _regex.IsMatch(input);
}
/// <summary>
/// Transforms a filter pattern into a Regex pattern
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
/// <remarks>
/// Appending '$' only if not containing wildcard is stupid and broken.
/// It is however what seems to be what they're doing in .NET so we need to match the functionality.
/// </remarks>
internal static string FilterToRegex(string pattern)
{
if (pattern == null) return null;
return "^" + Regex.Escape(pattern).Replace("\\*", ".*").Replace("\\?", ".") + (pattern.Contains("*") ? string.Empty : "$");
}
}
}
+3 -14
View File
@@ -52,20 +52,9 @@ namespace Umbraco.Core.IO
try
{
Directory.Delete(dir, true);
// shadowPath make be path/to/dir, remove each
dir = dir.Replace("/", "\\");
var min = IOHelper.MapPath("~/App_Data/TEMP/ShadowFs").Length;
var pos = dir.LastIndexOf("\\", StringComparison.OrdinalIgnoreCase);
while (pos > min)
{
dir = dir.Substring(0, pos);
if (Directory.EnumerateFileSystemEntries(dir).Any() == false)
Directory.Delete(dir, true);
else
break;
pos = dir.LastIndexOf("\\", StringComparison.OrdinalIgnoreCase);
}
dir = dir.Substring(0, dir.Length - _shadowPath.Length - 1);
if (Directory.EnumerateFileSystemEntries(dir).Any() == false)
Directory.Delete(dir, true);
}
catch
{
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Logging
/// This is an old/deprecated logger and has been superceded by ParallelForwardingAppender which is included in Umbraco and
/// also by AsyncForwardingAppender in the Log4Net.Async library.
/// </summary>
[Obsolete("This is superceded by the ParallelForwardingAppender, this will be removed in v8, do not use this")]
[Obsolete("This is superceded by the ParallelForwardingAppender, this will be removed in v8")]
[EditorBrowsable(EditorBrowsableState.Never)]
public class AsynchronousRollingFileAppender : RollingFileAppender
{
+5 -39
View File
@@ -7,8 +7,6 @@ using System.Threading;
using System.Web;
using log4net;
using log4net.Config;
using Umbraco.Core.Configuration;
using Umbraco.Core.Diagnostics;
namespace Umbraco.Core.Logging
{
@@ -59,55 +57,23 @@ namespace Umbraco.Core.Logging
internal ILog LoggerFor(object getTypeFromInstance)
{
if (getTypeFromInstance == null) throw new ArgumentNullException("getTypeFromInstance");
return LogManager.GetLogger(getTypeFromInstance.GetType());
}
public void Error(Type callingType, string message, Exception exception)
{
var logger = LogManager.GetLogger(callingType);
if (logger == null) return;
var dump = false;
if (IsTimeoutThreadAbortException(exception))
{
message += "\r\nThe thread has been aborted, because the request has timed out.";
// dump if configured, or if stacktrace contains Monitor.ReliableEnter
dump = UmbracoConfig.For.CoreDebug().DumpOnTimeoutThreadAbort || IsMonitorEnterThreadAbortException(exception);
// dump if it is ok to dump (might have a cap on number of dump...)
dump &= MiniDump.OkToDump();
}
if (dump)
{
try
{
var dumped = MiniDump.Dump(withException: true);
message += dumped
? "\r\nA minidump was created in App_Data/MiniDump"
: "\r\nFailed to create a minidump";
}
catch (Exception e)
{
message += string.Format("\r\nFailed to create a minidump ({0}: {1})", e.GetType().FullName, e.Message);
}
}
logger.Error(message, exception);
logger.Error(message, exception);
}
private static bool IsMonitorEnterThreadAbortException(Exception exception)
{
var abort = exception as ThreadAbortException;
if (abort == null) return false;
var stacktrace = abort.StackTrace;
return stacktrace.Contains("System.Threading.Monitor.ReliableEnter");
}
private static bool IsTimeoutThreadAbortException(Exception exception)
{
var abort = exception as ThreadAbortException;
@@ -139,7 +105,7 @@ namespace Umbraco.Core.Logging
if (showHttpTrace && HttpContext.Current != null)
{
HttpContext.Current.Trace.Warn(callingType.Name, string.Format(message, formatItems.Select(x => x.Invoke()).ToArray()));
}
}
var logger = LogManager.GetLogger(callingType);
if (logger == null || logger.IsWarnEnabled == false) return;
@@ -156,7 +122,7 @@ namespace Umbraco.Core.Logging
var logger = LogManager.GetLogger(callingType);
if (logger == null || logger.IsWarnEnabled == false) return;
var executedParams = formatItems.Select(x => x.Invoke()).ToArray();
logger.WarnFormat((message) + ". Exception: " + e, executedParams);
logger.WarnFormat((message) + ". Exception: " + e, executedParams);
}
/// <summary>
@@ -13,8 +13,301 @@ namespace Umbraco.Core.Logging
/// <remarks>
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
/// </remarks>
[Obsolete("Use the Log4Net.Async.ParallelForwardingAppender instead this will be removed in future versions")]
public class ParallelForwardingAppender : Log4Net.Async.ParallelForwardingAppender
public class ParallelForwardingAppender : AsyncForwardingAppenderBase, IDisposable
{
#region Private Members
private const int DefaultBufferSize = 1000;
private BlockingCollection<LoggingEventContext> _loggingEvents;
private CancellationTokenSource _loggingCancelationTokenSource;
private CancellationToken _loggingCancelationToken;
private Task _loggingTask;
private Double _shutdownFlushTimeout = 2;
private TimeSpan _shutdownFlushTimespan = TimeSpan.FromSeconds(2);
private static readonly Type ThisType = typeof(ParallelForwardingAppender);
private volatile bool shutDownRequested;
private int? bufferSize = DefaultBufferSize;
#endregion Private Members
#region Properties
/// <summary>
/// Gets or sets the number of LoggingEvents that will be buffered. Set to null for unlimited.
/// </summary>
public override int? BufferSize
{
get { return bufferSize; }
set { bufferSize = value; }
}
public int BufferEntryCount
{
get
{
if (_loggingEvents == null) return 0;
return _loggingEvents.Count;
}
}
/// <summary>
/// Gets or sets the time period in which the system will wait for appenders to flush before canceling the background task.
/// </summary>
public Double ShutdownFlushTimeout
{
get
{
return _shutdownFlushTimeout;
}
set
{
_shutdownFlushTimeout = value;
}
}
protected override string InternalLoggerName
{
get
{
{
return "ParallelForwardingAppender";
}
}
}
#endregion Properties
#region Startup
public override void ActivateOptions()
{
base.ActivateOptions();
_shutdownFlushTimespan = TimeSpan.FromSeconds(_shutdownFlushTimeout);
StartForwarding();
}
private void StartForwarding()
{
if (shutDownRequested)
{
return;
}
//Create a collection which will block the thread and wait for new entries
//if the collection is empty
if (BufferSize.HasValue && BufferSize > 0)
{
_loggingEvents = new BlockingCollection<LoggingEventContext>(BufferSize.Value);
}
else
{
//No limit on the number of events.
_loggingEvents = new BlockingCollection<LoggingEventContext>();
}
//The cancellation token is used to cancel a running task gracefully.
_loggingCancelationTokenSource = new CancellationTokenSource();
_loggingCancelationToken = _loggingCancelationTokenSource.Token;
_loggingTask = new Task(SubscriberLoop, _loggingCancelationToken);
_loggingTask.Start();
}
#endregion Startup
#region Shutdown
private void CompleteSubscriberTask()
{
shutDownRequested = true;
if (_loggingEvents == null || _loggingEvents.IsAddingCompleted)
{
return;
}
//Don't allow more entries to be added.
_loggingEvents.CompleteAdding();
//Allow some time to flush
Thread.Sleep(_shutdownFlushTimespan);
if (!_loggingTask.IsCompleted && !_loggingCancelationToken.IsCancellationRequested)
{
_loggingCancelationTokenSource.Cancel();
//Wait here so that the error logging messages do not get into a random order.
//Don't pass the cancellation token because we are not interested
//in catching the OperationCanceledException that results.
_loggingTask.Wait();
}
if (!_loggingEvents.IsCompleted)
{
ForwardInternalError("The buffer was not able to be flushed before timeout occurred.", null, ThisType);
}
}
protected override void OnClose()
{
CompleteSubscriberTask();
base.OnClose();
}
#endregion Shutdown
#region Appending
protected override void Append(LoggingEvent loggingEvent)
{
if (_loggingEvents == null || _loggingEvents.IsAddingCompleted || loggingEvent == null)
{
return;
}
loggingEvent.Fix = Fix;
//In the case where blocking on a full collection, and the task is subsequently completed, the cancellation token
//will prevent the entry from attempting to add to the completed collection which would result in an exception.
_loggingEvents.Add(new LoggingEventContext(loggingEvent, HttpContext), _loggingCancelationToken);
}
protected override void Append(LoggingEvent[] loggingEvents)
{
if (_loggingEvents == null || _loggingEvents.IsAddingCompleted || loggingEvents == null)
{
return;
}
foreach (var loggingEvent in loggingEvents)
{
Append(loggingEvent);
}
}
#endregion Appending
#region Forwarding
/// <summary>
/// Iterates over a BlockingCollection containing LoggingEvents.
/// </summary>
private void SubscriberLoop()
{
Thread.CurrentThread.Name = String.Format("{0} ParallelForwardingAppender Subscriber Task", Name);
//The task will continue in a blocking loop until
//the queue is marked as adding completed, or the task is canceled.
try
{
//This call blocks until an item is available or until adding is completed
foreach (var entry in _loggingEvents.GetConsumingEnumerable(_loggingCancelationToken))
{
HttpContext = entry.HttpContext;
ForwardLoggingEvent(entry.LoggingEvent, ThisType);
}
}
catch (OperationCanceledException ex)
{
//The thread was canceled before all entries could be forwarded and the collection completed.
ForwardInternalError("Subscriber task was canceled before completion.", ex, ThisType);
//Cancellation is called in the CompleteSubscriberTask so don't call that again.
}
catch (ThreadAbortException ex)
{
//Thread abort may occur on domain unload.
ForwardInternalError("Subscriber task was aborted.", ex, ThisType);
//Cannot recover from a thread abort so complete the task.
CompleteSubscriberTask();
//The exception is swallowed because we don't want the client application
//to halt due to a logging issue.
}
catch (Exception ex)
{
//On exception, try to log the exception
ForwardInternalError("Subscriber task error in forwarding loop.", ex, ThisType);
//Any error in the loop is going to be some sort of extenuating circumstance from which we
//probably cannot recover anyway. Complete subscribing.
CompleteSubscriberTask();
}
}
#endregion Forwarding
#region IDisposable Implementation
private bool _disposed = false;
//Implement IDisposable.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
if (_loggingTask != null)
{
if (!(_loggingTask.IsCanceled || _loggingTask.IsCompleted || _loggingTask.IsFaulted))
{
try
{
CompleteSubscriberTask();
}
catch (Exception ex)
{
LogLog.Error(ThisType, "Exception Completing Subscriber Task in Dispose Method", ex);
}
}
try
{
_loggingTask.Dispose();
}
catch (Exception ex)
{
LogLog.Error(ThisType, "Exception Disposing Logging Task", ex);
}
finally
{
_loggingTask = null;
}
}
if (_loggingEvents != null)
{
try
{
_loggingEvents.Dispose();
}
catch (Exception ex)
{
LogLog.Error(ThisType, "Exception Disposing BlockingCollection", ex);
}
finally
{
_loggingEvents = null;
}
}
if (_loggingCancelationTokenSource != null)
{
try
{
_loggingCancelationTokenSource.Dispose();
}
catch (Exception ex)
{
LogLog.Error(ThisType, "Exception Disposing CancellationTokenSource", ex);
}
finally
{
_loggingCancelationTokenSource = null;
}
}
}
_disposed = true;
}
}
// Use C# destructor syntax for finalization code.
~ParallelForwardingAppender()
{
// Simply call Dispose(false).
Dispose(false);
}
#endregion IDisposable Implementation
}
}
+2 -8
View File
@@ -1,14 +1,8 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
namespace Umbraco.Core.Media
{
// note: because this interface is obsolete is is *not* IDiscoverable, and in case the
// PluginManager is asked to find types implementing this interface it will fall back
// to a complete scan.
[Obsolete("IImageUrlProvider is no longer used and will be removed in future versions")]
public interface IImageUrlProvider // IDiscoverable
public interface IImageUrlProvider
{
string Name { get; }
string GetImageUrlFromMedia(int mediaId, IDictionary<string, string> parameters);
+2 -9
View File
@@ -1,13 +1,6 @@
using System;
namespace Umbraco.Core.Media
namespace Umbraco.Core.Media
{
// note: because this interface is obsolete is is *not* IDiscoverable, and in case the
// PluginManager is asked to find types implementing this interface it will fall back
// to a complete scan.
[Obsolete("Thumbnails are generated by ImageProcessor, use that instead")]
public interface IThumbnailProvider // : IDiscoverable
public interface IThumbnailProvider
{
bool CanProvideThumbnail(string fileUrl);
string GetThumbnailUrl(string fileUrl);
@@ -96,7 +96,8 @@ namespace Umbraco.Core.Media
/// <param name="propertyTypeAlias">The property type alias.</param>
/// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param>
/// <param name="filestream">The stream containing the file data.</param>
public void Populate(IContentBase content, string propertyTypeAlias, string filepath, Stream filestream)
/// <param name="image">The file data as an image object.</param>
public void Populate(IContentBase content, string propertyTypeAlias, string filepath, Stream filestream, Image image = null)
{
if (content == null) throw new ArgumentNullException("content");
if (propertyTypeAlias == null) throw new ArgumentNullException("propertyTypeAlias");
@@ -109,7 +110,7 @@ namespace Umbraco.Core.Media
if (autoFillConfig == null) return; // nothing
// populate
Populate(content, autoFillConfig, filepath, filestream);
Populate(content, autoFillConfig, filepath, filestream, image);
}
/// <summary>
@@ -157,7 +158,8 @@ namespace Umbraco.Core.Media
/// <param name="autoFillConfig"></param>
/// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param>
/// <param name="filestream">The stream containing the file data.</param>
public void Populate(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string filepath, Stream filestream)
/// <param name="image">The file data as an image object.</param>
public void Populate(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string filepath, Stream filestream, Image image = null)
{
if (content == null) throw new ArgumentNullException("content");
if (autoFillConfig == null) throw new ArgumentNullException("autoFillConfig");
@@ -170,7 +172,11 @@ namespace Umbraco.Core.Media
else
{
var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.');
var size = _mediaFileSystem.IsImageFile(extension) ? (Size?)_mediaFileSystem.GetDimensions(filestream) : null;
Size? size;
if (image == null)
size = _mediaFileSystem.IsImageFile(extension) ? (Size?) _mediaFileSystem.GetDimensions(filestream) : null;
else
size = new Size(image.Width, image.Height);
SetProperties(content, autoFillConfig, size, filestream.Length, extension);
}
}
+3 -53
View File
@@ -1,7 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Models
{
@@ -86,64 +84,16 @@ namespace Umbraco.Core.Models
public string Type { get; set; }
private Type _runtimeType;
/// <summary>
/// Returns the CLR type based on it's assembly name stored in the config
/// </summary>
/// <returns></returns>
public Type GetRuntimeType()
{
if (_runtimeType != null)
return _runtimeType;
_runtimeType = TryGetType(Type);
return _runtimeType;
return _runtimeType ?? (_runtimeType = System.Type.GetType(Type));
}
/// <summary>
/// Used to try to get and cache the tree type
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
internal static Type TryGetType(string type)
{
try
{
return ResolvedTypes.GetOrAdd(type, s =>
{
var result = System.Type.GetType(type);
if (result != null)
{
return result;
}
//we need to implement a bit of a hack here due to some trees being renamed and backwards compat
var parts = type.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 2)
{
if (parts[1].Trim() == "umbraco" && parts[0].StartsWith("Umbraco.Web.Trees") && parts[0].EndsWith("Controller") == false)
{
//if it's one of our controllers but it's not suffixed with "Controller" then add it and try again
var tempType = parts[0] + "Controller, umbraco";
result = System.Type.GetType(tempType);
if (result != null)
{
return result;
}
}
}
throw new InvalidOperationException("Could not resolve type");
});
}
catch (InvalidOperationException)
{
//swallow, this is our own exception, couldn't find the type
return null;
}
}
private static readonly ConcurrentDictionary<string, Type> ResolvedTypes = new ConcurrentDictionary<string, Type>();
}
}
+18 -11
View File
@@ -1,5 +1,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
@@ -20,7 +23,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 +32,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 +68,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 +87,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 +95,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 +197,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
@@ -261,12 +274,6 @@ namespace Umbraco.Core.Models
/// </summary>
public bool HasPublishedVersion { get { return PublishedVersionGuid != default(Guid); } }
[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>
+2 -7
View File
@@ -264,7 +264,7 @@ namespace Umbraco.Core.Models
/// <returns><see cref="Property"/> Value as an <see cref="object"/></returns>
public virtual object GetValue(string propertyTypeAlias)
{
return Properties.Contains(propertyTypeAlias) ? Properties[propertyTypeAlias].Value : null;
return Properties[propertyTypeAlias].Value;
}
/// <summary>
@@ -275,13 +275,8 @@ namespace Umbraco.Core.Models
/// <returns><see cref="Property"/> Value as a <see cref="TPassType"/></returns>
public virtual TPassType GetValue<TPassType>(string propertyTypeAlias)
{
if (Properties.Contains(propertyTypeAlias) == false)
{
return default(TPassType);
}
var convertAttempt = Properties[propertyTypeAlias].Value.TryConvertTo<TPassType>();
return convertAttempt.Success ? convertAttempt.Result : default(TPassType);
return convertAttempt.Success ? convertAttempt.Result : default(TPassType);
}
/// <summary>
+4 -6
View File
@@ -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>
@@ -96,7 +91,10 @@ namespace Umbraco.Core.Models
set
{
SetPropertyValueAndDetectChanges(value, ref _allowedTemplates, Ps.Value.AllowedTemplatesSelector,
Ps.Value.TemplateComparer);
//Custom comparer for enumerable
new DelegateEqualityComparer<IEnumerable<ITemplate>>(
(templates, enumerable) => templates.UnsortedSequenceEqual(enumerable),
templates => templates.GetHashCode()));
}
}
+6 -9
View File
@@ -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()));
}
}
@@ -42,7 +42,6 @@ namespace Umbraco.Core.Models
public Guid Key { get; set; }
public DateTime CreateDate { get; set; }
public DateTime UpdateDate { get; set; }
public DateTime? DeletedDate { get; set; }
/// <summary>
/// Special case, always return false, this will cause the repositories managing
@@ -61,7 +60,5 @@ namespace Umbraco.Core.Models
DeepCloneHelper.DeepCloneRefProperties(this, clone);
return clone;
}
}
}
+4 -7
View File
@@ -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()));
}
}
}
+1 -8
View File
@@ -101,9 +101,6 @@ namespace Umbraco.Core.Models.EntityBase
set { SetPropertyValueAndDetectChanges(value, ref _updateDate, Ps.Value.UpdateDateSelector); }
}
[IgnoreDataMember]
public DateTime? DeletedDate { get; set; }
internal virtual void ResetIdentity()
{
_hasIdentity = false;
@@ -119,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>
@@ -129,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>

Some files were not shown because too many files have changed in this diff Show More