Merge remote-tracking branch 'fork/temp8-u4-11427-remove-propertyinjection' into castle-compatibility-cleanup
# Conflicts: # src/Umbraco.Tests/Models/MediaXmlTest.cs
@@ -28,3 +28,9 @@ dotnet_naming_symbols.private_fields.applicable_accessibilities = private
|
||||
|
||||
dotnet_naming_style.prefix_underscore.capitalization = camel_case
|
||||
dotnet_naming_style.prefix_underscore.required_prefix = _
|
||||
|
||||
# https://github.com/MicrosoftDocs/visualstudio-docs/blob/master/docs/ide/editorconfig-code-style-settings-reference.md
|
||||
[*.cs]
|
||||
csharp_style_var_for_built_in_types = true:suggestion
|
||||
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||
csharp_style_var_elsewhere = true:suggestion
|
||||
0
docs/BUILD.md → .github/BUILD.md
vendored
0
docs/CLEAR.md → .github/CLEAR.md
vendored
@@ -129,7 +129,7 @@ We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-fl
|
||||
|
||||
The easiest way to get started is to run `build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `gulp dev` in `src\Umbraco.Web.UI.Client`. See [this page](BUILD.md) for more details.
|
||||
|
||||
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 ([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.
|
||||
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 (version 15.3 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.
|
||||
|
||||

|
||||
|
||||
66
.github/ISSUE_TEMPLATE/1_Bug.md
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
---
|
||||
name: 🐛 Bug Report
|
||||
about: File a bug report, if you've discovered a problem in Umbraco.
|
||||
---
|
||||
|
||||
A brief description of the issue goes here.
|
||||
|
||||
<!--
|
||||
|
||||
If you haven't yet done so, please read the "contributing guidelines"
|
||||
thoroughly. Then, proceed by filling out the rest of the details in the issue
|
||||
template below. The more details you can give us, the easier it will be for us
|
||||
to determine the cause of a problem.
|
||||
|
||||
See: https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/.github/CONTRIBUTING.md
|
||||
|
||||
-->
|
||||
|
||||
|
||||
|
||||
Reproduction
|
||||
------------
|
||||
|
||||
If you're filing a bug, please describe how to reproduce it. Include as much
|
||||
relevant information as possible, such as:
|
||||
|
||||
### Bug summary
|
||||
|
||||
<!--
|
||||
* Write a short summary of the bug
|
||||
* Try to pinpoint it as much as possible
|
||||
* Try to state the _actual problem_, and not just what you _think_ the
|
||||
solution might be.
|
||||
-->
|
||||
|
||||
### Specifics
|
||||
|
||||
<!--
|
||||
* Mention the URL where this bug occurs, if applicable
|
||||
* What version of Umbraco are you using (down to the very last digit!)
|
||||
* What browser and version you are using
|
||||
* Please mention if you've checked it in other browsers as well
|
||||
* Please include *full error messages* and *screenshots* if possible
|
||||
-->
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
<!--
|
||||
* Clearly mention the steps to reproduce the bug
|
||||
-->
|
||||
|
||||
### Expected result
|
||||
|
||||
<!--
|
||||
* What did you _expect_ that would happen on your Umbraco site?
|
||||
* Describe the intended/desired outcome after you did the steps mentioned.
|
||||
-->
|
||||
|
||||
### Actual result
|
||||
|
||||
<!--
|
||||
* What is the actual result of the above steps?
|
||||
* Describe the behaviour of the bug
|
||||
* Please, please include **error messages** and screenshots. They might mean
|
||||
nothing to you, but they are _very_ helpful to us.
|
||||
-->
|
||||
31
.github/ISSUE_TEMPLATE/2_Feature_request.md
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: 📮 Feature Request
|
||||
about: Open a feature request, if you want to propose a new feature.
|
||||
---
|
||||
|
||||
A brief description of your feature request goes here.
|
||||
|
||||
|
||||
<!--
|
||||
If you want to discuss the feature you're imagining, please make sure to keep
|
||||
those discussions on the forum at https://our.umbraco.com/ (choose the
|
||||
category "Contributing to Umbraco", Umbraco HQ follows all new topics there).
|
||||
|
||||
Once you've come to a conclusion in the discussion, feel free to propose the
|
||||
new feature here.
|
||||
-->
|
||||
|
||||
How can you help?
|
||||
-------------------------------
|
||||
|
||||
<!--
|
||||
The resources (read: available time and effort) of Umbraco's core team are
|
||||
limited.
|
||||
|
||||
If we can not work on your suggestion, please don't take it personally. Most
|
||||
likely, it's either:
|
||||
|
||||
- We think your idea is valid, but we can't find the time to work on it.
|
||||
- Your idea might be better suited as a package, if it's not suitable for
|
||||
the majority of users.
|
||||
-->
|
||||
9
.github/ISSUE_TEMPLATE/3_Support_question.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
name: ⁉️ Support Question
|
||||
about: Having trouble with Umbraco? -> https://our.umbraco.com
|
||||
---
|
||||
|
||||
This issue tracker is NOT meant for support questions. If you have a question,
|
||||
please join us on the forum at https://our.umbraco.com.
|
||||
|
||||
Thanks!
|
||||
9
.github/ISSUE_TEMPLATE/4_Documentation_issue.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
name: 📖 Documentation Issue
|
||||
about: See https://github.com/umbraco/UmbracoDocs/issues for documentation issues
|
||||
---
|
||||
|
||||
The Umbraco documentation has its own dedicated repository. Please open your
|
||||
documentation-related issue at https://github.com/umbraco/UmbracoDocs/issues
|
||||
|
||||
Thanks!
|
||||
31
.github/ISSUE_TEMPLATE/5_Security_issue.md
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: 🔐 Security Issue
|
||||
about: Discovered a Security Issue in Umbraco?
|
||||
---
|
||||
|
||||
⚠️ PLEASE DON'T DISCLOSE SECURITY-RELATED ISSUES PUBLICLY, SEE BELOW.
|
||||
|
||||
If you have found a security issue in Umbraco, please send the details to
|
||||
security@umbraco.com and don't disclose it publicly until we can provide a fix for
|
||||
it. If you wish, we'll credit you for finding verified issues, when we release
|
||||
the patched version.
|
||||
|
||||
❗ Please read more about how to report security issues on https://umbraco.com/security
|
||||
|
||||
A note on "Self XSS"
|
||||
--------------------
|
||||
|
||||
Umbraco is a CMS, that allows users to edit content on a website. As such,
|
||||
all _authenticated users_ can:
|
||||
|
||||
- Edit content, and (depending on the field types) insert HTML and CSS in that
|
||||
content, with a variety of allowed attributes.
|
||||
- Depending on the user level: Edit template files, and insert C#, HTML, CSS and
|
||||
javascript in so on.
|
||||
- Upload files to the site, which will become publicly available.
|
||||
|
||||
We see these functionalities as _features_, and not as security issues. Please
|
||||
report the mentioned items only if they can be performed by non-authorized
|
||||
users, or other exploitable vulnerabilities.
|
||||
|
||||
Thanks!
|
||||
11
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
### Prerequisites
|
||||
|
||||
- [ ] I have [created an issue](https://github.com/umbraco/Umbraco-CMS/issues) for the proposed changes in this PR, the link is:
|
||||
- [ ] I have added steps to test this contribution in the description below
|
||||
|
||||
### Description
|
||||
<!-- A description of the changes proposed in the pull-request -->
|
||||
<!-- Make sure to link to the related issue number so we can easily find it in the issue tracker -->
|
||||
|
||||
|
||||
<!-- Thanks for contributing to Umbraco CMS! -->
|
||||
3
docs/README.md → .github/README.md
vendored
@@ -48,4 +48,5 @@ Umbraco is contribution focused and community driven. If you want to contribute
|
||||
|
||||
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](CONTRIBUTING_DETAILED.md#reporting-bugs).
|
||||
|
||||
To view existing issues, please visit [http://issues.umbraco.org](http://issues.umbraco.org).
|
||||
You can comment and report issues on the [github issue tracker](https://github.com/umbraco/Umbraco-CMS/issues).
|
||||
Since [September 2018](https://umbraco.com/blog/a-second-take-on-umbraco-issue-tracker-hello-github-issues/) the old issue tracker is in read only mode, but can still be found at [http://issues.umbraco.org](http://issues.umbraco.org).
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
0
docs/img/vimeo.png → .github/img/vimeo.png
vendored
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
@@ -10,7 +10,7 @@
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Contains the core assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms-package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
|
||||
<description>Contains the core assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
|
||||
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
@@ -21,35 +21,15 @@
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="AutoMapper" version="[7.0.1,7.999999)" />
|
||||
<dependency id="ClientDependency" version="[1.9.6,1.999999)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0,1.999999)" />
|
||||
<dependency id="CSharpTest.Net.Collections" version="[14.906.1403.1082,14.999999)" />
|
||||
<dependency id="Examine" version="[1.0.0-beta025,1.999999)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.7.2,1.999999)" />
|
||||
<dependency id="ImageProcessor" version="[2.6.1.19,2.999999)" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.9.2.19,4.999999)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.4.1.19,2.999999)" />
|
||||
<dependency id="LightInject" version="[5.1.2,5.999999)" />
|
||||
<dependency id="LightInject.Annotation" version="[1.1.0,1.999999)" />
|
||||
<dependency id="LightInject.Mvc" version="[2.0.0,2.999999)" />
|
||||
<dependency id="LightInject.WebApi" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Lucene.Net.Contrib" version="[3.0.3,3.999999)" />
|
||||
<dependency id="Markdown" version="[2.2.1,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.1,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.CodeAnalysis.CSharp" version="[2.8.0,2.999999)" />
|
||||
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[1.0.8,1.999999)" />
|
||||
<dependency id="Microsoft.Net.Compilers" version="[2.8.0,2.999999)" />
|
||||
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Owin.Security.Cookies" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Web.Xdt" version="[2.1.2,2.999999)" />
|
||||
<dependency id="LightInject.Web" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Core" version="[2.2.2,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi.Client" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.Owin" version="[4.0.0,4.999999)" />
|
||||
<dependency id="MiniProfiler" version="[3.2.0.157,3.999999)" />
|
||||
<dependency id="MySql.Data" version="[6.10.7,6.999999)" />
|
||||
<dependency id="Newtonsoft.Json" version="[11.0.2,11.999999)" />
|
||||
<dependency id="NPoco" version="[3.9.3,3.999999)" />
|
||||
<dependency id="Semver" version="[2.0.4,2.999999)" />
|
||||
<dependency id="Serilog" version="[2.7.1,2.999999)" />
|
||||
<dependency id="Serilog.Enrichers.Process" version="[2.0.1,2.999999)" />
|
||||
@@ -58,35 +38,19 @@
|
||||
<dependency id="Serilog.Formatting.Compact" version="[1.0.0,1.999999)" />
|
||||
<dependency id="Serilog.Settings.AppSettings" version="[2.1.2,2.999999)" />
|
||||
<dependency id="Serilog.Sinks.File" version="[4.0.0,4.999999)" />
|
||||
<dependency id="System.Reflection.Primitives" version="[4.3.0,4.999999)" />
|
||||
<dependency id="System.Runtime.Handles" version="[4.3.0,4.999999)" />
|
||||
<dependency id="System.Security.Cryptography.X509Certificates" version="[4.3.2,4.999999)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.8.0,4.999999)" />
|
||||
<dependency id="Umbraco.SqlServerCE" version="[4.0.0.1,4.999999)" />
|
||||
<dependency id="NPoco" version="[3.9.4,3.999999)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<!-- libs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.dll" target="lib\net472\Umbraco.Core.dll" />
|
||||
<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" />
|
||||
|
||||
<!-- docs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.xml" target="lib\Umbraco.Core.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.xml" target="lib\Umbraco.Web.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.xml" target="lib\Umbraco.Web.UI.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.xml" target="lib\Umbraco.Examine.xml" />
|
||||
|
||||
<file src="tools\install.core.ps1" target="tools\install.ps1" />
|
||||
|
||||
<!-- symbols -->
|
||||
<file src="$BuildTmp$\bin\Umbraco.Core.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Core\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Core" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Web.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Web\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Web.UI.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Web.UI\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web.UI" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Examine.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Examine\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Examine" />
|
||||
</files>
|
||||
</package>
|
||||
|
||||
62
build/NuSpecs/UmbracoCms.Web.nuspec
Normal file
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata minClientVersion="3.4.4">
|
||||
<id>UmbracoCms.Web</id>
|
||||
<version>8.0.0</version>
|
||||
<title>Umbraco Cms Core Binaries</title>
|
||||
<authors>Umbraco HQ</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>Contains the web assemblies needed to run Umbraco Cms. This package only contains assemblies and can be used for package development. Use the UmbracoCms package to setup Umbraco in Visual Studio as an ASP.NET project.</description>
|
||||
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<!--
|
||||
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
|
||||
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
|
||||
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="AutoMapper" version="[7.0.1,7.999999)" />
|
||||
<dependency id="ClientDependency" version="[1.9.7,1.999999)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0,1.999999)" />
|
||||
<dependency id="CSharpTest.Net.Collections" version="[14.906.1403.1082,14.999999)" />
|
||||
<dependency id="Examine" version="[1.0.0-beta025,1.999999)" />
|
||||
<dependency id="Lucene.Net.Contrib" version="[3.0.3,3.999999)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.8.9,1.999999)" />
|
||||
<dependency id="ImageProcessor" version="[2.6.2.25,2.999999)" />
|
||||
<dependency id="LightInject.Mvc" version="[2.0.0,2.999999)" />
|
||||
<dependency id="LightInject.WebApi" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Markdown" version="[2.2.1,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.2,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Owin.Security.Cookies" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.0,4.999999)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.8.0,4.999999)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<!-- libs -->
|
||||
<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" />
|
||||
|
||||
<!-- docs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.xml" target="lib\Umbraco.Web.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.xml" target="lib\Umbraco.Web.UI.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.xml" target="lib\Umbraco.Examine.xml" />
|
||||
|
||||
<!-- symbols -->
|
||||
<file src="$BuildTmp$\bin\Umbraco.Web.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Web\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Examine.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Examine\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Examine" />
|
||||
</files>
|
||||
</package>
|
||||
@@ -15,44 +15,51 @@
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<dependency id="UmbracoCms.Core" version="[$version$]" />
|
||||
<dependency id="UmbracoCms.Web" version="[$version$]" />
|
||||
<!--
|
||||
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
|
||||
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
|
||||
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.2.3, 2.999999)" />
|
||||
<dependency id="Umbraco.ModelsBuilder.Ui" version="[8.0.0-alpha.22]" />
|
||||
<dependency id="Umbraco.ModelsBuilder.Ui" version="[8.0.0-alpha.24]" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.9.3.25,4.999999)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.4.1.19,2.999999)" />
|
||||
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Microsoft.Net.Compilers" version="[2.9.0,2.999999)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<!-- files -->
|
||||
<file src="$BuildTmp$\Configs\**" target="Content\Config" exclude="$BuildTmp$\Configs\Web.config.transform" />
|
||||
<file src="$BuildTmp$\WebApp\Views\**" target="Content\Views" exclude="$BuildTmp$\WebApp\Views\Web.config" />
|
||||
<file src="$BuildTmp$\WebApp\default.aspx" target="Content\default.aspx" />
|
||||
<file src="$BuildTmp$\WebApp\Global.asax" target="Content\Global.asax" />
|
||||
<file src="$BuildTmp$\WebApp\Web.config" target="UmbracoFiles\Web.config" />
|
||||
<file src="$BuildTmp$\WebApp\App_Browsers\**" target="UmbracoFiles\App_Browsers" />
|
||||
<file src="$BuildTmp$\WebApp\config\splashes\**" target="UmbracoFiles\Config\splashes" />
|
||||
<file src="$BuildTmp$\WebApp\config\BackOfficeTours\**" target="Content\Config\BackOfficeTours" />
|
||||
<file src="$BuildTmp$\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
|
||||
<file src="$BuildTmp$\WebApp\Media\Web.config" target="Content\Media\Web.config" />
|
||||
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\modelsbuilder.htm" target="Content\App_Plugins\ModelsBuilder\modelsbuilder.htm" />
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\modelsbuilder.controller.js" target="Content\App_Plugins\ModelsBuilder\modelsbuilder.controller.js" />
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\modelsbuilder.resource.js" target="Content\App_Plugins\ModelsBuilder\modelsbuilder.resource.js" />
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\package.manifest" target="Content\App_Plugins\ModelsBuilder\package.manifest" />
|
||||
<!-- these files are copied by install.ps1 -->
|
||||
<file src="$BuildTmp$\WebApp\Web.config" target="UmbracoFiles\Web.config" />
|
||||
<file src="$BuildTmp$\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
|
||||
<file src="$BuildTmp$\WebApp\config\splashes\**" target="UmbracoFiles\Config\splashes" />
|
||||
|
||||
<!-- tools -->
|
||||
<!-- beware! install.ps1 not supported by PackageReference -->
|
||||
<file src="tools\install.ps1" target="tools\install.ps1" />
|
||||
<file src="tools\Readme.txt" target="tools\Readme.txt" />
|
||||
<file src="tools\ReadmeUpgrade.txt" target="tools\ReadmeUpgrade.txt" />
|
||||
|
||||
<!-- config transforms -->
|
||||
<!-- beware! config transforms not supported by PackageReference -->
|
||||
<file src="tools\Web.config.install.xdt" target="Content\Web.config.install.xdt" />
|
||||
<file src="tools\applications.config.install.xdt" target="Content\config\applications.config.install.xdt" />
|
||||
<file src="tools\ClientDependency.config.install.xdt" target="Content\config\ClientDependency.config.install.xdt" />
|
||||
<file src="tools\Dashboard.config.install.xdt" target="Content\config\Dashboard.config.install.xdt" />
|
||||
<file src="tools\trees.config.install.xdt" target="Content\config\trees.config.install.xdt" />
|
||||
<file src="tools\umbracoSettings.config.install.xdt" target="Content\config\umbracoSettings.config.install.xdt" />
|
||||
<file src="tools\Views.Web.config.install.xdt" target="Views\Web.config.install.xdt" />
|
||||
<file src="tools\Views.Web.config.install.xdt" target="Views\Web.config.install.xdt" /> <!-- FIXME Content\ !! and then... transform?! -->
|
||||
|
||||
<!-- UmbracoCms props and targets -->
|
||||
<file src="build\**" target="build" />
|
||||
</files>
|
||||
</package>
|
||||
|
||||
@@ -47,9 +47,6 @@
|
||||
<CustomFilesToInclude Include=".\umbraco\**\*">
|
||||
<Dir>umbraco</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\umbraco_client\**\*">
|
||||
<Dir>umbraco_client</Dir>
|
||||
</CustomFilesToInclude>
|
||||
<CustomFilesToInclude Include=".\Global.asax">
|
||||
<Dir>.</Dir>
|
||||
</CustomFilesToInclude>
|
||||
|
||||
@@ -18,9 +18,9 @@ This NuGet package includes build targets that extend the creation of a deploy p
|
||||
Publishing from Visual Studio. The targets will only work once Publishing is configured, so if you don't use
|
||||
Publish this won't affect you.
|
||||
The following items will now be automatically included when creating a deploy package or publishing to the file
|
||||
system: umbraco, umbraco_client, config\splashes and global.asax.
|
||||
system: umbraco, config\splashes and global.asax.
|
||||
|
||||
Please read the release notes on our.umbraco.com:
|
||||
http://our.umbraco.com/contribute/releases
|
||||
https://our.umbraco.com/download/releases
|
||||
|
||||
- Umbraco
|
||||
@@ -8,21 +8,12 @@
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
*** IMPORTANT NOTICE FOR UPGRADES FROM VERSIONS BELOW 7.7.0 ***
|
||||
|
||||
Be sure to read the version specific upgrade information before proceeding:
|
||||
https://our.umbraco.com/documentation/Getting-Started/Setup/Upgrading/version-specific#version-7-7-0
|
||||
|
||||
Depending on the version you are upgrading from, you may need to make some changes to your web.config
|
||||
and you will need to be aware of the breaking changes listed there to see if these affect your installation.
|
||||
|
||||
|
||||
Don't forget to build!
|
||||
|
||||
We've done our best to transform your configuration files but in case something is not quite right: remember we
|
||||
backed up your files in App_Data\NuGetBackup so you can find the original files before they were transformed.
|
||||
|
||||
We've overwritten all the files in the Umbraco and Umbraco_Client folder, these have been backed up in
|
||||
We've overwritten all the files in the Umbraco folder, these have been backed up in
|
||||
App_Data\NuGetBackup. We didn't overwrite the UI.xml file nor did we remove any files or folders that you or
|
||||
a package might have added. Only the existing files were overwritten. If you customized anything then make
|
||||
sure to do a compare and merge with the NuGetBackup folder.
|
||||
@@ -31,7 +22,7 @@ This NuGet package includes build targets that extend the creation of a deploy p
|
||||
Publishing from Visual Studio. The targets will only work once Publishing is configured, so if you don't use
|
||||
Publish this won't affect you.
|
||||
The following items will now be automatically included when creating a deploy package or publishing to the file
|
||||
system: umbraco, umbraco_client, config\splashes and global.asax.
|
||||
system: umbraco, config\splashes and global.asax.
|
||||
|
||||
Please read the release notes on our.umbraco.com:
|
||||
http://our.umbraco.com/contribute/releases
|
||||
|
||||
@@ -150,10 +150,6 @@
|
||||
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0"?>
|
||||
<applications xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<add alias="content" icon="traycontent" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="media" icon="traymedia" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="settings" icon="traysettings" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="developer" icon="traydeveloper" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="users" icon="trayusers" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="member" icon="traymember" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="forms" name="Forms" icon="icon-umb-contour" sortOrder="6" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing" />
|
||||
<add alias="translation" icon="traytranslation" sortOrder="7" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon,sortOrder)" />
|
||||
<add alias="content" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="media" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="settings" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="developer" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="users" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="member" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon)" />
|
||||
<add alias="forms" name="Forms" sortOrder="6" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing" />
|
||||
<add alias="translation" sortOrder="7" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes(icon,sortOrder)" />
|
||||
</applications>
|
||||
@@ -44,14 +44,6 @@ if ($project) {
|
||||
robocopy $umbracoFolder $umbracoBackupPath /e /LOG:$copyLogsPath\UmbracoBackup.log
|
||||
robocopy $umbracoFolderSource $umbracoFolder /is /it /e /xf UI.xml /LOG:$copyLogsPath\UmbracoCopy.log
|
||||
|
||||
$umbracoClientFolder = Join-Path $projectPath "Umbraco_Client"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoClientFolder
|
||||
$umbracoClientFolderSource = Join-Path $installPath "UmbracoFiles\Umbraco_Client"
|
||||
$umbracoClientBackupPath = Join-Path $backupPath "Umbraco_Client"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoClientBackupPath
|
||||
robocopy $umbracoClientFolder $umbracoClientBackupPath /e /LOG:$copyLogsPath\UmbracoClientBackup.log
|
||||
robocopy $umbracoClientFolderSource $umbracoClientFolder /is /it /e /LOG:$copyLogsPath\UmbracoClientCopy.log
|
||||
|
||||
$copyWebconfig = $true
|
||||
$destinationWebConfig = Join-Path $projectPath "Web.config"
|
||||
|
||||
@@ -86,14 +78,6 @@ if ($project) {
|
||||
New-Item $splashesDestination -Type directory
|
||||
Copy-Item $splashesSource $splashesDestination -Force
|
||||
|
||||
$sqlCe64Source = Join-Path $installPath "UmbracoFiles\bin\amd64\*"
|
||||
$sqlCe64Destination = Join-Path $projectPath "bin\amd64\"
|
||||
Copy-Item $sqlCe64Source $sqlCe64Destination -Force
|
||||
|
||||
$sqlCex86Source = Join-Path $installPath "UmbracoFiles\bin\x86\*"
|
||||
$sqlCex86Destination = Join-Path $projectPath "bin\x86\"
|
||||
Copy-Item $sqlCex86source $sqlCex86Destination -Force
|
||||
|
||||
$umbracoUIXMLSource = Join-Path $installPath "UmbracoFiles\Umbraco\Config\Create\UI.xml"
|
||||
$umbracoUIXMLDestination = Join-Path $projectPath "Umbraco\Config\Create\UI.xml"
|
||||
Copy-Item $umbracoUIXMLSource $umbracoUIXMLDestination -Force
|
||||
|
||||
@@ -69,6 +69,9 @@
|
||||
$global:node_nodepath = $this.ClearEnvVar("NODEPATH")
|
||||
$global:node_npmcache = $this.ClearEnvVar("NPM_CONFIG_CACHE")
|
||||
$global:node_npmprefix = $this.ClearEnvVar("NPM_CONFIG_PREFIX")
|
||||
|
||||
# https://github.com/gruntjs/grunt-contrib-connect/issues/235
|
||||
$this.SetEnvVar("NODE_NO_HTTP2", "1")
|
||||
})
|
||||
|
||||
$ubuild.DefineMethod("RestoreNode",
|
||||
@@ -78,6 +81,8 @@
|
||||
$this.SetEnvVar("NODEPATH", $node_nodepath)
|
||||
$this.SetEnvVar("NPM_CONFIG_CACHE", $node_npmcache)
|
||||
$this.SetEnvVar("NPM_CONFIG_PREFIX", $node_npmprefix)
|
||||
|
||||
$ignore = $this.ClearEnvVar("NODE_NO_HTTP2")
|
||||
})
|
||||
|
||||
$ubuild.DefineMethod("CompileBelle",
|
||||
@@ -124,7 +129,7 @@
|
||||
|
||||
Write-Output "### install gulp-cli" >> $log 2>&1
|
||||
&npm install -g gulp-cli --quiet >> $log 2>&1
|
||||
if (-not $?) { throw "Failed to install gulp-cli" } # that one is expected to work
|
||||
$error.Clear() # that one fails 'cos some files not being removed - ignore
|
||||
|
||||
Write-Output "### gulp build for version $($this.Version.Release)" >> $log 2>&1
|
||||
&gulp build --buildversion=$this.Version.Release >> $log 2>&1
|
||||
@@ -399,9 +404,15 @@
|
||||
-Symbols -Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmscore.log"
|
||||
if (-not $?) { throw "Failed to pack NuGet UmbracoCms.Core." }
|
||||
|
||||
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.Web.nuspec" `
|
||||
-Properties BuildTmp="$($this.BuildTemp)" `
|
||||
-Version "$($this.Version.Semver.ToString())" `
|
||||
-Symbols -Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmsweb.log"
|
||||
if (-not $?) { throw "Failed to pack NuGet UmbracoCms.Web." }
|
||||
|
||||
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.nuspec" `
|
||||
-Properties BuildTmp="$($this.BuildTemp)" `
|
||||
-Version $this.Version.Semver.ToString() `
|
||||
-Version "$($this.Version.Semver.ToString())" `
|
||||
-Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cms.log"
|
||||
if (-not $?) { throw "Failed to pack NuGet UmbracoCms." }
|
||||
|
||||
@@ -417,7 +428,7 @@
|
||||
$ubuild.DefineMethod("VerifyNuGet",
|
||||
{
|
||||
$this.VerifyNuGetConsistency(
|
||||
("UmbracoCms", "UmbracoCms.Core"),
|
||||
("UmbracoCms", "UmbracoCms.Core", "UmbracoCms.Web"),
|
||||
("Umbraco.Core", "Umbraco.Web", "Umbraco.Web.UI", "Umbraco.Examine"))
|
||||
if ($this.OnError()) { return }
|
||||
})
|
||||
@@ -457,6 +468,7 @@
|
||||
if ($this.OnError()) { return }
|
||||
$this.PrepareAzureGallery()
|
||||
if ($this.OnError()) { return }
|
||||
Write-Host "Done"
|
||||
})
|
||||
|
||||
# ################################################################
|
||||
@@ -472,5 +484,4 @@
|
||||
$ubuild.Build()
|
||||
if ($ubuild.OnError()) { return }
|
||||
}
|
||||
Write-Host "Done"
|
||||
if ($get) { return $ubuild }
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
### Prerequisites
|
||||
|
||||
- [ ] I have written a descriptive pull-request title
|
||||
- [ ] I have linked this PR to an issue on the tracker at http://issues.umbraco.org
|
||||
|
||||
### Description
|
||||
<!-- A description of the changes proposed in the pull-request -->
|
||||
|
||||
|
||||
|
||||
<!-- Thanks for contributing to Umbraco CMS! -->
|
||||
@@ -19,4 +19,4 @@ using System.Resources;
|
||||
|
||||
// these are FYI and changed automatically
|
||||
[assembly: AssemblyFileVersion("8.0.0")]
|
||||
[assembly: AssemblyInformationalVersion("8.0.0-alpha.49")]
|
||||
[assembly: AssemblyInformationalVersion("8.0.0-alpha.52")]
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Components;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
@@ -11,7 +10,7 @@ using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
|
||||
namespace Umbraco.Core.Auditing
|
||||
namespace Umbraco.Core.Components
|
||||
{
|
||||
public sealed class AuditEventsComponent : UmbracoComponentBase, IUmbracoCoreComponent
|
||||
{
|
||||
@@ -53,18 +52,6 @@ namespace Umbraco.Core.Auditing
|
||||
_userService = userService;
|
||||
_entityService = entityService;
|
||||
|
||||
//BackOfficeUserManager.AccountLocked += ;
|
||||
//BackOfficeUserManager.AccountUnlocked += ;
|
||||
BackOfficeUserManager.ForgotPasswordRequested += OnForgotPasswordRequest;
|
||||
BackOfficeUserManager.ForgotPasswordChangedSuccess += OnForgotPasswordChange;
|
||||
BackOfficeUserManager.LoginFailed += OnLoginFailed;
|
||||
//BackOfficeUserManager.LoginRequiresVerification += ;
|
||||
BackOfficeUserManager.LoginSuccess += OnLoginSuccess;
|
||||
BackOfficeUserManager.LogoutSuccess += OnLogoutSuccess;
|
||||
BackOfficeUserManager.PasswordChanged += OnPasswordChanged;
|
||||
BackOfficeUserManager.PasswordReset += OnPasswordReset;
|
||||
//BackOfficeUserManager.ResetAccessFailedCount += ;
|
||||
|
||||
UserService.SavedUserGroup += OnSavedUserGroupWithUsers;
|
||||
|
||||
UserService.SavedUser += OnSavedUser;
|
||||
@@ -255,64 +242,6 @@ namespace Umbraco.Core.Auditing
|
||||
"umbraco/user/delete", "delete user");
|
||||
}
|
||||
|
||||
private void OnLoginSuccess(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs)
|
||||
{
|
||||
var performingUser = GetPerformingUser(identityArgs.PerformingUser);
|
||||
WriteAudit(performingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/sign-in/login", "login success");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLogoutSuccess(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs)
|
||||
{
|
||||
var performingUser = GetPerformingUser(identityArgs.PerformingUser);
|
||||
WriteAudit(performingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/sign-in/logout", "logout success");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPasswordReset(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
|
||||
{
|
||||
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/reset", "password reset");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPasswordChanged(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
|
||||
{
|
||||
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/change", "password change");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLoginFailed(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
|
||||
{
|
||||
WriteAudit(identityArgs.PerformingUser, 0, identityArgs.IpAddress, "umbraco/user/sign-in/failed", "login failed", affectedDetails: "");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnForgotPasswordChange(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
|
||||
{
|
||||
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/forgot/change", "password forgot/change");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnForgotPasswordRequest(object sender, EventArgs args)
|
||||
{
|
||||
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
|
||||
{
|
||||
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/forgot/request", "password forgot/request");
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteAudit(int performingId, int affectedId, string ipAddress, string eventType, string eventDetails, string affectedDetails = null)
|
||||
{
|
||||
var performingUser = _userService.GetUserById(performingId);
|
||||
@@ -1,11 +1,9 @@
|
||||
using System.IO;
|
||||
using Umbraco.Core.Components;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Manifest;
|
||||
|
||||
namespace Umbraco.Core.Strategies
|
||||
namespace Umbraco.Core.Components
|
||||
{
|
||||
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
|
||||
public class ManifestWatcherComponent : UmbracoComponentBase, IUmbracoCoreComponent
|
||||
@@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using Umbraco.Core.Components;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
|
||||
namespace Umbraco.Core.Strategies
|
||||
namespace Umbraco.Core.Components
|
||||
{
|
||||
//TODO: This should just exist in the content service/repo!
|
||||
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
|
||||
@@ -1,13 +1,11 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Components;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
|
||||
namespace Umbraco.Core.Strategies
|
||||
namespace Umbraco.Core.Components
|
||||
{
|
||||
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
|
||||
public sealed class RelateOnTrashComponent : UmbracoComponentBase, IUmbracoCoreComponent
|
||||
@@ -38,8 +38,6 @@ namespace Umbraco.Core.Composing.Composers
|
||||
container.RegisterSingleton<IRelationTypeRepository, RelationTypeRepository>();
|
||||
container.RegisterSingleton<IServerRegistrationRepository, ServerRegistrationRepository>();
|
||||
container.RegisterSingleton<ITagRepository, TagRepository>();
|
||||
container.RegisterSingleton<ITaskRepository, TaskRepository>();
|
||||
container.RegisterSingleton<ITaskTypeRepository, TaskTypeRepository>();
|
||||
container.RegisterSingleton<ITemplateRepository, TemplateRepository>();
|
||||
container.RegisterSingleton<IUserGroupRepository, UserGroupRepository>();
|
||||
container.RegisterSingleton<IUserRepository, UserRepository>();
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace Umbraco.Core.Composing.Composers
|
||||
// register the services
|
||||
container.RegisterSingleton<IKeyValueService, KeyValueService>();
|
||||
container.RegisterSingleton<IPublicAccessService, PublicAccessService>();
|
||||
container.RegisterSingleton<ITaskService, TaskService>();
|
||||
container.RegisterSingleton<IDomainService, DomainService>();
|
||||
container.RegisterSingleton<IAuditService, AuditService>();
|
||||
container.RegisterSingleton<ITagService, TagService>();
|
||||
|
||||
@@ -158,6 +158,9 @@ namespace Umbraco.Core.Composing
|
||||
public static IPublishedValueFallback PublishedValueFallback
|
||||
=> _publishedValueFallback ?? Container.GetInstance<IPublishedValueFallback>() ?? new NoopPublishedValueFallback();
|
||||
|
||||
public static IVariationContextAccessor VariationContextAccessor
|
||||
=> Container.GetInstance<IVariationContextAccessor>();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
[ConfigurationProperty("loginBackgroundImage")]
|
||||
internal InnerTextConfigurationElement<string> LoginBackgroundImage => GetOptionalTextElement("loginBackgroundImage", string.Empty);
|
||||
[ConfigurationProperty("StripUdiAttributes")]
|
||||
internal InnerTextConfigurationElement<bool> StripUdiAttributes
|
||||
{
|
||||
get { return GetOptionalTextElement("StripUdiAttributes", true); }
|
||||
}
|
||||
|
||||
|
||||
string IContentSection.NotificationEmailAddress => Notifications.NotificationEmailAddress;
|
||||
|
||||
@@ -136,6 +142,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
bool IContentSection.EnableInheritedMediaTypes => EnableInheritedMediaTypes;
|
||||
|
||||
bool IContentSection.StripUdiAttributes => StripUdiAttributes;
|
||||
|
||||
string IContentSection.LoginBackgroundImage => LoginBackgroundImage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,24 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
public static class ContentSectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the file extension corresponds to an image.
|
||||
/// </summary>
|
||||
/// <param name="extension">The file extension.</param>
|
||||
/// <param name="contentConfig"></param>
|
||||
/// <returns>A value indicating whether the file extension corresponds to an image.</returns>
|
||||
public static bool IsImageFile(this IContentSection contentConfig, string extension)
|
||||
{
|
||||
if (contentConfig == null) throw new ArgumentNullException(nameof(contentConfig));
|
||||
if (extension == null) return false;
|
||||
extension = extension.TrimStart('.');
|
||||
return contentConfig.ImageFileTypes.InvariantContains(extension);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if file extension is allowed for upload based on (optional) white list and black list
|
||||
/// held in settings.
|
||||
@@ -15,5 +30,17 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
(contentSection.AllowedUploadFiles.Any() == false &&
|
||||
contentSection.DisallowedUploadFiles.Any(x => x.InvariantEquals(extension)) == false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the auto-fill configuration for a specified property alias.
|
||||
/// </summary>
|
||||
/// <param name="contentSection"></param>
|
||||
/// <param name="propertyTypeAlias">The property type alias.</param>
|
||||
/// <returns>The auto-fill configuration for the specified property alias, or null.</returns>
|
||||
public static IImagingAutoFillUploadField GetConfig(this IContentSection contentSection, string propertyTypeAlias)
|
||||
{
|
||||
var autoFillConfigs = contentSection.ImageAutoFillProperties;
|
||||
return autoFillConfigs?.FirstOrDefault(x => x.Alias == propertyTypeAlias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,5 +66,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
bool EnableInheritedMediaTypes { get; }
|
||||
|
||||
string LoginBackgroundImage { get; }
|
||||
bool StripUdiAttributes { get; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
bool DisableAlternativeTemplates { get; }
|
||||
|
||||
bool ValidateAlternativeTemplates { get; }
|
||||
|
||||
bool DisableFindContentByIdPath { get; }
|
||||
|
||||
bool DisableRedirectUrlTracking { get; }
|
||||
@@ -16,5 +18,4 @@
|
||||
|
||||
string UmbracoApplicationUrl { get; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,44 +5,27 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
internal class WebRoutingElement : ConfigurationElement, IWebRoutingSection
|
||||
{
|
||||
[ConfigurationProperty("trySkipIisCustomErrors", DefaultValue = "false")]
|
||||
public bool TrySkipIisCustomErrors
|
||||
{
|
||||
get { return (bool) base["trySkipIisCustomErrors"]; }
|
||||
}
|
||||
public bool TrySkipIisCustomErrors => (bool) base["trySkipIisCustomErrors"];
|
||||
|
||||
[ConfigurationProperty("internalRedirectPreservesTemplate", DefaultValue = "false")]
|
||||
public bool InternalRedirectPreservesTemplate
|
||||
{
|
||||
get { return (bool) base["internalRedirectPreservesTemplate"]; }
|
||||
}
|
||||
public bool InternalRedirectPreservesTemplate => (bool) base["internalRedirectPreservesTemplate"];
|
||||
|
||||
[ConfigurationProperty("disableAlternativeTemplates", DefaultValue = "false")]
|
||||
public bool DisableAlternativeTemplates
|
||||
{
|
||||
get { return (bool) base["disableAlternativeTemplates"]; }
|
||||
}
|
||||
public bool DisableAlternativeTemplates => (bool) base["disableAlternativeTemplates"];
|
||||
|
||||
[ConfigurationProperty("validateAlternativeTemplates", DefaultValue = "false")]
|
||||
public bool ValidateAlternativeTemplates => (bool) base["validateAlternativeTemplates"];
|
||||
|
||||
[ConfigurationProperty("disableFindContentByIdPath", DefaultValue = "false")]
|
||||
public bool DisableFindContentByIdPath
|
||||
{
|
||||
get { return (bool) base["disableFindContentByIdPath"]; }
|
||||
}
|
||||
public bool DisableFindContentByIdPath => (bool) base["disableFindContentByIdPath"];
|
||||
|
||||
[ConfigurationProperty("disableRedirectUrlTracking", DefaultValue = "false")]
|
||||
public bool DisableRedirectUrlTracking
|
||||
{
|
||||
get { return (bool) base["disableRedirectUrlTracking"]; }
|
||||
}
|
||||
public bool DisableRedirectUrlTracking => (bool) base["disableRedirectUrlTracking"];
|
||||
|
||||
[ConfigurationProperty("urlProviderMode", DefaultValue = "AutoLegacy")]
|
||||
public string UrlProviderMode
|
||||
{
|
||||
get { return (string) base["urlProviderMode"]; }
|
||||
}
|
||||
public string UrlProviderMode => (string) base["urlProviderMode"];
|
||||
|
||||
[ConfigurationProperty("umbracoApplicationUrl", DefaultValue = null)]
|
||||
public string UmbracoApplicationUrl
|
||||
{
|
||||
get { return (string)base["umbracoApplicationUrl"]; }
|
||||
}
|
||||
public string UmbracoApplicationUrl => (string)base["umbracoApplicationUrl"];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// <summary>
|
||||
/// Gets the version comment of the executing code (eg "beta").
|
||||
/// </summary>
|
||||
public static string CurrentComment => "alpha.49";
|
||||
public static string CurrentComment => "alpha.52";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assembly version of Umbraco.Code.dll.
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
public const string Content = "content";
|
||||
|
||||
/// <summary>
|
||||
/// Application alias for the developer section.
|
||||
/// Application alias for the packages section.
|
||||
/// </summary>
|
||||
public const string Developer = "developer";
|
||||
public const string Packages = "packages";
|
||||
|
||||
/// <summary>
|
||||
/// Application alias for the media section.
|
||||
|
||||
@@ -23,9 +23,6 @@ namespace Umbraco.Core
|
||||
{
|
||||
public const string MemberUsernameRuleType = "MemberUsername";
|
||||
public const string MemberRoleRuleType = "MemberRole";
|
||||
|
||||
[Obsolete("No longer supported, this is here for backwards compatibility only")]
|
||||
public const string MemberIdRuleType = "MemberId";
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +91,11 @@ namespace Umbraco.Core
|
||||
/// Property alias for the Media's file extension.
|
||||
/// </summary>
|
||||
public const string Extension = "umbracoExtension";
|
||||
|
||||
/// <summary>
|
||||
/// The default height/width of an image file if the size can't be determined from the metadata
|
||||
/// </summary>
|
||||
public const int DefaultSize = 200;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -71,9 +71,6 @@ namespace Umbraco.Core
|
||||
[Obsolete("This no longer exists in the database")]
|
||||
internal const string Stylesheet = "9F68DA4F-A3A8-44C2-8226-DCBD125E4840";
|
||||
|
||||
[Obsolete("This no longer exists in the database")]
|
||||
internal const string StylesheetProperty = "5555da4f-a123-42b2-4488-dcdfb25e4111";
|
||||
|
||||
// ReSharper restore MemberHidesStaticFromOuterClass
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
/// </remarks>
|
||||
public const string RecycleBinMediaPathPrefix = "-1,-21,";
|
||||
|
||||
public const int DefaultLabelDataTypeId = -92;
|
||||
public const string UmbracoConnectionName = "umbracoDbDSN";
|
||||
public const string UmbracoUpgradePlanName = "Umbraco.Core";
|
||||
}
|
||||
|
||||
@@ -7,12 +7,13 @@ using System.Web;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static class ContentExtensions
|
||||
{
|
||||
@@ -241,31 +242,6 @@ namespace Umbraco.Core.Models
|
||||
|
||||
#region SetValue for setting file contents
|
||||
|
||||
/// <summary>
|
||||
/// Sets the posted file value of a property.
|
||||
/// </summary>
|
||||
public static void SetValue(this IContentBase content, string propertyTypeAlias, HttpPostedFileBase value, string culture = null, string segment = null)
|
||||
{
|
||||
// ensure we get the filename without the path in IE in intranet mode
|
||||
// http://stackoverflow.com/questions/382464/httppostedfile-filename-different-from-ie
|
||||
var filename = value.FileName;
|
||||
var pos = filename.LastIndexOf(@"\", StringComparison.InvariantCulture);
|
||||
if (pos > 0)
|
||||
filename = filename.Substring(pos + 1);
|
||||
|
||||
// strip any directory info
|
||||
pos = filename.LastIndexOf(IOHelper.DirSepChar);
|
||||
if (pos > 0)
|
||||
filename = filename.Substring(pos + 1);
|
||||
|
||||
// get a safe & clean filename
|
||||
filename = IOHelper.SafeFileName(filename);
|
||||
if (string.IsNullOrWhiteSpace(filename)) return;
|
||||
filename = filename.ToLower(); // fixme - er... why?
|
||||
|
||||
MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, value.InputStream, culture, segment);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the posted file value of a property.
|
||||
/// </summary>
|
||||
@@ -281,7 +257,31 @@ namespace Umbraco.Core.Models
|
||||
if (string.IsNullOrWhiteSpace(filename)) return;
|
||||
filename = filename.ToLower(); // fixme - er... why?
|
||||
|
||||
MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, filestream, culture, segment);
|
||||
SetUploadFile(content, propertyTypeAlias, filename, filestream, culture, segment);
|
||||
}
|
||||
|
||||
private static void SetUploadFile(this IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null)
|
||||
{
|
||||
var property = GetProperty(content, propertyTypeAlias);
|
||||
var oldpath = property.GetValue(culture, segment) is string svalue ? MediaFileSystem.GetRelativePath(svalue) : null;
|
||||
var filepath = MediaFileSystem.StoreFile(content, property.PropertyType, filename, filestream, oldpath);
|
||||
property.SetValue(MediaFileSystem.GetUrl(filepath), culture, segment);
|
||||
}
|
||||
|
||||
// gets or creates a property for a content item.
|
||||
private static Property GetProperty(IContentBase content, string propertyTypeAlias)
|
||||
{
|
||||
var property = content.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
|
||||
if (property != null) return property;
|
||||
|
||||
var propertyType = content.GetContentType().CompositionPropertyTypes
|
||||
.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
|
||||
if (propertyType == null)
|
||||
throw new Exception("No property type exists with alias " + propertyTypeAlias + ".");
|
||||
|
||||
property = new Property(propertyType);
|
||||
content.Properties.Add(property);
|
||||
return property;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -92,17 +92,6 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The flatten list.</summary>
|
||||
/// <param name="e">The items.</param>
|
||||
/// <param name="f">The select child.</param>
|
||||
/// <typeparam name="T">Item type</typeparam>
|
||||
/// <returns>list of TItem</returns>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Do not use, use SelectRecursive instead which has far less potential of re-iterating an iterator which may cause significantly more SQL queries")]
|
||||
public static IEnumerable<T> FlattenList<T>(this IEnumerable<T> e, Func<T, IEnumerable<T>> f)
|
||||
{
|
||||
return e.SelectMany(c => f(c).FlattenList(f)).Concat(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if all items in the other collection exist in this collection
|
||||
|
||||
@@ -307,7 +307,7 @@ namespace Umbraco.Core.Events
|
||||
|
||||
// fixme see notes above
|
||||
// delete event args does NOT superceedes 'unpublished' event
|
||||
if (argType.IsGenericType && argType.GetGenericTypeDefinition() == typeof(PublishEventArgs<>) && infos.EventDefinition.EventName == "UnPublished")
|
||||
if (argType.IsGenericType && argType.GetGenericTypeDefinition() == typeof(PublishEventArgs<>) && infos.EventDefinition.EventName == "Unpublished")
|
||||
return false;
|
||||
|
||||
// found occurences, need to determine if this event args is superceded
|
||||
|
||||
@@ -24,11 +24,19 @@ namespace Umbraco.Core
|
||||
{
|
||||
return "Unknown, httpContext is null";
|
||||
}
|
||||
if (httpContext.Request == null)
|
||||
|
||||
HttpRequestBase request;
|
||||
try
|
||||
{
|
||||
// is not null - throws
|
||||
request = httpContext.Request;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "Unknown, httpContext.Request is null";
|
||||
}
|
||||
if (httpContext.Request.ServerVariables == null)
|
||||
|
||||
if (request.ServerVariables == null)
|
||||
{
|
||||
return "Unknown, httpContext.Request.ServerVariables is null";
|
||||
}
|
||||
@@ -37,16 +45,16 @@ namespace Umbraco.Core
|
||||
|
||||
try
|
||||
{
|
||||
var ipAddress = httpContext.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
|
||||
var ipAddress = request.ServerVariables["HTTP_X_FORWARDED_FOR"];
|
||||
|
||||
if (string.IsNullOrEmpty(ipAddress))
|
||||
return httpContext.Request.UserHostAddress;
|
||||
return request.UserHostAddress;
|
||||
|
||||
var addresses = ipAddress.Split(',');
|
||||
if (addresses.Length != 0)
|
||||
return addresses[0];
|
||||
|
||||
return httpContext.Request.UserHostAddress;
|
||||
return request.UserHostAddress;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -9,7 +8,6 @@ using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Media;
|
||||
using Umbraco.Core.Media.Exif;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
@@ -27,8 +25,6 @@ namespace Umbraco.Core.IO
|
||||
Logger = Current.Container.GetInstance<ILogger>();
|
||||
MediaPathScheme = Current.Container.GetInstance<IMediaPathScheme>();
|
||||
MediaPathScheme.Initialize(this);
|
||||
|
||||
UploadAutoFillProperties = new UploadAutoFillProperties(this, Logger, ContentConfig);
|
||||
}
|
||||
|
||||
private IMediaPathScheme MediaPathScheme { get; }
|
||||
@@ -37,8 +33,6 @@ namespace Umbraco.Core.IO
|
||||
|
||||
private ILogger Logger { get; }
|
||||
|
||||
internal UploadAutoFillProperties UploadAutoFillProperties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all files passed in.
|
||||
/// </summary>
|
||||
@@ -205,113 +199,9 @@ namespace Umbraco.Core.IO
|
||||
return filepath;
|
||||
}
|
||||
|
||||
// gets or creates a property for a content item.
|
||||
private static Property GetProperty(IContentBase content, string propertyTypeAlias)
|
||||
{
|
||||
var property = content.Properties.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
|
||||
if (property != null) return property;
|
||||
|
||||
var propertyType = content.GetContentType().CompositionPropertyTypes
|
||||
.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
|
||||
if (propertyType == null)
|
||||
throw new Exception("No property type exists with alias " + propertyTypeAlias + ".");
|
||||
|
||||
property = new Property(propertyType);
|
||||
content.Properties.Add(property);
|
||||
return property;
|
||||
}
|
||||
|
||||
// fixme - what's below belongs to the upload property editor, not the media filesystem!
|
||||
|
||||
public void SetUploadFile(IContentBase content, string propertyTypeAlias, string filename, Stream filestream, string culture = null, string segment = null)
|
||||
{
|
||||
var property = GetProperty(content, propertyTypeAlias);
|
||||
var oldpath = property.GetValue(culture, segment) is string svalue ? GetRelativePath(svalue) : null;
|
||||
var filepath = StoreFile(content, property.PropertyType, filename, filestream, oldpath);
|
||||
property.SetValue(GetUrl(filepath), culture, segment);
|
||||
SetUploadFile(content, property, filepath, filestream, culture, segment);
|
||||
}
|
||||
|
||||
public void SetUploadFile(IContentBase content, string propertyTypeAlias, string filepath, string culture = null, string segment = null)
|
||||
{
|
||||
var property = GetProperty(content, propertyTypeAlias);
|
||||
// fixme delete?
|
||||
var oldpath = property.GetValue(culture, segment) is string svalue ? GetRelativePath(svalue) : null;
|
||||
if (string.IsNullOrWhiteSpace(oldpath) == false && oldpath != filepath)
|
||||
DeleteFile(oldpath);
|
||||
property.SetValue(GetUrl(filepath), culture, segment);
|
||||
using (var filestream = OpenFile(filepath))
|
||||
{
|
||||
SetUploadFile(content, property, filepath, filestream, culture, segment);
|
||||
}
|
||||
}
|
||||
|
||||
// sets a file for the FileUpload property editor
|
||||
// ie generates thumbnails and populates autofill properties
|
||||
private void SetUploadFile(IContentBase content, Property property, string filepath, Stream filestream, string culture = null, string segment = null)
|
||||
{
|
||||
// will use filepath for extension, and filestream for length
|
||||
UploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream, culture, segment);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Image
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the file extension corresponds to an image.
|
||||
/// </summary>
|
||||
/// <param name="extension">The file extension.</param>
|
||||
/// <returns>A value indicating whether the file extension corresponds to an image.</returns>
|
||||
public bool IsImageFile(string extension)
|
||||
{
|
||||
if (extension == null) return false;
|
||||
extension = extension.TrimStart('.');
|
||||
return ContentConfig.ImageFileTypes.InvariantContains(extension);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the dimensions of an image.
|
||||
/// </summary>
|
||||
/// <param name="stream">A stream containing the image bytes.</param>
|
||||
/// <returns>The dimension of the image.</returns>
|
||||
/// <remarks>First try with EXIF as it is faster and does not load the entire image
|
||||
/// in memory. Fallback to GDI which means loading the image in memory and thus
|
||||
/// use potentially large amounts of memory.</remarks>
|
||||
public Size GetDimensions(Stream stream)
|
||||
{
|
||||
//Try to load with exif
|
||||
try
|
||||
{
|
||||
var jpgInfo = ImageFile.FromStream(stream);
|
||||
|
||||
if (jpgInfo.Format != ImageFileFormat.Unknown
|
||||
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelYDimension)
|
||||
&& jpgInfo.Properties.ContainsKey(ExifTag.PixelXDimension))
|
||||
{
|
||||
var height = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelYDimension].Value);
|
||||
var width = Convert.ToInt32(jpgInfo.Properties[ExifTag.PixelXDimension].Value);
|
||||
if (height > 0 && width > 0)
|
||||
{
|
||||
return new Size(width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//We will just swallow, just means we can't read exif data, we don't want to log an error either
|
||||
}
|
||||
|
||||
//we have no choice but to try to read in via GDI
|
||||
using (var image = Image.FromStream(stream))
|
||||
{
|
||||
|
||||
var fileWidth = image.Width;
|
||||
var fileHeight = image.Height;
|
||||
return new Size(fileWidth, fileHeight);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public static string Umbraco => IOHelper.ReturnPath("umbracoPath", "~/umbraco");
|
||||
|
||||
[Obsolete("This will be removed, there is no more umbraco_client folder")]
|
||||
public static string UmbracoClient => IOHelper.ReturnPath("umbracoClientPath", "~/umbraco_client");
|
||||
|
||||
public static string UserControls => IOHelper.ReturnPath("umbracoUsercontrolsPath", "~/usercontrols");
|
||||
|
||||
@@ -30,17 +30,17 @@ namespace Umbraco.Core.Logging
|
||||
_endMessage = endMessage;
|
||||
_failMessage = failMessage;
|
||||
_thresholdMilliseconds = thresholdMilliseconds < 0 ? 0 : thresholdMilliseconds;
|
||||
_timingId = Guid.NewGuid().ToString("N");
|
||||
_timingId = Guid.NewGuid().ToString("N").Substring(0, 7); // keep it short-ish
|
||||
|
||||
if (thresholdMilliseconds == 0)
|
||||
{
|
||||
switch (_level)
|
||||
{
|
||||
case LogLevel.Debug:
|
||||
logger.Debug(loggerType, "[Timing {TimingId}] {StartMessage}", _timingId, startMessage);
|
||||
logger.Debug(loggerType, "{StartMessage} [Timing {TimingId}]", startMessage, _timingId);
|
||||
break;
|
||||
case LogLevel.Information:
|
||||
logger.Info(loggerType, "[Timing {TimingId}] {StartMessage}", _timingId, startMessage);
|
||||
logger.Info(loggerType, "{StartMessage} [Timing {TimingId}]", startMessage, _timingId);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(level));
|
||||
@@ -84,15 +84,15 @@ namespace Umbraco.Core.Logging
|
||||
{
|
||||
if (_failed)
|
||||
{
|
||||
_logger.Error(_loggerType, _failException, "[Timing {TimingId}] {FailMessage} ({TimingDuration}ms)", _timingId, _failMessage, Stopwatch.ElapsedMilliseconds);
|
||||
_logger.Error(_loggerType, _failException, "{FailMessage} ({Duration}ms) [Timing {TimingId}]", _failMessage, Stopwatch.ElapsedMilliseconds, _timingId);
|
||||
}
|
||||
else switch (_level)
|
||||
{
|
||||
case LogLevel.Debug:
|
||||
_logger.Debug(_loggerType, "[Timing {TimingId}] {EndMessage} ({TimingDuration}ms)", _timingId, _endMessage, Stopwatch.ElapsedMilliseconds);
|
||||
_logger.Debug(_loggerType, "{EndMessage} ({Duration}ms) [Timing {TimingId}]", _endMessage, Stopwatch.ElapsedMilliseconds, _timingId);
|
||||
break;
|
||||
case LogLevel.Information:
|
||||
_logger.Info(_loggerType, "[Timing {TimingId}] {EndMessage} ({TimingDuration}ms)", _timingId, _endMessage, Stopwatch.ElapsedMilliseconds);
|
||||
_logger.Info(_loggerType, "{EndMessage} ({Duration}ms) [Timing {TimingId}]", _endMessage, Stopwatch.ElapsedMilliseconds, _timingId);
|
||||
break;
|
||||
// filtered in the ctor
|
||||
//default:
|
||||
|
||||
32
src/Umbraco.Core/Logging/LogHttpRequest.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
public static class LogHttpRequest
|
||||
{
|
||||
static readonly string RequestIdItemName = typeof(LogHttpRequest).Name + "+RequestId";
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the id assigned to the currently-executing HTTP request, if any.
|
||||
/// </summary>
|
||||
/// <param name="requestId">The request id.</param>
|
||||
/// <returns><c>true</c> if there is a request in progress; <c>false</c> otherwise.</returns>
|
||||
public static bool TryGetCurrentHttpRequestId(out Guid requestId)
|
||||
{
|
||||
if (HttpContext.Current == null)
|
||||
{
|
||||
requestId = default(Guid);
|
||||
return false;
|
||||
}
|
||||
|
||||
var requestIdItem = HttpContext.Current.Items[RequestIdItemName];
|
||||
if (requestIdItem == null)
|
||||
HttpContext.Current.Items[RequestIdItemName] = requestId = Guid.NewGuid();
|
||||
else
|
||||
requestId = (Guid)requestIdItem;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
|
||||
namespace Umbraco.Core.Logging.Serilog.Enrichers
|
||||
{
|
||||
/// <summary>
|
||||
/// Enrich log events with a HttpRequestId GUID.
|
||||
/// Original source - https://github.com/serilog-web/classic/blob/master/src/SerilogWeb.Classic/Classic/Enrichers/HttpRequestIdEnricher.cs
|
||||
/// Nupkg: 'Serilog.Web.Classic' contains handlers & extra bits we do not want
|
||||
/// </summary>
|
||||
internal class HttpRequestIdEnricher : ILogEventEnricher
|
||||
{
|
||||
/// <summary>
|
||||
/// The property name added to enriched log events.
|
||||
/// </summary>
|
||||
public const string HttpRequestIdPropertyName = "HttpRequestId";
|
||||
|
||||
/// <summary>
|
||||
/// Enrich the log event with an id assigned to the currently-executing HTTP request, if any.
|
||||
/// </summary>
|
||||
/// <param name="logEvent">The log event to enrich.</param>
|
||||
/// <param name="propertyFactory">Factory for creating new properties to add to the event.</param>
|
||||
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
|
||||
{
|
||||
if (logEvent == null) throw new ArgumentNullException("logEvent");
|
||||
|
||||
Guid requestId;
|
||||
if (!LogHttpRequest.TryGetCurrentHttpRequestId(out requestId))
|
||||
return;
|
||||
|
||||
var requestIdProperty = new LogEventProperty(HttpRequestIdPropertyName, new ScalarValue(requestId));
|
||||
logEvent.AddPropertyIfAbsent(requestIdProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
|
||||
namespace Umbraco.Core.Logging.Serilog.Enrichers
|
||||
{
|
||||
/// <summary>
|
||||
/// Enrich log events with a HttpRequestNumber unique within the current
|
||||
/// logging session.
|
||||
/// Original source - https://github.com/serilog-web/classic/blob/master/src/SerilogWeb.Classic/Classic/Enrichers/HttpRequestNumberEnricher.cs
|
||||
/// Nupkg: 'Serilog.Web.Classic' contains handlers & extra bits we do not want
|
||||
/// </summary>
|
||||
internal class HttpRequestNumberEnricher : ILogEventEnricher
|
||||
{
|
||||
/// <summary>
|
||||
/// The property name added to enriched log events.
|
||||
/// </summary>
|
||||
public const string HttpRequestNumberPropertyName = "HttpRequestNumber";
|
||||
|
||||
static int _lastRequestNumber;
|
||||
static readonly string RequestNumberItemName = typeof(HttpRequestNumberEnricher).Name + "+RequestNumber";
|
||||
|
||||
/// <summary>
|
||||
/// Enrich the log event with the number assigned to the currently-executing HTTP request, if any.
|
||||
/// </summary>
|
||||
/// <param name="logEvent">The log event to enrich.</param>
|
||||
/// <param name="propertyFactory">Factory for creating new properties to add to the event.</param>
|
||||
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
|
||||
{
|
||||
if (logEvent == null) throw new ArgumentNullException("logEvent");
|
||||
|
||||
if (HttpContext.Current == null)
|
||||
return;
|
||||
|
||||
int requestNumber;
|
||||
var requestNumberItem = HttpContext.Current.Items[RequestNumberItemName];
|
||||
if (requestNumberItem == null)
|
||||
HttpContext.Current.Items[RequestNumberItemName] = requestNumber = Interlocked.Increment(ref _lastRequestNumber);
|
||||
else
|
||||
requestNumber = (int)requestNumberItem;
|
||||
|
||||
var requestNumberProperty = new LogEventProperty(HttpRequestNumberPropertyName, new ScalarValue(requestNumber));
|
||||
logEvent.AddPropertyIfAbsent(requestNumberProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
using System;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core.Logging.Serilog.Enrichers
|
||||
{
|
||||
/// <summary>
|
||||
/// Enrich log events with the HttpSessionId property.
|
||||
/// Original source - https://github.com/serilog-web/classic/blob/master/src/SerilogWeb.Classic/Classic/Enrichers/HttpSessionIdEnricher.cs
|
||||
/// Nupkg: 'Serilog.Web.Classic' contains handlers & extra bits we do not want
|
||||
/// </summary>
|
||||
internal class HttpSessionIdEnricher : ILogEventEnricher
|
||||
{
|
||||
/// <summary>
|
||||
/// The property name added to enriched log events.
|
||||
/// </summary>
|
||||
public const string HttpSessionIdPropertyName = "HttpSessionId";
|
||||
|
||||
/// <summary>
|
||||
/// Enrich the log event with the current ASP.NET session id, if sessions are enabled.</summary>
|
||||
/// <param name="logEvent">The log event to enrich.</param>
|
||||
/// <param name="propertyFactory">Factory for creating new properties to add to the event.</param>
|
||||
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
|
||||
{
|
||||
if (logEvent == null) throw new ArgumentNullException("logEvent");
|
||||
|
||||
if (HttpContext.Current == null)
|
||||
return;
|
||||
|
||||
if (HttpContext.Current.Session == null)
|
||||
return;
|
||||
|
||||
var sessionId = HttpContext.Current.Session.SessionID;
|
||||
var sessionIdProperty = new LogEventProperty(HttpSessionIdPropertyName, new ScalarValue(sessionId));
|
||||
logEvent.AddPropertyIfAbsent(sessionIdProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
|
||||
namespace Umbraco.Core.Logging.Serilog
|
||||
namespace Umbraco.Core.Logging.Serilog.Enrichers
|
||||
{
|
||||
/// <summary>
|
||||
/// This is used to create a new property in Logs called 'Log4NetLevel'
|
||||
@@ -3,6 +3,7 @@ using System.Web;
|
||||
using Serilog;
|
||||
using Serilog.Events;
|
||||
using Serilog.Formatting.Compact;
|
||||
using Umbraco.Core.Logging.Serilog.Enrichers;
|
||||
|
||||
namespace Umbraco.Core.Logging.Serilog
|
||||
{
|
||||
@@ -29,7 +30,10 @@ namespace Umbraco.Core.Logging.Serilog
|
||||
.Enrich.WithProperty("AppDomainId", AppDomain.CurrentDomain.Id)
|
||||
.Enrich.WithProperty("AppDomainAppId", HttpRuntime.AppDomainAppId.ReplaceNonAlphanumericChars(string.Empty))
|
||||
.Enrich.WithProperty("MachineName", Environment.MachineName)
|
||||
.Enrich.With<Log4NetLevelMapperEnricher>();
|
||||
.Enrich.With<Log4NetLevelMapperEnricher>()
|
||||
.Enrich.With<HttpSessionIdEnricher>()
|
||||
.Enrich.With<HttpRequestNumberEnricher>()
|
||||
.Enrich.With<HttpRequestIdEnricher>();
|
||||
|
||||
return logConfig;
|
||||
}
|
||||
|
||||
16
src/Umbraco.Core/Manifest/ContentAppDefinitionConverter.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.Models.ContentEditing;
|
||||
using Umbraco.Core.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Manifest
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a json read converter for <see cref="IContentAppDefinition"/>.
|
||||
/// </summary>
|
||||
internal class ContentAppDefinitionConverter : JsonReadConverter<IContentAppDefinition>
|
||||
{
|
||||
protected override IContentAppDefinition Create(Type objectType, string path, JObject jObject)
|
||||
=> new ManifestContentAppDefinition();
|
||||
}
|
||||
}
|
||||
176
src/Umbraco.Core/Manifest/ManifestContentAppDefinition.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.ContentEditing;
|
||||
|
||||
namespace Umbraco.Core.Manifest
|
||||
{
|
||||
// contentApps: [
|
||||
// {
|
||||
// name: 'App Name', // required
|
||||
// alias: 'appAlias', // required
|
||||
// weight: 0, // optional, default is 0, use values between -99 and +99
|
||||
// icon: 'icon.app', // required
|
||||
// view: 'path/view.htm', // required
|
||||
// show: [ // optional, default is always show
|
||||
// '-content/foo', // hide for content type 'foo'
|
||||
// '+content/*', // show for all other content types
|
||||
// '+media/*' // show for all media types
|
||||
// ]
|
||||
// },
|
||||
// ...
|
||||
// ]
|
||||
|
||||
/// <summary>
|
||||
/// Represents a content app definition, parsed from a manifest.
|
||||
/// </summary>
|
||||
[DataContract(Name = "appdef", Namespace = "")]
|
||||
public class ManifestContentAppDefinition : IContentAppDefinition
|
||||
{
|
||||
private string _view;
|
||||
private ContentApp _app;
|
||||
private ShowRule[] _showRules;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the content app.
|
||||
/// </summary>
|
||||
[DataMember(Name = "name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the unique alias of the content app.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Must be a valid javascript identifier, ie no spaces etc.</para>
|
||||
/// </remarks>
|
||||
[DataMember(Name = "alias")]
|
||||
public string Alias { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the weight of the content app.
|
||||
/// </summary>
|
||||
[DataMember(Name = "weight")]
|
||||
public int Weight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the icon of the content app.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Must be a valid helveticons class name (see http://hlvticons.ch/).</para>
|
||||
/// </remarks>
|
||||
[DataMember(Name = "icon")]
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the view for rendering the content app.
|
||||
/// </summary>
|
||||
[DataMember(Name = "view")]
|
||||
public string View
|
||||
{
|
||||
get => _view;
|
||||
set => _view = IOHelper.ResolveVirtualUrl(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the list of 'show' conditions for the content app.
|
||||
/// </summary>
|
||||
[DataMember(Name = "show")]
|
||||
public string[] Show { get; set; } = Array.Empty<string>();
|
||||
|
||||
/// <inheritdoc />
|
||||
public ContentApp GetContentAppFor(object o)
|
||||
{
|
||||
string partA, partB;
|
||||
|
||||
switch (o)
|
||||
{
|
||||
case IContent content:
|
||||
partA = "content";
|
||||
partB = content.ContentType.Alias;
|
||||
break;
|
||||
|
||||
case IMedia media:
|
||||
partA = "media";
|
||||
partB = media.ContentType.Alias;
|
||||
break;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
var rules = _showRules ?? (_showRules = ShowRule.Parse(Show).ToArray());
|
||||
|
||||
// if no 'show' is specified, then always display the content app
|
||||
if (rules.Length > 0)
|
||||
{
|
||||
var ok = false;
|
||||
|
||||
// else iterate over each entry
|
||||
foreach (var rule in rules)
|
||||
{
|
||||
// if the entry does not apply, skip it
|
||||
if (!rule.Matches(partA, partB))
|
||||
continue;
|
||||
|
||||
// if the entry applies,
|
||||
// if it's an exclude entry, exit, do not display the content app
|
||||
if (!rule.Show)
|
||||
return null;
|
||||
|
||||
// else break - ok to display
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// when 'show' is specified, default is to *not* show the content app
|
||||
if (!ok)
|
||||
return null;
|
||||
}
|
||||
|
||||
// content app can be displayed
|
||||
return _app ?? (_app = new ContentApp
|
||||
{
|
||||
Alias = Alias,
|
||||
Name = Name,
|
||||
Icon = Icon,
|
||||
View = View,
|
||||
Weight = Weight
|
||||
});
|
||||
}
|
||||
|
||||
private class ShowRule
|
||||
{
|
||||
private static readonly Regex ShowRegex = new Regex("^([+-])?([a-z]+)/([a-z0-9_]+|\\*)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public bool Show { get; private set; }
|
||||
public string PartA { get; private set; }
|
||||
public string PartB { get; private set; }
|
||||
|
||||
public bool Matches(string partA, string partB)
|
||||
{
|
||||
return (PartA == "*" || PartA.InvariantEquals(partA)) && (PartB == "*" || PartB.InvariantEquals(partB));
|
||||
}
|
||||
|
||||
public static IEnumerable<ShowRule> Parse(string[] rules)
|
||||
{
|
||||
foreach (var rule in rules)
|
||||
{
|
||||
var match = ShowRegex.Match(rule);
|
||||
if (!match.Success)
|
||||
throw new FormatException($"Illegal 'show' entry \"{rule}\" in manifest.");
|
||||
|
||||
yield return new ShowRule
|
||||
{
|
||||
Show = match.Groups[1].Value != "-",
|
||||
PartA = match.Groups[2].Value,
|
||||
PartB = match.Groups[3].Value
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.ContentEditing;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Core.Manifest
|
||||
@@ -98,6 +99,7 @@ namespace Umbraco.Core.Manifest
|
||||
var propertyEditors = new List<IDataEditor>();
|
||||
var parameterEditors = new List<IDataEditor>();
|
||||
var gridEditors = new List<GridEditor>();
|
||||
var contentApps = new List<IContentAppDefinition>();
|
||||
|
||||
foreach (var manifest in manifests)
|
||||
{
|
||||
@@ -106,6 +108,7 @@ namespace Umbraco.Core.Manifest
|
||||
if (manifest.PropertyEditors != null) propertyEditors.AddRange(manifest.PropertyEditors);
|
||||
if (manifest.ParameterEditors != null) parameterEditors.AddRange(manifest.ParameterEditors);
|
||||
if (manifest.GridEditors != null) gridEditors.AddRange(manifest.GridEditors);
|
||||
if (manifest.ContentApps != null) contentApps.AddRange(manifest.ContentApps);
|
||||
}
|
||||
|
||||
return new PackageManifest
|
||||
@@ -114,7 +117,8 @@ namespace Umbraco.Core.Manifest
|
||||
Stylesheets = stylesheets.ToArray(),
|
||||
PropertyEditors = propertyEditors.ToArray(),
|
||||
ParameterEditors = parameterEditors.ToArray(),
|
||||
GridEditors = gridEditors.ToArray()
|
||||
GridEditors = gridEditors.ToArray(),
|
||||
ContentApps = contentApps.ToArray()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -146,7 +150,8 @@ namespace Umbraco.Core.Manifest
|
||||
|
||||
var manifest = JsonConvert.DeserializeObject<PackageManifest>(text,
|
||||
new DataEditorConverter(_logger),
|
||||
new ValueValidatorConverter(_validators));
|
||||
new ValueValidatorConverter(_validators),
|
||||
new ContentAppDefinitionConverter());
|
||||
|
||||
// scripts and stylesheets are raw string, must process here
|
||||
for (var i = 0; i < manifest.Scripts.Length; i++)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Umbraco.Core.Models.ContentEditing;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Core.Manifest
|
||||
@@ -23,5 +24,8 @@ namespace Umbraco.Core.Manifest
|
||||
|
||||
[JsonProperty("gridEditors")]
|
||||
public GridEditor[] GridEditors { get; set; } = Array.Empty<GridEditor>();
|
||||
|
||||
[JsonProperty("contentApps")]
|
||||
public IContentAppDefinition[] ContentApps { get; set; } = Array.Empty<IContentAppDefinition>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Media
|
||||
{
|
||||
public static class ImageExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the MIME type of an image.
|
||||
/// </summary>
|
||||
/// <param name="image">The image.</param>
|
||||
/// <returns>The MIME type of the image.</returns>
|
||||
public static string GetMimeType(this Image image)
|
||||
{
|
||||
var format = image.RawFormat;
|
||||
var codec = ImageCodecInfo.GetImageDecoders().First(c => c.FormatID == format.Guid);
|
||||
return codec.MimeType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,9 +70,6 @@ namespace Umbraco.Core.Migrations.Install
|
||||
if (tableName.Equals(Constants.DatabaseSchema.Tables.RelationType))
|
||||
CreateRelationTypeData();
|
||||
|
||||
if (tableName.Equals(Constants.DatabaseSchema.Tables.TaskType))
|
||||
CreateTaskTypeData();
|
||||
|
||||
if (tableName.Equals(Constants.DatabaseSchema.Tables.KeyValue))
|
||||
CreateKeyValueData();
|
||||
|
||||
@@ -152,6 +149,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.MemberTypes, Name = "MemberTypes" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Lock, "id", false, new LockDto { Id = Constants.Locks.MemberTree, Name = "MemberTree" });
|
||||
_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.Languages, Name = "Languages" });
|
||||
}
|
||||
|
||||
private void CreateContentTypeData()
|
||||
@@ -185,7 +183,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
private void CreateUserGroup2AppData()
|
||||
{
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Content });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Developer });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Packages });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Media });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Members });
|
||||
_database.Insert(new UserGroup2AppDto { UserGroupId = 1, AppAlias = Constants.Applications.Settings });
|
||||
@@ -232,7 +230,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
|
||||
private void CreateLanguageData()
|
||||
{
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Language, "id", false, new LanguageDto { Id = 1, IsoCode = "en-US", CultureName = "English (United States)" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Language, "id", false, new LanguageDto { Id = 1, IsoCode = "en-US", CultureName = "English (United States)", IsDefault = true });
|
||||
}
|
||||
|
||||
private void CreateContentChildTypeData()
|
||||
@@ -318,11 +316,6 @@ namespace Umbraco.Core.Migrations.Install
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.RelationType, "id", false, relationType);
|
||||
}
|
||||
|
||||
private void CreateTaskTypeData()
|
||||
{
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.TaskType, "id", false, new TaskTypeDto { Id = 1, Alias = "toTranslate" });
|
||||
}
|
||||
|
||||
private void CreateKeyValueData()
|
||||
{
|
||||
// on install, initialize the umbraco migration plan with the final state
|
||||
|
||||
@@ -59,8 +59,6 @@ namespace Umbraco.Core.Migrations.Install
|
||||
typeof (RelationDto),
|
||||
typeof (TagDto),
|
||||
typeof (TagRelationshipDto),
|
||||
typeof (TaskTypeDto),
|
||||
typeof (TaskDto),
|
||||
typeof (ContentType2ContentTypeDto),
|
||||
typeof (ContentTypeAllowedContentTypeDto),
|
||||
typeof (User2NodeNotifyDto),
|
||||
|
||||
@@ -107,16 +107,37 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
|
||||
Chain<UserForeignKeys>("{3E44F712-E2E3-473A-AE49-5D7F8E67CE3F}"); // shannon added that one - let's keep it as the default path
|
||||
//Chain<AddTypedLabels>("{65D6B71C-BDD5-4A2E-8D35-8896325E9151}"); // stephan added that one = merge conflict, remove,
|
||||
Chain<AddTypedLabels>("{4CACE351-C6B9-4F0C-A6BA-85A02BBD39E4}"); // but it after shannon's, with a new target state,
|
||||
Chain<AddTypedLabels>("{4CACE351-C6B9-4F0C-A6BA-85A02BBD39E4}"); // but add it after shannon's, with a new target state,
|
||||
Add<UserForeignKeys>("{65D6B71C-BDD5-4A2E-8D35-8896325E9151}", "{4CACE351-C6B9-4F0C-A6BA-85A02BBD39E4}"); // and provide a path out of the conflict state
|
||||
// resume at {4CACE351-C6B9-4F0C-A6BA-85A02BBD39E4} ...
|
||||
|
||||
Chain<ContentVariationMigration>("{1350617A-4930-4D61-852F-E3AA9E692173}");
|
||||
Chain<UpdateUmbracoConsent>("{39E5B1F7-A50B-437E-B768-1723AEC45B65}"); // from 7.12.0
|
||||
//Chain<FallbackLanguage>("{CF51B39B-9B9A-4740-BB7C-EAF606A7BFBF}"); // andy added that one = merge conflict, remove
|
||||
Chain<AddRelationTypeForMediaFolderOnDelete>("{0541A62B-EF87-4CA2-8225-F0EB98ECCC9F}"); // from 7.12.0
|
||||
Chain<IncreaseLanguageIsoCodeColumnLength>("{EB34B5DC-BB87-4005-985E-D983EA496C38}"); // from 7.12.0
|
||||
Chain<RenameTrueFalseField>("{517CE9EA-36D7-472A-BF4B-A0D6FB1B8F89}"); // from 7.12.0
|
||||
Chain<SetDefaultTagsStorageType>("{BBD99901-1545-40E4-8A5A-D7A675C7D2F2}"); // from 7.12.0
|
||||
//Chain<UpdateDefaultMandatoryLanguage>("{2C87AA47-D1BC-4ECB-8A73-2D8D1046C27F}"); // stephan added that one = merge conflict, remove
|
||||
|
||||
Chain<FallbackLanguage>("{8B14CEBD-EE47-4AAD-A841-93551D917F11}"); // add andy's after others, with a new target state
|
||||
From("{CF51B39B-9B9A-4740-BB7C-EAF606A7BFBF}") // and provide a path out of andy's
|
||||
.CopyChain("{39E5B1F7-A50B-437E-B768-1723AEC45B65}", "{BBD99901-1545-40E4-8A5A-D7A675C7D2F2}", "{8B14CEBD-EE47-4AAD-A841-93551D917F11}"); // to next
|
||||
// resume at {8B14CEBD-EE47-4AAD-A841-93551D917F11} ...
|
||||
|
||||
Chain<UpdateDefaultMandatoryLanguage>("{5F4597F4-A4E0-4AFE-90B5-6D2F896830EB}"); // add stephan's after others, with a new target state
|
||||
From("{2C87AA47-D1BC-4ECB-8A73-2D8D1046C27F}") // and provide a path out of stephan's
|
||||
.Chain<FallbackLanguage>("{5F4597F4-A4E0-4AFE-90B5-6D2F896830EB}"); // to next
|
||||
// resume at {5F4597F4-A4E0-4AFE-90B5-6D2F896830EB} ...
|
||||
|
||||
//Chain<RefactorVariantsModel>("{B19BF0F2-E1C6-4AEB-A146-BC559D97A2C6}");
|
||||
Chain<RefactorVariantsModel>("{290C18EE-B3DE-4769-84F1-1F467F3F76DA}");
|
||||
From("{B19BF0F2-E1C6-4AEB-A146-BC559D97A2C6}")
|
||||
.Chain<FallbackLanguage>("{290C18EE-B3DE-4769-84F1-1F467F3F76DA}");
|
||||
// resume at {290C18EE-B3DE-4769-84F1-1F467F3F76DA}...
|
||||
|
||||
Chain<DropTaskTables>("{6A2C7C1B-A9DB-4EA9-B6AB-78E7D5B722A7}");
|
||||
|
||||
//FINAL
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -23,11 +24,18 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
|
||||
private void EnsureLockObject(int id, string name)
|
||||
{
|
||||
var db = Database;
|
||||
EnsureLockObject(Database, id, name);
|
||||
}
|
||||
|
||||
internal static void EnsureLockObject(IUmbracoDatabase db, int id, string name)
|
||||
{
|
||||
// not if it already exists
|
||||
var exists = db.Exists<LockDto>(id);
|
||||
if (exists) return;
|
||||
|
||||
// be safe: delete old umbracoNode lock objects if any
|
||||
db.Execute($"DELETE FROM umbracoNode WHERE id={id};");
|
||||
|
||||
// then create umbracoLock object
|
||||
db.Execute($"INSERT umbracoLock (id, name, value) VALUES ({id}, '{name}', 1);");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
{
|
||||
public class DropTaskTables : MigrationBase
|
||||
{
|
||||
public DropTaskTables(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
Delete.Table("cmsTaskType");
|
||||
Delete.Table("cmsTask");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a new, self-joined field to umbracoLanguages to hold the fall-back language for
|
||||
/// a given language.
|
||||
/// </summary>
|
||||
public class FallbackLanguage : MigrationBase
|
||||
{
|
||||
public FallbackLanguage(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray();
|
||||
|
||||
if (columns.Any(x => x.TableName.InvariantEquals(Constants.DatabaseSchema.Tables.Language) && x.ColumnName.InvariantEquals("fallbackLanguageId")) == false)
|
||||
AddColumn<LanguageDto>("fallbackLanguageId");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
{
|
||||
public class RefactorVariantsModel : MigrationBase
|
||||
{
|
||||
public RefactorVariantsModel(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
Delete.Column("edited").FromTable(Constants.DatabaseSchema.Tables.ContentVersionCultureVariation).Do();
|
||||
|
||||
|
||||
// add available column
|
||||
AddColumn<DocumentCultureVariationDto>("available", out var sqls);
|
||||
|
||||
// so far, only those cultures that were available had records in the table
|
||||
Update.Table(DocumentCultureVariationDto.TableName).Set(new { available = true }).AllRows().Do();
|
||||
|
||||
foreach (var sql in sqls) Execute.Sql(sql).Do();
|
||||
|
||||
|
||||
// add published column
|
||||
AddColumn<DocumentCultureVariationDto>("published", out sqls);
|
||||
|
||||
// make it false by default
|
||||
Update.Table(DocumentCultureVariationDto.TableName).Set(new { published = false }).AllRows().Do();
|
||||
|
||||
// now figure out whether these available cultures are published, too
|
||||
var getPublished = Sql()
|
||||
.Select<NodeDto>(x => x.NodeId)
|
||||
.AndSelect<ContentVersionCultureVariationDto>(x => x.LanguageId)
|
||||
.From<NodeDto>()
|
||||
.InnerJoin<ContentVersionDto>().On<NodeDto, ContentVersionDto>((node, cv) => node.NodeId == cv.NodeId)
|
||||
.InnerJoin<DocumentVersionDto>().On<ContentVersionDto, DocumentVersionDto>((cv, dv) => cv.Id == dv.Id && dv.Published)
|
||||
.InnerJoin<ContentVersionCultureVariationDto>().On<ContentVersionDto, ContentVersionCultureVariationDto>((cv, ccv) => cv.Id == ccv.VersionId);
|
||||
|
||||
foreach (var dto in Database.Fetch<TempDto>(getPublished))
|
||||
Database.Execute(Sql()
|
||||
.Update<DocumentCultureVariationDto>(u => u.Set(x => x.Published, true))
|
||||
.Where<DocumentCultureVariationDto>(x => x.NodeId == dto.NodeId && x.LanguageId == dto.LanguageId));
|
||||
|
||||
foreach (var sql in sqls) Execute.Sql(sql).Do();
|
||||
|
||||
// so far, it was kinda impossible to make a culture unavailable again,
|
||||
// so we *should* not have anything published but not available - ignore
|
||||
|
||||
|
||||
// add name column
|
||||
AddColumn<DocumentCultureVariationDto>("name");
|
||||
|
||||
// so far, every record in the table mapped to an available culture
|
||||
var getNames = Sql()
|
||||
.Select<NodeDto>(x => x.NodeId)
|
||||
.AndSelect<ContentVersionCultureVariationDto>(x => x.LanguageId, x => x.Name)
|
||||
.From<NodeDto>()
|
||||
.InnerJoin<ContentVersionDto>().On<NodeDto, ContentVersionDto>((node, cv) => node.NodeId == cv.NodeId && cv.Current)
|
||||
.InnerJoin<ContentVersionCultureVariationDto>().On<ContentVersionDto, ContentVersionCultureVariationDto>((cv, ccv) => cv.Id == ccv.VersionId);
|
||||
|
||||
foreach (var dto in Database.Fetch<TempDto>(getNames))
|
||||
Database.Execute(Sql()
|
||||
.Update<DocumentCultureVariationDto>(u => u.Set(x => x.Name, dto.Name))
|
||||
.Where<DocumentCultureVariationDto>(x => x.NodeId == dto.NodeId && x.LanguageId == dto.LanguageId));
|
||||
}
|
||||
|
||||
// ReSharper disable once ClassNeverInstantiated.Local
|
||||
// ReSharper disable UnusedAutoPropertyAccessor.Local
|
||||
private class TempDto
|
||||
{
|
||||
public int NodeId { get; set; }
|
||||
public int LanguageId { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
// ReSharper restore UnusedAutoPropertyAccessor.Local
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
|
||||
{
|
||||
public class UpdateDefaultMandatoryLanguage : MigrationBase
|
||||
{
|
||||
public UpdateDefaultMandatoryLanguage(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
// add the new languages lock object
|
||||
AddLockObjects.EnsureLockObject(Database, Constants.Locks.Languages, "Languages");
|
||||
|
||||
// get all existing languages
|
||||
var selectDtos = Sql()
|
||||
.Select<LanguageDto>()
|
||||
.From<LanguageDto>();
|
||||
|
||||
var dtos = Database.Fetch<LanguageDto>(selectDtos);
|
||||
|
||||
// get the id of the language which is already the default one, if any,
|
||||
// else get the lowest language id, which will become the default language
|
||||
var defaultId = int.MaxValue;
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
if (dto.IsDefault)
|
||||
{
|
||||
defaultId = dto.Id;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dto.Id < defaultId) defaultId = dto.Id;
|
||||
}
|
||||
|
||||
// update, so that language with that id is now default and mandatory
|
||||
var updateDefault = Sql()
|
||||
.Update<LanguageDto>(u => u
|
||||
.Set(x => x.IsDefault, true)
|
||||
.Set(x => x.IsMandatory, true))
|
||||
.Where<LanguageDto>(x => x.Id == defaultId);
|
||||
|
||||
Database.Execute(updateDefault);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -325,8 +325,6 @@ WHERE v1.propertyTypeId=v2.propertyTypeId AND v1.languageId=v2.languageId AND v1
|
||||
public const string Tag = "cmsTags";
|
||||
public const string TagRelationship = "cmsTagRelationship";
|
||||
|
||||
public const string Task = "cmsTask";
|
||||
public const string TaskType = "cmsTaskType";
|
||||
// ReSharper restore UnusedMember.Local
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
/// <summary>
|
||||
/// Used when nodes are unpublished
|
||||
/// </summary>
|
||||
UnPublish,
|
||||
Unpublish,
|
||||
/// <summary>
|
||||
/// Used when nodes are moved
|
||||
/// </summary>
|
||||
|
||||
@@ -269,7 +269,7 @@ namespace Umbraco.Core.Models
|
||||
if (_publishInfos == null)
|
||||
_publishInfos = new Dictionary<string, (string Name, DateTime Date)>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
_publishInfos[culture] = (name, date);
|
||||
_publishInfos[culture.ToLowerInvariant()] = (name, date);
|
||||
}
|
||||
|
||||
private void ClearPublishInfos()
|
||||
@@ -294,7 +294,7 @@ namespace Umbraco.Core.Models
|
||||
throw new ArgumentNullOrEmptyException(nameof(culture));
|
||||
if (_editedCultures == null)
|
||||
_editedCultures = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
_editedCultures.Add(culture);
|
||||
_editedCultures.Add(culture.ToLowerInvariant());
|
||||
}
|
||||
|
||||
// sets all publish edited
|
||||
|
||||
@@ -167,7 +167,7 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public DateTime? GetCultureDate(string culture)
|
||||
public DateTime? GetUpdateDate(string culture)
|
||||
{
|
||||
if (culture.IsNullOrWhiteSpace()) return null;
|
||||
if (!ContentTypeBase.VariesByCulture()) return null;
|
||||
@@ -202,6 +202,12 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
internal void TouchCulture(string culture)
|
||||
{
|
||||
if (ContentTypeBase.VariesByCulture() && _cultureInfos != null && _cultureInfos.TryGetValue(culture, out var infos))
|
||||
_cultureInfos[culture] = (infos.Name, DateTime.Now);
|
||||
}
|
||||
|
||||
protected void ClearCultureInfos()
|
||||
{
|
||||
_cultureInfos = null;
|
||||
@@ -280,26 +286,6 @@ namespace Umbraco.Core.Models
|
||||
Properties.Add(property);
|
||||
}
|
||||
|
||||
// HttpPostedFileBase is the base class that can be mocked
|
||||
// HttpPostedFile is what we get in ASP.NET
|
||||
// HttpPostedFileWrapper wraps sealed HttpPostedFile as HttpPostedFileBase
|
||||
|
||||
/// <summary>
|
||||
/// Sets the posted file value of a property.
|
||||
/// </summary>
|
||||
public virtual void SetValue(string propertyTypeAlias, HttpPostedFile value, string culture = null, string segment = null)
|
||||
{
|
||||
ContentExtensions.SetValue(this, propertyTypeAlias, new HttpPostedFileWrapper(value), culture, segment);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the posted file value of a property.
|
||||
/// </summary>
|
||||
public virtual void SetValue(string propertyTypeAlias, HttpPostedFileBase value, string culture = null, string segment = null)
|
||||
{
|
||||
ContentExtensions.SetValue(this, propertyTypeAlias, value, culture, segment);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Copy
|
||||
|
||||
72
src/Umbraco.Core/Models/ContentEditing/ContentApp.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Models.ContentEditing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a content app.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Content apps are editor extensions.</para>
|
||||
/// </remarks>
|
||||
[DataContract(Name = "app", Namespace = "")]
|
||||
public class ContentApp
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the content app.
|
||||
/// </summary>
|
||||
[DataMember(Name = "name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unique alias of the content app.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Must be a valid javascript identifier, ie no spaces etc.</para>
|
||||
/// </remarks>
|
||||
[DataMember(Name = "alias")]
|
||||
public string Alias { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the weight of the content app.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Content apps are ordered by weight, from left (lowest values) to right (highest values).</para>
|
||||
/// <para>Some built-in apps have special weights: listview is -666, content is -100 and infos is +100.</para>
|
||||
/// <para>The default weight is 0, meaning somewhere in-between content and infos, but weight could
|
||||
/// be used for ordering between user-level apps, or anything really.</para>
|
||||
/// </remarks>
|
||||
[DataMember(Name = "weight")]
|
||||
public int Weight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the icon of the content app.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Must be a valid helveticons class name (see http://hlvticons.ch/).</para>
|
||||
/// </remarks>
|
||||
[DataMember(Name = "icon")]
|
||||
public string Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the view for rendering the content app.
|
||||
/// </summary>
|
||||
[DataMember(Name = "view")]
|
||||
public string View { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The view model specific to this app
|
||||
/// </summary>
|
||||
[DataMember(Name = "viewModel")]
|
||||
public object ViewModel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the app is active.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Normally reserved for Angular to deal with but in some cases this can be set on the server side.</para>
|
||||
/// </remarks>
|
||||
[DataMember(Name = "active")]
|
||||
public bool Active { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace Umbraco.Core.Models.ContentEditing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a content app definition.
|
||||
/// </summary>
|
||||
public interface IContentAppDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the content app for an object.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <returns>The content app for the object, or null.</returns>
|
||||
/// <remarks>
|
||||
/// <para>The definition must determine, based on <paramref name="source"/>, whether
|
||||
/// the content app should be displayed or not, and return either a <see cref="ContentApp"/>
|
||||
/// instance, or null.</para>
|
||||
/// </remarks>
|
||||
ContentApp GetContentAppFor(object source);
|
||||
}
|
||||
}
|
||||
@@ -98,6 +98,30 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if AllowedTemplates contains templateId
|
||||
/// </summary>
|
||||
/// <param name="templateId">The template id to check</param>
|
||||
/// <returns>True if AllowedTemplates contains the templateId else False</returns>
|
||||
public bool IsAllowedTemplate(int templateId)
|
||||
{
|
||||
return AllowedTemplates == null
|
||||
? false
|
||||
: AllowedTemplates.Any(t => t.Id == templateId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if AllowedTemplates contains templateId
|
||||
/// </summary>
|
||||
/// <param name="templateAlias">The template alias to check</param>
|
||||
/// <returns>True if AllowedTemplates contains the templateAlias else False</returns>
|
||||
public bool IsAllowedTemplate(string templateAlias)
|
||||
{
|
||||
return AllowedTemplates == null
|
||||
? false
|
||||
: AllowedTemplates.Any(t => t.Alias.Equals(templateAlias, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the default template for the ContentType
|
||||
/// </summary>
|
||||
|
||||
@@ -30,6 +30,9 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
_editor = editor ?? throw new ArgumentNullException(nameof(editor));
|
||||
ParentId = parentId;
|
||||
|
||||
// set a default configuration
|
||||
Configuration = _editor.GetConfigurationEditor().DefaultConfigurationObject;
|
||||
}
|
||||
|
||||
private static PropertySelectors Selectors => _selectors ?? (_selectors = new PropertySelectors());
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models.Entities
|
||||
{
|
||||
@@ -8,13 +9,32 @@ namespace Umbraco.Core.Models.Entities
|
||||
public class DocumentEntitySlim : ContentEntitySlim, IDocumentEntitySlim
|
||||
{
|
||||
private static readonly IReadOnlyDictionary<string, string> Empty = new Dictionary<string, string>();
|
||||
|
||||
private IReadOnlyDictionary<string, string> _cultureNames;
|
||||
private IEnumerable<string> _publishedCultures;
|
||||
private IEnumerable<string> _editedCultures;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyDictionary<string, string> CultureNames
|
||||
{
|
||||
get => _cultureNames ?? Empty;
|
||||
set => _cultureNames = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<string> PublishedCultures
|
||||
{
|
||||
get => _publishedCultures ?? Enumerable.Empty<string>();
|
||||
set => _publishedCultures = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<string> EditedCultures
|
||||
{
|
||||
get => _editedCultures ?? Enumerable.Empty<string>();
|
||||
set => _editedCultures = value;
|
||||
}
|
||||
|
||||
public ContentVariation Variations { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -22,5 +42,6 @@ namespace Umbraco.Core.Models.Entities
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Edited { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,26 +7,35 @@ namespace Umbraco.Core.Models.Entities
|
||||
/// </summary>
|
||||
public interface IDocumentEntitySlim : IContentEntitySlim
|
||||
{
|
||||
//fixme we need to supply more information than this and change this property name. This will need to include Published/Editor per variation since we need this information for the tree
|
||||
/// <summary>
|
||||
/// Gets the variant name for each culture
|
||||
/// </summary>
|
||||
IReadOnlyDictionary<string, string> CultureNames { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the published cultures.
|
||||
/// </summary>
|
||||
IEnumerable<string> PublishedCultures { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the edited cultures.
|
||||
/// </summary>
|
||||
IEnumerable<string> EditedCultures { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content variation of the content type.
|
||||
/// </summary>
|
||||
ContentVariation Variations { get; }
|
||||
|
||||
/// <summary>
|
||||
/// At least one variation is published
|
||||
/// Gets a value indicating whether the content is published.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the document is invariant, this simply means there is a published version
|
||||
/// </remarks>
|
||||
bool Published { get; set; }
|
||||
bool Published { get; }
|
||||
|
||||
/// <summary>
|
||||
/// At least one variation has pending changes
|
||||
/// Gets a value indicating whether the content has been edited.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the document is invariant, this simply means there is pending changes
|
||||
/// </remarks>
|
||||
bool Edited { get; set; }
|
||||
bool Edited { get; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,10 +172,9 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
/// <returns>A value indicating whether the culture can be published.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Fails if values cannot be published, e.g. if some values are not valid.</para>
|
||||
/// <para>Fails if properties don't pass variant validtion rules.</para>
|
||||
/// <para>Publishing must be finalized via the content service SavePublishing method.</para>
|
||||
/// </remarks>
|
||||
// fixme - should return an attempt with error results
|
||||
bool PublishCulture(string culture = "*");
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -80,13 +80,13 @@ namespace Umbraco.Core.Models
|
||||
bool IsCultureAvailable(string culture);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the date a culture was created.
|
||||
/// Gets the date a culture was updated.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>When <paramref name="culture" /> is <c>null</c>, returns <c>null</c>.</para>
|
||||
/// <para>If the specified culture is not available, returns <c>null</c>.</para>
|
||||
/// </remarks>
|
||||
DateTime? GetCultureDate(string culture);
|
||||
DateTime? GetUpdateDate(string culture);
|
||||
|
||||
/// <summary>
|
||||
/// List of properties, which make up all the data available for this Content object
|
||||
@@ -139,7 +139,7 @@ namespace Umbraco.Core.Models
|
||||
// fixme validate published cultures?
|
||||
|
||||
/// <summary>
|
||||
/// Validates the content item's properties.
|
||||
/// Validates the content item's properties pass variant rules
|
||||
/// </summary>
|
||||
/// <para>If the content type is variant, then culture can be either '*' or an actual culture, but neither 'null' nor
|
||||
/// 'empty'. If the content type is invariant, then culture can be either '*' or null or empty.</para>
|
||||
|
||||
@@ -17,6 +17,20 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
IEnumerable<ITemplate> AllowedTemplates { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines if AllowedTemplates contains templateId
|
||||
/// </summary>
|
||||
/// <param name="templateId">The template id to check</param>
|
||||
/// <returns>True if AllowedTemplates contains the templateId else False</returns>
|
||||
bool IsAllowedTemplate(int templateId);
|
||||
|
||||
/// <summary>
|
||||
/// Determines if AllowedTemplates contains templateId
|
||||
/// </summary>
|
||||
/// <param name="templateAlias">The template alias to check</param>
|
||||
/// <returns>True if AllowedTemplates contains the templateAlias else False</returns>
|
||||
bool IsAllowedTemplate(string templateAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the default template for the ContentType
|
||||
/// </summary>
|
||||
|
||||
@@ -4,34 +4,54 @@ using Umbraco.Core.Models.Entities;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a language.
|
||||
/// </summary>
|
||||
public interface ILanguage : IEntity, IRememberBeingDirty
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the Iso Code for the Language
|
||||
/// Gets or sets the ISO code of the language.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
string IsoCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Culture Name for the Language
|
||||
/// Gets or sets the culture name of the language.
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
string CultureName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="CultureInfo"/> object for the current Language
|
||||
/// Gets the <see cref="CultureInfo"/> object for the language.
|
||||
/// </summary>
|
||||
[IgnoreDataMember]
|
||||
CultureInfo CultureInfo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines if this language is the default variant language when language variants are in use
|
||||
/// Gets or sets a value indicating whether the language is the default language.
|
||||
/// </summary>
|
||||
bool IsDefaultVariantLanguage { get; set; }
|
||||
[DataMember]
|
||||
bool IsDefault { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true, a variant node cannot be published unless this language variant is created
|
||||
/// Gets or sets a value indicating whether the language is mandatory.
|
||||
/// </summary>
|
||||
bool Mandatory { get; set; }
|
||||
/// <remarks>
|
||||
/// <para>When a language is mandatory, a multi-lingual document cannot be published
|
||||
/// without that language being published, and unpublishing that language unpublishes
|
||||
/// the entire document.</para>
|
||||
/// </remarks>
|
||||
[DataMember]
|
||||
bool IsMandatory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the identifier of a fallback language.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The fallback language can be used in multi-lingual scenarios, to help
|
||||
/// define fallback strategies when a value does not exist for a requested language.</para>
|
||||
/// </remarks>
|
||||
[DataMember]
|
||||
int? FallbackLanguageId { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,14 +93,6 @@ namespace Umbraco.Core.Models.Identity
|
||||
_roles.CollectionChanged += _roles_CollectionChanged;
|
||||
}
|
||||
|
||||
public virtual async Task<ClaimsIdentity> GenerateUserIdentityAsync(BackOfficeUserManager<BackOfficeIdentityUser> manager)
|
||||
{
|
||||
// NOTE the authenticationType must match the umbraco one
|
||||
// defined in CookieAuthenticationOptions.AuthenticationType
|
||||
var userIdentity = await manager.CreateIdentityAsync(this, Constants.Security.BackOfficeAuthenticationType);
|
||||
return userIdentity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if an Id has been set on this object this will be false if the object is new and not peristed to the database
|
||||
/// </summary>
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Umbraco.Core.Models
|
||||
private string _cultureName;
|
||||
private bool _isDefaultVariantLanguage;
|
||||
private bool _mandatory;
|
||||
private int? _fallbackLanguageId;
|
||||
|
||||
public Language(string isoCode)
|
||||
{
|
||||
@@ -30,13 +31,12 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
public readonly PropertyInfo IsoCodeSelector = ExpressionHelper.GetPropertyInfo<Language, string>(x => x.IsoCode);
|
||||
public readonly PropertyInfo CultureNameSelector = ExpressionHelper.GetPropertyInfo<Language, string>(x => x.CultureName);
|
||||
public readonly PropertyInfo IsDefaultVariantLanguageSelector = ExpressionHelper.GetPropertyInfo<Language, bool>(x => x.IsDefaultVariantLanguage);
|
||||
public readonly PropertyInfo MandatorySelector = ExpressionHelper.GetPropertyInfo<Language, bool>(x => x.Mandatory);
|
||||
public readonly PropertyInfo IsDefaultVariantLanguageSelector = ExpressionHelper.GetPropertyInfo<Language, bool>(x => x.IsDefault);
|
||||
public readonly PropertyInfo MandatorySelector = ExpressionHelper.GetPropertyInfo<Language, bool>(x => x.IsMandatory);
|
||||
public readonly PropertyInfo FallbackLanguageSelector = ExpressionHelper.GetPropertyInfo<Language, int?>(x => x.FallbackLanguageId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Iso Code for the Language
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
public string IsoCode
|
||||
{
|
||||
@@ -44,9 +44,7 @@ namespace Umbraco.Core.Models
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _isoCode, Ps.Value.IsoCodeSelector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Culture Name for the Language
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[DataMember]
|
||||
public string CultureName
|
||||
{
|
||||
@@ -54,22 +52,29 @@ namespace Umbraco.Core.Models
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _cultureName, Ps.Value.CultureNameSelector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="CultureInfo"/> object for the current Language
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
[IgnoreDataMember]
|
||||
public CultureInfo CultureInfo => CultureInfo.GetCultureInfo(IsoCode);
|
||||
|
||||
public bool IsDefaultVariantLanguage
|
||||
/// <inheritdoc />
|
||||
public bool IsDefault
|
||||
{
|
||||
get => _isDefaultVariantLanguage;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _isDefaultVariantLanguage, Ps.Value.IsDefaultVariantLanguageSelector);
|
||||
}
|
||||
|
||||
public bool Mandatory
|
||||
/// <inheritdoc />
|
||||
public bool IsMandatory
|
||||
{
|
||||
get => _mandatory;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _mandatory, Ps.Value.MandatorySelector);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? FallbackLanguageId
|
||||
{
|
||||
get => _fallbackLanguageId;
|
||||
set => SetPropertyValueAndDetectChanges(value, ref _fallbackLanguageId, Ps.Value.FallbackLanguageSelector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
get
|
||||
{
|
||||
if (LastLoginDate == default(DateTime) && IsApproved == false && InvitedDate != null)
|
||||
if (LastLoginDate == default && IsApproved == false && InvitedDate != null)
|
||||
return UserState.Invited;
|
||||
|
||||
if (IsLockedOut)
|
||||
@@ -268,6 +268,10 @@ namespace Umbraco.Core.Models.Membership
|
||||
if (IsApproved == false)
|
||||
return UserState.Disabled;
|
||||
|
||||
// User is not disabled or locked and has never logged in before
|
||||
if (LastLoginDate == default && IsApproved && IsLockedOut == false)
|
||||
return UserState.Inactive;
|
||||
|
||||
return UserState.Active;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
Active = 0,
|
||||
Disabled = 1,
|
||||
LockedOut = 2,
|
||||
Invited = 3
|
||||
Invited = 3,
|
||||
Inactive = 4
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A set of tag changes.
|
||||
/// </summary>
|
||||
internal class PropertyTagChange
|
||||
{
|
||||
public ChangeType Type { get; set; }
|
||||
|
||||
public IEnumerable<(string Type, string Tags)> Tags { get; set; }
|
||||
|
||||
public enum ChangeType
|
||||
{
|
||||
Replace,
|
||||
Remove,
|
||||
Merge
|
||||
}
|
||||
}
|
||||
}
|
||||
75
src/Umbraco.Core/Models/PublishedContent/Fallback.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages the built-in fallback policies.
|
||||
/// </summary>
|
||||
public struct Fallback : IEnumerable<int>
|
||||
{
|
||||
private readonly int[] _values;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Fallback"/> struct with values.
|
||||
/// </summary>
|
||||
private Fallback(int[] values)
|
||||
{
|
||||
_values = values;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an ordered set of fallback policies.
|
||||
/// </summary>
|
||||
/// <param name="values"></param>
|
||||
public static Fallback To(params int[] values) => new Fallback(values);
|
||||
|
||||
/// <summary>
|
||||
/// Do not fallback.
|
||||
/// </summary>
|
||||
public const int None = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Fallback to default value.
|
||||
/// </summary>
|
||||
public const int DefaultValue = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the fallback to default value policy.
|
||||
/// </summary>
|
||||
public static Fallback ToDefaultValue => new Fallback(new[] { DefaultValue });
|
||||
|
||||
/// <summary>
|
||||
/// Fallback to other languages.
|
||||
/// </summary>
|
||||
public const int Language = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the fallback to language policy.
|
||||
/// </summary>
|
||||
public static Fallback ToLanguage => new Fallback(new[] { Language });
|
||||
|
||||
/// <summary>
|
||||
/// Fallback to tree ancestors.
|
||||
/// </summary>
|
||||
public const int Ancestors = 3;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the fallback to tree ancestors policy.
|
||||
/// </summary>
|
||||
public static Fallback ToAncestors => new Fallback(new[] { Ancestors });
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerator<int> GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<int>)_values ?? Array.Empty<int>()).GetEnumerator();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +1,122 @@
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a fallback strategy for getting <see cref="IPublishedElement"/> values.
|
||||
/// </summary>
|
||||
// fixme - IPublishedValueFallback is still WorkInProgress
|
||||
// todo - properly document methods, etc
|
||||
// todo - understand caching vs fallback (recurse etc)
|
||||
public interface IPublishedValueFallback
|
||||
{
|
||||
// note that at property level, property.GetValue() does NOT implement fallback, and one has
|
||||
// to get property.Value() or property.Value<T>() to trigger fallback
|
||||
/// <summary>
|
||||
/// Tries to get a fallback value for a property.
|
||||
/// </summary>
|
||||
/// <param name="property">The property.</param>
|
||||
/// <param name="culture">The requested culture.</param>
|
||||
/// <param name="segment">The requested segment.</param>
|
||||
/// <param name="fallback">A fallback strategy.</param>
|
||||
/// <param name="defaultValue">An optional default value.</param>
|
||||
/// <param name="value">The fallback value.</param>
|
||||
/// <returns>A value indicating whether a fallback value could be provided.</returns>
|
||||
/// <remarks>
|
||||
/// <para>This method is called whenever property.Value(culture, segment, defaultValue) is called, and
|
||||
/// property.HasValue(culture, segment) is false.</para>
|
||||
/// <para>It can only fallback at property level (no recurse).</para>
|
||||
/// <para>At property level, property.GetValue() does *not* implement fallback, and one has to
|
||||
/// get property.Value() or property.Value{T}() to trigger fallback.</para>
|
||||
/// <para>Note that <paramref name="culture"/> and <paramref name="segment"/> may not be contextualized,
|
||||
/// so the variant context should be used to contextualize them (see our default implementation in
|
||||
/// the web project.</para>
|
||||
/// </remarks>
|
||||
bool TryGetValue(IPublishedProperty property, string culture, string segment, Fallback fallback, object defaultValue, out object value);
|
||||
|
||||
// this method is called whenever property.Value(culture, segment, defaultValue) is called, and
|
||||
// property.HasValue(culture, segment) is false. it can only fallback at property level (no recurse).
|
||||
/// <summary>
|
||||
/// Tries to get a fallback value for a property.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the value.</typeparam>
|
||||
/// <param name="property">The property.</param>
|
||||
/// <param name="culture">The requested culture.</param>
|
||||
/// <param name="segment">The requested segment.</param>
|
||||
/// <param name="fallback">A fallback strategy.</param>
|
||||
/// <param name="defaultValue">An optional default value.</param>
|
||||
/// <param name="value">The fallback value.</param>
|
||||
/// <returns>A value indicating whether a fallback value could be provided.</returns>
|
||||
/// <remarks>
|
||||
/// <para>This method is called whenever property.Value{T}(culture, segment, defaultValue) is called, and
|
||||
/// property.HasValue(culture, segment) is false.</para>
|
||||
/// <para>It can only fallback at property level (no recurse).</para>
|
||||
/// <para>At property level, property.GetValue() does *not* implement fallback, and one has to
|
||||
/// get property.Value() or property.Value{T}() to trigger fallback.</para>
|
||||
/// </remarks>
|
||||
bool TryGetValue<T>(IPublishedProperty property, string culture, string segment, Fallback fallback, T defaultValue, out T value);
|
||||
|
||||
object GetValue(IPublishedProperty property, string culture, string segment, object defaultValue);
|
||||
/// <summary>
|
||||
/// Tries to get a fallback value for a published element property.
|
||||
/// </summary>
|
||||
/// <param name="content">The published element.</param>
|
||||
/// <param name="alias">The property alias.</param>
|
||||
/// <param name="culture">The requested culture.</param>
|
||||
/// <param name="segment">The requested segment.</param>
|
||||
/// <param name="fallback">A fallback strategy.</param>
|
||||
/// <param name="defaultValue">An optional default value.</param>
|
||||
/// <param name="value">The fallback value.</param>
|
||||
/// <returns>A value indicating whether a fallback value could be provided.</returns>
|
||||
/// <remarks>
|
||||
/// <para>This method is called whenever getting the property value for the specified alias, culture and
|
||||
/// segment, either returned no property at all, or a property with HasValue(culture, segment) being false.</para>
|
||||
/// <para>It can only fallback at element level (no recurse).</para>
|
||||
/// </remarks>
|
||||
bool TryGetValue(IPublishedElement content, string alias, string culture, string segment, Fallback fallback, object defaultValue, out object value);
|
||||
|
||||
// this method is called whenever property.Value<T>(culture, segment, defaultValue) is called, and
|
||||
// property.HasValue(culture, segment) is false. it can only fallback at property level (no recurse).
|
||||
/// <summary>
|
||||
/// Tries to get a fallback value for a published element property.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the value.</typeparam>
|
||||
/// <param name="content">The published element.</param>
|
||||
/// <param name="alias">The property alias.</param>
|
||||
/// <param name="culture">The requested culture.</param>
|
||||
/// <param name="segment">The requested segment.</param>
|
||||
/// <param name="fallback">A fallback strategy.</param>
|
||||
/// <param name="defaultValue">An optional default value.</param>
|
||||
/// <param name="value">The fallback value.</param>
|
||||
/// <returns>A value indicating whether a fallback value could be provided.</returns>
|
||||
/// <remarks>
|
||||
/// <para>This method is called whenever getting the property value for the specified alias, culture and
|
||||
/// segment, either returned no property at all, or a property with HasValue(culture, segment) being false.</para>
|
||||
/// <para>It can only fallback at element level (no recurse).</para>
|
||||
/// </remarks>
|
||||
bool TryGetValue<T>(IPublishedElement content, string alias, string culture, string segment, Fallback fallback, T defaultValue, out T value);
|
||||
|
||||
T GetValue<T>(IPublishedProperty property, string culture, string segment, T defaultValue);
|
||||
/// <summary>
|
||||
/// Tries to get a fallback value for a published content property.
|
||||
/// </summary>
|
||||
/// <param name="content">The published element.</param>
|
||||
/// <param name="alias">The property alias.</param>
|
||||
/// <param name="culture">The requested culture.</param>
|
||||
/// <param name="segment">The requested segment.</param>
|
||||
/// <param name="fallback">A fallback strategy.</param>
|
||||
/// <param name="defaultValue">An optional default value.</param>
|
||||
/// <param name="value">The fallback value.</param>
|
||||
/// <returns>A value indicating whether a fallback value could be provided.</returns>
|
||||
/// <remarks>
|
||||
/// <para>This method is called whenever getting the property value for the specified alias, culture and
|
||||
/// segment, either returned no property at all, or a property with HasValue(culture, segment) being false.</para>
|
||||
/// </remarks>
|
||||
bool TryGetValue(IPublishedContent content, string alias, string culture, string segment, Fallback fallback, object defaultValue, out object value);
|
||||
|
||||
// these methods to be called whenever getting the property value for the specified alias, culture and segment,
|
||||
// either returned no property at all, or a property that does not HasValue for the specified culture and segment.
|
||||
|
||||
object GetValue(IPublishedElement content, string alias, string culture, string segment, object defaultValue);
|
||||
|
||||
T GetValue<T>(IPublishedElement content, string alias, string culture, string segment, T defaultValue);
|
||||
|
||||
object GetValue(IPublishedContent content, string alias, string culture, string segment, object defaultValue, bool recurse);
|
||||
|
||||
T GetValue<T>(IPublishedContent content, string alias, string culture, string segment, T defaultValue, bool recurse);
|
||||
/// <summary>
|
||||
/// Tries to get a fallback value for a published content property.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the value.</typeparam>
|
||||
/// <param name="content">The published element.</param>
|
||||
/// <param name="alias">The property alias.</param>
|
||||
/// <param name="culture">The requested culture.</param>
|
||||
/// <param name="segment">The requested segment.</param>
|
||||
/// <param name="fallback">A fallback strategy.</param>
|
||||
/// <param name="defaultValue">An optional default value.</param>
|
||||
/// <param name="value">The fallback value.</param>
|
||||
/// <returns>A value indicating whether a fallback value could be provided.</returns>
|
||||
/// <remarks>
|
||||
/// <para>This method is called whenever getting the property value for the specified alias, culture and
|
||||
/// segment, either returned no property at all, or a property with HasValue(culture, segment) being false.</para>
|
||||
/// </remarks>
|
||||
bool TryGetValue<T>(IPublishedContent content, string alias, string culture, string segment, Fallback fallback, T defaultValue, out T value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,17 +49,24 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// <param name="modelTypes">The model types map.</param>
|
||||
/// <returns>The actual Clr type.</returns>
|
||||
public static Type Map(Type type, Dictionary<string, Type> modelTypes)
|
||||
=> Map(type, modelTypes, false);
|
||||
|
||||
public static Type Map(Type type, Dictionary<string, Type> modelTypes, bool dictionaryIsInvariant)
|
||||
{
|
||||
// it may be that senders forgot to send an invariant dictionary (garbage-in)
|
||||
if (!dictionaryIsInvariant)
|
||||
modelTypes = new Dictionary<string, Type>(modelTypes, StringComparer.InvariantCultureIgnoreCase);
|
||||
|
||||
if (type is ModelType modelType)
|
||||
{
|
||||
if (modelTypes.TryGetValue(modelType.ContentTypeAlias, out Type actualType))
|
||||
if (modelTypes.TryGetValue(modelType.ContentTypeAlias, out var actualType))
|
||||
return actualType;
|
||||
throw new InvalidOperationException($"Don't know how to map ModelType with content type alias \"{modelType.ContentTypeAlias}\".");
|
||||
}
|
||||
|
||||
if (type is ModelTypeArrayType arrayType)
|
||||
{
|
||||
if (modelTypes.TryGetValue(arrayType.ContentTypeAlias, out Type actualType))
|
||||
if (modelTypes.TryGetValue(arrayType.ContentTypeAlias, out var actualType))
|
||||
return actualType.MakeArrayType();
|
||||
throw new InvalidOperationException($"Don't know how to map ModelType with content type alias \"{arrayType.ContentTypeAlias}\".");
|
||||
}
|
||||
@@ -70,7 +77,7 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
if (def == null)
|
||||
throw new InvalidOperationException("panic");
|
||||
|
||||
var args = type.GetGenericArguments().Select(x => Map(x, modelTypes)).ToArray();
|
||||
var args = type.GetGenericArguments().Select(x => Map(x, modelTypes, true)).ToArray();
|
||||
return def.MakeGenericType(args);
|
||||
}
|
||||
|
||||
@@ -81,7 +88,14 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
/// <param name="map">The model types map.</param>
|
||||
/// <returns>The actual Clr type name.</returns>
|
||||
public static string MapToName(Type type, Dictionary<string, string> map)
|
||||
=> MapToName(type, map, false);
|
||||
|
||||
private static string MapToName(Type type, Dictionary<string, string> map, bool dictionaryIsInvariant)
|
||||
{
|
||||
// it may be that senders forgot to send an invariant dictionary (garbage-in)
|
||||
if (!dictionaryIsInvariant)
|
||||
map = new Dictionary<string, string>(map, StringComparer.InvariantCultureIgnoreCase);
|
||||
|
||||
if (type is ModelType modelType)
|
||||
{
|
||||
if (map.TryGetValue(modelType.ContentTypeAlias, out var actualTypeName))
|
||||
@@ -102,7 +116,7 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
if (def == null)
|
||||
throw new InvalidOperationException("panic");
|
||||
|
||||
var args = type.GetGenericArguments().Select(x => MapToName(x, map)).ToArray();
|
||||
var args = type.GetGenericArguments().Select(x => MapToName(x, map, true)).ToArray();
|
||||
var defFullName = def.FullName.Substring(0, def.FullName.IndexOf('`'));
|
||||
return defFullName + "<" + string.Join(", ", args) + ">";
|
||||
}
|
||||
|
||||
@@ -9,21 +9,45 @@
|
||||
public class NoopPublishedValueFallback : IPublishedValueFallback
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public object GetValue(IPublishedProperty property, string culture, string segment, object defaultValue) => defaultValue;
|
||||
public bool TryGetValue(IPublishedProperty property, string culture, string segment, Fallback fallback, object defaultValue, out object value)
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public T GetValue<T>(IPublishedProperty property, string culture, string segment, T defaultValue) => defaultValue;
|
||||
public bool TryGetValue<T>(IPublishedProperty property, string culture, string segment, Fallback fallback, T defaultValue, out T value)
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public object GetValue(IPublishedElement content, string alias, string culture, string segment, object defaultValue) => defaultValue;
|
||||
public bool TryGetValue(IPublishedElement content, string alias, string culture, string segment, Fallback fallback, object defaultValue, out object value)
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public T GetValue<T>(IPublishedElement content, string alias, string culture, string segment, T defaultValue) => defaultValue;
|
||||
public bool TryGetValue<T>(IPublishedElement content, string alias, string culture, string segment, Fallback fallback, T defaultValue, out T value)
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public object GetValue(IPublishedContent content, string alias, string culture, string segment, object defaultValue, bool recurse) => defaultValue;
|
||||
public bool TryGetValue(IPublishedContent content, string alias, string culture, string segment, Fallback fallback, object defaultValue, out object value)
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public T GetValue<T>(IPublishedContent content, string alias, string culture, string segment, T defaultValue, bool recurse) => defaultValue;
|
||||
public bool TryGetValue<T>(IPublishedContent content, string alias, string culture, string segment, Fallback fallback, T defaultValue, out T value)
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||