Merge remote-tracking branch 'origin/v8/dev' into v8/feature/7133-do-not-paste-keys-in-nested-content
This commit is contained in:
+10
-6
@@ -13,7 +13,7 @@
|
||||
*.png binary
|
||||
*.gif binary
|
||||
|
||||
*.cs text=auto diff=csharp
|
||||
*.cs text=auto diff=csharp
|
||||
*.vb text=auto
|
||||
*.c text=auto
|
||||
*.cpp text=auto
|
||||
@@ -41,9 +41,13 @@
|
||||
*.fs text=auto
|
||||
*.fsx text=auto
|
||||
*.hs text=auto
|
||||
*.json text=auto
|
||||
*.xml text=auto
|
||||
|
||||
*.csproj text=auto merge=union
|
||||
*.vbproj text=auto merge=union
|
||||
*.fsproj text=auto merge=union
|
||||
*.dbproj text=auto merge=union
|
||||
*.sln text=auto eol=crlf merge=union
|
||||
*.csproj text=auto merge=union
|
||||
*.vbproj text=auto merge=union
|
||||
*.fsproj text=auto merge=union
|
||||
*.dbproj text=auto merge=union
|
||||
*.sln text=auto eol=crlf merge=union
|
||||
|
||||
*.gitattributes text=auto
|
||||
|
||||
@@ -43,6 +43,8 @@ If you only see a build.bat-file, you're probably on the wrong branch. If you sw
|
||||
|
||||
You might run into [Powershell quirks](#powershell-quirks).
|
||||
|
||||
If it runs without errors; Hooray! Now you can continue with [the next step](CONTRIBUTING.md#how-do-i-begin) and open the solution and build it.
|
||||
|
||||
### Build Infrastructure
|
||||
|
||||
The Umbraco Build infrastructure relies on a PowerShell object. The object can be retrieved with:
|
||||
|
||||
+19
-17
@@ -22,13 +22,13 @@ This project and everyone participating in it, is governed by the [our Code of C
|
||||
|
||||
[Reviews](#reviews)
|
||||
* [Styleguides](#styleguides)
|
||||
* [The PR team](#the-pr-team)
|
||||
* [The Core Contributors](#the-core-contributors-team)
|
||||
* [Questions?](#questions)
|
||||
|
||||
[Working with the code](#working-with-the-code)
|
||||
* [Building Umbraco from source code](#building-umbraco-from-source-code)
|
||||
* [Working with the source code](#working-with-the-source-code)
|
||||
* [Making changes after the PR was opened](#making-changes-after-the-pr-was-opened)
|
||||
* [Making changes after the PR is open](#making-changes-after-the-pr-is-open)
|
||||
* [Which branch should I target for my contributions?](#which-branch-should-i-target-for-my-contributions)
|
||||
* [Keeping your Umbraco fork in sync with the main repository](#keeping-your-umbraco-fork-in-sync-with-the-main-repository)
|
||||
|
||||
@@ -60,19 +60,19 @@ Great question! The short version goes like this:
|
||||
|
||||

|
||||
|
||||
* **Switch to the correct branch** - switch to the v8-dev branch
|
||||
* **Switch to the correct branch** - switch to the `v8/contrib` branch
|
||||
* **Build** - build your fork of Umbraco locally as described in [building Umbraco from source code](BUILD.md)
|
||||
* **Change** - make your changes, experiment, have fun, explore and learn, and don't be afraid. We welcome all contributions and will [happily give feedback](#questions)
|
||||
* **Commit** - done? Yay! 🎉 **Important:** create a new branch now and name it after the issue you're fixing, we usually follow the format: `temp-12345`. This means it's a temporary branch for the particular issue you're working on, in this case `12345`. When you have a branch, commit your changes. Don't commit to `v8/dev`, create a new branch first.
|
||||
* **Commit** - done? Yay! 🎉 **Important:** create a new branch now and name it after the issue you're fixing, we usually follow the format: `temp-12345`. This means it's a temporary branch for the particular issue you're working on, in this case `12345`. When you have a branch, commit your changes. Don't commit to `v8/contrib`, create a new branch first.
|
||||
* **Push** - great, now you can push the changes up to your fork on GitHub
|
||||
* **Create pull request** - exciting! You're ready to show us your changes (or not quite ready, you just need some feedback to progress - you can now make use of GitHub's draft pull request status, detailed [here] (https://github.blog/2019-02-14-introducing-draft-pull-requests/)). GitHub has picked up on the new branch you've pushed and will offer to create a Pull Request. Click that green button and away you go.
|
||||
* **Create pull request** - exciting! You're ready to show us your changes (or not quite ready, you just need some feedback to progress - you can now make use of GitHub's draft pull request status, detailed [here](https://github.blog/2019-02-14-introducing-draft-pull-requests/)). GitHub has picked up on the new branch you've pushed and will offer to create a Pull Request. Click that green button and away you go.
|
||||
|
||||

|
||||
|
||||
### Pull requests
|
||||
The most successful pull requests usually look a like this:
|
||||
|
||||
* Fill in the required template, linking your pull request to an issue on the [issue tracker,](https://github.com/umbraco/Umbraco-CMS/issues) if applicable.
|
||||
* Fill in the required template (shown when starting a PR on GitHub), and link your pull request to an issue on the [issue tracker,](https://github.com/umbraco/Umbraco-CMS/issues) if applicable.
|
||||
* Include screenshots and animated GIFs in your pull request whenever possible.
|
||||
* Unit tests, while optional, are awesome. Thank you!
|
||||
* New code is commented with documentation from which [the reference documentation](https://our.umbraco.com/documentation/Reference/) is generated.
|
||||
@@ -98,20 +98,21 @@ To be honest, we don't like rules very much. We trust you have the best of inten
|
||||
|
||||
That said, the Umbraco development team likes to follow the hints that ReSharper gives us (no problem if you don't have this installed) and we've added a `.editorconfig` file so that Visual Studio knows what to do with whitespace, line endings, etc.
|
||||
|
||||
### The PR team
|
||||
### The Core Contributors team
|
||||
|
||||
The pull request team consists of one member of Umbraco HQ, [Sebastiaan](https://github.com/nul800sebastiaan), who gets assistance from the following community members who have comitted to volunteering their free time:
|
||||
The Core Contributors team consists of one member of Umbraco HQ, [Sebastiaan](https://github.com/nul800sebastiaan), who gets assistance from the following community members who have comitted to volunteering their free time:
|
||||
|
||||
- [Anders Bjerner](https://github.com/abjerner)
|
||||
- [Dave Woestenborghs](https://github.com/dawoe)
|
||||
- [Emma Burstow](https://github.com/emmaburstow)
|
||||
- [Poornima Nayar](https://github.com/poornimanayar)
|
||||
- [Kenn Jacobsen](https://twitter.com/KennJacobsen_DK)
|
||||
|
||||
|
||||
These wonderful people aim to provide you with a first reply to your PR, review and test out your changes and on occasions, they might ask more questions. If they are happy with your work, they'll let Umbraco HQ know by approving the PR. Hq will have final sign-off and will check the work again before it is merged.
|
||||
|
||||
### Questions?
|
||||
|
||||
You can get in touch with [the PR team](#the-pr-team) in multiple ways; we love open conversations and we are a friendly bunch. No question you have is stupid. Any question you have usually helps out multiple people with the same question. Ask away:
|
||||
You can get in touch with [the core contributors team](#the-core-contributors-team) in multiple ways; we love open conversations and we are a friendly bunch. No question you have is stupid. Any question you have usually helps out multiple people with the same question. Ask away:
|
||||
|
||||
- If there's an existing issue on the issue tracker then that's a good place to leave questions and discuss how to start or move forward.
|
||||
- Unsure where to start? Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.com/forum/contributing-to-umbraco-cms/) forum. The team monitors that one closely, so one of us will be on hand and ready to point you in the right direction.
|
||||
@@ -122,9 +123,10 @@ You can get in touch with [the PR team](#the-pr-team) in multiple ways; we love
|
||||
|
||||
In order to build the Umbraco source code locally, first make sure you have the following installed.
|
||||
|
||||
* Visual Studio 2017 v15.9.7+
|
||||
* Node v10+
|
||||
* npm v6.4.1+
|
||||
* [Visual Studio 2017 v15.9.7+](https://visualstudio.microsoft.com/vs/)
|
||||
* [Node.js v10+](https://nodejs.org/en/download/)
|
||||
* npm v6.4.1+ (installed with Node.js)
|
||||
* [Git command line](https://git-scm.com/download/)
|
||||
|
||||
The easiest way to get started is to open `src\umbraco.sln` in Visual Studio 2017 (version 15.9.7 or higher, [the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
|
||||
|
||||
@@ -158,7 +160,7 @@ To find the general areas for something you're looking to fix or improve, have a
|
||||
|
||||
### Which branch should I target for my contributions?
|
||||
|
||||
We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-flow/), but don't worry if you are not familiar with it. The most important thing you need to know is that when you fork the Umbraco repository, the default branch is set to something, usually `v8/dev`. If you are working on v8, this is the branch you should be targetting. For v7 contributions, please target 'v7/dev'.
|
||||
We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-flow/), but don't worry if you are not familiar with it. The most important thing you need to know is that when you fork the Umbraco repository, the default branch is set to something, usually `v8/contrib`. If you are working on v8, this is the branch you should be targetting. For v7 contributions, please target 'v7/dev'.
|
||||
|
||||
Please note: we are no longer accepting features for v7 but will continue to merge bug fixes as and when they arise.
|
||||
|
||||
@@ -184,13 +186,13 @@ Then when you want to get the changes from the main repository:
|
||||
|
||||
```
|
||||
git fetch upstream
|
||||
git rebase upstream/v8/dev
|
||||
git rebase upstream/v8/contrib
|
||||
```
|
||||
|
||||
In this command we're syncing with the `v8/dev` branch, but you can of course choose another one if needed.
|
||||
In this command we're syncing with the `v8/contrib` branch, but you can of course choose another one if needed.
|
||||
|
||||
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
|
||||
|
||||
### And finally
|
||||
|
||||
We welcome all kinds of contributions to this repository. If you don't feel you'd like to make code changes here, you can visit our [documentation repository](https://github.com/umbraco/UmbracoDocs) and use your experience to contribute to making the docs we have, even better. We also encourage community members to feel free to comment on others' pull requests and issues - the expertise we have is not limited to the PR team and HQ. So, if you see something on the issue tracker or pull requests you feel you can add to, please don't be shy.
|
||||
We welcome all kinds of contributions to this repository. If you don't feel you'd like to make code changes here, you can visit our [documentation repository](https://github.com/umbraco/UmbracoDocs) and use your experience to contribute to making the docs we have, even better. We also encourage community members to feel free to comment on others' pull requests and issues - the expertise we have is not limited to the Core Contributors and HQ. So, if you see something on the issue tracker or pull requests you feel you can add to, please don't be shy.
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# [Umbraco CMS](https://umbraco.com) · [](../LICENSE.md) [](https://umbraco.visualstudio.com/Umbraco%20Cms/_build?definitionId=75) [](CONTRIBUTING.md) [](https://twitter.com/intent/follow?screen_name=umbraco)
|
||||
# [Umbraco CMS](https://umbraco.com) · [](../LICENSE.md) [](https://umbraco.visualstudio.com/Umbraco%20Cms/_build?definitionId=75) [](CONTRIBUTING.md) [](https://twitter.com/intent/follow?screen_name=umbraco)
|
||||
|
||||
Umbraco is the friendliest, most flexible and fastest growing ASP.NET CMS, and used by more than 500,000 websites worldwide. Our mission is to help you deliver delightful digital experiences by making Umbraco friendly, simpler and social.
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 24 KiB |
+11
@@ -55,6 +55,7 @@ App_Data/TEMP/*
|
||||
src/Umbraco.Web.UI/[Cc]ss/*
|
||||
src/Umbraco.Web.UI/App_Code/*
|
||||
src/Umbraco.Web.UI/App_Data/*
|
||||
src/Umbraco.Web.UI/data/*
|
||||
src/Umbraco.Tests/App_Data/*
|
||||
src/Umbraco.Web.UI/[Mm]edia/*
|
||||
src/Umbraco.Web.UI/[Mm]aster[Pp]ages/*
|
||||
@@ -99,6 +100,9 @@ src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.dev.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/canvasdesigner.*.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/navigation.controller.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.controller.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/utilities.js
|
||||
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js
|
||||
@@ -163,3 +167,10 @@ build/temp/
|
||||
# eof
|
||||
/src/Umbraco.Web.UI.Client/TESTS-*.xml
|
||||
/src/ApiDocs/api/*
|
||||
|
||||
# Acceptance tests
|
||||
cypress.env.json
|
||||
/src/Umbraco.Tests.AcceptanceTest/cypress/support/chainable.ts
|
||||
/src/Umbraco.Tests.AcceptanceTest/package-lock.json
|
||||
/src/Umbraco.Tests.AcceptanceTest/cypress/videos/
|
||||
/src/Umbraco.Tests.AcceptanceTest/cypress/screenshots/
|
||||
|
||||
@@ -7,6 +7,5 @@
|
||||
-->
|
||||
<packageSources>
|
||||
<add key="UmbracoCoreMyGet" value="https://www.myget.org/F/umbracocore/api/v3/index.json" />
|
||||
<add key="ExamineAppVeyor" value="https://ci.appveyor.com/nuget/examine-f73l6qv0oqfh/" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="UmbracoCms.Core" version="[$version$]" />
|
||||
<dependency id="ClientDependency" version="[1.9.8,1.999999)" />
|
||||
<dependency id="ClientDependency" version="[1.9.9,1.999999)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.9.3,1.999999)" />
|
||||
<dependency id="CSharpTest.Net.Collections" version="[14.906.1403.1082,14.999999)" />
|
||||
<dependency id="Examine" version="[1.0.1,1.999999)" />
|
||||
<dependency id="Examine" version="[1.0.2,1.999999)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.8.14,1.999999)" />
|
||||
<dependency id="ImageProcessor" version="[2.7.0.100,2.999999)" />
|
||||
<dependency id="LightInject.Mvc" version="[2.0.0,2.999999)" />
|
||||
@@ -52,14 +52,17 @@
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.dll" target="lib\net472\Umbraco.Web.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.dll" target="lib\net472\Umbraco.Web.UI.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.dll" target="lib\net472\Umbraco.Examine.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.ModelsBuilder.Embedded.dll" target="lib\net472\Umbraco.ModelsBuilder.Embedded.dll" />
|
||||
|
||||
<!-- docs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.xml" target="lib\net472\Umbraco.Web.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.xml" target="lib\net472\Umbraco.Web.UI.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.xml" target="lib\net472\Umbraco.Examine.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.ModelsBuilder.Embedded.xml" target="lib\net472\Umbraco.ModelsBuilder.Embedded.xml" />
|
||||
|
||||
<!-- symbols -->
|
||||
<file src="$BuildTmp$\bin\Umbraco.Web.pdb" target="lib\net472\Umbraco.Web.pdb" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Examine.pdb" target="lib\net472\Umbraco.Examine.pdb" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.ModelsBuilder.Embedded.pdb" target="lib\net472\Umbraco.ModelsBuilder.Embedded.pdb" />
|
||||
</files>
|
||||
</package>
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.4.0, 2.999999)" />
|
||||
<dependency id="Umbraco.ModelsBuilder.Ui" version="[8.1.0]" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.10.0.100,4.999999)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.5.0.100,2.999999)" />
|
||||
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[2.0.1,2.999999)" />
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(factoryType)" xdt:Transform="SetAttributes(factoryType)" />
|
||||
<pages pageBaseType="System.Web.Mvc.WebViewPage">
|
||||
<namespaces>
|
||||
<add namespace="Umbraco.Web.PublishedContentModels" xdt:Transform="InsertIfMissing" />
|
||||
<add namespace="Umbraco.Web.PublishedModels" xdt:Transform="InsertIfMissing" />
|
||||
</namespaces>
|
||||
</pages>
|
||||
</system.web.webPages.razor>
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
# get NuGet
|
||||
$cache = 4
|
||||
$nuget = "$scriptTemp\nuget.exe"
|
||||
# ensure the correct NuGet-source is used. This one is used by Umbraco
|
||||
$nugetsourceUmbraco = "https://www.myget.org/F/umbracocore/api/v3/index.json"
|
||||
if (-not $local)
|
||||
{
|
||||
$source = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
|
||||
@@ -61,7 +63,7 @@
|
||||
# get the build system
|
||||
if (-not $local)
|
||||
{
|
||||
$params = "-OutputDirectory", $scriptTemp, "-Verbosity", "quiet", "-PreRelease"
|
||||
$params = "-OutputDirectory", $scriptTemp, "-Verbosity", "quiet", "-PreRelease", "-Source", $nugetsourceUmbraco
|
||||
&$nuget install Umbraco.Build @params
|
||||
if (-not $?) { throw "Failed to download Umbraco.Build." }
|
||||
}
|
||||
|
||||
+7
-3
@@ -375,11 +375,14 @@
|
||||
|
||||
})
|
||||
|
||||
$nugetsourceUmbraco = "https://api.nuget.org/v3/index.json"
|
||||
|
||||
$ubuild.DefineMethod("RestoreNuGet",
|
||||
{
|
||||
Write-Host "Restore NuGet"
|
||||
Write-Host "Logging to $($this.BuildTemp)\nuget.restore.log"
|
||||
&$this.BuildEnv.NuGet restore "$($this.SolutionRoot)\src\Umbraco.sln" > "$($this.BuildTemp)\nuget.restore.log"
|
||||
$params = "-Source", $nugetsourceUmbraco
|
||||
&$this.BuildEnv.NuGet restore "$($this.SolutionRoot)\src\Umbraco.sln" > "$($this.BuildTemp)\nuget.restore.log" @params
|
||||
if (-not $?) { throw "Failed to restore NuGet packages." }
|
||||
})
|
||||
|
||||
@@ -456,10 +459,10 @@
|
||||
$ubuild.DefineMethod("PrepareAngularDocs",
|
||||
{
|
||||
Write-Host "Prepare Angular Documentation"
|
||||
|
||||
|
||||
$src = "$($this.SolutionRoot)\src"
|
||||
$out = $this.BuildOutput
|
||||
|
||||
|
||||
"Moving to Umbraco.Web.UI.Docs folder"
|
||||
cd ..\src\Umbraco.Web.UI.Docs
|
||||
|
||||
@@ -532,6 +535,7 @@
|
||||
# run
|
||||
if (-not $get)
|
||||
{
|
||||
cd
|
||||
if ($command.Length -eq 0)
|
||||
{
|
||||
$command = @( "Build" )
|
||||
|
||||
+3
-3
@@ -2,7 +2,7 @@
|
||||
using System.Resources;
|
||||
|
||||
[assembly: AssemblyCompany("Umbraco")]
|
||||
[assembly: AssemblyCopyright("Copyright © Umbraco 2019")]
|
||||
[assembly: AssemblyCopyright("Copyright © Umbraco 2020")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@@ -18,5 +18,5 @@ using System.Resources;
|
||||
[assembly: AssemblyVersion("8.0.0")]
|
||||
|
||||
// these are FYI and changed automatically
|
||||
[assembly: AssemblyFileVersion("8.6.0")]
|
||||
[assembly: AssemblyInformationalVersion("8.6.0")]
|
||||
[assembly: AssemblyFileVersion("8.7.0")]
|
||||
[assembly: AssemblyInformationalVersion("8.7.0")]
|
||||
|
||||
@@ -37,23 +37,13 @@ namespace Umbraco.Core.Cache
|
||||
/// <inheritdoc />
|
||||
public object Get(string key, Func<object> factory, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
CacheDependency dependency = null;
|
||||
if (dependentFiles != null && dependentFiles.Any())
|
||||
{
|
||||
dependency = new CacheDependency(dependentFiles);
|
||||
}
|
||||
return Get(key, factory, timeout, isSliding, priority, removedCallback, dependency);
|
||||
return GetInternal(key, factory, timeout, isSliding, priority, removedCallback, dependentFiles);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Insert(string key, Func<object> factory, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
CacheDependency dependency = null;
|
||||
if (dependentFiles != null && dependentFiles.Any())
|
||||
{
|
||||
dependency = new CacheDependency(dependentFiles);
|
||||
}
|
||||
Insert(key, factory, timeout, isSliding, priority, removedCallback, dependency);
|
||||
InsertInternal(key, factory, timeout, isSliding, priority, removedCallback, dependentFiles);
|
||||
}
|
||||
|
||||
#region Dictionary
|
||||
@@ -86,7 +76,7 @@ namespace Umbraco.Core.Cache
|
||||
|
||||
protected override void EnterWriteLock()
|
||||
{
|
||||
_locker.EnterWriteLock();;
|
||||
_locker.EnterWriteLock();
|
||||
}
|
||||
|
||||
protected override void ExitReadLock()
|
||||
@@ -103,7 +93,7 @@ namespace Umbraco.Core.Cache
|
||||
|
||||
#endregion
|
||||
|
||||
private object Get(string key, Func<object> factory, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null)
|
||||
private object GetInternal(string key, Func<object> factory, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
key = GetCacheKey(key);
|
||||
|
||||
@@ -163,6 +153,10 @@ namespace Umbraco.Core.Cache
|
||||
var sliding = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration);
|
||||
|
||||
lck.UpgradeToWriteLock();
|
||||
|
||||
// create a cache dependency if one is needed.
|
||||
var dependency = dependentFiles != null && dependentFiles.Length > 0 ? new CacheDependency(dependentFiles) : null;
|
||||
|
||||
//NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update!
|
||||
_cache.Insert(key, result, dependency, absolute, sliding, priority, removedCallback);
|
||||
}
|
||||
@@ -180,7 +174,7 @@ namespace Umbraco.Core.Cache
|
||||
return value;
|
||||
}
|
||||
|
||||
private void Insert(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null)
|
||||
private void InsertInternal(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
// NOTE - here also we must insert a Lazy<object> but we can evaluate it right now
|
||||
// and make sure we don't store a null value.
|
||||
@@ -197,6 +191,10 @@ namespace Umbraco.Core.Cache
|
||||
try
|
||||
{
|
||||
_locker.EnterWriteLock();
|
||||
|
||||
// create a cache dependency if one is needed.
|
||||
var dependency = dependentFiles != null && dependentFiles.Length > 0 ? new CacheDependency(dependentFiles) : null;
|
||||
|
||||
//NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update!
|
||||
_cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,23 @@ namespace Umbraco.Core.Collections
|
||||
/// The number of elements contained in the <see cref="T:System.Collections.ICollection"/>.
|
||||
/// </returns>
|
||||
/// <filterpriority>2</filterpriority>
|
||||
public int Count => GetThreadSafeClone().Count;
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
_instanceLocker.EnterReadLock();
|
||||
return _innerSet.Count;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_instanceLocker.IsReadLockHeld)
|
||||
_instanceLocker.ExitReadLock();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
|
||||
@@ -105,8 +121,7 @@ namespace Umbraco.Core.Collections
|
||||
/// <returns></returns>
|
||||
public bool TryAdd(T item)
|
||||
{
|
||||
var clone = GetThreadSafeClone();
|
||||
if (clone.Contains(item)) return false;
|
||||
if (Contains(item)) return false;
|
||||
try
|
||||
{
|
||||
_instanceLocker.EnterWriteLock();
|
||||
@@ -150,7 +165,16 @@ namespace Umbraco.Core.Collections
|
||||
/// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
|
||||
public bool Contains(T item)
|
||||
{
|
||||
return GetThreadSafeClone().Contains(item);
|
||||
try
|
||||
{
|
||||
_instanceLocker.EnterReadLock();
|
||||
return _innerSet.Contains(item);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_instanceLocker.IsReadLockHeld)
|
||||
_instanceLocker.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -168,13 +192,13 @@ namespace Umbraco.Core.Collections
|
||||
HashSet<T> clone = null;
|
||||
try
|
||||
{
|
||||
_instanceLocker.EnterWriteLock();
|
||||
_instanceLocker.EnterReadLock();
|
||||
clone = new HashSet<T>(_innerSet, _innerSet.Comparer);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_instanceLocker.IsWriteLockHeld)
|
||||
_instanceLocker.ExitWriteLock();
|
||||
if (_instanceLocker.IsReadLockHeld)
|
||||
_instanceLocker.ExitReadLock();
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Collections
|
||||
{
|
||||
@@ -26,7 +27,7 @@ namespace Umbraco.Core.Collections
|
||||
/// <param name="equalityComparer">The equality comparer to use when comparing keys, or null to use the default comparer.</param>
|
||||
public ObservableDictionary(Func<TValue, TKey> keySelector, IEqualityComparer<TKey> equalityComparer = null)
|
||||
{
|
||||
KeySelector = keySelector ?? throw new ArgumentException("keySelector");
|
||||
KeySelector = keySelector ?? throw new ArgumentException(nameof(keySelector));
|
||||
Indecies = new Dictionary<TKey, int>(equalityComparer);
|
||||
}
|
||||
|
||||
@@ -36,7 +37,7 @@ namespace Umbraco.Core.Collections
|
||||
{
|
||||
var key = KeySelector(item);
|
||||
if (Indecies.ContainsKey(key))
|
||||
throw new DuplicateKeyException(key.ToString());
|
||||
throw new ArgumentException($"An element with the same key '{key}' already exists in the dictionary.", nameof(item));
|
||||
|
||||
if (index != Count)
|
||||
{
|
||||
@@ -91,7 +92,7 @@ namespace Umbraco.Core.Collections
|
||||
{
|
||||
//confirm key matches
|
||||
if (!KeySelector(value).Equals(key))
|
||||
throw new InvalidOperationException("Key of new value does not match");
|
||||
throw new InvalidOperationException("Key of new value does not match.");
|
||||
|
||||
if (!Indecies.ContainsKey(key))
|
||||
{
|
||||
@@ -118,7 +119,7 @@ namespace Umbraco.Core.Collections
|
||||
|
||||
//confirm key matches
|
||||
if (!KeySelector(value).Equals(key))
|
||||
throw new InvalidOperationException("Key of new value does not match");
|
||||
throw new InvalidOperationException("Key of new value does not match.");
|
||||
|
||||
this[Indecies[key]] = value;
|
||||
return true;
|
||||
@@ -155,12 +156,12 @@ namespace Umbraco.Core.Collections
|
||||
{
|
||||
if (!Indecies.ContainsKey(currentKey))
|
||||
{
|
||||
throw new InvalidOperationException("No item with the key " + currentKey + "was found in the collection");
|
||||
throw new InvalidOperationException($"No item with the key '{currentKey}' was found in the dictionary.");
|
||||
}
|
||||
|
||||
if (ContainsKey(newKey))
|
||||
{
|
||||
throw new DuplicateKeyException(newKey.ToString());
|
||||
throw new ArgumentException($"An element with the same key '{newKey}' already exists in the dictionary.", nameof(newKey));
|
||||
}
|
||||
|
||||
var currentIndex = Indecies[currentKey];
|
||||
@@ -234,16 +235,5 @@ namespace Umbraco.Core.Collections
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
internal class DuplicateKeyException : Exception
|
||||
{
|
||||
public DuplicateKeyException(string key)
|
||||
: base("Attempted to insert duplicate key \"" + key + "\" in collection.")
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
|
||||
public string Key { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace Umbraco.Core.Collections
|
||||
if (_items.TryGetValue(key, out value))
|
||||
yield return value;
|
||||
else if (throwOnMissing)
|
||||
throw new Exception(MissingDependencyError);
|
||||
throw new Exception($"{MissingDependencyError} Error in type {typeof(TItem).Name}, with key {key}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,10 +26,11 @@ namespace Umbraco.Core.Compose
|
||||
|
||||
if (relationType == null)
|
||||
{
|
||||
relationType = new RelationType(Constants.ObjectTypes.Document,
|
||||
relationType = new RelationType(Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias,
|
||||
Constants.Conventions.RelationTypes.RelateDocumentOnCopyName,
|
||||
true,
|
||||
Constants.ObjectTypes.Document,
|
||||
Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias,
|
||||
Constants.Conventions.RelationTypes.RelateDocumentOnCopyName) { IsBidirectional = true };
|
||||
Constants.ObjectTypes.Document);
|
||||
|
||||
relationService.Save(relationType);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace Umbraco.Core.Compose
|
||||
var documentObjectType = Constants.ObjectTypes.Document;
|
||||
const string relationTypeName = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteName;
|
||||
|
||||
relationType = new RelationType(documentObjectType, documentObjectType, relationTypeAlias, relationTypeName);
|
||||
relationType = new RelationType(relationTypeName, relationTypeAlias, false, documentObjectType, documentObjectType);
|
||||
relationService.Save(relationType);
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace Umbraco.Core.Compose
|
||||
{
|
||||
var documentObjectType = Constants.ObjectTypes.Document;
|
||||
const string relationTypeName = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName;
|
||||
relationType = new RelationType(documentObjectType, documentObjectType, relationTypeAlias, relationTypeName);
|
||||
relationType = new RelationType(relationTypeName, relationTypeAlias, false, documentObjectType, documentObjectType);
|
||||
relationService.Save(relationType);
|
||||
}
|
||||
foreach (var item in e.MoveInfoCollection)
|
||||
|
||||
@@ -79,9 +79,12 @@ namespace Umbraco.Core.Composing
|
||||
foreach (var type in types)
|
||||
EnsureType(type, "register");
|
||||
|
||||
// register them
|
||||
// register them - ensuring that each item is registered with the same lifetime as the collection.
|
||||
// NOTE: Previously each one was not registered with the same lifetime which would mean that if there
|
||||
// was a dependency on an individual item, it would resolve a brand new transient instance which isn't what
|
||||
// we would expect to happen. The same item should be resolved from the container as the collection.
|
||||
foreach (var type in types)
|
||||
register.Register(type);
|
||||
register.Register(type, CollectionLifetime);
|
||||
|
||||
_registeredTypes = types;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
@@ -43,8 +44,15 @@ namespace Umbraco.Core.Composing
|
||||
var componentType = component.GetType();
|
||||
using (_logger.DebugDuration<ComponentCollection>($"Terminating {componentType.FullName}.", $"Terminated {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds))
|
||||
{
|
||||
component.Terminate();
|
||||
component.DisposeIfDisposable();
|
||||
try
|
||||
{
|
||||
component.Terminate();
|
||||
component.DisposeIfDisposable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error<ComponentCollection>(ex, "Error while terminating component {ComponentType}.", componentType.FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,19 +18,52 @@ namespace Umbraco.Core.Composing
|
||||
private readonly Composition _composition;
|
||||
private readonly IProfilingLogger _logger;
|
||||
private readonly IEnumerable<Type> _composerTypes;
|
||||
private readonly IEnumerable<Attribute> _enableDisableAttributes;
|
||||
|
||||
private const int LogThresholdMilliseconds = 100;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Composers"/> class.
|
||||
/// Initializes a new instance of the <see cref="Composers" /> class.
|
||||
/// </summary>
|
||||
/// <param name="composition">The composition.</param>
|
||||
/// <param name="composerTypes">The composer types.</param>
|
||||
/// <param name="logger">A profiling logger.</param>
|
||||
/// <param name="composerTypes">The <see cref="IComposer" /> types.</param>
|
||||
/// <param name="logger">The profiling logger.</param>
|
||||
[Obsolete("This overload only gets the EnableComposer/DisableComposer attributes from the composerTypes assemblies.")]
|
||||
public Composers(Composition composition, IEnumerable<Type> composerTypes, IProfilingLogger logger)
|
||||
: this(composition, composerTypes, Enumerable.Empty<Attribute>(), logger)
|
||||
{
|
||||
var enableDisableAttributes = new List<Attribute>();
|
||||
|
||||
var assemblies = composerTypes.Select(t => t.Assembly).Distinct();
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
enableDisableAttributes.AddRange(assembly.GetCustomAttributes(typeof(EnableComposerAttribute)));
|
||||
enableDisableAttributes.AddRange(assembly.GetCustomAttributes(typeof(DisableComposerAttribute)));
|
||||
}
|
||||
|
||||
_enableDisableAttributes = enableDisableAttributes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Composers" /> class.
|
||||
/// </summary>
|
||||
/// <param name="composition">The composition.</param>
|
||||
/// <param name="composerTypes">The <see cref="IComposer" /> types.</param>
|
||||
/// <param name="enableDisableAttributes">The <see cref="EnableComposerAttribute" /> and/or <see cref="DisableComposerAttribute" /> attributes.</param>
|
||||
/// <param name="logger">The profiling logger.</param>
|
||||
/// <exception cref="ArgumentNullException">composition
|
||||
/// or
|
||||
/// composerTypes
|
||||
/// or
|
||||
/// enableDisableAttributes
|
||||
/// or
|
||||
/// logger</exception>
|
||||
|
||||
public Composers(Composition composition, IEnumerable<Type> composerTypes, IEnumerable<Attribute> enableDisableAttributes, IProfilingLogger logger)
|
||||
{
|
||||
_composition = composition ?? throw new ArgumentNullException(nameof(composition));
|
||||
_composerTypes = composerTypes ?? throw new ArgumentNullException(nameof(composerTypes));
|
||||
_enableDisableAttributes = enableDisableAttributes ?? throw new ArgumentNullException(nameof(enableDisableAttributes));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
@@ -103,7 +136,7 @@ namespace Umbraco.Core.Composing
|
||||
.ToList();
|
||||
|
||||
// enable or disable composers
|
||||
EnableDisableComposers(composerTypeList);
|
||||
EnableDisableComposers(_enableDisableAttributes, composerTypeList);
|
||||
|
||||
void GatherInterfaces<TAttribute>(Type type, Func<TAttribute, Type> getTypeInAttribute, HashSet<Type> iset, List<Type> set2)
|
||||
where TAttribute : Attribute
|
||||
@@ -218,7 +251,7 @@ namespace Umbraco.Core.Composing
|
||||
return text.ToString();
|
||||
}
|
||||
|
||||
private static void EnableDisableComposers(ICollection<Type> types)
|
||||
private static void EnableDisableComposers(IEnumerable<Attribute> enableDisableAttributes, ICollection<Type> types)
|
||||
{
|
||||
var enabled = new Dictionary<Type, EnableInfo>();
|
||||
|
||||
@@ -240,20 +273,16 @@ namespace Umbraco.Core.Composing
|
||||
enableInfo.Weight = weight2;
|
||||
}
|
||||
|
||||
var assemblies = types.Select(x => x.Assembly).Distinct();
|
||||
foreach (var assembly in assemblies)
|
||||
foreach (var attr in enableDisableAttributes.OfType<EnableComposerAttribute>())
|
||||
{
|
||||
foreach (var attr in assembly.GetCustomAttributes<EnableComposerAttribute>())
|
||||
{
|
||||
var type = attr.EnabledType;
|
||||
UpdateEnableInfo(type, 2, enabled, true);
|
||||
}
|
||||
var type = attr.EnabledType;
|
||||
UpdateEnableInfo(type, 2, enabled, true);
|
||||
}
|
||||
|
||||
foreach (var attr in assembly.GetCustomAttributes<DisableComposerAttribute>())
|
||||
{
|
||||
var type = attr.DisabledType;
|
||||
UpdateEnableInfo(type, 2, enabled, false);
|
||||
}
|
||||
foreach (var attr in enableDisableAttributes.OfType<DisableComposerAttribute>())
|
||||
{
|
||||
var type = attr.DisabledType;
|
||||
UpdateEnableInfo(type, 2, enabled, false);
|
||||
}
|
||||
|
||||
foreach (var composerType in types)
|
||||
|
||||
@@ -47,6 +47,8 @@ namespace Umbraco.Core.Composing.CompositionExtensions
|
||||
composition.RegisterUnique<IScriptRepository, ScriptRepository>();
|
||||
composition.RegisterUnique<IStylesheetRepository, StylesheetRepository>();
|
||||
composition.RegisterUnique<IContentTypeCommonRepository, ContentTypeCommonRepository>();
|
||||
composition.RegisterUnique<IInstallationRepository, InstallationRepository>();
|
||||
composition.RegisterUnique<IUpgradeCheckRepository, UpgradeCheckRepository>();
|
||||
|
||||
return composition;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using Umbraco.Core.Dictionary;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.PackageActions;
|
||||
using Umbraco.Core.Packaging;
|
||||
@@ -154,6 +155,9 @@ namespace Umbraco.Core.Composing
|
||||
public static DataEditorCollection DataEditors
|
||||
=> Factory.GetInstance<DataEditorCollection>();
|
||||
|
||||
public static DataValueReferenceFactoryCollection DataValueReferenceFactories
|
||||
=> Factory.GetInstance<DataValueReferenceFactoryCollection>();
|
||||
|
||||
public static PropertyEditorCollection PropertyEditors
|
||||
=> Factory.GetInstance<PropertyEditorCollection>();
|
||||
|
||||
@@ -205,6 +209,8 @@ namespace Umbraco.Core.Composing
|
||||
public static IVariationContextAccessor VariationContextAccessor
|
||||
=> Factory.GetInstance<IVariationContextAccessor>();
|
||||
|
||||
public static IImageUrlGenerator ImageUrlGenerator
|
||||
=> Factory.GetInstance<IImageUrlGenerator>();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Composing.LightInject
|
||||
@@ -6,20 +7,51 @@ namespace Umbraco.Core.Composing.LightInject
|
||||
/// <summary>
|
||||
/// Represents errors that occur due to LightInject.
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Exception" />
|
||||
[Serializable]
|
||||
public class LightInjectException : Exception
|
||||
{
|
||||
public LightInjectException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
|
||||
public LightInjectException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{ }
|
||||
|
||||
private const string LightInjectUnableToResolveType = "Unable to resolve type:";
|
||||
private const string LightInjectUnresolvedDependency = "Unresolved dependency ";
|
||||
private const string LightInjectRequestedDependency = "[Requested dependency:";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LightInjectException" /> class.
|
||||
/// </summary>
|
||||
public LightInjectException()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LightInjectException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
public LightInjectException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LightInjectException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
|
||||
public LightInjectException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LightInjectException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
|
||||
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
|
||||
protected LightInjectException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Tries to throw the exception with additional details.
|
||||
/// </summary>
|
||||
/// <param name="e">The exception.</param>
|
||||
/// <exception cref="Umbraco.Core.Composing.LightInject.LightInjectException"></exception>
|
||||
public static void TryThrow(Exception e)
|
||||
{
|
||||
var ex = e as InvalidOperationException;
|
||||
@@ -32,6 +64,12 @@ namespace Umbraco.Core.Composing.LightInject
|
||||
throw new LightInjectException(sb.ToString(), e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to throw the exception with additional details.
|
||||
/// </summary>
|
||||
/// <param name="e">The exception.</param>
|
||||
/// <param name="implementingType">The implementing type.</param>
|
||||
/// <exception cref="Umbraco.Core.Composing.LightInject.LightInjectException"></exception>
|
||||
public static void TryThrow(Exception e, Type implementingType)
|
||||
{
|
||||
var ex = e as InvalidOperationException;
|
||||
@@ -45,6 +83,11 @@ namespace Umbraco.Core.Composing.LightInject
|
||||
throw new LightInjectException(sb.ToString(), e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the details.
|
||||
/// </summary>
|
||||
/// <param name="ex">The exception.</param>
|
||||
/// <param name="sb">The <see cref="StringBuilder" /> to write the details to.</param>
|
||||
private static void WriteDetails(InvalidOperationException ex, StringBuilder sb)
|
||||
{
|
||||
ex = ex.InnerException as InvalidOperationException;
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
@@ -505,6 +506,49 @@ namespace Umbraco.Core.Composing
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get Assembly Attributes
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly attributes of the specified type <typeparamref name="T" />.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The attribute type.</typeparam>
|
||||
/// <returns>
|
||||
/// The assembly attributes of the specified type <typeparamref name="T" />.
|
||||
/// </returns>
|
||||
public IEnumerable<T> GetAssemblyAttributes<T>()
|
||||
where T : Attribute
|
||||
{
|
||||
return AssembliesToScan.SelectMany(a => a.GetCustomAttributes<T>()).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all the assembly attributes.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// All assembly attributes.
|
||||
/// </returns>
|
||||
public IEnumerable<Attribute> GetAssemblyAttributes()
|
||||
{
|
||||
return AssembliesToScan.SelectMany(a => a.GetCustomAttributes()).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly attributes of the specified <paramref name="attributeTypes" />.
|
||||
/// </summary>
|
||||
/// <param name="attributeTypes">The attribute types.</param>
|
||||
/// <returns>
|
||||
/// The assembly attributes of the specified types.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">attributeTypes</exception>
|
||||
public IEnumerable<Attribute> GetAssemblyAttributes(params Type[] attributeTypes)
|
||||
{
|
||||
if (attributeTypes == null) throw new ArgumentNullException(nameof(attributeTypes));
|
||||
|
||||
return AssembliesToScan.SelectMany(a => attributeTypes.SelectMany(at => a.GetCustomAttributes(at))).ToList();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get Types
|
||||
|
||||
/// <summary>
|
||||
@@ -813,11 +857,44 @@ namespace Umbraco.Core.Composing
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the error that occurs when a type was not found in the cache type
|
||||
/// list with the specified TypeResolutionKind.
|
||||
/// Represents the error that occurs when a type was not found in the cache type list with the specified TypeResolutionKind.
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Exception" />
|
||||
[Serializable]
|
||||
internal class CachedTypeNotFoundInFileException : Exception
|
||||
{ }
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CachedTypeNotFoundInFileException" /> class.
|
||||
/// </summary>
|
||||
public CachedTypeNotFoundInFileException()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CachedTypeNotFoundInFileException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
public CachedTypeNotFoundInFileException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CachedTypeNotFoundInFileException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
|
||||
public CachedTypeNotFoundInFileException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CachedTypeNotFoundInFileException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
|
||||
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
|
||||
protected CachedTypeNotFoundInFileException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{ }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -49,6 +49,13 @@ namespace Umbraco.Core
|
||||
public static DataEditorCollectionBuilder DataEditors(this Composition composition)
|
||||
=> composition.WithCollectionBuilder<DataEditorCollectionBuilder>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data value reference factory collection builder.
|
||||
/// </summary>
|
||||
/// <param name="composition">The composition.</param>
|
||||
public static DataValueReferenceFactoryCollectionBuilder DataValueReferenceFactories(this Composition composition)
|
||||
=> composition.WithCollectionBuilder<DataValueReferenceFactoryCollectionBuilder>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the property value converters collection builder.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
public interface IKeepAliveSection : IUmbracoConfigurationSection
|
||||
{
|
||||
bool DisableKeepAliveTask { get; }
|
||||
string KeepAlivePingUrl { get; }
|
||||
}
|
||||
}
|
||||
@@ -15,5 +15,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
ILoggingSection Logging { get; }
|
||||
|
||||
IWebRoutingSection WebRouting { get; }
|
||||
|
||||
IKeepAliveSection KeepAlive { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class KeepAliveElement : ConfigurationElement, IKeepAliveSection
|
||||
{
|
||||
[ConfigurationProperty("disableKeepAliveTask", DefaultValue = "false")]
|
||||
public bool DisableKeepAliveTask => (bool)base["disableKeepAliveTask"];
|
||||
|
||||
[ConfigurationProperty("keepAlivePingUrl", DefaultValue = "{umbracoApplicationUrl}/api/keepalive/ping")]
|
||||
public string KeepAlivePingUrl => (string)base["keepAlivePingUrl"];
|
||||
}
|
||||
}
|
||||
@@ -19,10 +19,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
[ConfigurationProperty("logging")]
|
||||
internal LoggingElement Logging => (LoggingElement)this["logging"];
|
||||
|
||||
|
||||
[ConfigurationProperty("web.routing")]
|
||||
internal WebRoutingElement WebRouting => (WebRoutingElement)this["web.routing"];
|
||||
|
||||
[ConfigurationProperty("keepAlive")]
|
||||
internal KeepAliveElement KeepAlive => (KeepAliveElement)this["keepAlive"];
|
||||
|
||||
IContentSection IUmbracoSettingsSection.Content => Content;
|
||||
|
||||
ISecuritySection IUmbracoSettingsSection.Security => Security;
|
||||
@@ -34,5 +36,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
ILoggingSection IUmbracoSettingsSection.Logging => Logging;
|
||||
|
||||
IWebRoutingSection IUmbracoSettingsSection.WebRouting => WebRouting;
|
||||
|
||||
IKeepAliveSection IUmbracoSettingsSection.KeepAlive => KeepAlive;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public static class AppSettings
|
||||
{
|
||||
public const string MainDomLock = "Umbraco.Core.MainDom.Lock";
|
||||
|
||||
// TODO: Kill me - still used in Umbraco.Core.IO.SystemFiles:27
|
||||
[Obsolete("We need to kill this appsetting as we do not use XML content cache umbraco.config anymore due to NuCache")]
|
||||
public const string ContentXML = "Umbraco.Core.ContentXML"; //umbracoContentXML
|
||||
@@ -41,6 +43,21 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string Path = "Umbraco.Core.Path";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the css directory (/css by default).
|
||||
/// </summary>
|
||||
public const string CssPath = "umbracoCssPath";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the scripts directory (/scripts by default).
|
||||
/// </summary>
|
||||
public const string ScriptsPath = "umbracoScriptsPath";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to media directory (/media by default).
|
||||
/// </summary>
|
||||
public const string MediaPath = "umbracoMediaPath";
|
||||
|
||||
/// <summary>
|
||||
/// The reserved urls from web.config.
|
||||
/// </summary>
|
||||
|
||||
@@ -315,34 +315,65 @@ namespace Umbraco.Core
|
||||
public static class RelationTypes
|
||||
{
|
||||
/// <summary>
|
||||
/// ContentType name for default relation type "Relate Document On Copy".
|
||||
/// Name for default relation type "Related Media".
|
||||
/// </summary>
|
||||
public const string RelatedMediaName = "Related Media";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for default relation type "Related Media"
|
||||
/// </summary>
|
||||
public const string RelatedMediaAlias = "umbMedia";
|
||||
|
||||
/// <summary>
|
||||
/// Name for default relation type "Related Document".
|
||||
/// </summary>
|
||||
public const string RelatedDocumentName = "Related Document";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for default relation type "Related Document"
|
||||
/// </summary>
|
||||
public const string RelatedDocumentAlias = "umbDocument";
|
||||
|
||||
/// <summary>
|
||||
/// Name for default relation type "Relate Document On Copy".
|
||||
/// </summary>
|
||||
public const string RelateDocumentOnCopyName = "Relate Document On Copy";
|
||||
|
||||
/// <summary>
|
||||
/// ContentType alias for default relation type "Relate Document On Copy".
|
||||
/// Alias for default relation type "Relate Document On Copy".
|
||||
/// </summary>
|
||||
public const string RelateDocumentOnCopyAlias = "relateDocumentOnCopy";
|
||||
|
||||
/// <summary>
|
||||
/// ContentType name for default relation type "Relate Parent Document On Delete".
|
||||
/// Name for default relation type "Relate Parent Document On Delete".
|
||||
/// </summary>
|
||||
public const string RelateParentDocumentOnDeleteName = "Relate Parent Document On Delete";
|
||||
|
||||
/// <summary>
|
||||
/// ContentType alias for default relation type "Relate Parent Document On Delete".
|
||||
/// Alias for default relation type "Relate Parent Document On Delete".
|
||||
/// </summary>
|
||||
public const string RelateParentDocumentOnDeleteAlias = "relateParentDocumentOnDelete";
|
||||
|
||||
/// <summary>
|
||||
/// ContentType name for default relation type "Relate Parent Media Folder On Delete".
|
||||
/// Name for default relation type "Relate Parent Media Folder On Delete".
|
||||
/// </summary>
|
||||
public const string RelateParentMediaFolderOnDeleteName = "Relate Parent Media Folder On Delete";
|
||||
|
||||
/// <summary>
|
||||
/// ContentType alias for default relation type "Relate Parent Media Folder On Delete".
|
||||
/// Alias for default relation type "Relate Parent Media Folder On Delete".
|
||||
/// </summary>
|
||||
public const string RelateParentMediaFolderOnDeleteAlias = "relateParentMediaFolderOnDelete";
|
||||
|
||||
/// <summary>
|
||||
/// Returns the types of relations that are automatically tracked
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Developers should not manually use these relation types since they will all be cleared whenever an entity
|
||||
/// (content, media or member) is saved since they are auto-populated based on property values.
|
||||
/// </remarks>
|
||||
public static string[] AutomaticRelationTypes = new[] { RelatedMediaAlias, RelatedDocumentAlias };
|
||||
|
||||
//TODO: return a list of built in types so we can use that to prevent deletion in the uI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,10 @@ namespace Umbraco.Core
|
||||
public const string UnknownUserName = "SYTEM";
|
||||
|
||||
public const string AdminGroupAlias = "admin";
|
||||
public const string EditorGroupAlias = "editor";
|
||||
public const string SensitiveDataGroupAlias = "sensitiveData";
|
||||
public const string TranslatorGroupAlias = "translator";
|
||||
public const string WriterGroupAlias = "writer";
|
||||
|
||||
public const string BackOfficeAuthenticationType = "UmbracoBackOffice";
|
||||
public const string BackOfficeExternalAuthenticationType = "UmbracoExternalCookie";
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
{
|
||||
public static class SqlTemplates
|
||||
{
|
||||
public static class VersionableRepository
|
||||
{
|
||||
public const string GetVersionIds = "Umbraco.Core.VersionableRepository.GetVersionIds";
|
||||
public const string GetVersion = "Umbraco.Core.VersionableRepository.GetVersion";
|
||||
public const string GetVersions = "Umbraco.Core.VersionableRepository.GetVersions";
|
||||
public const string EnsureUniqueNodeName = "Umbraco.Core.VersionableRepository.EnsureUniqueNodeName";
|
||||
public const string GetSortOrder = "Umbraco.Core.VersionableRepository.GetSortOrder";
|
||||
public const string GetParentNode = "Umbraco.Core.VersionableRepository.GetParentNode";
|
||||
public const string GetReservedId = "Umbraco.Core.VersionableRepository.GetReservedId";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
|
||||
@@ -23,6 +24,8 @@ namespace Umbraco.Core
|
||||
// this ain't pretty
|
||||
private static IMediaFileSystem _mediaFileSystem;
|
||||
private static IMediaFileSystem MediaFileSystem => _mediaFileSystem ?? (_mediaFileSystem = Current.MediaFileSystem);
|
||||
private static readonly PropertyEditorCollection _propertyEditors;
|
||||
private static PropertyEditorCollection PropertyEditors = _propertyEditors ?? (_propertyEditors = Current.PropertyEditors);
|
||||
|
||||
#region IContent
|
||||
|
||||
@@ -57,6 +60,19 @@ namespace Umbraco.Core
|
||||
|
||||
#endregion
|
||||
|
||||
internal static bool IsMoving(this IContentBase entity)
|
||||
{
|
||||
// Check if this entity is being moved as a descendant as part of a bulk moving operations.
|
||||
// When this occurs, only Path + Level + UpdateDate are being changed. In this case we can bypass a lot of the below
|
||||
// operations which will make this whole operation go much faster. When moving we don't need to create
|
||||
// new versions, etc... because we cannot roll this operation back anyways.
|
||||
var isMoving = entity.IsPropertyDirty(nameof(entity.Path))
|
||||
&& entity.IsPropertyDirty(nameof(entity.Level))
|
||||
&& entity.IsPropertyDirty(nameof(entity.UpdateDate));
|
||||
|
||||
return isMoving;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes characters that are not valid XML characters from all entity properties
|
||||
/// of type string. See: http://stackoverflow.com/a/961504/5018
|
||||
@@ -162,14 +178,12 @@ namespace Umbraco.Core
|
||||
// Fixes https://github.com/umbraco/Umbraco-CMS/issues/3937 - Assigning a new file to an
|
||||
// existing IMedia with extension SetValue causes exception 'Illegal characters in path'
|
||||
string oldpath = null;
|
||||
if (property.GetValue(culture, segment) is string svalue)
|
||||
var value = property.GetValue(culture, segment);
|
||||
|
||||
if (PropertyEditors.TryGet(propertyTypeAlias, out var editor)
|
||||
&& editor is IDataEditorWithMediaPath dataEditor)
|
||||
{
|
||||
if (svalue.DetectIsJson())
|
||||
{
|
||||
// the property value is a JSON serialized image crop data set - grab the "src" property as the file source
|
||||
var jObject = JsonConvert.DeserializeObject<JObject>(svalue);
|
||||
svalue = jObject != null ? jObject.GetValueAsString("src") : svalue;
|
||||
}
|
||||
var svalue = dataEditor.GetMediaPath(value);
|
||||
oldpath = MediaFileSystem.GetRelativePath(svalue);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,121 +12,260 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Determines whether the content type is invariant.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The content type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the content type is invariant.
|
||||
/// </returns>
|
||||
public static bool VariesByNothing(this ISimpleContentType contentType) => contentType.Variations.VariesByNothing();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by culture.
|
||||
/// </summary>
|
||||
public static bool VariesByCulture(this ISimpleContentType contentType) => contentType.Variations.VariesByCulture();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type is invariant.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The content type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the content type is invariant.
|
||||
/// </returns>
|
||||
public static bool VariesByNothing(this IContentTypeBase contentType) => contentType.Variations.VariesByNothing();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by culture.
|
||||
/// </summary>
|
||||
/// <remarks>And then it could also vary by segment.</remarks>
|
||||
public static bool VariesByCulture(this IContentTypeBase contentType) => contentType.Variations.VariesByCulture();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by segment.
|
||||
/// </summary>
|
||||
/// <remarks>And then it could also vary by culture.</remarks>
|
||||
public static bool VariesBySegment(this IContentTypeBase contentType) => contentType.Variations.VariesBySegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by culture and segment.
|
||||
/// </summary>
|
||||
public static bool VariesByCultureAndSegment(this IContentTypeBase contentType) => contentType.Variations.VariesByCultureAndSegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type is invariant.
|
||||
/// </summary>
|
||||
public static bool VariesByNothing(this PropertyType propertyType) => propertyType.Variations.VariesByNothing();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type varies by culture.
|
||||
/// </summary>
|
||||
/// <remarks>And then it could also vary by segment.</remarks>
|
||||
public static bool VariesByCulture(this PropertyType propertyType) => propertyType.Variations.VariesByCulture();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type varies by segment.
|
||||
/// </summary>
|
||||
/// <remarks>And then it could also vary by culture.</remarks>
|
||||
public static bool VariesBySegment(this PropertyType propertyType) => propertyType.Variations.VariesBySegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type varies by culture and segment.
|
||||
/// </summary>
|
||||
public static bool VariesByCultureAndSegment(this PropertyType propertyType) => propertyType.Variations.VariesByCultureAndSegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type is invariant.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The content type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the content type is invariant.
|
||||
/// </returns>
|
||||
public static bool VariesByNothing(this IPublishedContentType contentType) => contentType.Variations.VariesByNothing();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by culture.
|
||||
/// Determines whether the property type is invariant.
|
||||
/// </summary>
|
||||
/// <remarks>And then it could also vary by segment.</remarks>
|
||||
public static bool VariesByCulture(this IPublishedContentType contentType) => contentType.Variations.VariesByCulture();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by segment.
|
||||
/// </summary>
|
||||
/// <remarks>And then it could also vary by culture.</remarks>
|
||||
public static bool VariesBySegment(this IPublishedContentType contentType) => contentType.Variations.VariesBySegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by culture and segment.
|
||||
/// </summary>
|
||||
public static bool VariesByCultureAndSegment(this IPublishedContentType contentType) => contentType.Variations.VariesByCultureAndSegment();
|
||||
/// <param name="propertyType">The property type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the property type is invariant.
|
||||
/// </returns>
|
||||
public static bool VariesByNothing(this PropertyType propertyType) => propertyType.Variations.VariesByNothing();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type is invariant.
|
||||
/// </summary>
|
||||
/// <param name="propertyType">The property type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the property type is invariant.
|
||||
/// </returns>
|
||||
public static bool VariesByNothing(this IPublishedPropertyType propertyType) => propertyType.Variations.VariesByNothing();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type varies by culture.
|
||||
/// </summary>
|
||||
public static bool VariesByCulture(this IPublishedPropertyType propertyType) => propertyType.Variations.VariesByCulture();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type varies by segment.
|
||||
/// </summary>
|
||||
public static bool VariesBySegment(this IPublishedPropertyType propertyType) => propertyType.Variations.VariesBySegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type varies by culture and segment.
|
||||
/// </summary>
|
||||
public static bool VariesByCultureAndSegment(this IPublishedPropertyType propertyType) => propertyType.Variations.VariesByCultureAndSegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a variation is invariant.
|
||||
/// </summary>
|
||||
/// <param name="variation">The variation.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the variation is invariant.
|
||||
/// </returns>
|
||||
public static bool VariesByNothing(this ContentVariation variation) => variation == ContentVariation.Nothing;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by culture.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The content type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the content type varies by culture.
|
||||
/// </returns>
|
||||
public static bool VariesByCulture(this ISimpleContentType contentType) => contentType.Variations.VariesByCulture();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by culture.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The content type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the content type varies by culture.
|
||||
/// </returns>
|
||||
public static bool VariesByCulture(this IContentTypeBase contentType) => contentType.Variations.VariesByCulture();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by culture.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The content type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the content type varies by culture.
|
||||
/// </returns>
|
||||
public static bool VariesByCulture(this IPublishedContentType contentType) => contentType.Variations.VariesByCulture();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type varies by culture.
|
||||
/// </summary>
|
||||
/// <param name="propertyType">The property type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the property type varies by culture.
|
||||
/// </returns>
|
||||
public static bool VariesByCulture(this PropertyType propertyType) => propertyType.Variations.VariesByCulture();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type varies by culture.
|
||||
/// </summary>
|
||||
/// <param name="propertyType">The property type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the property type varies by culture.
|
||||
/// </returns>
|
||||
public static bool VariesByCulture(this IPublishedPropertyType propertyType) => propertyType.Variations.VariesByCulture();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a variation varies by culture.
|
||||
/// </summary>
|
||||
/// <remarks>And then it could also vary by segment.</remarks>
|
||||
/// <param name="variation">The variation.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the variation varies by culture.
|
||||
/// </returns>
|
||||
public static bool VariesByCulture(this ContentVariation variation) => (variation & ContentVariation.Culture) > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by segment.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The content type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the content type varies by segment.
|
||||
/// </returns>
|
||||
public static bool VariesBySegment(this ISimpleContentType contentType) => contentType.Variations.VariesBySegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by segment.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The content type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the content type varies by segment.
|
||||
/// </returns>
|
||||
public static bool VariesBySegment(this IContentTypeBase contentType) => contentType.Variations.VariesBySegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by segment.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The content type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the content type varies by segment.
|
||||
/// </returns>
|
||||
public static bool VariesBySegment(this IPublishedContentType contentType) => contentType.Variations.VariesBySegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type varies by segment.
|
||||
/// </summary>
|
||||
/// <param name="propertyType">The property type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the property type varies by segment.
|
||||
/// </returns>
|
||||
public static bool VariesBySegment(this PropertyType propertyType) => propertyType.Variations.VariesBySegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type varies by segment.
|
||||
/// </summary>
|
||||
/// <param name="propertyType">The property type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the property type varies by segment.
|
||||
/// </returns>
|
||||
public static bool VariesBySegment(this IPublishedPropertyType propertyType) => propertyType.Variations.VariesBySegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a variation varies by segment.
|
||||
/// </summary>
|
||||
/// <remarks>And then it could also vary by culture.</remarks>
|
||||
/// <param name="variation">The variation.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the variation varies by segment.
|
||||
/// </returns>
|
||||
public static bool VariesBySegment(this ContentVariation variation) => (variation & ContentVariation.Segment) > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by culture and segment.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The content type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the content type varies by culture and segment.
|
||||
/// </returns>
|
||||
public static bool VariesByCultureAndSegment(this ISimpleContentType contentType) => contentType.Variations.VariesByCultureAndSegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by culture and segment.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The content type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the content type varies by culture and segment.
|
||||
/// </returns>
|
||||
public static bool VariesByCultureAndSegment(this IContentTypeBase contentType) => contentType.Variations.VariesByCultureAndSegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by culture and segment.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The content type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the content type varies by culture and segment.
|
||||
/// </returns>
|
||||
public static bool VariesByCultureAndSegment(this IPublishedContentType contentType) => contentType.Variations.VariesByCultureAndSegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type varies by culture and segment.
|
||||
/// </summary>
|
||||
/// <param name="propertyType">The property type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the property type varies by culture and segment.
|
||||
/// </returns>
|
||||
public static bool VariesByCultureAndSegment(this PropertyType propertyType) => propertyType.Variations.VariesByCultureAndSegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type varies by culture and segment.
|
||||
/// </summary>
|
||||
/// <param name="propertyType">The property type.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the property type varies by culture and segment.
|
||||
/// </returns>
|
||||
public static bool VariesByCultureAndSegment(this IPublishedPropertyType propertyType) => propertyType.Variations.VariesByCultureAndSegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a variation varies by culture and segment.
|
||||
/// </summary>
|
||||
/// <param name="variation">The variation.</param>
|
||||
/// <returns>
|
||||
/// A value indicating whether the variation varies by culture and segment.
|
||||
/// </returns>
|
||||
public static bool VariesByCultureAndSegment(this ContentVariation variation) => (variation & ContentVariation.CultureAndSegment) == ContentVariation.CultureAndSegment;
|
||||
|
||||
/// <summary>
|
||||
/// Sets or removes the content type variation depending on the specified value.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The content type.</param>
|
||||
/// <param name="variation">The variation to set or remove.</param>
|
||||
/// <param name="value">If set to <c>true</c> sets the variation; otherwise, removes the variation.</param>
|
||||
/// <remarks>
|
||||
/// This method does not support setting the variation to nothing.
|
||||
/// </remarks>
|
||||
public static void SetVariesBy(this IContentTypeBase contentType, ContentVariation variation, bool value = true) => contentType.Variations = contentType.Variations.SetFlag(variation, value);
|
||||
|
||||
/// <summary>
|
||||
/// Sets or removes the property type variation depending on the specified value.
|
||||
/// </summary>
|
||||
/// <param name="propertyType">The property type.</param>
|
||||
/// <param name="variation">The variation to set or remove.</param>
|
||||
/// <param name="value">If set to <c>true</c> sets the variation; otherwise, removes the variation.</param>
|
||||
/// <remarks>
|
||||
/// This method does not support setting the variation to nothing.
|
||||
/// </remarks>
|
||||
public static void SetVariesBy(this PropertyType propertyType, ContentVariation variation, bool value = true) => propertyType.Variations = propertyType.Variations.SetFlag(variation, value);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the variations with the variation set or removed depending on the specified value.
|
||||
/// </summary>
|
||||
/// <param name="variations">The existing variations.</param>
|
||||
/// <param name="variation">The variation to set or remove.</param>
|
||||
/// <param name="value">If set to <c>true</c> sets the variation; otherwise, removes the variation.</param>
|
||||
/// <returns>
|
||||
/// The variations with the variation set or removed.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method does not support setting the variation to nothing.
|
||||
/// </remarks>
|
||||
public static ContentVariation SetFlag(this ContentVariation variations, ContentVariation variation, bool value = true)
|
||||
{
|
||||
return value
|
||||
? variations | variation // Set flag using bitwise logical OR
|
||||
: variations & ~variation; // Remove flag using bitwise logical AND with bitwise complement (reversing the bit)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates that a combination of culture and segment is valid for the variation.
|
||||
/// </summary>
|
||||
@@ -135,16 +274,18 @@ namespace Umbraco.Core
|
||||
/// <param name="segment">The segment.</param>
|
||||
/// <param name="exact">A value indicating whether to perform exact validation.</param>
|
||||
/// <param name="wildcards">A value indicating whether to support wildcards.</param>
|
||||
/// <param name="throwIfInvalid">A value indicating whether to throw a <see cref="NotSupportedException"/> when the combination is invalid.</param>
|
||||
/// <returns>True if the combination is valid; otherwise false.</returns>
|
||||
/// <param name="throwIfInvalid">A value indicating whether to throw a <see cref="NotSupportedException" /> when the combination is invalid.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the combination is valid; otherwise <c>false</c>.
|
||||
/// </returns>
|
||||
/// <exception cref="NotSupportedException">Occurs when the combination is invalid, and <paramref name="throwIfInvalid" /> is true.</exception>
|
||||
/// <remarks>
|
||||
/// <para>When validation is exact, the combination must match the variation exactly. For instance, if the variation is Culture, then
|
||||
/// a culture is required. When validation is not strict, the combination must be equivalent, or more restrictive: if the variation is
|
||||
/// Culture, an invariant combination is ok.</para>
|
||||
/// <para>Basically, exact is for one content type, or one property type, and !exact is for "all property types" of one content type.</para>
|
||||
/// <para>Both <paramref name="culture"/> and <paramref name="segment"/> can be "*" to indicate "all of them".</para>
|
||||
/// <para>Both <paramref name="culture" /> and <paramref name="segment" /> can be "*" to indicate "all of them".</para>
|
||||
/// </remarks>
|
||||
/// <exception cref="NotSupportedException">Occurs when the combination is invalid, and <paramref name="throwIfInvalid"/> is true.</exception>
|
||||
public static bool ValidateVariation(this ContentVariation variation, string culture, string segment, bool exact, bool wildcards, bool throwIfInvalid)
|
||||
{
|
||||
culture = culture.NullOrWhiteSpaceAsNull();
|
||||
@@ -161,13 +302,14 @@ namespace Umbraco.Core
|
||||
if (variation.VariesByCulture())
|
||||
{
|
||||
// varies by culture
|
||||
// in exact mode, the culture cannot be null
|
||||
// in exact mode, the culture cannot be null
|
||||
if (exact && culture == null)
|
||||
{
|
||||
if (throwIfInvalid)
|
||||
throw new NotSupportedException($"Culture may not be null because culture variation is enabled.");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -178,9 +320,10 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (throwIfInvalid)
|
||||
throw new NotSupportedException($"Culture \"{culture}\" is invalid because culture variation is disabled.");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if it does not vary by segment
|
||||
// the segment cannot have a value
|
||||
@@ -190,6 +333,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (throwIfInvalid)
|
||||
throw new NotSupportedException($"Segment \"{segment}\" is invalid because segment variation is disabled.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,43 +3,42 @@
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides extension methods to enums.
|
||||
/// Provides extension methods to <see cref="Enum"/>.
|
||||
/// </summary>
|
||||
public static class EnumExtensions
|
||||
{
|
||||
// note:
|
||||
// - no need to HasFlagExact, that's basically an == test
|
||||
// - HasFlagAll cannot be named HasFlag because ext. methods never take priority over instance methods
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a flag enum has all the specified values.
|
||||
/// Determines whether all the flags/bits are set within the enum value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>True when all bits set in <paramref name="uses"/> are set in <paramref name="use"/>, though other bits may be set too.</para>
|
||||
/// <para>This is the behavior of the original <see cref="Enum.HasFlag"/> method.</para>
|
||||
/// </remarks>
|
||||
public static bool HasFlagAll<T>(this T use, T uses)
|
||||
/// <typeparam name="T">The enum type.</typeparam>
|
||||
/// <param name="value">The enum value.</param>
|
||||
/// <param name="flags">The flags.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if all the flags/bits are set within the enum value; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
[Obsolete("Use Enum.HasFlag() or bitwise operations (if performance is important) instead.")]
|
||||
public static bool HasFlagAll<T>(this T value, T flags)
|
||||
where T : Enum
|
||||
{
|
||||
var num = Convert.ToUInt64(use);
|
||||
var nums = Convert.ToUInt64(uses);
|
||||
|
||||
return (num & nums) == nums;
|
||||
return value.HasFlag(flags);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a flag enum has any of the specified values.
|
||||
/// Determines whether any of the flags/bits are set within the enum value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>True when at least one of the bits set in <paramref name="uses"/> is set in <paramref name="use"/>.</para>
|
||||
/// </remarks>
|
||||
public static bool HasFlagAny<T>(this T use, T uses)
|
||||
/// <typeparam name="T">The enum type.</typeparam>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="flags">The flags.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if any of the flags/bits are set within the enum value; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool HasFlagAny<T>(this T value, T flags)
|
||||
where T : Enum
|
||||
{
|
||||
var num = Convert.ToUInt64(use);
|
||||
var nums = Convert.ToUInt64(uses);
|
||||
var v = Convert.ToUInt64(value);
|
||||
var f = Convert.ToUInt64(flags);
|
||||
|
||||
return (num & nums) > 0;
|
||||
return (v & f) > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using Umbraco.Core.Models.Membership;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
internal class UserGroupWithUsers
|
||||
public class UserGroupWithUsers
|
||||
{
|
||||
public UserGroupWithUsers(IUserGroup userGroup, IUser[] addedUsers, IUser[] removedUsers)
|
||||
{
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The exception that is thrown when a null reference, or an empty argument,
|
||||
/// is passed to a method that does not accept it as a valid argument.
|
||||
/// The exception that is thrown when a null reference, or an empty argument, is passed to a method that does not accept it as a valid argument.
|
||||
/// </summary>
|
||||
/// <seealso cref="System.ArgumentNullException" />
|
||||
[Obsolete("Throw an ArgumentNullException when the parameter is null or an ArgumentException when its empty instead.")]
|
||||
[Serializable]
|
||||
public class ArgumentNullOrEmptyException : ArgumentNullException
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ArgumentNullOrEmptyException"/> class
|
||||
/// with the name of the parameter that caused this exception.
|
||||
/// Initializes a new instance of the <see cref="ArgumentNullOrEmptyException" /> class.
|
||||
/// </summary>
|
||||
public ArgumentNullOrEmptyException()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ArgumentNullOrEmptyException" /> class with the name of the parameter that caused this exception.
|
||||
/// </summary>
|
||||
/// <param name="paramName">The named of the parameter that caused the exception.</param>
|
||||
public ArgumentNullOrEmptyException(string paramName)
|
||||
@@ -18,13 +26,30 @@ namespace Umbraco.Core.Exceptions
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ArgumentNullOrEmptyException"/> class
|
||||
/// with a specified error message and the name of the parameter that caused this exception.
|
||||
/// Initializes a new instance of the <see cref="ArgumentNullOrEmptyException" /> class with a specified error message and the name of the parameter that caused this exception.
|
||||
/// </summary>
|
||||
/// <param name="paramName">The named of the parameter that caused the exception.</param>
|
||||
/// <param name="message">A message that describes the error.</param>
|
||||
public ArgumentNullOrEmptyException(string paramName, string message)
|
||||
: base(paramName, message)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ArgumentNullOrEmptyException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for this exception.</param>
|
||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
|
||||
public ArgumentNullOrEmptyException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ArgumentNullOrEmptyException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="info">The object that holds the serialized object data.</param>
|
||||
/// <param name="context">An object that describes the source or destination of the serialized data.</param>
|
||||
protected ArgumentNullOrEmptyException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,45 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The exception that is thrown when authorization failed.
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Exception" />
|
||||
[Serializable]
|
||||
public class AuthorizationException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AuthorizationException" /> class.
|
||||
/// </summary>
|
||||
public AuthorizationException()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AuthorizationException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
public AuthorizationException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AuthorizationException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
|
||||
public AuthorizationException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AuthorizationException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
|
||||
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
|
||||
protected AuthorizationException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Exceptions
|
||||
@@ -6,6 +7,8 @@ namespace Umbraco.Core.Exceptions
|
||||
/// <summary>
|
||||
/// An exception that is thrown if the Umbraco application cannot boot.
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Exception" />
|
||||
[Serializable]
|
||||
public class BootFailedException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
@@ -14,27 +17,47 @@ namespace Umbraco.Core.Exceptions
|
||||
public const string DefaultMessage = "Boot failed: Umbraco cannot run. See Umbraco's log file for more details.";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Exception"/> class with a specified error message.
|
||||
/// Initializes a new instance of the <see cref="BootFailedException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error. </param>
|
||||
public BootFailedException()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Exception" /> class with a specified error message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
public BootFailedException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Exception"/> class with a specified error message
|
||||
/// Initializes a new instance of the <see cref="Exception" /> class with a specified error message
|
||||
/// and a reference to the inner exception which is the cause of this exception.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error. </param>
|
||||
/// <param name="inner">The inner exception, or null.</param>
|
||||
public BootFailedException(string message, Exception inner)
|
||||
: base(message, inner)
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
/// <param name="innerException">The inner exception, or null.</param>
|
||||
public BootFailedException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Rethrows a captured <see cref="BootFailedException"/>.
|
||||
/// Initializes a new instance of the <see cref="BootFailedException" /> class.
|
||||
/// </summary>
|
||||
/// <remarks>The exception can be null, in which case a default message is used.</remarks>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
|
||||
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
|
||||
protected BootFailedException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Rethrows a captured <see cref="BootFailedException" />.
|
||||
/// </summary>
|
||||
/// <param name="bootFailedException">The boot failed exception.</param>
|
||||
/// <exception cref="Umbraco.Core.Exceptions.BootFailedException">
|
||||
/// </exception>
|
||||
/// <remarks>
|
||||
/// The exception can be null, in which case a default message is used.
|
||||
/// </remarks>
|
||||
public static void Rethrow(BootFailedException bootFailedException)
|
||||
{
|
||||
if (bootFailedException == null)
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Exceptions
|
||||
{
|
||||
internal class ConnectionException : Exception
|
||||
{
|
||||
public ConnectionException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,98 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <seealso cref="System.Exception" />
|
||||
[Serializable]
|
||||
internal class DataOperationException<T> : Exception
|
||||
where T : Enum
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the operation.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The operation.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This object should be serializable to prevent a <see cref="SerializationException" /> to be thrown.
|
||||
/// </remarks>
|
||||
public T Operation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DataOperationException{T}" /> class.
|
||||
/// </summary>
|
||||
public DataOperationException()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DataOperationException{T}" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
public DataOperationException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DataOperationException{T}" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
|
||||
public DataOperationException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DataOperationException{T}" /> class.
|
||||
/// </summary>
|
||||
/// <param name="operation">The operation.</param>
|
||||
public DataOperationException(T operation)
|
||||
: this(operation, "Data operation exception: " + operation)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DataOperationException{T}" /> class.
|
||||
/// </summary>
|
||||
/// <param name="operation">The operation.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
public DataOperationException(T operation, string message)
|
||||
: base(message)
|
||||
{
|
||||
Operation = operation;
|
||||
}
|
||||
|
||||
public DataOperationException(T operation)
|
||||
: base("Data operation exception: " + operation)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DataOperationException{T}" /> class.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
|
||||
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
|
||||
/// <exception cref="ArgumentNullException">info</exception>
|
||||
protected DataOperationException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
Operation = operation;
|
||||
Operation = (T)Enum.Parse(typeof(T), info.GetString(nameof(Operation)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When overridden in a derived class, sets the <see cref="T:System.Runtime.Serialization.SerializationInfo" /> with information about the exception.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
|
||||
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
|
||||
/// <exception cref="ArgumentNullException">info</exception>
|
||||
public override void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (info == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(info));
|
||||
}
|
||||
|
||||
info.AddValue(nameof(Operation), Enum.GetName(typeof(T), Operation));
|
||||
|
||||
base.GetObjectData(info, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +1,126 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The exception that is thrown when a composition is invalid.
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Exception" />
|
||||
[Serializable]
|
||||
public class InvalidCompositionException : Exception
|
||||
{
|
||||
public InvalidCompositionException(string contentTypeAlias, string addedCompositionAlias, string[] propertyTypeAliass)
|
||||
{
|
||||
ContentTypeAlias = contentTypeAlias;
|
||||
AddedCompositionAlias = addedCompositionAlias;
|
||||
PropertyTypeAliases = propertyTypeAliass;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the content type alias.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The content type alias.
|
||||
/// </value>
|
||||
public string ContentTypeAlias { get; }
|
||||
|
||||
public InvalidCompositionException(string contentTypeAlias, string[] propertyTypeAliass)
|
||||
{
|
||||
ContentTypeAlias = contentTypeAlias;
|
||||
PropertyTypeAliases = propertyTypeAliass;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the added composition alias.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The added composition alias.
|
||||
/// </value>
|
||||
public string AddedCompositionAlias { get; }
|
||||
|
||||
public string ContentTypeAlias { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets the property type aliases.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The property type aliases.
|
||||
/// </value>
|
||||
public string[] PropertyTypeAliases { get; }
|
||||
|
||||
public string AddedCompositionAlias { get; private set; }
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InvalidCompositionException" /> class.
|
||||
/// </summary>
|
||||
public InvalidCompositionException()
|
||||
{ }
|
||||
|
||||
public string[] PropertyTypeAliases { get; private set; }
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InvalidCompositionException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="contentTypeAlias">The content type alias.</param>
|
||||
/// <param name="propertyTypeAliases">The property type aliases.</param>
|
||||
public InvalidCompositionException(string contentTypeAlias, string[] propertyTypeAliases)
|
||||
: this(contentTypeAlias, null, propertyTypeAliases)
|
||||
{ }
|
||||
|
||||
public override string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
return AddedCompositionAlias.IsNullOrWhiteSpace()
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InvalidCompositionException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="contentTypeAlias">The content type alias.</param>
|
||||
/// <param name="addedCompositionAlias">The added composition alias.</param>
|
||||
/// <param name="propertyTypeAliases">The property type aliases.</param>
|
||||
public InvalidCompositionException(string contentTypeAlias, string addedCompositionAlias, string[] propertyTypeAliases)
|
||||
: this(addedCompositionAlias.IsNullOrWhiteSpace()
|
||||
? string.Format(
|
||||
"ContentType with alias '{0}' has an invalid composition " +
|
||||
"and there was a conflict on the following PropertyTypes: '{1}'. " +
|
||||
"PropertyTypes must have a unique alias across all Compositions in order to compose a valid ContentType Composition.",
|
||||
ContentTypeAlias, string.Join(", ", PropertyTypeAliases))
|
||||
contentTypeAlias, string.Join(", ", propertyTypeAliases))
|
||||
: string.Format(
|
||||
"ContentType with alias '{0}' was added as a Composition to ContentType with alias '{1}', " +
|
||||
"but there was a conflict on the following PropertyTypes: '{2}'. " +
|
||||
"PropertyTypes must have a unique alias across all Compositions in order to compose a valid ContentType Composition.",
|
||||
AddedCompositionAlias, ContentTypeAlias, string.Join(", ", PropertyTypeAliases));
|
||||
addedCompositionAlias, contentTypeAlias, string.Join(", ", propertyTypeAliases)))
|
||||
{
|
||||
ContentTypeAlias = contentTypeAlias;
|
||||
AddedCompositionAlias = addedCompositionAlias;
|
||||
PropertyTypeAliases = propertyTypeAliases;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InvalidCompositionException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
public InvalidCompositionException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InvalidCompositionException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
|
||||
public InvalidCompositionException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InvalidCompositionException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
|
||||
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
|
||||
protected InvalidCompositionException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
ContentTypeAlias = info.GetString(nameof(ContentTypeAlias));
|
||||
AddedCompositionAlias = info.GetString(nameof(AddedCompositionAlias));
|
||||
PropertyTypeAliases = (string[])info.GetValue(nameof(PropertyTypeAliases), typeof(string[]));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When overridden in a derived class, sets the <see cref="T:System.Runtime.Serialization.SerializationInfo" /> with information about the exception.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
|
||||
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
|
||||
/// <exception cref="ArgumentNullException">info</exception>
|
||||
public override void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (info == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(info));
|
||||
}
|
||||
|
||||
info.AddValue(nameof(ContentTypeAlias), ContentTypeAlias);
|
||||
info.AddValue(nameof(AddedCompositionAlias), AddedCompositionAlias);
|
||||
info.AddValue(nameof(PropertyTypeAliases), PropertyTypeAliases);
|
||||
|
||||
base.GetObjectData(info, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,25 +4,42 @@ using System.Runtime.Serialization;
|
||||
namespace Umbraco.Core.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal exception that in theory should never ben thrown, it is only thrown in circumstances that should never happen
|
||||
/// Represents an internal exception that in theory should never been thrown, it is only thrown in circumstances that should never happen.
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Exception" />
|
||||
[Serializable]
|
||||
internal class PanicException : Exception
|
||||
public class PanicException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PanicException" /> class.
|
||||
/// </summary>
|
||||
public PanicException()
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
public PanicException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PanicException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
public PanicException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
|
||||
public PanicException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PanicException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
|
||||
public PanicException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{ }
|
||||
|
||||
protected PanicException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PanicException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
|
||||
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
|
||||
protected PanicException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,52 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The exception that is thrown when a requested method or operation is not, and will not be, implemented.
|
||||
/// </summary>
|
||||
/// <remarks>The <see cref="NotImplementedException"/> is to be used when some code is not implemented,
|
||||
/// <remarks>
|
||||
/// The <see cref="NotImplementedException" /> is to be used when some code is not implemented,
|
||||
/// but should eventually be implemented (i.e. work in progress) and is reported by tools such as ReSharper.
|
||||
/// This exception is to be used when some code is not implemented, and is not meant to be, for whatever
|
||||
/// reason.</remarks>
|
||||
/// reason.
|
||||
/// </remarks>
|
||||
/// <seealso cref="System.NotImplementedException" />
|
||||
[Serializable]
|
||||
[Obsolete("If a method or operation is not, and will not be, implemented, it is invalid or not supported, so we should throw either an InvalidOperationException or NotSupportedException instead.")]
|
||||
public class WontImplementException : NotImplementedException
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WontImplementException"/> class.
|
||||
/// Initializes a new instance of the <see cref="WontImplementException" /> class.
|
||||
/// </summary>
|
||||
public WontImplementException()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WontImplementException"/> class with a specified reason message.
|
||||
/// Initializes a new instance of the <see cref="WontImplementException" /> class with a specified reason message.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
public WontImplementException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WontImplementException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="inner">The exception that is the cause of the current exception. If the <paramref name="inner" /> parameter is not <see langword="null" />, the current exception is raised in a <see langword="catch" /> block that handles the inner exception.</param>
|
||||
public WontImplementException(string message, Exception inner)
|
||||
: base(message, inner)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WontImplementException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
|
||||
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
|
||||
protected WontImplementException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Umbraco.Core
|
||||
|
||||
internal void AddDateTime(DateTime d)
|
||||
{
|
||||
_writer.Write(d.Ticks);;
|
||||
_writer.Write(d.Ticks);
|
||||
}
|
||||
|
||||
internal void AddString(string s)
|
||||
|
||||
@@ -1,20 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// The exception that is thrown when the caller does not have the required permission to access a file.
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Exception" />
|
||||
[Obsolete("Throw an UnauthorizedAccessException instead.")]
|
||||
[Serializable]
|
||||
public class FileSecurityException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FileSecurityException" /> class.
|
||||
/// </summary>
|
||||
public FileSecurityException()
|
||||
{
|
||||
{ }
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FileSecurityException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
public FileSecurityException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
|
||||
public FileSecurityException(string message) : base(message)
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FileSecurityException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
|
||||
public FileSecurityException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{ }
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FileSecurityException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
|
||||
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
|
||||
protected FileSecurityException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Media;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
@@ -92,7 +87,8 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
if (propertyType == null) throw new ArgumentNullException(nameof(propertyType));
|
||||
if (string.IsNullOrWhiteSpace(filename)) throw new ArgumentNullOrEmptyException(nameof(filename));
|
||||
if (filename == null) throw new ArgumentNullException(nameof(filename));
|
||||
if (string.IsNullOrWhiteSpace(filename)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(filename));
|
||||
if (filestream == null) throw new ArgumentNullException(nameof(filestream));
|
||||
|
||||
// clear the old file, if any
|
||||
@@ -111,7 +107,8 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException(nameof(content));
|
||||
if (propertyType == null) throw new ArgumentNullException(nameof(propertyType));
|
||||
if (string.IsNullOrWhiteSpace(sourcepath)) throw new ArgumentNullOrEmptyException(nameof(sourcepath));
|
||||
if (sourcepath == null) throw new ArgumentNullException(nameof(sourcepath));
|
||||
if (string.IsNullOrWhiteSpace(sourcepath)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(sourcepath));
|
||||
|
||||
// ensure we have a file to copy
|
||||
if (FileExists(sourcepath) == false) return null;
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
@@ -39,9 +38,11 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public PhysicalFileSystem(string rootPath, string rootUrl)
|
||||
{
|
||||
if (string.IsNullOrEmpty(rootPath)) throw new ArgumentNullOrEmptyException(nameof(rootPath));
|
||||
if (string.IsNullOrEmpty(rootUrl)) throw new ArgumentNullOrEmptyException(nameof(rootUrl));
|
||||
if (rootPath.StartsWith("~/")) throw new ArgumentException("The rootPath argument cannot be a virtual path and cannot start with '~/'");
|
||||
if (rootPath == null) throw new ArgumentNullException(nameof(rootPath));
|
||||
if (string.IsNullOrEmpty(rootPath)) throw new ArgumentException("Value can't be empty.", nameof(rootPath));
|
||||
if (rootUrl == null) throw new ArgumentNullException(nameof(rootUrl));
|
||||
if (string.IsNullOrEmpty(rootUrl)) throw new ArgumentException("Value can't be empty.", nameof(rootUrl));
|
||||
if (rootPath.StartsWith("~/")) throw new ArgumentException("Value can't be a virtual path and start with '~/'.", nameof(rootPath));
|
||||
|
||||
// rootPath should be... rooted, as in, it's a root path!
|
||||
if (Path.IsPathRooted(rootPath) == false)
|
||||
@@ -314,7 +315,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
// nothing prevents us to reach the file, security-wise, yet it is outside
|
||||
// this filesystem's root - throw
|
||||
throw new FileSecurityException("File '" + opath + "' is outside this filesystem's root.");
|
||||
throw new UnauthorizedAccessException("File '" + opath + "' is outside this filesystem's root.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -29,13 +29,13 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public static string MacroPartials => MvcViews + "/MacroPartials/";
|
||||
|
||||
public static string Media => IOHelper.ReturnPath("umbracoMediaPath", "~/media");
|
||||
public static string Media => IOHelper.ReturnPath(Constants.AppSettings.MediaPath, "~/media");
|
||||
|
||||
public static string Scripts => IOHelper.ReturnPath("umbracoScriptsPath", "~/scripts");
|
||||
public static string Scripts => IOHelper.ReturnPath(Constants.AppSettings.ScriptsPath, "~/scripts");
|
||||
|
||||
public static string Css => IOHelper.ReturnPath("umbracoCssPath", "~/css");
|
||||
public static string Css => IOHelper.ReturnPath(Constants.AppSettings.CssPath, "~/css");
|
||||
|
||||
public static string Umbraco => IOHelper.ReturnPath("umbracoPath", "~/umbraco");
|
||||
public static string Umbraco => IOHelper.ReturnPath(Constants.AppSettings.Path, "~/umbraco");
|
||||
|
||||
public static string Packages => Data + "/packages";
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ namespace Umbraco.Core.Manifest
|
||||
// '-content/foo', // hide for content type 'foo'
|
||||
// '+content/*', // show for all other content types
|
||||
// '+media/*', // show for all media types
|
||||
// '-member/foo' // hide for member type 'foo'
|
||||
// '+member/*' // show for all member types
|
||||
// '+role/admin' // show for admin users. Role based permissions will override others.
|
||||
// ]
|
||||
// },
|
||||
@@ -56,6 +58,10 @@ namespace Umbraco.Core.Manifest
|
||||
partA = "media";
|
||||
partB = media.ContentType.Alias;
|
||||
break;
|
||||
case IMember member:
|
||||
partA = "member";
|
||||
partB = member.ContentType.Alias;
|
||||
break;
|
||||
|
||||
default:
|
||||
return null;
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
@@ -42,7 +41,8 @@ namespace Umbraco.Core.Manifest
|
||||
_cache = appCaches.RuntimeCache;
|
||||
_validators = validators ?? throw new ArgumentNullException(nameof(validators));
|
||||
_filters = filters ?? throw new ArgumentNullException(nameof(filters));
|
||||
if (string.IsNullOrWhiteSpace(path)) throw new ArgumentNullOrEmptyException(nameof(path));
|
||||
if (path == null) throw new ArgumentNullException(nameof(path));
|
||||
if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(path));
|
||||
Path = path;
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
@@ -155,8 +155,8 @@ namespace Umbraco.Core.Manifest
|
||||
/// </summary>
|
||||
internal PackageManifest ParseManifest(string text)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
throw new ArgumentNullOrEmptyException(nameof(text));
|
||||
if (text == null) throw new ArgumentNullException(nameof(text));
|
||||
if (string.IsNullOrWhiteSpace(text)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(text));
|
||||
|
||||
var manifest = JsonConvert.DeserializeObject<PackageManifest>(text,
|
||||
new DataEditorConverter(_logger),
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Migrations
|
||||
{
|
||||
/// <summary>
|
||||
/// Used if a migration has executed but the whole process has failed and cannot be rolled back
|
||||
/// </summary>
|
||||
internal class DataLossException : Exception
|
||||
{
|
||||
public DataLossException(string msg)
|
||||
: base(msg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public DataLossException(string msg, Exception inner)
|
||||
: base(msg, inner)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using Umbraco.Core.Exceptions;
|
||||
using System;
|
||||
using Umbraco.Core.Migrations.Expressions.Common;
|
||||
using Umbraco.Core.Migrations.Expressions.Delete.Column;
|
||||
using Umbraco.Core.Migrations.Expressions.Delete.Constraint;
|
||||
@@ -39,8 +39,9 @@ namespace Umbraco.Core.Migrations.Expressions.Delete
|
||||
/// <inheritdoc />
|
||||
public IExecutableBuilder KeysAndIndexes(string tableName, bool local = true, bool foreign = true)
|
||||
{
|
||||
if (tableName.IsNullOrWhiteSpace())
|
||||
throw new ArgumentNullOrEmptyException(nameof(tableName));
|
||||
if (tableName == null) throw new ArgumentNullException(nameof(tableName));
|
||||
if (string.IsNullOrWhiteSpace(tableName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(tableName));
|
||||
|
||||
return new DeleteKeysAndIndexesBuilder(_context) { TableName = tableName, DeleteLocal = local, DeleteForeign = foreign };
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +1,49 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Migrations
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents errors that occurs when a migration exception is not executed.
|
||||
/// The exception that is thrown when a migration expression is not executed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Migration expression such as Alter.Table(...).Do() *must* end with Do() else they are
|
||||
/// not executed. When a non-executed expression is detected, an IncompleteMigrationExpressionException
|
||||
/// is thrown.</para>
|
||||
/// Migration expressions such as Alter.Table(...).Do() must end with Do(), else they are not executed.
|
||||
/// When a non-executed expression is detected, an IncompleteMigrationExpressionException is thrown.
|
||||
/// </remarks>
|
||||
/// <seealso cref="System.Exception" />
|
||||
[Serializable]
|
||||
public class IncompleteMigrationExpressionException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IncompleteMigrationExpressionException"/> class.
|
||||
/// Initializes a new instance of the <see cref="IncompleteMigrationExpressionException" /> class.
|
||||
/// </summary>
|
||||
public IncompleteMigrationExpressionException()
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IncompleteMigrationExpressionException"/> class with a message.
|
||||
/// Initializes a new instance of the <see cref="IncompleteMigrationExpressionException" /> class with a message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error.</param>
|
||||
public IncompleteMigrationExpressionException(string message)
|
||||
: base(message)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IncompleteMigrationExpressionException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (<see langword="Nothing" /> in Visual Basic) if no inner exception is specified.</param>
|
||||
public IncompleteMigrationExpressionException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="IncompleteMigrationExpressionException" /> class.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
|
||||
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
|
||||
protected IncompleteMigrationExpressionException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Migrations.Upgrade;
|
||||
@@ -278,8 +277,10 @@ namespace Umbraco.Core.Migrations.Install
|
||||
/// <param name="logger">A logger.</param>
|
||||
private static void SaveConnectionString(string connectionString, string providerName, ILogger logger)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(connectionString)) throw new ArgumentNullOrEmptyException(nameof(connectionString));
|
||||
if (string.IsNullOrWhiteSpace(providerName)) throw new ArgumentNullOrEmptyException(nameof(providerName));
|
||||
if (connectionString == null) throw new ArgumentNullException(nameof(connectionString));
|
||||
if (string.IsNullOrWhiteSpace(connectionString)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(connectionString));
|
||||
if (providerName == null) throw new ArgumentNullException(nameof(providerName));
|
||||
if (string.IsNullOrWhiteSpace(providerName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(providerName));
|
||||
|
||||
var fileSource = "web.config";
|
||||
var fileName = IOHelper.MapPath(SystemDirectories.Root +"/" + fileSource);
|
||||
|
||||
@@ -151,6 +151,8 @@ namespace Umbraco.Core.Migrations.Install
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.Domains, Name = "Domains" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.KeyValues, Name = "KeyValues" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.Languages, Name = "Languages" });
|
||||
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.MainDom, Name = "MainDom" });
|
||||
}
|
||||
|
||||
private void CreateContentTypeData()
|
||||
@@ -169,8 +171,8 @@ namespace Umbraco.Core.Migrations.Install
|
||||
private void CreateUserGroupData()
|
||||
{
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.UserGroup, "id", false, new UserGroupDto { Id = 1, StartMediaId = -1, StartContentId = -1, Alias = Constants.Security.AdminGroupAlias, Name = "Administrators", DefaultPermissions = "CADMOSKTPIURZ:5F7ï", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-medal" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.UserGroup, "id", false, new UserGroupDto { Id = 2, StartMediaId = -1, StartContentId = -1, Alias = "writer", Name = "Writers", DefaultPermissions = "CAH:F", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-edit" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.UserGroup, "id", false, new UserGroupDto { Id = 3, StartMediaId = -1, StartContentId = -1, Alias = "editor", Name = "Editors", DefaultPermissions = "CADMOSKTPUZ:5Fï", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-tools" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.UserGroup, "id", false, new UserGroupDto { Id = 2, StartMediaId = -1, StartContentId = -1, Alias = Constants.Security.WriterGroupAlias, Name = "Writers", DefaultPermissions = "CAH:F", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-edit" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.UserGroup, "id", false, new UserGroupDto { Id = 3, StartMediaId = -1, StartContentId = -1, Alias = Constants.Security.EditorGroupAlias, Name = "Editors", DefaultPermissions = "CADMOSKTPUZ:5Fï", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-tools" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.UserGroup, "id", false, new UserGroupDto { Id = 4, StartMediaId = -1, StartContentId = -1, Alias = Constants.Security.TranslatorGroupAlias, Name = "Translators", DefaultPermissions = "AF", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-globe" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.UserGroup, "id", false, new UserGroupDto { Id = 5, StartMediaId = -1, StartContentId = -1, Alias = Constants.Security.SensitiveDataGroupAlias, Name = "Sensitive data", DefaultPermissions = "", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-lock" });
|
||||
}
|
||||
@@ -310,14 +312,27 @@ namespace Umbraco.Core.Migrations.Install
|
||||
private void CreateRelationTypeData()
|
||||
{
|
||||
var relationType = new RelationTypeDto { Id = 1, Alias = Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias, ChildObjectType = Constants.ObjectTypes.Document, ParentObjectType = Constants.ObjectTypes.Document, Dual = true, Name = Constants.Conventions.RelationTypes.RelateDocumentOnCopyName };
|
||||
relationType.UniqueId = (relationType.Alias + "____" + relationType.Name).ToGuid();
|
||||
relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name);
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);
|
||||
relationType = new RelationTypeDto { Id = 2, Alias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias, ChildObjectType = Constants.ObjectTypes.Document, ParentObjectType = Constants.ObjectTypes.Document, Dual = false, Name = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteName };
|
||||
relationType.UniqueId = (relationType.Alias + "____" + relationType.Name).ToGuid();
|
||||
relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name);
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);
|
||||
relationType = new RelationTypeDto { Id = 3, Alias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias, ChildObjectType = Constants.ObjectTypes.Media, ParentObjectType = Constants.ObjectTypes.Media, Dual = false, Name = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName };
|
||||
relationType.UniqueId = (relationType.Alias + "____" + relationType.Name).ToGuid();
|
||||
relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name);
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);
|
||||
|
||||
relationType = new RelationTypeDto { Id = 4, Alias = Constants.Conventions.RelationTypes.RelatedMediaAlias, ChildObjectType = null, ParentObjectType = null, Dual = false, Name = Constants.Conventions.RelationTypes.RelatedMediaName };
|
||||
relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name);
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);
|
||||
|
||||
relationType = new RelationTypeDto { Id = 5, Alias = Constants.Conventions.RelationTypes.RelatedDocumentAlias, ChildObjectType = null, ParentObjectType = null, Dual = false, Name = Constants.Conventions.RelationTypes.RelatedDocumentName };
|
||||
relationType.UniqueId = CreateUniqueRelationTypeId(relationType.Alias, relationType.Name);
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);
|
||||
}
|
||||
|
||||
internal static Guid CreateUniqueRelationTypeId(string alias, string name)
|
||||
{
|
||||
return (alias + "____" + name).ToGuid();
|
||||
}
|
||||
|
||||
private void CreateKeyValueData()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
@@ -84,10 +85,18 @@ namespace Umbraco.Core.Migrations
|
||||
|
||||
protected void ReplaceColumn<T>(string tableName, string currentName, string newName)
|
||||
{
|
||||
AddColumn<T>(tableName, newName, out var sqls);
|
||||
Execute.Sql($"UPDATE {SqlSyntax.GetQuotedTableName(tableName)} SET {SqlSyntax.GetQuotedColumnName(newName)}={SqlSyntax.GetQuotedColumnName(currentName)}").Do();
|
||||
foreach (var sql in sqls) Execute.Sql(sql).Do();
|
||||
Delete.Column(currentName).FromTable(tableName).Do();
|
||||
if (DatabaseType.IsSqlCe())
|
||||
{
|
||||
AddColumn<T>(tableName, newName, out var sqls);
|
||||
Execute.Sql($"UPDATE {SqlSyntax.GetQuotedTableName(tableName)} SET {SqlSyntax.GetQuotedColumnName(newName)}={SqlSyntax.GetQuotedColumnName(currentName)}").Do();
|
||||
foreach (var sql in sqls) Execute.Sql(sql).Do();
|
||||
Delete.Column(currentName).FromTable(tableName).Do();
|
||||
}
|
||||
else
|
||||
{
|
||||
Execute.Sql(SqlSyntax.FormatColumnRename(tableName, currentName, newName)).Do();
|
||||
AlterColumn<T>(tableName, newName);
|
||||
}
|
||||
}
|
||||
|
||||
protected bool TableExists(string tableName)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Type = System.Type;
|
||||
@@ -25,7 +24,9 @@ namespace Umbraco.Core.Migrations
|
||||
/// <param name="name">The name of the plan.</param>
|
||||
public MigrationPlan(string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name));
|
||||
if (name == null) throw new ArgumentNullException(nameof(name));
|
||||
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
|
||||
|
||||
Name = name;
|
||||
}
|
||||
|
||||
@@ -43,7 +44,8 @@ namespace Umbraco.Core.Migrations
|
||||
private MigrationPlan Add(string sourceState, string targetState, Type migration)
|
||||
{
|
||||
if (sourceState == null) throw new ArgumentNullException(nameof(sourceState));
|
||||
if (string.IsNullOrWhiteSpace(targetState)) throw new ArgumentNullOrEmptyException(nameof(targetState));
|
||||
if (targetState == null) throw new ArgumentNullException(nameof(targetState));
|
||||
if (string.IsNullOrWhiteSpace(targetState)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(targetState));
|
||||
if (sourceState == targetState) throw new ArgumentException("Source and target state cannot be identical.");
|
||||
if (migration == null) throw new ArgumentNullException(nameof(migration));
|
||||
if (!migration.Implements<IMigration>()) throw new ArgumentException($"Type {migration.Name} does not implement IMigration.", nameof(migration));
|
||||
@@ -135,10 +137,12 @@ namespace Umbraco.Core.Migrations
|
||||
/// </summary>
|
||||
public MigrationPlan ToWithClone(string startState, string endState, string targetState)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(startState)) throw new ArgumentNullOrEmptyException(nameof(startState));
|
||||
if (string.IsNullOrWhiteSpace(endState)) throw new ArgumentNullOrEmptyException(nameof(endState));
|
||||
if (string.IsNullOrWhiteSpace(targetState)) throw new ArgumentNullOrEmptyException(nameof(targetState));
|
||||
|
||||
if (startState == null) throw new ArgumentNullException(nameof(startState));
|
||||
if (string.IsNullOrWhiteSpace(startState)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(startState));
|
||||
if (endState == null) throw new ArgumentNullException(nameof(endState));
|
||||
if (string.IsNullOrWhiteSpace(endState)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(endState));
|
||||
if (targetState == null) throw new ArgumentNullException(nameof(targetState));
|
||||
if (string.IsNullOrWhiteSpace(targetState)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(targetState));
|
||||
if (startState == endState) throw new ArgumentException("Start and end states cannot be identical.");
|
||||
|
||||
startState = startState.Trim();
|
||||
@@ -317,7 +321,7 @@ namespace Umbraco.Core.Migrations
|
||||
// throw a raw exception here: this should never happen as the plan has
|
||||
// been validated - this is just a paranoid safety test
|
||||
if (!_transitions.TryGetValue(origState, out transition))
|
||||
throw new Exception($"Unknown state \"{origState}\".");
|
||||
throw new InvalidOperationException($"Unknown state \"{origState}\".");
|
||||
}
|
||||
|
||||
// prepare and de-duplicate post-migrations, only keeping the 1st occurence
|
||||
@@ -339,7 +343,7 @@ namespace Umbraco.Core.Migrations
|
||||
// safety check - again, this should never happen as the plan has been validated,
|
||||
// and this is just a paranoid safety test
|
||||
if (origState != _finalState)
|
||||
throw new Exception($"Internal error, reached state {origState} which is not final state {_finalState}");
|
||||
throw new InvalidOperationException($"Internal error, reached state {origState} which is not final state {_finalState}");
|
||||
|
||||
return origState;
|
||||
}
|
||||
@@ -358,7 +362,7 @@ namespace Umbraco.Core.Migrations
|
||||
var states = new List<string> { origState };
|
||||
|
||||
if (!_transitions.TryGetValue(origState, out var transition))
|
||||
throw new Exception($"Unknown state \"{origState}\".");
|
||||
throw new InvalidOperationException($"Unknown state \"{origState}\".");
|
||||
|
||||
while (transition != null)
|
||||
{
|
||||
@@ -373,12 +377,12 @@ namespace Umbraco.Core.Migrations
|
||||
}
|
||||
|
||||
if (!_transitions.TryGetValue(origState, out transition))
|
||||
throw new Exception($"Unknown state \"{origState}\".");
|
||||
throw new InvalidOperationException($"Unknown state \"{origState}\".");
|
||||
}
|
||||
|
||||
// safety check
|
||||
if (origState != (toState ?? _finalState))
|
||||
throw new Exception($"Internal error, reached state {origState} which is not state {toState ?? _finalState}");
|
||||
throw new InvalidOperationException($"Internal error, reached state {origState} which is not state {toState ?? _finalState}");
|
||||
|
||||
return states;
|
||||
}
|
||||
@@ -417,7 +421,7 @@ namespace Umbraco.Core.Migrations
|
||||
public override string ToString()
|
||||
{
|
||||
return MigrationType == typeof(NoopMigration)
|
||||
? $"{(SourceState == "" ? "<empty>" : SourceState)} --> {TargetState}"
|
||||
? $"{(SourceState == string.Empty ? "<empty>" : SourceState)} --> {TargetState}"
|
||||
: $"{SourceState} -- ({MigrationType.FullName}) --> {TargetState}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Umbraco.Core.Migrations.Upgrade.Common
|
||||
{
|
||||
// remove those that may already have keys
|
||||
Delete.KeysAndIndexes(Constants.DatabaseSchema.Tables.KeyValue).Do();
|
||||
Delete.KeysAndIndexes(Constants.DatabaseSchema.Tables.PropertyData).Do();
|
||||
|
||||
// re-create *all* keys and indexes
|
||||
foreach (var x in DatabaseSchemaCreator.OrderedTables)
|
||||
|
||||
@@ -6,6 +6,7 @@ using Umbraco.Core.Migrations.Upgrade.Common;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_8_0_0;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_8_0_1;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_8_1_0;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_8_6_0;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade
|
||||
{
|
||||
@@ -165,6 +166,7 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
.As("{0576E786-5C30-4000-B969-302B61E90CA3}");
|
||||
|
||||
To<FixLanguageIsoCodeLength>("{48AD6CCD-C7A4-4305-A8AB-38728AD23FC5}");
|
||||
To<AddPackagesSectionAccess>("{DF470D86-E5CA-42AC-9780-9D28070E25F9}");
|
||||
|
||||
// finish migrating from v7 - recreate all keys and indexes
|
||||
To<CreateKeysAndIndexes>("{3F9764F5-73D0-4D45-8804-1240A66E43A2}");
|
||||
@@ -182,6 +184,16 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
To<RenameUserLoginDtoDateIndex>("{0372A42B-DECF-498D-B4D1-6379E907EB94}");
|
||||
To<FixContentNuCascade>("{5B1E0D93-F5A3-449B-84BA-65366B84E2D4}");
|
||||
|
||||
// to 8.6.0...
|
||||
To<UpdateRelationTypeTable>("{4759A294-9860-46BC-99F9-B4C975CAE580}");
|
||||
To<AddNewRelationTypes>("{0BC866BC-0665-487A-9913-0290BD0169AD}");
|
||||
To<AddPropertyTypeValidationMessageColumns>("{3D67D2C8-5E65-47D0-A9E1-DC2EE0779D6B}");
|
||||
To<MissingContentVersionsIndexes>("{EE288A91-531B-4995-8179-1D62D9AA3E2E}");
|
||||
To<AddMainDomLock>("{2AB29964-02A1-474D-BD6B-72148D2A53A2}");
|
||||
|
||||
|
||||
To<MissingDictionaryIndex>("{a78e3369-8ea3-40ec-ad3f-5f76929d2b20}");
|
||||
|
||||
//FINAL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
{
|
||||
public class AddPackagesSectionAccess : MigrationBase
|
||||
{
|
||||
public AddPackagesSectionAccess(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
// Any user group which had access to the Developer section should have access to Packages
|
||||
Database.Execute($@"
|
||||
insert into {Constants.DatabaseSchema.Tables.UserGroup2App}
|
||||
select userGroupId, '{Constants.Applications.Packages}'
|
||||
from {Constants.DatabaseSchema.Tables.UserGroup2App}
|
||||
where app='developer'");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,8 +75,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
var labelPropertyTypes = Database.Fetch<PropertyTypeDto>(Sql()
|
||||
.Select<PropertyTypeDto>(x => x.Id, x => x.Alias)
|
||||
.From<PropertyTypeDto>()
|
||||
.Where<PropertyTypeDto>(x => x.DataTypeId == Constants.DataTypes.LabelString)
|
||||
);
|
||||
.Where<PropertyTypeDto>(x => x.DataTypeId == Constants.DataTypes.LabelString));
|
||||
|
||||
var intPropertyAliases = new[] { Constants.Conventions.Media.Width, Constants.Conventions.Media.Height, Constants.Conventions.Member.FailedPasswordAttempts };
|
||||
var bigintPropertyAliases = new[] { Constants.Conventions.Media.Bytes };
|
||||
@@ -101,16 +100,18 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
foreach (var value in values)
|
||||
Database.Execute(Sql()
|
||||
.Update<PropertyDataDto>(u => u
|
||||
.Set(x => x.IntegerValue, string.IsNullOrWhiteSpace(value.VarcharValue) ? (int?) null : int.Parse(value.VarcharValue, NumberStyles.Any, CultureInfo.InvariantCulture))
|
||||
.Set(x => x.TextValue, null))
|
||||
.Set(x => x.IntegerValue, string.IsNullOrWhiteSpace(value.VarcharValue) ? (int?)null : int.Parse(value.VarcharValue, NumberStyles.Any, CultureInfo.InvariantCulture))
|
||||
.Set(x => x.TextValue, null)
|
||||
.Set(x => x.VarcharValue, null))
|
||||
.Where<PropertyDataDto>(x => x.Id == value.Id));
|
||||
|
||||
values = Database.Fetch<PropertyDataValue>(Sql().Select<PropertyDataDto>(x => x.Id, x => x.VarcharValue).From<PropertyDataDto>().WhereIn<PropertyDataDto>(x => x.PropertyTypeId, dtPropertyTypes));
|
||||
foreach (var value in values)
|
||||
Database.Execute(Sql()
|
||||
.Update<PropertyDataDto>(u => u
|
||||
.Set(x => x.DateValue, string.IsNullOrWhiteSpace(value.VarcharValue) ? (DateTime?) null : DateTime.Parse(value.VarcharValue, CultureInfo.InvariantCulture, DateTimeStyles.None))
|
||||
.Set(x => x.TextValue, null))
|
||||
.Set(x => x.DateValue, string.IsNullOrWhiteSpace(value.VarcharValue) ? (DateTime?)null : DateTime.Parse(value.VarcharValue, CultureInfo.InvariantCulture, DateTimeStyles.None))
|
||||
.Set(x => x.TextValue, null)
|
||||
.Set(x => x.VarcharValue, null))
|
||||
.Where<PropertyDataDto>(x => x.Id == value.Id));
|
||||
|
||||
// anything that's custom... ppl will have to figure it out manually, there isn't much we can do about it
|
||||
|
||||
@@ -4,8 +4,10 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NPoco;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_8_0_0.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.DatabaseAnnotations;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
@@ -47,14 +49,14 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
}
|
||||
}
|
||||
|
||||
var propertyTypes = Database.Fetch<PropertyTypeDto>(Sql().Select<PropertyTypeDto>().From<PropertyTypeDto>());
|
||||
var propertyTypes = Database.Fetch<PropertyTypeDto80>(Sql().Select<PropertyTypeDto80>().From<PropertyTypeDto80>());
|
||||
foreach (var dto in propertyTypes)
|
||||
{
|
||||
dto.Variations = GetNewValue(dto.Variations);
|
||||
Database.Update(dto);
|
||||
}
|
||||
|
||||
var contentTypes = Database.Fetch<ContentTypeDto>(Sql().Select<ContentTypeDto>().From<ContentTypeDto>());
|
||||
var contentTypes = Database.Fetch<ContentTypeDto80>(Sql().Select<ContentTypeDto80>().From<ContentTypeDto80>());
|
||||
foreach (var dto in contentTypes)
|
||||
{
|
||||
dto.Variations = GetNewValue(dto.Variations);
|
||||
@@ -62,57 +64,11 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
}
|
||||
}
|
||||
|
||||
// we *need* to use this private DTO here, which does *not* have extra properties, which would kill the migration
|
||||
// we *need* to use these private DTOs here, which does *not* have extra properties, which would kill the migration
|
||||
|
||||
[TableName(TableName)]
|
||||
[PrimaryKey("pk")]
|
||||
[ExplicitColumns]
|
||||
private class ContentTypeDto
|
||||
{
|
||||
public const string TableName = Constants.DatabaseSchema.Tables.ContentType;
|
||||
|
||||
|
||||
[Column("pk")]
|
||||
[PrimaryKeyColumn(IdentitySeed = 535)]
|
||||
public int PrimaryKey { get; set; }
|
||||
|
||||
[Column("nodeId")]
|
||||
[ForeignKey(typeof(NodeDto))]
|
||||
[Index(IndexTypes.UniqueNonClustered, Name = "IX_cmsContentType")]
|
||||
public int NodeId { get; set; }
|
||||
|
||||
[Column("alias")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public string Alias { get; set; }
|
||||
|
||||
[Column("icon")]
|
||||
[Index(IndexTypes.NonClustered)]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public string Icon { get; set; }
|
||||
|
||||
[Column("thumbnail")]
|
||||
[Constraint(Default = "folder.png")]
|
||||
public string Thumbnail { get; set; }
|
||||
|
||||
[Column("description")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[Length(1500)]
|
||||
public string Description { get; set; }
|
||||
|
||||
[Column("isContainer")]
|
||||
[Constraint(Default = "0")]
|
||||
public bool IsContainer { get; set; }
|
||||
|
||||
[Column("allowAtRoot")]
|
||||
[Constraint(Default = "0")]
|
||||
public bool AllowAtRoot { get; set; }
|
||||
|
||||
[Column("variations")]
|
||||
[Constraint(Default = "1" /*ContentVariation.InvariantNeutral*/)]
|
||||
public byte Variations { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public NodeDto NodeDto { get; set; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_8_0_0.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
@@ -34,11 +33,11 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
}
|
||||
|
||||
var sqlPropertyTpes = Sql()
|
||||
.Select<PropertyTypeDto>()
|
||||
.From<PropertyTypeDto>()
|
||||
.Where<PropertyTypeDto>(x => dataTypeIds.Contains(x.DataTypeId));
|
||||
.Select<PropertyTypeDto80>()
|
||||
.From<PropertyTypeDto80>()
|
||||
.Where<PropertyTypeDto80>(x => dataTypeIds.Contains(x.DataTypeId));
|
||||
|
||||
var propertyTypeIds = Database.Fetch<PropertyTypeDto>(sqlPropertyTpes).Select(x => x.Id).ToList();
|
||||
var propertyTypeIds = Database.Fetch<PropertyTypeDto80>(sqlPropertyTpes).Select(x => x.Id).ToList();
|
||||
|
||||
if (propertyTypeIds.Count == 0) return;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
if (string.IsNullOrEmpty(dataType.Configuration))
|
||||
{
|
||||
config.Format = "YYYY-MM-DD";
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
using NPoco;
|
||||
using Umbraco.Core.Persistence.DatabaseAnnotations;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0.Models
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Snapshot of the <see cref="ContentTypeDto"/> as it was at version 8.0
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is required during migrations the schema of this table changed and running SQL against the new table would result in errors
|
||||
/// </remarks>
|
||||
[TableName(TableName)]
|
||||
[PrimaryKey("pk")]
|
||||
[ExplicitColumns]
|
||||
internal class ContentTypeDto80
|
||||
{
|
||||
public const string TableName = Constants.DatabaseSchema.Tables.ContentType;
|
||||
|
||||
[Column("pk")]
|
||||
[PrimaryKeyColumn(IdentitySeed = 535)]
|
||||
public int PrimaryKey { get; set; }
|
||||
|
||||
[Column("nodeId")]
|
||||
[ForeignKey(typeof(NodeDto))]
|
||||
[Index(IndexTypes.UniqueNonClustered, Name = "IX_cmsContentType")]
|
||||
public int NodeId { get; set; }
|
||||
|
||||
[Column("alias")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public string Alias { get; set; }
|
||||
|
||||
[Column("icon")]
|
||||
[Index(IndexTypes.NonClustered)]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public string Icon { get; set; }
|
||||
|
||||
[Column("thumbnail")]
|
||||
[Constraint(Default = "folder.png")]
|
||||
public string Thumbnail { get; set; }
|
||||
|
||||
[Column("description")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[Length(1500)]
|
||||
public string Description { get; set; }
|
||||
|
||||
[Column("isContainer")]
|
||||
[Constraint(Default = "0")]
|
||||
public bool IsContainer { get; set; }
|
||||
|
||||
[Column("allowAtRoot")]
|
||||
[Constraint(Default = "0")]
|
||||
public bool AllowAtRoot { get; set; }
|
||||
|
||||
[Column("variations")]
|
||||
[Constraint(Default = "1" /*ContentVariation.InvariantNeutral*/)]
|
||||
public byte Variations { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public NodeDto NodeDto { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
using NPoco;
|
||||
using System;
|
||||
using Umbraco.Core.Persistence.DatabaseAnnotations;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Snapshot of the <see cref="PropertyDataDto"/> as it was at version 8.0
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is required during migrations the schema of this table changed and running SQL against the new table would result in errors
|
||||
/// </remarks>
|
||||
[TableName(TableName)]
|
||||
[PrimaryKey("id")]
|
||||
[ExplicitColumns]
|
||||
internal class PropertyDataDto80
|
||||
{
|
||||
public const string TableName = Constants.DatabaseSchema.Tables.PropertyData;
|
||||
public const int VarcharLength = 512;
|
||||
public const int SegmentLength = 256;
|
||||
|
||||
private decimal? _decimalValue;
|
||||
|
||||
// pk, not used at the moment (never updating)
|
||||
[Column("id")]
|
||||
[PrimaryKeyColumn]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("versionId")]
|
||||
[ForeignKey(typeof(ContentVersionDto))]
|
||||
[Index(IndexTypes.UniqueNonClustered, Name = "IX_" + TableName + "_VersionId", ForColumns = "versionId,propertyTypeId,languageId,segment")]
|
||||
public int VersionId { get; set; }
|
||||
|
||||
[Column("propertyTypeId")]
|
||||
[ForeignKey(typeof(PropertyTypeDto80))]
|
||||
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_PropertyTypeId")]
|
||||
public int PropertyTypeId { get; set; }
|
||||
|
||||
[Column("languageId")]
|
||||
[ForeignKey(typeof(LanguageDto))]
|
||||
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_LanguageId")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public int? LanguageId { get; set; }
|
||||
|
||||
[Column("segment")]
|
||||
[Index(IndexTypes.NonClustered, Name = "IX_" + TableName + "_Segment")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[Length(SegmentLength)]
|
||||
public string Segment { get; set; }
|
||||
|
||||
[Column("intValue")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public int? IntegerValue { get; set; }
|
||||
|
||||
[Column("decimalValue")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public decimal? DecimalValue
|
||||
{
|
||||
get => _decimalValue;
|
||||
set => _decimalValue = value?.Normalize();
|
||||
}
|
||||
|
||||
[Column("dateValue")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public DateTime? DateValue { get; set; }
|
||||
|
||||
[Column("varcharValue")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[Length(VarcharLength)]
|
||||
public string VarcharValue { get; set; }
|
||||
|
||||
[Column("textValue")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[SpecialDbType(SpecialDbTypes.NTEXT)]
|
||||
public string TextValue { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
[Reference(ReferenceType.OneToOne, ColumnName = "PropertyTypeId")]
|
||||
public PropertyTypeDto80 PropertyTypeDto { get; set; }
|
||||
|
||||
[Ignore]
|
||||
public object Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IntegerValue.HasValue)
|
||||
return IntegerValue.Value;
|
||||
|
||||
if (DecimalValue.HasValue)
|
||||
return DecimalValue.Value;
|
||||
|
||||
if (DateValue.HasValue)
|
||||
return DateValue.Value;
|
||||
|
||||
if (!string.IsNullOrEmpty(VarcharValue))
|
||||
return VarcharValue;
|
||||
|
||||
if (!string.IsNullOrEmpty(TextValue))
|
||||
return TextValue;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public PropertyDataDto80 Clone(int versionId)
|
||||
{
|
||||
return new PropertyDataDto80
|
||||
{
|
||||
VersionId = versionId,
|
||||
PropertyTypeId = PropertyTypeId,
|
||||
LanguageId = LanguageId,
|
||||
Segment = Segment,
|
||||
IntegerValue = IntegerValue,
|
||||
DecimalValue = DecimalValue,
|
||||
DateValue = DateValue,
|
||||
VarcharValue = VarcharValue,
|
||||
TextValue = TextValue,
|
||||
PropertyTypeDto = PropertyTypeDto
|
||||
};
|
||||
}
|
||||
|
||||
protected bool Equals(PropertyDataDto other)
|
||||
{
|
||||
return Id == other.Id;
|
||||
}
|
||||
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
return
|
||||
!ReferenceEquals(null, other) // other is not null
|
||||
&& (ReferenceEquals(this, other) // and either ref-equals, or same id
|
||||
|| other is PropertyDataDto pdata && pdata.Id == Id);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
// ReSharper disable once NonReadonlyMemberInGetHashCode
|
||||
return Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using NPoco;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core.Persistence.DatabaseAnnotations;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Snapshot of the <see cref="PropertyTypeDto"/> as it was at version 8.0
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is required during migrations before 8.6 since the schema has changed and running SQL against the new table would result in errors
|
||||
/// </remarks>
|
||||
[TableName(Constants.DatabaseSchema.Tables.PropertyType)]
|
||||
[PrimaryKey("id")]
|
||||
[ExplicitColumns]
|
||||
internal class PropertyTypeDto80
|
||||
{
|
||||
[Column("id")]
|
||||
[PrimaryKeyColumn(IdentitySeed = 50)]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("dataTypeId")]
|
||||
[ForeignKey(typeof(DataTypeDto), Column = "nodeId")]
|
||||
public int DataTypeId { get; set; }
|
||||
|
||||
[Column("contentTypeId")]
|
||||
[ForeignKey(typeof(ContentTypeDto), Column = "nodeId")]
|
||||
public int ContentTypeId { get; set; }
|
||||
|
||||
[Column("propertyTypeGroupId")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[ForeignKey(typeof(PropertyTypeGroupDto))]
|
||||
public int? PropertyTypeGroupId { get; set; }
|
||||
|
||||
[Index(IndexTypes.NonClustered, Name = "IX_cmsPropertyTypeAlias")]
|
||||
[Column("Alias")]
|
||||
public string Alias { get; set; }
|
||||
|
||||
[Column("Name")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Column("sortOrder")]
|
||||
[Constraint(Default = "0")]
|
||||
public int SortOrder { get; set; }
|
||||
|
||||
[Column("mandatory")]
|
||||
[Constraint(Default = "0")]
|
||||
public bool Mandatory { get; set; }
|
||||
|
||||
[Column("validationRegExp")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
public string ValidationRegExp { get; set; }
|
||||
|
||||
[Column("Description")]
|
||||
[NullSetting(NullSetting = NullSettings.Null)]
|
||||
[Length(2000)]
|
||||
public string Description { get; set; }
|
||||
|
||||
[Column("variations")]
|
||||
[Constraint(Default = "1" /*ContentVariation.InvariantNeutral*/)]
|
||||
public byte Variations { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
[Reference(ReferenceType.OneToOne, ColumnName = "DataTypeId")]
|
||||
public DataTypeDto DataTypeDto { get; set; }
|
||||
|
||||
[Column("UniqueID")]
|
||||
[NullSetting(NullSetting = NullSettings.NotNull)]
|
||||
[Constraint(Default = SystemMethods.NewGuid)]
|
||||
[Index(IndexTypes.UniqueNonClustered, Name = "IX_cmsPropertyTypeUniqueID")]
|
||||
public Guid UniqueId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
{
|
||||
@@ -17,14 +18,24 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
|
||||
AddColumn<MediaVersionDto>("id", out var sqls);
|
||||
|
||||
// SQLCE does not support UPDATE...FROM
|
||||
var temp2 = Database.Fetch<dynamic>($@"SELECT v.versionId, v.id
|
||||
if (Database.DatabaseType.IsSqlCe())
|
||||
{
|
||||
// SQLCE does not support UPDATE...FROM
|
||||
var versions = Database.Fetch<dynamic>($@"SELECT v.versionId, v.id
|
||||
FROM cmsContentVersion v
|
||||
JOIN umbracoNode n on v.contentId=n.id
|
||||
WHERE n.nodeObjectType='{Constants.ObjectTypes.Media}'");
|
||||
foreach (var t in temp2)
|
||||
Execute.Sql($"UPDATE {Constants.DatabaseSchema.Tables.MediaVersion} SET id={t.id} WHERE versionId='{t.versionId}'").Do();
|
||||
|
||||
foreach (var t in versions)
|
||||
Execute.Sql($"UPDATE {Constants.DatabaseSchema.Tables.MediaVersion} SET id={t.id} WHERE versionId='{t.versionId}'").Do();
|
||||
}
|
||||
else
|
||||
{
|
||||
Database.Execute($@"UPDATE {Constants.DatabaseSchema.Tables.MediaVersion} SET id=v.id
|
||||
FROM {Constants.DatabaseSchema.Tables.MediaVersion} m
|
||||
JOIN cmsContentVersion v on m.versionId = v.versionId
|
||||
JOIN umbracoNode n on v.contentId=n.id
|
||||
WHERE n.nodeObjectType='{Constants.ObjectTypes.Media}'");
|
||||
}
|
||||
foreach (var sql in sqls)
|
||||
Execute.Sql(sql).Do();
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Migrations.Install;
|
||||
@@ -19,6 +20,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
public override void Migrate()
|
||||
{
|
||||
MigratePropertyData();
|
||||
CreatePropertyDataIndexes();
|
||||
MigrateContentAndPropertyTypes();
|
||||
MigrateContent();
|
||||
MigrateVersions();
|
||||
@@ -74,10 +76,20 @@ HAVING COUNT(v2.id) <> 1").Any())
|
||||
{
|
||||
Alter.Table(PreTables.PropertyData).AddColumn("versionId2").AsInt32().Nullable().Do();
|
||||
|
||||
// SQLCE does not support UPDATE...FROM
|
||||
var temp = Database.Fetch<dynamic>($"SELECT id, versionId FROM {PreTables.ContentVersion}");
|
||||
foreach (var t in temp)
|
||||
Database.Execute($"UPDATE {PreTables.PropertyData} SET versionId2=@v2 WHERE versionId=@v1", new { v1 = t.versionId, v2 = t.id });
|
||||
if (Database.DatabaseType.IsSqlCe())
|
||||
{
|
||||
// SQLCE does not support UPDATE...FROM
|
||||
var versions = Database.Fetch<dynamic>($"SELECT id, versionId FROM {PreTables.ContentVersion}");
|
||||
foreach (var t in versions)
|
||||
Database.Execute($"UPDATE {PreTables.PropertyData} SET versionId2=@v2 WHERE versionId=@v1", new { v1 = t.versionId, v2 = t.id });
|
||||
}
|
||||
else
|
||||
{
|
||||
Database.Execute($@"UPDATE {PreTables.PropertyData} SET versionId2={PreTables.ContentVersion}.id
|
||||
FROM {PreTables.ContentVersion}
|
||||
INNER JOIN {PreTables.PropertyData} ON {PreTables.ContentVersion}.versionId = {PreTables.PropertyData}.versionId");
|
||||
}
|
||||
|
||||
Delete.Column("versionId").FromTable(PreTables.PropertyData).Do();
|
||||
ReplaceColumn<PropertyDataDto>(PreTables.PropertyData, "versionId2", "versionId");
|
||||
}
|
||||
@@ -90,6 +102,22 @@ HAVING COUNT(v2.id) <> 1").Any())
|
||||
Rename.Table(PreTables.PropertyData).To(Constants.DatabaseSchema.Tables.PropertyData).Do();
|
||||
}
|
||||
|
||||
private void CreatePropertyDataIndexes()
|
||||
{
|
||||
// Creates a temporary index on umbracoPropertyData to speed up other migrations which update property values.
|
||||
// It will be removed in CreateKeysAndIndexes before the normal indexes for the table are created
|
||||
var tableDefinition = Persistence.DatabaseModelDefinitions.DefinitionFactory.GetTableDefinition(typeof(PropertyDataDto), SqlSyntax);
|
||||
Execute.Sql(SqlSyntax.FormatPrimaryKey(tableDefinition)).Do();
|
||||
Create.Index("IX_umbracoPropertyData_Temp").OnTable(PropertyDataDto.TableName)
|
||||
.WithOptions().Unique()
|
||||
.WithOptions().NonClustered()
|
||||
.OnColumn("versionId").Ascending()
|
||||
.OnColumn("propertyTypeId").Ascending()
|
||||
.OnColumn("languageId").Ascending()
|
||||
.OnColumn("segment").Ascending()
|
||||
.Do();
|
||||
}
|
||||
|
||||
private void MigrateContentAndPropertyTypes()
|
||||
{
|
||||
if (!ColumnExists(PreTables.ContentType, "variations"))
|
||||
@@ -153,22 +181,40 @@ HAVING COUNT(v2.id) <> 1").Any())
|
||||
ReplaceColumn<ContentVersionDto>(PreTables.ContentVersion, "ContentId", "nodeId");
|
||||
|
||||
// populate contentVersion text, current and userId columns for documents
|
||||
// SQLCE does not support UPDATE...FROM
|
||||
var temp1 = Database.Fetch<dynamic>($"SELECT versionId, text, newest, documentUser FROM {PreTables.Document}");
|
||||
foreach (var t in temp1)
|
||||
Database.Execute($@"UPDATE {PreTables.ContentVersion} SET text=@text, {SqlSyntax.GetQuotedColumnName("current")}=@current, userId=@userId WHERE versionId=@versionId",
|
||||
new { text = t.text, current = t.newest, userId=t.documentUser, versionId=t.versionId });
|
||||
if (Database.DatabaseType.IsSqlCe())
|
||||
{
|
||||
// SQLCE does not support UPDATE...FROM
|
||||
var documents = Database.Fetch<dynamic>($"SELECT versionId, text, published, newest, documentUser FROM {PreTables.Document}");
|
||||
foreach (var t in documents)
|
||||
Database.Execute($@"UPDATE {PreTables.ContentVersion} SET text=@text, {SqlSyntax.GetQuotedColumnName("current")}=@current, userId=@userId WHERE versionId=@versionId",
|
||||
new { text = t.text, current = t.newest && !t.published, userId = t.documentUser, versionId = t.versionId });
|
||||
}
|
||||
else
|
||||
{
|
||||
Database.Execute($@"UPDATE {PreTables.ContentVersion} SET text=d.text, {SqlSyntax.GetQuotedColumnName("current")}=(d.newest & ~d.published), userId=d.documentUser
|
||||
FROM {PreTables.ContentVersion} v INNER JOIN {PreTables.Document} d ON d.versionId = v.versionId");
|
||||
}
|
||||
|
||||
// populate contentVersion text and current columns for non-documents, userId is default
|
||||
// SQLCE does not support UPDATE...FROM
|
||||
var temp2 = Database.Fetch<dynamic>($@"SELECT cver.versionId, n.text
|
||||
if (Database.DatabaseType.IsSqlCe())
|
||||
{
|
||||
// SQLCE does not support UPDATE...FROM
|
||||
var otherContent = Database.Fetch<dynamic>($@"SELECT cver.versionId, n.text
|
||||
FROM {PreTables.ContentVersion} cver
|
||||
JOIN {SqlSyntax.GetQuotedTableName(Constants.DatabaseSchema.Tables.Node)} n ON cver.nodeId=n.id
|
||||
WHERE cver.versionId NOT IN (SELECT versionId FROM {SqlSyntax.GetQuotedTableName(PreTables.Document)})");
|
||||
|
||||
foreach (var t in temp2)
|
||||
Database.Execute($@"UPDATE {PreTables.ContentVersion} SET text=@text, {SqlSyntax.GetQuotedColumnName("current")}=1, userId=0 WHERE versionId=@versionId",
|
||||
new { text = t.text, versionId=t.versionId });
|
||||
foreach (var t in otherContent)
|
||||
Database.Execute($@"UPDATE {PreTables.ContentVersion} SET text=@text, {SqlSyntax.GetQuotedColumnName("current")}=1, userId=0 WHERE versionId=@versionId",
|
||||
new { text = t.text, versionId = t.versionId });
|
||||
}
|
||||
else
|
||||
{
|
||||
Database.Execute($@"UPDATE {PreTables.ContentVersion} SET text=n.text, {SqlSyntax.GetQuotedColumnName("current")}=1, userId=0
|
||||
FROM {PreTables.ContentVersion} cver
|
||||
JOIN {SqlSyntax.GetQuotedTableName(Constants.DatabaseSchema.Tables.Node)} n ON cver.nodeId=n.id
|
||||
WHERE cver.versionId NOT IN (SELECT versionId FROM {SqlSyntax.GetQuotedTableName(PreTables.Document)})");
|
||||
}
|
||||
|
||||
// create table
|
||||
Create.Table<DocumentVersionDto>(withoutKeysAndIndexes: true).Do();
|
||||
@@ -179,36 +225,42 @@ SELECT cver.id, doc.templateId, doc.published
|
||||
FROM {SqlSyntax.GetQuotedTableName(PreTables.ContentVersion)} cver
|
||||
JOIN {SqlSyntax.GetQuotedTableName(PreTables.Document)} doc ON doc.nodeId=cver.nodeId AND doc.versionId=cver.versionId");
|
||||
|
||||
|
||||
// need to add extra rows for where published=newest
|
||||
// 'cos INSERT above has inserted the 'published' document version
|
||||
// and v8 always has a 'edited' document version too
|
||||
var temp3 = Database.Fetch<dynamic>($@"SELECT doc.nodeId, doc.updateDate, doc.documentUser, doc.text, doc.templateId, cver.id versionId
|
||||
Database.Execute($@"
|
||||
INSERT INTO {SqlSyntax.GetQuotedTableName(PreTables.ContentVersion)} (nodeId, versionId, versionDate, userId, {SqlSyntax.GetQuotedColumnName("current")}, text)
|
||||
SELECT doc.nodeId, NEWID(), doc.updateDate, doc.documentUser, 1, doc.text
|
||||
FROM {SqlSyntax.GetQuotedTableName(PreTables.Document)} doc
|
||||
JOIN {SqlSyntax.GetQuotedTableName(PreTables.ContentVersion)} cver ON doc.nodeId=cver.nodeId AND doc.versionId=cver.versionId
|
||||
WHERE doc.newest=1 AND doc.published=1");
|
||||
var getIdentity = "@@@@IDENTITY";
|
||||
foreach (var t in temp3)
|
||||
{
|
||||
Database.Execute($@"INSERT INTO {SqlSyntax.GetQuotedTableName(PreTables.ContentVersion)} (nodeId, versionId, versionDate, userId, {SqlSyntax.GetQuotedColumnName("current")}, text)
|
||||
VALUES (@nodeId, @versionId, @versionDate, @userId, 1, @text)", new { nodeId=t.nodeId, versionId=Guid.NewGuid(), versionDate=t.updateDate, userId=t.documentUser, text=t.text });
|
||||
var id = Database.ExecuteScalar<int>("SELECT " + getIdentity);
|
||||
Database.Execute($"UPDATE {SqlSyntax.GetQuotedTableName(PreTables.ContentVersion)} SET {SqlSyntax.GetQuotedColumnName("current")}=0 WHERE nodeId=@0 AND id<>@1", (int) t.nodeId, id);
|
||||
Database.Execute($@"INSERT INTO {SqlSyntax.GetQuotedTableName(Constants.DatabaseSchema.Tables.DocumentVersion)} (id, templateId, published)
|
||||
VALUES (@id, @templateId, 0)", new { id=id, templateId=t.templateId });
|
||||
|
||||
var versionId = (int) t.versionId;
|
||||
var pdatas = Database.Fetch<PropertyDataDto>(Sql().Select<PropertyDataDto>().From<PropertyDataDto>().Where<PropertyDataDto>(x => x.VersionId == versionId));
|
||||
foreach (var pdata in pdatas)
|
||||
{
|
||||
pdata.VersionId = id;
|
||||
Database.Insert(pdata);
|
||||
}
|
||||
}
|
||||
Database.Execute($@"
|
||||
INSERT INTO {SqlSyntax.GetQuotedTableName(Constants.DatabaseSchema.Tables.DocumentVersion)} (id, templateId, published)
|
||||
SELECT cverNew.id, doc.templateId, 0
|
||||
FROM {SqlSyntax.GetQuotedTableName(PreTables.Document)} doc
|
||||
JOIN {SqlSyntax.GetQuotedTableName(PreTables.ContentVersion)} cverNew ON doc.nodeId = cverNew.nodeId
|
||||
WHERE doc.newest=1 AND doc.published=1 AND cverNew.{SqlSyntax.GetQuotedColumnName("current")} = 1");
|
||||
|
||||
Database.Execute($@"
|
||||
INSERT INTO {SqlSyntax.GetQuotedTableName(PropertyDataDto.TableName)} (propertytypeid,languageId,segment,textValue,varcharValue,decimalValue,intValue,dateValue,versionId)
|
||||
SELECT propertytypeid,languageId,segment,textValue,varcharValue,decimalValue,intValue,dateValue,cverNew.id
|
||||
FROM {SqlSyntax.GetQuotedTableName(PreTables.Document)} doc
|
||||
JOIN {SqlSyntax.GetQuotedTableName(PreTables.ContentVersion)} cver ON doc.nodeId=cver.nodeId AND doc.versionId=cver.versionId
|
||||
JOIN {SqlSyntax.GetQuotedTableName(PreTables.ContentVersion)} cverNew ON doc.nodeId = cverNew.nodeId
|
||||
JOIN {SqlSyntax.GetQuotedTableName(PropertyDataDto.TableName)} pd ON pd.versionId=cver.id
|
||||
WHERE doc.newest=1 AND doc.published=1 AND cverNew.{SqlSyntax.GetQuotedColumnName("current")} = 1");
|
||||
|
||||
|
||||
// reduce document to 1 row per content
|
||||
Database.Execute($@"DELETE FROM {PreTables.Document}
|
||||
WHERE versionId NOT IN (SELECT (versionId) FROM {PreTables.ContentVersion} WHERE {SqlSyntax.GetQuotedColumnName("current")} = 1) AND (published<>1 OR newest<>1)");
|
||||
|
||||
// ensure that documents with a published version are marked as published
|
||||
Database.Execute($@"UPDATE {PreTables.Document} SET published=1 WHERE nodeId IN (
|
||||
SELECT nodeId FROM {PreTables.ContentVersion} cv INNER JOIN {Constants.DatabaseSchema.Tables.DocumentVersion} dv ON dv.id = cv.id WHERE dv.published=1)");
|
||||
|
||||
// drop some document columns
|
||||
Delete.Column("text").FromTable(PreTables.Document).Do();
|
||||
Delete.Column("templateId").FromTable(PreTables.Document).Do();
|
||||
@@ -223,7 +275,7 @@ WHERE versionId NOT IN (SELECT (versionId) FROM {PreTables.ContentVersion} WHERE
|
||||
if (!ColumnExists(PreTables.Document, "edited"))
|
||||
{
|
||||
AddColumn<DocumentDto>(PreTables.Document, "edited", out var sqls);
|
||||
Database.Execute($"UPDATE {SqlSyntax.GetQuotedTableName(PreTables.Document)} SET edited=0");
|
||||
Database.Execute($"UPDATE {SqlSyntax.GetQuotedTableName(PreTables.Document)} SET edited=~published");
|
||||
foreach (var sql in sqls) Database.Execute(sql);
|
||||
}
|
||||
|
||||
@@ -240,11 +292,15 @@ JOIN {Constants.DatabaseSchema.Tables.PropertyData} v1 ON cv1.id=v1.versionId
|
||||
JOIN {PreTables.ContentVersion} cv2 ON n.id=cv2.nodeId
|
||||
JOIN {Constants.DatabaseSchema.Tables.DocumentVersion} dv ON cv2.id=dv.id AND dv.published=1
|
||||
JOIN {Constants.DatabaseSchema.Tables.PropertyData} v2 ON cv2.id=v2.versionId
|
||||
WHERE v1.propertyTypeId=v2.propertyTypeId AND v1.languageId=v2.languageId AND v1.segment=v2.segment");
|
||||
WHERE v1.propertyTypeId=v2.propertyTypeId
|
||||
AND (v1.languageId=v2.languageId OR (v1.languageId IS NULL AND v2.languageId IS NULL))
|
||||
AND (v1.segment=v2.segment OR (v1.segment IS NULL AND v2.segment IS NULL))");
|
||||
|
||||
var updatedIds = new HashSet<int>();
|
||||
foreach (var t in temp)
|
||||
if (t.intValue1 != t.intValue2 || t.decimalValue1 != t.decimalValue2 || t.dateValue1 != t.dateValue2 || t.varcharValue1 != t.varcharValue2 || t.textValue1 != t.textValue2)
|
||||
Database.Execute("UPDATE {SqlSyntax.GetQuotedTableName(PreTables.Document)} SET edited=1 WHERE nodeId=@nodeIdd", new { t.id });
|
||||
if (updatedIds.Add((int)t.id))
|
||||
Database.Execute($"UPDATE {SqlSyntax.GetQuotedTableName(PreTables.Document)} SET edited=1 WHERE nodeId=@nodeId", new { nodeId = t.id });
|
||||
|
||||
// drop more columns
|
||||
Delete.Column("versionId").FromTable(PreTables.ContentVersion).Do();
|
||||
|
||||
+23
-10
@@ -5,6 +5,7 @@ using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.Migrations.PostMigrations;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_8_0_0.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -27,15 +28,15 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_1_0
|
||||
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
|
||||
var sqlPropertyData = Sql()
|
||||
.Select<PropertyDataDto>(r => r.Select(x => x.PropertyTypeDto, r1 => r1.Select(x => x.DataTypeDto)))
|
||||
.From<PropertyDataDto>()
|
||||
.InnerJoin<PropertyTypeDto>().On<PropertyDataDto, PropertyTypeDto>((left, right) => left.PropertyTypeId == right.Id)
|
||||
.InnerJoin<DataTypeDto>().On<PropertyTypeDto, DataTypeDto>((left, right) => left.DataTypeId == right.NodeId)
|
||||
.Select<PropertyDataDto80>(r => r.Select(x => x.PropertyTypeDto, r1 => r1.Select(x => x.DataTypeDto)))
|
||||
.From<PropertyDataDto80>()
|
||||
.InnerJoin<PropertyTypeDto80>().On<PropertyDataDto80, PropertyTypeDto80>((left, right) => left.PropertyTypeId == right.Id)
|
||||
.InnerJoin<DataTypeDto>().On<PropertyTypeDto80, DataTypeDto>((left, right) => left.DataTypeId == right.NodeId)
|
||||
.Where<DataTypeDto>(x =>
|
||||
x.EditorAlias == Constants.PropertyEditors.Aliases.TinyMce ||
|
||||
x.EditorAlias == Constants.PropertyEditors.Aliases.Grid);
|
||||
|
||||
var properties = Database.Fetch<PropertyDataDto>(sqlPropertyData);
|
||||
var properties = Database.Fetch<PropertyDataDto80>(sqlPropertyData);
|
||||
|
||||
var exceptions = new List<Exception>();
|
||||
foreach (var property in properties)
|
||||
@@ -43,6 +44,8 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_1_0
|
||||
var value = property.TextValue;
|
||||
if (string.IsNullOrWhiteSpace(value)) continue;
|
||||
|
||||
|
||||
bool propertyChanged = false;
|
||||
if (property.PropertyTypeDto.DataTypeDto.EditorAlias == Constants.PropertyEditors.Aliases.Grid)
|
||||
{
|
||||
try
|
||||
@@ -55,7 +58,8 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_1_0
|
||||
var controlValue = control["value"];
|
||||
if (controlValue?.Type == JTokenType.String)
|
||||
{
|
||||
control["value"] = UpdateMediaUrls(mediaLinkPattern, controlValue.Value<string>());
|
||||
control["value"] = UpdateMediaUrls(mediaLinkPattern, controlValue.Value<string>(), out var controlChanged);
|
||||
propertyChanged |= controlChanged;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,10 +80,11 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_1_0
|
||||
}
|
||||
else
|
||||
{
|
||||
property.TextValue = UpdateMediaUrls(mediaLinkPattern, value);
|
||||
property.TextValue = UpdateMediaUrls(mediaLinkPattern, value, out propertyChanged);
|
||||
}
|
||||
|
||||
Database.Update(property);
|
||||
if (propertyChanged)
|
||||
Database.Update(property);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,10 +96,14 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_1_0
|
||||
Context.AddPostMigration<RebuildPublishedSnapshot>();
|
||||
}
|
||||
|
||||
private string UpdateMediaUrls(Regex mediaLinkPattern, string value)
|
||||
private string UpdateMediaUrls(Regex mediaLinkPattern, string value, out bool changed)
|
||||
{
|
||||
return mediaLinkPattern.Replace(value, match =>
|
||||
bool matched = false;
|
||||
|
||||
var result = mediaLinkPattern.Replace(value, match =>
|
||||
{
|
||||
matched = true;
|
||||
|
||||
// match groups:
|
||||
// - 1 = from the beginning of the a tag until href attribute value begins
|
||||
// - 2 = the href attribute value excluding the querystring (if present)
|
||||
@@ -106,6 +115,10 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_1_0
|
||||
? match.Value
|
||||
: $"{match.Groups[1].Value}/{{localLink:{media.GetUdi()}}}{match.Groups[3].Value}";
|
||||
});
|
||||
|
||||
changed = matched;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_6_0
|
||||
{
|
||||
public class AddMainDomLock : MigrationBase
|
||||
{
|
||||
public AddMainDomLock(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
Database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.MainDom, Name = "MainDom" });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using Umbraco.Core.Migrations.Install;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_6_0
|
||||
{
|
||||
/// <summary>
|
||||
/// Ensures the new relation types are created
|
||||
/// </summary>
|
||||
public class AddNewRelationTypes : MigrationBase
|
||||
{
|
||||
public AddNewRelationTypes(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
CreateRelation(
|
||||
Constants.Conventions.RelationTypes.RelatedMediaAlias,
|
||||
Constants.Conventions.RelationTypes.RelatedMediaName);
|
||||
|
||||
CreateRelation(
|
||||
Constants.Conventions.RelationTypes.RelatedDocumentAlias,
|
||||
Constants.Conventions.RelationTypes.RelatedDocumentName);
|
||||
}
|
||||
|
||||
private void CreateRelation(string alias, string name)
|
||||
{
|
||||
var uniqueId = DatabaseDataCreator.CreateUniqueRelationTypeId(alias ,name); //this is the same as how it installs so everything is consistent
|
||||
Insert.IntoTable(Constants.DatabaseSchema.Tables.RelationType)
|
||||
.Row(new { typeUniqueId = uniqueId, dual = 0, name, alias })
|
||||
.Do();
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_6_0
|
||||
{
|
||||
|
||||
public class AddPropertyTypeValidationMessageColumns : MigrationBase
|
||||
{
|
||||
public AddPropertyTypeValidationMessageColumns(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToList();
|
||||
|
||||
AddColumnIfNotExists<PropertyTypeDto>(columns, "mandatoryMessage");
|
||||
AddColumnIfNotExists<PropertyTypeDto>(columns, "validationRegExpMessage");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_6_0
|
||||
{
|
||||
public class MissingContentVersionsIndexes : MigrationBase
|
||||
{
|
||||
private const string IndexName = "IX_" + ContentVersionDto.TableName + "_NodeId";
|
||||
|
||||
public MissingContentVersionsIndexes(IMigrationContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
// We must check before we create an index because if we are upgrading from v7 we force re-create all
|
||||
// indexes in the whole DB and then this would throw
|
||||
|
||||
if (!IndexExists(IndexName))
|
||||
{
|
||||
Create
|
||||
.Index(IndexName)
|
||||
.OnTable(ContentVersionDto.TableName)
|
||||
.OnColumn("nodeId")
|
||||
.Ascending()
|
||||
.OnColumn("current")
|
||||
.Ascending()
|
||||
.WithOptions().NonClustered()
|
||||
.Do();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_6_0
|
||||
{
|
||||
|
||||
public class UpdateRelationTypeTable : MigrationBase
|
||||
{
|
||||
public UpdateRelationTypeTable(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
|
||||
Alter.Table(Constants.DatabaseSchema.Tables.RelationType).AlterColumn("parentObjectType").AsGuid().Nullable().Do();
|
||||
Alter.Table(Constants.DatabaseSchema.Tables.RelationType).AlterColumn("childObjectType").AsGuid().Nullable().Do();
|
||||
|
||||
//TODO: We have to update this field to ensure it's not null, we can just copy across the name since that is not nullable
|
||||
|
||||
//drop index before we can alter the column
|
||||
if (IndexExists("IX_umbracoRelationType_alias"))
|
||||
Delete
|
||||
.Index("IX_umbracoRelationType_alias")
|
||||
.OnTable(Constants.DatabaseSchema.Tables.RelationType)
|
||||
.Do();
|
||||
//change the column to non nullable
|
||||
Alter.Table(Constants.DatabaseSchema.Tables.RelationType).AlterColumn("alias").AsString(100).NotNullable().Do();
|
||||
//re-create the index
|
||||
Create
|
||||
.Index("IX_umbracoRelationType_alias")
|
||||
.OnTable(Constants.DatabaseSchema.Tables.RelationType)
|
||||
.OnColumn("alias")
|
||||
.Ascending()
|
||||
.WithOptions().Unique().WithOptions().NonClustered()
|
||||
.Do();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_6_0
|
||||
{
|
||||
public class MissingDictionaryIndex : MigrationBase
|
||||
{
|
||||
public MissingDictionaryIndex(IMigrationContext context)
|
||||
: base(context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an index to the foreign key column <c>parent</c> on <c>DictionaryDto</c>'s table
|
||||
/// if it doesn't already exist
|
||||
/// </summary>
|
||||
public override void Migrate()
|
||||
{
|
||||
var indexName = "IX_" + DictionaryDto.TableName + "_Parent";
|
||||
|
||||
if (!IndexExists(indexName))
|
||||
{
|
||||
Create
|
||||
.Index(indexName)
|
||||
.OnTable(DictionaryDto.TableName)
|
||||
.OnColumn("parent")
|
||||
.Ascending()
|
||||
.WithOptions().NonClustered()
|
||||
.Do();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,6 @@ using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
@@ -229,8 +227,8 @@ namespace Umbraco.Core.Models
|
||||
|
||||
private void ClearCultureInfo(string culture)
|
||||
{
|
||||
if (culture.IsNullOrWhiteSpace())
|
||||
throw new ArgumentNullOrEmptyException(nameof(culture));
|
||||
if (culture == null) throw new ArgumentNullException(nameof(culture));
|
||||
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture));
|
||||
|
||||
if (_cultureInfos == null) return;
|
||||
_cultureInfos.Remove(culture);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
@@ -18,7 +17,9 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
public ContentCultureInfos(string culture)
|
||||
{
|
||||
if (culture.IsNullOrWhiteSpace()) throw new ArgumentNullOrEmptyException(nameof(culture));
|
||||
if (culture == null) throw new ArgumentNullException(nameof(culture));
|
||||
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture));
|
||||
|
||||
Culture = culture;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using Umbraco.Core.Collections;
|
||||
using Umbraco.Core.Exceptions;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
@@ -23,7 +21,9 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
public void AddOrUpdate(string culture, string name, DateTime date)
|
||||
{
|
||||
if (culture.IsNullOrWhiteSpace()) throw new ArgumentNullOrEmptyException(nameof(culture));
|
||||
if (culture == null) throw new ArgumentNullException(nameof(culture));
|
||||
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture));
|
||||
|
||||
culture = culture.ToLowerInvariant();
|
||||
|
||||
if (TryGetValue(culture, out var item))
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public class ContentDataIntegrityReport
|
||||
{
|
||||
public ContentDataIntegrityReport(IReadOnlyDictionary<int, ContentDataIntegrityReportEntry> detectedIssues)
|
||||
{
|
||||
DetectedIssues = detectedIssues;
|
||||
}
|
||||
|
||||
public bool Ok => DetectedIssues.Count == 0 || DetectedIssues.Count == DetectedIssues.Values.Count(x => x.Fixed);
|
||||
|
||||
public IReadOnlyDictionary<int, ContentDataIntegrityReportEntry> DetectedIssues { get; }
|
||||
|
||||
public IReadOnlyDictionary<int, ContentDataIntegrityReportEntry> FixedIssues
|
||||
=> DetectedIssues.Where(x => x.Value.Fixed).ToDictionary(x => x.Key, x => x.Value);
|
||||
|
||||
public enum IssueType
|
||||
{
|
||||
/// <summary>
|
||||
/// The item's level and path are inconsistent with it's parent's path and level
|
||||
/// </summary>
|
||||
InvalidPathAndLevelByParentId,
|
||||
|
||||
/// <summary>
|
||||
/// The item's path doesn't contain all required parts
|
||||
/// </summary>
|
||||
InvalidPathEmpty,
|
||||
|
||||
/// <summary>
|
||||
/// The item's path parts are inconsistent with it's level value
|
||||
/// </summary>
|
||||
InvalidPathLevelMismatch,
|
||||
|
||||
/// <summary>
|
||||
/// The item's path does not end with it's own ID
|
||||
/// </summary>
|
||||
InvalidPathById,
|
||||
|
||||
/// <summary>
|
||||
/// The item's path does not have it's parent Id as the 2nd last entry
|
||||
/// </summary>
|
||||
InvalidPathByParentId,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public class ContentDataIntegrityReportEntry
|
||||
{
|
||||
public ContentDataIntegrityReportEntry(ContentDataIntegrityReport.IssueType issueType)
|
||||
{
|
||||
IssueType = issueType;
|
||||
}
|
||||
|
||||
public ContentDataIntegrityReport.IssueType IssueType { get; }
|
||||
public bool Fixed { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public class ContentDataIntegrityReportOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Set to true to try to automatically resolve data integrity issues
|
||||
/// </summary>
|
||||
public bool FixIssues { get; set; }
|
||||
|
||||
// TODO: We could define all sorts of options for the data integrity check like what to check for, what to fix, etc...
|
||||
// things like Tag data consistency, etc...
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Exceptions;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
@@ -103,11 +102,11 @@ namespace Umbraco.Core.Models
|
||||
|
||||
public static void SetPublishInfo(this IContent content, string culture, string name, DateTime date)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
throw new ArgumentNullOrEmptyException(nameof(name));
|
||||
if (name == null) throw new ArgumentNullException(nameof(name));
|
||||
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
|
||||
|
||||
if (culture.IsNullOrWhiteSpace())
|
||||
throw new ArgumentNullOrEmptyException(nameof(culture));
|
||||
if (culture == null) throw new ArgumentNullException(nameof(culture));
|
||||
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture));
|
||||
|
||||
content.PublishCultureInfos.AddOrUpdate(culture, name, date);
|
||||
}
|
||||
@@ -153,11 +152,11 @@ namespace Umbraco.Core.Models
|
||||
|
||||
public static void SetCultureInfo(this IContentBase content, string culture, string name, DateTime date)
|
||||
{
|
||||
if (name.IsNullOrWhiteSpace())
|
||||
throw new ArgumentNullOrEmptyException(nameof(name));
|
||||
if (name == null) throw new ArgumentNullException(nameof(name));
|
||||
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(name));
|
||||
|
||||
if (culture.IsNullOrWhiteSpace())
|
||||
throw new ArgumentNullOrEmptyException(nameof(culture));
|
||||
if (culture == null) throw new ArgumentNullException(nameof(culture));
|
||||
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture));
|
||||
|
||||
content.CultureInfos.AddOrUpdate(culture, name, date);
|
||||
}
|
||||
@@ -276,8 +275,8 @@ namespace Umbraco.Core.Models
|
||||
/// <returns></returns>
|
||||
public static bool ClearPublishInfo(this IContent content, string culture)
|
||||
{
|
||||
if (culture.IsNullOrWhiteSpace())
|
||||
throw new ArgumentNullOrEmptyException(nameof(culture));
|
||||
if (culture == null) throw new ArgumentNullException(nameof(culture));
|
||||
if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(culture));
|
||||
|
||||
var removed = content.PublishCultureInfos.Remove(culture);
|
||||
if (removed)
|
||||
|
||||
@@ -81,9 +81,10 @@ namespace Umbraco.Core.Models
|
||||
if (propertyInfo.PropertyType.IsGenericType
|
||||
&& (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
|
||||
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>)
|
||||
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
|
||||
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)
|
||||
|| propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IReadOnlyCollection<>)))
|
||||
{
|
||||
//if it is a IEnumerable<>, IList<T> or ICollection<> we'll use a List<>
|
||||
//if it is a IEnumerable<>, IReadOnlyCollection<T>, IList<T> or ICollection<> we'll use a List<> since it implements them all
|
||||
var genericType = typeof(List<>).MakeGenericType(propertyInfo.PropertyType.GetGenericArguments());
|
||||
return new ClonePropertyInfo(propertyInfo) { GenericListType = genericType };
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
namespace Umbraco.Core.Models.Editors
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Represents an uploaded file for a property.
|
||||
/// </summary>
|
||||
@@ -15,6 +16,11 @@
|
||||
/// </summary>
|
||||
public string Culture { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When dealing with content variants, this is the segment for the variant
|
||||
/// </summary>
|
||||
public string Segment { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An array of metadata that is parsed out from the file info posted to the server which is set on the client.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Models.Editors
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to track reference to other entities in a property value
|
||||
/// </summary>
|
||||
public struct UmbracoEntityReference : IEquatable<UmbracoEntityReference>
|
||||
{
|
||||
private static readonly UmbracoEntityReference _empty = new UmbracoEntityReference(Udi.UnknownTypeUdi.Instance, string.Empty);
|
||||
|
||||
public UmbracoEntityReference(Udi udi, string relationTypeAlias)
|
||||
{
|
||||
Udi = udi ?? throw new ArgumentNullException(nameof(udi));
|
||||
RelationTypeAlias = relationTypeAlias ?? throw new ArgumentNullException(nameof(relationTypeAlias));
|
||||
}
|
||||
|
||||
public UmbracoEntityReference(Udi udi)
|
||||
{
|
||||
Udi = udi ?? throw new ArgumentNullException(nameof(udi));
|
||||
|
||||
switch (udi.EntityType)
|
||||
{
|
||||
case Constants.UdiEntityType.Media:
|
||||
RelationTypeAlias = Constants.Conventions.RelationTypes.RelatedMediaAlias;
|
||||
break;
|
||||
default:
|
||||
RelationTypeAlias = Constants.Conventions.RelationTypes.RelatedDocumentAlias;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static UmbracoEntityReference Empty() => _empty;
|
||||
|
||||
public static bool IsEmpty(UmbracoEntityReference reference) => reference == Empty();
|
||||
|
||||
public Udi Udi { get; }
|
||||
public string RelationTypeAlias { get; }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is UmbracoEntityReference reference && Equals(reference);
|
||||
}
|
||||
|
||||
public bool Equals(UmbracoEntityReference other)
|
||||
{
|
||||
return EqualityComparer<Udi>.Default.Equals(Udi, other.Udi) &&
|
||||
RelationTypeAlias == other.RelationTypeAlias;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashCode = -487348478;
|
||||
hashCode = hashCode * -1521134295 + EqualityComparer<Udi>.Default.GetHashCode(Udi);
|
||||
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(RelationTypeAlias);
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
public static bool operator ==(UmbracoEntityReference left, UmbracoEntityReference right)
|
||||
{
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
public static bool operator !=(UmbracoEntityReference left, UmbracoEntityReference right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,7 @@ namespace Umbraco.Core.Models.Entities
|
||||
public int ParentId { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SetParent(ITreeEntity parent) => throw new WontImplementException();
|
||||
public void SetParent(ITreeEntity parent) => throw new InvalidOperationException("This property won't be implemented.");
|
||||
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
@@ -116,7 +116,7 @@ namespace Umbraco.Core.Models.Entities
|
||||
/// <inheritdoc />
|
||||
public object DeepClone()
|
||||
{
|
||||
throw new WontImplementException();
|
||||
throw new InvalidOperationException("This method won't be implemented.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -128,47 +128,47 @@ namespace Umbraco.Core.Models.Entities
|
||||
|
||||
public bool IsDirty()
|
||||
{
|
||||
throw new WontImplementException();
|
||||
throw new InvalidOperationException("This method won't be implemented.");
|
||||
}
|
||||
|
||||
public bool IsPropertyDirty(string propName)
|
||||
{
|
||||
throw new WontImplementException();
|
||||
throw new InvalidOperationException("This method won't be implemented.");
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetDirtyProperties()
|
||||
{
|
||||
throw new WontImplementException();
|
||||
throw new InvalidOperationException("This method won't be implemented.");
|
||||
}
|
||||
|
||||
public void ResetDirtyProperties()
|
||||
{
|
||||
throw new WontImplementException();
|
||||
throw new InvalidOperationException("This method won't be implemented.");
|
||||
}
|
||||
|
||||
public bool WasDirty()
|
||||
{
|
||||
throw new WontImplementException();
|
||||
throw new InvalidOperationException("This method won't be implemented.");
|
||||
}
|
||||
|
||||
public bool WasPropertyDirty(string propertyName)
|
||||
{
|
||||
throw new WontImplementException();
|
||||
throw new InvalidOperationException("This method won't be implemented.");
|
||||
}
|
||||
|
||||
public void ResetWereDirtyProperties()
|
||||
{
|
||||
throw new WontImplementException();
|
||||
throw new InvalidOperationException("This method won't be implemented.");
|
||||
}
|
||||
|
||||
public void ResetDirtyProperties(bool rememberDirty)
|
||||
{
|
||||
throw new WontImplementException();
|
||||
throw new InvalidOperationException("This method won't be implemented.");
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetWereDirtyProperties()
|
||||
{
|
||||
throw new WontImplementException();
|
||||
throw new InvalidOperationException("This method won't be implemented.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
/// Sets the parent entity.
|
||||
/// </summary>
|
||||
/// <remarks>Use this method to set the parent entity when the parent entity is known, but has not
|
||||
/// been persistent and does not yet have an identity. The parent identifier will we retrieved
|
||||
/// been persistent and does not yet have an identity. The parent identifier will be retrieved
|
||||
/// from the parent entity when needed. If the parent entity still does not have an entity by that
|
||||
/// time, an exception will be thrown by <see cref="ParentId"/> getter.</remarks>
|
||||
void SetParent(ITreeEntity parent);
|
||||
@@ -53,4 +53,4 @@
|
||||
/// </remarks>
|
||||
bool Trashed { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
namespace Umbraco.Core.Models.Entities
|
||||
{
|
||||
public class MemberEntitySlim : EntitySlim, IMemberEntitySlim
|
||||
public class MemberEntitySlim : ContentEntitySlim, IMemberEntitySlim
|
||||
{
|
||||
public string ContentTypeAlias { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string ContentTypeIcon { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string ContentTypeThumbnail { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public interface IImageUrlGenerator
|
||||
{
|
||||
string GetImageUrl(ImageUrlGenerationOptions options);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Runtime.Serialization;
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
@@ -11,12 +12,18 @@ namespace Umbraco.Core.Models
|
||||
[DataMember]
|
||||
int ParentId { get; set; }
|
||||
|
||||
[DataMember]
|
||||
Guid ParentObjectType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Child Id of the Relation (Destination)
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
int ChildId { get; set; }
|
||||
|
||||
[DataMember]
|
||||
Guid ChildObjectType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="RelationType"/> for the Relation
|
||||
/// </summary>
|
||||
|
||||
@@ -29,13 +29,13 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
/// <remarks>Corresponds to the NodeObjectType in the umbracoNode table</remarks>
|
||||
[DataMember]
|
||||
Guid ParentObjectType { get; set; }
|
||||
Guid? ParentObjectType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Childs object type id
|
||||
/// </summary>
|
||||
/// <remarks>Corresponds to the NodeObjectType in the umbracoNode table</remarks>
|
||||
[DataMember]
|
||||
Guid ChildObjectType { get; set; }
|
||||
Guid? ChildObjectType { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// These are options that are passed to the IImageUrlGenerator implementation to determine
|
||||
/// the propery URL that is needed
|
||||
/// </summary>
|
||||
public class ImageUrlGenerationOptions
|
||||
{
|
||||
public ImageUrlGenerationOptions (string imageUrl)
|
||||
{
|
||||
ImageUrl = imageUrl;
|
||||
}
|
||||
|
||||
public string ImageUrl { get; }
|
||||
public int? Width { get; set; }
|
||||
public int? Height { get; set; }
|
||||
public decimal? WidthRatio { get; set; }
|
||||
public decimal? HeightRatio { get; set; }
|
||||
public int? Quality { get; set; }
|
||||
public string ImageCropMode { get; set; }
|
||||
public string ImageCropAnchor { get; set; }
|
||||
public bool DefaultCrop { get; set; }
|
||||
public FocalPointPosition FocalPoint { get; set; }
|
||||
public CropCoordinates Crop { get; set; }
|
||||
public string CacheBusterValue { get; set; }
|
||||
public string FurtherOptions { get; set; }
|
||||
public bool UpScale { get; set; } = true;
|
||||
public string AnimationProcessMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The focal point position, in whatever units the registered IImageUrlGenerator uses,
|
||||
/// typically a percentage of the total image from 0.0 to 1.0.
|
||||
/// </summary>
|
||||
public class FocalPointPosition
|
||||
{
|
||||
public FocalPointPosition (decimal top, decimal left)
|
||||
{
|
||||
Left = left;
|
||||
Top = top;
|
||||
}
|
||||
|
||||
public decimal Left { get; }
|
||||
public decimal Top { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The bounds of the crop within the original image, in whatever units the registered
|
||||
/// IImageUrlGenerator uses, typically a percentage between 0 and 100.
|
||||
/// </summary>
|
||||
public class CropCoordinates
|
||||
{
|
||||
public CropCoordinates (decimal x1, decimal y1, decimal x2, decimal y2)
|
||||
{
|
||||
X1 = x1;
|
||||
Y1 = y1;
|
||||
X2 = x2;
|
||||
Y2 = y2;
|
||||
}
|
||||
|
||||
public decimal X1 { get; }
|
||||
public decimal Y1 { get; }
|
||||
public decimal X2 { get; }
|
||||
public decimal Y2 { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public class InstallLog
|
||||
{
|
||||
public Guid InstallId { get; }
|
||||
public bool IsUpgrade { get; set; }
|
||||
public bool InstallCompleted { get; set; }
|
||||
public DateTime Timestamp { get; set; }
|
||||
public int VersionMajor { get; }
|
||||
public int VersionMinor { get; }
|
||||
public int VersionPatch { get; }
|
||||
public string VersionComment { get; }
|
||||
public string Error { get; }
|
||||
public string UserAgent { get; }
|
||||
public string DbProvider { get; set; }
|
||||
|
||||
public InstallLog(Guid installId, bool isUpgrade, bool installCompleted, DateTime timestamp, int versionMajor, int versionMinor, int versionPatch, string versionComment, string error, string userAgent, string dbProvider)
|
||||
{
|
||||
InstallId = installId;
|
||||
IsUpgrade = isUpgrade;
|
||||
InstallCompleted = installCompleted;
|
||||
Timestamp = timestamp;
|
||||
VersionMajor = versionMajor;
|
||||
VersionMinor = versionMinor;
|
||||
VersionPatch = versionPatch;
|
||||
VersionComment = versionComment;
|
||||
Error = error;
|
||||
UserAgent = userAgent;
|
||||
DbProvider = dbProvider;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.PropertyEditors.ValueConverters;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
@@ -18,29 +16,12 @@ namespace Umbraco.Core.Models
|
||||
if (!media.Properties.TryGetValue(propertyAlias, out var property))
|
||||
return string.Empty;
|
||||
|
||||
// TODO: would need to be adjusted to variations, when media become variants
|
||||
if (!(property.GetValue() is string jsonString))
|
||||
return string.Empty;
|
||||
|
||||
if (property.PropertyType.PropertyEditorAlias == Constants.PropertyEditors.Aliases.UploadField)
|
||||
return jsonString;
|
||||
|
||||
if (property.PropertyType.PropertyEditorAlias == Constants.PropertyEditors.Aliases.ImageCropper)
|
||||
if (Current.PropertyEditors.TryGet(property.PropertyType.PropertyEditorAlias, out var editor)
|
||||
&& editor is IDataEditorWithMediaPath dataEditor)
|
||||
{
|
||||
if (jsonString.DetectIsJson() == false)
|
||||
return jsonString;
|
||||
|
||||
try
|
||||
{
|
||||
var json = JsonConvert.DeserializeObject<JObject>(jsonString);
|
||||
if (json["src"] != null)
|
||||
return json["src"].Value<string>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error<ImageCropperValueConverter>(ex, "Could not parse the string '{JsonString}' to a json object", jsonString);
|
||||
return string.Empty;
|
||||
}
|
||||
// TODO: would need to be adjusted to variations, when media become variants
|
||||
var value = property.GetValue();
|
||||
return dataEditor.GetMediaPath(value);
|
||||
}
|
||||
|
||||
// Without knowing what it is, just adding a string here might not be very nice
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user