Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 209c50c585 | |||
| d726f5ffe9 | |||
| cecc1e4b52 |
+3
-7
@@ -25,7 +25,6 @@ dotnet_naming_rule.private_members_with_underscore.severity = suggestion
|
||||
|
||||
dotnet_naming_symbols.private_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
|
||||
# dotnet_naming_symbols.private_fields.required_modifiers = abstract,async,readonly,static # all except const
|
||||
|
||||
dotnet_naming_style.prefix_underscore.capitalization = camel_case
|
||||
dotnet_naming_style.prefix_underscore.required_prefix = _
|
||||
@@ -35,10 +34,7 @@ dotnet_naming_style.prefix_underscore.required_prefix = _
|
||||
csharp_style_var_for_built_in_types = true:suggestion
|
||||
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||
csharp_style_var_elsewhere = true:suggestion
|
||||
csharp_prefer_braces = false : none
|
||||
csharp_prefer_braces = false : none
|
||||
|
||||
[*.js]
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.less]
|
||||
trim_trailing_whitespace = false
|
||||
[*.{js,less}]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
+6
-10
@@ -13,7 +13,7 @@
|
||||
*.png binary
|
||||
*.gif binary
|
||||
|
||||
*.cs text=auto diff=csharp
|
||||
*.cs text=auto diff=csharp
|
||||
*.vb text=auto
|
||||
*.c text=auto
|
||||
*.cpp text=auto
|
||||
@@ -41,13 +41,9 @@
|
||||
*.fs text=auto
|
||||
*.fsx text=auto
|
||||
*.hs text=auto
|
||||
*.json text=auto
|
||||
*.xml text=auto
|
||||
|
||||
*.csproj text=auto merge=union
|
||||
*.vbproj text=auto merge=union
|
||||
*.fsproj text=auto merge=union
|
||||
*.dbproj text=auto merge=union
|
||||
*.sln text=auto eol=crlf merge=union
|
||||
|
||||
*.gitattributes text=auto
|
||||
*.csproj text=auto merge=union
|
||||
*.vbproj text=auto merge=union
|
||||
*.fsproj text=auto merge=union
|
||||
*.dbproj text=auto merge=union
|
||||
*.sln text=auto eol=crlf merge=union
|
||||
|
||||
+3
-7
@@ -1,4 +1,4 @@
|
||||
# Umbraco CMS Build
|
||||
# Umbraco Cms Build
|
||||
|
||||
## Are you sure?
|
||||
|
||||
@@ -39,12 +39,8 @@ To build Umbraco, fire up PowerShell and move to Umbraco's repository root (the
|
||||
|
||||
build/build.ps1
|
||||
|
||||
If you only see a build.bat-file, you're probably on the wrong branch. If you switch to the correct branch (dev-v8) the file will appear and you can build it.
|
||||
|
||||
You might run into [Powershell quirks](#powershell-quirks).
|
||||
|
||||
If it runs without errors; Hooray! Now you can continue with [the next step](CONTRIBUTING.md#how-do-i-begin) and open the solution and build it.
|
||||
|
||||
### Build Infrastructure
|
||||
|
||||
The Umbraco Build infrastructure relies on a PowerShell object. The object can be retrieved with:
|
||||
@@ -70,7 +66,7 @@ The Visual Studio object is `null` when Visual Studio has not been detected (eg
|
||||
* `Path`: Visual Studio installation path (eg some place under `Program Files`)
|
||||
* `Major`: Visual Studio major version (eg `15` for VS 2017)
|
||||
* `Minor`: Visual Studio minor version
|
||||
* `MsBuild`: the absolute path to the MsBuild executable
|
||||
* `MsBUild`: the absolute path to the MsBuild executable
|
||||
|
||||
#### GetUmbracoVersion
|
||||
|
||||
@@ -213,4 +209,4 @@ The best solution is to unblock the Zip file before un-zipping: right-click the
|
||||
|
||||
### Git Quirks
|
||||
|
||||
Git might have issues dealing with long file paths during build. You may want/need to enable `core.longpaths` support (see [this page](https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path) for details).
|
||||
Git might have issues dealing with long file paths during build. You may want/need to enable `core.longpaths` support (see [this page](https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path) for details).
|
||||
@@ -29,4 +29,4 @@ Don't rest on your laurels and never accept the status quo. Contribute and give
|
||||
|
||||
## Friendly
|
||||
|
||||
Don’t judge upon mistakes made but rather upon the speed and quality with which mistakes are corrected. Friendly posts and contributions generate smiles and build long lasting relationships.
|
||||
Don’t judge upon mistakes made but rather upon the speed and quality with which mistakes are corrected. Friendly posts and contributions generate smiles and builds long lasting relationships.
|
||||
+40
-51
@@ -2,15 +2,15 @@
|
||||
|
||||
👍🎉 First off, thanks for taking the time to contribute! 🎉👍
|
||||
|
||||
The following is a set of guidelines, for contributing to Umbraco CMS.
|
||||
The following is a set of guidelines for contributing to Umbraco CMS.
|
||||
|
||||
These are mostly guidelines, not rules. Use your best judgement, and feel free to propose changes to this document in a pull request.
|
||||
These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
|
||||
|
||||
Remember, we're a friendly bunch and are happy with whatever contribution you might provide. Below are guidelines for success that we've gathered over the years. If you choose to ignore them then we still love you 💖.
|
||||
|
||||
**Code of conduct**
|
||||
|
||||
This project and everyone participating in it, is governed by the [our Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [Sebastiaan Janssen - sj@umbraco.dk](mailto:sj@umbraco.dk).
|
||||
This project and everyone participating in it is governed by the [our Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [Sebastiaan Janssen - sj@umbraco.dk](mailto:sj@umbraco.dk).
|
||||
|
||||
**Table of contents**
|
||||
|
||||
@@ -22,13 +22,13 @@ This project and everyone participating in it, is governed by the [our Code of C
|
||||
|
||||
[Reviews](#reviews)
|
||||
* [Styleguides](#styleguides)
|
||||
* [The Core Contributors](#the-core-contributors-team)
|
||||
* [The PR team](#the-pr-team)
|
||||
* [Questions?](#questions)
|
||||
|
||||
[Working with the code](#working-with-the-code)
|
||||
* [Building Umbraco from source code](#building-umbraco-from-source-code)
|
||||
* [Working with the source code](#working-with-the-source-code)
|
||||
* [Making changes after the PR is open](#making-changes-after-the-pr-is-open)
|
||||
* [Making changes after the PR was opened](#making-changes-after-the-pr-was-opened)
|
||||
* [Which branch should I target for my contributions?](#which-branch-should-i-target-for-my-contributions)
|
||||
* [Keeping your Umbraco fork in sync with the main repository](#keeping-your-umbraco-fork-in-sync-with-the-main-repository)
|
||||
|
||||
@@ -38,11 +38,11 @@ This document gives you a quick overview on how to get started.
|
||||
|
||||
### Guidelines for contributions we welcome
|
||||
|
||||
Not all changes are wanted, so on occasion we might close a PR without merging it. We will give you feedback why we can't accept your changes and we'll be nice about it, thanking you for spending your valuable time.
|
||||
Not all changes are wanted, so on occassion we might close a PR without merging it. We will give you feedback why we can't accept your changes and we'll be nice about it, thanking you for spending your valuable time.
|
||||
|
||||
We have [documented what we consider small and large changes](CONTRIBUTION_GUIDELINES.md). Make sure to talk to us before making large changes, so we can ensure that you don't put all your hard work into something we would not be able to merge.
|
||||
We have [documented what we consider small and large changes](CONTRIBUTION_GUIDELINES.md). Make sure to talk to us before making large changes.
|
||||
|
||||
Remember, it is always worth working on an issue from the `Up for grabs` list or even asking for some feedback before you send us a PR. This way, your PR will not be closed as unwanted.
|
||||
Remember, if an issue is in the `Up for grabs` list or you've asked for some feedback before you sent us a PR, your PR will not be closed as unwanted.
|
||||
|
||||
### What can I start with?
|
||||
|
||||
@@ -59,38 +59,37 @@ Great question! The short version goes like this:
|
||||
* **Clone** - when GitHub has created your fork, you can clone it in your favorite Git tool
|
||||
|
||||

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

|
||||
|
||||
### Pull requests
|
||||
The most successful pull requests usually look a like this:
|
||||
|
||||
* Fill in the required template (shown when starting a PR on GitHub), and link your pull request to an issue on the [issue tracker,](https://github.com/umbraco/Umbraco-CMS/issues) if applicable.
|
||||
* Fill in the required template
|
||||
* Include screenshots and animated GIFs in your pull request whenever possible.
|
||||
* Unit tests, while optional, are awesome. Thank you!
|
||||
* New code is commented with documentation from which [the reference documentation](https://our.umbraco.com/documentation/Reference/) is generated.
|
||||
* Unit tests, while optional are awesome, thank you!
|
||||
* New code is commented with documentation from which [the reference documentation](https://our.umbraco.com/documentation/Reference/) is generated
|
||||
|
||||
Again, these are guidelines, not strict requirements. However, the more information that you give to us, the more we have to work with when considering your contributions. Good documentation of a pull request can really speed up the time it takes to review and merge your work!
|
||||
Again, these are guidelines, not strict requirements.
|
||||
|
||||
## Reviews
|
||||
|
||||
You've sent us your first contribution - congratulations! Now what?
|
||||
You've sent us your first contribution, congratulations! Now what?
|
||||
|
||||
The [pull request team](#the-pr-team) can now start reviewing your proposed changes and give you feedback on them. If it's not perfect, we'll either fix up what we need or we can request that you make some additional changes.
|
||||
The [pull request team](#the-pr-team) can now start reviewing your proposed changes and give you feedback on them. If it's not perfect, we'll either fix up what we need or we can request you to make some additional changes.
|
||||
|
||||
We have [a process in place which you can read all about](REVIEW_PROCESS.md). The very abbreviated version is:
|
||||
|
||||
- Your PR will get a reply within 48 hours
|
||||
- An in-depth reply will be added within at most 2 weeks
|
||||
- The PR will be either merged or rejected within at most 4 weeks
|
||||
- Sometimes it is difficult to meet these timelines and we'll talk to you if this is the case.
|
||||
- Sometimes it is difficult to meet these timelines and we'll talk to you
|
||||
|
||||
### Styleguides
|
||||
|
||||
@@ -98,24 +97,23 @@ To be honest, we don't like rules very much. We trust you have the best of inten
|
||||
|
||||
That said, the Umbraco development team likes to follow the hints that ReSharper gives us (no problem if you don't have this installed) and we've added a `.editorconfig` file so that Visual Studio knows what to do with whitespace, line endings, etc.
|
||||
|
||||
### The Core Contributors team
|
||||
### The PR team
|
||||
|
||||
The Core Contributors team consists of one member of Umbraco HQ, [Sebastiaan](https://github.com/nul800sebastiaan), who gets assistance from the following community members who have comitted to volunteering their free time:
|
||||
The pull request team consists of a member of Umbraco HQ, [Sebastiaan](https://github.com/nul800sebastiaan), who gets assistance from the following community members
|
||||
|
||||
- [Anders Bjerner](https://github.com/abjerner)
|
||||
- [Dave Woestenborghs](https://github.com/dawoe)
|
||||
- [Emma Burstow](https://github.com/emmaburstow)
|
||||
- [Poornima Nayar](https://github.com/poornimanayar)
|
||||
- [Kenn Jacobsen](https://twitter.com/KennJacobsen_DK)
|
||||
|
||||
|
||||
These wonderful people aim to provide you with a first reply to your PR, review and test out your changes and on occasions, they might ask more questions. If they are happy with your work, they'll let Umbraco HQ know by approving the PR. Hq will have final sign-off and will check the work again before it is merged.
|
||||
These wonderful volunteers will provide you with a first reply to your PR, review and test out your changes and might ask more questions. After that they'll let Umbraco HQ know if everything seems okay.
|
||||
|
||||
### Questions?
|
||||
|
||||
You can get in touch with [the core contributors team](#the-core-contributors-team) in multiple ways; we love open conversations and we are a friendly bunch. No question you have is stupid. Any question you have usually helps out multiple people with the same question. Ask away:
|
||||
You can get in touch with [the PR team](#the-pr-team) in multiple ways, we love open conversations and we are a friendly bunch. No question you have is stupid. Any questions you have usually helps out multiple people with the same question. Ask away:
|
||||
|
||||
- If there's an existing issue on the issue tracker then that's a good place to leave questions and discuss how to start or move forward.
|
||||
- Unsure where to start? Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.com/forum/contributing-to-umbraco-cms/) forum. The team monitors that one closely, so one of us will be on hand and ready to point you in the right direction.
|
||||
- If there's an existing issue on the issue tracker then that's a good place to leave questions and discuss how to start or move forward
|
||||
- Unsure where to start? Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.com/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely
|
||||
|
||||
## Working with the code
|
||||
|
||||
@@ -123,24 +121,23 @@ You can get in touch with [the core contributors team](#the-core-contributors-te
|
||||
|
||||
In order to build the Umbraco source code locally, first make sure you have the following installed.
|
||||
|
||||
* [Visual Studio 2017 v15.9.7+](https://visualstudio.microsoft.com/vs/)
|
||||
* [Node.js v10+](https://nodejs.org/en/download/)
|
||||
* npm v6.4.1+ (installed with Node.js)
|
||||
* [Git command line](https://git-scm.com/download/)
|
||||
* Visual Studio 2017 v15.9.7+
|
||||
* Node v10+
|
||||
* npm v6.4.1+
|
||||
|
||||
The easiest way to get started is to open `src\umbraco.sln` in Visual Studio 2017 (version 15.9.7 or higher, [the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
|
||||
The easiest way to get started is to run `build.ps1` 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 run `build.ps1` from the Powershell command line, 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 (version 15.9.7 or higher, [the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
|
||||
|
||||

|
||||
|
||||
After this build completes, you should be able to hit `F5` in Visual Studio to build and run the project. A IISExpress webserver will start and the Umbraco installer will pop up in your browser. Follow the directions there to get a working Umbraco install up and running.
|
||||
After this build completes, you should be able to hit `F5` in Visual Studio to build and run the project. A IISExpress webserver will start and the Umbraco installer will pop up in your browser, follow the directions there to get a working Umbraco install up and running.
|
||||
|
||||
### Working with the source code
|
||||
|
||||
Some parts of our source code are over 10 years old now. And when we say "old", we mean "mature" of course!
|
||||
|
||||
There are two big areas that you should know about:
|
||||
There's two big areas that you should know about:
|
||||
|
||||
1. The Umbraco backoffice is a extensible AngularJS app and requires you to run a `gulp dev` command while you're working with it, so changes are copied over to the appropriate directories and you can refresh your browser to view the results of your changes.
|
||||
You may need to run the following commands to set up gulp properly:
|
||||
@@ -149,34 +146,30 @@ There are two big areas that you should know about:
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
The caching for the back office has been described as 'aggressive' so we often find it's best when making back office changes to disable caching in the browser to help you to see the changes you're making.
|
||||
|
||||
2. "The rest" is a C# based codebase, which is mostly ASP.NET MVC based. You can make changes, build them in Visual Studio, and hit `F5` to see the result.
|
||||
|
||||
To find the general areas for something you're looking to fix or improve, have a look at the following two parts of the API documentation.
|
||||
To find the general areas of something you're looking to fix or improve, have a look at the following two parts of the API documentation.
|
||||
|
||||
* [The AngularJS based backoffice files](https://our.umbraco.com/apidocs/ui/#/api) (to be found in `src\Umbraco.Web.UI.Client\src`)
|
||||
* [The C# application](https://our.umbraco.com/apidocs/csharp/)
|
||||
|
||||
### Which branch should I target for my contributions?
|
||||
|
||||
We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-flow/), but don't worry if you are not familiar with it. The most important thing you need to know is that when you fork the Umbraco repository, the default branch is set to something, usually `v8/contrib`. If you are working on v8, this is the branch you should be targetting. For v7 contributions, please target 'v7/dev'.
|
||||
|
||||
Please note: we are no longer accepting features for v7 but will continue to merge bug fixes as and when they arise.
|
||||
We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-flow/), don't worry if you are not familiar with it. The most important thing you need to know is that when you fork the Umbraco repository, the default branch is set to something, usually `v8/dev`. Whatever the default is, that's where we'd like you to target your contributions.
|
||||
|
||||

|
||||
|
||||
### Making changes after the PR is open
|
||||
### Making changes after the PR was opened
|
||||
|
||||
If you make the corrections we ask for in the same branch and push them to your fork again, the pull request automatically updates with the additional commit(s) so we can review it again. If all is well, we'll merge the code and your commits are forever part of Umbraco!
|
||||
|
||||
### Keeping your Umbraco fork in sync with the main repository
|
||||
|
||||
We recommend you to sync with our repository before you submit your pull request. That way, you can fix any potential merge conflicts and make our lives a little bit easier.
|
||||
We recommend you sync with our repository before you submit your pull request. That way, you can fix any potential merge conflicts and make our lives a little bit easier.
|
||||
|
||||
Also, if you have submitted a pull request three weeks ago and want to work on something new, you'll want to get the latest code to build against of course.
|
||||
Also, if you've submitted a pull request three weeks ago and want to work on something new, you'll want to get the latest code to build against of course.
|
||||
|
||||
To sync your fork with this original one, you'll have to add the upstream url. You only have to do this once:
|
||||
To sync your fork with this original one, you'll have to add the upstream url, you only have to do this once:
|
||||
|
||||
```
|
||||
git remote add upstream https://github.com/umbraco/Umbraco-CMS.git
|
||||
@@ -186,13 +179,9 @@ Then when you want to get the changes from the main repository:
|
||||
|
||||
```
|
||||
git fetch upstream
|
||||
git rebase upstream/v8/contrib
|
||||
git rebase upstream/v8/dev
|
||||
```
|
||||
|
||||
In this command we're syncing with the `v8/contrib` branch, but you can of course choose another one if needed.
|
||||
In this command we're syncing with the `v8/dev` branch, but you can of course choose another one if needed.
|
||||
|
||||
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
|
||||
|
||||
### And finally
|
||||
|
||||
We welcome all kinds of contributions to this repository. If you don't feel you'd like to make code changes here, you can visit our [documentation repository](https://github.com/umbraco/UmbracoDocs) and use your experience to contribute to making the docs we have, even better. We also encourage community members to feel free to comment on others' pull requests and issues - the expertise we have is not limited to the Core Contributors and HQ. So, if you see something on the issue tracker or pull requests you feel you can add to, please don't be shy.
|
||||
|
||||
@@ -13,7 +13,7 @@ We’re usually able to handle small PRs pretty quickly. A community volunteer w
|
||||
|
||||
Umbraco HQ will regularly mark newly created issues on the issue tracker with the `Up for grabs` tag. This means that the proposed changes are wanted in Umbraco but the HQ does not have the time to make them at this time. We encourage anyone to pick them up and help out.
|
||||
|
||||
If you do start working on something, make sure to leave a small comment on the issue saying something like: "I'm working on this". That way other people stumbling upon the issue know they don't need to pick it up, someone already has.
|
||||
If you do start working on something, make sure leave a small comment on the issue saying something like: "I'm working on this". That way other people stumbling upon the issue know they don't need to pick it up, someone already has.
|
||||
|
||||
## Large PRs
|
||||
New features and large refactorings - can be recognized by seeing a large number of changes, plenty of new files, updates to package manager files (NuGet’s packages.config, NPM’s packages.json, etc.).
|
||||
@@ -30,6 +30,6 @@ It is highly recommended that you speak to the HQ before making large, complex c
|
||||
|
||||
### Pull request or package?
|
||||
|
||||
If it doesn’t fit in CMS right now, we will likely encourage you to make it into a package instead. A package is a great way to check out popularity of a feature, learn how people use it, validate good usability and fix bugs.
|
||||
If it doesn’t fit in CMS right now, we will likely encourage you to make it into a package instead. A package is a great way to check out popularity of a feature, learn how people use it, validate good usability and to fix bugs.
|
||||
|
||||
Eventually, a package could "graduate" to be included in the CMS.
|
||||
|
||||
@@ -7,15 +7,15 @@ A brief description of the issue goes here.
|
||||
|
||||
<!--
|
||||
|
||||
Please fill 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
|
||||
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/v8/dev/.github/CONTRIBUTING.md
|
||||
|
||||
-->
|
||||
|
||||
## Umbraco version
|
||||
|
||||
I am seeing this issue on Umbraco version: <!-- please note the version here -->
|
||||
|
||||
|
||||
Reproduction
|
||||
|
||||
+4
-3
@@ -1,4 +1,4 @@
|
||||
# [Umbraco CMS](https://umbraco.com) · [](../LICENSE.md) [](https://umbraco.visualstudio.com/Umbraco%20Cms/_build?definitionId=75) [](CONTRIBUTING.md) [](https://twitter.com/intent/follow?screen_name=umbraco)
|
||||
# [Umbraco CMS](https://umbraco.com) · [](../LICENSE.md) [](https://umbraco.visualstudio.com/Umbraco%20Cms/_build?definitionId=75) [](CONTRIBUTING.md) [](https://pullreminders.com?ref=badge)
|
||||
|
||||
Umbraco is the friendliest, most flexible and fastest growing ASP.NET CMS, and used by more than 500,000 websites worldwide. Our mission is to help you deliver delightful digital experiences by making Umbraco friendly, simpler and social.
|
||||
|
||||
@@ -21,7 +21,7 @@ Please also see our [Code of Conduct](CODE_OF_CONDUCT.md).
|
||||
|
||||
[Umbraco Cloud](https://umbraco.com/cloud) is the easiest and fastest way to use Umbraco yet, with full support for all your custom .NET code and integrations. You're up and running in less than a minute, and your life will be made easier with automated upgrades and a built-in deployment engine. We offer a free 14-day trial, no credit card needed.
|
||||
|
||||
If you want to DIY, then you can [download Umbraco]((https://our.umbraco.com/download)) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Cloud, but you'll need to find a place to host it yourself, and handling deployments and upgrades will be all up to you.
|
||||
If you want to DIY, you can [download Umbraco]((https://our.umbraco.com/download)) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Cloud, but you'll need to find a place to host it yourself, and handling deployments and upgrades will be all up to you.
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -29,7 +29,7 @@ The documentation for Umbraco CMS can be found [on Our Umbraco](https://our.umbr
|
||||
|
||||
## Join the Umbraco community
|
||||
|
||||
Our friendly community is available 24/7 at the community hub, we call ["Our Umbraco"](https://our.umbraco.com/). Our Umbraco features forums for questions and answers, documentation, downloadable plugins for Umbraco, and a rich collection of community resources.
|
||||
Our friendly community is available 24/7 at the community hub we call ["Our Umbraco"](https://our.umbraco.com/). Our Umbraco features forums for questions and answers, documentation, downloadable plugins for Umbraco, and a rich collection of community resources.
|
||||
|
||||
Besides "Our", we all support each other also via Twitter: [Umbraco HQ](https://twitter.com/umbraco), [Release Updates](https://twitter.com/umbracoproject), [#umbraco](https://twitter.com/hashtag/umbraco)
|
||||
|
||||
@@ -37,3 +37,4 @@ Besides "Our", we all support each other also via Twitter: [Umbraco HQ](https://
|
||||
## Contributing
|
||||
|
||||
Umbraco is contribution-focused and community-driven. If you want to contribute back to the Umbraco source code, please check out our [guide to contributing](CONTRIBUTING.md).
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 17 KiB |
+1
-23
@@ -55,7 +55,6 @@ App_Data/TEMP/*
|
||||
src/Umbraco.Web.UI/[Cc]ss/*
|
||||
src/Umbraco.Web.UI/App_Code/*
|
||||
src/Umbraco.Web.UI/App_Data/*
|
||||
src/Umbraco.Web.UI/data/*
|
||||
src/Umbraco.Tests/App_Data/*
|
||||
src/Umbraco.Web.UI/[Mm]edia/*
|
||||
src/Umbraco.Web.UI/[Mm]aster[Pp]ages/*
|
||||
@@ -100,9 +99,6 @@ src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.dev.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/canvasdesigner.*.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/navigation.controller.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.controller.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/utilities.js
|
||||
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js
|
||||
@@ -136,8 +132,7 @@ src/Umbraco.Web.UI.Client/bower_components/*
|
||||
preserve.belle
|
||||
|
||||
#Ignore Rule for output of generated documentation files from Grunt docserve
|
||||
src/Umbraco.Web.UI.Docs/api
|
||||
src/Umbraco.Web.UI.Docs/package-lock.json
|
||||
src/Umbraco.Web.UI.Client/docs/api
|
||||
src/*.boltdata/
|
||||
src/umbraco.sln.ide/*
|
||||
src/.vs/
|
||||
@@ -163,24 +158,7 @@ build/hooks/
|
||||
build/temp/
|
||||
|
||||
|
||||
# Acceptance tests
|
||||
cypress.env.json
|
||||
/src/Umbraco.Tests.AcceptanceTest/cypress/support/chainable.ts
|
||||
/src/Umbraco.Tests.AcceptanceTest/package-lock.json
|
||||
/src/Umbraco.Tests.AcceptanceTest/cypress/videos/
|
||||
/src/Umbraco.Tests.AcceptanceTest/cypress/screenshots/
|
||||
|
||||
|
||||
# eof
|
||||
/src/Umbraco.Web.UI.Client/TESTS-*.xml
|
||||
/src/ApiDocs/api/*
|
||||
/src/Umbraco.Web.UI.NetCore/wwwroot/Media/*
|
||||
/src/Umbraco.Web.UI.NetCore/wwwroot/is-cache/*
|
||||
/src/Umbraco.Tests.Integration/App_Data/*
|
||||
/src/Umbraco.Tests.Integration/TEMP/*
|
||||
/src/Umbraco.Web.UI.NetCore/wwwroot/Umbraco/assets/*
|
||||
/src/Umbraco.Web.UI.NetCore/wwwroot/Umbraco/js/*
|
||||
/src/Umbraco.Web.UI.NetCore/wwwroot/Umbraco/lib/*
|
||||
/src/Umbraco.Web.UI.NetCore/wwwroot/Umbraco/views/*
|
||||
/src/Umbraco.Web.UI.NetCore/wwwroot/App_Data/TEMP/*
|
||||
/src/Umbraco.Web.UI.NetCore/App_Data/Logs/*
|
||||
|
||||
+1
-1
@@ -7,6 +7,6 @@
|
||||
-->
|
||||
<packageSources>
|
||||
<add key="UmbracoCoreMyGet" value="https://www.myget.org/F/umbracocore/api/v3/index.json" />
|
||||
<add key="ExamineAzurePipelines" value="https://shazwazza.pkgs.visualstudio.com/Examine/_packaging/Examine-Beta/nuget/v3/index.json" />
|
||||
<add key="ExamineAppVeyor" value="https://ci.appveyor.com/nuget/examine-f73l6qv0oqfh/" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
|
||||
@@ -25,15 +25,16 @@
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="UmbracoCms.Core" version="[$version$]" />
|
||||
<dependency id="ClientDependency" version="[1.9.9,1.999999)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.9.3,1.999999)" />
|
||||
<dependency id="Examine" version="[1.0.2,1.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,1.999999)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.8.14,1.999999)" />
|
||||
<dependency id="ImageProcessor" version="[2.7.0.100,2.999999)" />
|
||||
<dependency id="LightInject.Mvc" version="[2.0.0,2.999999)" />
|
||||
<dependency id="LightInject.WebApi" version="[2.0.0,2.999999)" />
|
||||
<dependency id="Markdown" version="[2.2.1,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Core" version="[2.2.2,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.2,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.7,5.999999)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.4.0,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.7,5.999999)" />
|
||||
@@ -41,7 +42,6 @@
|
||||
<dependency id="Microsoft.Owin.Security.Cookies" version="[4.0.1,4.999999)" />
|
||||
<dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.1,4.999999)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.9.0,4.999999)" />
|
||||
<dependency id="HtmlSanitizer" version="[4.0.217,4.999999)" />
|
||||
|
||||
</group>
|
||||
|
||||
@@ -52,17 +52,14 @@
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.dll" target="lib\net472\Umbraco.Web.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.dll" target="lib\net472\Umbraco.Web.UI.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.dll" target="lib\net472\Umbraco.Examine.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.ModelsBuilder.Embedded.dll" target="lib\net472\Umbraco.ModelsBuilder.Embedded.dll" />
|
||||
|
||||
<!-- docs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.xml" target="lib\net472\Umbraco.Web.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.xml" target="lib\net472\Umbraco.Web.UI.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.xml" target="lib\net472\Umbraco.Examine.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.ModelsBuilder.Embedded.xml" target="lib\net472\Umbraco.ModelsBuilder.Embedded.xml" />
|
||||
|
||||
<!-- symbols -->
|
||||
<file src="$BuildTmp$\bin\Umbraco.Web.pdb" target="lib\net472\Umbraco.Web.pdb" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Examine.pdb" target="lib\net472\Umbraco.Examine.pdb" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.ModelsBuilder.Embedded.pdb" target="lib\net472\Umbraco.ModelsBuilder.Embedded.pdb" />
|
||||
</files>
|
||||
</package>
|
||||
|
||||
@@ -26,9 +26,11 @@
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.4.0, 2.999999)" />
|
||||
<dependency id="Umbraco.ModelsBuilder.Ui" version="[8.1.0]" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.10.0.100,4.999999)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.5.0.100,2.999999)" />
|
||||
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[2.0.1,2.999999)" />
|
||||
<dependency id="Microsoft.Net.Compilers" version="[2.10.0,2.999999)" />
|
||||
|
||||
</group>
|
||||
|
||||
|
||||
@@ -11,16 +11,21 @@ Y88 88Y 888 888 888 888 d88P 888 888 888 Y88b. Y88..88P
|
||||
|
||||
Don't forget to build!
|
||||
|
||||
We've done our best to transform your configuration files but in case something is not quite right: we recommmend you look in source control for the previous version so you can find the original files before they were transformed.
|
||||
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 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.
|
||||
|
||||
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
|
||||
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, config\splashes and global.asax.
|
||||
|
||||
Please read the release notes on our.umbraco.com:
|
||||
https://our.umbraco.com/contribute/releases
|
||||
http://our.umbraco.com/contribute/releases
|
||||
|
||||
- Umbraco
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(factoryType)" xdt:Transform="SetAttributes(factoryType)" />
|
||||
<pages pageBaseType="System.Web.Mvc.WebViewPage">
|
||||
<namespaces>
|
||||
<add namespace="Umbraco.Web.PublishedModels" xdt:Transform="InsertIfMissing" />
|
||||
<add namespace="Umbraco.Web.PublishedContentModels" xdt:Transform="InsertIfMissing" />
|
||||
</namespaces>
|
||||
</pages>
|
||||
</system.web.webPages.razor>
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
<sectionGroup name="applicationSettings" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<sectionGroup name="system.web.webPages.razor" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<sectionGroup name="umbracoConfiguration" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing">
|
||||
<section name="settings" type="Umbraco.Core.Configuration.UmbracoSettings.UmbracoSettingsSection, Umbraco.Configuration" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="settings" type="Umbraco.Core.Configuration.UmbracoSettings.UmbracoSettingsSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="dashBoard" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<section name="HealthChecks" type="Umbraco.Core.Configuration.HealthChecks.HealthChecksSection, Umbraco.Configuration" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="HealthChecks" type="Umbraco.Core.Configuration.HealthChecks.HealthChecksSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<add name="umbracoBaseRequestModule" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<add name="viewstateMoverModule" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<add name=" UmbracoModule" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<add name="UmbracoModule" type="Umbraco.Web.UmbracoModule,Umbraco.Web" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<add name="UmbracoModule" type="Umbraco.Web.UmbracoModule,umbraco" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
</httpModules>
|
||||
|
||||
<httpHandlers xdt:Transform="InsertIfMissing" />
|
||||
@@ -76,7 +76,7 @@
|
||||
<!-- Note, we're removing the one that starts with a space here, don't correct it -->
|
||||
<!-- This to fix a quirk we for a lot of releases where we added it with the space by default -->
|
||||
<add name=" UmbracoModule" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<add name="UmbracoModule" type="Umbraco.Web.UmbracoModule,Umbraco.Web" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<add name="UmbracoModule" type="Umbraco.Web.UmbracoModule,umbraco" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
</modules>
|
||||
|
||||
<staticContent xdt:Transform="InsertIfMissing" />
|
||||
@@ -128,7 +128,6 @@
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Data.SqlServerCe')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.ValueTuple')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http.Formatting')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Collections.Immutable')" xdt:Transform="Remove" />
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">>
|
||||
<appSettings>
|
||||
|
||||
<add key="serilog:using:File" value="Umbraco.Infrastructure" xdt:Transform="SetAttributes(value)" xdt:Locator="Match(key)"/>
|
||||
<add key="serilog:using:File" value="Umbraco.Core" xdt:Transform="SetAttributes(value)" xdt:Locator="Match(key)"/>
|
||||
<add key="serilog:write-to:File.shared" xdt:Transform="Remove" xdt:Locator="Match(key)"/>
|
||||
|
||||
</appSettings>
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
##############################################################
|
||||
## V8 CMS - .NET & AngularJS Doc sites ##
|
||||
## Built on demand only, NO automatic PR/branch triggers ##
|
||||
## ##
|
||||
## This build pipeline has a webhook for sucessful ##
|
||||
## builds, that sends the ZIP artifacts to our.umb to host ##
|
||||
##############################################################
|
||||
|
||||
# Name != name of pipeline but the build number format
|
||||
# https://docs.microsoft.com/en-us/azure/devops/pipelines/process/run-number?view=azure-devops&tabs=yaml
|
||||
|
||||
# Build Pipeline triggers
|
||||
# https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/github?view=azure-devops&tabs=yaml#ci-triggers
|
||||
trigger: none
|
||||
pr: none
|
||||
|
||||
# Variables & their default values
|
||||
variables:
|
||||
buildPlatform: 'Any CPU'
|
||||
buildConfiguration: 'Release'
|
||||
|
||||
# VM to run the build on & it's installed software
|
||||
# https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops
|
||||
# https://github.com/actions/virtual-environments/blob/master/images/win/Windows2019-Readme.md
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
|
||||
jobs:
|
||||
- job: buildDocs
|
||||
displayName: 'Build static docs site as ZIPs'
|
||||
steps:
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: 'Prep build tool, build C# & JS Docs'
|
||||
inputs:
|
||||
targetType: 'inline'
|
||||
script: |
|
||||
$uenv=./build.ps1 -get -doc
|
||||
$uenv.SandboxNode()
|
||||
$uenv.CompileBelle()
|
||||
$uenv.PrepareAngularDocs()
|
||||
$nugetsourceUmbraco = "https://api.nuget.org/v3/index.json"
|
||||
$uenv.PrepareCSharpDocs()
|
||||
$uenv.RestoreNode()
|
||||
errorActionPreference: 'continue'
|
||||
workingDirectory: 'build'
|
||||
|
||||
- task: PublishPipelineArtifact@1
|
||||
inputs:
|
||||
targetPath: '$(Build.Repository.LocalPath)\build.out\'
|
||||
artifact: 'docs'
|
||||
publishLocation: 'pipeline'
|
||||
@@ -22,8 +22,6 @@
|
||||
# get NuGet
|
||||
$cache = 4
|
||||
$nuget = "$scriptTemp\nuget.exe"
|
||||
# ensure the correct NuGet-source is used. This one is used by Umbraco
|
||||
$nugetsourceUmbraco = "https://www.myget.org/F/umbracocore/api/v3/index.json"
|
||||
if (-not $local)
|
||||
{
|
||||
$source = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
|
||||
@@ -63,7 +61,7 @@
|
||||
# get the build system
|
||||
if (-not $local)
|
||||
{
|
||||
$params = "-OutputDirectory", $scriptTemp, "-Verbosity", "quiet", "-PreRelease", "-Source", $nugetsourceUmbraco
|
||||
$params = "-OutputDirectory", $scriptTemp, "-Verbosity", "quiet", "-PreRelease"
|
||||
&$nuget install Umbraco.Build @params
|
||||
if (-not $?) { throw "Failed to download Umbraco.Build." }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
$uenv=build/build.ps1 -get
|
||||
|
||||
$src = "$($uenv.SolutionRoot)\src"
|
||||
$tmp = $uenv.BuildTemp
|
||||
$out = $uenv.BuildOutput
|
||||
$DocFxJson = "$src\ApiDocs\docfx.json"
|
||||
$DocFxSiteOutput = "$tmp\_site\*.*"
|
||||
|
||||
################ Do the UI docs
|
||||
$uenv.CompileBelle()
|
||||
|
||||
"Moving to Umbraco.Web.UI.Client folder"
|
||||
cd .\src\Umbraco.Web.UI.Client
|
||||
|
||||
"Generating the docs and waiting before executing the next commands"
|
||||
& gulp docs | Out-Null
|
||||
|
||||
# change baseUrl
|
||||
$BaseUrl = "https://our.umbraco.com/apidocs/v8/ui/"
|
||||
$IndexPath = "./docs/api/index.html"
|
||||
(Get-Content $IndexPath).replace('location.href.replace(rUrl, indexFile)', "`'" + $BaseUrl + "`'") | Set-Content $IndexPath
|
||||
|
||||
# zip it
|
||||
& $uenv.BuildEnv.Zip a -tzip -r "$out\ui-docs.zip" "$src\Umbraco.Web.UI.Client\docs\api\*.*"
|
||||
|
||||
|
||||
################ Do the c# docs
|
||||
|
||||
# Build the solution in debug mode
|
||||
$SolutionPath = Join-Path -Path $src -ChildPath "umbraco.sln"
|
||||
#$uenv.CompileUmbraco()
|
||||
|
||||
#restore nuget packages
|
||||
$uenv.RestoreNuGet()
|
||||
|
||||
# run DocFx
|
||||
$DocFx = $uenv.BuildEnv.DocFx
|
||||
|
||||
Write-Host "$DocFxJson"
|
||||
& $DocFx metadata $DocFxJson
|
||||
& $DocFx build $DocFxJson
|
||||
|
||||
# zip it
|
||||
& $uenv.BuildEnv.Zip a -tzip -r "$out\csharp-docs.zip" $DocFxSiteOutput
|
||||
+14
-19
@@ -375,14 +375,11 @@
|
||||
|
||||
})
|
||||
|
||||
$nugetsourceUmbraco = "https://api.nuget.org/v3/index.json"
|
||||
|
||||
$ubuild.DefineMethod("RestoreNuGet",
|
||||
{
|
||||
Write-Host "Restore NuGet"
|
||||
Write-Host "Logging to $($this.BuildTemp)\nuget.restore.log"
|
||||
$params = "-Source", $nugetsourceUmbraco
|
||||
&$this.BuildEnv.NuGet restore "$($this.SolutionRoot)\src\Umbraco.sln" > "$($this.BuildTemp)\nuget.restore.log" @params
|
||||
&$this.BuildEnv.NuGet restore "$($this.SolutionRoot)\src\Umbraco.sln" > "$($this.BuildTemp)\nuget.restore.log"
|
||||
if (-not $?) { throw "Failed to restore NuGet packages." }
|
||||
})
|
||||
|
||||
@@ -438,11 +435,14 @@
|
||||
Write-Host "Prepare C# Documentation"
|
||||
|
||||
$src = "$($this.SolutionRoot)\src"
|
||||
$tmp = $this.BuildTemp
|
||||
$out = $this.BuildOutput
|
||||
$tmp = $this.BuildTemp
|
||||
$out = $this.BuildOutput
|
||||
$DocFxJson = Join-Path -Path $src "\ApiDocs\docfx.json"
|
||||
$DocFxSiteOutput = Join-Path -Path $tmp "\_site\*.*"
|
||||
|
||||
|
||||
#restore nuget packages
|
||||
$this.RestoreNuGet()
|
||||
# run DocFx
|
||||
$DocFx = $this.BuildEnv.DocFx
|
||||
|
||||
@@ -458,27 +458,23 @@
|
||||
Write-Host "Prepare Angular Documentation"
|
||||
|
||||
$src = "$($this.SolutionRoot)\src"
|
||||
$out = $this.BuildOutput
|
||||
$out = $this.BuildOutput
|
||||
|
||||
# Check if the solution has been built
|
||||
if (!(Test-Path "$src\Umbraco.Web.UI.Client\node_modules")) {throw "Umbraco needs to be built before generating the Angular Docs"}
|
||||
$this.CompileBelle()
|
||||
|
||||
"Moving to Umbraco.Web.UI.Docs folder"
|
||||
cd $src\Umbraco.Web.UI.Docs
|
||||
"Moving to Umbraco.Web.UI.Client folder"
|
||||
cd .\src\Umbraco.Web.UI.Client
|
||||
|
||||
"Generating the docs and waiting before executing the next commands"
|
||||
& npm install
|
||||
& npx gulp docs
|
||||
& gulp docs | Out-Null
|
||||
|
||||
Pop-Location
|
||||
|
||||
# change baseUrl
|
||||
$BaseUrl = "https://our.umbraco.com/apidocs/v8/ui/"
|
||||
$IndexPath = "./api/index.html"
|
||||
(Get-Content $IndexPath).replace('origin + location.href.substr(origin.length).replace(rUrl, indexFile)', "`'" + $BaseUrl + "`'") | Set-Content $IndexPath
|
||||
$IndexPath = "./docs/api/index.html"
|
||||
(Get-Content $IndexPath).replace('location.href.replace(rUrl, indexFile)', "`'" + $BaseUrl + "`'") | Set-Content $IndexPath
|
||||
|
||||
# zip it
|
||||
& $this.BuildEnv.Zip a -tzip -r "$out\ui-docs.zip" "$src\Umbraco.Web.UI.Docs\api\*.*"
|
||||
& $this.BuildEnv.Zip a -tzip -r "$out\ui-docs.zip" "$src\Umbraco.Web.UI.Client\docs\api\*.*"
|
||||
})
|
||||
|
||||
$ubuild.DefineMethod("Build",
|
||||
@@ -537,7 +533,6 @@
|
||||
# run
|
||||
if (-not $get)
|
||||
{
|
||||
cd
|
||||
if ($command.Length -eq 0)
|
||||
{
|
||||
$command = @( "Build" )
|
||||
|
||||
@@ -1,11 +1,65 @@
|
||||
body {
|
||||
color: #34393e;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
line-height: 1.5;
|
||||
font-size: 16px;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
word-wrap: break-word
|
||||
color: rgba(0,0,0,.8);
|
||||
}
|
||||
.navbar-inverse {
|
||||
background: #a3db78;
|
||||
}
|
||||
.navbar-inverse .navbar-nav>li>a, .navbar-inverse .navbar-text {
|
||||
color: rgba(0,0,0,.8);
|
||||
}
|
||||
|
||||
.navbar-inverse {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.sidetoc {
|
||||
background-color: #f5fbf1;
|
||||
}
|
||||
body .toc {
|
||||
background-color: #f5fbf1;
|
||||
}
|
||||
.sidefilter {
|
||||
background-color: #daf0c9;
|
||||
}
|
||||
.subnav {
|
||||
background-color: #f5fbf1;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-nav>.active>a {
|
||||
color: rgba(0,0,0,.8);
|
||||
background-color: #daf0c9;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-nav>.active>a:focus, .navbar-inverse .navbar-nav>.active>a:hover {
|
||||
color: rgba(0,0,0,.8);
|
||||
background-color: #daf0c9;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: rgba(0,0,0,.8);
|
||||
background-color: #fff;
|
||||
border-color: rgba(0,0,0,.8);
|
||||
}
|
||||
.btn-primary:hover {
|
||||
background-color: #daf0c9;
|
||||
color: rgba(0,0,0,.8);
|
||||
border-color: rgba(0,0,0,.8);
|
||||
}
|
||||
|
||||
.toc .nav > li > a {
|
||||
color: rgba(0,0,0,.8);
|
||||
}
|
||||
|
||||
button, a {
|
||||
color: #f36f21;
|
||||
}
|
||||
|
||||
button:hover,
|
||||
button:focus,
|
||||
a:hover,
|
||||
a:focus {
|
||||
color: #143653;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.navbar-header .navbar-brand {
|
||||
@@ -14,202 +68,6 @@ body {
|
||||
width:50px;
|
||||
}
|
||||
|
||||
#_content>a {
|
||||
margin-top: 5px;
|
||||
.toc .nav > li.active > a {
|
||||
color: #f36f21;
|
||||
}
|
||||
/* HEADINGS */
|
||||
|
||||
h1 {
|
||||
font-weight: 600;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-weight: 600;
|
||||
font-size: 24px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 14px;
|
||||
padding: 10px 0px;
|
||||
}
|
||||
|
||||
article h1,
|
||||
article h2,
|
||||
article h3,
|
||||
article h4 {
|
||||
margin-top: 35px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
article h4 {
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 2px solid #ddd;
|
||||
}
|
||||
|
||||
/* NAVBAR */
|
||||
|
||||
.navbar-brand>img {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
border: none;
|
||||
/* Both navbars use box-shadow */
|
||||
-webkit-box-shadow: 0px 1px 3px 0px rgba(100, 100, 100, 0.5);
|
||||
-moz-box-shadow: 0px 1px 3px 0px rgba(100, 100, 100, 0.5);
|
||||
box-shadow: 0px 1px 3px 0px rgba(100, 100, 100, 0.5);
|
||||
}
|
||||
|
||||
.subnav {
|
||||
border-top: 1px solid #ddd;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.navbar-inverse {
|
||||
background-color: #303ea1;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-nav>li>a,
|
||||
.navbar-inverse .navbar-text {
|
||||
color: #fff;
|
||||
background-color: #303ea1;
|
||||
border-bottom: 3px solid transparent;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-nav>li>a:focus,
|
||||
.navbar-inverse .navbar-nav>li>a:hover {
|
||||
color: #fff;
|
||||
background-color: #303ea1;
|
||||
border-bottom: 3px solid white;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-nav>.active>a,
|
||||
.navbar-inverse .navbar-nav>.active>a:focus,
|
||||
.navbar-inverse .navbar-nav>.active>a:hover {
|
||||
color: #fff;
|
||||
background-color: #303ea1;
|
||||
border-bottom: 3px solid white;
|
||||
}
|
||||
|
||||
.navbar-form .form-control {
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
/* SIDEBAR */
|
||||
|
||||
.toc .level1>li {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.toc .nav>li>a {
|
||||
color: #34393e;
|
||||
}
|
||||
|
||||
.sidefilter {
|
||||
background-color: #fff;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.sidefilter {
|
||||
background-color: #fff;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.toc-filter {
|
||||
padding: 10px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.toc-filter>input {
|
||||
border: 2px solid #ddd;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.toc-filter>.filter-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidetoc>.toc {
|
||||
background-color: #fff;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.sidetoc {
|
||||
background-color: #fff;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* ALERTS */
|
||||
|
||||
.alert {
|
||||
padding: 0px 0px 5px 0px;
|
||||
color: inherit;
|
||||
background-color: inherit;
|
||||
border: none;
|
||||
box-shadow: 0px 2px 2px 0px rgba(100, 100, 100, 0.4);
|
||||
}
|
||||
|
||||
.alert>p {
|
||||
margin-bottom: 0;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.alert>ul {
|
||||
margin-bottom: 0;
|
||||
padding: 5px 40px;
|
||||
}
|
||||
|
||||
.alert>h5 {
|
||||
padding: 10px 15px;
|
||||
margin-top: 0;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
.alert-info>h5 {
|
||||
color: #1976d2;
|
||||
border-bottom: 4px solid #1976d2;
|
||||
background-color: #e3f2fd;
|
||||
}
|
||||
|
||||
.alert-warning>h5 {
|
||||
color: #f57f17;
|
||||
border-bottom: 4px solid #f57f17;
|
||||
background-color: #fff3e0;
|
||||
}
|
||||
|
||||
.alert-danger>h5 {
|
||||
color: #d32f2f;
|
||||
border-bottom: 4px solid #d32f2f;
|
||||
background-color: #ffebee;
|
||||
}
|
||||
|
||||
/* CODE HIGHLIGHT */
|
||||
pre {
|
||||
padding: 9.5px;
|
||||
margin: 0 0 10px;
|
||||
font-size: 13px;
|
||||
word-break: break-all;
|
||||
word-wrap: break-word;
|
||||
background-color: #fffaef;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 1px 4px 1px rgba(100, 100, 100, 0.4);
|
||||
}
|
||||
|
||||
.sideaffix {
|
||||
overflow: visible;
|
||||
}
|
||||
+4
-4
@@ -2,7 +2,7 @@
|
||||
using System.Resources;
|
||||
|
||||
[assembly: AssemblyCompany("Umbraco")]
|
||||
[assembly: AssemblyCopyright("Copyright © Umbraco 2020")]
|
||||
[assembly: AssemblyCopyright("Copyright © Umbraco 2019")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@@ -15,8 +15,8 @@ using System.Resources;
|
||||
|
||||
// this is the ONLY ONE the CLR cares about for compatibility
|
||||
// should change ONLY when "hard" breaking compatibility (manual change)
|
||||
[assembly: AssemblyVersion("9.0.0")]
|
||||
[assembly: AssemblyVersion("8.0.0")]
|
||||
|
||||
// these are FYI and changed automatically
|
||||
[assembly: AssemblyFileVersion("9.0.0")]
|
||||
[assembly: AssemblyInformationalVersion("9.0.0")]
|
||||
[assembly: AssemblyFileVersion("8.2.0")]
|
||||
[assembly: AssemblyInformationalVersion("8.2.0")]
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Configuration.Models;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.HealthChecks;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using ConnectionStrings = Umbraco.Configuration.Models.ConnectionStrings;
|
||||
using CoreDebugSettings = Umbraco.Configuration.Models.CoreDebugSettings;
|
||||
|
||||
namespace Umbraco.Configuration
|
||||
{
|
||||
public class AspNetCoreConfigsFactory : IConfigsFactory
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public AspNetCoreConfigsFactory(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration ?? throw new System.ArgumentNullException(nameof(configuration));
|
||||
}
|
||||
|
||||
public Configs Create()
|
||||
{
|
||||
var configs = new Configs();
|
||||
|
||||
configs.Add<ITourSettings>(() => new TourSettings(_configuration));
|
||||
configs.Add<ICoreDebugSettings>(() => new CoreDebugSettings(_configuration));
|
||||
configs.Add<IRequestHandlerSettings>(() => new RequestHandlerSettings(_configuration));
|
||||
configs.Add<ISecuritySettings>(() => new SecuritySettings(_configuration));
|
||||
configs.Add<IUserPasswordConfiguration>(() => new UserPasswordConfigurationSettings(_configuration));
|
||||
configs.Add<IMemberPasswordConfiguration>(() => new MemberPasswordConfigurationSettings(_configuration));
|
||||
configs.Add<IKeepAliveSettings>(() => new KeepAliveSettings(_configuration));
|
||||
configs.Add<IContentSettings>(() => new ContentSettings(_configuration));
|
||||
configs.Add<IHealthChecksSettings>(() => new HealthChecksSettings(_configuration));
|
||||
configs.Add<ILoggingSettings>(() => new LoggingSettings(_configuration));
|
||||
configs.Add<IExceptionFilterSettings>(() => new ExceptionFilterSettings(_configuration));
|
||||
configs.Add<IActiveDirectorySettings>(() => new ActiveDirectorySettings(_configuration));
|
||||
configs.Add<IRuntimeSettings>(() => new RuntimeSettings(_configuration));
|
||||
configs.Add<ITypeFinderSettings>(() => new TypeFinderSettings(_configuration));
|
||||
configs.Add<INuCacheSettings>(() => new NuCacheSettings(_configuration));
|
||||
configs.Add<IWebRoutingSettings>(() => new WebRoutingSettings(_configuration));
|
||||
configs.Add<IIndexCreatorSettings>(() => new IndexCreatorSettings(_configuration));
|
||||
configs.Add<IModelsBuilderConfig>(() => new ModelsBuilderConfig(_configuration));
|
||||
configs.Add<IHostingSettings>(() => new HostingSettings(_configuration));
|
||||
configs.Add<IGlobalSettings>(() => new GlobalSettings(_configuration));
|
||||
configs.Add<IConnectionStrings>(() => new ConnectionStrings(_configuration));
|
||||
configs.Add<IImagingSettings>(() => new ImagingSettings(_configuration));
|
||||
|
||||
return configs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
using Umbraco.Configuration;
|
||||
using Umbraco.Configuration.Implementations;
|
||||
using Umbraco.Configuration.Legacy;
|
||||
using Umbraco.Core.Configuration.HealthChecks;
|
||||
using Umbraco.Core.Configuration.Legacy;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class ConfigsFactory : IConfigsFactory
|
||||
{
|
||||
public IHostingSettings HostingSettings { get; } = new HostingSettings();
|
||||
public ICoreDebugSettings CoreDebugSettings { get; } = new CoreDebugSettings();
|
||||
public IIndexCreatorSettings IndexCreatorSettings { get; } = new IndexCreatorSettings();
|
||||
public INuCacheSettings NuCacheSettings { get; } = new NuCacheSettings();
|
||||
public ITypeFinderSettings TypeFinderSettings { get; } = new TypeFinderSettings();
|
||||
public IRuntimeSettings RuntimeSettings { get; } = new RuntimeSettings();
|
||||
public IActiveDirectorySettings ActiveDirectorySettings { get; } = new ActiveDirectorySettings();
|
||||
public IExceptionFilterSettings ExceptionFilterSettings { get; } = new ExceptionFilterSettings();
|
||||
public ITourSettings TourSettings { get; } = new TourSettings();
|
||||
public ILoggingSettings LoggingSettings { get; } = new LoggingSettings();
|
||||
public IKeepAliveSettings KeepAliveSettings { get; } = new KeepAliveSettings();
|
||||
public IWebRoutingSettings WebRoutingSettings { get; } = new WebRoutingSettings();
|
||||
public IRequestHandlerSettings RequestHandlerSettings { get; } = new RequestHandlerSettings();
|
||||
public ISecuritySettings SecuritySettings { get; } = new SecuritySettings();
|
||||
public IUserPasswordConfiguration UserPasswordConfigurationSettings { get; } = new UserPasswordConfigurationSettings();
|
||||
public IMemberPasswordConfiguration MemberPasswordConfigurationSettings { get; } = new MemberPasswordConfigurationSettings();
|
||||
public IContentSettings ContentSettings { get; } = new ContentSettings();
|
||||
public IGlobalSettings GlobalSettings { get; } = new GlobalSettings();
|
||||
public IHealthChecksSettings HealthChecksSettings { get; } = new HealthChecksSettings();
|
||||
public IConnectionStrings ConnectionStrings { get; } = new ConnectionStrings();
|
||||
public IModelsBuilderConfig ModelsBuilderConfig { get; } = new ModelsBuilderConfig();
|
||||
|
||||
public Configs Create()
|
||||
{
|
||||
var configs = new Configs();
|
||||
|
||||
configs.Add<IGlobalSettings>(() => GlobalSettings);
|
||||
configs.Add<IHostingSettings>(() => HostingSettings);
|
||||
configs.Add<IHealthChecksSettings>(() => HealthChecksSettings);
|
||||
configs.Add<ICoreDebugSettings>(() => CoreDebugSettings);
|
||||
configs.Add<IConnectionStrings>(() => ConnectionStrings);
|
||||
configs.Add<IModelsBuilderConfig>(() => ModelsBuilderConfig);
|
||||
configs.Add<IIndexCreatorSettings>(() => IndexCreatorSettings);
|
||||
configs.Add<INuCacheSettings>(() => NuCacheSettings);
|
||||
configs.Add<ITypeFinderSettings>(() => TypeFinderSettings);
|
||||
configs.Add<IRuntimeSettings>(() => RuntimeSettings);
|
||||
configs.Add<IActiveDirectorySettings>(() => ActiveDirectorySettings);
|
||||
configs.Add<IExceptionFilterSettings>(() => ExceptionFilterSettings);
|
||||
configs.Add<ITourSettings>(() => TourSettings);
|
||||
configs.Add<ILoggingSettings>(() => LoggingSettings);
|
||||
configs.Add<IKeepAliveSettings>(() => KeepAliveSettings);
|
||||
configs.Add<IWebRoutingSettings>(() => WebRoutingSettings);
|
||||
configs.Add<IRequestHandlerSettings>(() => RequestHandlerSettings);
|
||||
configs.Add<ISecuritySettings>(() => SecuritySettings);
|
||||
configs.Add<IUserPasswordConfiguration>(() => UserPasswordConfigurationSettings);
|
||||
configs.Add<IMemberPasswordConfiguration>(() => MemberPasswordConfigurationSettings);
|
||||
configs.Add<IContentSettings>(() => ContentSettings);
|
||||
|
||||
return configs;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Legacy
|
||||
{
|
||||
public class ActiveDirectorySettings : IActiveDirectorySettings
|
||||
{
|
||||
public ActiveDirectorySettings()
|
||||
{
|
||||
ActiveDirectoryDomain = ConfigurationManager.AppSettings["ActiveDirectoryDomain"];
|
||||
}
|
||||
|
||||
public string ActiveDirectoryDomain { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal abstract class ConfigurationManagerConfigBase
|
||||
{
|
||||
private UmbracoSettingsSection _umbracoSettingsSection;
|
||||
|
||||
protected UmbracoSettingsSection UmbracoSettingsSection
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_umbracoSettingsSection is null)
|
||||
{
|
||||
_umbracoSettingsSection = ConfigurationManager.GetSection("umbracoConfiguration/settings") as UmbracoSettingsSection;
|
||||
}
|
||||
return _umbracoSettingsSection;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class ConnectionStrings : IConnectionStrings
|
||||
{
|
||||
public ConfigConnectionString this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
var settings = ConfigurationManager.ConnectionStrings[key];
|
||||
if (settings == null) return null;
|
||||
return new ConfigConnectionString(settings.ConnectionString, settings.ProviderName, settings.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Macros;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class ContentSettings : ConfigurationManagerConfigBase, IContentSettings
|
||||
{
|
||||
public string NotificationEmailAddress => UmbracoSettingsSection.Content.Notifications.NotificationEmailAddress;
|
||||
public bool DisableHtmlEmail => UmbracoSettingsSection.Content.Notifications.DisableHtmlEmail;
|
||||
public IEnumerable<string> ImageFileTypes => UmbracoSettingsSection.Content.Imaging.ImageFileTypes;
|
||||
public IEnumerable<IImagingAutoFillUploadField> ImageAutoFillProperties => UmbracoSettingsSection.Content.Imaging.ImageAutoFillProperties;
|
||||
public bool ResolveUrlsFromTextString => UmbracoSettingsSection.Content.ResolveUrlsFromTextString;
|
||||
public IEnumerable<IContentErrorPage> Error404Collection => UmbracoSettingsSection.Content.Error404Collection;
|
||||
public string PreviewBadge => UmbracoSettingsSection.Content.PreviewBadge;
|
||||
public MacroErrorBehaviour MacroErrorBehaviour => UmbracoSettingsSection.Content.MacroErrors;
|
||||
public IEnumerable<string> DisallowedUploadFiles => UmbracoSettingsSection.Content.DisallowedUploadFiles;
|
||||
public IEnumerable<string> AllowedUploadFiles => UmbracoSettingsSection.Content.AllowedUploadFiles;
|
||||
public bool ShowDeprecatedPropertyEditors => UmbracoSettingsSection.Content.ShowDeprecatedPropertyEditors;
|
||||
public string LoginBackgroundImage => UmbracoSettingsSection.Content.LoginBackgroundImage;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Legacy
|
||||
{
|
||||
public class ExceptionFilterSettings : IExceptionFilterSettings
|
||||
{
|
||||
public ExceptionFilterSettings()
|
||||
{
|
||||
if (bool.TryParse(ConfigurationManager.AppSettings["Umbraco.Web.DisableModelBindingExceptionFilter"],
|
||||
out var disabled))
|
||||
{
|
||||
Disabled = disabled;
|
||||
}
|
||||
}
|
||||
public bool Disabled { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Configuration.HealthChecks;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Legacy
|
||||
{
|
||||
public class HealthChecksSettings : IHealthChecksSettings
|
||||
{
|
||||
private HealthChecksSection _healthChecksSection;
|
||||
|
||||
private HealthChecksSection HealthChecksSection
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_healthChecksSection is null)
|
||||
{
|
||||
_healthChecksSection = ConfigurationManager.GetSection("umbracoConfiguration/HealthChecks") as HealthChecksSection;
|
||||
}
|
||||
return _healthChecksSection;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<IDisabledHealthCheck> DisabledChecks => HealthChecksSection.DisabledChecks;
|
||||
public IHealthCheckNotificationSettings NotificationSettings => HealthChecksSection.NotificationSettings;
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Legacy
|
||||
{
|
||||
public class HostingSettings : IHostingSettings
|
||||
{
|
||||
private bool? _debugMode;
|
||||
|
||||
/// <inheritdoc />
|
||||
public LocalTempStorage LocalTempStorageLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
var setting = ConfigurationManager.AppSettings[Constants.AppSettings.LocalTempStorage];
|
||||
if (!string.IsNullOrWhiteSpace(setting))
|
||||
return Enum<LocalTempStorage>.Parse(setting);
|
||||
|
||||
return LocalTempStorage.Default;
|
||||
}
|
||||
}
|
||||
|
||||
public string ApplicationVirtualPath => null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether umbraco is running in [debug mode].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [debug mode]; otherwise, <c>false</c>.</value>
|
||||
public bool DebugMode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_debugMode.HasValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ConfigurationManager.GetSection("system.web/compilation") is ConfigurationSection compilation)
|
||||
{
|
||||
var debugElement = compilation.ElementInformation.Properties["debug"];
|
||||
|
||||
_debugMode = debugElement != null && (debugElement.Value is bool debug && debug);
|
||||
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
_debugMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
return _debugMode.GetValueOrDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Legacy
|
||||
{
|
||||
public class IndexCreatorSettings : IIndexCreatorSettings
|
||||
{
|
||||
public IndexCreatorSettings()
|
||||
{
|
||||
LuceneDirectoryFactory = ConfigurationManager.AppSettings["Umbraco.Examine.LuceneDirectoryFactory"];
|
||||
}
|
||||
|
||||
public string LuceneDirectoryFactory { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class KeepAliveSettings : ConfigurationManagerConfigBase, IKeepAliveSettings
|
||||
{
|
||||
public bool DisableKeepAliveTask => UmbracoSettingsSection.KeepAlive.DisableKeepAliveTask;
|
||||
public string KeepAlivePingUrl => UmbracoSettingsSection.KeepAlive.KeepAlivePingUrl;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class LoggingSettings : ConfigurationManagerConfigBase, ILoggingSettings
|
||||
{
|
||||
public int MaxLogAge => UmbracoSettingsSection.Logging.MaxLogAge;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class MemberPasswordConfigurationSettings : ConfigurationManagerConfigBase, IMemberPasswordConfiguration
|
||||
{
|
||||
public int RequiredLength => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequiredLength;
|
||||
public bool RequireNonLetterOrDigit => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireNonLetterOrDigit;
|
||||
public bool RequireDigit => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireDigit;
|
||||
public bool RequireLowercase=> UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireLowercase;
|
||||
public bool RequireUppercase=> UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireUppercase;
|
||||
public bool UseLegacyEncoding=> UmbracoSettingsSection.Security.UserPasswordConfiguration.UseLegacyEncoding;
|
||||
public string HashAlgorithmType=> UmbracoSettingsSection.Security.UserPasswordConfiguration.HashAlgorithmType;
|
||||
public int MaxFailedAccessAttemptsBeforeLockout => UmbracoSettingsSection.Security.UserPasswordConfiguration.MaxFailedAccessAttemptsBeforeLockout;
|
||||
}
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Configuration.Legacy
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the models builder configuration.
|
||||
/// </summary>
|
||||
public class ModelsBuilderConfig : IModelsBuilderConfig
|
||||
{
|
||||
|
||||
private const string Prefix = "Umbraco.ModelsBuilder.";
|
||||
private object _modelsModelLock;
|
||||
private bool _modelsModelConfigured;
|
||||
private ModelsMode _modelsMode;
|
||||
private object _flagOutOfDateModelsLock;
|
||||
private bool _flagOutOfDateModelsConfigured;
|
||||
private bool _flagOutOfDateModels;
|
||||
|
||||
|
||||
public string DefaultModelsDirectory => "~/App_Data/Models";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ModelsBuilderConfig"/> class.
|
||||
/// </summary>
|
||||
public ModelsBuilderConfig()
|
||||
{
|
||||
// giant kill switch, default: false
|
||||
// must be explicitely set to true for anything else to happen
|
||||
Enable = ConfigurationManager.AppSettings[Prefix + "Enable"] == "true";
|
||||
|
||||
// ensure defaults are initialized for tests
|
||||
ModelsNamespace = Constants.ModelsBuilder.DefaultModelsNamespace;
|
||||
ModelsDirectory = DefaultModelsDirectory;
|
||||
DebugLevel = 0;
|
||||
|
||||
// stop here, everything is false
|
||||
if (!Enable) return;
|
||||
|
||||
// default: false
|
||||
AcceptUnsafeModelsDirectory = ConfigurationManager.AppSettings[Prefix + "AcceptUnsafeModelsDirectory"].InvariantEquals("true");
|
||||
|
||||
// default: true
|
||||
EnableFactory = !ConfigurationManager.AppSettings[Prefix + "EnableFactory"].InvariantEquals("false");
|
||||
|
||||
// default: initialized above with DefaultModelsNamespace const
|
||||
var value = ConfigurationManager.AppSettings[Prefix + "ModelsNamespace"];
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
ModelsNamespace = value;
|
||||
|
||||
// default: initialized above with DefaultModelsDirectory const
|
||||
value = ConfigurationManager.AppSettings[Prefix + "ModelsDirectory"];
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
// GetModelsDirectory will ensure that the path is safe
|
||||
ModelsDirectory = value;
|
||||
}
|
||||
|
||||
// default: 0
|
||||
value = ConfigurationManager.AppSettings[Prefix + "DebugLevel"];
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
if (!int.TryParse(value, out var debugLevel))
|
||||
throw new ConfigurationErrorsException($"Invalid debug level \"{value}\".");
|
||||
DebugLevel = debugLevel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ModelsBuilderConfig"/> class.
|
||||
/// </summary>
|
||||
public ModelsBuilderConfig(
|
||||
bool enable = false,
|
||||
ModelsMode modelsMode = ModelsMode.Nothing,
|
||||
string modelsNamespace = null,
|
||||
bool enableFactory = true,
|
||||
bool flagOutOfDateModels = true,
|
||||
string modelsDirectory = null,
|
||||
bool acceptUnsafeModelsDirectory = false,
|
||||
int debugLevel = 0)
|
||||
{
|
||||
Enable = enable;
|
||||
_modelsMode = modelsMode;
|
||||
|
||||
ModelsNamespace = string.IsNullOrWhiteSpace(modelsNamespace) ? Constants.ModelsBuilder.DefaultModelsNamespace : modelsNamespace;
|
||||
EnableFactory = enableFactory;
|
||||
_flagOutOfDateModels = flagOutOfDateModels;
|
||||
ModelsDirectory = string.IsNullOrWhiteSpace(modelsDirectory) ? DefaultModelsDirectory : modelsDirectory;
|
||||
AcceptUnsafeModelsDirectory = acceptUnsafeModelsDirectory;
|
||||
DebugLevel = debugLevel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the whole models experience is enabled.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>If this is false then absolutely nothing happens.</para>
|
||||
/// <para>Default value is <c>false</c> which means that unless we have this setting, nothing happens.</para>
|
||||
/// </remarks>
|
||||
public bool Enable { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the models mode.
|
||||
/// </summary>
|
||||
public ModelsMode ModelsMode =>
|
||||
LazyInitializer.EnsureInitialized(ref _modelsMode, ref _modelsModelConfigured, ref _modelsModelLock, () =>
|
||||
{
|
||||
// mode
|
||||
var modelsMode = ConfigurationManager.AppSettings[Prefix + "ModelsMode"];
|
||||
if (string.IsNullOrWhiteSpace(modelsMode)) return ModelsMode.Nothing; //default
|
||||
switch (modelsMode)
|
||||
{
|
||||
case nameof(ModelsMode.Nothing):
|
||||
return ModelsMode.Nothing;
|
||||
case nameof(ModelsMode.PureLive):
|
||||
return ModelsMode.PureLive;
|
||||
case nameof(ModelsMode.AppData):
|
||||
return ModelsMode.AppData;
|
||||
case nameof(ModelsMode.LiveAppData):
|
||||
return ModelsMode.LiveAppData;
|
||||
default:
|
||||
throw new ConfigurationErrorsException($"ModelsMode \"{modelsMode}\" is not a valid mode." + " Note that modes are case-sensitive. Possible values are: " + string.Join(", ", Enum.GetNames(typeof(ModelsMode))));
|
||||
}
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether system.web/compilation/@debug is true.
|
||||
/// </summary>
|
||||
public bool IsDebug
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ConfigurationManager.GetSection("system.web/compilation") is ConfigurationSection section &&
|
||||
bool.TryParse(section.ElementInformation.Properties["debug"].Value.ToString(), out var isDebug))
|
||||
{
|
||||
return isDebug;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the models namespace.
|
||||
/// </summary>
|
||||
/// <remarks>That value could be overriden by other (attribute in user's code...). Return default if no value was supplied.</remarks>
|
||||
public string ModelsNamespace { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether we should enable the models factory.
|
||||
/// </summary>
|
||||
/// <remarks>Default value is <c>true</c> because no factory is enabled by default in Umbraco.</remarks>
|
||||
public bool EnableFactory { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether we should flag out-of-date models.
|
||||
/// </summary>
|
||||
/// <remarks>Models become out-of-date when data types or content types are updated. When this
|
||||
/// setting is activated the ~/App_Data/Models/ood.txt file is then created. When models are
|
||||
/// generated through the dashboard, the files is cleared. Default value is <c>false</c>.</remarks>
|
||||
public bool FlagOutOfDateModels
|
||||
=> LazyInitializer.EnsureInitialized(ref _flagOutOfDateModels, ref _flagOutOfDateModelsConfigured, ref _flagOutOfDateModelsLock, () =>
|
||||
{
|
||||
var flagOutOfDateModels = !ConfigurationManager.AppSettings[Prefix + "FlagOutOfDateModels"].InvariantEquals("false");
|
||||
if (ModelsMode == ModelsMode.Nothing || ModelsMode.IsLive())
|
||||
{
|
||||
flagOutOfDateModels = false;
|
||||
}
|
||||
|
||||
return flagOutOfDateModels;
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Gets the models directory.
|
||||
/// </summary>
|
||||
/// <remarks>Default is ~/App_Data/Models but that can be changed.</remarks>
|
||||
public string ModelsDirectory { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether to accept an unsafe value for ModelsDirectory.
|
||||
/// </summary>
|
||||
/// <remarks>An unsafe value is an absolute path, or a relative path pointing outside
|
||||
/// of the website root.</remarks>
|
||||
public bool AcceptUnsafeModelsDirectory { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating the debug log level.
|
||||
/// </summary>
|
||||
/// <remarks>0 means minimal (safe on live site), anything else means more and more details (maybe not safe).</remarks>
|
||||
public int DebugLevel { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Legacy
|
||||
{
|
||||
public class NuCacheSettings : INuCacheSettings
|
||||
{
|
||||
public NuCacheSettings()
|
||||
{
|
||||
BTreeBlockSize = ConfigurationManager.AppSettings["Umbraco.Web.PublishedCache.NuCache.BTree.BlockSize"];
|
||||
}
|
||||
public string BTreeBlockSize { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class RequestHandlerSettings : ConfigurationManagerConfigBase, IRequestHandlerSettings
|
||||
{
|
||||
public bool AddTrailingSlash => UmbracoSettingsSection?.RequestHandler?.AddTrailingSlash ?? true;
|
||||
public bool ConvertUrlsToAscii => UmbracoSettingsSection?.RequestHandler?.UrlReplacing?.ConvertUrlsToAscii.InvariantEquals("true") ?? false;
|
||||
public bool TryConvertUrlsToAscii => UmbracoSettingsSection?.RequestHandler?.UrlReplacing?.ConvertUrlsToAscii.InvariantEquals("try") ?? false;
|
||||
public IEnumerable<IChar> CharCollection => UmbracoSettingsSection?.RequestHandler?.UrlReplacing?.CharCollection ?? Enumerable.Empty<IChar>();
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Legacy
|
||||
{
|
||||
public class RuntimeSettings : IRuntimeSettings
|
||||
{
|
||||
public RuntimeSettings()
|
||||
{
|
||||
if (ConfigurationManager.GetSection("system.web/httpRuntime") is ConfigurationSection section)
|
||||
{
|
||||
var maxRequestLengthProperty = section.ElementInformation.Properties["maxRequestLength"];
|
||||
if (maxRequestLengthProperty != null && maxRequestLengthProperty.Value is int requestLength)
|
||||
{
|
||||
MaxRequestLength = requestLength;
|
||||
}
|
||||
|
||||
var maxQueryStringProperty = section.ElementInformation.Properties["maxQueryStringLength"];
|
||||
if (maxQueryStringProperty != null && maxQueryStringProperty.Value is int maxQueryStringLength)
|
||||
{
|
||||
MaxQueryStringLength = maxQueryStringLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
public int? MaxQueryStringLength { get; }
|
||||
public int? MaxRequestLength { get; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class SecuritySettings : ConfigurationManagerConfigBase, ISecuritySettings
|
||||
{
|
||||
public bool KeepUserLoggedIn => UmbracoSettingsSection.Security.KeepUserLoggedIn;
|
||||
public bool HideDisabledUsersInBackoffice => UmbracoSettingsSection.Security.HideDisabledUsersInBackoffice;
|
||||
public bool AllowPasswordReset => UmbracoSettingsSection.Security.AllowPasswordReset;
|
||||
public string AuthCookieName => UmbracoSettingsSection.Security.AuthCookieName;
|
||||
public string AuthCookieDomain => UmbracoSettingsSection.Security.AuthCookieDomain;
|
||||
public bool UsernameIsEmail => UmbracoSettingsSection.Security.UsernameIsEmail;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using System.Net.Mail;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration
|
||||
{
|
||||
public class SmtpSettings : ISmtpSettings
|
||||
{
|
||||
public string From { get; set; }
|
||||
public string Host { get; set; }
|
||||
public int Port { get; set; }
|
||||
public string PickupDirectoryLocation { get; set; }
|
||||
public SmtpDeliveryMethod DeliveryMethod { get; set; }
|
||||
|
||||
public string Username { get; set; }
|
||||
|
||||
public string Password { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class TourSettings : ConfigurationManagerConfigBase, ITourSettings
|
||||
{
|
||||
public bool EnableTours => UmbracoSettingsSection.BackOffice.Tours.EnableTours;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Legacy
|
||||
{
|
||||
public class TypeFinderSettings : ITypeFinderSettings
|
||||
{
|
||||
public TypeFinderSettings()
|
||||
{
|
||||
AssembliesAcceptingLoadExceptions = ConfigurationManager.AppSettings[
|
||||
Constants.AppSettings.AssembliesAcceptingLoadExceptions];
|
||||
}
|
||||
|
||||
public string AssembliesAcceptingLoadExceptions { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using Umbraco.Core.Configuration;
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class UserPasswordConfigurationSettings : ConfigurationManagerConfigBase, IUserPasswordConfiguration
|
||||
{
|
||||
public int RequiredLength => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequiredLength;
|
||||
public bool RequireNonLetterOrDigit => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireNonLetterOrDigit;
|
||||
public bool RequireDigit => UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireDigit;
|
||||
public bool RequireLowercase=> UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireLowercase;
|
||||
public bool RequireUppercase=> UmbracoSettingsSection.Security.UserPasswordConfiguration.RequireUppercase;
|
||||
public bool UseLegacyEncoding=> UmbracoSettingsSection.Security.UserPasswordConfiguration.UseLegacyEncoding;
|
||||
public string HashAlgorithmType=> UmbracoSettingsSection.Security.UserPasswordConfiguration.HashAlgorithmType;
|
||||
public int MaxFailedAccessAttemptsBeforeLockout => UmbracoSettingsSection.Security.UserPasswordConfiguration.MaxFailedAccessAttemptsBeforeLockout;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Implementations
|
||||
{
|
||||
internal class WebRoutingSettings : ConfigurationManagerConfigBase, IWebRoutingSettings
|
||||
{
|
||||
public bool TrySkipIisCustomErrors => UmbracoSettingsSection?.WebRouting?.TrySkipIisCustomErrors ?? false;
|
||||
public bool InternalRedirectPreservesTemplate => UmbracoSettingsSection?.WebRouting?.InternalRedirectPreservesTemplate ?? false;
|
||||
public bool DisableAlternativeTemplates => UmbracoSettingsSection?.WebRouting?.DisableAlternativeTemplates ?? false;
|
||||
public bool ValidateAlternativeTemplates => UmbracoSettingsSection?.WebRouting?.ValidateAlternativeTemplates ?? false;
|
||||
public bool DisableFindContentByIdPath => UmbracoSettingsSection?.WebRouting?.DisableFindContentByIdPath ?? false;
|
||||
public bool DisableRedirectUrlTracking => UmbracoSettingsSection?.WebRouting?.DisableRedirectUrlTracking ?? false;
|
||||
public string UrlProviderMode => UmbracoSettingsSection?.WebRouting?.UrlProviderMode ?? "Auto";
|
||||
public string UmbracoApplicationUrl => UmbracoSettingsSection?.WebRouting?.UmbracoApplicationUrl;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class ActiveDirectorySettings : IActiveDirectorySettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "ActiveDirectory:";
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public ActiveDirectorySettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public string ActiveDirectoryDomain => _configuration.GetValue<string>(Prefix+"Domain");
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
public class ConnectionStrings : IConnectionStrings
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public ConnectionStrings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public ConfigConnectionString this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
var connectionString = _configuration.GetConnectionString(key);
|
||||
var provider = ParseProvider(connectionString);
|
||||
return new ConfigConnectionString(connectionString, provider, key);
|
||||
}
|
||||
set => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private string ParseProvider(string connectionString)
|
||||
{
|
||||
if (string.IsNullOrEmpty(connectionString))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var builder = new DbConnectionStringBuilder();
|
||||
|
||||
builder.ConnectionString = connectionString;
|
||||
|
||||
if (builder.TryGetValue("Data Source", out var ds) && ds is string dataSource)
|
||||
{
|
||||
if (dataSource.EndsWith(".sdf"))
|
||||
{
|
||||
return Constants.DbProviderNames.SqlCe;
|
||||
}
|
||||
}
|
||||
|
||||
if (builder.TryGetValue("Server", out var s) && s is string server && builder.TryGetValue("Database", out var db) && db is string database)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(server) && !string.IsNullOrEmpty(database))
|
||||
{
|
||||
return Constants.DbProviderNames.SqlServer;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentException("Cannot determine provider name from connection string", nameof(connectionString));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Macros;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class ContentSettings : IContentSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "Content:";
|
||||
private const string NotificationsPrefix = Prefix + "Notifications:";
|
||||
private const string ImagingPrefix = Prefix + "Imaging:";
|
||||
private const string DefaultPreviewBadge =
|
||||
@"<div id=""umbracoPreviewBadge"" class=""umbraco-preview-badge""><span class=""umbraco-preview-badge__header"">Preview mode</span><a href=""{0}/preview/end?redir={1}"" class=""umbraco-preview-badge__end""><svg viewBox=""0 0 100 100"" xmlns=""http://www.w3.org/2000/svg""><title>Click to end</title><path d=""M5273.1 2400.1v-2c0-2.8-5-4-9.7-4s-9.7 1.3-9.7 4v2a7 7 0 002 4.9l5 4.9c.3.3.4.6.4 1v6.4c0 .4.2.7.6.8l2.9.9c.5.1 1-.2 1-.8v-7.2c0-.4.2-.7.4-1l5.1-5a7 7 0 002-4.9zm-9.7-.1c-4.8 0-7.4-1.3-7.5-1.8.1-.5 2.7-1.8 7.5-1.8s7.3 1.3 7.5 1.8c-.2.5-2.7 1.8-7.5 1.8z""/><path d=""M5268.4 2410.3c-.6 0-1 .4-1 1s.4 1 1 1h4.3c.6 0 1-.4 1-1s-.4-1-1-1h-4.3zM5272.7 2413.7h-4.3c-.6 0-1 .4-1 1s.4 1 1 1h4.3c.6 0 1-.4 1-1s-.4-1-1-1zM5272.7 2417h-4.3c-.6 0-1 .4-1 1s.4 1 1 1h4.3c.6 0 1-.4 1-1 0-.5-.4-1-1-1z""/><path d=""M78.2 13l-8.7 11.7a32.5 32.5 0 11-51.9 25.8c0-10.3 4.7-19.7 12.9-25.8L21.8 13a47 47 0 1056.4 0z""/><path d=""M42.7 2.5h14.6v49.4H42.7z""/></svg></a></div><style type=""text/css"">.umbraco-preview-badge {{position: absolute;top: 1em;right: 1em;display: inline-flex;background: #1b264f;color: #fff;padding: 1em;font-size: 12px;z-index: 99999999;justify-content: center;align-items: center;box-shadow: 0 10px 50px rgba(0, 0, 0, .1), 0 6px 20px rgba(0, 0, 0, .16);line-height: 1;}}.umbraco-preview-badge__header {{font-weight: bold;}}.umbraco-preview-badge__end {{width: 3em;padding: 1em;margin: -1em -1em -1em 2em;display: flex;flex-shrink: 0;align-items: center;align-self: stretch;}}.umbraco-preview-badge__end:hover,.umbraco-preview-badge__end:focus {{background: #f5c1bc;}}.umbraco-preview-badge__end svg {{fill: #fff;width:1em;}}</style>";
|
||||
|
||||
private static readonly ImagingAutoFillUploadField[] DefaultImagingAutoFillUploadField =
|
||||
{
|
||||
new ImagingAutoFillUploadField
|
||||
{
|
||||
Alias = "umbracoFile"
|
||||
}
|
||||
};
|
||||
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public ContentSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public string NotificationEmailAddress =>
|
||||
_configuration.GetValue<string>(NotificationsPrefix+"Email");
|
||||
|
||||
public bool DisableHtmlEmail =>
|
||||
_configuration.GetValue(NotificationsPrefix+"DisableHtmlEmail", false);
|
||||
|
||||
public IEnumerable<string> ImageFileTypes => _configuration.GetValue(
|
||||
ImagingPrefix+"ImageFileTypes", new[] { "jpeg", "jpg", "gif", "bmp", "png", "tiff", "tif" });
|
||||
|
||||
public IEnumerable<IImagingAutoFillUploadField> ImageAutoFillProperties =>
|
||||
_configuration.GetValue(ImagingPrefix+"AutoFillImageProperties",
|
||||
DefaultImagingAutoFillUploadField);
|
||||
|
||||
|
||||
public bool ResolveUrlsFromTextString =>
|
||||
_configuration.GetValue(Prefix+"ResolveUrlsFromTextString", false);
|
||||
|
||||
public IEnumerable<IContentErrorPage> Error404Collection => _configuration
|
||||
.GetSection(Prefix+"Errors:Error404")
|
||||
.GetChildren()
|
||||
.Select(x => new ContentErrorPage(x));
|
||||
|
||||
public string PreviewBadge => _configuration.GetValue(Prefix+"PreviewBadge", DefaultPreviewBadge);
|
||||
|
||||
public MacroErrorBehaviour MacroErrorBehaviour =>
|
||||
_configuration.GetValue(Prefix+"MacroErrors", MacroErrorBehaviour.Inline);
|
||||
|
||||
public IEnumerable<string> DisallowedUploadFiles => _configuration.GetValue(
|
||||
Prefix+"DisallowedUploadFiles",
|
||||
new[] { "ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd" });
|
||||
|
||||
public IEnumerable<string> AllowedUploadFiles =>
|
||||
_configuration.GetValue(Prefix+"AllowedUploadFiles", Array.Empty<string>());
|
||||
|
||||
public bool ShowDeprecatedPropertyEditors =>
|
||||
_configuration.GetValue(Prefix+"ShowDeprecatedPropertyEditors", false);
|
||||
|
||||
public string LoginBackgroundImage =>
|
||||
_configuration.GetValue(Prefix+"LoginBackgroundImage", string.Empty);
|
||||
|
||||
private class ContentErrorPage : IContentErrorPage
|
||||
{
|
||||
public ContentErrorPage(IConfigurationSection configurationSection)
|
||||
{
|
||||
Culture = configurationSection.Key;
|
||||
|
||||
var value = configurationSection.Value;
|
||||
|
||||
if (int.TryParse(value, out var contentId))
|
||||
{
|
||||
HasContentId = true;
|
||||
ContentId = contentId;
|
||||
}
|
||||
else if (Guid.TryParse(value, out var contentKey))
|
||||
{
|
||||
HasContentKey = true;
|
||||
ContentKey = contentKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
ContentXPath = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int ContentId { get; }
|
||||
public Guid ContentKey { get; }
|
||||
public string ContentXPath { get; }
|
||||
public bool HasContentId { get; }
|
||||
public bool HasContentKey { get; }
|
||||
public string Culture { get; set; }
|
||||
}
|
||||
|
||||
private class ImagingAutoFillUploadField : IImagingAutoFillUploadField
|
||||
{
|
||||
public string Alias { get; set; }
|
||||
public string WidthFieldAlias { get; set; }
|
||||
public string HeightFieldAlias { get; set; }
|
||||
public string LengthFieldAlias { get; set; }
|
||||
public string ExtensionFieldAlias { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class CoreDebugSettings : ICoreDebugSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "Core:Debug:";
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public CoreDebugSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public bool LogUncompletedScopes =>
|
||||
_configuration.GetValue(Prefix+"LogUncompletedScopes", false);
|
||||
|
||||
public bool DumpOnTimeoutThreadAbort =>
|
||||
_configuration.GetValue(Prefix+"DumpOnTimeoutThreadAbort", false);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class ExceptionFilterSettings : IExceptionFilterSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "ExceptionFilter:";
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public ExceptionFilterSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public bool Disabled => _configuration.GetValue(Prefix+"Disabled", false);
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Mail;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// The GlobalSettings Class contains general settings information for the entire Umbraco instance based on information
|
||||
/// from web.config appsettings
|
||||
/// </summary>
|
||||
internal class GlobalSettings : IGlobalSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigGlobalPrefix;
|
||||
|
||||
internal const string
|
||||
StaticReservedPaths = "~/app_plugins/,~/install/,~/mini-profiler-resources/,"; //must end with a comma!
|
||||
|
||||
internal const string
|
||||
StaticReservedUrls = "~/config/splashes/noNodes.aspx,~/.well-known,"; //must end with a comma!
|
||||
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public GlobalSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public string ReservedUrls => _configuration.GetValue(Prefix + "ReservedUrls", StaticReservedUrls);
|
||||
public string ReservedPaths => _configuration.GetValue(Prefix + "ReservedPaths", StaticReservedPaths);
|
||||
|
||||
// TODO: https://github.com/umbraco/Umbraco-CMS/issues/4238 - stop having version in web.config appSettings
|
||||
public string ConfigurationStatus
|
||||
{
|
||||
get => _configuration.GetValue<string>(Prefix + "ConfigurationStatus");
|
||||
set => throw new NotImplementedException("We should remove this and only use the value from database");
|
||||
}
|
||||
|
||||
public int TimeOutInMinutes => _configuration.GetValue(Prefix + "TimeOutInMinutes", 20);
|
||||
public string DefaultUILanguage => _configuration.GetValue(Prefix + "TimeOutInMinutes", "en-US");
|
||||
|
||||
public bool HideTopLevelNodeFromPath =>
|
||||
_configuration.GetValue(Prefix + "HideTopLevelNodeFromPath", false);
|
||||
|
||||
public bool UseHttps => _configuration.GetValue(Prefix + "UseHttps", false);
|
||||
public int VersionCheckPeriod => _configuration.GetValue(Prefix + "VersionCheckPeriod", 7);
|
||||
public string UmbracoPath => _configuration.GetValue(Prefix + "UmbracoPath", "~/umbraco");
|
||||
public string IconsPath => _configuration.GetValue(Prefix + "IconsPath", $"{UmbracoPath}/assets/icons");
|
||||
|
||||
public string UmbracoCssPath => _configuration.GetValue(Prefix + "UmbracoCssPath", "~/css");
|
||||
|
||||
public string UmbracoScriptsPath =>
|
||||
_configuration.GetValue(Prefix + "UmbracoScriptsPath", "~/scripts");
|
||||
|
||||
public string UmbracoMediaPath => _configuration.GetValue(Prefix + "UmbracoMediaPath", "~/media");
|
||||
|
||||
public bool InstallMissingDatabase =>
|
||||
_configuration.GetValue(Prefix + "InstallMissingDatabase", false);
|
||||
|
||||
public bool InstallEmptyDatabase => _configuration.GetValue(Prefix + "InstallEmptyDatabase", false);
|
||||
|
||||
public bool DisableElectionForSingleServer =>
|
||||
_configuration.GetValue(Prefix + "DisableElectionForSingleServer", false);
|
||||
|
||||
public string RegisterType => _configuration.GetValue(Prefix + "RegisterType", string.Empty);
|
||||
|
||||
public string DatabaseFactoryServerVersion =>
|
||||
_configuration.GetValue(Prefix + "DatabaseFactoryServerVersion", string.Empty);
|
||||
|
||||
public string MainDomLock => _configuration.GetValue(Prefix + "MainDomLock", string.Empty);
|
||||
|
||||
public string NoNodesViewPath =>
|
||||
_configuration.GetValue(Prefix + "NoNodesViewPath", "~/config/splashes/NoNodes.cshtml");
|
||||
|
||||
public bool IsSmtpServerConfigured =>
|
||||
_configuration.GetSection(Constants.Configuration.ConfigGlobalPrefix + "Smtp")?.GetChildren().Any() ?? false;
|
||||
|
||||
public ISmtpSettings SmtpSettings =>
|
||||
new SmtpSettingsImpl(_configuration.GetSection(Constants.Configuration.ConfigGlobalPrefix + "Smtp"));
|
||||
|
||||
private class SmtpSettingsImpl : ISmtpSettings
|
||||
{
|
||||
private readonly IConfigurationSection _configurationSection;
|
||||
|
||||
public SmtpSettingsImpl(IConfigurationSection configurationSection)
|
||||
{
|
||||
_configurationSection = configurationSection;
|
||||
}
|
||||
|
||||
public string From => _configurationSection.GetValue<string>("From");
|
||||
public string Host => _configurationSection.GetValue<string>("Host");
|
||||
public int Port => _configurationSection.GetValue<int>("Port");
|
||||
public string PickupDirectoryLocation => _configurationSection.GetValue<string>("PickupDirectoryLocation");
|
||||
public SmtpDeliveryMethod DeliveryMethod => _configurationSection.GetValue<SmtpDeliveryMethod>("DeliveryMethod");
|
||||
|
||||
public string Username => _configurationSection.GetValue<string>("Username");
|
||||
|
||||
public string Password => _configurationSection.GetValue<string>("Password");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.HealthChecks;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class HealthChecksSettings : IHealthChecksSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "HealthChecks:";
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public HealthChecksSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public IEnumerable<IDisabledHealthCheck> DisabledChecks => _configuration
|
||||
.GetSection(Prefix+"DisabledChecks")
|
||||
.GetChildren()
|
||||
.Select(
|
||||
x => new DisabledHealthCheck
|
||||
{
|
||||
Id = x.GetValue<Guid>("Id"),
|
||||
DisabledOn = x.GetValue<DateTime>("DisabledOn"),
|
||||
DisabledBy = x.GetValue<int>("DisabledBy")
|
||||
});
|
||||
|
||||
public IHealthCheckNotificationSettings NotificationSettings =>
|
||||
new HealthCheckNotificationSettings(
|
||||
_configuration.GetSection(Prefix+"NotificationSettings"));
|
||||
|
||||
private class DisabledHealthCheck : IDisabledHealthCheck
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public DateTime DisabledOn { get; set; }
|
||||
public int DisabledBy { get; set; }
|
||||
}
|
||||
|
||||
private class HealthCheckNotificationSettings : IHealthCheckNotificationSettings
|
||||
{
|
||||
private readonly IConfigurationSection _configurationSection;
|
||||
|
||||
public HealthCheckNotificationSettings(IConfigurationSection configurationSection)
|
||||
{
|
||||
_configurationSection = configurationSection;
|
||||
}
|
||||
|
||||
public bool Enabled => _configurationSection.GetValue("Enabled", false);
|
||||
public string FirstRunTime => _configurationSection.GetValue<string>("FirstRunTime");
|
||||
public int PeriodInHours => _configurationSection.GetValue("PeriodInHours", 24);
|
||||
|
||||
public IReadOnlyDictionary<string, INotificationMethod> NotificationMethods => _configurationSection
|
||||
.GetSection("NotificationMethods")
|
||||
.GetChildren()
|
||||
.ToDictionary(x => x.Key, x => (INotificationMethod) new NotificationMethod(x.Key, x));
|
||||
|
||||
public IEnumerable<IDisabledHealthCheck> DisabledChecks => _configurationSection
|
||||
.GetSection("DisabledChecks").GetChildren().Select(
|
||||
x => new DisabledHealthCheck
|
||||
{
|
||||
Id = x.GetValue<Guid>("Id"),
|
||||
DisabledOn = x.GetValue<DateTime>("DisabledOn"),
|
||||
DisabledBy = x.GetValue<int>("DisabledBy")
|
||||
});
|
||||
}
|
||||
|
||||
private class NotificationMethod : INotificationMethod
|
||||
{
|
||||
private readonly IConfigurationSection _configurationSection;
|
||||
|
||||
public NotificationMethod(string alias, IConfigurationSection configurationSection)
|
||||
{
|
||||
Alias = alias;
|
||||
_configurationSection = configurationSection;
|
||||
}
|
||||
|
||||
public string Alias { get; }
|
||||
public bool Enabled => _configurationSection.GetValue("Enabled", false);
|
||||
|
||||
public HealthCheckNotificationVerbosity Verbosity =>
|
||||
_configurationSection.GetValue("Verbosity", HealthCheckNotificationVerbosity.Summary);
|
||||
|
||||
public bool FailureOnly => _configurationSection.GetValue("FailureOnly", true);
|
||||
|
||||
public IReadOnlyDictionary<string, INotificationMethodSettings> Settings => _configurationSection
|
||||
.GetSection("Settings").GetChildren().ToDictionary(x => x.Key,
|
||||
x => (INotificationMethodSettings) new NotificationMethodSettings(x.Key, x.Value));
|
||||
}
|
||||
|
||||
private class NotificationMethodSettings : INotificationMethodSettings
|
||||
{
|
||||
public NotificationMethodSettings(string key, string value)
|
||||
{
|
||||
Key = key;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public string Key { get; }
|
||||
public string Value { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class HostingSettings : IHostingSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "Hosting:";
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public HostingSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public LocalTempStorage LocalTempStorageLocation =>
|
||||
_configuration.GetValue(Prefix+"LocalTempStorage", LocalTempStorage.Default);
|
||||
|
||||
public string ApplicationVirtualPath => null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether umbraco is running in [debug mode].
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [debug mode]; otherwise, <c>false</c>.</value>
|
||||
public bool DebugMode => _configuration.GetValue(Prefix+"Debug", false);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class ImagingSettings : IImagingSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "Imaging:";
|
||||
private const string CachePrefix = Prefix + "Cache:";
|
||||
private const string ResizePrefix = Prefix + "Resize:";
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public ImagingSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public int MaxBrowserCacheDays => _configuration.GetValue(CachePrefix + "MaxBrowserCacheDays", 7);
|
||||
public int MaxCacheDays => _configuration.GetValue(CachePrefix + "MaxCacheDays", 365);
|
||||
public uint CachedNameLength => _configuration.GetValue(CachePrefix + "CachedNameLength", (uint) 8);
|
||||
public string CacheFolder => _configuration.GetValue(CachePrefix + "Folder", "../App_Data/Cache");
|
||||
public int MaxResizeWidth => _configuration.GetValue(ResizePrefix + "MaxWidth", 5000);
|
||||
public int MaxResizeHeight => _configuration.GetValue(ResizePrefix + "MaxHeight", 5000);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class IndexCreatorSettings : IIndexCreatorSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "Examine:";
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public IndexCreatorSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public string LuceneDirectoryFactory =>
|
||||
_configuration.GetValue<string>(Prefix + "LuceneDirectoryFactory");
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class KeepAliveSettings : IKeepAliveSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "KeepAlive:";
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public KeepAliveSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public bool DisableKeepAliveTask =>
|
||||
_configuration.GetValue(Prefix + "DisableKeepAliveTask", false);
|
||||
|
||||
public string KeepAlivePingUrl => _configuration.GetValue(Prefix + "KeepAlivePingUrl",
|
||||
"{umbracoApplicationUrl}/api/keepalive/ping");
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class LoggingSettings : ILoggingSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "Logging:";
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public LoggingSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public int MaxLogAge => _configuration.GetValue(Prefix + "MaxLogAge", -1);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class MemberPasswordConfigurationSettings : IMemberPasswordConfiguration
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigSecurityPrefix + "MemberPassword:";
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public MemberPasswordConfigurationSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public int RequiredLength =>
|
||||
_configuration.GetValue(Prefix + "RequiredLength", 10);
|
||||
|
||||
public bool RequireNonLetterOrDigit =>
|
||||
_configuration.GetValue(Prefix + "RequireNonLetterOrDigit", false);
|
||||
|
||||
public bool RequireDigit =>
|
||||
_configuration.GetValue(Prefix + "RequireDigit", false);
|
||||
|
||||
public bool RequireLowercase =>
|
||||
_configuration.GetValue(Prefix + "RequireLowercase", false);
|
||||
|
||||
public bool RequireUppercase =>
|
||||
_configuration.GetValue(Prefix + "RequireUppercase", false);
|
||||
|
||||
public string HashAlgorithmType =>
|
||||
_configuration.GetValue(Prefix + "HashAlgorithmType", "HMACSHA256");
|
||||
|
||||
public int MaxFailedAccessAttemptsBeforeLockout =>
|
||||
_configuration.GetValue(Prefix + "MaxFailedAccessAttemptsBeforeLockout", 5);
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the models builder configuration.
|
||||
/// </summary>
|
||||
internal class ModelsBuilderConfig : IModelsBuilderConfig
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigModelsBuilderPrefix;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ModelsBuilderConfig" /> class.
|
||||
/// </summary>
|
||||
public ModelsBuilderConfig(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public string DefaultModelsDirectory => "~/App_Data/Models";
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the whole models experience is enabled.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>If this is false then absolutely nothing happens.</para>
|
||||
/// <para>Default value is <c>false</c> which means that unless we have this setting, nothing happens.</para>
|
||||
/// </remarks>
|
||||
public bool Enable => _configuration.GetValue(Prefix+"Enable", false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the models mode.
|
||||
/// </summary>
|
||||
public ModelsMode ModelsMode =>
|
||||
_configuration.GetValue(Prefix+"ModelsMode", ModelsMode.Nothing);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the models namespace.
|
||||
/// </summary>
|
||||
/// <remarks>That value could be overriden by other (attribute in user's code...). Return default if no value was supplied.</remarks>
|
||||
public string ModelsNamespace => _configuration.GetValue<string>(Prefix+"ModelsNamespace");
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether we should enable the models factory.
|
||||
/// </summary>
|
||||
/// <remarks>Default value is <c>true</c> because no factory is enabled by default in Umbraco.</remarks>
|
||||
public bool EnableFactory => _configuration.GetValue(Prefix+"EnableFactory", true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether we should flag out-of-date models.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Models become out-of-date when data types or content types are updated. When this
|
||||
/// setting is activated the ~/App_Data/Models/ood.txt file is then created. When models are
|
||||
/// generated through the dashboard, the files is cleared. Default value is <c>false</c>.
|
||||
/// </remarks>
|
||||
public bool FlagOutOfDateModels =>
|
||||
_configuration.GetValue(Prefix+"FlagOutOfDateModels", false) && !ModelsMode.IsLive();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the models directory.
|
||||
/// </summary>
|
||||
/// <remarks>Default is ~/App_Data/Models but that can be changed.</remarks>
|
||||
public string ModelsDirectory =>
|
||||
_configuration.GetValue(Prefix+"ModelsDirectory", "~/App_Data/Models");
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether to accept an unsafe value for ModelsDirectory.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// An unsafe value is an absolute path, or a relative path pointing outside
|
||||
/// of the website root.
|
||||
/// </remarks>
|
||||
public bool AcceptUnsafeModelsDirectory =>
|
||||
_configuration.GetValue(Prefix+"AcceptUnsafeModelsDirectory", false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating the debug log level.
|
||||
/// </summary>
|
||||
/// <remarks>0 means minimal (safe on live site), anything else means more and more details (maybe not safe).</remarks>
|
||||
public int DebugLevel => _configuration.GetValue(Prefix+"DebugLevel", 0);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class NuCacheSettings : INuCacheSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "NuCache:";
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public NuCacheSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public string BTreeBlockSize => _configuration.GetValue<string>(Prefix+"BTreeBlockSize");
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class RequestHandlerSettings : IRequestHandlerSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "RequestHandler:";
|
||||
private static readonly CharItem[] DefaultCharCollection =
|
||||
{
|
||||
new CharItem { Char = " ", Replacement = "-" },
|
||||
new CharItem { Char = "\"", Replacement = "" },
|
||||
new CharItem { Char = "'", Replacement = "" },
|
||||
new CharItem { Char = "%", Replacement = "" },
|
||||
new CharItem { Char = ".", Replacement = "" },
|
||||
new CharItem { Char = ";", Replacement = "" },
|
||||
new CharItem { Char = "/", Replacement = "" },
|
||||
new CharItem { Char = "\\", Replacement = "" },
|
||||
new CharItem { Char = ":", Replacement = "" },
|
||||
new CharItem { Char = "#", Replacement = "" },
|
||||
new CharItem { Char = "+", Replacement = "plus" },
|
||||
new CharItem { Char = "*", Replacement = "star" },
|
||||
new CharItem { Char = "&", Replacement = "" },
|
||||
new CharItem { Char = "?", Replacement = "" },
|
||||
new CharItem { Char = "æ", Replacement = "ae" },
|
||||
new CharItem { Char = "ä", Replacement = "ae" },
|
||||
new CharItem { Char = "ø", Replacement = "oe" },
|
||||
new CharItem { Char = "ö", Replacement = "oe" },
|
||||
new CharItem { Char = "å", Replacement = "aa" },
|
||||
new CharItem { Char = "ü", Replacement = "ue" },
|
||||
new CharItem { Char = "ß", Replacement = "ss" },
|
||||
new CharItem { Char = "|", Replacement = "-" },
|
||||
new CharItem { Char = "<", Replacement = "" },
|
||||
new CharItem { Char = ">", Replacement = "" }
|
||||
};
|
||||
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public RequestHandlerSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public bool AddTrailingSlash =>
|
||||
_configuration.GetValue(Prefix+"AddTrailingSlash", true);
|
||||
|
||||
public bool ConvertUrlsToAscii => _configuration
|
||||
.GetValue<string>(Prefix+"ConvertUrlsToAscii").InvariantEquals("true");
|
||||
|
||||
public bool TryConvertUrlsToAscii => _configuration
|
||||
.GetValue<string>(Prefix+"ConvertUrlsToAscii").InvariantEquals("try");
|
||||
|
||||
|
||||
//We need to special handle ":", as this character is special in keys
|
||||
public IEnumerable<IChar> CharCollection
|
||||
{
|
||||
get
|
||||
{
|
||||
var collection = _configuration.GetSection(Prefix + "CharCollection").GetChildren()
|
||||
.Select(x => new CharItem()
|
||||
{
|
||||
Char = x.GetValue<string>("Char"),
|
||||
Replacement = x.GetValue<string>("Replacement"),
|
||||
}).ToArray();
|
||||
|
||||
if (collection.Any() || _configuration.GetSection("Prefix").GetChildren().Any(x =>
|
||||
x.Key.Equals("CharCollection", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return collection;
|
||||
}
|
||||
|
||||
return DefaultCharCollection;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class CharItem : IChar
|
||||
{
|
||||
public string Char { get; set; }
|
||||
public string Replacement { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class RuntimeSettings : IRuntimeSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "Runtime:";
|
||||
private readonly IConfiguration _configuration;
|
||||
public RuntimeSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public int? MaxQueryStringLength => _configuration.GetValue<int?>(Prefix+"MaxRequestLength");
|
||||
public int? MaxRequestLength => _configuration.GetValue<int?>(Prefix+"MaxRequestLength");
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class SecuritySettings : ISecuritySettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigSecurityPrefix;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public SecuritySettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public bool KeepUserLoggedIn => _configuration.GetValue(Prefix + "KeepUserLoggedIn", true);
|
||||
|
||||
public bool HideDisabledUsersInBackoffice =>
|
||||
_configuration.GetValue(Prefix + "HideDisabledUsersInBackoffice", false);
|
||||
|
||||
public bool AllowPasswordReset =>
|
||||
_configuration.GetValue(Prefix + "AllowPasswordResetAllowPasswordReset", true);
|
||||
|
||||
public string AuthCookieName =>
|
||||
_configuration.GetValue(Prefix + "AuthCookieName", "UMB_UCONTEXT");
|
||||
|
||||
public string AuthCookieDomain =>
|
||||
_configuration.GetValue<string>(Prefix + "AuthCookieDomain");
|
||||
|
||||
public bool UsernameIsEmail => _configuration.GetValue(Prefix + "UsernameIsEmail", true);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class TourSettings : ITourSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "Tours:";
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public TourSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public string Type { get; set; }
|
||||
|
||||
public bool EnableTours => _configuration.GetValue(Prefix+"EnableTours", true);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class TypeFinderSettings : ITypeFinderSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "TypeFinder:";
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public TypeFinderSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public string AssembliesAcceptingLoadExceptions =>
|
||||
_configuration.GetValue<string>(Prefix+"AssembliesAcceptingLoadExceptions");
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class UserPasswordConfigurationSettings : IUserPasswordConfiguration
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigSecurityPrefix + "UserPassword:";
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public UserPasswordConfigurationSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public int RequiredLength => _configuration.GetValue(Prefix + "RequiredLength", 10);
|
||||
|
||||
public bool RequireNonLetterOrDigit =>
|
||||
_configuration.GetValue(Prefix + "RequireNonLetterOrDigit", false);
|
||||
|
||||
public bool RequireDigit => _configuration.GetValue(Prefix + "RequireDigit", false);
|
||||
|
||||
public bool RequireLowercase =>
|
||||
_configuration.GetValue(Prefix + "RequireLowercase", false);
|
||||
|
||||
public bool RequireUppercase =>
|
||||
_configuration.GetValue(Prefix + "RequireUppercase", false);
|
||||
|
||||
public string HashAlgorithmType =>
|
||||
_configuration.GetValue(Prefix + "HashAlgorithmType", "HMACSHA256");
|
||||
|
||||
public int MaxFailedAccessAttemptsBeforeLockout =>
|
||||
_configuration.GetValue(Prefix + "MaxFailedAccessAttemptsBeforeLockout", 5);
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Configuration.Models
|
||||
{
|
||||
internal class WebRoutingSettings : IWebRoutingSettings
|
||||
{
|
||||
private const string Prefix = Constants.Configuration.ConfigPrefix + "WebRouting:";
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public WebRoutingSettings(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public bool TrySkipIisCustomErrors =>
|
||||
_configuration.GetValue(Prefix + "TrySkipIisCustomErrors", false);
|
||||
|
||||
public bool InternalRedirectPreservesTemplate =>
|
||||
_configuration.GetValue(Prefix + "InternalRedirectPreservesTemplate", false);
|
||||
|
||||
public bool DisableAlternativeTemplates =>
|
||||
_configuration.GetValue(Prefix + "DisableAlternativeTemplates", false);
|
||||
|
||||
public bool ValidateAlternativeTemplates =>
|
||||
_configuration.GetValue(Prefix + "ValidateAlternativeTemplates", false);
|
||||
|
||||
public bool DisableFindContentByIdPath =>
|
||||
_configuration.GetValue(Prefix + "DisableFindContentByIdPath", false);
|
||||
|
||||
public bool DisableRedirectUrlTracking =>
|
||||
_configuration.GetValue(Prefix + "DisableRedirectUrlTracking", false);
|
||||
|
||||
public string UrlProviderMode =>
|
||||
_configuration.GetValue(Prefix + "UrlProviderMode", UrlMode.Auto.ToString());
|
||||
|
||||
public string UmbracoApplicationUrl =>
|
||||
_configuration.GetValue<string>(Prefix + "UmbracoApplicationUrl");
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Umbraco Cms
|
||||
[assembly: InternalsVisibleTo("Umbraco.Tests")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Tests.Common")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Tests.Benchmarks")]
|
||||
|
||||
// Allow this to be mocked in our unit tests
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
||||
@@ -1,41 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<LangVersion>8</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="obj\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Remove="obj\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="obj\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_UnmanagedRegistrationCache Remove="obj\Umbraco.Configuration.csproj.UnmanagedRegistration.cache" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.2" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.6.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
|
||||
<_Parameter1>Umbraco.Tests.Integration</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,65 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using Umbraco.Core.Macros;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class ContentElement : UmbracoConfigurationElement, IContentSettings
|
||||
{
|
||||
private const string DefaultPreviewBadge = @"<div id=""umbracoPreviewBadge"" class=""umbraco-preview-badge""><span class=""umbraco-preview-badge__header"">Preview mode</span><a href=""{0}/preview/end?redir={1}"" class=""umbraco-preview-badge__end""><svg viewBox=""0 0 100 100"" xmlns=""http://www.w3.org/2000/svg""><title>Click to end</title><path d=""M5273.1 2400.1v-2c0-2.8-5-4-9.7-4s-9.7 1.3-9.7 4v2a7 7 0 002 4.9l5 4.9c.3.3.4.6.4 1v6.4c0 .4.2.7.6.8l2.9.9c.5.1 1-.2 1-.8v-7.2c0-.4.2-.7.4-1l5.1-5a7 7 0 002-4.9zm-9.7-.1c-4.8 0-7.4-1.3-7.5-1.8.1-.5 2.7-1.8 7.5-1.8s7.3 1.3 7.5 1.8c-.2.5-2.7 1.8-7.5 1.8z""/><path d=""M5268.4 2410.3c-.6 0-1 .4-1 1s.4 1 1 1h4.3c.6 0 1-.4 1-1s-.4-1-1-1h-4.3zM5272.7 2413.7h-4.3c-.6 0-1 .4-1 1s.4 1 1 1h4.3c.6 0 1-.4 1-1s-.4-1-1-1zM5272.7 2417h-4.3c-.6 0-1 .4-1 1s.4 1 1 1h4.3c.6 0 1-.4 1-1 0-.5-.4-1-1-1z""/><path d=""M78.2 13l-8.7 11.7a32.5 32.5 0 11-51.9 25.8c0-10.3 4.7-19.7 12.9-25.8L21.8 13a47 47 0 1056.4 0z""/><path d=""M42.7 2.5h14.6v49.4H42.7z""/></svg></a></div><style type=""text/css"">.umbraco-preview-badge {{position: absolute;top: 1em;right: 1em;display: inline-flex;background: #1b264f;color: #fff;padding: 1em;font-size: 12px;z-index: 99999999;justify-content: center;align-items: center;box-shadow: 0 10px 50px rgba(0, 0, 0, .1), 0 6px 20px rgba(0, 0, 0, .16);line-height: 1;}}.umbraco-preview-badge__header {{font-weight: bold;}}.umbraco-preview-badge__end {{width: 3em;padding: 1em;margin: -1em -1em -1em 2em;display: flex;flex-shrink: 0;align-items: center;align-self: stretch;}}.umbraco-preview-badge__end:hover,.umbraco-preview-badge__end:focus {{background: #f5c1bc;}}.umbraco-preview-badge__end svg {{fill: #fff;width:1em;}}</style>";
|
||||
|
||||
[ConfigurationProperty("imaging")]
|
||||
internal ContentImagingElement Imaging => (ContentImagingElement) this["imaging"];
|
||||
|
||||
[ConfigurationProperty("ResolveUrlsFromTextString")]
|
||||
internal InnerTextConfigurationElement<bool> ResolveUrlsFromTextString => GetOptionalTextElement("ResolveUrlsFromTextString", false);
|
||||
|
||||
public IEnumerable<IContentErrorPage> Error404Collection => Errors.Error404Collection;
|
||||
|
||||
[ConfigurationProperty("errors", IsRequired = true)]
|
||||
internal ContentErrorsElement Errors => (ContentErrorsElement) base["errors"];
|
||||
|
||||
[ConfigurationProperty("notifications", IsRequired = true)]
|
||||
internal NotificationsElement Notifications => (NotificationsElement) base["notifications"];
|
||||
|
||||
[ConfigurationProperty("PreviewBadge")]
|
||||
internal InnerTextConfigurationElement<string> PreviewBadge => GetOptionalTextElement("PreviewBadge", DefaultPreviewBadge);
|
||||
|
||||
[ConfigurationProperty("MacroErrors")]
|
||||
internal InnerTextConfigurationElement<MacroErrorBehaviour> MacroErrors => GetOptionalTextElement("MacroErrors", MacroErrorBehaviour.Inline);
|
||||
|
||||
[ConfigurationProperty("disallowedUploadFiles")]
|
||||
internal CommaDelimitedConfigurationElement DisallowedUploadFiles => GetOptionalDelimitedElement("disallowedUploadFiles", new[] {"ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd"});
|
||||
|
||||
[ConfigurationProperty("allowedUploadFiles")]
|
||||
internal CommaDelimitedConfigurationElement AllowedUploadFiles => GetOptionalDelimitedElement("allowedUploadFiles", new string[0]);
|
||||
|
||||
[ConfigurationProperty("showDeprecatedPropertyEditors")]
|
||||
internal InnerTextConfigurationElement<bool> ShowDeprecatedPropertyEditors => GetOptionalTextElement("showDeprecatedPropertyEditors", false);
|
||||
|
||||
[ConfigurationProperty("loginBackgroundImage")]
|
||||
internal InnerTextConfigurationElement<string> LoginBackgroundImage => GetOptionalTextElement("loginBackgroundImage", string.Empty);
|
||||
|
||||
string IContentSettings.NotificationEmailAddress => Notifications.NotificationEmailAddress;
|
||||
|
||||
bool IContentSettings.DisableHtmlEmail => Notifications.DisableHtmlEmail;
|
||||
|
||||
IEnumerable<string> IContentSettings.ImageFileTypes => Imaging.ImageFileTypes;
|
||||
|
||||
IEnumerable<IImagingAutoFillUploadField> IContentSettings.ImageAutoFillProperties => Imaging.ImageAutoFillProperties;
|
||||
|
||||
bool IContentSettings.ResolveUrlsFromTextString => ResolveUrlsFromTextString;
|
||||
|
||||
string IContentSettings.PreviewBadge => PreviewBadge;
|
||||
|
||||
MacroErrorBehaviour IContentSettings.MacroErrorBehaviour => MacroErrors;
|
||||
|
||||
IEnumerable<string> IContentSettings.DisallowedUploadFiles => DisallowedUploadFiles;
|
||||
|
||||
IEnumerable<string> IContentSettings.AllowedUploadFiles => AllowedUploadFiles;
|
||||
|
||||
bool IContentSettings.ShowDeprecatedPropertyEditors => ShowDeprecatedPropertyEditors;
|
||||
|
||||
string IContentSettings.LoginBackgroundImage => LoginBackgroundImage;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class KeepAliveElement : ConfigurationElement, IKeepAliveSettings
|
||||
{
|
||||
[ConfigurationProperty("disableKeepAliveTask", DefaultValue = "false")]
|
||||
public bool DisableKeepAliveTask => (bool)base["disableKeepAliveTask"];
|
||||
|
||||
[ConfigurationProperty("keepAlivePingUrl", DefaultValue = "{umbracoApplicationUrl}/api/keepalive/ping")]
|
||||
public string KeepAlivePingUrl => (string)base["keepAlivePingUrl"];
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class MemberPasswordConfigurationElement : PasswordConfigurationElement, IMemberPasswordConfiguration
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class PasswordConfigurationElement : UmbracoConfigurationElement
|
||||
{
|
||||
[ConfigurationProperty("requiredLength", DefaultValue = "12")]
|
||||
public int RequiredLength => (int)base["requiredLength"];
|
||||
|
||||
[ConfigurationProperty("requireNonLetterOrDigit", DefaultValue = "false")]
|
||||
public bool RequireNonLetterOrDigit => (bool)base["requireNonLetterOrDigit"];
|
||||
|
||||
[ConfigurationProperty("requireDigit", DefaultValue = "false")]
|
||||
public bool RequireDigit => (bool)base["requireDigit"];
|
||||
|
||||
[ConfigurationProperty("requireLowercase", DefaultValue = "false")]
|
||||
public bool RequireLowercase => (bool)base["requireLowercase"];
|
||||
|
||||
[ConfigurationProperty("requireUppercase", DefaultValue = "false")]
|
||||
public bool RequireUppercase => (bool)base["requireUppercase"];
|
||||
|
||||
[ConfigurationProperty("useLegacyEncoding", DefaultValue = "false")]
|
||||
public bool UseLegacyEncoding => (bool)base["useLegacyEncoding"];
|
||||
|
||||
[ConfigurationProperty("hashAlgorithmType", DefaultValue = "HMACSHA256")]
|
||||
public string HashAlgorithmType => (string)base["hashAlgorithmType"];
|
||||
|
||||
[ConfigurationProperty("maxFailedAccessAttemptsBeforeLockout", DefaultValue = "5")]
|
||||
public int MaxFailedAccessAttemptsBeforeLockout => (int)base["maxFailedAccessAttemptsBeforeLockout"];
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class UmbracoSettingsSection : ConfigurationSection
|
||||
{
|
||||
[ConfigurationProperty("backOffice")]
|
||||
public BackOfficeElement BackOffice => (BackOfficeElement)this["backOffice"];
|
||||
|
||||
[ConfigurationProperty("content")]
|
||||
public ContentElement Content => (ContentElement)this["content"];
|
||||
|
||||
[ConfigurationProperty("security")]
|
||||
public SecurityElement Security => (SecurityElement)this["security"];
|
||||
|
||||
[ConfigurationProperty("requestHandler")]
|
||||
public RequestHandlerElement RequestHandler => (RequestHandlerElement)this["requestHandler"];
|
||||
|
||||
[ConfigurationProperty("logging")]
|
||||
public LoggingElement Logging => (LoggingElement)this["logging"];
|
||||
|
||||
[ConfigurationProperty("web.routing")]
|
||||
public WebRoutingElement WebRouting => (WebRoutingElement)this["web.routing"];
|
||||
|
||||
[ConfigurationProperty("keepAlive")]
|
||||
internal KeepAliveElement KeepAlive => (KeepAliveElement)this["keepAlive"];
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
internal class UserPasswordConfigurationElement : PasswordConfigurationElement, IUserPasswordConfiguration
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,40 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static class AssemblyExtensions
|
||||
internal static class AssemblyExtensions
|
||||
{
|
||||
private static string _rootDir = "";
|
||||
|
||||
/// <summary>
|
||||
/// Utility method that returns the path to the root of the application, by getting the path to where the assembly where this
|
||||
/// method is included is present, then traversing until it's past the /bin directory. Ie. this makes it work
|
||||
/// even if the assembly is in a /bin/debug or /bin/release folder
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string GetRootDirectorySafe(this Assembly executingAssembly)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_rootDir) == false)
|
||||
{
|
||||
return _rootDir;
|
||||
}
|
||||
|
||||
var codeBase = executingAssembly.CodeBase;
|
||||
var uri = new Uri(codeBase);
|
||||
var path = uri.LocalPath;
|
||||
var baseDirectory = Path.GetDirectoryName(path);
|
||||
if (string.IsNullOrEmpty(baseDirectory))
|
||||
throw new Exception("No root directory could be resolved. Please ensure that your Umbraco solution is correctly configured.");
|
||||
|
||||
_rootDir = baseDirectory.Contains("bin")
|
||||
? baseDirectory.Substring(0, baseDirectory.LastIndexOf("bin", StringComparison.OrdinalIgnoreCase) - 1)
|
||||
: baseDirectory;
|
||||
|
||||
return _rootDir;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the file used to load the assembly
|
||||
/// </summary>
|
||||
|
||||
@@ -21,18 +21,18 @@ namespace Umbraco.Core
|
||||
// been closed, the Semaphore system object is destroyed - so in any case
|
||||
// an iisreset should clean up everything
|
||||
//
|
||||
public class SystemLock
|
||||
internal class AsyncLock
|
||||
{
|
||||
private readonly SemaphoreSlim _semaphore;
|
||||
private readonly Semaphore _semaphore2;
|
||||
private readonly IDisposable _releaser;
|
||||
private readonly Task<IDisposable> _releaserTask;
|
||||
|
||||
public SystemLock()
|
||||
: this(null)
|
||||
public AsyncLock()
|
||||
: this (null)
|
||||
{ }
|
||||
|
||||
public SystemLock(string name)
|
||||
public AsyncLock(string name)
|
||||
{
|
||||
// WaitOne() waits until count > 0 then decrements count
|
||||
// Release() increments count
|
||||
@@ -67,6 +67,35 @@ namespace Umbraco.Core
|
||||
: new NamedSemaphoreReleaser(_semaphore2);
|
||||
}
|
||||
|
||||
//NOTE: We don't use the "Async" part of this lock at all
|
||||
//TODO: Remove this and rename this class something like SystemWideLock, then we can re-instate this logic if we ever need an Async lock again
|
||||
|
||||
//public Task<IDisposable> LockAsync()
|
||||
//{
|
||||
// var wait = _semaphore != null
|
||||
// ? _semaphore.WaitAsync()
|
||||
// : _semaphore2.WaitOneAsync();
|
||||
|
||||
// return wait.IsCompleted
|
||||
// ? _releaserTask ?? Task.FromResult(CreateReleaser()) // anonymous vs named
|
||||
// : wait.ContinueWith((_, state) => (((AsyncLock) state).CreateReleaser()),
|
||||
// this, CancellationToken.None,
|
||||
// TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
|
||||
//}
|
||||
|
||||
//public Task<IDisposable> LockAsync(int millisecondsTimeout)
|
||||
//{
|
||||
// var wait = _semaphore != null
|
||||
// ? _semaphore.WaitAsync(millisecondsTimeout)
|
||||
// : _semaphore2.WaitOneAsync(millisecondsTimeout);
|
||||
|
||||
// return wait.IsCompleted
|
||||
// ? _releaserTask ?? Task.FromResult(CreateReleaser()) // anonymous vs named
|
||||
// : wait.ContinueWith((_, state) => (((AsyncLock)state).CreateReleaser()),
|
||||
// this, CancellationToken.None,
|
||||
// TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
|
||||
//}
|
||||
|
||||
public IDisposable Lock()
|
||||
{
|
||||
if (_semaphore != null)
|
||||
@@ -92,18 +121,14 @@ namespace Umbraco.Core
|
||||
private class NamedSemaphoreReleaser : CriticalFinalizerObject, IDisposable
|
||||
{
|
||||
private readonly Semaphore _semaphore;
|
||||
private GCHandle _handle;
|
||||
|
||||
internal NamedSemaphoreReleaser(Semaphore semaphore)
|
||||
{
|
||||
_semaphore = semaphore;
|
||||
_handle = GCHandle.Alloc(_semaphore);
|
||||
}
|
||||
|
||||
#region IDisposable Support
|
||||
|
||||
// This code added to correctly implement the disposable pattern.
|
||||
|
||||
private bool disposedValue = false; // To detect redundant calls
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
@@ -112,22 +137,10 @@ namespace Umbraco.Core
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
_semaphore.Release();
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
_semaphore.Dispose();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
disposedValue = true;
|
||||
}
|
||||
// critical
|
||||
_handle.Free();
|
||||
_semaphore.Release();
|
||||
_semaphore.Dispose();
|
||||
}
|
||||
|
||||
// we WANT to release the semaphore because it's a system object, ie a critical
|
||||
@@ -158,9 +171,6 @@ namespace Umbraco.Core
|
||||
// we do NOT want the finalizer to throw - never ever
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
private class SemaphoreSlimReleaser : IDisposable
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Web;
|
||||
using Umbraco.Core;
|
||||
|
||||
// no binding redirect for now = de-activate
|
||||
//[assembly: PreApplicationStartMethod(typeof(BindingRedirects), "Initialize")]
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages any assembly binding redirects that cannot be done via config (i.e. unsigned --> signed assemblies)
|
||||
/// </summary>
|
||||
public sealed class BindingRedirects
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
// this only gets called when an assembly can't be resolved
|
||||
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used to do an assembly binding redirect via code - normally required due to signature changes in assemblies
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||
{
|
||||
// When an assembly can't be resolved. In here we can do magic with the assembly name and try loading another.
|
||||
|
||||
// keep here for reference - we don't use AutoMapper
|
||||
/*
|
||||
//AutoMapper:
|
||||
// this is used for loading a signed assembly of AutoMapper (v. 3.1+) without having to recompile old code.
|
||||
// ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again
|
||||
// do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stackoverflow
|
||||
if (args.Name.StartsWith("AutoMapper") && args.Name.EndsWith("PublicKeyToken=null"))
|
||||
return Assembly.Load(args.Name.Replace(", PublicKeyToken=null", ", PublicKeyToken=be96cd2c38ef1005"));
|
||||
*/
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
@@ -14,9 +15,11 @@ namespace Umbraco.Core.Cache
|
||||
Func<T> getCacheItem,
|
||||
TimeSpan? timeout,
|
||||
bool isSliding = false,
|
||||
CacheItemPriority priority = CacheItemPriority.Normal,
|
||||
CacheItemRemovedCallback removedCallback = null,
|
||||
string[] dependentFiles = null)
|
||||
{
|
||||
var result = provider.Get(cacheKey, () => getCacheItem(), timeout, isSliding, dependentFiles);
|
||||
var result = provider.Get(cacheKey, () => getCacheItem(), timeout, isSliding, priority, removedCallback, dependentFiles);
|
||||
return result == null ? default(T) : result.TryConvertTo<T>().Result;
|
||||
}
|
||||
|
||||
@@ -25,9 +28,11 @@ namespace Umbraco.Core.Cache
|
||||
Func<T> getCacheItem,
|
||||
TimeSpan? timeout = null,
|
||||
bool isSliding = false,
|
||||
CacheItemPriority priority = CacheItemPriority.Normal,
|
||||
CacheItemRemovedCallback removedCallback = null,
|
||||
string[] dependentFiles = null)
|
||||
{
|
||||
provider.Insert(cacheKey, () => getCacheItem(), timeout, isSliding, dependentFiles);
|
||||
provider.Insert(cacheKey, () => getCacheItem(), timeout, isSliding, priority, removedCallback, dependentFiles);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> GetCacheItemsByKeySearch<T>(this IAppCache provider, string keyStartsWith)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
@@ -7,12 +8,29 @@ namespace Umbraco.Core.Cache
|
||||
/// </summary>
|
||||
public class AppCaches
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AppCaches"/> for use in a web application.
|
||||
/// </summary>
|
||||
public AppCaches()
|
||||
: this(HttpRuntime.Cache)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AppCaches"/> for use in a web application.
|
||||
/// </summary>
|
||||
public AppCaches(System.Web.Caching.Cache cache)
|
||||
: this(
|
||||
new WebCachingAppCache(cache),
|
||||
new HttpRequestAppCache(),
|
||||
new IsolatedCaches(t => new ObjectCacheAppCache()))
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AppCaches"/> with cache providers.
|
||||
/// </summary>
|
||||
public AppCaches(
|
||||
IAppPolicyCache runtimeCache,
|
||||
IRequestCache requestCache,
|
||||
IAppCache requestCache,
|
||||
IsolatedCaches isolatedCaches)
|
||||
{
|
||||
RuntimeCache = runtimeCache ?? throw new ArgumentNullException(nameof(runtimeCache));
|
||||
@@ -45,7 +63,7 @@ namespace Umbraco.Core.Cache
|
||||
/// <para>The per-request caches works on top of the current HttpContext items.</para>
|
||||
/// <para>Outside a web environment, the behavior of that cache is unspecified.</para>
|
||||
/// </remarks>
|
||||
public IRequestCache RequestCache { get; }
|
||||
public IAppCache RequestCache { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the runtime cache.
|
||||
|
||||
@@ -17,24 +17,24 @@ namespace Umbraco.Core.Cache
|
||||
/// <param name="cacheFactory"></param>
|
||||
protected AppPolicedCacheDictionary(Func<TKey, IAppPolicyCache> cacheFactory)
|
||||
{
|
||||
_cacheFactory = cacheFactory;
|
||||
CacheFactory = cacheFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the internal cache factory, for tests only!
|
||||
/// </summary>
|
||||
private readonly Func<TKey, IAppPolicyCache> _cacheFactory;
|
||||
internal readonly Func<TKey, IAppPolicyCache> CacheFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or creates a cache.
|
||||
/// </summary>
|
||||
public IAppPolicyCache GetOrCreate(TKey key)
|
||||
=> _caches.GetOrAdd(key, k => _cacheFactory(k));
|
||||
=> _caches.GetOrAdd(key, k => CacheFactory(k));
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get a cache.
|
||||
/// </summary>
|
||||
protected Attempt<IAppPolicyCache> Get(TKey key)
|
||||
public Attempt<IAppPolicyCache> Get(TKey key)
|
||||
=> _caches.TryGetValue(key, out var cache) ? Attempt.Succeed(cache) : Attempt.Fail<IAppPolicyCache>();
|
||||
|
||||
/// <summary>
|
||||
@@ -56,7 +56,7 @@ namespace Umbraco.Core.Cache
|
||||
/// <summary>
|
||||
/// Clears a cache.
|
||||
/// </summary>
|
||||
protected void ClearCache(TKey key)
|
||||
public void ClearCache(TKey key)
|
||||
{
|
||||
if (_caches.TryGetValue(key, out var cache))
|
||||
cache.Clear();
|
||||
@@ -71,4 +71,4 @@ namespace Umbraco.Core.Cache
|
||||
cache.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,5 @@
|
||||
public const string TemplateFrontEndCacheKey = "template";
|
||||
|
||||
public const string MacroContentCacheKey = "macroContent_"; // used in MacroRenderers
|
||||
public const string MacroFromAliasCacheKey = "macroFromAlias_";
|
||||
|
||||
public const string UserGroupGetByAliasCacheKeyPrefix = "UserGroupRepository_GetByAlias_";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Caching;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
|
||||
@@ -11,7 +12,7 @@ namespace Umbraco.Core.Cache
|
||||
/// instance, and ensuring that all inserts and returns are deep cloned copies of the cache item,
|
||||
/// when the item is deep-cloneable.
|
||||
/// </summary>
|
||||
public class DeepCloneAppCache : IAppPolicyCache
|
||||
internal class DeepCloneAppCache : IAppPolicyCache
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DeepCloneAppCache"/> class.
|
||||
@@ -29,7 +30,7 @@ namespace Umbraco.Core.Cache
|
||||
/// <summary>
|
||||
/// Gets the inner cache.
|
||||
/// </summary>
|
||||
private IAppPolicyCache InnerCache { get; }
|
||||
public IAppPolicyCache InnerCache { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public object Get(string key)
|
||||
@@ -43,7 +44,7 @@ namespace Umbraco.Core.Cache
|
||||
{
|
||||
var cached = InnerCache.Get(key, () =>
|
||||
{
|
||||
var result = SafeLazy.GetSafeLazy(factory);
|
||||
var result = FastDictionaryAppCacheBase.GetSafeLazy(factory);
|
||||
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
|
||||
// do not store null values (backward compat), clone / reset to go into the cache
|
||||
return value == null ? null : CheckCloneableAndTracksChanges(value);
|
||||
@@ -66,32 +67,32 @@ namespace Umbraco.Core.Cache
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public object Get(string key, Func<object> factory, TimeSpan? timeout, bool isSliding = false, string[] dependentFiles = null)
|
||||
public object Get(string key, Func<object> factory, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
var cached = InnerCache.Get(key, () =>
|
||||
{
|
||||
var result = SafeLazy.GetSafeLazy(factory);
|
||||
var result = FastDictionaryAppCacheBase.GetSafeLazy(factory);
|
||||
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
|
||||
// do not store null values (backward compat), clone / reset to go into the cache
|
||||
return value == null ? null : CheckCloneableAndTracksChanges(value);
|
||||
return value == null ? null : CheckCloneableAndTracksChanges(value);
|
||||
|
||||
// clone / reset to go into the cache
|
||||
}, timeout, isSliding, dependentFiles);
|
||||
}, timeout, isSliding, priority, removedCallback, dependentFiles);
|
||||
|
||||
// clone / reset to go into the cache
|
||||
return CheckCloneableAndTracksChanges(cached);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Insert(string key, Func<object> factory, TimeSpan? timeout = null, bool isSliding = false, string[] dependentFiles = null)
|
||||
public void Insert(string key, Func<object> factory, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
InnerCache.Insert(key, () =>
|
||||
{
|
||||
var result = SafeLazy.GetSafeLazy(factory);
|
||||
var result = FastDictionaryAppCacheBase.GetSafeLazy(factory);
|
||||
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
|
||||
// do not store null values (backward compat), clone / reset to go into the cache
|
||||
return value == null ? null : CheckCloneableAndTracksChanges(value);
|
||||
}, timeout, isSliding, dependentFiles);
|
||||
}, timeout, isSliding, priority, removedCallback, dependentFiles);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -107,9 +108,9 @@ namespace Umbraco.Core.Cache
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ClearOfType(Type type)
|
||||
public void ClearOfType(string typeName)
|
||||
{
|
||||
InnerCache.ClearOfType(type);
|
||||
InnerCache.ClearOfType(typeName);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ namespace Umbraco.Core.Cache
|
||||
/// <para>If options.GetAllCacheAllowZeroCount then a 'zero-count' array is cached when GetAll finds nothing.</para>
|
||||
/// <para>If options.GetAllCacheValidateCount then we check against the db when getting many entities.</para>
|
||||
/// </remarks>
|
||||
public class DefaultRepositoryCachePolicy<TEntity, TId> : RepositoryCachePolicyBase<TEntity, TId>
|
||||
internal class DefaultRepositoryCachePolicy<TEntity, TId> : RepositoryCachePolicyBase<TEntity, TId>
|
||||
where TEntity : class, IEntity
|
||||
{
|
||||
private static readonly TEntity[] EmptyEntities = new TEntity[0]; // const
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -9,39 +8,30 @@ namespace Umbraco.Core.Cache
|
||||
/// <summary>
|
||||
/// Implements <see cref="IAppCache"/> on top of a concurrent dictionary.
|
||||
/// </summary>
|
||||
public class DictionaryAppCache : IRequestCache
|
||||
public class DictionaryAppCache : IAppCache
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the internal items dictionary, for tests only!
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<string, object> _items = new ConcurrentDictionary<string, object>();
|
||||
|
||||
public int Count => _items.Count;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsAvailable => true;
|
||||
internal readonly ConcurrentDictionary<string, object> Items = new ConcurrentDictionary<string, object>();
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual object Get(string key)
|
||||
{
|
||||
return _items.TryGetValue(key, out var value) ? value : null;
|
||||
return Items.TryGetValue(key, out var value) ? value : null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual object Get(string key, Func<object> factory)
|
||||
{
|
||||
return _items.GetOrAdd(key, _ => factory());
|
||||
return Items.GetOrAdd(key, _ => factory());
|
||||
}
|
||||
|
||||
public bool Set(string key, object value) => _items.TryAdd(key, value);
|
||||
|
||||
public bool Remove(string key) => _items.TryRemove(key, out _);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IEnumerable<object> SearchByKey(string keyStartsWith)
|
||||
{
|
||||
var items = new List<object>();
|
||||
foreach (var (key, value) in _items)
|
||||
foreach (var (key, value) in Items)
|
||||
if (key.InvariantStartsWith(keyStartsWith))
|
||||
items.Add(value);
|
||||
return items;
|
||||
@@ -52,7 +42,7 @@ namespace Umbraco.Core.Cache
|
||||
{
|
||||
var compiled = new Regex(regex, RegexOptions.Compiled);
|
||||
var items = new List<object>();
|
||||
foreach (var (key, value) in _items)
|
||||
foreach (var (key, value) in Items)
|
||||
if (compiled.IsMatch(key))
|
||||
items.Add(value);
|
||||
return items;
|
||||
@@ -61,50 +51,46 @@ namespace Umbraco.Core.Cache
|
||||
/// <inheritdoc />
|
||||
public virtual void Clear()
|
||||
{
|
||||
_items.Clear();
|
||||
Items.Clear();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void Clear(string key)
|
||||
{
|
||||
_items.TryRemove(key, out _);
|
||||
Items.TryRemove(key, out _);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void ClearOfType(Type type)
|
||||
public virtual void ClearOfType(string typeName)
|
||||
{
|
||||
_items.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == type);
|
||||
Items.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType().ToString().InvariantEquals(typeName));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void ClearOfType<T>()
|
||||
{
|
||||
var typeOfT = typeof(T);
|
||||
ClearOfType(typeOfT);
|
||||
Items.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void ClearOfType<T>(Func<string, T, bool> predicate)
|
||||
{
|
||||
var typeOfT = typeof(T);
|
||||
_items.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT && predicate(kvp.Key, (T)kvp.Value));
|
||||
Items.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT && predicate(kvp.Key, (T)kvp.Value));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void ClearByKey(string keyStartsWith)
|
||||
{
|
||||
_items.RemoveAll(kvp => kvp.Key.InvariantStartsWith(keyStartsWith));
|
||||
Items.RemoveAll(kvp => kvp.Key.InvariantStartsWith(keyStartsWith));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void ClearByRegex(string regex)
|
||||
{
|
||||
var compiled = new Regex(regex, RegexOptions.Compiled);
|
||||
_items.RemoveAll(kvp => compiled.IsMatch(kvp.Key));
|
||||
Items.RemoveAll(kvp => compiled.IsMatch(kvp.Key));
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator() => _items.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,37 +10,34 @@ namespace Umbraco.Core.Cache
|
||||
/// <summary>
|
||||
/// Implements a fast <see cref="IAppCache"/> on top of a concurrent dictionary.
|
||||
/// </summary>
|
||||
public class FastDictionaryAppCache : IAppCache
|
||||
internal class FastDictionaryAppCache : IAppCache
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Gets the internal items dictionary, for tests only!
|
||||
/// </summary>
|
||||
private readonly ConcurrentDictionary<string, Lazy<object>> _items = new ConcurrentDictionary<string, Lazy<object>>();
|
||||
|
||||
public int Count => _items.Count;
|
||||
internal readonly ConcurrentDictionary<string, Lazy<object>> Items = new ConcurrentDictionary<string, Lazy<object>>();
|
||||
|
||||
/// <inheritdoc />
|
||||
public object Get(string cacheKey)
|
||||
{
|
||||
_items.TryGetValue(cacheKey, out var result); // else null
|
||||
return result == null ? null : SafeLazy.GetSafeLazyValue(result); // return exceptions as null
|
||||
Items.TryGetValue(cacheKey, out var result); // else null
|
||||
return result == null ? null : FastDictionaryAppCacheBase.GetSafeLazyValue(result); // return exceptions as null
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public object Get(string cacheKey, Func<object> getCacheItem)
|
||||
{
|
||||
var result = _items.GetOrAdd(cacheKey, k => SafeLazy.GetSafeLazy(getCacheItem));
|
||||
var result = Items.GetOrAdd(cacheKey, k => FastDictionaryAppCacheBase.GetSafeLazy(getCacheItem));
|
||||
|
||||
var value = result.Value; // will not throw (safe lazy)
|
||||
if (!(value is SafeLazy.ExceptionHolder eh))
|
||||
if (!(value is FastDictionaryAppCacheBase.ExceptionHolder eh))
|
||||
return value;
|
||||
|
||||
// and... it's in the cache anyway - so contrary to other cache providers,
|
||||
// which would trick with GetSafeLazyValue, we need to remove by ourselves,
|
||||
// in order NOT to cache exceptions
|
||||
|
||||
_items.TryRemove(cacheKey, out result);
|
||||
Items.TryRemove(cacheKey, out result);
|
||||
eh.Exception.Throw(); // throw once!
|
||||
return null; // never reached
|
||||
}
|
||||
@@ -48,9 +45,9 @@ namespace Umbraco.Core.Cache
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<object> SearchByKey(string keyStartsWith)
|
||||
{
|
||||
return _items
|
||||
return Items
|
||||
.Where(kvp => kvp.Key.InvariantStartsWith(keyStartsWith))
|
||||
.Select(kvp => SafeLazy.GetSafeLazyValue(kvp.Value))
|
||||
.Select(kvp => FastDictionaryAppCacheBase.GetSafeLazyValue(kvp.Value))
|
||||
.Where(x => x != null);
|
||||
}
|
||||
|
||||
@@ -58,43 +55,44 @@ namespace Umbraco.Core.Cache
|
||||
public IEnumerable<object> SearchByRegex(string regex)
|
||||
{
|
||||
var compiled = new Regex(regex, RegexOptions.Compiled);
|
||||
return _items
|
||||
return Items
|
||||
.Where(kvp => compiled.IsMatch(kvp.Key))
|
||||
.Select(kvp => SafeLazy.GetSafeLazyValue(kvp.Value))
|
||||
.Select(kvp => FastDictionaryAppCacheBase.GetSafeLazyValue(kvp.Value))
|
||||
.Where(x => x != null);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Clear()
|
||||
{
|
||||
_items.Clear();
|
||||
Items.Clear();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Clear(string key)
|
||||
{
|
||||
_items.TryRemove(key, out _);
|
||||
Items.TryRemove(key, out _);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ClearOfType(Type type)
|
||||
public void ClearOfType(string typeName)
|
||||
{
|
||||
var type = TypeFinder.GetTypeByName(typeName);
|
||||
if (type == null) return;
|
||||
var isInterface = type.IsInterface;
|
||||
|
||||
foreach (var kvp in _items
|
||||
foreach (var kvp in Items
|
||||
.Where(x =>
|
||||
{
|
||||
// entry.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = SafeLazy.GetSafeLazyValue(x.Value, true);
|
||||
var value = FastDictionaryAppCacheBase.GetSafeLazyValue(x.Value, true);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return value == null || (isInterface ? (type.IsInstanceOfType(value)) : (value.GetType() == type));
|
||||
}))
|
||||
_items.TryRemove(kvp.Key, out _);
|
||||
Items.TryRemove(kvp.Key, out _);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -103,20 +101,20 @@ namespace Umbraco.Core.Cache
|
||||
var typeOfT = typeof(T);
|
||||
var isInterface = typeOfT.IsInterface;
|
||||
|
||||
foreach (var kvp in _items
|
||||
foreach (var kvp in Items
|
||||
.Where(x =>
|
||||
{
|
||||
// entry.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// compare on exact type, don't use "is"
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = SafeLazy.GetSafeLazyValue(x.Value, true);
|
||||
var value = FastDictionaryAppCacheBase.GetSafeLazyValue(x.Value, true);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return value == null || (isInterface ? (value is T) : (value.GetType() == typeOfT));
|
||||
}))
|
||||
_items.TryRemove(kvp.Key, out _);
|
||||
Items.TryRemove(kvp.Key, out _);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -125,14 +123,14 @@ namespace Umbraco.Core.Cache
|
||||
var typeOfT = typeof(T);
|
||||
var isInterface = typeOfT.IsInterface;
|
||||
|
||||
foreach (var kvp in _items
|
||||
foreach (var kvp in Items
|
||||
.Where(x =>
|
||||
{
|
||||
// entry.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// compare on exact type, don't use "is"
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = SafeLazy.GetSafeLazyValue(x.Value, true);
|
||||
var value = FastDictionaryAppCacheBase.GetSafeLazyValue(x.Value, true);
|
||||
if (value == null) return true;
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
@@ -141,24 +139,24 @@ namespace Umbraco.Core.Cache
|
||||
// run predicate on the 'public key' part only, ie without prefix
|
||||
&& predicate(x.Key, (T)value);
|
||||
}))
|
||||
_items.TryRemove(kvp.Key, out _);
|
||||
Items.TryRemove(kvp.Key, out _);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ClearByKey(string keyStartsWith)
|
||||
{
|
||||
foreach (var ikvp in _items
|
||||
foreach (var ikvp in Items
|
||||
.Where(kvp => kvp.Key.InvariantStartsWith(keyStartsWith)))
|
||||
_items.TryRemove(ikvp.Key, out _);
|
||||
Items.TryRemove(ikvp.Key, out _);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ClearByRegex(string regex)
|
||||
{
|
||||
var compiled = new Regex(regex, RegexOptions.Compiled);
|
||||
foreach (var ikvp in _items
|
||||
foreach (var ikvp in Items
|
||||
.Where(kvp => compiled.IsMatch(kvp.Key)))
|
||||
_items.TryRemove(ikvp.Key, out _);
|
||||
Items.TryRemove(ikvp.Key, out _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
@@ -10,11 +11,14 @@ namespace Umbraco.Core.Cache
|
||||
/// <summary>
|
||||
/// Provides a base class to fast, dictionary-based <see cref="IAppCache"/> implementations.
|
||||
/// </summary>
|
||||
public abstract class FastDictionaryAppCacheBase : IAppCache
|
||||
internal abstract class FastDictionaryAppCacheBase : IAppCache
|
||||
{
|
||||
// prefix cache keys so we know which one are ours
|
||||
protected const string CacheItemPrefix = "umbrtmche";
|
||||
|
||||
// an object that represent a value that has not been created yet
|
||||
protected internal static readonly object ValueNotCreated = new object();
|
||||
|
||||
#region IAppCache
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -31,7 +35,7 @@ namespace Umbraco.Core.Cache
|
||||
{
|
||||
ExitReadLock();
|
||||
}
|
||||
return result == null ? null : SafeLazy.GetSafeLazyValue(result); // return exceptions as null
|
||||
return result == null ? null : GetSafeLazyValue(result); // return exceptions as null
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -55,7 +59,7 @@ namespace Umbraco.Core.Cache
|
||||
}
|
||||
|
||||
return entries
|
||||
.Select(x => SafeLazy.GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
|
||||
.Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
|
||||
.Where(x => x != null); // backward compat, don't store null values in the cache
|
||||
}
|
||||
|
||||
@@ -78,7 +82,7 @@ namespace Umbraco.Core.Cache
|
||||
ExitReadLock();
|
||||
}
|
||||
return entries
|
||||
.Select(x => SafeLazy.GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
|
||||
.Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
|
||||
.Where(x => x != null); // backward compatible, don't store null values in the cache
|
||||
}
|
||||
|
||||
@@ -114,8 +118,9 @@ namespace Umbraco.Core.Cache
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void ClearOfType(Type type)
|
||||
public virtual void ClearOfType(string typeName)
|
||||
{
|
||||
var type = TypeFinder.GetTypeByName(typeName);
|
||||
if (type == null) return;
|
||||
var isInterface = type.IsInterface;
|
||||
try
|
||||
@@ -127,7 +132,7 @@ namespace Umbraco.Core.Cache
|
||||
// entry.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = SafeLazy.GetSafeLazyValue((Lazy<object>) x.Value, true);
|
||||
var value = GetSafeLazyValue((Lazy<object>) x.Value, true);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
@@ -157,7 +162,7 @@ namespace Umbraco.Core.Cache
|
||||
// remove null values as well, does not hurt
|
||||
// compare on exact type, don't use "is"
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = SafeLazy.GetSafeLazyValue((Lazy<object>) x.Value, true);
|
||||
var value = GetSafeLazyValue((Lazy<object>) x.Value, true);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
@@ -188,7 +193,7 @@ namespace Umbraco.Core.Cache
|
||||
// remove null values as well, does not hurt
|
||||
// compare on exact type, don't use "is"
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = SafeLazy.GetSafeLazyValue((Lazy<object>) x.Value, true);
|
||||
var value = GetSafeLazyValue((Lazy<object>) x.Value, true);
|
||||
if (value == null) return true;
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
@@ -267,7 +272,57 @@ namespace Umbraco.Core.Cache
|
||||
return $"{CacheItemPrefix}-{key}";
|
||||
}
|
||||
|
||||
protected internal static Lazy<object> GetSafeLazy(Func<object> getCacheItem)
|
||||
{
|
||||
// try to generate the value and if it fails,
|
||||
// wrap in an ExceptionHolder - would be much simpler
|
||||
// to just use lazy.IsValueFaulted alas that field is
|
||||
// internal
|
||||
return new Lazy<object>(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return getCacheItem();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return new ExceptionHolder(ExceptionDispatchInfo.Capture(e));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected internal static object GetSafeLazyValue(Lazy<object> lazy, bool onlyIfValueIsCreated = false)
|
||||
{
|
||||
// if onlyIfValueIsCreated, do not trigger value creation
|
||||
// must return something, though, to differentiate from null values
|
||||
if (onlyIfValueIsCreated && lazy.IsValueCreated == false) return ValueNotCreated;
|
||||
|
||||
// if execution has thrown then lazy.IsValueCreated is false
|
||||
// and lazy.IsValueFaulted is true (but internal) so we use our
|
||||
// own exception holder (see Lazy<T> source code) to return null
|
||||
if (lazy.Value is ExceptionHolder) return null;
|
||||
|
||||
// we have a value and execution has not thrown so returning
|
||||
// here does not throw - unless we're re-entering, take care of it
|
||||
try
|
||||
{
|
||||
return lazy.Value;
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
throw new InvalidOperationException("The method that computes a value for the cache has tried to read that value from the cache.", e);
|
||||
}
|
||||
}
|
||||
|
||||
internal class ExceptionHolder
|
||||
{
|
||||
public ExceptionHolder(ExceptionDispatchInfo e)
|
||||
{
|
||||
Exception = e;
|
||||
}
|
||||
|
||||
public ExceptionDispatchInfo Exception { get; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a fast <see cref="IAppCache"/> on top of HttpContext.Items.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>If no current HttpContext items can be found (no current HttpContext,
|
||||
/// or no Items...) then this cache acts as a pass-through and does not cache
|
||||
/// anything.</para>
|
||||
/// </remarks>
|
||||
public class GenericDictionaryRequestAppCache : FastDictionaryAppCacheBase, IRequestCache
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HttpRequestAppCache"/> class with a context, for unit tests!
|
||||
/// </summary>
|
||||
public GenericDictionaryRequestAppCache(Func<IDictionary<object, object>> requestItems) : base()
|
||||
{
|
||||
ContextItems = requestItems;
|
||||
}
|
||||
|
||||
private Func<IDictionary<object, object>> ContextItems { get; }
|
||||
|
||||
public bool IsAvailable => TryGetContextItems(out _);
|
||||
|
||||
private bool TryGetContextItems(out IDictionary<object, object> items)
|
||||
{
|
||||
items = ContextItems?.Invoke();
|
||||
return items != null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object Get(string key, Func<object> factory)
|
||||
{
|
||||
//no place to cache so just return the callback result
|
||||
if (!TryGetContextItems(out var items)) return factory();
|
||||
|
||||
key = GetCacheKey(key);
|
||||
|
||||
Lazy<object> result;
|
||||
|
||||
try
|
||||
{
|
||||
EnterWriteLock();
|
||||
result = items[key] as Lazy<object>; // null if key not found
|
||||
|
||||
// cannot create value within the lock, so if result.IsValueCreated is false, just
|
||||
// do nothing here - means that if creation throws, a race condition could cause
|
||||
// more than one thread to reach the return statement below and throw - accepted.
|
||||
|
||||
if (result == null || SafeLazy.GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
|
||||
{
|
||||
result = SafeLazy.GetSafeLazy(factory);
|
||||
items[key] = result;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitWriteLock();
|
||||
}
|
||||
|
||||
// using GetSafeLazy and GetSafeLazyValue ensures that we don't cache
|
||||
// exceptions (but try again and again) and silently eat them - however at
|
||||
// some point we have to report them - so need to re-throw here
|
||||
|
||||
// this does not throw anymore
|
||||
//return result.Value;
|
||||
|
||||
var value = result.Value; // will not throw (safe lazy)
|
||||
if (value is SafeLazy.ExceptionHolder eh) eh.Exception.Throw(); // throw once!
|
||||
return value;
|
||||
}
|
||||
|
||||
public bool Set(string key, object value)
|
||||
{
|
||||
//no place to cache so just return the callback result
|
||||
if (!TryGetContextItems(out var items)) return false;
|
||||
key = GetCacheKey(key);
|
||||
try
|
||||
{
|
||||
|
||||
EnterWriteLock();
|
||||
items[key] = SafeLazy.GetSafeLazy(() => value);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitWriteLock();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
//no place to cache so just return the callback result
|
||||
if (!TryGetContextItems(out var items)) return false;
|
||||
key = GetCacheKey(key);
|
||||
try
|
||||
{
|
||||
|
||||
EnterWriteLock();
|
||||
items.Remove(key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitWriteLock();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#region Entries
|
||||
|
||||
protected override IEnumerable<DictionaryEntry> GetDictionaryEntries()
|
||||
{
|
||||
const string prefix = CacheItemPrefix + "-";
|
||||
|
||||
if (!TryGetContextItems(out var items)) return Enumerable.Empty<DictionaryEntry>();
|
||||
|
||||
return items.Cast<DictionaryEntry>()
|
||||
.Where(x => x.Key is string s && s.StartsWith(prefix));
|
||||
}
|
||||
|
||||
protected override void RemoveEntry(string key)
|
||||
{
|
||||
if (!TryGetContextItems(out var items)) return;
|
||||
|
||||
items.Remove(key);
|
||||
}
|
||||
|
||||
protected override object GetEntry(string key)
|
||||
{
|
||||
return !TryGetContextItems(out var items) ? null : items[key];
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lock
|
||||
|
||||
private const string ContextItemsLockKey = "Umbraco.Core.Cache.HttpRequestCache::LockEntered";
|
||||
|
||||
protected override void EnterReadLock() => EnterWriteLock();
|
||||
|
||||
protected override void EnterWriteLock()
|
||||
{
|
||||
if (!TryGetContextItems(out var items)) return;
|
||||
|
||||
// note: cannot keep 'entered' as a class variable here,
|
||||
// since there is one per request - so storing it within
|
||||
// ContextItems - which is locked, so this should be safe
|
||||
|
||||
var entered = false;
|
||||
Monitor.Enter(items, ref entered);
|
||||
items[ContextItemsLockKey] = entered;
|
||||
}
|
||||
|
||||
protected override void ExitReadLock() => ExitWriteLock();
|
||||
|
||||
protected override void ExitWriteLock()
|
||||
{
|
||||
if (!TryGetContextItems(out var items)) return;
|
||||
|
||||
var entered = (bool?)items[ContextItemsLockKey] ?? false;
|
||||
if (entered)
|
||||
Monitor.Exit(items);
|
||||
items.Remove(ContextItemsLockKey);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||
{
|
||||
if (!TryGetContextItems(out var items))
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
yield return new KeyValuePair<string, object>(item.Key.ToString(), item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Composing;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
@@ -15,31 +15,37 @@ namespace Umbraco.Core.Cache
|
||||
/// or no Items...) then this cache acts as a pass-through and does not cache
|
||||
/// anything.</para>
|
||||
/// </remarks>
|
||||
public class HttpRequestAppCache : FastDictionaryAppCacheBase, IRequestCache
|
||||
internal class HttpRequestAppCache : FastDictionaryAppCacheBase
|
||||
{
|
||||
private readonly HttpContextBase _context;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HttpRequestAppCache"/> class with a context, for unit tests!
|
||||
/// </summary>
|
||||
public HttpRequestAppCache(Func<IDictionary> requestItems) : base()
|
||||
public HttpRequestAppCache(HttpContextBase context)
|
||||
{
|
||||
ContextItems = requestItems;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
private Func<IDictionary> ContextItems { get; }
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HttpRequestAppCache"/> class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Will use HttpContext.Current.</para>
|
||||
/// TODO: https://github.com/umbraco/Umbraco-CMS/issues/4239 - use IHttpContextAccessor NOT HttpContext.Current
|
||||
/// </remarks>
|
||||
public HttpRequestAppCache()
|
||||
{ }
|
||||
|
||||
public bool IsAvailable => TryGetContextItems(out _);
|
||||
private IDictionary ContextItems => _context?.Items ?? HttpContext.Current?.Items;
|
||||
|
||||
private bool TryGetContextItems(out IDictionary items)
|
||||
{
|
||||
items = ContextItems?.Invoke();
|
||||
return items != null;
|
||||
}
|
||||
private bool HasContextItems => _context?.Items != null || HttpContext.Current != null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object Get(string key, Func<object> factory)
|
||||
{
|
||||
//no place to cache so just return the callback result
|
||||
if (!TryGetContextItems(out var items)) return factory();
|
||||
if (HasContextItems == false) return factory();
|
||||
|
||||
key = GetCacheKey(key);
|
||||
|
||||
@@ -48,16 +54,16 @@ namespace Umbraco.Core.Cache
|
||||
try
|
||||
{
|
||||
EnterWriteLock();
|
||||
result = items[key] as Lazy<object>; // null if key not found
|
||||
result = ContextItems[key] as Lazy<object>; // null if key not found
|
||||
|
||||
// cannot create value within the lock, so if result.IsValueCreated is false, just
|
||||
// do nothing here - means that if creation throws, a race condition could cause
|
||||
// more than one thread to reach the return statement below and throw - accepted.
|
||||
|
||||
if (result == null || SafeLazy.GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
|
||||
if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
|
||||
{
|
||||
result = SafeLazy.GetSafeLazy(factory);
|
||||
items[key] = result;
|
||||
result = GetSafeLazy(factory);
|
||||
ContextItems[key] = result;
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -73,68 +79,32 @@ namespace Umbraco.Core.Cache
|
||||
//return result.Value;
|
||||
|
||||
var value = result.Value; // will not throw (safe lazy)
|
||||
if (value is SafeLazy.ExceptionHolder eh) eh.Exception.Throw(); // throw once!
|
||||
if (value is ExceptionHolder eh) eh.Exception.Throw(); // throw once!
|
||||
return value;
|
||||
}
|
||||
|
||||
public bool Set(string key, object value)
|
||||
{
|
||||
//no place to cache so just return the callback result
|
||||
if (!TryGetContextItems(out var items)) return false;
|
||||
key = GetCacheKey(key);
|
||||
try
|
||||
{
|
||||
|
||||
EnterWriteLock();
|
||||
items[key] = SafeLazy.GetSafeLazy(() => value);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitWriteLock();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
//no place to cache so just return the callback result
|
||||
if (!TryGetContextItems(out var items)) return false;
|
||||
key = GetCacheKey(key);
|
||||
try
|
||||
{
|
||||
|
||||
EnterWriteLock();
|
||||
items.Remove(key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitWriteLock();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#region Entries
|
||||
|
||||
protected override IEnumerable<DictionaryEntry> GetDictionaryEntries()
|
||||
{
|
||||
const string prefix = CacheItemPrefix + "-";
|
||||
|
||||
if (!TryGetContextItems(out var items)) return Enumerable.Empty<DictionaryEntry>();
|
||||
if (HasContextItems == false) return Enumerable.Empty<DictionaryEntry>();
|
||||
|
||||
return items.Cast<DictionaryEntry>()
|
||||
return ContextItems.Cast<DictionaryEntry>()
|
||||
.Where(x => x.Key is string s && s.StartsWith(prefix));
|
||||
}
|
||||
|
||||
protected override void RemoveEntry(string key)
|
||||
{
|
||||
if (!TryGetContextItems(out var items)) return;
|
||||
if (HasContextItems == false) return;
|
||||
|
||||
items.Remove(key);
|
||||
ContextItems.Remove(key);
|
||||
}
|
||||
|
||||
protected override object GetEntry(string key)
|
||||
{
|
||||
return !TryGetContextItems(out var items) ? null : items[key];
|
||||
return HasContextItems ? ContextItems[key] : null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -147,44 +117,28 @@ namespace Umbraco.Core.Cache
|
||||
|
||||
protected override void EnterWriteLock()
|
||||
{
|
||||
if (!TryGetContextItems(out var items)) return;
|
||||
if (HasContextItems)
|
||||
{
|
||||
// note: cannot keep 'entered' as a class variable here,
|
||||
// since there is one per request - so storing it within
|
||||
// ContextItems - which is locked, so this should be safe
|
||||
|
||||
// note: cannot keep 'entered' as a class variable here,
|
||||
// since there is one per request - so storing it within
|
||||
// ContextItems - which is locked, so this should be safe
|
||||
|
||||
var entered = false;
|
||||
Monitor.Enter(items.SyncRoot, ref entered);
|
||||
items[ContextItemsLockKey] = entered;
|
||||
var entered = false;
|
||||
Monitor.Enter(ContextItems.SyncRoot, ref entered);
|
||||
ContextItems[ContextItemsLockKey] = entered;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ExitReadLock() => ExitWriteLock();
|
||||
|
||||
protected override void ExitWriteLock()
|
||||
{
|
||||
if (!TryGetContextItems(out var items)) return;
|
||||
|
||||
var entered = (bool?)items[ContextItemsLockKey] ?? false;
|
||||
var entered = (bool?) ContextItems[ContextItemsLockKey] ?? false;
|
||||
if (entered)
|
||||
Monitor.Exit(items.SyncRoot);
|
||||
items.Remove(ContextItemsLockKey);
|
||||
Monitor.Exit(ContextItems.SyncRoot);
|
||||
ContextItems.Remove(ContextItemsLockKey);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||
{
|
||||
if (!TryGetContextItems(out var items))
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
foreach (DictionaryEntry item in items)
|
||||
{
|
||||
yield return new KeyValuePair<string, object>(item.Key.ToString(), item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,14 +51,14 @@ namespace Umbraco.Core.Cache
|
||||
/// <summary>
|
||||
/// Removes items of a specified type from the cache.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to remove.</param>
|
||||
/// <param name="typeName">The name of the type to remove.</param>
|
||||
/// <remarks>
|
||||
/// <para>If the type is an interface, then all items of a type implementing that interface are
|
||||
/// removed. Otherwise, only items of that exact type are removed (items of type inheriting from
|
||||
/// the specified type are not removed).</para>
|
||||
/// <para>Performs a case-sensitive search.</para>
|
||||
/// </remarks>
|
||||
void ClearOfType(Type type);
|
||||
void ClearOfType(string typeName);
|
||||
|
||||
/// <summary>
|
||||
/// Removes items of a specified type from the cache.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
@@ -16,6 +17,8 @@ namespace Umbraco.Core.Cache
|
||||
/// <param name="factory">A factory function that can create the item.</param>
|
||||
/// <param name="timeout">An optional cache timeout.</param>
|
||||
/// <param name="isSliding">An optional value indicating whether the cache timeout is sliding (default is false).</param>
|
||||
/// <param name="priority">An optional cache priority (default is Normal).</param>
|
||||
/// <param name="removedCallback">An optional callback to handle removals.</param>
|
||||
/// <param name="dependentFiles">Files the cache entry depends on.</param>
|
||||
/// <returns>The item.</returns>
|
||||
object Get(
|
||||
@@ -23,6 +26,8 @@ namespace Umbraco.Core.Cache
|
||||
Func<object> factory,
|
||||
TimeSpan? timeout,
|
||||
bool isSliding = false,
|
||||
CacheItemPriority priority = CacheItemPriority.Normal,
|
||||
CacheItemRemovedCallback removedCallback = null,
|
||||
string[] dependentFiles = null);
|
||||
|
||||
/// <summary>
|
||||
@@ -32,12 +37,16 @@ namespace Umbraco.Core.Cache
|
||||
/// <param name="factory">A factory function that can create the item.</param>
|
||||
/// <param name="timeout">An optional cache timeout.</param>
|
||||
/// <param name="isSliding">An optional value indicating whether the cache timeout is sliding (default is false).</param>
|
||||
/// <param name="priority">An optional cache priority (default is Normal).</param>
|
||||
/// <param name="removedCallback">An optional callback to handle removals.</param>
|
||||
/// <param name="dependentFiles">Files the cache entry depends on.</param>
|
||||
void Insert(
|
||||
string key,
|
||||
Func<object> factory,
|
||||
TimeSpan? timeout = null,
|
||||
bool isSliding = false,
|
||||
CacheItemPriority priority = CacheItemPriority.Normal,
|
||||
CacheItemRemovedCallback removedCallback = null,
|
||||
string[] dependentFiles = null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Umbraco.Core.Cache
|
||||
/// This is much better for performance when we're not running in a load balanced environment so we can refresh the cache
|
||||
/// against a already resolved object instead of looking the object back up by id.
|
||||
/// </remarks>
|
||||
public interface ICacheRefresher<T> : ICacheRefresher
|
||||
interface ICacheRefresher<T> : ICacheRefresher
|
||||
{
|
||||
void Refresh(T instance);
|
||||
void Remove(T instance);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/// <summary>
|
||||
/// A cache refresher that supports refreshing or removing cache based on a custom Json payload
|
||||
/// </summary>
|
||||
public interface IJsonCacheRefresher : ICacheRefresher
|
||||
interface IJsonCacheRefresher : ICacheRefresher
|
||||
{
|
||||
/// <summary>
|
||||
/// Refreshes, clears, etc... any cache based on the information provided in the json
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/// <summary>
|
||||
/// A cache refresher that supports refreshing cache based on a custom payload
|
||||
/// </summary>
|
||||
public interface IPayloadCacheRefresher<TPayload> : IJsonCacheRefresher
|
||||
interface IPayloadCacheRefresher<TPayload> : IJsonCacheRefresher
|
||||
{
|
||||
/// <summary>
|
||||
/// Refreshes, clears, etc... any cache based on the information provided in the payload
|
||||
|
||||
@@ -5,7 +5,7 @@ using Umbraco.Core.Scoping;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
public interface IRepositoryCachePolicy<TEntity, TId>
|
||||
internal interface IRepositoryCachePolicy<TEntity, TId>
|
||||
where TEntity : class, IEntity
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
public interface IRequestCache : IAppCache, IEnumerable<KeyValuePair<string, object>>
|
||||
{
|
||||
bool Set(string key, object value);
|
||||
bool Remove(string key);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the request cache is available otherwise false
|
||||
/// </summary>
|
||||
bool IsAvailable { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Umbraco.Core.Serialization;
|
||||
using Umbraco.Core.Sync;
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
@@ -8,19 +7,15 @@ namespace Umbraco.Core.Cache
|
||||
/// </summary>
|
||||
/// <typeparam name="TInstanceType">The actual cache refresher type.</typeparam>
|
||||
/// <remarks>The actual cache refresher type is used for strongly typed events.</remarks>
|
||||
public abstract class JsonCacheRefresherBase<TInstanceType, TJsonPayload> : CacheRefresherBase<TInstanceType>, IJsonCacheRefresher
|
||||
public abstract class JsonCacheRefresherBase<TInstanceType> : CacheRefresherBase<TInstanceType>, IJsonCacheRefresher
|
||||
where TInstanceType : class, ICacheRefresher
|
||||
{
|
||||
protected IJsonSerializer JsonSerializer { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonCacheRefresherBase{TInstanceType}"/>.
|
||||
/// </summary>
|
||||
/// <param name="appCaches">A cache helper.</param>
|
||||
protected JsonCacheRefresherBase(AppCaches appCaches, IJsonSerializer jsonSerializer) : base(appCaches)
|
||||
{
|
||||
JsonSerializer = jsonSerializer;
|
||||
}
|
||||
protected JsonCacheRefresherBase(AppCaches appCaches) : base(appCaches)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes as specified by a json payload.
|
||||
@@ -30,24 +25,5 @@ namespace Umbraco.Core.Cache
|
||||
{
|
||||
OnCacheUpdated(This, new CacheRefresherEventArgs(json, MessageType.RefreshByJson));
|
||||
}
|
||||
|
||||
#region Json
|
||||
/// <summary>
|
||||
/// Deserializes a json payload into an object payload.
|
||||
/// </summary>
|
||||
/// <param name="json">The json payload.</param>
|
||||
/// <returns>The deserialized object payload.</returns>
|
||||
public TJsonPayload[] Deserialize(string json)
|
||||
{
|
||||
return JsonSerializer.Deserialize<TJsonPayload[]>(json);
|
||||
}
|
||||
|
||||
|
||||
public string Serialize(params TJsonPayload[] jsonPayloads)
|
||||
{
|
||||
return JsonSerializer.Serialize(jsonPayloads);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Serialization;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Changes;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using static Umbraco.Web.Cache.LanguageCacheRefresher.JsonPayload;
|
||||
|
||||
namespace Umbraco.Web.Cache
|
||||
{
|
||||
public sealed class LanguageCacheRefresher : PayloadCacheRefresherBase<LanguageCacheRefresher, LanguageCacheRefresher.JsonPayload>
|
||||
{
|
||||
public LanguageCacheRefresher(AppCaches appCaches, IJsonSerializer serializer, IPublishedSnapshotService publishedSnapshotService)
|
||||
: base(appCaches, serializer)
|
||||
{
|
||||
_publishedSnapshotService = publishedSnapshotService;
|
||||
}
|
||||
|
||||
#region Define
|
||||
|
||||
protected override LanguageCacheRefresher This => this;
|
||||
|
||||
public static readonly Guid UniqueId = Guid.Parse("3E0F95D8-0BE5-44B8-8394-2B8750B62654");
|
||||
private readonly IPublishedSnapshotService _publishedSnapshotService;
|
||||
|
||||
public override Guid RefresherUniqueId => UniqueId;
|
||||
|
||||
public override string Name => "Language Cache Refresher";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Refresher
|
||||
|
||||
public override void Refresh(JsonPayload[] payloads)
|
||||
{
|
||||
if (payloads.Length == 0) return;
|
||||
|
||||
var clearDictionary = false;
|
||||
var clearContent = false;
|
||||
|
||||
//clear all no matter what type of payload
|
||||
ClearAllIsolatedCacheByEntityType<ILanguage>();
|
||||
|
||||
foreach (var payload in payloads)
|
||||
{
|
||||
switch (payload.ChangeType)
|
||||
{
|
||||
case LanguageChangeType.Update:
|
||||
clearDictionary = true;
|
||||
break;
|
||||
case LanguageChangeType.Remove:
|
||||
case LanguageChangeType.ChangeCulture:
|
||||
clearDictionary = true;
|
||||
clearContent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (clearDictionary)
|
||||
{
|
||||
ClearAllIsolatedCacheByEntityType<IDictionaryItem>();
|
||||
}
|
||||
|
||||
//if this flag is set, we will tell the published snapshot service to refresh ALL content and evict ALL IContent items
|
||||
if (clearContent)
|
||||
{
|
||||
//clear all domain caches
|
||||
RefreshDomains();
|
||||
ContentCacheRefresher.RefreshContentTypes(AppCaches); // we need to evict all IContent items
|
||||
//now refresh all nucache
|
||||
var clearContentPayload = new[] { new ContentCacheRefresher.JsonPayload(0, null, TreeChangeTypes.RefreshAll) };
|
||||
ContentCacheRefresher.NotifyPublishedSnapshotService(_publishedSnapshotService, AppCaches, clearContentPayload);
|
||||
}
|
||||
|
||||
// then trigger event
|
||||
base.Refresh(payloads);
|
||||
}
|
||||
|
||||
// these events should never trigger
|
||||
// everything should be PAYLOAD/JSON
|
||||
|
||||
public override void RefreshAll() => throw new NotSupportedException();
|
||||
|
||||
public override void Refresh(int id) => throw new NotSupportedException();
|
||||
|
||||
public override void Refresh(Guid id) => throw new NotSupportedException();
|
||||
|
||||
public override void Remove(int id) => throw new NotSupportedException();
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Clears all domain caches
|
||||
/// </summary>
|
||||
private void RefreshDomains()
|
||||
{
|
||||
ClearAllIsolatedCacheByEntityType<IDomain>();
|
||||
|
||||
// note: must do what's above FIRST else the repositories still have the old cached
|
||||
// content and when the PublishedCachesService is notified of changes it does not see
|
||||
// the new content...
|
||||
|
||||
var payloads = new[] { new DomainCacheRefresher.JsonPayload(0, DomainChangeTypes.RefreshAll) };
|
||||
_publishedSnapshotService.Notify(payloads);
|
||||
}
|
||||
|
||||
#region Json
|
||||
|
||||
public class JsonPayload
|
||||
{
|
||||
public JsonPayload(int id, string isoCode, LanguageChangeType changeType)
|
||||
{
|
||||
Id = id;
|
||||
IsoCode = isoCode;
|
||||
ChangeType = changeType;
|
||||
}
|
||||
|
||||
public int Id { get; }
|
||||
public string IsoCode { get; }
|
||||
public LanguageChangeType ChangeType { get; }
|
||||
|
||||
public enum LanguageChangeType
|
||||
{
|
||||
/// <summary>
|
||||
/// A new languages has been added
|
||||
/// </summary>
|
||||
Add = 0,
|
||||
|
||||
/// <summary>
|
||||
/// A language has been deleted
|
||||
/// </summary>
|
||||
Remove = 1,
|
||||
|
||||
/// <summary>
|
||||
/// A language has been updated - but it's culture remains the same
|
||||
/// </summary>
|
||||
Update = 2,
|
||||
|
||||
/// <summary>
|
||||
/// A language has been updated - it's culture has changed
|
||||
/// </summary>
|
||||
ChangeCulture = 3
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user