Compare commits

..

9 Commits

975 changed files with 16923 additions and 43132 deletions
-5
View File
@@ -56,7 +56,6 @@ build/*.nupkg
src/Umbraco.Tests/config/applications.config
src/Umbraco.Tests/config/trees.config
src/Umbraco.Web.UI/web.config
src/Umbraco.Web.UI/Config/ClientDependency.config
*.orig
src/Umbraco.Tests/config/404handlers.config
src/Umbraco.Web.UI/[Vv]iews/*.cshtml
@@ -140,7 +139,3 @@ apidocs/api/*
build/docs.zip
build/ui-docs.zip
build/csharp-docs.zip
build/msbuild.log
.vs/
build/tools/
+13 -27
View File
@@ -1,54 +1,40 @@
[![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)
[![ScreenShot](vimeo.png)](https://vimeo.com/172382998/)
## Umbraco CMS ##
Umbraco is a free open source Content Management System built on the ASP.NET platform. Our mission is to help you deliver delightful digital experiences by making Umbraco friendly, simpler and social.
Umbraco is a free open source Content Management System built on the ASP.NET platform.
## Building Umbraco from source ##
The easiest way to get started is to run `build/build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `grunt vs` in `src\Umbraco.Web.UI.Client`.
The easiest way to get started is to run `build/build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `grunt dev` in `src\Umbraco.Web.UI.Client`.
If you're interested in making changes to Belle without running Visual Studio make sure to read the [Belle ReadMe file](src/Umbraco.Web.UI.Client/README.md).
If you're interested in making changes to Belle make sure to read the [Belle ReadMe file](src/Umbraco.Web.UI.Client/README.md). Note that you can always [download a nightly build](http://nightly.umbraco.org/umbraco%207.0.0/) so you don't have to build the code yourself.
Note that you can always [download a nightly build](http://nightly.umbraco.org/?container=umbraco-750) so you don't have to build the code yourself.
## Watch an introduction video ##
## Watch a introduction video ##
[![ScreenShot](http://umbraco.com/images/whatisumbraco.png)](https://umbraco.tv/videos/umbraco-v7/content-editor/basics/introduction/cms-explanation/)
## Umbraco - The Friendly CMS ##
## Umbraco - the simple, flexible and friendly ASP.NET CMS ##
For the first time on the Microsoft platform, there is a free user and developer friendly CMS that makes it quick and easy to create websites - or a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, out of the box.
**More than 350,000 sites trust Umbraco**
Umbraco is not only loved by developers, but is a content editors dream. Enjoy intuitive editing tools, media management, responsive views and approval workflows to send your content live.
For the first time on the Microsoft platform, there is a free user and developer friendly CMS that makes it quick and easy to create websites - or a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, out of the box. It's a developer's dream and your users will love it too.
Used by more than 350,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scales. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 200,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
Used by more than 350,000 active websites including [http://daviscup.com](http://daviscup.com), [http://heinz.com](http://heinz.com), [http://peugeot.com](http://peugeot.com), [http://www.hersheys.com/](http://www.hersheys.com/) and **The Official ASP.NET and IIS.NET website from Microsoft** ([http://asp.net](http://asp.net) / [http://iis.net](http://iis.net)), you can be sure that the technology is proven, stable and scales.
To view more examples, please visit [https://umbraco.com/why-umbraco/#caseStudies](https://umbraco.com/why-umbraco/#caseStudies)
## Why Open Source? ##
As an Open Source platform, Umbraco is more than just a CMS. We are transparent with our roadmap for future versions, our incremental sprint planning notes are publicly accessible and community contributions and packages are available for all to use.
To view more examples, please visit [http://umbraco.com/why-umbraco/#caseStudies](http://umbraco.com/why-umbraco/#caseStudies)
## Downloading ##
The downloadable Umbraco releases live at [https://our.umbraco.org/download](https://our.umbraco.org/download).
The downloadable Umbraco releases live at [http://our.umbraco.org/download](http://our.umbraco.org/download).
## Forums ##
Peer-to-peer support is available 24/7 at the community forum on [https://our.umbraco.org](https://our.umbraco.org).
We have a forum running on [http://our.umbraco.org](http://our.umbraco.org). The discussions group on [Google Groups](https://groups.google.com/forum/#!forum/umbraco-dev) is for discussions on developing the core, and not on Umbraco-implementations or extensions in general. For those topics, please use [http://our.umbraco.org](http://our.umbraco.org).
## Contribute to Umbraco ##
Umbraco is contribution focused and community driven. If you want to contribute back to Umbraco please check out our [guide to contributing](https://our.umbraco.org/contribute).
If you want to contribute back to Umbraco you should check out our [guide to contributing](http://our.umbraco.org/contribute).
## Found a bug? ##
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](https://our.umbraco.org/contribute/report-an-issue-or-request-a-feature).
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](http://our.umbraco.org/contribute/report-an-issue-or-request-a-feature).
To view existing issues, please visit [http://issues.umbraco.org](http://issues.umbraco.org).
+17 -23
View File
@@ -8,45 +8,39 @@ build_script:
FOR /F "skip=1 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED release SET "release=%%i"
SET nuGetFolder=C:\Users\appveyor\.nuget\packages
SET PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
ECHO %PATH%
ECHO Building Release %release% build%APPVEYOR_BUILD_NUMBER%
SET nuGetFolder=%CD%\..\src\packages\
..\src\.nuget\NuGet.exe sources Add -Name MyGetUmbracoCore -Source https://www.myget.org/F/umbracocore/api/v2/ >NUL
..\src\.nuget\NuGet.exe install ..\src\Umbraco.Web.UI\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet
IF EXIST ..\src\umbraco.businesslogic\packages.config ..\src\.nuget\NuGet.exe install ..\src\umbraco.businesslogic\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet
..\src\.nuget\NuGet.exe install ..\src\Umbraco.Core\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet
ECHO Building Release %release% build%APPVEYOR_BUILD_NUMBER%
SET PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
SET MSBUILD="C:\Program Files (x86)\MSBuild\14.0\Bin\MsBuild.exe"
XCOPY "..\src\Umbraco.Tests\unit-test-log4net.CI.config" "..\src\Umbraco.Tests\unit-test-log4net.config" /Y
%MSBUILD% "..\src\Umbraco.Tests\Umbraco.Tests.csproj" /consoleloggerparameters:Summary;ErrorsOnly
build.bat nopause %release% build%APPVEYOR_BUILD_NUMBER%
%MSBUILD% "../src/Umbraco.Tests/Umbraco.Tests.csproj" /verbosity:minimal
build.bat %release% build%APPVEYOR_BUILD_NUMBER%
ECHO %PATH%
test:
assemblies: src\Umbraco.Tests\bin\Debug\Umbraco.Tests.dll
artifacts:
- path: build\UmbracoCms.*
name: UmbracoFiles
- path: build\msbuild.log
name: BuildLog
deploy:
- provider: AzureBlob
storage_account_name: umbraconightlies
storage_access_key:
secure: bmEMml2SF7QLHULiePa/a01XOeIa2SxJeXuaZ+1R27b+Vb2nNUQVYiPlUyF2cZAFSHI/zO/LekRsVU1rTescGhJjF7SSjKybymI3p+F/OWpwqiu2WfFee1ofXBFx8QHw
container: umbraco-750
artifact: UmbracoFiles
on:
branch: dev-v7
notifications:
- provider: Slack
auth_token:
+10 -89
View File
@@ -11,28 +11,20 @@ FOR /F "skip=1 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED release SE
FOR /F "skip=2 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED comment SET "comment=%%i"
REM If there's arguments on the command line overrule UmbracoVersion.txt and use that as the version
IF [%2] NEQ [] (SET release=%2)
IF [%3] NEQ [] (SET comment=%3) ELSE (IF [%2] NEQ [] (SET "comment="))
REM Get the "is continuous integration" from the parameters
SET "isci=0"
IF [%1] NEQ [] (SET isci=1)
IF [%1] NEQ [] (SET release=%1)
IF [%2] NEQ [] (SET comment=%2) ELSE (IF [%1] NEQ [] (SET "comment="))
SET version=%release%
IF [%comment%] EQU [] (SET version=%release%) ELSE (SET version=%release%-%comment%)
ECHO.
IF [%comment%] EQU [] (SET version=%release%) ELSE (SET version=%release%-%comment%)
ECHO Building Umbraco %version%
ECHO.
ReplaceIISExpressPortNumber.exe ..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj %release%
ECHO.
ECHO Removing the belle build folder and bower_components folder to make sure everything is clean as a whistle
RD ..\src\Umbraco.Web.UI.Client\build /Q /S
RD ..\src\Umbraco.Web.UI.Client\bower_components /Q /S
ECHO.
ECHO Removing existing built files to make sure everything is clean as a whistle
RMDIR /Q /S _BuildOutput
DEL /F /Q UmbracoCms.*.zip
@@ -40,98 +32,27 @@ DEL /F /Q UmbracoExamine.*.zip
DEL /F /Q UmbracoCms.*.nupkg
DEL /F /Q webpihash.txt
ECHO.
ECHO Making sure Git is in the path so that the build can succeed
CALL InstallGit.cmd
REM Adding the default Git path so that if it's installed it can actually be found
REM This is necessary because SETLOCAL is on in InstallGit.cmd so that one might find Git,
REM but the path setting is lost due to SETLOCAL
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 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
)
:: 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
)
:: 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"
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.
ECHO Performing MSBuild and producing Umbraco binaries zip files
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%
IF ERRORLEVEL 1 GOTO :error
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" /p:BUILD_RELEASE=%release% /p:BUILD_COMMENT=%comment% /verbosity:minimal
ECHO.
ECHO Setting node_modules folder to hidden to prevent VS13 from crashing on it while loading the websites project
attrib +h ..\src\Umbraco.Web.UI.Client\node_modules
ECHO.
ECHO Adding Web.config transform files to the NuGet package
REN .\_BuildOutput\WebApp\Views\Web.config Web.config.transform
REN .\_BuildOutput\WebApp\Xslt\Web.config Web.config.transform
ECHO.
ECHO Packing the NuGet release files
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.Core.nuspec -Version %version% -Symbols -Verbosity quiet
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.nuspec -Version %version% -Verbosity quiet
IF ERRORLEVEL 1 GOTO :error
IF ERRORLEVEL 1 GOTO :showerror
:success
ECHO.
ECHO No errors were detected!
ECHO There may still be some in the output, which you would need to investigate.
ECHO Warnings are usually normal.
ECHO No errors were detected but you still may see some in the output, then it's time to investigate.
ECHO You might see some warnings but that is completely normal.
GOTO :EOF
:error
ECHO.
ECHO Errors were detected!
REM don't pause if continuous integration else the build server waits forever
REM before cancelling the build (and, there is noone to read the output anyways)
IF isci NEQ 1 PAUSE
:showerror
PAUSE
+21 -48
View File
@@ -1,59 +1,32 @@
@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
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"
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\"
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 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%')"
)
SET buildFolder=%CD%
SET drive=%CD:~0,2%
SET nuGetFolder=%drive%\packages\
FOR /f "delims=" %%A in ('dir "%nuGetFolder%npm.*" /b') DO SET "npmPath=%nuGetFolder%%%A\"
ECHO Change directory to %CD%\..\src\Umbraco.Web.UI.Client\
CD %CD%\..\src\Umbraco.Web.UI.Client\
IF [%npmPath%] == [] GOTO :installnpm
IF NOT [%npmPath%] == [] GOTO :build
ECHO Do npm install and the grunt build of Belle
call npm install --quiet
call npm install -g grunt-cli --quiet
call npm install -g bower --quiet
call grunt build --buildversion=%release%
: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%
+13 -44
View File
@@ -1,33 +1,23 @@
@ECHO OFF
SETLOCAL
:: SETLOCAL is on, so changes to the path not persist to the actual user's path
REM SETLOCAL is on, so changes to the path not persist to the actual user's path
git.exe --version
IF %ERRORLEVEL%==9009 GOTO :trydefaultpath
git.exe 2> NUL
if %ERRORLEVEL%==9009 GOTO :trydefaultpath
GOTO :EOF
:: Git is installed, no need to to anything else
:trydefaultpath
PATH=C:\Program Files (x86)\Git\cmd;C:\Program Files\Git\cmd;%PATH%
git.exe --version
IF %ERRORLEVEL%==9009 GOTO :showerror
path=C:\Program Files (x86)\Git\cmd;C:\Program Files\Git\cmd;%PATH%
git.exe 2> NUL
if %ERRORLEVEL%==9009 GOTO :showerror
GOTO :EOF
:: Git is installed, no need to to anything else
:showerror
ECHO Git is not in your path and could not be found in C:\Program Files (x86)\Git\cmd nor in C:\Program Files\Git\cmd
SET /p install=" Do you want to install Git through Chocolatey [y/n]? " %=%
IF %install%==y (
:: Create a temporary batch file to execute either after elevating to admin or as-is when the user is already admin
ECHO @ECHO OFF > "%temp%\ChocoInstallGit.cmd"
ECHO SETLOCAL >> "%temp%\ChocoInstallGit.cmd"
ECHO ECHO Installing Chocolatey first >> "%temp%\ChocoInstallGit.cmd"
ECHO @powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" >> "%temp%\ChocoInstallGit.cmd"
ECHO SET PATH=%%PATH%%;%%ALLUSERSPROFILE%%\chocolatey\bin >> "%temp%\ChocoInstallGit.cmd"
ECHO choco install git -y >> "%temp%\ChocoInstallGit.cmd"
set /p install=" Do you want to install Git through Chocolatey [y/n]? " %=%
if %install%==y (
GOTO :installgit
) ELSE (
) else (
GOTO :cantcontinue
)
@@ -36,28 +26,7 @@ ECHO Can't complete the build without Git being in the path. Please add it to be
GOTO :EOF
:installgit
pushd %~dp0
:: Running prompt elevated
:: --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
:: --> If error flag set, we do not have admin.
IF '%errorlevel%' NEQ '0' (
GOTO UACPrompt
) ELSE ( GOTO gotAdmin )
:UACPrompt
ECHO You're not currently running this with admin privileges, we'll now try to execute the install of Git through Chocolatey after elevating to admin privileges
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
ECHO UAC.ShellExecute "%temp%\ChocoInstallGit.cmd", "", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
EXIT /B
:gotAdmin
IF EXIST "%temp%\getadmin.vbs" ( DEL "%temp%\getadmin.vbs" )
pushd "%CD%"
CD /D "%~dp0"
CALL "%temp%\ChocoInstallGit.cmd"
ECHO Installing Chocolatey first
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin
ECHO Installing Git through Chocolatey
choco install git
+9 -11
View File
@@ -27,18 +27,16 @@
<dependency id="SharpZipLib" version="[0.86.0, 1.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)" />
<!-- AutoMapper can not be updated due to: https://github.com/AutoMapper/AutoMapper/issues/373#issuecomment-127644405 -->
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
<dependency id="Newtonsoft.Json" version="[6.0.8, 10.0.0)" />
<dependency id="Examine" version="[0.1.82, 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="ClientDependency" version="[1.8.4, 2.0.0)" />
<dependency id="ClientDependency-Mvc5" version="[1.8.0, 2.0.0)" />
<dependency id="AutoMapper" version="[3.0.0, 3.1.0)" />
<dependency id="Newtonsoft.Json" version="[6.0.8, 9.0.0)" />
<dependency id="Examine" version="[0.1.68, 1.0.0)" />
<dependency id="ImageProcessor" version="[2.3.3, 3.0.0)" />
<dependency id="ImageProcessor.Web" version="[4.5.3, 5.0.0)" />
<dependency id="semver" version="[1.1.2, 2.0.0)" />
<dependency id="UrlRewritingNet" version="[2.0.7, 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="Markdown" version="[1.14.4, 2.0.0)" />
</dependencies>
</metadata>
<files>
@@ -103,4 +101,4 @@
<file src="..\_BuildOutput\bin\UmbracoExamine.pdb" target="lib" />
<file src="..\..\src\UmbracoExamine\**\*.cs" exclude="..\..\src\**\TemporaryGeneratedFile*.cs" target="src\UmbracoExamine" />
</files>
</package>
</package>
+3 -7
View File
@@ -16,9 +16,8 @@
<tags>umbraco</tags>
<dependencies>
<dependency id="UmbracoCms.Core" version="[$version$]" />
<dependency id="Newtonsoft.Json" version="[6.0.8, 10.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.7, 4.0.0)" />
<dependency id="ImageProcessor.Web.Config" version="[2.3.0, 3.0.0)" />
<dependency id="Newtonsoft.Json" version="[6.0.8, 9.0.0)" />
<dependency id="Umbraco.ModelsBuilder" version="[3.0.2, 4.0.0)" />
</dependencies>
</metadata>
<files>
@@ -33,7 +32,6 @@
<file src="..\_BuildOutput\WebApp\config\splashes\**" target="UmbracoFiles\Config\splashes" />
<file src="..\_BuildOutput\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
<file src="..\_BuildOutput\WebApp\umbraco_client\**" target="UmbracoFiles\umbraco_client" />
<file src="..\_BuildOutput\WebApp\Media\Web.config" target="Content\Media\Web.config" />
<file src="tools\install.ps1" target="tools\install.ps1" />
<file src="tools\Readme.txt" target="tools\Readme.txt" />
<file src="tools\ReadmeUpgrade.txt" target="tools\ReadmeUpgrade.txt" />
@@ -44,8 +42,6 @@
<file src="tools\trees.config.install.xdt" target="Content\config\trees.config.install.xdt" />
<file src="tools\umbracoSettings.config.install.xdt" target="Content\config\umbracoSettings.config.install.xdt" />
<file src="tools\Views.Web.config.install.xdt" target="Views\Web.config.install.xdt" />
<file src="tools\processing.config.install.xdt" target="Content\Config\imageprocessor\processing.config.install.xdt" />
<file src="tools\cache.config.install.xdt" target="Content\Config\imageprocessor\cache.config.install.xdt" />
<file src="build\**" target="build" />
</files>
</package>
</package>
@@ -21,12 +21,6 @@
</section>
<section alias="StartupDeveloperDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<areas xdt:Transform="InsertIfMissing">
<area xdt:Transform="InsertIfMissing">developer</area>
</areas>
</section>
<section alias="StartupDeveloperDashboardSection">
<tab caption="Get Started" xdt:Locator="Match(caption)" xdt:Transform="Replace">
<control showOnce="true" addPanel="true" panelCaption="">
views/dashboard/developer/developerdashboardvideos.html
@@ -36,11 +30,16 @@
</section>
<section alias="StartupDeveloperDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<tab caption="Examine Management" xdt:Locator="Match(caption)" xdt:Transform="InsertIfMissing">
<tab caption="Examine Management" xdt:Locator="Match(caption)" xdt:Transform="InsertIfMissing">
<control>
views/dashboard/developer/examinemanagement.html
</control>
</tab>
</tab>
<tab caption="Xml Data Integrity Report" xdt:Transform="InsertIfMissing">
<control>
views/dashboard/developer/xmldataintegrityreport.html
</control>
</tab>
</section>
<section alias="StartupMediaDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
@@ -53,6 +52,19 @@
</tab>
</section>
<section alias="StartupDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<tab caption="Get Started" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
<tab caption="Get Started" xdt:Transform="Insert">
<access>
<grant>admin</grant>
</access>
<control showOnce="true" addPanel="true" panelCaption="">
views/dashboard/default/startupdashboardintro.html
</control>
</tab>
<tab caption="Last Edits" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
</section>
<section alias="StartupMemberDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<tab caption="Get Started" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
<tab caption="Get Started" xdt:Transform="Insert">
@@ -68,28 +80,5 @@
<section alias="StartupDashboardSection">
<tab caption="Change Password" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
<tab caption="Last Edits" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
</section>
<section alias="RedirectUrlManagement" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<areas>
<area>content</area>
</areas>
<tab caption="Redirect URL Management">
<control>
views/dashboard/developer/redirecturls.html
</control>
</tab>
</section>
<section alias="UmbracoHealthCheck" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
<areas>
<area>developer</area>
</areas>
<tab caption="Health Check">
<control>
views/dashboard/developer/healthcheck.html
</control>
</tab>
</section>
</dashBoard>
+1 -8
View File
@@ -292,8 +292,6 @@
<mimeMap fileExtension=".svg" mimeType="image/svg+xml" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<remove fileExtension=".woff" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<mimeMap fileExtension=".woff" mimeType="application/x-font-woff" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<remove fileExtension=".woff2" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<mimeMap fileExtension=".woff2" mimeType="application/x-font-woff2" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<remove fileExtension=".less" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
<mimeMap fileExtension=".less" mimeType="text/css" xdt:Locator="Match(fileExtension)" xdt:Transform="InsertIfMissing" />
</staticContent>
@@ -319,7 +317,6 @@
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='HtmlAgilityPack')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='AutoMapper')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Newtonsoft.Json')" xdt:Transform="Remove" />
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Web.Mvc')" xdt:Transform="Remove" />
@@ -335,14 +332,10 @@
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly xdt:Transform="Insert">
<dependentAssembly>
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
<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" />
<bindingRedirect oldVersion="0.0.0.0-3.3.1.0" newVersion="3.3.1.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
@@ -1,6 +0,0 @@
<?xml version="1.0"?>
<caching xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<caches>
<cache name="DiskCache" trimCache="false" xdt:Transform="SetAttributes(trimCache)" xdt:Locator="Match(name)" />
</caches>
</caching>
-1
View File
@@ -71,7 +71,6 @@ if ($project) {
if(Test-Path $umbracoBinFolder\ImageProcessor.dll) { Remove-Item $umbracoBinFolder\ImageProcessor.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\ImageProcessor.Web.dll) { Remove-Item $umbracoBinFolder\ImageProcessor.Web.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Lucene.Net.dll) { Remove-Item $umbracoBinFolder\Lucene.Net.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Microsoft.IO.RecyclableMemoryStream.dll) { Remove-Item $umbracoBinFolder\Microsoft.IO.RecyclableMemoryStream.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Microsoft.AspNet.Identity.Core.dll) { Remove-Item $umbracoBinFolder\Microsoft.AspNet.Identity.Core.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Microsoft.AspNet.Identity.Owin.dll) { Remove-Item $umbracoBinFolder\Microsoft.AspNet.Identity.Owin.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Microsoft.CodeAnalysis.CSharp.dll) { Remove-Item $umbracoBinFolder\Microsoft.CodeAnalysis.CSharp.dll -Force -Confirm:$false }
+1 -6
View File
@@ -97,12 +97,7 @@ if ($project) {
$umbracoUIXMLSource = Join-Path $installPath "UmbracoFiles\Umbraco\Config\Create\UI.xml"
$umbracoUIXMLDestination = Join-Path $projectPath "Umbraco\Config\Create\UI.xml"
Copy-Item $umbracoUIXMLSource $umbracoUIXMLDestination -Force
} else {
$upgradeViewSource = Join-Path $umbracoFolderSource "Views\install\*"
$upgradeView = Join-Path $umbracoFolder "Views\install\"
Write-Host "Copying2 ${upgradeViewSource} to ${upgradeView}"
Copy-Item $upgradeViewSource $upgradeView -Force
}
}
$installFolder = Join-Path $projectPath "Install"
if(Test-Path $installFolder) {
@@ -1 +0,0 @@
<processing xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" xdt:Transform="SetAttributes(preserveExifMetaData)" preserveExifMetaData="true" />
+9 -17
View File
@@ -55,29 +55,21 @@
xdt:Transform="SetAttributes()" />
<!--Developer-->
<add alias="packager" application="developer"
<add alias="datatype" application="developer"
xdt:Locator="Match(application,alias)"
xdt:Transform="Remove" />
<add alias="packagerPackages" application="developer"
<add initialize="true" sortOrder="0" alias="datatypes" application="developer" title="Data Types" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.DataTypeTreeController, umbraco"
xdt:Locator="Match(application,alias)"
xdt:Transform="Remove" />
<add initialize="true" sortOrder="0" alias="packager" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.PackagesTreeController, umbraco"
xdt:Locator="Match(application,alias)"
xdt:Transform="InsertIfMissing" />
<!-- Before 7.4 this tree had the alias 'dataType', without the 's' on the end, this is here to rename it -->
<add sortOrder="1" alias="dataTypes" application="developer" type="Umbraco.Web.Trees.DataTypeTreeController, umbraco"
xdt:Locator="Match(application,type)"
xdt:Transform="SetAttributes(alias,sortOrder)" />
<!-- Yes, set the sortOrder again, like above because.. sometimes apparently we already have a dataTypes node and we can't remove more than one.. if they're equal though (same alias,application and sortOrder) it doesn't throw an error -->
<add sortOrder="1" alias="dataTypes" application="developer"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes(sortOrder)" />
xdt:Transform="InsertIfMissing" />
<add application="developer" alias="macros" title="Macros" type="umbraco.loadMacros, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="2"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="packager" title="Packages" type="umbraco.loadPackager, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="3"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="packagerPackages" title="Packager Packages" type="umbraco.loadPackages, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" initialize="false" sortOrder="3"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="relationTypes" title="Relation Types" type="umbraco.loadRelationTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
+1 -1
View File
@@ -1,2 +1,2 @@
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
7.5.13
7.5.0
+4
View File
@@ -49,9 +49,13 @@
<Reference Include="System.Core" />
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
<Private>False</Private>
</Reference>
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
<Private>False</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
+9 -4
View File
@@ -40,10 +40,15 @@ namespace SqlCE4Umbraco
var localConnection = new SqlCeConnection(ConnectionString);
if (!System.IO.File.Exists(ReplaceDataDirectory(localConnection.Database)))
{
using (var sqlCeEngine = new SqlCeEngine(ConnectionString))
{
sqlCeEngine.CreateDatabase();
}
var sqlCeEngine = new SqlCeEngine(ConnectionString);
sqlCeEngine.CreateDatabase();
// SD: Pretty sure this should be in a using clause but i don't want to cause unknown side-effects here
// since it's been like this for quite some time
//using (var sqlCeEngine = new SqlCeEngine(ConnectionString))
//{
// sqlCeEngine.CreateDatabase();
//}
}
}
+22 -24
View File
@@ -21,15 +21,15 @@ namespace SqlCE4Umbraco
public class SqlCEInstaller : DefaultInstallerUtility<SqlCEHelper>
{
#region Private Constants
/// <summary>The latest database version this installer supports.</summary>
private const DatabaseVersion LatestVersionSupported = DatabaseVersion.Version4_8;
/// <summary>The specifications to determine the database version.</summary>
private static readonly VersionSpecs[] m_VersionSpecs = new VersionSpecs[] {
new VersionSpecs("SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS LEFT OUTER JOIN umbracoApp ON appAlias = appAlias WHERE CONSTRAINT_NAME = 'FK_umbracoUser2app_umbracoApp'", 0, DatabaseVersion.Version4_8),
new VersionSpecs("SELECT id FROM umbracoNode WHERE id = -21", 1, DatabaseVersion.Version4_1),
new VersionSpecs("SELECT action FROM umbracoAppTree",DatabaseVersion.Version4),
new VersionSpecs("SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS LEFT OUTER JOIN umbracoApp ON appAlias = appAlias WHERE CONSTRAINT_NAME = 'FK_umbracoUser2app_umbracoApp'", 0, DatabaseVersion.Version4_8),
new VersionSpecs("SELECT id FROM umbracoNode WHERE id = -21", 1, DatabaseVersion.Version4_1),
new VersionSpecs("SELECT action FROM umbracoAppTree",DatabaseVersion.Version4),
new VersionSpecs("SELECT description FROM cmsContentType",DatabaseVersion.Version3),
new VersionSpecs("SELECT id FROM sysobjects",DatabaseVersion.None) };
@@ -43,9 +43,8 @@ namespace SqlCE4Umbraco
public override bool CanConnect
{
get
{
using (var sqlHelper = SqlHelper)
sqlHelper.CreateEmptyDatabase();
{
SqlHelper.CreateEmptyDatabase();
return base.CanConnect;
}
}
@@ -94,22 +93,22 @@ namespace SqlCE4Umbraco
#region DefaultInstaller Members
/// <summary>
/// Returns the sql to do a full install
/// </summary>
protected override string FullInstallSql
{
get { return string.Empty; }
}
/// <summary>
/// Returns the sql to do a full install
/// </summary>
protected override string FullInstallSql
{
get { return string.Empty; }
}
/// <summary>
/// Returns the sql to do an upgrade
/// </summary>
protected override string UpgradeSql
{
get { return string.Empty; }
}
/// <summary>
/// Returns the sql to do an upgrade
/// </summary>
protected override string UpgradeSql
{
get { return string.Empty; }
}
// We need to override this as the default way of detection a db connection checks for systables that doesn't exist
// in a CE db
@@ -124,9 +123,8 @@ namespace SqlCE4Umbraco
// verify connection
try
{
using (var sqlHelper = SqlHelper)
if (SqlCeApplicationBlock.VerifyConnection(sqlHelper.ConnectionString))
return DatabaseVersion.None;
if (SqlCeApplicationBlock.VerifyConnection(base.SqlHelper.ConnectionString))
return DatabaseVersion.None;
}
catch (Exception e)
{
+11 -17
View File
@@ -37,15 +37,13 @@ namespace SqlCE4Umbraco
ITable table = null;
// get name in correct casing
using (var sqlHelper = SqlHelper)
name = sqlHelper.ExecuteScalar<string>("SELECT name FROM sys.tables WHERE name=@name",
sqlHelper.CreateParameter("name", name));
name = SqlHelper.ExecuteScalar<string>("SELECT name FROM sys.tables WHERE name=@name",
SqlHelper.CreateParameter("name", name));
if (name != null)
{
table = new DefaultTable(name);
using (var sqlHelper = SqlHelper)
using (IRecordsReader reader = sqlHelper.ExecuteReader(
using (IRecordsReader reader = SqlHelper.ExecuteReader(
@"SELECT c.name AS Name, st.name AS DataType, c.max_length, c.is_nullable, c.is_identity
FROM sys.tables AS t
JOIN sys.columns AS c ON t.object_id = c.object_id
@@ -53,7 +51,7 @@ namespace SqlCE4Umbraco
JOIN sys.types AS ty ON ty.user_type_id = c.user_type_id
JOIN sys.types st ON ty.system_type_id = st.user_type_id
WHERE t.name = @name
ORDER BY c.column_id", sqlHelper.CreateParameter("name", name)))
ORDER BY c.column_id", SqlHelper.CreateParameter("name", name)))
{
while (reader.Read())
{
@@ -114,8 +112,7 @@ namespace SqlCE4Umbraco
// create query
StringBuilder createTableQuery = new StringBuilder();
using (var sqlHelper = SqlHelper)
createTableQuery.AppendFormat("CREATE TABLE [{0}] (", sqlHelper.EscapeString(table.Name));
createTableQuery.AppendFormat("CREATE TABLE [{0}] (", SqlHelper.EscapeString(table.Name));
// add fields
while (hasNext)
@@ -139,8 +136,7 @@ namespace SqlCE4Umbraco
// execute query
try
{
using (var sqlHelper = SqlHelper)
sqlHelper.ExecuteNonQuery(createTableQuery.ToString());
SqlHelper.ExecuteNonQuery(createTableQuery.ToString());
}
catch (Exception executeException)
{
@@ -158,15 +154,13 @@ namespace SqlCE4Umbraco
Debug.Assert(table != null && field != null);
StringBuilder addColumnQuery = new StringBuilder();
using (var sqlHelper = SqlHelper)
addColumnQuery.AppendFormat("ALTER TABLE [{0}] ADD [{1}] {2}",
sqlHelper.EscapeString(table.Name),
sqlHelper.EscapeString(field.Name),
sqlHelper.EscapeString(GetDatabaseType(field)));
addColumnQuery.AppendFormat("ALTER TABLE [{0}] ADD [{1}] {2}",
SqlHelper.EscapeString(table.Name),
SqlHelper.EscapeString(field.Name),
SqlHelper.EscapeString(GetDatabaseType(field)));
try
{
using (var sqlHelper = SqlHelper)
sqlHelper.ExecuteNonQuery(addColumnQuery.ToString());
SqlHelper.ExecuteNonQuery(addColumnQuery.ToString());
}
catch (Exception executeException)
{
+3 -3
View File
@@ -2,7 +2,7 @@
using System.Resources;
[assembly: AssemblyCompany("Umbraco")]
[assembly: AssemblyCopyright("Copyright © Umbraco 2017")]
[assembly: AssemblyCopyright("Copyright © Umbraco 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.5.13")]
[assembly: AssemblyInformationalVersion("7.5.13")]
[assembly: AssemblyFileVersion("7.5.0")]
[assembly: AssemblyInformationalVersion("7.5.0")]
+22 -8
View File
@@ -1,18 +1,22 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;
using Umbraco.Core.Packaging;
using Umbraco.Core.Persistence.Migrations;
using Umbraco.Core.Profiling;
using Umbraco.Core.Services;
using Umbraco.Core.Sync;
namespace Umbraco.Core
{
/// <summary>
/// <summary>
/// the Umbraco Application context
/// </summary>
/// <remarks>
@@ -183,6 +187,7 @@ namespace Umbraco.Core
readonly ManualResetEventSlim _isReadyEvent = new ManualResetEventSlim(false);
private DatabaseContext _databaseContext;
private ServiceContext _services;
private PackageMigrationsContext _packageMigrationsContext;
public bool IsReady
{
@@ -212,17 +217,19 @@ namespace Umbraco.Core
public bool IsConfigured
{
get { return _configured.Value; }
get { return _umbracoVersionConfigured.Value; }
}
/// <summary>
/// If the db is configured, there is a database context and there is an umbraco schema, but we are not 'configured' , then it means we are upgrading
/// If the db is configured, there is a database context and there is an umbraco schema,
/// but we are: (not 'configured' OR there's pending migrations), then it means we are upgrading
/// </summary>
public bool IsUpgrading
{
get
{
if (IsConfigured == false
if ((IsConfigured == false || PackageMigrationsContext.HasPendingPackageMigrations)
&& DatabaseContext != null
&& DatabaseContext.IsDatabaseConfigured)
{
@@ -268,7 +275,8 @@ namespace Umbraco.Core
// ReSharper disable once InconsistentNaming
internal string _umbracoApplicationUrl;
private Lazy<bool> _configured;
private Lazy<bool> _umbracoVersionConfigured;
internal MainDom MainDom { get; private set; }
private void Init()
@@ -277,7 +285,7 @@ namespace Umbraco.Core
MainDom.Acquire();
//Create the lazy value to resolve whether or not the application is 'configured'
_configured = new Lazy<bool>(() =>
_umbracoVersionConfigured = new Lazy<bool>(() =>
{
try
{
@@ -318,9 +326,10 @@ namespace Umbraco.Core
LogHelper.Error<ApplicationContext>("Error determining if application is configured, returning false", ex);
return false;
}
});
});
}
_packageMigrationsContext = new PackageMigrationsContext(DatabaseContext, Services.MigrationEntryService, ProfilingLogger.Logger);
}
private string ConfigurationStatus
{
@@ -343,6 +352,11 @@ namespace Umbraco.Core
throw new Exception("ApplicationContext has already been initialized.");
}
internal PackageMigrationsContext PackageMigrationsContext
{
get { return _packageMigrationsContext; }
}
/// <summary>
/// Gets the current DatabaseContext
/// </summary>
+1 -2
View File
@@ -64,8 +64,7 @@ namespace Umbraco.Core.Cache
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
public const string ContentTypePropertiesCacheKey = "ContentType_PropertyTypes_Content:";
[Obsolete("No longer used and will be removed in v8")]
[EditorBrowsable(EditorBrowsableState.Never)]
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
public const string PropertyTypeCacheKey = "UmbracoPropertyTypeCache";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
@@ -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);
}
@@ -9,9 +9,6 @@ namespace Umbraco.Core.Cache
/// <summary>
/// A cache provider that caches items in the HttpContext.Items
/// </summary>
/// <remarks>
/// If the Items collection is null, then this provider has no effect
/// </remarks>
internal class HttpRequestCacheProvider : DictionaryCacheProviderBase
{
// context provider
@@ -37,11 +34,6 @@ namespace Umbraco.Core.Cache
get { return _context != null ? _context.Items : HttpContext.Current.Items; }
}
private bool HasContextItems
{
get { return (_context != null && _context.Items != null) || HttpContext.Current != null; }
}
// for unit tests
public HttpRequestCacheProvider(HttpContextBase context)
{
@@ -58,23 +50,18 @@ namespace Umbraco.Core.Cache
protected override IEnumerable<DictionaryEntry> GetDictionaryEntries()
{
const string prefix = CacheItemPrefix + "-";
if (HasContextItems == false) return Enumerable.Empty<DictionaryEntry>();
return ContextItems.Cast<DictionaryEntry>()
.Where(x => x.Key is string && ((string)x.Key).StartsWith(prefix));
}
protected override void RemoveEntry(string key)
{
if (HasContextItems == false) return;
ContextItems.Remove(key);
}
protected override object GetEntry(string key)
{
return HasContextItems ? ContextItems[key] : null;
return ContextItems[key];
}
#region Lock
@@ -94,9 +81,7 @@ namespace Umbraco.Core.Cache
get
{
return HasContextItems
? (IDisposable) new MonitorLock(ContextItems.SyncRoot)
: new NoopLocker();
return new MonitorLock(ContextItems.SyncRoot);
}
}
@@ -106,9 +91,6 @@ namespace Umbraco.Core.Cache
public override object GetCacheItem(string cacheKey, Func<object> getCacheItem)
{
//no place to cache so just return the callback result
if (HasContextItems == false) return getCacheItem();
cacheKey = GetCacheKey(cacheKey);
Lazy<object> result;
@@ -146,10 +128,5 @@ namespace Umbraco.Core.Cache
#region Insert
#endregion
private class NoopLocker : DisposableObject
{
protected override void DisposeResources()
{ }
}
}
}
+21 -12
View File
@@ -5,31 +5,38 @@ using System.Web.Caching;
namespace Umbraco.Core.Cache
{
/// <summary>
/// Represents a cache provider that does not cache anything.
/// </summary>
public class NullCacheProvider : IRuntimeCacheProvider
internal class NullCacheProvider : IRuntimeCacheProvider
{
public virtual void ClearAllCache()
{ }
{
}
public virtual void ClearCacheItem(string key)
{ }
{
}
public virtual void ClearCacheObjectTypes(string typeName)
{ }
{
}
public virtual void ClearCacheObjectTypes<T>()
{ }
{
}
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
{ }
{
}
public virtual void ClearCacheByKeySearch(string keyStartsWith)
{ }
{
}
public virtual void ClearCacheByKeyExpression(string regexString)
{ }
{
}
public virtual IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
{
@@ -57,6 +64,8 @@ namespace Umbraco.Core.Cache
}
public void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
{ }
{
}
}
}
@@ -1,23 +1,23 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.Caching;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web.Caching;
using Umbraco.Core.Logging;
using CacheItemPriority = System.Web.Caching.CacheItemPriority;
namespace Umbraco.Core.Cache
{
/// <summary>
/// Represents a cache provider that caches item in a <see cref="MemoryCache"/>.
/// A cache provider that wraps the logic of a System.Runtime.Caching.ObjectCache
/// </summary>
/// <remarks>The <see cref="MemoryCache"/> is created with name "in-memory". That name is
/// used to retrieve configuration options. It does not identify the memory cache, i.e.
/// each instance of this class has its own, independent, memory cache.</remarks>
public class ObjectCacheRuntimeCacheProvider : IRuntimeCacheProvider
internal class ObjectCacheRuntimeCacheProvider : IRuntimeCacheProvider
{
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
internal ObjectCache MemoryCache;
@@ -3,13 +3,14 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Caching;
namespace Umbraco.Core.Cache
{
/// <summary>
/// Represents a cache provider that statically caches item in a concurrent dictionary.
/// A cache provider that statically caches everything in an in memory dictionary
/// </summary>
public class StaticCacheProvider : ICacheProvider
internal class StaticCacheProvider : ICacheProvider
{
internal readonly ConcurrentDictionary<string, object> StaticCache = new ConcurrentDictionary<string, object>();
@@ -74,6 +75,7 @@ namespace Umbraco.Core.Cache
public virtual object GetCacheItem(string cacheKey, Func<object> getCacheItem)
{
return StaticCache.GetOrAdd(cacheKey, key => getCacheItem());
}
}
}
}
@@ -1,9 +0,0 @@
namespace Umbraco.Core.Configuration
{
internal enum ContentXmlStorage
{
Default,
AspNetTemp,
EnvironmentTemp
}
}
@@ -1,27 +0,0 @@
using System;
namespace Umbraco.Core.Configuration
{
internal static class CoreDebugExtensions
{
private static CoreDebug _coreDebug;
public static CoreDebug CoreDebug(this UmbracoConfig config)
{
return _coreDebug ?? (_coreDebug = new CoreDebug());
}
}
internal class CoreDebug
{
public CoreDebug()
{
var appSettings = System.Configuration.ConfigurationManager.AppSettings;
DumpOnTimeoutThreadAbort = string.Equals("true", appSettings["Umbraco.CoreDebug.DumpOnTimeoutThreadAbort"], StringComparison.OrdinalIgnoreCase);
}
// 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; }
}
}
@@ -520,25 +520,12 @@ namespace Umbraco.Core.Configuration
}
internal static bool ContentCacheXmlStoredInCodeGen
{
get { return ContentCacheXmlStorageLocation == ContentXmlStorage.AspNetTemp; }
}
internal static ContentXmlStorage ContentCacheXmlStorageLocation
{
get
{
if (ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLStorage"))
{
return Enum<ContentXmlStorage>.Parse(ConfigurationManager.AppSettings["umbracoContentXMLStorage"]);
}
if (ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLUseLocalTemp"))
{
return bool.Parse(ConfigurationManager.AppSettings["umbracoContentXMLUseLocalTemp"])
? ContentXmlStorage.AspNetTemp
: ContentXmlStorage.Default;
}
return ContentXmlStorage.Default;
//defaults to false
return ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLUseLocalTemp")
&& bool.Parse(ConfigurationManager.AppSettings["umbracoContentXMLUseLocalTemp"]); //default to false
}
}
@@ -4,7 +4,8 @@ using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class ContentElement : UmbracoConfigurationElement, IContentSection
internal class ContentElement : ConfigurationElement, IContentSection
{
[ConfigurationProperty("imaging")]
internal ContentImagingElement Imaging
@@ -21,13 +22,25 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
[ConfigurationProperty("ResolveUrlsFromTextString")]
internal InnerTextConfigurationElement<bool> ResolveUrlsFromTextString
{
get { return GetOptionalTextElement<bool>("ResolveUrlsFromTextString", false); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["ResolveUrlsFromTextString"],
//set the default
false);
}
}
[ConfigurationProperty("UploadAllowDirectories")]
internal InnerTextConfigurationElement<bool> UploadAllowDirectories
{
get { return GetOptionalTextElement("UploadAllowDirectories", true); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["UploadAllowDirectories"],
//set the default
true);
}
}
public IEnumerable<IContentErrorPage> Error404Collection
@@ -50,61 +63,121 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
[ConfigurationProperty("ensureUniqueNaming")]
internal InnerTextConfigurationElement<bool> EnsureUniqueNaming
{
get { return GetOptionalTextElement("ensureUniqueNaming", true); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["ensureUniqueNaming"],
//set the default
true);
}
}
[ConfigurationProperty("TidyEditorContent")]
internal InnerTextConfigurationElement<bool> TidyEditorContent
{
get { return GetOptionalTextElement("TidyEditorContent", false); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["TidyEditorContent"],
//set the default
false);
}
}
[ConfigurationProperty("TidyCharEncoding")]
internal InnerTextConfigurationElement<string> TidyCharEncoding
{
get { return GetOptionalTextElement("TidyCharEncoding", "UTF8"); }
get
{
return new OptionalInnerTextConfigurationElement<string>(
(InnerTextConfigurationElement<string>)this["TidyCharEncoding"],
//set the default
"UTF8");
}
}
[ConfigurationProperty("XmlCacheEnabled")]
internal InnerTextConfigurationElement<bool> XmlCacheEnabled
{
get { return GetOptionalTextElement("XmlCacheEnabled", true); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["XmlCacheEnabled"],
//set the default
true);
}
}
[ConfigurationProperty("ContinouslyUpdateXmlDiskCache")]
internal InnerTextConfigurationElement<bool> ContinouslyUpdateXmlDiskCache
{
get { return GetOptionalTextElement("ContinouslyUpdateXmlDiskCache", true); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["ContinouslyUpdateXmlDiskCache"],
//set the default
true);
}
}
[ConfigurationProperty("XmlContentCheckForDiskChanges")]
internal InnerTextConfigurationElement<bool> XmlContentCheckForDiskChanges
{
get { return GetOptionalTextElement("XmlContentCheckForDiskChanges", false); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["XmlContentCheckForDiskChanges"],
//set the default
false);
}
}
[ConfigurationProperty("EnableSplashWhileLoading")]
internal InnerTextConfigurationElement<bool> EnableSplashWhileLoading
{
get { return GetOptionalTextElement("EnableSplashWhileLoading", false); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["EnableSplashWhileLoading"],
//set the default
false);
}
}
[ConfigurationProperty("PropertyContextHelpOption")]
internal InnerTextConfigurationElement<string> PropertyContextHelpOption
{
get { return GetOptionalTextElement("PropertyContextHelpOption", "text"); }
get
{
return new OptionalInnerTextConfigurationElement<string>(
(InnerTextConfigurationElement<string>)this["PropertyContextHelpOption"],
//set the default
"text");
}
}
[ConfigurationProperty("UseLegacyXmlSchema")]
internal InnerTextConfigurationElement<bool> UseLegacyXmlSchema
{
get { return GetOptionalTextElement("UseLegacyXmlSchema", false); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["UseLegacyXmlSchema"],
//set the default
false);
}
}
[ConfigurationProperty("ForceSafeAliases")]
internal InnerTextConfigurationElement<bool> ForceSafeAliases
{
get { return GetOptionalTextElement("ForceSafeAliases", true); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["ForceSafeAliases"],
//set the default
true);
}
}
[ConfigurationProperty("PreviewBadge")]
@@ -112,65 +185,113 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{
get
{
return GetOptionalTextElement("PreviewBadge", @"<a id=""umbracoPreviewBadge"" style=""position: absolute; top: 0; right: 0; border: 0; width: 149px; height: 149px; background: url('{1}/preview/previewModeBadge.png') no-repeat;"" href=""{0}/endPreview.aspx?redir={2}""><span style=""display:none;"">In Preview Mode - click to end</span></a>");
return new OptionalInnerTextConfigurationElement<string>(
(InnerTextConfigurationElement<string>)this["PreviewBadge"],
//set the default
@"<a id=""umbracoPreviewBadge"" style=""position: absolute; top: 0; right: 0; border: 0; width: 149px; height: 149px; background: url('{1}/preview/previewModeBadge.png') no-repeat;"" href=""{0}/endPreview.aspx?redir={2}""><span style=""display:none;"">In Preview Mode - click to end</span></a>");
}
}
[ConfigurationProperty("UmbracoLibraryCacheDuration")]
internal InnerTextConfigurationElement<int> UmbracoLibraryCacheDuration
{
get { return GetOptionalTextElement("UmbracoLibraryCacheDuration", 1800); }
get
{
return new OptionalInnerTextConfigurationElement<int>(
(InnerTextConfigurationElement<int>)this["UmbracoLibraryCacheDuration"],
//set the default
1800);
}
}
[ConfigurationProperty("MacroErrors")]
internal InnerTextConfigurationElement<MacroErrorBehaviour> MacroErrors
{
get { return GetOptionalTextElement("MacroErrors", MacroErrorBehaviour.Inline); }
get
{
return new OptionalInnerTextConfigurationElement<MacroErrorBehaviour>(
(InnerTextConfigurationElement<MacroErrorBehaviour>)this["MacroErrors"],
//set the default
MacroErrorBehaviour.Inline);
}
}
[Obsolete("This is here so that if this config element exists we won't get a YSOD, it is not used whatsoever and will be removed in future versions")]
[ConfigurationProperty("DocumentTypeIconList")]
internal InnerTextConfigurationElement<IconPickerBehaviour> DocumentTypeIconList
{
get { return GetOptionalTextElement("DocumentTypeIconList", IconPickerBehaviour.HideFileDuplicates); }
get
{
return new OptionalInnerTextConfigurationElement<IconPickerBehaviour>(
(InnerTextConfigurationElement<IconPickerBehaviour>)this["DocumentTypeIconList"],
//set the default
IconPickerBehaviour.HideFileDuplicates);
}
}
[ConfigurationProperty("disallowedUploadFiles")]
internal CommaDelimitedConfigurationElement DisallowedUploadFiles
{
get { return GetOptionalDelimitedElement("disallowedUploadFiles", new[] {"ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd"}); }
get
{
return new OptionalCommaDelimitedConfigurationElement(
(CommaDelimitedConfigurationElement)this["disallowedUploadFiles"],
//set the default
new[] { "ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd" });
}
}
[ConfigurationProperty("cloneXmlContent")]
internal InnerTextConfigurationElement<bool> CloneXmlContent
{
get { return GetOptionalTextElement("cloneXmlContent", true); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["cloneXmlContent"],
//set the default
true);
}
}
[ConfigurationProperty("GlobalPreviewStorageEnabled")]
internal InnerTextConfigurationElement<bool> GlobalPreviewStorageEnabled
{
get { return GetOptionalTextElement("GlobalPreviewStorageEnabled", false); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["GlobalPreviewStorageEnabled"],
//set the default
false);
}
}
[ConfigurationProperty("defaultDocumentTypeProperty")]
internal InnerTextConfigurationElement<string> DefaultDocumentTypeProperty
{
get { return GetOptionalTextElement("defaultDocumentTypeProperty", "Textstring"); }
get
{
return new OptionalInnerTextConfigurationElement<string>(
(InnerTextConfigurationElement<string>)this["defaultDocumentTypeProperty"],
//set the default
"Textstring");
}
}
[ConfigurationProperty("EnableInheritedDocumentTypes")]
internal InnerTextConfigurationElement<bool> EnableInheritedDocumentTypes
{
get { return GetOptionalTextElement("EnableInheritedDocumentTypes", true); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>) this["EnableInheritedDocumentTypes"],
//set the default
true);
}
}
[ConfigurationProperty("EnableInheritedMediaTypes")]
internal InnerTextConfigurationElement<bool> EnableInheritedMediaTypes
{
get { return GetOptionalTextElement("EnableInheritedMediaTypes", true); }
}
string IContentSection.NotificationEmailAddress
{
get { return Notifications.NotificationEmailAddress; }
@@ -310,10 +431,5 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{
get { return EnableInheritedDocumentTypes; }
}
bool IContentSection.EnableInheritedMediaTypes
{
get { return EnableInheritedMediaTypes; }
}
}
}
@@ -3,24 +3,42 @@ using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class ContentScriptEditorElement : UmbracoConfigurationElement
internal class ContentScriptEditorElement : ConfigurationElement
{
[ConfigurationProperty("scriptFolderPath")]
internal InnerTextConfigurationElement<string> ScriptFolderPath
{
get { return GetOptionalTextElement("scriptFolderPath", "/scripts"); }
get
{
return new OptionalInnerTextConfigurationElement<string>(
(InnerTextConfigurationElement<string>)this["scriptFolderPath"],
//set the default
"/scripts");
}
}
[ConfigurationProperty("scriptFileTypes")]
internal OptionalCommaDelimitedConfigurationElement ScriptFileTypes
{
get { return GetOptionalDelimitedElement("scriptFileTypes", new[] {"js", "xml"}); }
get
{
return new OptionalCommaDelimitedConfigurationElement(
(OptionalCommaDelimitedConfigurationElement)this["scriptFileTypes"],
//set the default
new[] { "js", "xml" });
}
}
[ConfigurationProperty("scriptDisableEditor")]
internal InnerTextConfigurationElement<bool> ScriptEditorDisable
{
get { return GetOptionalTextElement("scriptDisableEditor", false); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>) this["scriptDisableEditor"],
//set the default
false);
}
}
}
@@ -61,7 +61,5 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
string DefaultDocumentTypeProperty { get; }
bool EnableInheritedDocumentTypes { get; }
bool EnableInheritedMediaTypes { 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; }
}
}
@@ -9,8 +9,6 @@
bool DisableAlternativeTemplates { get; }
bool DisableFindContentByIdPath { get; }
bool DisableRedirectUrlTracking { get; }
string UrlProviderMode { get; }
@@ -2,7 +2,7 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class ImagingAutoFillUploadFieldElement : UmbracoConfigurationElement, IImagingAutoFillUploadField
internal class ImagingAutoFillUploadFieldElement : ConfigurationElement, IImagingAutoFillUploadField
{
/// <summary>
/// Allow setting internally so we can create a default
@@ -17,25 +17,49 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
[ConfigurationProperty("widthFieldAlias")]
internal InnerTextConfigurationElement<string> WidthFieldAlias
{
get { return GetOptionalTextElement("widthFieldAlias", "umbracoWidth"); }
get
{
return new OptionalInnerTextConfigurationElement<string>(
(InnerTextConfigurationElement<string>)this["widthFieldAlias"],
//set the default
"umbracoWidth");
}
}
[ConfigurationProperty("heightFieldAlias")]
internal InnerTextConfigurationElement<string> HeightFieldAlias
{
get { return GetOptionalTextElement("heightFieldAlias", "umbracoHeight"); }
get
{
return new OptionalInnerTextConfigurationElement<string>(
(InnerTextConfigurationElement<string>)this["heightFieldAlias"],
//set the default
"umbracoHeight");
}
}
[ConfigurationProperty("lengthFieldAlias")]
internal InnerTextConfigurationElement<string> LengthFieldAlias
{
get { return GetOptionalTextElement("lengthFieldAlias", "umbracoBytes"); }
get
{
return new OptionalInnerTextConfigurationElement<string>(
(InnerTextConfigurationElement<string>)this["lengthFieldAlias"],
//set the default
"umbracoBytes");
}
}
[ConfigurationProperty("extensionFieldAlias")]
internal InnerTextConfigurationElement<string> ExtensionFieldAlias
{
get { return GetOptionalTextElement("extensionFieldAlias", "umbracoExtension"); }
get
{
return new OptionalInnerTextConfigurationElement<string>(
(InnerTextConfigurationElement<string>)this["extensionFieldAlias"],
//set the default
"umbracoExtension");
}
}
string IImagingAutoFillUploadField.Alias
@@ -3,37 +3,67 @@ using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class LoggingElement : UmbracoConfigurationElement, ILoggingSection
internal class LoggingElement : ConfigurationElement, ILoggingSection
{
[ConfigurationProperty("autoCleanLogs")]
internal InnerTextConfigurationElement<bool> AutoCleanLogs
{
get { return GetOptionalTextElement("autoCleanLogs", false); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["autoCleanLogs"],
//set the default
false);
}
}
[ConfigurationProperty("enableLogging")]
internal InnerTextConfigurationElement<bool> EnableLogging
{
get { return GetOptionalTextElement("enableLogging", true); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["enableLogging"],
//set the default
true);
}
}
[ConfigurationProperty("enableAsyncLogging")]
internal InnerTextConfigurationElement<bool> EnableAsyncLogging
{
get { return GetOptionalTextElement("enableAsyncLogging", true); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["enableAsyncLogging"],
//set the default
true);
}
}
[ConfigurationProperty("cleaningMiliseconds")]
internal InnerTextConfigurationElement<int> CleaningMiliseconds
{
get { return GetOptionalTextElement("cleaningMiliseconds", -1); }
get
{
return new OptionalInnerTextConfigurationElement<int>(
(InnerTextConfigurationElement<int>)this["cleaningMiliseconds"],
//set the default
-1);
}
}
[ConfigurationProperty("maxLogAge")]
internal InnerTextConfigurationElement<int> MaxLogAge
{
get { return GetOptionalTextElement("maxLogAge", -1); }
get
{
return new OptionalInnerTextConfigurationElement<int>(
(InnerTextConfigurationElement<int>)this["maxLogAge"],
//set the default
-1);
}
}
[ConfigurationCollection(typeof(DisabledLogTypesCollection), AddItemName = "logTypeAlias")]
@@ -2,7 +2,7 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class NotificationsElement : UmbracoConfigurationElement
internal class NotificationsElement : ConfigurationElement
{
[ConfigurationProperty("email")]
internal InnerTextConfigurationElement<string> NotificationEmailAddress
@@ -13,7 +13,13 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
[ConfigurationProperty("disableHtmlEmail")]
internal InnerTextConfigurationElement<bool> DisableHtmlEmail
{
get { return GetOptionalTextElement("disableHtmlEmail", false); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>) this["disableHtmlEmail"],
//set the default
false);
}
}
}
@@ -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; }
}
}
}
@@ -5,18 +5,30 @@ using System.Collections.Generic;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class RequestHandlerElement : UmbracoConfigurationElement, IRequestHandlerSection
internal class RequestHandlerElement : ConfigurationElement, IRequestHandlerSection
{
[ConfigurationProperty("useDomainPrefixes")]
public InnerTextConfigurationElement<bool> UseDomainPrefixes
{
get { return GetOptionalTextElement("useDomainPrefixes", false); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["useDomainPrefixes"],
//set the default
false);
}
}
[ConfigurationProperty("addTrailingSlash")]
public InnerTextConfigurationElement<bool> AddTrailingSlash
{
get { return GetOptionalTextElement("addTrailingSlash", true); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["addTrailingSlash"],
//set the default
true);
}
}
private UrlReplacingElement _defaultUrlReplacing;
@@ -2,36 +2,66 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class SecurityElement : UmbracoConfigurationElement, ISecuritySection
internal class SecurityElement : ConfigurationElement, ISecuritySection
{
[ConfigurationProperty("keepUserLoggedIn")]
internal InnerTextConfigurationElement<bool> KeepUserLoggedIn
{
get { return GetOptionalTextElement("keepUserLoggedIn", true); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["keepUserLoggedIn"],
//set the default
true);
}
}
[ConfigurationProperty("hideDisabledUsersInBackoffice")]
internal InnerTextConfigurationElement<bool> HideDisabledUsersInBackoffice
{
get { return GetOptionalTextElement("hideDisabledUsersInBackoffice", false); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["hideDisabledUsersInBackoffice"],
//set the default
false);
}
}
[ConfigurationProperty("allowPasswordReset")]
internal InnerTextConfigurationElement<bool> AllowPasswordReset
{
get { return GetOptionalTextElement("allowPasswordReset", true); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["allowPasswordReset"],
//set the default
true);
}
}
[ConfigurationProperty("authCookieName")]
internal InnerTextConfigurationElement<string> AuthCookieName
{
get { return GetOptionalTextElement("authCookieName", Constants.Web.AuthCookieName); }
get
{
return new OptionalInnerTextConfigurationElement<string>(
(InnerTextConfigurationElement<string>)this["authCookieName"],
//set the default
Constants.Web.AuthCookieName);
}
}
[ConfigurationProperty("authCookieDomain")]
internal InnerTextConfigurationElement<string> AuthCookieDomain
{
get { return GetOptionalTextElement<string>("authCookieDomain", null); }
get
{
return new OptionalInnerTextConfigurationElement<string>(
(InnerTextConfigurationElement<string>)this["authCookieDomain"],
//set the default
null);
}
}
bool ISecuritySection.KeepUserLoggedIn
@@ -3,31 +3,55 @@ using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class TemplatesElement : UmbracoConfigurationElement, ITemplatesSection
internal class TemplatesElement : ConfigurationElement, ITemplatesSection
{
[ConfigurationProperty("useAspNetMasterPages")]
internal InnerTextConfigurationElement<bool> UseAspNetMasterPages
{
get { return GetOptionalTextElement("useAspNetMasterPages", true); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["useAspNetMasterPages"],
//set the default
true);
}
}
[ConfigurationProperty("enableSkinSupport")]
internal InnerTextConfigurationElement<bool> EnableSkinSupport
{
get { return GetOptionalTextElement("enableSkinSupport", true); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["enableSkinSupport"],
//set the default
true);
}
}
[ConfigurationProperty("defaultRenderingEngine", IsRequired = true)]
internal InnerTextConfigurationElement<RenderingEngine> DefaultRenderingEngine
{
get { return GetOptionalTextElement("defaultRenderingEngine", RenderingEngine.Mvc); }
get
{
return new OptionalInnerTextConfigurationElement<RenderingEngine>(
(InnerTextConfigurationElement<RenderingEngine>)this["defaultRenderingEngine"],
//set the default
RenderingEngine.Mvc);
}
}
[Obsolete("This has no affect and will be removed in future versions")]
[ConfigurationProperty("enableTemplateFolders")]
internal InnerTextConfigurationElement<bool> EnableTemplateFolders
{
get { return GetOptionalTextElement("enableTemplateFolders", false); }
get
{
return new OptionalInnerTextConfigurationElement<bool>(
(InnerTextConfigurationElement<bool>)this["enableTemplateFolders"],
//set the default
false);
}
}
bool ITemplatesSection.UseAspNetMasterPages
@@ -1,36 +0,0 @@
using System.Collections.Concurrent;
using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
/// <summary>
/// Base class with shared helper methods
/// </summary>
internal class UmbracoConfigurationElement : ConfigurationElement
{
/// <summary>
/// Used so the RawElement types are not re-created every time they are accessed
/// </summary>
private readonly ConcurrentDictionary<string, RawXmlConfigurationElement> _rawElements = new ConcurrentDictionary<string, RawXmlConfigurationElement>();
protected OptionalInnerTextConfigurationElement<T> GetOptionalTextElement<T>(string name, T defaultVal)
{
return (OptionalInnerTextConfigurationElement<T>) _rawElements.GetOrAdd(
name,
s => new OptionalInnerTextConfigurationElement<T>(
(InnerTextConfigurationElement<T>) this[s],
//set the default
defaultVal));
}
protected OptionalCommaDelimitedConfigurationElement GetOptionalDelimitedElement(string name, string[] defaultVal)
{
return (OptionalCommaDelimitedConfigurationElement) _rawElements.GetOrAdd(
name,
s => new OptionalCommaDelimitedConfigurationElement(
(CommaDelimitedConfigurationElement) this[name],
//set the default
defaultVal));
}
}
}
@@ -27,12 +27,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
get { return (bool) base["disableFindContentByIdPath"]; }
}
[ConfigurationProperty("disableRedirectUrlTracking", DefaultValue = "false")]
public bool DisableRedirectUrlTracking
{
get { return (bool) base["disableRedirectUrlTracking"]; }
}
[ConfigurationProperty("urlProviderMode", DefaultValue = "AutoLegacy")]
public string UrlProviderMode
{
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.5.13");
private static readonly Version Version = new Version("7.5.0");
/// <summary>
/// Gets the current version of Umbraco.
@@ -32,12 +32,7 @@ namespace Umbraco.Core.Configuration
public static SemVersion GetSemanticVersion()
{
return new SemVersion(
Current.Major,
Current.Minor,
Current.Build,
CurrentComment.IsNullOrWhiteSpace() ? null : CurrentComment,
Current.Revision > 0 ? Current.Revision.ToInvariantString() : null);
return Current.GetSemanticVersion();
}
}
}
@@ -73,11 +73,6 @@
/// </summary>
public const string DataTypes = "dataTypes";
/// <summary>
/// alias for the packages tree
/// </summary>
public const string Packages = "packager";
/// <summary>
/// alias for the dictionary tree.
/// </summary>
@@ -122,11 +122,6 @@ namespace Umbraco.Core
/// MediaType alias for an image.
/// </summary>
public const string Image = "Image";
/// <summary>
/// MediaType alias indicating allowing auto-selection.
/// </summary>
public const string AutoSelect = "umbracoAutoSelect";
}
/// <summary>
+7 -20
View File
@@ -1,23 +1,15 @@
namespace Umbraco.Core
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Umbraco.Core
{
public static partial class Constants
{
public static class Examine
{
/// <summary>
/// The alias of the internal member indexer
/// </summary>
public const string InternalMemberIndexer = "InternalMemberIndexer";
/// <summary>
/// The alias of the internal content indexer
/// </summary>
public const string InternalIndexer = "InternalIndexer";
/// <summary>
/// The alias of the external content indexer
/// </summary>
public const string ExternalIndexer = "ExternalIndexer";
/// <summary>
/// The alias of the internal member searcher
/// </summary>
@@ -27,11 +19,6 @@
/// The alias of the internal content searcher
/// </summary>
public const string InternalSearcher = "InternalSearcher";
/// <summary>
/// The alias of the external content searcher
/// </summary>
public const string ExternalSearcher = "ExternalSearcher";
}
}
}
@@ -69,11 +69,6 @@ namespace Umbraco.Core
/// </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 Type object.
/// </summary>
+23 -30
View File
@@ -1,40 +1,33 @@
namespace Umbraco.Core
{
public static partial class Constants
{
/// <summary>
/// Defines the identifiers for Umbraco system nodes.
/// </summary>
public static class System
{
/// <summary>
/// The integer identifier for global system root node.
/// </summary>
public const int Root = -1;
public static partial class Constants
{
/// <summary>
/// Defines the identifiers for Umbraco system nodes.
/// </summary>
public static class System
{
/// <summary>
/// The integer identifier for global system root node.
/// </summary>
public const int Root = -1;
/// <summary>
/// The integer identifier for content's recycle bin.
/// </summary>
public const int RecycleBinContent = -20;
/// <summary>
/// The integer identifier for content's recycle bin.
/// </summary>
public const int RecycleBinContent = -20;
/// <summary>
/// The integer identifier for media's recycle bin.
/// </summary>
public const int RecycleBinMedia = -21;
/// <summary>
/// The integer identifier for media's recycle bin.
/// </summary>
public const int RecycleBinMedia = -21;
public const int DefaultContentListViewDataTypeId = -95;
public const int DefaultContentListViewDataTypeId = -95;
public const int DefaultMediaListViewDataTypeId = -96;
public const int DefaultMembersListViewDataTypeId = -97;
// identifiers for lock objects
public const int ServersLock = -331;
}
public static class DatabaseProviders
{
public const string SqlCe = "System.Data.SqlServerCe.4.0";
public const string SqlServer = "System.Data.SqlClient";
public const string MySql = "MySql.Data.MySqlClient";
}
}
public const int ServersLock = -331;
}
}
}
+18 -18
View File
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Threading;
@@ -31,13 +30,12 @@ using Umbraco.Core.Manifest;
using Umbraco.Core.Services;
using Umbraco.Core.Sync;
using Umbraco.Core.Strings;
using IntegerValidator = Umbraco.Core.PropertyEditors.IntegerValidator;
using MigrationsVersionFourNineZero = Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionFourNineZero;
namespace Umbraco.Core
{
/// <summary>
/// A bootstrapper for the Umbraco application which initializes all objects for the Core of the application
/// A bootstrapper for the Umbraco application which initializes all objects for the Core of the application
/// </summary>
/// <remarks>
/// This does not provide any startup functionality relating to web objects
@@ -193,14 +191,14 @@ namespace Umbraco.Core
protected virtual CacheHelper CreateApplicationCache()
{
var cacheHelper = new CacheHelper(
//we need to have the dep clone runtime cache provider to ensure
//we need to have the dep clone runtime cache provider to ensure
//all entities are cached properly (cloned in and cloned out)
new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()),
new StaticCacheProvider(),
//we have no request based cache when not running in web-based context
new NullCacheProvider(),
new IsolatedRuntimeCache(type =>
//we need to have the dep clone runtime cache provider to ensure
//we need to have the dep clone runtime cache provider to ensure
//all entities are cached properly (cloned in and cloned out)
new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())));
@@ -253,18 +251,18 @@ namespace Umbraco.Core
}
/// <summary>
/// Special method to initialize the ApplicationEventsResolver and any modifications required for it such
/// Special method to initialize the ApplicationEventsResolver and any modifications required for it such
/// as adding custom types to the resolver.
/// </summary>
protected virtual void InitializeApplicationEventsResolver()
{
//find and initialize the application startup handlers, we need to initialize this resolver here because
//it is a special resolver where they need to be instantiated first before any other resolvers in order to bind to
//it is a special resolver where they need to be instantiated first before any other resolvers in order to bind to
//events and to call their events during bootup.
//ApplicationStartupHandler.RegisterHandlers();
//... and set the special flag to let us resolve before frozen resolution
ApplicationEventsResolver.Current = new ApplicationEventsResolver(
ServiceProvider,
ServiceProvider,
ProfilingLogger.Logger,
PluginManager.ResolveApplicationStartupHandlers())
{
@@ -284,7 +282,7 @@ namespace Umbraco.Core
}
/// <summary>
/// Fires after initialization and calls the callback to allow for customizations to occur &
/// Fires after initialization and calls the callback to allow for customizations to occur &
/// Ensure that the OnApplicationStarting methods of the IApplicationEvents are called
/// </summary>
/// <param name="afterStartup"></param>
@@ -336,7 +334,7 @@ namespace Umbraco.Core
{
if (_isComplete)
throw new InvalidOperationException("The boot manager has already been completed");
FreezeResolution();
//Here we need to make sure the db can be connected to
@@ -368,7 +366,7 @@ namespace Umbraco.Core
ProfilingLogger.Logger.Error<CoreBootManager>("An error occurred running OnApplicationStarted for handler " + x.GetType(), ex);
throw;
}
});
});
}
//Now, startup all of our legacy startup handler
@@ -415,7 +413,7 @@ namespace Umbraco.Core
if (currentTry == 5)
{
throw new UmbracoStartupFailedException("Umbraco cannot start. A connection string is configured but Umbraco cannot connect to the database.");
throw new UmbracoStartupFailedException("Umbraco cannot start. A connection string is configured but the Umbraco cannot connect to the database.");
}
}
@@ -457,10 +455,6 @@ namespace Umbraco.Core
{
ServerRegistrarResolver.Current = new ServerRegistrarResolver(new ConfigServerRegistrar());
}
else if ("true".InvariantEquals(ConfigurationManager.AppSettings["umbracoDisableElectionForSingleServer"]))
{
ServerRegistrarResolver.Current = new ServerRegistrarResolver(new SingleServerRegistrar());
}
else
{
ServerRegistrarResolver.Current = new ServerRegistrarResolver(
@@ -468,6 +462,7 @@ namespace Umbraco.Core
new Lazy<IServerRegistrationService>(() => ApplicationContext.Services.ServerRegistrationService),
new DatabaseServerRegistrarOptions()));
}
//by default we'll use the database server messenger with default options (no callbacks),
// this will be overridden in the web startup
@@ -478,7 +473,7 @@ namespace Umbraco.Core
ServiceProvider, ProfilingLogger.Logger,
() => PluginManager.ResolveAssignedMapperTypes());
//RepositoryResolver.Current = new RepositoryResolver(
// new RepositoryFactory(ApplicationCache));
@@ -505,7 +500,12 @@ namespace Umbraco.Core
//the database migration objects
MigrationResolver.Current = new MigrationResolver(
ProfilingLogger.Logger,
() => PluginManager.ResolveTypes<IMigration>());
() => PluginManager.ResolveTypes<IMigration>())
{
//This needs to be resolved before it's frozen because we need to find migrations to determine
// if Umbraco IsConfigured
CanResolveBeforeFrozen = true
};
// todo: remove once we drop IPropertyEditorValueConverter support.
PropertyEditorValueConvertersResolver.Current = new PropertyEditorValueConvertersResolver(
+84 -50
View File
@@ -34,12 +34,6 @@ namespace Umbraco.Core
private string _connectionString;
private string _providerName;
private DatabaseSchemaResult _result;
private DateTime? _connectionLastChecked = null;
/// <summary>
/// The number of minutes to throttle the checks to CanConnect
/// </summary>
private const int ConnectionCheckMinutes = 1;
[Obsolete("Use the constructor specifying all dependencies instead")]
public DatabaseContext(IDatabaseFactory factory)
@@ -116,28 +110,13 @@ namespace Umbraco.Core
{
get
{
if (IsDatabaseConfigured == false)
return false;
//Don't check again if the timeout period hasn't elapsed
//this ensures we don't keep checking the connection too many times in a row like during startup.
//Do check if the _connectionLastChecked is null which means we're just initializing or it could
//not connect last time it was checked.
if ((_connectionLastChecked.HasValue && (DateTime.Now - _connectionLastChecked.Value).TotalMinutes > ConnectionCheckMinutes)
|| _connectionLastChecked.HasValue == false)
{
var canConnect = DbConnectionExtensions.IsConnectionAvailable(ConnectionString, DatabaseProvider);
LogHelper.Info<DatabaseContext>("CanConnect = " + canConnect);
_connectionLastChecked = canConnect == false ? null : (DateTime?) DateTime.Now;
return canConnect;
}
return _connectionLastChecked.HasValue;
if (IsDatabaseConfigured == false) return false;
var canConnect = DbConnectionExtensions.IsConnectionAvailable(ConnectionString, DatabaseProvider);
LogHelper.Info<DatabaseContext>("CanConnect = " + canConnect);
return canConnect;
}
}
/// <summary>
/// Gets the configured umbraco db connection string.
/// </summary>
@@ -156,7 +135,7 @@ namespace Umbraco.Core
if (string.IsNullOrEmpty(_providerName) == false)
return _providerName;
_providerName = Constants.DatabaseProviders.SqlServer;
_providerName = "System.Data.SqlClient";
if (ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName] != null)
{
if (string.IsNullOrEmpty(ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ProviderName) == false)
@@ -195,7 +174,7 @@ namespace Umbraco.Core
/// </summary>
public void ConfigureEmbeddedDatabaseConnection()
{
const string providerName = Constants.DatabaseProviders.SqlCe;
const string providerName = "System.Data.SqlServerCe.4.0";
var connectionString = GetEmbeddedDatabaseConnectionString();
SaveConnectionString(connectionString, providerName);
@@ -203,10 +182,15 @@ namespace Umbraco.Core
var path = Path.Combine(GlobalSettings.FullpathToRoot, "App_Data", "Umbraco.sdf");
if (File.Exists(path) == false)
{
using (var engine = new SqlCeEngine(connectionString))
{
engine.CreateDatabase();
}
var engine = new SqlCeEngine(connectionString);
engine.CreateDatabase();
// SD: Pretty sure this should be in a using clause but i don't want to cause unknown side-effects here
// since it's been like this for quite some time
//using (var engine = new SqlCeEngine(connectionString))
//{
// engine.CreateDatabase();
//}
}
Initialize(providerName);
@@ -228,10 +212,10 @@ namespace Umbraco.Core
{
var provider = DbConnectionExtensions.DetectProviderFromConnectionString(connectionString);
var databaseProvider = provider.ToString();
var providerName = Constants.DatabaseProviders.SqlServer;
var providerName = "System.Data.SqlClient";
if (databaseProvider.ToLower().Contains("mysql"))
{
providerName = Constants.DatabaseProviders.MySql;
providerName = "MySql.Data.MySqlClient";
}
SaveConnectionString(connectionString, providerName);
Initialize(string.Empty);
@@ -256,10 +240,10 @@ namespace Umbraco.Core
public string GetDatabaseConnectionString(string server, string databaseName, string user, string password, string databaseProvider, out string providerName)
{
providerName = Constants.DatabaseProviders.SqlServer;
providerName = "System.Data.SqlClient";
if (databaseProvider.ToLower().Contains("mysql"))
{
providerName = Constants.DatabaseProviders.MySql;
providerName = "MySql.Data.MySqlClient";
return string.Format("Server={0}; Database={1};Uid={2};Pwd={3}", server, databaseName, user, password);
}
if (databaseProvider.ToLower().Contains("azure"))
@@ -276,7 +260,7 @@ namespace Umbraco.Core
/// <param name="databaseName">Name of the database</param>
public void ConfigureIntegratedSecurityDatabaseConnection(string server, string databaseName)
{
const string providerName = Constants.DatabaseProviders.SqlServer;
const string providerName = "System.Data.SqlClient";
var connectionString = GetIntegratedSecurityDatabaseConnectionString(server, databaseName);
SaveConnectionString(connectionString, providerName);
Initialize(providerName);
@@ -389,7 +373,7 @@ namespace Umbraco.Core
var databaseSettings = ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName];
if (databaseSettings != null && string.IsNullOrWhiteSpace(databaseSettings.ConnectionString) == false && string.IsNullOrWhiteSpace(databaseSettings.ProviderName) == false)
{
var providerName = Constants.DatabaseProviders.SqlServer;
var providerName = "System.Data.SqlClient";
string connString = null;
if (!string.IsNullOrEmpty(ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ProviderName))
{
@@ -397,7 +381,8 @@ namespace Umbraco.Core
connString = ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ConnectionString;
}
Initialize(providerName, connString);
DetermineSqlServerVersion();
}
else if (ConfigurationManager.AppSettings.ContainsKey(GlobalSettings.UmbracoConnectionName) && string.IsNullOrEmpty(ConfigurationManager.AppSettings[GlobalSettings.UmbracoConnectionName]) == false)
{
@@ -410,8 +395,8 @@ namespace Umbraco.Core
else if (legacyConnString.ToLowerInvariant().Contains("tcp:"))
{
//Must be sql azure
SaveConnectionString(legacyConnString, Constants.DatabaseProviders.SqlServer);
Initialize(Constants.DatabaseProviders.SqlServer);
SaveConnectionString(legacyConnString, "System.Data.SqlClient");
Initialize("System.Data.SqlClient");
}
else if (legacyConnString.ToLowerInvariant().Contains("datalayer=mysql"))
{
@@ -422,19 +407,20 @@ namespace Umbraco.Core
foreach (var variable in legacyConnString.Split(';').Where(x => x.ToLowerInvariant().StartsWith("datalayer") == false))
connectionStringWithoutDatalayer = string.Format("{0}{1};", connectionStringWithoutDatalayer, variable);
SaveConnectionString(connectionStringWithoutDatalayer, Constants.DatabaseProviders.MySql);
Initialize(Constants.DatabaseProviders.MySql);
SaveConnectionString(connectionStringWithoutDatalayer, "MySql.Data.MySqlClient");
Initialize("MySql.Data.MySqlClient");
}
else
{
//Must be sql
SaveConnectionString(legacyConnString, Constants.DatabaseProviders.SqlServer);
Initialize(Constants.DatabaseProviders.SqlServer);
SaveConnectionString(legacyConnString, "System.Data.SqlClient");
Initialize("System.Data.SqlClient");
}
//Remove the legacy connection string, so we don't end up in a loop if something goes wrong.
GlobalSettings.RemoveSetting(GlobalSettings.UmbracoConnectionName);
DetermineSqlServerVersion();
}
else
{
@@ -479,6 +465,49 @@ namespace Umbraco.Core
Initialize(providerName);
}
/// <summary>
/// Set the lazy resolution of determining the SQL server version if that is the db type we're using
/// </summary>
private void DetermineSqlServerVersion()
{
var sqlServerSyntax = SqlSyntax as SqlServerSyntaxProvider;
if (sqlServerSyntax != null)
{
//this will not execute now, it is lazy so will only execute when we need to actually know
// the sql server version.
sqlServerSyntax.VersionName = new Lazy<SqlServerVersionName>(() =>
{
try
{
var database = this._factory.CreateDatabase();
var version = database.ExecuteScalar<string>("SELECT SERVERPROPERTY('productversion')");
var firstPart = version.Split('.')[0];
switch (firstPart)
{
case "11":
return SqlServerVersionName.V2012;
case "10":
return SqlServerVersionName.V2008;
case "9":
return SqlServerVersionName.V2005;
case "8":
return SqlServerVersionName.V2000;
case "7":
return SqlServerVersionName.V7;
default:
return SqlServerVersionName.Other;
}
}
catch (Exception)
{
return SqlServerVersionName.Invalid;
}
});
}
}
internal DatabaseSchemaResult ValidateDatabaseSchema()
{
if (_configured == false || (string.IsNullOrEmpty(_connectionString) || string.IsNullOrEmpty(ProviderName)))
@@ -488,7 +517,7 @@ namespace Umbraco.Core
{
if (SystemUtilities.GetCurrentTrustLevel() != AspNetHostingPermissionLevel.Unrestricted
&& ProviderName == Constants.DatabaseProviders.MySql)
&& ProviderName == "MySql.Data.MySqlClient")
{
throw new InvalidOperationException("Cannot use MySql in Medium Trust configuration");
}
@@ -596,8 +625,13 @@ namespace Umbraco.Core
var installedSchemaVersion = new SemVersion(schemaResult.DetermineInstalledVersion());
var installedMigrationVersion = schemaResult.DetermineInstalledVersionByMigrations(migrationEntryService);
var installedMigrationVersion = new SemVersion(0);
//we cannot check the migrations table if it doesn't exist, this will occur when upgrading to 7.3
if (schemaResult.ValidTables.Any(x => x.InvariantEquals("umbracoMigration")))
{
installedMigrationVersion = schemaResult.DetermineInstalledVersionByMigrations(migrationEntryService);
}
var targetVersion = UmbracoVersion.Current;
//In some cases - like upgrading from 7.2.6 -> 7.3, there will be no migration information in the database and therefore it will
@@ -697,7 +731,7 @@ namespace Umbraco.Core
private Attempt<Result> CheckReadyForInstall()
{
if (SystemUtilities.GetCurrentTrustLevel() != AspNetHostingPermissionLevel.Unrestricted
&& ProviderName == Constants.DatabaseProviders.MySql)
&& ProviderName == "MySql.Data.MySqlClient")
{
throw new InvalidOperationException("Cannot use MySql in Medium Trust configuration");
}
@@ -746,7 +780,7 @@ namespace Umbraco.Core
{
var dbIsSqlCe = false;
if (databaseSettings != null && databaseSettings.ProviderName != null)
dbIsSqlCe = databaseSettings.ProviderName == Constants.DatabaseProviders.SqlCe;
dbIsSqlCe = databaseSettings.ProviderName == "System.Data.SqlServerCe.4.0";
var sqlCeDatabaseExists = false;
if (dbIsSqlCe)
{
-23
View File
@@ -1,23 +0,0 @@
namespace Umbraco.Core
{
/// <summary>
/// Provides extension methods for System.Decimal.
/// </summary>
/// <remarks>See System.Decimal on MSDN and also
/// http://stackoverflow.com/questions/4298719/parse-decimal-and-filter-extra-0-on-the-right/4298787#4298787.
/// </remarks>
public static class DecimalExtensions
{
/// <summary>
/// Gets the normalized value.
/// </summary>
/// <param name="value">The value to normalize.</param>
/// <returns>The normalized value.</returns>
/// <remarks>Normalizing changes the scaling factor and removes trailing zeroes,
/// so 1.2500m comes out as 1.25m.</remarks>
public static decimal Normalize(this decimal value)
{
return value / 1.000000000000000000000000000000000m;
}
}
}
-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;
}
}
}
}
@@ -128,14 +128,8 @@ namespace Umbraco.Core.Events
get { return TargetSemVersion.GetVersion(); }
}
/// <summary>
/// Gets the origin version of the migration, i.e. the one that is currently installed.
/// </summary>
public SemVersion ConfiguredSemVersion { get; private set; }
/// <summary>
/// Gets the target version of the migration.
/// </summary>
public SemVersion TargetSemVersion { get; private set; }
public string ProductName { get; private set; }
@@ -1,12 +0,0 @@
using System;
namespace Umbraco.Core.Exceptions
{
internal class ConnectionException : Exception
{
public ConnectionException(string message, Exception innerException) : base(message, innerException)
{
}
}
}
+5 -1
View File
@@ -41,7 +41,11 @@ namespace Umbraco.Core.IO
{
using (var file = fs.OpenFile(path))
{
return file.Length;
using (var sr = new StreamReader(file))
{
var str = sr.ReadToEnd();
return str.Length;
}
}
}
+3 -108
View File
@@ -7,144 +7,39 @@ namespace Umbraco.Core.IO
//TODO: There is no way to create a directory here without creating a file in a directory and then deleting it
//TODO: Should probably implement a rename?
/// <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);
}
}
+1 -1
View File
@@ -122,7 +122,7 @@ namespace Umbraco.Core.IO
Directory.CreateDirectory(Path.GetDirectoryName(fullPath)); // ensure it exists
if (stream.CanSeek)
stream.Seek(0, SeekOrigin.Begin);
stream.Seek(0, 0);
using (var destination = (Stream)File.Create(fullPath))
stream.CopyTo(destination);
+1 -10
View File
@@ -69,16 +69,7 @@ namespace Umbraco.Core.IO
}
}
public static string AppCode
{
get
{
//NOTE: this is not configurable and shouldn't need to be
return "~/App_Code";
}
}
public static string AppPlugins
public static string AppPlugins
{
get
{
+4 -18
View File
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.IO;
using System.Linq;
@@ -73,28 +72,15 @@ namespace Umbraco.Core.IO
{
get
{
switch (GlobalSettings.ContentCacheXmlStorageLocation)
{
case ContentXmlStorage.AspNetTemp:
return Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData\umbraco.config");
case ContentXmlStorage.EnvironmentTemp:
var appDomainHash = HttpRuntime.AppDomainAppId.ToSHA1();
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoXml",
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
// utilizing an old path
appDomainHash);
return Path.Combine(cachePath, "umbraco.config");
case ContentXmlStorage.Default:
return IOHelper.ReturnPath("umbracoContentXML", "~/App_Data/umbraco.config");
default:
throw new ArgumentOutOfRangeException();
if (GlobalSettings.ContentCacheXmlStoredInCodeGen && SystemUtilities.GetCurrentTrustLevel() == AspNetHostingPermissionLevel.Unrestricted)
{
return Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData\umbraco.config");
}
return IOHelper.ReturnPath("umbracoContentXML", "~/App_Data/umbraco.config");
}
}
[Obsolete("Use GlobalSettings.ContentCacheXmlStoredInCodeGen instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
internal static bool ContentCacheXmlStoredInCodeGen
{
get { return GlobalSettings.ContentCacheXmlStoredInCodeGen; }
+1 -1
View File
@@ -86,7 +86,7 @@ namespace Umbraco.Core.IO
private void Initialize()
{
Filename = _fs.GetFileName(Path);
Extension = string.IsNullOrEmpty(_fs.GetExtension(Path)) == false
Extension = _fs.GetExtension(Path) != null
? _fs.GetExtension(Path).Substring(1).ToLowerInvariant()
: "";
Url = _fs.GetUrl(Path);
@@ -1,21 +1,20 @@
using System;
using log4net.Appender;
using log4net.Core;
using log4net.Util;
using System;
using System.Runtime.Remoting.Messaging;
namespace Umbraco.Core.Logging
{
/// <summary>
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
/// </summary>
/// <remarks>
/// Based on https://github.com/cjbhaines/Log4Net.Async
/// </remarks>
public abstract class AsyncForwardingAppenderBase : ForwardingAppender
{
#region Private Members
private const FixFlags DefaultFixFlags = FixFlags.Partial;
private FixFlags fixFlags = DefaultFixFlags;
private LoggingEventHelper loggingEventHelper;
private FixFlags _fixFlags = DefaultFixFlags;
private LoggingEventHelper _loggingEventHelper;
#endregion Private Members
@@ -23,25 +22,10 @@ namespace Umbraco.Core.Logging
public FixFlags Fix
{
get { return fixFlags; }
get { return _fixFlags; }
set { SetFixFlags(value); }
}
/// <summary>
/// Returns HttpContext.Current
/// </summary>
protected internal object HttpContext
{
get
{
return CallContext.HostContext;
}
set
{
CallContext.HostContext = value;
}
}
/// <summary>
/// The logger name that will be used for logging internal errors.
/// </summary>
@@ -54,7 +38,7 @@ namespace Umbraco.Core.Logging
public override void ActivateOptions()
{
base.ActivateOptions();
loggingEventHelper = new LoggingEventHelper(InternalLoggerName, DefaultFixFlags);
_loggingEventHelper = new LoggingEventHelper(InternalLoggerName, DefaultFixFlags);
InitializeAppenders();
}
@@ -68,10 +52,10 @@ namespace Umbraco.Core.Logging
private void SetFixFlags(FixFlags newFixFlags)
{
if (newFixFlags != fixFlags)
if (newFixFlags != _fixFlags)
{
loggingEventHelper.Fix = newFixFlags;
fixFlags = newFixFlags;
_loggingEventHelper.Fix = newFixFlags;
_fixFlags = newFixFlags;
InitializeAppenders();
}
}
@@ -100,7 +84,7 @@ namespace Umbraco.Core.Logging
protected void ForwardInternalError(string message, Exception exception, Type thisType)
{
LogLog.Error(thisType, message, exception);
var loggingEvent = loggingEventHelper.CreateLoggingEvent(Level.Error, message, exception);
var loggingEvent = _loggingEventHelper.CreateLoggingEvent(Level.Error, message, exception);
ForwardLoggingEvent(loggingEvent, thisType);
}
@@ -1,7 +1,6 @@
using log4net.Core;
using log4net.Util;
using System;
using System.ComponentModel;
using System.Runtime.Remoting.Messaging;
using System.Security.Principal;
using System.Threading;
@@ -13,11 +12,7 @@ namespace Umbraco.Core.Logging
/// <summary>
/// Based on https://github.com/cjbhaines/Log4Net.Async
/// which is based on code by Chris Haines http://cjbhaines.wordpress.com/2012/02/13/asynchronous-log4net-appenders/
/// 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")]
[EditorBrowsable(EditorBrowsableState.Never)]
public class AsynchronousRollingFileAppender : RollingFileAppender
{
private RingBuffer<LoggingEvent> pendingAppends;
@@ -203,4 +198,79 @@ namespace Umbraco.Core.Logging
}
}
internal interface IQueue<T>
{
void Enqueue(T item);
bool TryDequeue(out T ret);
}
internal class RingBuffer<T> : IQueue<T>
{
private readonly object lockObject = new object();
private readonly T[] buffer;
private readonly int size;
private int readIndex = 0;
private int writeIndex = 0;
private bool bufferFull = false;
public int Size { get { return size; } }
public event Action<object, EventArgs> BufferOverflow;
public RingBuffer(int size)
{
this.size = size;
buffer = new T[size];
}
public void Enqueue(T item)
{
var bufferWasFull = false;
lock (lockObject)
{
buffer[writeIndex] = item;
writeIndex = (++writeIndex) % size;
if (bufferFull)
{
bufferWasFull = true;
readIndex = writeIndex;
}
else if (writeIndex == readIndex)
{
bufferFull = true;
}
}
if (bufferWasFull)
{
if (BufferOverflow != null)
{
BufferOverflow(this, EventArgs.Empty);
}
}
}
public bool TryDequeue(out T ret)
{
if (readIndex == writeIndex && !bufferFull)
{
ret = default(T);
return false;
}
lock (lockObject)
{
if (readIndex == writeIndex && !bufferFull)
{
ret = default(T);
return false;
}
ret = buffer[readIndex];
buffer[readIndex] = default(T);
readIndex = (++readIndex) % size;
bufferFull = false;
return true;
}
}
}
}
-12
View File
@@ -1,12 +0,0 @@
namespace Umbraco.Core.Logging
{
/// <summary>
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
/// </summary>
/// <typeparam name="T"></typeparam>
internal interface IQueue<T>
{
void Enqueue(T item);
bool TryDequeue(out T ret);
}
}
@@ -1,46 +0,0 @@
using System;
using System.Runtime.CompilerServices;
using ImageProcessor.Common.Exceptions;
namespace Umbraco.Core.Logging
{
/// <summary>
/// A logger for explicitly logging ImageProcessor exceptions.
/// <remarks>
/// Creating this logger is enough for ImageProcessor to find and replace its in-built debug logger
/// without any additional configuration required. This class currently has to be public in order
/// to do so.
/// </remarks>
/// </summary>
public sealed class ImageProcessorLogger : ImageProcessor.Common.Exceptions.ILogger
{
/// <summary>
/// Logs the specified message as an error.
/// </summary>
/// <typeparam name="T">The type calling the logger.</typeparam>
/// <param name="text">The message to log.</param>
/// <param name="callerName">The property or method name calling the log.</param>
/// <param name="lineNumber">The line number where the method is called.</param>
public void Log<T>(string text, [CallerMemberName] string callerName = null, [CallerLineNumber] int lineNumber = 0)
{
// Using LogHelper since the ImageProcessor logger expects a parameterless constructor.
var message = string.Format("{0} {1} : {2}", callerName, lineNumber, text);
LogHelper.Error<T>(string.Empty, new ImageProcessingException(message));
}
/// <summary>
/// Logs the specified message as an error.
/// </summary>
/// <param name="type">The type calling the logger.</param>
/// <param name="text">The message to log.</param>
/// <param name="callerName">The property or method name calling the log.</param>
/// <param name="lineNumber">The line number where the method is called.</param>
public void Log(Type type, string text, [CallerMemberName] string callerName = null, [CallerLineNumber] int lineNumber = 0)
{
// Using LogHelper since the ImageProcessor logger expects a parameterless constructor.
var message = string.Format("{0} {1} : {2}", callerName, lineNumber, text);
LogHelper.Error(type, string.Empty, new ImageProcessingException(message));
}
}
}
+8 -65
View File
@@ -2,13 +2,10 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Web;
using log4net;
using log4net.Config;
using Umbraco.Core.Configuration;
using Umbraco.Core.Diagnostics;
namespace Umbraco.Core.Logging
{
@@ -59,72 +56,18 @@ 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);
var logger = LogManager.GetLogger(callingType);
if (logger != null)
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;
if (abort == null) return false;
if (abort.ExceptionState == null) return false;
var stateType = abort.ExceptionState.GetType();
if (stateType.FullName != "System.Web.HttpApplication+CancelModuleException") return false;
var timeoutField = stateType.GetField("_timeout", BindingFlags.Instance | BindingFlags.NonPublic);
if (timeoutField == null) return false;
return (bool) timeoutField.GetValue(abort.ExceptionState);
}
public void Warn(Type callingType, string message, params Func<object>[] formatItems)
public void Warn(Type callingType, string message, params Func<object>[] formatItems)
{
var logger = LogManager.GetLogger(callingType);
if (logger == null || logger.IsWarnEnabled == false) return;
@@ -139,7 +82,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 +99,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>
@@ -3,18 +3,15 @@ using log4net.Core;
namespace Umbraco.Core.Logging
{
/// <remarks>
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
/// Based on https://github.com/cjbhaines/Log4Net.Async
/// </remarks>
internal sealed class LoggingEventContext
internal class LoggingEventContext
{
public LoggingEventContext(LoggingEvent loggingEvent, object httpContext)
public LoggingEventContext(LoggingEvent loggingEvent)
{
LoggingEvent = loggingEvent;
HttpContext = httpContext;
}
public LoggingEvent LoggingEvent { get; set; }
public object HttpContext { get; set; }
}
}
@@ -4,9 +4,9 @@ using log4net.Core;
namespace Umbraco.Core.Logging
{
/// <remarks>
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
/// Based on https://github.com/cjbhaines/Log4Net.Async
/// </remarks>
internal sealed class LoggingEventHelper
internal class LoggingEventHelper
{
// needs to be a seperate class so that location is determined correctly by log4net when required
@@ -23,10 +23,8 @@ namespace Umbraco.Core.Logging
public LoggingEvent CreateLoggingEvent(Level level, string message, Exception exception)
{
var loggingEvent = new LoggingEvent(HelperType, null, loggerName, level, message, exception)
{
Fix = Fix
};
var loggingEvent = new LoggingEvent(HelperType, null, loggerName, level, message, exception);
loggingEvent.Fix = Fix;
return loggingEvent;
}
}
@@ -1,9 +1,9 @@
using log4net.Core;
using log4net.Util;
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using log4net.Core;
using log4net.Util;
namespace Umbraco.Core.Logging
{
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Logging
/// An asynchronous appender based on <see cref="BlockingCollection{T}"/>
/// </summary>
/// <remarks>
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
/// Based on https://github.com/cjbhaines/Log4Net.Async
/// </remarks>
public class ParallelForwardingAppender : AsyncForwardingAppenderBase, IDisposable
{
@@ -22,11 +22,11 @@ namespace Umbraco.Core.Logging
private CancellationTokenSource _loggingCancelationTokenSource;
private CancellationToken _loggingCancelationToken;
private Task _loggingTask;
private Double _shutdownFlushTimeout = 2;
private TimeSpan _shutdownFlushTimespan = TimeSpan.FromSeconds(2);
private Double _shutdownFlushTimeout = 1;
private TimeSpan _shutdownFlushTimespan = TimeSpan.FromSeconds(1);
private static readonly Type ThisType = typeof(ParallelForwardingAppender);
private volatile bool shutDownRequested;
private int? bufferSize = DefaultBufferSize;
private volatile bool _shutDownRequested;
private int? _bufferSize = DefaultBufferSize;
#endregion Private Members
@@ -37,8 +37,8 @@ namespace Umbraco.Core.Logging
/// </summary>
public override int? BufferSize
{
get { return bufferSize; }
set { bufferSize = value; }
get { return _bufferSize; }
set { _bufferSize = value; }
}
public int BufferEntryCount
@@ -67,12 +67,7 @@ namespace Umbraco.Core.Logging
protected override string InternalLoggerName
{
get
{
{
return "ParallelForwardingAppender";
}
}
get { return "ParallelForwardingAppender"; }
}
#endregion Properties
@@ -88,7 +83,7 @@ namespace Umbraco.Core.Logging
private void StartForwarding()
{
if (shutDownRequested)
if (_shutDownRequested)
{
return;
}
@@ -116,7 +111,7 @@ namespace Umbraco.Core.Logging
private void CompleteSubscriberTask()
{
shutDownRequested = true;
_shutDownRequested = true;
if (_loggingEvents == null || _loggingEvents.IsAddingCompleted)
{
return;
@@ -159,7 +154,7 @@ namespace Umbraco.Core.Logging
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);
_loggingEvents.Add(new LoggingEventContext(loggingEvent), _loggingCancelationToken);
}
protected override void Append(LoggingEvent[] loggingEvents)
@@ -192,7 +187,6 @@ namespace Umbraco.Core.Logging
//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);
}
}
-78
View File
@@ -1,78 +0,0 @@
using System;
namespace Umbraco.Core.Logging
{
/// <summary>
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
/// </summary>
/// <typeparam name="T"></typeparam>
internal sealed class RingBuffer<T> : IQueue<T>
{
private readonly object lockObject = new object();
private readonly T[] buffer;
private readonly int size;
private int readIndex = 0;
private int writeIndex = 0;
private bool bufferFull = false;
public int Size { get { return size; } }
public event Action<object, EventArgs> BufferOverflow;
public RingBuffer(int size)
{
this.size = size;
buffer = new T[size];
}
public void Enqueue(T item)
{
var bufferWasFull = false;
lock (lockObject)
{
buffer[writeIndex] = item;
writeIndex = (++writeIndex) % size;
if (bufferFull)
{
bufferWasFull = true;
readIndex = writeIndex;
}
else if (writeIndex == readIndex)
{
bufferFull = true;
}
}
if (bufferWasFull)
{
if (BufferOverflow != null)
{
BufferOverflow(this, EventArgs.Empty);
}
}
}
public bool TryDequeue(out T ret)
{
if (readIndex == writeIndex && !bufferFull)
{
ret = default(T);
return false;
}
lock (lockObject)
{
if (readIndex == writeIndex && !bufferFull)
{
ret = default(T);
return false;
}
ret = buffer[readIndex];
buffer[readIndex] = default(T);
readIndex = (++readIndex) % size;
bufferFull = false;
return true;
}
}
}
}
+22 -60
View File
@@ -1,21 +1,18 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.MemoryMappedFiles;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Hosting;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;
namespace Umbraco.Core
{
/// <summary>
/// Represents the main AppDomain running for a given application.
/// </summary>
/// <remarks>
/// <para>There can be only one "main" AppDomain running for a given application at a time.</para>
/// <para>When an AppDomain starts, it tries to acquire the main domain status.</para>
/// <para>When an AppDomain stops (eg the application is restarting) it should release the main domain status.</para>
/// <para>It is possible to register against the MainDom and be notified when it is released.</para>
/// </remarks>
internal class MainDom : IRegisteredObject
// represents the main domain
class MainDom : IRegisteredObject
{
#region Vars
@@ -28,7 +25,7 @@ namespace Umbraco.Core
private readonly AsyncLock _asyncLock;
private IDisposable _asyncLocker;
// event wait handle used to notify current main domain that it should
// event wait handle used to notify current main domain that it should
// release the lock because a new domain wants to be the main domain
private readonly EventWaitHandle _signal;
@@ -37,26 +34,16 @@ namespace Umbraco.Core
private volatile bool _signaled; // we have been signaled
// actions to run before releasing the main domain
private readonly SortedList<int, Action> _callbacks = new SortedList<int, Action>(new WeightComparer());
private readonly SortedList<int, Action> _callbacks = new SortedList<int, Action>();
private const int LockTimeoutMilliseconds = 90000; // (1.5 * 60 * 1000) == 1 min 30 seconds
private class WeightComparer : IComparer<int>
{
public int Compare(int x, int y)
{
var result = x.CompareTo(y);
// return "equal" as "greater than"
return result == 0 ? 1 : result;
}
}
#endregion
#region Ctor
// initializes a new instance of MainDom
internal MainDom(ILogger logger)
public MainDom(ILogger logger)
{
_logger = logger;
@@ -65,47 +52,22 @@ namespace Umbraco.Core
if (HostingEnvironment.ApplicationID != null)
appId = HostingEnvironment.ApplicationID.ReplaceNonAlphanumericChars(string.Empty);
// combining with the physical path because if running on eg IIS Express,
// two sites could have the same appId even though they are different.
//
// now what could still collide is... two sites, running in two different processes
// and having the same appId, and running on the same app physical path
//
// we *cannot* use the process ID here because when an AppPool restarts it is
// a new process for the same application path
var appPath = HostingEnvironment.ApplicationPhysicalPath;
var hash = (appId + ":::" + appPath).ToSHA1();
var lockName = "UMBRACO-" + hash + "-MAINDOM-LCK";
var lockName = "UMBRACO-" + appId + "-MAINDOM-LCK";
_asyncLock = new AsyncLock(lockName);
var eventName = "UMBRACO-" + hash + "-MAINDOM-EVT";
var eventName = "UMBRACO-" + appId + "-MAINDOM-EVT";
_signal = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
}
#endregion
/// <summary>
/// Registers a resource that requires the current AppDomain to be the main domain to function.
/// </summary>
/// <param name="release">An action to execute before the AppDomain releases the main domain status.</param>
/// <param name="weight">An optional weight (lower goes first).</param>
/// <returns>A value indicating whether it was possible to register.</returns>
// register a main domain consumer
public bool Register(Action release, int weight = 100)
{
return Register(null, release, weight);
}
/// <summary>
/// Registers a resource that requires the current AppDomain to be the main domain to function.
/// </summary>
/// <param name="install">An action to execute when registering.</param>
/// <param name="release">An action to execute before the AppDomain releases the main domain status.</param>
/// <param name="weight">An optional weight (lower goes first).</param>
/// <returns>A value indicating whether it was possible to register.</returns>
/// <remarks>If registering is successful, then the <paramref name="install"/> action
/// is guaranteed to execute before the AppDomain releases the main domain status.</remarks>
// register a main domain consumer
public bool Register(Action install, Action release, int weight = 100)
{
lock (_locko)
@@ -135,7 +97,7 @@ namespace Umbraco.Core
try
{
_logger.Info<MainDom>("Stopping...");
_logger.Debug<MainDom>("Stopping...");
foreach (var callback in _callbacks.Values)
{
try
@@ -147,7 +109,7 @@ namespace Umbraco.Core
_logger.Error<MainDom>("Error while running callback, remaining callbacks will not run.", e);
throw;
}
}
_logger.Debug<MainDom>("Stopped.");
}
@@ -156,12 +118,12 @@ namespace Umbraco.Core
// in any case...
_isMainDom = false;
_asyncLocker.Dispose();
_logger.Info<MainDom>("Released MainDom.");
_logger.Debug<MainDom>("Released MainDom.");
}
}
// acquires the main domain
internal bool Acquire()
public bool Acquire()
{
lock (_locko) // we don't want the hosting environment to interfere by signaling
{
@@ -169,11 +131,11 @@ namespace Umbraco.Core
// the handler is not installed so that would be the hosting environment
if (_signaled)
{
_logger.Info<MainDom>("Cannot acquire MainDom (signaled).");
_logger.Debug<MainDom>("Cannot acquire MainDom (signaled).");
return false;
}
_logger.Info<MainDom>("Acquiring MainDom...");
_logger.Debug<MainDom>("Acquiring MainDom...");
// signal other instances that we want the lock, then wait one the lock,
// which may timeout, and this is accepted - see comments below
@@ -200,7 +162,7 @@ namespace Umbraco.Core
HostingEnvironment.RegisterObject(this);
_logger.Info<MainDom>("Acquired MainDom.");
_logger.Debug<MainDom>("Acquired MainDom.");
return true;
}
}
@@ -212,7 +174,7 @@ namespace Umbraco.Core
}
// IRegisteredObject
void IRegisteredObject.Stop(bool immediate)
public void Stop(bool immediate)
{
try
{
+20 -22
View File
@@ -227,37 +227,35 @@ namespace Umbraco.Core.Media
}
// Set compresion ratio to 90%
string newFileName;
using (var ep = new EncoderParameters())
var ep = new EncoderParameters();
ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L);
// Save the new image using the dimensions of the image
var predictableThumbnailName = thumbnailFileName.Replace("UMBRACOSYSTHUMBNAIL", maxWidthHeight.ToString(CultureInfo.InvariantCulture));
var predictableThumbnailNameJpg = predictableThumbnailName.Substring(0, predictableThumbnailName.LastIndexOf(".", StringComparison.Ordinal)) + ".jpg";
using (var ms = new MemoryStream())
{
ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L);
bp.Save(ms, codec, ep);
ms.Seek(0, 0);
// Save the new image using the dimensions of the image
var predictableThumbnailName = thumbnailFileName.Replace("UMBRACOSYSTHUMBNAIL", maxWidthHeight.ToString(CultureInfo.InvariantCulture));
var predictableThumbnailNameJpg = predictableThumbnailName.Substring(0, predictableThumbnailName.LastIndexOf(".", StringComparison.Ordinal)) + ".jpg";
using (var ms = new MemoryStream())
{
bp.Save(ms, codec, ep);
ms.Seek(0, SeekOrigin.Begin);
fs.AddFile(predictableThumbnailName, ms);
fs.AddFile(predictableThumbnailNameJpg, ms);
}
fs.AddFile(predictableThumbnailName, ms);
fs.AddFile(predictableThumbnailNameJpg, ms);
}
// TODO: Remove this, this is ONLY here for backwards compatibility but it is essentially completely unusable see U4-5385
var newFileName = thumbnailFileName.Replace("UMBRACOSYSTHUMBNAIL", string.Format("{0}x{1}", widthTh, heightTh));
using (var ms = new MemoryStream())
{
bp.Save(ms, codec, ep);
ms.Seek(0, 0);
// TODO: Remove this, this is ONLY here for backwards compatibility but it is essentially completely unusable see U4-5385
newFileName = thumbnailFileName.Replace("UMBRACOSYSTHUMBNAIL", string.Format("{0}x{1}", widthTh, heightTh));
using (var ms = new MemoryStream())
{
bp.Save(ms, codec, ep);
ms.Seek(0, SeekOrigin.Begin);
fs.AddFile(newFileName, ms);
}
fs.AddFile(newFileName, ms);
}
return new ResizedImage(widthTh, heightTh, newFileName);
}
}
}
}
}
+72 -24
View File
@@ -76,19 +76,14 @@ namespace Umbraco.Core.Models
_contentType = contentType;
}
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo TemplateSelector = ExpressionHelper.GetPropertyInfo<Content, ITemplate>(x => x.Template);
public readonly PropertyInfo PublishedSelector = ExpressionHelper.GetPropertyInfo<Content, bool>(x => x.Published);
public readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo<Content, string>(x => x.Language);
public readonly PropertyInfo ReleaseDateSelector = ExpressionHelper.GetPropertyInfo<Content, DateTime?>(x => x.ReleaseDate);
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);
}
private static readonly PropertyInfo TemplateSelector = ExpressionHelper.GetPropertyInfo<Content, ITemplate>(x => x.Template);
private static readonly PropertyInfo PublishedSelector = ExpressionHelper.GetPropertyInfo<Content, bool>(x => x.Published);
private static readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo<Content, string>(x => x.Language);
private static readonly PropertyInfo ReleaseDateSelector = ExpressionHelper.GetPropertyInfo<Content, DateTime?>(x => x.ReleaseDate);
private static readonly PropertyInfo ExpireDateSelector = ExpressionHelper.GetPropertyInfo<Content, DateTime?>(x => x.ExpireDate);
private static readonly PropertyInfo WriterSelector = ExpressionHelper.GetPropertyInfo<Content, int>(x => x.WriterId);
private static readonly PropertyInfo NodeNameSelector = ExpressionHelper.GetPropertyInfo<Content, string>(x => x.NodeName);
private static readonly PropertyInfo PermissionsChangedSelector = ExpressionHelper.GetPropertyInfo<Content, bool>(x => x.PermissionsChanged);
/// <summary>
/// Gets or sets the template used by the Content.
@@ -102,7 +97,14 @@ namespace Umbraco.Core.Models
public virtual ITemplate Template
{
get { return _template; }
set { SetPropertyValueAndDetectChanges(value, ref _template, Ps.Value.TemplateSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_template = value;
return _template;
}, _template, TemplateSelector);
}
}
/// <summary>
@@ -140,7 +142,14 @@ namespace Umbraco.Core.Models
public bool Published
{
get { return _published; }
internal set { SetPropertyValueAndDetectChanges(value, ref _published, Ps.Value.PublishedSelector); }
internal set
{
SetPropertyValueAndDetectChanges(o =>
{
_published = value;
return _published;
}, _published, PublishedSelector);
}
}
/// <summary>
@@ -151,7 +160,14 @@ namespace Umbraco.Core.Models
public string Language
{
get { return _language; }
set { SetPropertyValueAndDetectChanges(value, ref _language, Ps.Value.LanguageSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_language = value;
return _language;
}, _language, LanguageSelector);
}
}
/// <summary>
@@ -161,7 +177,14 @@ namespace Umbraco.Core.Models
public DateTime? ReleaseDate
{
get { return _releaseDate; }
set { SetPropertyValueAndDetectChanges(value, ref _releaseDate, Ps.Value.ReleaseDateSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_releaseDate = value;
return _releaseDate;
}, _releaseDate, ReleaseDateSelector);
}
}
/// <summary>
@@ -171,7 +194,14 @@ namespace Umbraco.Core.Models
public DateTime? ExpireDate
{
get { return _expireDate; }
set { SetPropertyValueAndDetectChanges(value, ref _expireDate, Ps.Value.ExpireDateSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_expireDate = value;
return _expireDate;
}, _expireDate, ExpireDateSelector);
}
}
/// <summary>
@@ -181,7 +211,14 @@ namespace Umbraco.Core.Models
public virtual int WriterId
{
get { return _writer; }
set { SetPropertyValueAndDetectChanges(value, ref _writer, Ps.Value.WriterSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_writer = value;
return _writer;
}, _writer, WriterSelector);
}
}
/// <summary>
@@ -194,7 +231,14 @@ namespace Umbraco.Core.Models
internal string NodeName
{
get { return _nodeName; }
set { SetPropertyValueAndDetectChanges(value, ref _nodeName, Ps.Value.NodeNameSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_nodeName = value;
return _nodeName;
}, _nodeName, NodeNameSelector);
}
}
/// <summary>
@@ -204,7 +248,14 @@ namespace Umbraco.Core.Models
internal bool PermissionsChanged
{
get { return _permissionsChanged; }
set { SetPropertyValueAndDetectChanges(value, ref _permissionsChanged, Ps.Value.PermissionsChangedSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_permissionsChanged = value;
return _permissionsChanged;
}, _permissionsChanged, PermissionsChangedSelector);
}
}
/// <summary>
@@ -274,9 +325,6 @@ namespace Umbraco.Core.Models
/// </summary>
public bool HasPublishedVersion { get { return PublishedVersionGuid != default(Guid); } }
[IgnoreDataMember]
internal DateTime PublishedDate { get; set; }
/// <summary>
/// Changes the Trashed state of the content object
/// </summary>
+67 -23
View File
@@ -81,24 +81,19 @@ namespace Umbraco.Core.Models
_additionalData = new Dictionary<string, object>();
}
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<ContentBase, string>(x => x.Name);
public readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.ParentId);
public readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.SortOrder);
public readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.Level);
public readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<ContentBase, string>(x => x.Path);
public readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.CreatorId);
public readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<ContentBase, bool>(x => x.Trashed);
public readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.ContentTypeId);
public readonly PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentBase, PropertyCollection>(x => x.Properties);
}
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<ContentBase, string>(x => x.Name);
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.ParentId);
private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.SortOrder);
private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.Level);
private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<ContentBase, string>(x => x.Path);
private static readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.CreatorId);
private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<ContentBase, bool>(x => x.Trashed);
private static readonly PropertyInfo DefaultContentTypeIdSelector = ExpressionHelper.GetPropertyInfo<ContentBase, int>(x => x.ContentTypeId);
private readonly static PropertyInfo PropertyCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentBase, PropertyCollection>(x => x.Properties);
protected void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(Ps.Value.PropertyCollectionSelector);
OnPropertyChanged(PropertyCollectionSelector);
}
/// <summary>
@@ -119,7 +114,7 @@ namespace Umbraco.Core.Models
set
{
_parentId = new Lazy<int>(() => value);
OnPropertyChanged(Ps.Value.ParentIdSelector);
OnPropertyChanged(ParentIdSelector);
}
}
@@ -130,7 +125,14 @@ namespace Umbraco.Core.Models
public virtual string Name
{
get { return _name; }
set { SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_name = value;
return _name;
}, _name, NameSelector);
}
}
/// <summary>
@@ -140,7 +142,14 @@ namespace Umbraco.Core.Models
public virtual int SortOrder
{
get { return _sortOrder; }
set { SetPropertyValueAndDetectChanges(value, ref _sortOrder, Ps.Value.SortOrderSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_sortOrder = value;
return _sortOrder;
}, _sortOrder, SortOrderSelector);
}
}
/// <summary>
@@ -150,7 +159,14 @@ namespace Umbraco.Core.Models
public virtual int Level
{
get { return _level; }
set { SetPropertyValueAndDetectChanges(value, ref _level, Ps.Value.LevelSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_level = value;
return _level;
}, _level, LevelSelector);
}
}
/// <summary>
@@ -160,7 +176,14 @@ namespace Umbraco.Core.Models
public virtual string Path //Setting this value should be handled by the class not the user
{
get { return _path; }
set { SetPropertyValueAndDetectChanges(value, ref _path, Ps.Value.PathSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_path = value;
return _path;
}, _path, PathSelector);
}
}
/// <summary>
@@ -170,7 +193,14 @@ namespace Umbraco.Core.Models
public virtual int CreatorId
{
get { return _creatorId; }
set { SetPropertyValueAndDetectChanges(value, ref _creatorId, Ps.Value.CreatorIdSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_creatorId = value;
return _creatorId;
}, _creatorId, CreatorIdSelector);
}
}
/// <summary>
@@ -182,7 +212,14 @@ namespace Umbraco.Core.Models
public virtual bool Trashed //Setting this value should be handled by the class not the user
{
get { return _trashed; }
internal set { SetPropertyValueAndDetectChanges(value, ref _trashed, Ps.Value.TrashedSelector); }
internal set
{
SetPropertyValueAndDetectChanges(o =>
{
_trashed = value;
return _trashed;
}, _trashed, TrashedSelector);
}
}
/// <summary>
@@ -207,7 +244,14 @@ namespace Umbraco.Core.Models
}
return _contentTypeId;
}
protected set { SetPropertyValueAndDetectChanges(value, ref _contentTypeId, Ps.Value.DefaultContentTypeIdSelector); }
protected set
{
SetPropertyValueAndDetectChanges(o =>
{
_contentTypeId = value;
return _contentTypeId;
}, _contentTypeId, DefaultContentTypeIdSelector);
}
}
/// <summary>
+3 -2
View File
@@ -404,7 +404,8 @@ namespace Umbraco.Core.Models
return content.Properties
.Where(property => propertyGroup.PropertyTypes
.Select(propertyType => propertyType.Id)
.Contains(property.PropertyTypeId));
.Contains(property.PropertyTypeId))
.OrderBy(x => x.PropertyType.SortOrder);
}
/// <summary>
@@ -545,7 +546,7 @@ namespace Umbraco.Core.Models
if (supportsResizing)
{
//get the original image from the original stream
if (fileStream.CanSeek) fileStream.Seek(0, SeekOrigin.Begin);
if (fileStream.CanSeek) fileStream.Seek(0, 0);
using (var originalImage = Image.FromStream(fileStream))
{
var additionalSizes = new List<int>();
+15 -9
View File
@@ -48,13 +48,8 @@ namespace Umbraco.Core.Models
_allowedTemplates = new List<ITemplate>();
}
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo DefaultTemplateSelector = ExpressionHelper.GetPropertyInfo<ContentType, int>(x => x.DefaultTemplateId);
public readonly PropertyInfo AllowedTemplatesSelector = ExpressionHelper.GetPropertyInfo<ContentType, IEnumerable<ITemplate>>(x => x.AllowedTemplates);
}
private static readonly PropertyInfo DefaultTemplateSelector = ExpressionHelper.GetPropertyInfo<ContentType, int>(x => x.DefaultTemplateId);
private static readonly PropertyInfo AllowedTemplatesSelector = ExpressionHelper.GetPropertyInfo<ContentType, IEnumerable<ITemplate>>(x => x.AllowedTemplates);
/// <summary>
/// Gets or sets the alias of the default Template.
@@ -75,7 +70,14 @@ namespace Umbraco.Core.Models
internal int DefaultTemplateId
{
get { return _defaultTemplate; }
set { SetPropertyValueAndDetectChanges(value, ref _defaultTemplate, Ps.Value.DefaultTemplateSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_defaultTemplate = value;
return _defaultTemplate;
}, _defaultTemplate, DefaultTemplateSelector);
}
}
/// <summary>
@@ -90,7 +92,11 @@ namespace Umbraco.Core.Models
get { return _allowedTemplates; }
set
{
SetPropertyValueAndDetectChanges(value, ref _allowedTemplates, Ps.Value.AllowedTemplatesSelector,
SetPropertyValueAndDetectChanges(o =>
{
_allowedTemplates = value;
return _allowedTemplates;
}, _allowedTemplates, AllowedTemplatesSelector,
//Custom comparer for enumerable
new DelegateEqualityComparer<IEnumerable<ITemplate>>(
(templates, enumerable) => templates.UnsortedSequenceEqual(enumerable),
+123 -45
View File
@@ -67,38 +67,33 @@ namespace Umbraco.Core.Models
_additionalData = new Dictionary<string, object>();
}
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Name);
public readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.ParentId);
public readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.SortOrder);
public readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.Level);
public readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Path);
public readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Alias);
public readonly PropertyInfo DescriptionSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Description);
public readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Icon);
public readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Thumbnail);
public readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.CreatorId);
public readonly PropertyInfo AllowedAsRootSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.AllowedAsRoot);
public readonly PropertyInfo IsContainerSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.IsContainer);
public readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.Trashed);
public readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, IEnumerable<ContentTypeSort>>(x => x.AllowedContentTypes);
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);
}
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Name);
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.ParentId);
private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.SortOrder);
private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.Level);
private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Path);
private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Alias);
private static readonly PropertyInfo DescriptionSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Description);
private static readonly PropertyInfo IconSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Icon);
private static readonly PropertyInfo ThumbnailSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, string>(x => x.Thumbnail);
private static readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, int>(x => x.CreatorId);
private static readonly PropertyInfo AllowedAsRootSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.AllowedAsRoot);
private static readonly PropertyInfo IsContainerSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.IsContainer);
private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.Trashed);
private static readonly PropertyInfo AllowedContentTypesSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, IEnumerable<ContentTypeSort>>(x => x.AllowedContentTypes);
private static readonly PropertyInfo PropertyGroupCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, PropertyGroupCollection>(x => x.PropertyGroups);
private static readonly PropertyInfo PropertyTypeCollectionSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, IEnumerable<PropertyType>>(x => x.PropertyTypes);
private static readonly PropertyInfo HasPropertyTypeBeenRemovedSelector = ExpressionHelper.GetPropertyInfo<ContentTypeBase, bool>(x => x.HasPropertyTypeBeenRemoved);
protected void PropertyGroupsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(Ps.Value.PropertyGroupCollectionSelector);
OnPropertyChanged(PropertyGroupCollectionSelector);
}
protected void PropertyTypesChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(Ps.Value.PropertyTypeCollectionSelector);
OnPropertyChanged(PropertyTypeCollectionSelector);
}
/// <summary>
@@ -120,7 +115,7 @@ namespace Umbraco.Core.Models
set
{
_parentId = new Lazy<int>(() => value);
OnPropertyChanged(Ps.Value.ParentIdSelector);
OnPropertyChanged(ParentIdSelector);
}
}
@@ -131,7 +126,14 @@ namespace Umbraco.Core.Models
public virtual string Name
{
get { return _name; }
set { SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_name = value;
return _name;
}, _name, NameSelector);
}
}
/// <summary>
@@ -141,7 +143,14 @@ namespace Umbraco.Core.Models
public virtual int Level //NOTE Is this relevant for a ContentType?
{
get { return _level; }
set { SetPropertyValueAndDetectChanges(value, ref _level, Ps.Value.LevelSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_level = value;
return _level;
}, _level, LevelSelector);
}
}
/// <summary>
@@ -151,7 +160,14 @@ namespace Umbraco.Core.Models
public virtual string Path //NOTE Is this relevant for a ContentType?
{
get { return _path; }
set { SetPropertyValueAndDetectChanges(value, ref _path, Ps.Value.PathSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_path = value;
return _path;
}, _path, PathSelector);
}
}
/// <summary>
@@ -163,10 +179,12 @@ namespace Umbraco.Core.Models
get { return _alias; }
set
{
SetPropertyValueAndDetectChanges(
value.ToCleanString(CleanStringType.Alias | CleanStringType.UmbracoCase),
ref _alias,
Ps.Value.AliasSelector);
SetPropertyValueAndDetectChanges(o =>
{
//_alias = value.ToSafeAlias();
_alias = value.ToCleanString(CleanStringType.Alias | CleanStringType.UmbracoCase);
return _alias;
}, _alias, AliasSelector);
}
}
@@ -177,7 +195,14 @@ namespace Umbraco.Core.Models
public virtual string Description
{
get { return _description; }
set { SetPropertyValueAndDetectChanges(value, ref _description, Ps.Value.DescriptionSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_description = value;
return _description;
}, _description, DescriptionSelector);
}
}
/// <summary>
@@ -187,7 +212,14 @@ namespace Umbraco.Core.Models
public virtual int SortOrder
{
get { return _sortOrder; }
set { SetPropertyValueAndDetectChanges(value, ref _sortOrder, Ps.Value.SortOrderSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_sortOrder = value;
return _sortOrder;
}, _sortOrder, SortOrderSelector);
}
}
/// <summary>
@@ -197,7 +229,14 @@ namespace Umbraco.Core.Models
public virtual string Icon
{
get { return _icon; }
set { SetPropertyValueAndDetectChanges(value, ref _icon, Ps.Value.IconSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_icon = value;
return _icon;
}, _icon, IconSelector);
}
}
/// <summary>
@@ -207,7 +246,14 @@ namespace Umbraco.Core.Models
public virtual string Thumbnail
{
get { return _thumbnail; }
set { SetPropertyValueAndDetectChanges(value, ref _thumbnail, Ps.Value.ThumbnailSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_thumbnail = value;
return _thumbnail;
}, _thumbnail, ThumbnailSelector);
}
}
/// <summary>
@@ -217,7 +263,14 @@ namespace Umbraco.Core.Models
public virtual int CreatorId
{
get { return _creatorId; }
set { SetPropertyValueAndDetectChanges(value, ref _creatorId, Ps.Value.CreatorIdSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_creatorId = value;
return _creatorId;
}, _creatorId, CreatorIdSelector);
}
}
/// <summary>
@@ -227,7 +280,14 @@ namespace Umbraco.Core.Models
public virtual bool AllowedAsRoot
{
get { return _allowedAsRoot; }
set { SetPropertyValueAndDetectChanges(value, ref _allowedAsRoot, Ps.Value.AllowedAsRootSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_allowedAsRoot = value;
return _allowedAsRoot;
}, _allowedAsRoot, AllowedAsRootSelector);
}
}
/// <summary>
@@ -240,7 +300,14 @@ namespace Umbraco.Core.Models
public virtual bool IsContainer
{
get { return _isContainer; }
set { SetPropertyValueAndDetectChanges(value, ref _isContainer, Ps.Value.IsContainerSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_isContainer = value;
return _isContainer;
}, _isContainer, IsContainerSelector);
}
}
/// <summary>
@@ -251,7 +318,14 @@ namespace Umbraco.Core.Models
public virtual bool Trashed //NOTE Is this relevant for a ContentType?
{
get { return _trashed; }
set { SetPropertyValueAndDetectChanges(value, ref _trashed, Ps.Value.TrashedSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_trashed = value;
return _trashed;
}, _trashed, TrashedSelector);
}
}
private IDictionary<string, object> _additionalData;
@@ -273,11 +347,15 @@ namespace Umbraco.Core.Models
get { return _allowedContentTypes; }
set
{
SetPropertyValueAndDetectChanges(value, ref _allowedContentTypes, Ps.Value.AllowedContentTypesSelector,
SetPropertyValueAndDetectChanges(o =>
{
_allowedContentTypes = value;
return _allowedContentTypes;
}, _allowedContentTypes, AllowedContentTypesSelector,
//Custom comparer for enumerable
new DelegateEqualityComparer<IEnumerable<ContentTypeSort>>(
(sorts, enumerable) => sorts.UnsortedSequenceEqual(enumerable),
sorts => sorts.GetHashCode()));
sorts => sorts.GetHashCode()));
}
}
@@ -326,7 +404,7 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// <summary>
/// A boolean flag indicating if a property type has been removed from this instance.
/// </summary>
/// <remarks>
@@ -340,7 +418,7 @@ namespace Umbraco.Core.Models
private set
{
_hasPropertyTypeBeenRemoved = value;
OnPropertyChanged(Ps.Value.HasPropertyTypeBeenRemovedSelector);
OnPropertyChanged(HasPropertyTypeBeenRemovedSelector);
}
}
@@ -465,7 +543,7 @@ namespace Umbraco.Core.Models
// actually remove the group
PropertyGroups.RemoveItem(propertyGroupName);
OnPropertyChanged(Ps.Value.PropertyGroupCollectionSelector);
OnPropertyChanged(PropertyGroupCollectionSelector);
}
/// <summary>
@@ -32,13 +32,9 @@ namespace Umbraco.Core.Models
AddContentType(parent);
}
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo ContentTypeCompositionSelector =
ExpressionHelper.GetPropertyInfo<ContentTypeCompositionBase, IEnumerable<IContentTypeComposition>>(x => x.ContentTypeComposition);
}
private static readonly PropertyInfo ContentTypeCompositionSelector =
ExpressionHelper.GetPropertyInfo<ContentTypeCompositionBase, IEnumerable<IContentTypeComposition>>(
x => x.ContentTypeComposition);
/// <summary>
/// Gets or sets the content types that compose this content type.
@@ -50,7 +46,7 @@ namespace Umbraco.Core.Models
set
{
_contentTypeComposition = value.ToList();
OnPropertyChanged(Ps.Value.ContentTypeCompositionSelector);
OnPropertyChanged(ContentTypeCompositionSelector);
}
}
@@ -106,7 +102,7 @@ namespace Umbraco.Core.Models
throw new InvalidCompositionException(Alias, contentType.Alias, conflictingPropertyTypeAliases.ToArray());
_contentTypeComposition.Add(contentType);
OnPropertyChanged(Ps.Value.ContentTypeCompositionSelector);
OnPropertyChanged(ContentTypeCompositionSelector);
return true;
}
return false;
@@ -132,7 +128,7 @@ namespace Umbraco.Core.Models
if (compositionIdsToRemove.Any())
RemovedContentTypeKeyTracker.AddRange(compositionIdsToRemove);
OnPropertyChanged(Ps.Value.ContentTypeCompositionSelector);
OnPropertyChanged(ContentTypeCompositionSelector);
return _contentTypeComposition.Remove(contentTypeComposition);
}
return false;
+73 -23
View File
@@ -65,20 +65,15 @@ namespace Umbraco.Core.Models
_additionalData = new Dictionary<string, object>();
}
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, string>(x => x.Name);
public readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.ParentId);
public readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.SortOrder);
public readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.Level);
public readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, string>(x => x.Path);
public readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.CreatorId);
public readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, bool>(x => x.Trashed);
public readonly PropertyInfo PropertyEditorAliasSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, string>(x => x.PropertyEditorAlias);
public readonly PropertyInfo DatabaseTypeSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, DataTypeDatabaseType>(x => x.DatabaseType);
}
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, string>(x => x.Name);
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.ParentId);
private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.SortOrder);
private static readonly PropertyInfo LevelSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.Level);
private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, string>(x => x.Path);
private static readonly PropertyInfo UserIdSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, int>(x => x.CreatorId);
private static readonly PropertyInfo TrashedSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, bool>(x => x.Trashed);
private static readonly PropertyInfo PropertyEditorAliasSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, string>(x => x.PropertyEditorAlias);
private static readonly PropertyInfo DatabaseTypeSelector = ExpressionHelper.GetPropertyInfo<DataTypeDefinition, DataTypeDatabaseType>(x => x.DatabaseType);
/// <summary>
/// Gets or sets the Id of the Parent entity
@@ -88,7 +83,14 @@ namespace Umbraco.Core.Models
public int ParentId
{
get { return _parentId; }
set { SetPropertyValueAndDetectChanges(value, ref _parentId, Ps.Value.ParentIdSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_parentId = value;
return _parentId;
}, _parentId, ParentIdSelector);
}
}
/// <summary>
@@ -98,7 +100,14 @@ namespace Umbraco.Core.Models
public string Name
{
get { return _name; }
set { SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_name = value;
return _name;
}, _name, NameSelector);
}
}
/// <summary>
@@ -108,7 +117,14 @@ namespace Umbraco.Core.Models
public int SortOrder
{
get { return _sortOrder; }
set { SetPropertyValueAndDetectChanges(value, ref _sortOrder, Ps.Value.SortOrderSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_sortOrder = value;
return _sortOrder;
}, _sortOrder, SortOrderSelector);
}
}
/// <summary>
@@ -118,7 +134,14 @@ namespace Umbraco.Core.Models
public int Level
{
get { return _level; }
set { SetPropertyValueAndDetectChanges(value, ref _level, Ps.Value.LevelSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_level = value;
return _level;
}, _level, LevelSelector);
}
}
/// <summary>
@@ -128,7 +151,14 @@ namespace Umbraco.Core.Models
public string Path //Setting this value should be handled by the class not the user
{
get { return _path; }
set { SetPropertyValueAndDetectChanges(value, ref _path, Ps.Value.PathSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_path = value;
return _path;
}, _path, PathSelector);
}
}
/// <summary>
@@ -138,7 +168,14 @@ namespace Umbraco.Core.Models
public int CreatorId
{
get { return _creatorId; }
set { SetPropertyValueAndDetectChanges(value, ref _creatorId, Ps.Value.UserIdSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_creatorId = value;
return _creatorId;
}, _creatorId, UserIdSelector);
}
}
//NOTE: SD: Why do we have this ??
@@ -152,7 +189,11 @@ namespace Umbraco.Core.Models
get { return _trashed; }
internal set
{
SetPropertyValueAndDetectChanges(value, ref _trashed, Ps.Value.TrashedSelector);
SetPropertyValueAndDetectChanges(o =>
{
_trashed = value;
return _trashed;
}, _trashed, TrashedSelector);
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
_additionalData["Trashed"] = value;
}
@@ -164,7 +205,11 @@ namespace Umbraco.Core.Models
get { return _propertyEditorAlias; }
set
{
SetPropertyValueAndDetectChanges(value, ref _propertyEditorAlias, Ps.Value.PropertyEditorAliasSelector);
SetPropertyValueAndDetectChanges(o =>
{
_propertyEditorAlias = value;
return _propertyEditorAlias;
}, _propertyEditorAlias, PropertyEditorAliasSelector);
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
_additionalData["DatabaseType"] = value;
}
@@ -200,7 +245,12 @@ namespace Umbraco.Core.Models
get { return _databaseType; }
set
{
SetPropertyValueAndDetectChanges(value, ref _databaseType, Ps.Value.DatabaseTypeSelector);
SetPropertyValueAndDetectChanges(o =>
{
_databaseType = value;
return _databaseType;
}, _databaseType, DatabaseTypeSelector);
//This is a custom property that is not exposed in IUmbracoEntity so add it to the additional data
_additionalData["DatabaseType"] = value;
}
+31 -18
View File
@@ -30,14 +30,9 @@ namespace Umbraco.Core.Models
_translations = new List<IDictionaryTranslation>();
}
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
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);
}
private static readonly PropertyInfo ParentIdSelector = ExpressionHelper.GetPropertyInfo<DictionaryItem, Guid?>(x => x.ParentId);
private static readonly PropertyInfo ItemKeySelector = ExpressionHelper.GetPropertyInfo<DictionaryItem, string>(x => x.ItemKey);
private static readonly PropertyInfo TranslationsSelector = ExpressionHelper.GetPropertyInfo<DictionaryItem, IEnumerable<IDictionaryTranslation>>(x => x.Translations);
/// <summary>
/// Gets or Sets the Parent Id of the Dictionary Item
@@ -46,7 +41,14 @@ namespace Umbraco.Core.Models
public Guid? ParentId
{
get { return _parentId; }
set { SetPropertyValueAndDetectChanges(value, ref _parentId, Ps.Value.ParentIdSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_parentId = value;
return _parentId;
}, _parentId, ParentIdSelector);
}
}
/// <summary>
@@ -56,7 +58,14 @@ namespace Umbraco.Core.Models
public string ItemKey
{
get { return _itemKey; }
set { SetPropertyValueAndDetectChanges(value, ref _itemKey, Ps.Value.ItemKeySelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_itemKey = value;
return _itemKey;
}, _itemKey, ItemKeySelector);
}
}
/// <summary>
@@ -68,21 +77,25 @@ namespace Umbraco.Core.Models
get { return _translations; }
set
{
var asArray = value.ToArray();
//ensure the language callback is set on each translation
if (GetLanguage != null)
SetPropertyValueAndDetectChanges(o =>
{
foreach (var translation in asArray.OfType<DictionaryTranslation>())
var asArray = value.ToArray();
//ensure the language callback is set on each translation
if (GetLanguage != null)
{
translation.GetLanguage = GetLanguage;
foreach (var translation in asArray.OfType<DictionaryTranslation>())
{
translation.GetLanguage = GetLanguage;
}
}
}
SetPropertyValueAndDetectChanges(asArray, ref _translations, Ps.Value.TranslationsSelector,
_translations = asArray;
return _translations;
}, _translations, TranslationsSelector,
//Custom comparer for enumerable
new DelegateEqualityComparer<IEnumerable<IDictionaryTranslation>>(
(enumerable, translations) => enumerable.UnsortedSequenceEqual(translations),
enumerable => enumerable.GetHashCode()));
enumerable => enumerable.GetHashCode()));
}
}
}
@@ -19,7 +19,7 @@ namespace Umbraco.Core.Models
private string _value;
//note: this will be memberwise cloned
private int _languageId;
public DictionaryTranslation(ILanguage language, string value)
{
if (language == null) throw new ArgumentNullException("language");
@@ -50,13 +50,8 @@ namespace Umbraco.Core.Models
Key = uniqueId;
}
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo<DictionaryTranslation, ILanguage>(x => x.Language);
public readonly PropertyInfo ValueSelector = ExpressionHelper.GetPropertyInfo<DictionaryTranslation, string>(x => x.Value);
}
private static readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo<DictionaryTranslation, ILanguage>(x => x.Language);
private static readonly PropertyInfo ValueSelector = ExpressionHelper.GetPropertyInfo<DictionaryTranslation, string>(x => x.Value);
/// <summary>
/// Gets or sets the <see cref="Language"/> for the translation
@@ -84,8 +79,12 @@ namespace Umbraco.Core.Models
}
set
{
SetPropertyValueAndDetectChanges(value, ref _language, Ps.Value.LanguageSelector);
_languageId = _language == null ? -1 : _language.Id;
SetPropertyValueAndDetectChanges(o =>
{
_language = value;
_languageId = _language == null ? -1 : _language.Id;
return _language;
}, _language, LanguageSelector);
}
}
@@ -101,7 +100,14 @@ namespace Umbraco.Core.Models
public string Value
{
get { return _value; }
set { SetPropertyValueAndDetectChanges(value, ref _value, Ps.Value.ValueSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_value = value;
return _value;
}, _value, ValueSelector);
}
}
public override object DeepClone()
+57 -19
View File
@@ -23,17 +23,13 @@ namespace Umbraco.Core.Models.EntityBase
private DateTime _updateDate;
private bool _wasCancelled;
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo IdSelector = ExpressionHelper.GetPropertyInfo<Entity, int>(x => x.Id);
public readonly PropertyInfo KeySelector = ExpressionHelper.GetPropertyInfo<Entity, Guid>(x => x.Key);
public readonly PropertyInfo CreateDateSelector = ExpressionHelper.GetPropertyInfo<Entity, DateTime>(x => x.CreateDate);
public readonly PropertyInfo UpdateDateSelector = ExpressionHelper.GetPropertyInfo<Entity, DateTime>(x => x.UpdateDate);
public readonly PropertyInfo HasIdentitySelector = ExpressionHelper.GetPropertyInfo<Entity, bool>(x => x.HasIdentity);
public readonly PropertyInfo WasCancelledSelector = ExpressionHelper.GetPropertyInfo<Entity, bool>(x => x.WasCancelled);
}
private static readonly PropertyInfo IdSelector = ExpressionHelper.GetPropertyInfo<Entity, int>(x => x.Id);
private static readonly PropertyInfo KeySelector = ExpressionHelper.GetPropertyInfo<Entity, Guid>(x => x.Key);
private static readonly PropertyInfo CreateDateSelector = ExpressionHelper.GetPropertyInfo<Entity, DateTime>(x => x.CreateDate);
private static readonly PropertyInfo UpdateDateSelector = ExpressionHelper.GetPropertyInfo<Entity, DateTime>(x => x.UpdateDate);
private static readonly PropertyInfo HasIdentitySelector = ExpressionHelper.GetPropertyInfo<Entity, bool>(x => x.HasIdentity);
private static readonly PropertyInfo WasCancelledSelector = ExpressionHelper.GetPropertyInfo<Entity, bool>(x => x.WasCancelled);
/// <summary>
/// Integer Id
@@ -41,11 +37,18 @@ namespace Umbraco.Core.Models.EntityBase
[DataMember]
public int Id
{
get { return _id; }
get
{
return _id;
}
set
{
SetPropertyValueAndDetectChanges(value, ref _id, Ps.Value.IdSelector);
HasIdentity = true; //set the has Identity
SetPropertyValueAndDetectChanges(o =>
{
_id = value;
HasIdentity = true; //set the has Identity
return _id;
}, _id, IdSelector);
}
}
@@ -64,7 +67,14 @@ namespace Umbraco.Core.Models.EntityBase
_key = Guid.NewGuid();
return _key;
}
set { SetPropertyValueAndDetectChanges(value, ref _key, Ps.Value.KeySelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_key = value;
return _key;
}, _key, KeySelector);
}
}
/// <summary>
@@ -74,7 +84,14 @@ namespace Umbraco.Core.Models.EntityBase
public DateTime CreateDate
{
get { return _createDate; }
set { SetPropertyValueAndDetectChanges(value, ref _createDate, Ps.Value.CreateDateSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_createDate = value;
return _createDate;
}, _createDate, CreateDateSelector);
}
}
/// <summary>
@@ -88,7 +105,14 @@ namespace Umbraco.Core.Models.EntityBase
internal bool WasCancelled
{
get { return _wasCancelled; }
set { SetPropertyValueAndDetectChanges(value, ref _wasCancelled, Ps.Value.WasCancelledSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_wasCancelled = value;
return _wasCancelled;
}, _wasCancelled, WasCancelledSelector);
}
}
/// <summary>
@@ -98,7 +122,14 @@ namespace Umbraco.Core.Models.EntityBase
public DateTime UpdateDate
{
get { return _updateDate; }
set { SetPropertyValueAndDetectChanges(value, ref _updateDate, Ps.Value.UpdateDateSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_updateDate = value;
return _updateDate;
}, _updateDate, UpdateDateSelector);
}
}
internal virtual void ResetIdentity()
@@ -135,7 +166,14 @@ namespace Umbraco.Core.Models.EntityBase
{
return _hasIdentity;
}
protected set { SetPropertyValueAndDetectChanges(value, ref _hasIdentity, Ps.Value.HasIdentitySelector); }
protected set
{
SetPropertyValueAndDetectChanges(o =>
{
_hasIdentity = value;
return _hasIdentity;
}, _hasIdentity, HasIdentitySelector);
}
}
//TODO: Make this NOT virtual or even exist really!
@@ -18,9 +18,7 @@ namespace Umbraco.Core.Models.EntityBase
//TODO: This needs to go on to ICanBeDirty http://issues.umbraco.org/issue/U4-5662
public virtual IEnumerable<string> GetDirtyProperties()
{
return _propertyChangedInfo == null
? Enumerable.Empty<string>()
: _propertyChangedInfo.Where(x => x.Value).Select(x => x.Key);
return _propertyChangedInfo.Where(x => x.Value).Select(x => x.Key);
}
private bool _changeTrackingEnabled = true;
@@ -28,12 +26,12 @@ namespace Umbraco.Core.Models.EntityBase
/// <summary>
/// Tracks the properties that have changed
/// </summary>
private IDictionary<string, bool> _propertyChangedInfo;
private IDictionary<string, bool> _propertyChangedInfo = new Dictionary<string, bool>();
/// <summary>
/// Tracks the properties that we're changed before the last commit (or last call to ResetDirtyProperties)
/// </summary>
private IDictionary<string, bool> _lastPropertyChangedInfo;
private IDictionary<string, bool> _lastPropertyChangedInfo = null;
/// <summary>
/// Property changed event
@@ -49,13 +47,12 @@ namespace Umbraco.Core.Models.EntityBase
//return if we're not tracking changes
if (_changeTrackingEnabled == false) return;
if (_propertyChangedInfo == null)
_propertyChangedInfo = new Dictionary<string, bool>();
_propertyChangedInfo[propertyInfo.Name] = true;
if (PropertyChanged != null)
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyInfo.Name));
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyInfo.Name));
}
}
/// <summary>
@@ -65,7 +62,7 @@ namespace Umbraco.Core.Models.EntityBase
/// <returns>True if Property is dirty, otherwise False</returns>
public virtual bool IsPropertyDirty(string propertyName)
{
return _propertyChangedInfo != null && _propertyChangedInfo.Any(x => x.Key == propertyName);
return _propertyChangedInfo.Any(x => x.Key == propertyName);
}
/// <summary>
@@ -74,7 +71,7 @@ namespace Umbraco.Core.Models.EntityBase
/// <returns>True if entity is dirty, otherwise False</returns>
public virtual bool IsDirty()
{
return _propertyChangedInfo != null && _propertyChangedInfo.Any();
return _propertyChangedInfo.Any();
}
/// <summary>
@@ -93,7 +90,7 @@ namespace Umbraco.Core.Models.EntityBase
/// <returns>True if Property was changed, otherwise False. Returns false if the entity had not been previously changed.</returns>
public virtual bool WasPropertyDirty(string propertyName)
{
return _lastPropertyChangedInfo != null && _lastPropertyChangedInfo.Any(x => x.Key == propertyName);
return WasDirty() && _lastPropertyChangedInfo.Any(x => x.Key == propertyName);
}
/// <summary>
@@ -103,7 +100,7 @@ namespace Umbraco.Core.Models.EntityBase
{
//NOTE: We cannot .Clear() because when we memberwise clone this will be the SAME
// instance as the one on the clone, so we need to create a new instance.
_lastPropertyChangedInfo = null;
_lastPropertyChangedInfo = new Dictionary<string, bool>();
}
/// <summary>
@@ -133,29 +130,26 @@ namespace Umbraco.Core.Models.EntityBase
if (rememberPreviouslyChangedProperties)
{
//copy the changed properties to the last changed properties
if (_propertyChangedInfo != null)
{
_lastPropertyChangedInfo = _propertyChangedInfo.ToDictionary(v => v.Key, v => v.Value);
}
_lastPropertyChangedInfo = _propertyChangedInfo.ToDictionary(v => v.Key, v => v.Value);
}
//NOTE: We cannot .Clear() because when we memberwise clone this will be the SAME
// instance as the one on the clone, so we need to create a new instance.
_propertyChangedInfo = null;
_propertyChangedInfo = new Dictionary<string, bool>();
}
public void ResetChangeTrackingCollections()
protected void ResetChangeTrackingCollections()
{
_propertyChangedInfo = null;
_lastPropertyChangedInfo = null;
_propertyChangedInfo = new Dictionary<string, bool>();
_lastPropertyChangedInfo = new Dictionary<string, bool>();
}
public void DisableChangeTracking()
protected void DisableChangeTracking()
{
_changeTrackingEnabled = false;
}
public void EnableChangeTracking()
protected void EnableChangeTracking()
{
_changeTrackingEnabled = true;
}
@@ -164,61 +158,60 @@ namespace Umbraco.Core.Models.EntityBase
/// Used by inheritors to set the value of properties, this will detect if the property value actually changed and if it did
/// it will ensure that the property has a dirty flag set.
/// </summary>
/// <param name="newVal"></param>
/// <param name="origVal"></param>
/// <param name="setValue"></param>
/// <param name="value"></param>
/// <param name="propertySelector"></param>
/// <returns>returns true if the value changed</returns>
/// <remarks>
/// This is required because we don't want a property to show up as "dirty" if the value is the same. For example, when we
/// save a document type, nearly all properties are flagged as dirty just because we've 'reset' them, but they are all set
/// This is required because we don't want a property to show up as "dirty" if the value is the same. For example, when we
/// save a document type, nearly all properties are flagged as dirty just because we've 'reset' them, but they are all set
/// to the same value, so it's really not dirty.
/// </remarks>
internal void SetPropertyValueAndDetectChanges<T>(T newVal, ref T origVal, PropertyInfo propertySelector)
internal bool SetPropertyValueAndDetectChanges<T>(Func<T, T> setValue, T value, PropertyInfo propertySelector)
{
if ((typeof(T) == typeof(string) == false) && TypeHelper.IsTypeAssignableFrom<IEnumerable>(typeof(T)))
{
throw new InvalidOperationException("This method does not support IEnumerable instances. For IEnumerable instances a manual custom equality check will be required");
}
SetPropertyValueAndDetectChanges(newVal, ref origVal, propertySelector, EqualityComparer<T>.Default);
return SetPropertyValueAndDetectChanges(setValue, value, propertySelector,
new DelegateEqualityComparer<T>(
//Standard Equals comparison
(arg1, arg2) => Equals(arg1, arg2),
arg => arg.GetHashCode()));
}
/// <summary>
/// Used by inheritors to set the value of properties, this will detect if the property value actually changed and if it did
/// it will ensure that the property has a dirty flag set.
/// </summary>
/// <param name="newVal"></param>
/// <param name="origVal"></param>
/// <param name="setValue"></param>
/// <param name="value"></param>
/// <param name="propertySelector"></param>
/// <param name="comparer">The equality comparer to use</param>
/// <returns>returns true if the value changed</returns>
/// <remarks>
/// This is required because we don't want a property to show up as "dirty" if the value is the same. For example, when we
/// save a document type, nearly all properties are flagged as dirty just because we've 'reset' them, but they are all set
/// This is required because we don't want a property to show up as "dirty" if the value is the same. For example, when we
/// save a document type, nearly all properties are flagged as dirty just because we've 'reset' them, but they are all set
/// to the same value, so it's really not dirty.
/// </remarks>
internal void SetPropertyValueAndDetectChanges<T>(T newVal, ref T origVal, PropertyInfo propertySelector, IEqualityComparer<T> comparer)
internal bool SetPropertyValueAndDetectChanges<T>(Func<T, T> setValue, T value, PropertyInfo propertySelector, IEqualityComparer<T> comparer)
{
//don't track changes, just set the value
if (_changeTrackingEnabled == false)
{
//set the original value
origVal = newVal;
}
else
{
//check changed
var changed = comparer.Equals(origVal, newVal) == false;
var initVal = value;
var newVal = setValue(value);
//set the original value
origVal = newVal;
//don't track changes, just set the value (above)
if (_changeTrackingEnabled == false) return false;
//raise the event if it was changed
if (changed)
{
OnPropertyChanged(propertySelector);
}
if (comparer.Equals(initVal, newVal) == false)
{
OnPropertyChanged(propertySelector);
return true;
}
return false;
}
}
}
+12 -12
View File
@@ -33,14 +33,8 @@ namespace Umbraco.Core.Models
_content = getFileContent != null ? null : string.Empty;
}
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo ContentSelector = ExpressionHelper.GetPropertyInfo<File, string>(x => x.Content);
public readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<File, string>(x => x.Path);
}
private static readonly PropertyInfo ContentSelector = ExpressionHelper.GetPropertyInfo<File, string>(x => x.Content);
private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<File, string>(x => x.Path);
private string _alias;
private string _name;
@@ -93,7 +87,11 @@ namespace Umbraco.Core.Models
_alias = null;
_name = null;
SetPropertyValueAndDetectChanges(SanitizePath(value), ref _path, Ps.Value.PathSelector);
SetPropertyValueAndDetectChanges(o =>
{
_path = SanitizePath(value);
return _path;
}, _path, PathSelector);
}
}
@@ -133,9 +131,11 @@ namespace Umbraco.Core.Models
}
set
{
SetPropertyValueAndDetectChanges(
value ?? string.Empty, // cannot set to null
ref _content, Ps.Value.ContentSelector);
SetPropertyValueAndDetectChanges(o =>
{
_content = value ?? string.Empty; // cannot set to null
return _content;
}, _content, ContentSelector);
}
}
+1 -1
View File
@@ -4,7 +4,7 @@ namespace Umbraco.Core.Models
{
/// <summary>
/// Defines a ContentType, which Media is based on
/// </summary>
/// </summary
public interface IMediaType : IContentTypeComposition
{
+1 -2
View File
@@ -1,5 +1,4 @@
using System;
using Semver;
using Semver;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
-37
View File
@@ -1,37 +0,0 @@
using System;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a redirect url.
/// </summary>
public interface IRedirectUrl : IAggregateRoot, IRememberBeingDirty
{
/// <summary>
/// Gets or sets the identifier of the content item.
/// </summary>
[DataMember]
int ContentId { get; set; }
/// <summary>
/// Gets or sets the unique key identifying the content item.
/// </summary>
[DataMember]
Guid ContentKey { get; set; }
/// <summary>
/// Gets or sets the redirect url creation date.
/// </summary>
[DataMember]
DateTime CreateDateUtc { get; set; }
/// <summary>
/// Gets or sets the redirect url route.
/// </summary>
/// <remarks>Is a proper Umbraco route eg /path/to/foo or 123/path/tofoo.</remarks>
[DataMember]
string Url { get; set; }
}
}
@@ -19,7 +19,7 @@ namespace Umbraco.Core.Models.Identity
Culture = Configuration.GlobalSettings.DefaultUILanguage;
}
public virtual async Task<ClaimsIdentity> GenerateUserIdentityAsync(BackOfficeUserManager<BackOfficeIdentityUser> manager)
public virtual async Task<ClaimsIdentity> GenerateUserIdentityAsync(BackOfficeUserManager manager)
{
// NOTE the authenticationType must match the umbraco one
// defined in CookieAuthenticationOptions.AuthenticationType
@@ -13,7 +13,6 @@ namespace Umbraco.Core.Models.Identity
public override void ConfigureMappings(IConfiguration config, ApplicationContext applicationContext)
{
config.CreateMap<IUser, BackOfficeIdentityUser>()
.ForMember(user => user.LastLoginDateUtc, expression => expression.MapFrom(user => user.LastLoginDate.ToUniversalTime()))
.ForMember(user => user.Email, expression => expression.MapFrom(user => user.Email))
.ForMember(user => user.Id, expression => expression.MapFrom(user => user.Id))
.ForMember(user => user.LockoutEndDateUtc, expression => expression.MapFrom(user => user.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?)null))
@@ -24,17 +24,12 @@ namespace Umbraco.Core.Models.Identity
///
/// </summary>
public IdentityUser()
{
{
this.Claims = new List<TClaim>();
this.Roles = new List<TRole>();
this.Logins = new List<TLogin>();
}
/// <summary>
/// Last login date
/// </summary>
public virtual DateTime? LastLoginDateUtc { get; set; }
/// <summary>
/// Email
///
+18 -9
View File
@@ -21,13 +21,8 @@ namespace Umbraco.Core.Models
IsoCode = isoCode;
}
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo IsoCodeSelector = ExpressionHelper.GetPropertyInfo<Language, string>(x => x.IsoCode);
public readonly PropertyInfo CultureNameSelector = ExpressionHelper.GetPropertyInfo<Language, string>(x => x.CultureName);
}
private static readonly PropertyInfo IsoCodeSelector = ExpressionHelper.GetPropertyInfo<Language, string>(x => x.IsoCode);
private static readonly PropertyInfo CultureNameSelector = ExpressionHelper.GetPropertyInfo<Language, string>(x => x.CultureName);
/// <summary>
/// Gets or sets the Iso Code for the Language
@@ -36,7 +31,14 @@ namespace Umbraco.Core.Models
public string IsoCode
{
get { return _isoCode; }
set { SetPropertyValueAndDetectChanges(value, ref _isoCode, Ps.Value.IsoCodeSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_isoCode = value;
return _isoCode;
}, _isoCode, IsoCodeSelector);
}
}
/// <summary>
@@ -46,7 +48,14 @@ namespace Umbraco.Core.Models
public string CultureName
{
get { return _cultureName; }
set { SetPropertyValueAndDetectChanges(value, ref _cultureName, Ps.Value.CultureNameSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_cultureName = value;
return _cultureName;
}, _cultureName, CultureNameSelector);
}
}
/// <summary>
+102 -30
View File
@@ -114,27 +114,22 @@ namespace Umbraco.Core.Models
private List<string> _addedProperties;
private List<string> _removedProperties;
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.Alias);
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.Name);
public readonly PropertyInfo UseInEditorSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.UseInEditor);
public readonly PropertyInfo CacheDurationSelector = ExpressionHelper.GetPropertyInfo<Macro, int>(x => x.CacheDuration);
public readonly PropertyInfo CacheByPageSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.CacheByPage);
public readonly PropertyInfo CacheByMemberSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.CacheByMember);
public readonly PropertyInfo DontRenderSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.DontRender);
public readonly PropertyInfo ControlPathSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.ControlType);
public readonly PropertyInfo ControlAssemblySelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.ControlAssembly);
public readonly PropertyInfo ScriptPathSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.ScriptPath);
public readonly PropertyInfo XsltPathSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.XsltPath);
public readonly PropertyInfo PropertiesSelector = ExpressionHelper.GetPropertyInfo<Macro, MacroPropertyCollection>(x => x.Properties);
}
private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.Alias);
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.Name);
private static readonly PropertyInfo UseInEditorSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.UseInEditor);
private static readonly PropertyInfo CacheDurationSelector = ExpressionHelper.GetPropertyInfo<Macro, int>(x => x.CacheDuration);
private static readonly PropertyInfo CacheByPageSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.CacheByPage);
private static readonly PropertyInfo CacheByMemberSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.CacheByMember);
private static readonly PropertyInfo DontRenderSelector = ExpressionHelper.GetPropertyInfo<Macro, bool>(x => x.DontRender);
private static readonly PropertyInfo ControlPathSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.ControlType);
private static readonly PropertyInfo ControlAssemblySelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.ControlAssembly);
private static readonly PropertyInfo ScriptPathSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.ScriptPath);
private static readonly PropertyInfo XsltPathSelector = ExpressionHelper.GetPropertyInfo<Macro, string>(x => x.XsltPath);
private static readonly PropertyInfo PropertiesSelector = ExpressionHelper.GetPropertyInfo<Macro, MacroPropertyCollection>(x => x.Properties);
void PropertiesChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(Ps.Value.PropertiesSelector);
OnPropertyChanged(PropertiesSelector);
if (e.Action == NotifyCollectionChangedAction.Add)
{
@@ -172,7 +167,7 @@ namespace Umbraco.Core.Models
/// <param name="e"></param>
void PropertyDataChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged(Ps.Value.PropertiesSelector);
OnPropertyChanged(PropertiesSelector);
}
public override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
@@ -209,7 +204,14 @@ namespace Umbraco.Core.Models
public string Alias
{
get { return _alias; }
set { SetPropertyValueAndDetectChanges(value.ToCleanString(CleanStringType.Alias), ref _alias, Ps.Value.AliasSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_alias = value.ToCleanString(CleanStringType.Alias);
return _alias;
}, _alias, AliasSelector);
}
}
/// <summary>
@@ -219,7 +221,14 @@ namespace Umbraco.Core.Models
public string Name
{
get { return _name; }
set { SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_name = value;
return _name;
}, _name, NameSelector);
}
}
/// <summary>
@@ -229,7 +238,14 @@ namespace Umbraco.Core.Models
public bool UseInEditor
{
get { return _useInEditor; }
set { SetPropertyValueAndDetectChanges(value, ref _useInEditor, Ps.Value.UseInEditorSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_useInEditor = value;
return _useInEditor;
}, _useInEditor, UseInEditorSelector);
}
}
/// <summary>
@@ -239,7 +255,14 @@ namespace Umbraco.Core.Models
public int CacheDuration
{
get { return _cacheDuration; }
set { SetPropertyValueAndDetectChanges(value, ref _cacheDuration, Ps.Value.CacheDurationSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_cacheDuration = value;
return _cacheDuration;
}, _cacheDuration, CacheDurationSelector);
}
}
/// <summary>
@@ -249,7 +272,14 @@ namespace Umbraco.Core.Models
public bool CacheByPage
{
get { return _cacheByPage; }
set { SetPropertyValueAndDetectChanges(value, ref _cacheByPage, Ps.Value.CacheByPageSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_cacheByPage = value;
return _cacheByPage;
}, _cacheByPage, CacheByPageSelector);
}
}
/// <summary>
@@ -259,7 +289,14 @@ namespace Umbraco.Core.Models
public bool CacheByMember
{
get { return _cacheByMember; }
set { SetPropertyValueAndDetectChanges(value, ref _cacheByMember, Ps.Value.CacheByMemberSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_cacheByMember = value;
return _cacheByMember;
}, _cacheByMember, CacheByMemberSelector);
}
}
/// <summary>
@@ -269,7 +306,14 @@ namespace Umbraco.Core.Models
public bool DontRender
{
get { return _dontRender; }
set { SetPropertyValueAndDetectChanges(value, ref _dontRender, Ps.Value.DontRenderSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_dontRender = value;
return _dontRender;
}, _dontRender, DontRenderSelector);
}
}
/// <summary>
@@ -279,7 +323,14 @@ namespace Umbraco.Core.Models
public string ControlType
{
get { return _scriptFile; }
set { SetPropertyValueAndDetectChanges(value, ref _scriptFile, Ps.Value.ControlPathSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_scriptFile = value;
return _scriptFile;
}, _scriptFile, ControlPathSelector);
}
}
/// <summary>
@@ -290,7 +341,14 @@ namespace Umbraco.Core.Models
public string ControlAssembly
{
get { return _scriptAssembly; }
set { SetPropertyValueAndDetectChanges(value, ref _scriptAssembly, Ps.Value.ControlAssemblySelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_scriptAssembly = value;
return _scriptAssembly;
}, _scriptAssembly, ControlAssemblySelector);
}
}
/// <summary>
@@ -301,7 +359,14 @@ namespace Umbraco.Core.Models
public string ScriptPath
{
get { return _scriptPath; }
set { SetPropertyValueAndDetectChanges(value, ref _scriptPath, Ps.Value.ScriptPathSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_scriptPath = value;
return _scriptPath;
}, _scriptPath, ScriptPathSelector);
}
}
/// <summary>
@@ -312,7 +377,14 @@ namespace Umbraco.Core.Models
public string XsltPath
{
get { return _xslt; }
set { SetPropertyValueAndDetectChanges(value, ref _xslt, Ps.Value.XsltPathSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_xslt = value;
return _xslt;
}, _xslt, XsltPathSelector);
}
}
/// <summary>
+52 -18
View File
@@ -72,16 +72,11 @@ namespace Umbraco.Core.Models
private int _id;
private string _editorAlias;
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, string>(x => x.Alias);
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, string>(x => x.Name);
public readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, int>(x => x.SortOrder);
public readonly PropertyInfo IdSelector = ExpressionHelper.GetPropertyInfo<Entity, int>(x => x.Id);
public readonly PropertyInfo PropertyTypeSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, string>(x => x.EditorAlias);
}
private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, string>(x => x.Alias);
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, string>(x => x.Name);
private static readonly PropertyInfo SortOrderSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, int>(x => x.SortOrder);
private static readonly PropertyInfo IdSelector = ExpressionHelper.GetPropertyInfo<Entity, int>(x => x.Id);
private static readonly PropertyInfo PropertyTypeSelector = ExpressionHelper.GetPropertyInfo<MacroProperty, string>(x => x.EditorAlias);
/// <summary>
/// Gets or sets the Alias of the Property
@@ -90,7 +85,14 @@ namespace Umbraco.Core.Models
public int Id
{
get { return _id; }
set { SetPropertyValueAndDetectChanges(value, ref _id, Ps.Value.IdSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_id = value;
return _alias;
}, _alias, IdSelector);
}
}
/// <summary>
@@ -100,7 +102,14 @@ namespace Umbraco.Core.Models
public string Alias
{
get { return _alias; }
set { SetPropertyValueAndDetectChanges(value, ref _alias, Ps.Value.AliasSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_alias = value;
return _alias;
}, _alias, AliasSelector);
}
}
/// <summary>
@@ -110,7 +119,14 @@ namespace Umbraco.Core.Models
public string Name
{
get { return _name; }
set { SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_name = value;
return _name;
}, _name, NameSelector);
}
}
/// <summary>
@@ -120,7 +136,14 @@ namespace Umbraco.Core.Models
public int SortOrder
{
get { return _sortOrder; }
set { SetPropertyValueAndDetectChanges(value, ref _sortOrder, Ps.Value.SortOrderSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_sortOrder = value;
return _sortOrder;
}, _sortOrder, SortOrderSelector);
}
}
/// <summary>
@@ -136,10 +159,21 @@ namespace Umbraco.Core.Models
get { return _editorAlias; }
set
{
//try to get the new mapped parameter editor
var mapped = LegacyParameterEditorAliasConverter.GetNewAliasFromLegacyAlias(value, false);
var newVal = mapped.IsNullOrWhiteSpace() == false ? mapped : value;
SetPropertyValueAndDetectChanges(newVal, ref _editorAlias, Ps.Value.PropertyTypeSelector);
SetPropertyValueAndDetectChanges(o =>
{
//try to get the new mapped parameter editor
var mapped = LegacyParameterEditorAliasConverter.GetNewAliasFromLegacyAlias(value, false);
if (mapped.IsNullOrWhiteSpace() == false)
{
_editorAlias = mapped;
}
else
{
_editorAlias = value;
}
return _editorAlias;
}, _editorAlias, PropertyTypeSelector);
}
}
+36 -13
View File
@@ -109,15 +109,10 @@ namespace Umbraco.Core.Models
IsApproved = true;
}
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo UsernameSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.Username);
public readonly PropertyInfo EmailSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.Email);
public readonly PropertyInfo PasswordSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.RawPasswordValue);
public readonly PropertyInfo ProviderUserKeySelector = ExpressionHelper.GetPropertyInfo<Member, object>(x => x.ProviderUserKey);
}
private static readonly PropertyInfo UsernameSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.Username);
private static readonly PropertyInfo EmailSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.Email);
private static readonly PropertyInfo PasswordSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.RawPasswordValue);
private static readonly PropertyInfo ProviderUserKeySelector = ExpressionHelper.GetPropertyInfo<Member, object>(x => x.ProviderUserKey);
/// <summary>
/// Gets or sets the Username
@@ -126,7 +121,14 @@ namespace Umbraco.Core.Models
public string Username
{
get { return _username; }
set { SetPropertyValueAndDetectChanges(value, ref _username, Ps.Value.UsernameSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_username = value;
return _username;
}, _username, UsernameSelector);
}
}
/// <summary>
@@ -136,7 +138,14 @@ namespace Umbraco.Core.Models
public string Email
{
get { return _email; }
set { SetPropertyValueAndDetectChanges(value, ref _email, Ps.Value.EmailSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_email = value;
return _email;
}, _email, EmailSelector);
}
}
/// <summary>
@@ -146,7 +155,14 @@ namespace Umbraco.Core.Models
public string RawPasswordValue
{
get { return _rawPasswordValue; }
set { SetPropertyValueAndDetectChanges(value, ref _rawPasswordValue, Ps.Value.PasswordSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_rawPasswordValue = value;
return _rawPasswordValue;
}, _rawPasswordValue, PasswordSelector);
}
}
/// <summary>
@@ -474,7 +490,14 @@ namespace Umbraco.Core.Models
{
return _providerUserKey;
}
set { SetPropertyValueAndDetectChanges(value, ref _providerUserKey, Ps.Value.ProviderUserKeySelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_providerUserKey = value;
return _providerUserKey;
}, _providerUserKey, ProviderUserKeySelector);
}
}
+21 -15
View File
@@ -21,13 +21,8 @@ namespace Umbraco.Core.Models
private string _name;
private int _creatorId;
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<MemberGroup, string>(x => x.Name);
public readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo<MemberGroup, int>(x => x.CreatorId);
}
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<MemberGroup, string>(x => x.Name);
private static readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo<MemberGroup, int>(x => x.CreatorId);
[DataMember]
public string Name
@@ -35,22 +30,33 @@ namespace Umbraco.Core.Models
get { return _name; }
set
{
if (_name != value)
SetPropertyValueAndDetectChanges(o =>
{
//if the name has changed, add the value to the additional data,
//this is required purely for event handlers to know the previous name of the group
//so we can keep the public access up to date.
AdditionalData["previousName"] = _name;
}
if (_name != value)
{
//if the name has changed, add the value to the additional data,
//this is required purely for event handlers to know the previous name of the group
//so we can keep the public access up to date.
AdditionalData["previousName"] = _name;
}
SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector);
_name = value;
return _name;
}, _name, NameSelector);
}
}
public int CreatorId
{
get { return _creatorId; }
set { SetPropertyValueAndDetectChanges(value, ref _creatorId, Ps.Value.CreatorIdSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_creatorId = value;
return _creatorId;
}, _creatorId, CreatorIdSelector);
}
}
public IDictionary<string, object> AdditionalData { get; private set; }
+8 -11
View File
@@ -30,12 +30,7 @@ namespace Umbraco.Core.Models
MemberTypePropertyTypes = new Dictionary<string, MemberTypePropertyProfileAccess>();
}
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private class PropertySelectors
{
public readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<MemberType, string>(x => x.Alias);
}
private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<MemberType, string>(x => x.Alias);
/// <summary>
/// The Alias of the ContentType
@@ -55,11 +50,13 @@ namespace Umbraco.Core.Models
// .ToCleanString(CleanStringType.Alias | CleanStringType.UmbracoCase)
// Need to ask Stephen
var newVal = value == "_umbracoSystemDefaultProtectType"
? value
: (value == null ? string.Empty : value.ToSafeAlias());
SetPropertyValueAndDetectChanges(newVal, ref _alias, Ps.Value.AliasSelector);
SetPropertyValueAndDetectChanges(o =>
{
_alias = value == "_umbracoSystemDefaultProtectType"
? value
: (value == null ? string.Empty : value.ToSafeAlias() );
return _alias;
}, _alias, AliasSelector);
}
}
+153 -42
View File
@@ -77,32 +77,27 @@ namespace Umbraco.Core.Models.Membership
private bool _defaultToLiveEditing;
private static readonly Lazy<PropertySelectors> Ps = new Lazy<PropertySelectors>();
private static readonly PropertyInfo FailedPasswordAttemptsSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.FailedPasswordAttempts);
private static readonly PropertyInfo LastLockoutDateSelector = ExpressionHelper.GetPropertyInfo<User, DateTime>(x => x.LastLockoutDate);
private static readonly PropertyInfo LastLoginDateSelector = ExpressionHelper.GetPropertyInfo<User, DateTime>(x => x.LastLoginDate);
private static readonly PropertyInfo LastPasswordChangeDateSelector = ExpressionHelper.GetPropertyInfo<User, DateTime>(x => x.LastPasswordChangeDate);
private class PropertySelectors
{
public readonly PropertyInfo FailedPasswordAttemptsSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.FailedPasswordAttempts);
public readonly PropertyInfo LastLockoutDateSelector = ExpressionHelper.GetPropertyInfo<User, DateTime>(x => x.LastLockoutDate);
public readonly PropertyInfo LastLoginDateSelector = ExpressionHelper.GetPropertyInfo<User, DateTime>(x => x.LastLoginDate);
public readonly PropertyInfo LastPasswordChangeDateSelector = ExpressionHelper.GetPropertyInfo<User, DateTime>(x => x.LastPasswordChangeDate);
private static readonly PropertyInfo SecurityStampSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.SecurityStamp);
private static readonly PropertyInfo SessionTimeoutSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.SessionTimeout);
private static readonly PropertyInfo StartContentIdSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.StartContentId);
private static readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.StartMediaId);
private static readonly PropertyInfo AllowedSectionsSelector = ExpressionHelper.GetPropertyInfo<User, IEnumerable<string>>(x => x.AllowedSections);
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Name);
private static readonly PropertyInfo UsernameSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Username);
private static readonly PropertyInfo EmailSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Email);
private static readonly PropertyInfo PasswordSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.RawPasswordValue);
private static readonly PropertyInfo IsLockedOutSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.IsLockedOut);
private static readonly PropertyInfo IsApprovedSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.IsApproved);
private static readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Language);
public readonly PropertyInfo SecurityStampSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.SecurityStamp);
public readonly PropertyInfo SessionTimeoutSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.SessionTimeout);
public readonly PropertyInfo StartContentIdSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.StartContentId);
public readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.StartMediaId);
public readonly PropertyInfo AllowedSectionsSelector = ExpressionHelper.GetPropertyInfo<User, IEnumerable<string>>(x => x.AllowedSections);
public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Name);
public readonly PropertyInfo UsernameSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Username);
public readonly PropertyInfo EmailSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Email);
public readonly PropertyInfo PasswordSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.RawPasswordValue);
public readonly PropertyInfo IsLockedOutSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.IsLockedOut);
public readonly PropertyInfo IsApprovedSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.IsApproved);
public readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Language);
public readonly PropertyInfo DefaultToLiveEditingSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.DefaultToLiveEditing);
public readonly PropertyInfo UserTypeSelector = ExpressionHelper.GetPropertyInfo<User, IUserType>(x => x.UserType);
}
private static readonly PropertyInfo DefaultToLiveEditingSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.DefaultToLiveEditing);
private static readonly PropertyInfo UserTypeSelector = ExpressionHelper.GetPropertyInfo<User, IUserType>(x => x.UserType);
#region Implementation of IMembershipUser
@@ -118,61 +113,124 @@ namespace Umbraco.Core.Models.Membership
public string Username
{
get { return _username; }
set { SetPropertyValueAndDetectChanges(value, ref _username, Ps.Value.UsernameSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_username = value;
return _username;
}, _username, UsernameSelector);
}
}
[DataMember]
public string Email
{
get { return _email; }
set { SetPropertyValueAndDetectChanges(value, ref _email, Ps.Value.EmailSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_email = value;
return _email;
}, _email, EmailSelector);
}
}
[DataMember]
public string RawPasswordValue
{
get { return _rawPasswordValue; }
set { SetPropertyValueAndDetectChanges(value, ref _rawPasswordValue, Ps.Value.PasswordSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_rawPasswordValue = value;
return _rawPasswordValue;
}, _rawPasswordValue, PasswordSelector);
}
}
[DataMember]
public bool IsApproved
{
get { return _isApproved; }
set { SetPropertyValueAndDetectChanges(value, ref _isApproved, Ps.Value.IsApprovedSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_isApproved = value;
return _isApproved;
}, _isApproved, IsApprovedSelector);
}
}
[IgnoreDataMember]
public bool IsLockedOut
{
get { return _isLockedOut; }
set { SetPropertyValueAndDetectChanges(value, ref _isLockedOut, Ps.Value.IsLockedOutSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_isLockedOut = value;
return _isLockedOut;
}, _isLockedOut, IsLockedOutSelector);
}
}
[IgnoreDataMember]
public DateTime LastLoginDate
{
get { return _lastLoginDate; }
set { SetPropertyValueAndDetectChanges(value, ref _lastLoginDate, Ps.Value.LastLoginDateSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_lastLoginDate = value;
return _lastLoginDate;
}, _lastLoginDate, LastLoginDateSelector);
}
}
[IgnoreDataMember]
public DateTime LastPasswordChangeDate
{
get { return _lastPasswordChangedDate; }
set { SetPropertyValueAndDetectChanges(value, ref _lastPasswordChangedDate, Ps.Value.LastPasswordChangeDateSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_lastPasswordChangedDate = value;
return _lastPasswordChangedDate;
}, _lastPasswordChangedDate, LastPasswordChangeDateSelector);
}
}
[IgnoreDataMember]
public DateTime LastLockoutDate
{
get { return _lastLockoutDate; }
set { SetPropertyValueAndDetectChanges(value, ref _lastLockoutDate, Ps.Value.LastLockoutDateSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_lastLockoutDate = value;
return _lastLockoutDate;
}, _lastLockoutDate, LastLockoutDateSelector);
}
}
[IgnoreDataMember]
public int FailedPasswordAttempts
{
get { return _failedLoginAttempts; }
set { SetPropertyValueAndDetectChanges(value, ref _failedLoginAttempts, Ps.Value.FailedPasswordAttemptsSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_failedLoginAttempts = value;
return _failedLoginAttempts;
}, _failedLoginAttempts, FailedPasswordAttemptsSelector);
}
}
//TODO: Figure out how to support all of this! - we cannot have NotImplementedExceptions because these get used by the IMembershipMemberService<IUser> service so
@@ -193,7 +251,14 @@ namespace Umbraco.Core.Models.Membership
public string Name
{
get { return _name; }
set { SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_name = value;
return _name;
}, _name, NameSelector);
}
}
public IEnumerable<string> AllowedSections
@@ -229,7 +294,14 @@ namespace Umbraco.Core.Models.Membership
public string SecurityStamp
{
get { return _securityStamp; }
set { SetPropertyValueAndDetectChanges(value, ref _securityStamp, Ps.Value.SecurityStampSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_securityStamp = value;
return _securityStamp;
}, _securityStamp, SecurityStampSelector);
}
}
/// <summary>
@@ -258,7 +330,14 @@ namespace Umbraco.Core.Models.Membership
public int SessionTimeout
{
get { return _sessionTimeout; }
set { SetPropertyValueAndDetectChanges(value, ref _sessionTimeout, Ps.Value.SessionTimeoutSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_sessionTimeout = value;
return _sessionTimeout;
}, _sessionTimeout, SessionTimeoutSelector);
}
}
/// <summary>
@@ -271,7 +350,14 @@ namespace Umbraco.Core.Models.Membership
public int StartContentId
{
get { return _startContentId; }
set { SetPropertyValueAndDetectChanges(value, ref _startContentId, Ps.Value.StartContentIdSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_startContentId = value;
return _startContentId;
}, _startContentId, StartContentIdSelector);
}
}
/// <summary>
@@ -284,14 +370,28 @@ namespace Umbraco.Core.Models.Membership
public int StartMediaId
{
get { return _startMediaId; }
set { SetPropertyValueAndDetectChanges(value, ref _startMediaId, Ps.Value.StartMediaIdSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_startMediaId = value;
return _startMediaId;
}, _startMediaId, StartMediaIdSelector);
}
}
[DataMember]
public string Language
{
get { return _language; }
set { SetPropertyValueAndDetectChanges(value, ref _language, Ps.Value.LanguageSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_language = value;
return _language;
}, _language, LanguageSelector);
}
}
//TODO: This should be a private set
@@ -306,7 +406,14 @@ namespace Umbraco.Core.Models.Membership
internal bool DefaultToLiveEditing
{
get { return _defaultToLiveEditing; }
set { SetPropertyValueAndDetectChanges(value, ref _defaultToLiveEditing, Ps.Value.DefaultToLiveEditingSelector); }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_defaultToLiveEditing = value;
return _defaultToLiveEditing;
}, _defaultToLiveEditing, DefaultToLiveEditingSelector);
}
}
[IgnoreDataMember]
@@ -320,7 +427,11 @@ namespace Umbraco.Core.Models.Membership
throw new InvalidOperationException("Cannot assign a User Type that has not been persisted");
}
SetPropertyValueAndDetectChanges(value, ref _userType, Ps.Value.UserTypeSelector);
SetPropertyValueAndDetectChanges(o =>
{
_userType = value;
return _userType;
}, _userType, UserTypeSelector);
}
}
@@ -346,7 +457,7 @@ namespace Umbraco.Core.Models.Membership
/// <param name="e"></param>
void SectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(Ps.Value.AllowedSectionsSelector);
OnPropertyChanged(AllowedSectionsSelector);
if (e.Action == NotifyCollectionChangedAction.Add)
{

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