Merge remote-tracking branch 'fork/temp8-u4-11427-remove-propertyinjection' into castle-compatibility-cleanup

# Conflicts:
#	src/Umbraco.Tests/Models/MediaXmlTest.cs
This commit is contained in:
Lars-Erik Aabech
2018-10-15 23:56:07 +02:00
804 changed files with 24459 additions and 21583 deletions

View File

@@ -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

View File

View File

View File

@@ -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.
![Gulp build in Visual Studio](img/gulpbuild.png)

66
.github/ISSUE_TEMPLATE/1_Bug.md vendored Normal file
View 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.
-->

View 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.
-->

View 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!

View 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!

View 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
View 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! -->

View File

@@ -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).

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -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>

View 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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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

View File

@@ -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 }

View File

@@ -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! -->

View File

@@ -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")]

View File

@@ -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);

View File

@@ -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

View File

@@ -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)]

View File

@@ -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

View File

@@ -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>();

View File

@@ -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>();

View File

@@ -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
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -66,5 +66,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
bool EnableInheritedMediaTypes { get; }
string LoginBackgroundImage { get; }
bool StripUdiAttributes { get; }
}
}

View File

@@ -8,6 +8,8 @@
bool DisableAlternativeTemplates { get; }
bool ValidateAlternativeTemplates { get; }
bool DisableFindContentByIdPath { get; }
bool DisableRedirectUrlTracking { get; }
@@ -16,5 +18,4 @@
string UmbracoApplicationUrl { get; }
}
}

View File

@@ -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"];
}
}

View File

@@ -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.

View File

@@ -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.

View File

@@ -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>

View File

@@ -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
}

View File

@@ -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";
}

View File

@@ -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>

View File

@@ -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

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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
}
}

View File

@@ -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");

View File

@@ -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:

View 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;
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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'

View File

@@ -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;
}

View 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();
}
}

View 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
};
}
}
}
}
}

View File

@@ -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++)

View File

@@ -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>();
}
}

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -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),

View File

@@ -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

View File

@@ -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);");
}

View File

@@ -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");
}
}
}

View File

@@ -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");
}
}
}

View File

@@ -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
}
}

View File

@@ -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);
}
}
}

View File

@@ -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
}
}

View File

@@ -32,7 +32,7 @@
/// <summary>
/// Used when nodes are unpublished
/// </summary>
UnPublish,
Unpublish,
/// <summary>
/// Used when nodes are moved
/// </summary>

View File

@@ -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

View File

@@ -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

View 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; }
}
}

View File

@@ -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);
}
}

View File

@@ -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>

View File

@@ -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());

View File

@@ -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; }
}
}

View File

@@ -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; }
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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; }
}
}

View File

@@ -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>

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -9,6 +9,7 @@
Active = 0,
Disabled = 1,
LockedOut = 2,
Invited = 3
Invited = 3,
Inactive = 4
}
}

View File

@@ -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
}
}
}

View 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();
}
}
}

View File

@@ -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);
}
}

View File

@@ -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) + ">";
}

View File

@@ -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;
}
}
}

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