Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5a07e34fb4 | |||
| 1b5d614f5a | |||
| abb08260eb | |||
| 57c567c570 | |||
| 424f4601ae | |||
| 6f17129364 |
+122
-170
@@ -1,176 +1,14 @@
|
||||
# Umbraco Cms Build
|
||||
Umbraco Cms Build
|
||||
--
|
||||
----
|
||||
|
||||
## Are you sure?
|
||||
# Quick!
|
||||
|
||||
In order to use Umbraco as a CMS and build your website with it, you should not build it yourself. If you're reading this then you're trying to contribute to Umbraco or you're debugging a complex issue.
|
||||
|
||||
- Are you about to create a pull request for Umbraco?
|
||||
- Are you trying to get to the bottom of a problem in your existing Umbraco installation?
|
||||
|
||||
If the answer is yes, please read on. Otherwise, make sure to head on over [to the download page](https://our.umbraco.com/download) and start using Umbraco CMS as intended.
|
||||
|
||||
**Table of contents**
|
||||
|
||||
[Building from source](#building-from-source)
|
||||
* [The quick build](#quick)
|
||||
* [Build infrastructure](#build-infrastructure)
|
||||
* [Properties](#properties)
|
||||
* [GetUmbracoVersion](#getumbracoversion)
|
||||
* [SetUmbracoVersion](#setumbracoversion)
|
||||
* [Build](#build)
|
||||
* [Build-UmbracoDocs](#build-umbracodocs)
|
||||
* [Verify-NuGet](#verify-nuget)
|
||||
* [Cleaning up](#cleaning-up)
|
||||
|
||||
[Azure DevOps](#azure-devops)
|
||||
|
||||
[Quirks](#quirks)
|
||||
* [Powershell quirks](#powershell-quirks)
|
||||
* [Git quirks](#git-quirks)
|
||||
|
||||
|
||||
## Building from source
|
||||
|
||||
Did you read ["Are you sure"](#are-you-sure)?
|
||||
|
||||
### Quick!
|
||||
|
||||
To build Umbraco, fire up PowerShell and move to Umbraco's repository root (the directory that contains `src`, `build`, `LICENSE.md`...). There, trigger the build with the following command:
|
||||
To build Umbraco, fire PowerShell and move to Umbraco's repository root (the directory that contains `src`, `build`, `README.md`...). There, trigger the build with the following command:
|
||||
|
||||
build/build.ps1
|
||||
|
||||
You might run into [Powershell quirks](#powershell-quirks).
|
||||
|
||||
### Build Infrastructure
|
||||
|
||||
The Umbraco Build infrastructure relies on a PowerShell object. The object can be retrieved with:
|
||||
|
||||
$ubuild = build/build.ps1 -get
|
||||
|
||||
The object exposes various properties and methods that can be used to fine-grain build Umbraco. Some, but not all, of them are detailed below.
|
||||
|
||||
#### Properties
|
||||
|
||||
The object exposes the following properties:
|
||||
|
||||
* `SolutionRoot`: the absolute path to the solution root
|
||||
* `VisualStudio`: a Visual Studio object (see below)
|
||||
* `NuGet`: the absolute path to the NuGet executable
|
||||
* `Zip`: the absolute path to the 7Zip executable
|
||||
* `VsWhere`: the absolute path to the VsWhere executable
|
||||
* `NodePath`: the absolute path to the Node install
|
||||
* `NpmPath`: the absolute path to the Npm install
|
||||
|
||||
The Visual Studio object is `null` when Visual Studio has not been detected (eg on VSTS). When not null, the object exposes the following properties:
|
||||
|
||||
* `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
|
||||
|
||||
#### GetUmbracoVersion
|
||||
|
||||
Gets an object representing the current Umbraco version. Example:
|
||||
|
||||
$v = $ubuild.GetUmbracoVersion()
|
||||
Write-Host $v.Semver
|
||||
|
||||
The object exposes the following properties:
|
||||
|
||||
* `Semver`: the semver object representing the version
|
||||
* `Release`: the main part of the version (eg `7.6.33`)
|
||||
* `Comment`: the pre release part of the version (eg `alpha02`)
|
||||
* `Build`: the build number part of the version (eg `1234`)
|
||||
|
||||
#### SetUmbracoVersion
|
||||
|
||||
Modifies Umbraco files with the new version.
|
||||
|
||||
>This entirely replaces the legacy `UmbracoVersion.txt` file. Do *not* edit version infos in files.
|
||||
|
||||
The version must be a valid semver version. It can include a *pre release* part (eg `alpha02`) and/or a *build number* (eg `1234`). Examples:
|
||||
|
||||
$ubuild.SetUmbracoVersion("7.6.33")
|
||||
$ubuild.SetUmbracoVersion("7.6.33-alpha.2")
|
||||
$ubuild.SetUmbracoVersion("7.6.33+1234")
|
||||
$ubuild.SetUmbracoVersion("7.6.33-beta.5+5678")
|
||||
|
||||
#### Build
|
||||
|
||||
Builds Umbraco. Temporary files are generated in `build.tmp` while the actual artifacts (zip files, NuGet packages...) are produced in `build.out`. Example:
|
||||
|
||||
$ubuild.Build()
|
||||
|
||||
Some log files, such as MsBuild logs, are produced in `build.tmp` too. The `build` directory should remain clean during a build.
|
||||
|
||||
**Note: web.config**
|
||||
|
||||
Building Umbraco requires a clean `web.config` file in the `Umbraco.Web.UI` project. If a `web.config` file already exists, the `pre-build` task (see below) will save it as `web.config.temp-build` and replace it with a clean copy of `web.Template.config`. The original file is replaced once it is safe to do so, by the `pre-packages` task.
|
||||
|
||||
#### Build-UmbracoDocs
|
||||
|
||||
Builds umbraco documentation. Temporary files are generated in `build.tmp` while the actual artifacts (docs...) are produced in `build.out`. Example:
|
||||
|
||||
Build-UmbracoDocs
|
||||
|
||||
Some log files, such as MsBuild logs, are produced in `build.tmp` too. The `build` directory should remain clean during a build.
|
||||
|
||||
#### Verify-NuGet
|
||||
|
||||
Verifies that projects all require the same version of their dependencies, and that NuSpec files require versions that are consistent with projects. Example:
|
||||
|
||||
Verify-NuGet
|
||||
|
||||
### Cleaning up
|
||||
|
||||
Once the solution has been used to run a site, one may want to "reset" the solution in order to run a fresh new site again.
|
||||
|
||||
At the very minimum, you want
|
||||
|
||||
git clean -Xdf src/Umbraco.Web.UI/App_Data
|
||||
rm src/Umbraco.Web.UI/web.config
|
||||
|
||||
Then, a simple 'Rebuild All' in Visual Studio will recreate a fresh `web.config` but should be quite fast (since it does not really need to rebuild anything).
|
||||
|
||||
The `clean` Git command force (`-f`) removes (`-X`, note the capital X) all files and directories (`-d`) that are ignored by Git.
|
||||
|
||||
This will leave media files and views around, but in most cases, it will be enough.
|
||||
|
||||
To perform a more complete clear, you will want to also delete the content of the media, views, scripts... directories.
|
||||
|
||||
The following command will force remove all untracked files and directories, whether they are ignored by Git or not. Combined with `git reset` it can recreate a pristine working directory.
|
||||
|
||||
git clean -xdf .
|
||||
|
||||
For git documentation see:
|
||||
* git [clean](<https://git-scm.com/docs/git-clean>)
|
||||
* git [reset](<https://git-scm.com/docs/git-reset>)
|
||||
|
||||
## Azure DevOps
|
||||
|
||||
Umbraco uses Azure DevOps for continuous integration, nightly builds and release builds. The Umbraco CMS project on DevOps [is available for anonymous users](https://umbraco.visualstudio.com/Umbraco%20Cms).
|
||||
|
||||
DevOps uses the `Build-Umbraco` command several times, each time passing a different *target* parameter. The supported targets are:
|
||||
|
||||
* `pre-build`: prepares the build
|
||||
* `compile-belle`: compiles Belle
|
||||
* `compile-umbraco`: compiles Umbraco
|
||||
* `pre-tests`: prepares the tests
|
||||
* `compile-tests`: compiles the tests
|
||||
* `pre-packages`: prepares the packages
|
||||
* `pkg-zip`: creates the zip files
|
||||
* `pre-nuget`: prepares NuGet packages
|
||||
* `pkg-nuget`: creates NuGet packages
|
||||
|
||||
All these targets are executed when `Build-Umbraco` is invoked without a parameter (or with the `all` parameter). On VSTS, compilations (of Umbraco and tests) are performed by dedicated DevOps tasks. Similarly, creating the NuGet packages is also performed by dedicated DevOps tasks.
|
||||
|
||||
Finally, the produced artifacts are published in two containers that can be downloaded from DevOps: `zips` contains the zip files while `nuget` contains the NuGet packages.
|
||||
|
||||
>During a DevOps build, some environment `UMBRACO_*` variables are exported by the `pre-build` target and can be reused in other targets *and* in DevOps tasks. The `UMBRACO_TMP` environment variable is used in `Umbraco.Tests` to disable some tests that have issues with DevOps at the moment.
|
||||
|
||||
## Quirks
|
||||
|
||||
### PowerShell Quirks
|
||||
## PowerShell Quirks
|
||||
|
||||
There is a good chance that running `build.ps1` ends up in error, with messages such as
|
||||
|
||||
@@ -207,6 +45,120 @@ The best solution is to unblock the Zip file before un-zipping: right-click the
|
||||
|
||||
PS> Get-ChildItem -Recurse *.* | Unblock-File
|
||||
|
||||
### Git Quirks
|
||||
## 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).
|
||||
|
||||
# Build Infrastructure
|
||||
|
||||
The Umbraco Build infrastructure relies on a PowerShell object. The object can be retrieved with:
|
||||
|
||||
$ubuild = build/build.ps1 -get
|
||||
|
||||
The object exposes various properties and methods that can be used to fine-grain build Umbraco. Some, but not all, of them are detailed below.
|
||||
|
||||
## Properties
|
||||
|
||||
The object exposes the following properties:
|
||||
|
||||
* `SolutionRoot`: the absolute path to the solution root
|
||||
* `VisualStudio`: a Visual Studio object (see below)
|
||||
* `NuGet`: the absolute path to the NuGet executable
|
||||
* `Zip`: the absolute path to the 7Zip executable
|
||||
* `VsWhere`: the absolute path to the VsWhere executable
|
||||
* `NodePath`: the absolute path to the Node install
|
||||
* `NpmPath`: the absolute path to the Npm install
|
||||
|
||||
The Visual Studio object is `null` when Visual Studio has not been detected (eg on VSTS). When not null, the object exposes the following properties:
|
||||
|
||||
* `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
|
||||
|
||||
## GetUmbracoVersion
|
||||
|
||||
Gets an object representing the current Umbraco version. Example:
|
||||
|
||||
$v = $ubuild.GetUmbracoVersion()
|
||||
Write-Host $v.Semver
|
||||
|
||||
The object exposes the following properties:
|
||||
|
||||
* `Semver`: the semver object representing the version
|
||||
* `Release`: the main part of the version (eg `7.6.33`)
|
||||
* `Comment`: the pre release part of the version (eg `alpha02`)
|
||||
* `Build`: the build number part of the version (eg `1234`)
|
||||
|
||||
## SetUmbracoVersion
|
||||
|
||||
Modifies Umbraco files with the new version.
|
||||
|
||||
>This entirely replaces the legacy `UmbracoVersion.txt` file. Do *not* edit version infos in files.
|
||||
|
||||
The version must be a valid semver version. It can include a *pre release* part (eg `alpha02`) and/or a *build number* (eg `1234`). Examples:
|
||||
|
||||
$ubuild.SetUmbracoVersion("7.6.33")
|
||||
$ubuild.SetUmbracoVersion("7.6.33-alpha.2")
|
||||
$ubuild.SetUmbracoVersion("7.6.33+1234")
|
||||
$ubuild.SetUmbracoVersion("7.6.33-beta.5+5678")
|
||||
|
||||
## Build
|
||||
|
||||
Builds Umbraco. Temporary files are generated in `build.tmp` while the actual artifacts (zip files, NuGet packages...) are produced in `build.out`. Example:
|
||||
|
||||
$ubuild.Build()
|
||||
|
||||
Some log files, such as MsBuild logs, are produced in `build.tmp` too. The `build` directory should remain clean during a build.
|
||||
|
||||
### web.config
|
||||
|
||||
Building Umbraco requires a clean `web.config` file in the `Umbraco.Web.UI` project. If a `web.config` file already exists, the `pre-build` task (see below) will save it as `web.config.temp-build` and replace it with a clean copy of `web.Template.config`. The original file is replaced once it is safe to do so, by the `pre-packages` task.
|
||||
|
||||
## Build-UmbracoDocs
|
||||
|
||||
Builds umbraco documentation. Temporary files are generated in `build.tmp` while the actual artifacts (docs...) are produced in `build.out`. Example:
|
||||
|
||||
Build-UmbracoDocs
|
||||
|
||||
Some log files, such as MsBuild logs, are produced in `build.tmp` too. The `build` directory should remain clean during a build.
|
||||
|
||||
## Verify-NuGet
|
||||
|
||||
Verifies that projects all require the same version of their dependencies, and that NuSpec files require versions that are consistent with projects. Example:
|
||||
|
||||
Verify-NuGet
|
||||
|
||||
# VSTS
|
||||
|
||||
Continuous integration, nightly builds and release builds run on VSTS.
|
||||
|
||||
VSTS uses the `Build-Umbraco` command several times, each time passing a different *target* parameter. The supported targets are:
|
||||
|
||||
* `pre-build`: prepares the build
|
||||
* `compile-belle`: compiles Belle
|
||||
* `compile-umbraco`: compiles Umbraco
|
||||
* `pre-tests`: prepares the tests
|
||||
* `compile-tests`: compiles the tests
|
||||
* `pre-packages`: prepares the packages
|
||||
* `pkg-zip`: creates the zip files
|
||||
* `pre-nuget`: prepares NuGet packages
|
||||
* `pkg-nuget`: creates NuGet packages
|
||||
|
||||
All these targets are executed when `Build-Umbraco` is invoked without a parameter (or with the `all` parameter). On VSTS, compilations (of Umbraco and tests) are performed by dedicated VSTS tasks. Similarly, creating the NuGet packages is also performed by dedicated VSTS tasks.
|
||||
|
||||
Finally, the produced artifacts are published in two containers that can be downloaded from VSTS: `zips` contains the zip files while `nuget` contains the NuGet packages.
|
||||
|
||||
>During a VSTS build, some environment `UMBRACO_*` variables are exported by the `pre-build` target and can be reused in other targets *and* in VSTS tasks. The `UMBRACO_TMP` environment variable is used in `Umbraco.Tests` to disable some tests that have issues with VSTS at the moment.
|
||||
|
||||
# Notes
|
||||
|
||||
*This part needs to be cleaned up*
|
||||
|
||||
Nightlies should use some sort of build number.
|
||||
|
||||
We should increment versions as soon as a version is released. Ie, as soon as `7.6.33` is released, we should `Set-UmbracoVersion 7.6.34-alpha` and push.
|
||||
|
||||
NuGet / NuSpec consistency checks are performed in tests. We should move it so it is done as part of the PowerShell script even before we try to compile and run the tests.
|
||||
|
||||
/eof
|
||||
@@ -0,0 +1,34 @@
|
||||
Umbraco Cms Clear
|
||||
--
|
||||
----
|
||||
|
||||
Once the solution has been used to run a site, one may want to "reset" the solution in order to run a fresh new site again.
|
||||
|
||||
## Fast
|
||||
|
||||
At the very minimum, you want
|
||||
|
||||
git clean -Xdf src/Umbraco.Web.UI/App_Data
|
||||
rm src/Umbraco.Web.UI/web.config
|
||||
|
||||
Then, a simple 'Rebuild All' in Visual Studio will recreate a fresh `web.config` but should be quite fast (since it does not really need to rebuild anything).
|
||||
|
||||
The `clean` Git command force (`-f`) removes (`-X`, note the capital X) all files and directories (`-d`) that are ignored by Git.
|
||||
|
||||
This will leave medias and views around, but in most cases, it will be enough.
|
||||
|
||||
## More
|
||||
|
||||
To perform a more complete clear, you will want to also delete the content of the media, views, masterpages, scripts... directories.
|
||||
|
||||
## Full
|
||||
|
||||
The following command will force remove all untracked files and directories, be they ignored by Git or not. Combined with `git reset` it can recreate a pristine working directory.
|
||||
|
||||
git clean -xdf .
|
||||
|
||||
## Docs
|
||||
|
||||
See
|
||||
* git [clean](<https://git-scm.com/docs/git-clean>)
|
||||
* git [reset](<https://git-scm.com/docs/git-reset>)
|
||||
+97
-187
@@ -1,187 +1,97 @@
|
||||
# Contributing to Umbraco CMS
|
||||
|
||||
👍🎉 First off, thanks for taking the time to contribute! 🎉👍
|
||||
|
||||
The following is a set of guidelines for contributing to Umbraco CMS.
|
||||
|
||||
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).
|
||||
|
||||
**Table of contents**
|
||||
|
||||
[Contributing code changes](#contributing-code-changes)
|
||||
* [Guidelines for contributions we welcome](#guidelines-for-contributions-we-welcome)
|
||||
* [What can I start with?](#what-can-i-start-with)
|
||||
* [How do I begin?](#how-do-i-begin)
|
||||
* [Pull requests](#pull-requests)
|
||||
|
||||
[Reviews](#reviews)
|
||||
* [Styleguides](#styleguides)
|
||||
* [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 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)
|
||||
|
||||
## Contributing code changes
|
||||
|
||||
This document gives you a quick overview on how to get started.
|
||||
|
||||
### Guidelines for contributions we welcome
|
||||
|
||||
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.
|
||||
|
||||
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?
|
||||
|
||||
Unsure where to begin contributing to Umbraco? You can start by looking through [these `Up for grabs` issues](https://github.com/umbraco/Umbraco-CMS/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Acommunity%2Fup-for-grabs+)
|
||||
|
||||
### How do I begin?
|
||||
|
||||
Great question! The short version goes like this:
|
||||
|
||||
* **Fork** - create a fork of [`Umbraco-CMS` on GitHub](https://github.com/umbraco/Umbraco-CMS)
|
||||
|
||||

|
||||
|
||||
* **Clone** - when GitHub has created your fork, you can clone it in your favorite Git tool
|
||||
|
||||

|
||||
|
||||
* **Build** - build your fork of Umbraco locally as described in [building Umbraco from source code](BUILD.md)
|
||||
* **Change** - make your changes, experiment, have fun, explore and learn, and don't be afraid. We welcome all contributions and will [happily give feedback](#questions)
|
||||
* **Commit** - done? Yay! 🎉 **Important:** create a new branch now and name it after the issue you're fixing, we usually follow the format: `temp-12345`. This means it's a temporary branch for the particular issue you're working on, in this case `12345`. When you have a branch, commit your changes. Don't commit to `v8/dev`, create a new branch first.
|
||||
* **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). 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
|
||||
* 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
|
||||
|
||||
Again, these are guidelines, not strict requirements.
|
||||
|
||||
## Reviews
|
||||
|
||||
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 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
|
||||
|
||||
### Styleguides
|
||||
|
||||
To be honest, we don't like rules very much. We trust you have the best of intentions and we encourage you to create working code. If it doesn't look perfect then we'll happily help clean it up.
|
||||
|
||||
That said, the Umbraco development team likes to follow the hints that ReSharper gives us (no problem if you don't have this installed) and we've added a `.editorconfig` file so that Visual Studio knows what to do with whitespace, line endings, etc.
|
||||
|
||||
### The PR team
|
||||
|
||||
The 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)
|
||||
|
||||
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 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
|
||||
|
||||
## Working with the code
|
||||
|
||||
### Building Umbraco from source code
|
||||
|
||||
In order to build the Umbraco source code locally, first make sure you have the following installed.
|
||||
|
||||
* Visual Studio 2017 v15.9.7+
|
||||
* Node v10+
|
||||
* npm v6.4.1+
|
||||
|
||||
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 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.
|
||||
|
||||
### 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'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:
|
||||
```
|
||||
npm cache clean --force
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
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 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/), 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 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 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'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:
|
||||
|
||||
```
|
||||
git remote add upstream https://github.com/umbraco/Umbraco-CMS.git
|
||||
```
|
||||
|
||||
Then when you want to get the changes from the main repository:
|
||||
|
||||
```
|
||||
git fetch upstream
|
||||
git rebase upstream/v8/dev
|
||||
```
|
||||
|
||||
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))
|
||||
_Looking for Umbraco version 8? [Click here](https://github.com/umbraco/Umbraco-CMS/blob/temp8/.github/V8_GETTING_STARTED.md) to go to the v8 branch_
|
||||
# Contributing to Umbraco CMS
|
||||
|
||||
👍🎉 First off, thanks for taking the time to contribute! 🎉👍
|
||||
|
||||
The following is a set of guidelines for contributing to Umbraco CMS.
|
||||
|
||||
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 💖.
|
||||
|
||||
## Contributing code changes
|
||||
|
||||
This document gives you a quick overview on how to get started, we will link to in-depth documentation throughout if you need some more background info.
|
||||
|
||||
|
||||
## Guidelines for contributions we welcome
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
## How do I begin?
|
||||
|
||||
Great question! The short version goes like this:
|
||||
|
||||
* **Fork** - create a fork of [`Umbraco-CMS` on GitHub](https://github.com/umbraco/Umbraco-CMS)
|
||||
|
||||

|
||||
|
||||
* **Clone** - when GitHub has created your fork, you can clone it in your favorite Git tool
|
||||
|
||||

|
||||
|
||||
* **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! 🎉 It is recommended to 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`
|
||||
* **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). 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.
|
||||
|
||||

|
||||
|
||||
### Further reading
|
||||
|
||||
At this point you might want to [read on about contributing in depth](CONTRIBUTING_DETAILED.md).
|
||||
|
||||
### Reviews
|
||||
|
||||
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 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
|
||||
|
||||
## Styleguides
|
||||
|
||||
To be honest, we don't like rules very much. We trust you have the best of intentions and we encourage you to create working code. If it doesn't look perfect then we'll happily help clean it up.
|
||||
|
||||
That said, the Umbraco development team likes to follow the hints that ReSharper gives us (no problem if you don't have this installed) and we've added a `.editorconfig` file so that Visual Studio knows what to do with whitespace, line endings, etc.
|
||||
|
||||
## The PR team
|
||||
|
||||
The 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)
|
||||
|
||||
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 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
|
||||
|
||||
## 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).
|
||||
|
||||
|
||||
## Contributing to Umbraco, in depth
|
||||
|
||||
There are other ways to contribute, and there's a few more things that you might be wondering about. We will answer the [most common questions and ways to contribute in our detailed documentation](CONTRIBUTING_DETAILED.md).
|
||||
|
||||
## Credits
|
||||
|
||||
This contribution guide borrows heavily from the excellent work on [the Atom contribution guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md). A big [#h5yr](http://h5yr.com/) to them!
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
# Contributing in detail
|
||||
|
||||
There's more than one way to contribute to Umbraco, there's some more suggestions below.
|
||||
|
||||
When contributing code to Umbraco there's plenty of things you'll want to know, skip down to [What should I know before I get started](#what-should-i-know-before-i-get-started) for the answers to your burning questions.
|
||||
|
||||
#### Table Of Contents
|
||||
|
||||
[How Can I Contribute?](#how-can-i-contribute)
|
||||
* [Reporting Bugs](#reporting-bugs)
|
||||
* [Suggesting Enhancements](#suggesting-enhancements)
|
||||
* [Your First Code Contribution](#your-first-code-contribution)
|
||||
* [Pull Requests](#pull-requests)
|
||||
|
||||
[Styleguides](#styleguides)
|
||||
|
||||
[What should I know before I get started?](#what-should-i-know-before-i-get-started)
|
||||
* [Working with the source code](#working-with-the-source-code)
|
||||
* [What branch should I target for my contributions?](#what-branch-should-i-target-for-my-contributions)
|
||||
* [Building Umbraco from source code](#building-umbraco-from-source-code)
|
||||
* [Keeping your Umbraco fork in sync with the main repository](#keeping-your-umbraco-fork-in-sync-with-the-main-repository)
|
||||
|
||||
## How Can I Contribute?
|
||||
|
||||
### Reporting Bugs
|
||||
This section guides you through submitting a bug report for Umbraco CMS. Following these guidelines helps maintainers and the community understand your report 📝, reproduce the behavior 💻 💻, and find related reports 🔎.
|
||||
|
||||
Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](https://github.com/umbraco/Umbraco-CMS/issues/new/choose), the information it asks for helps us resolve issues faster.
|
||||
|
||||
> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one.
|
||||
|
||||
##### Before Submitting A Bug Report
|
||||
|
||||
* Most importantly, check **if you can reproduce the problem** in the [latest version of Umbraco](https://our.umbraco.com/download/). We might have already fixed your particular problem.
|
||||
* It also helps tremendously to check if the issue you're experiencing is present in **a clean install** of the Umbraco version you're currently using. Custom code can have side-effects that don't occur in a clean install.
|
||||
* **Use the Google**. Whatever you're experiencing, Google it plus "Umbraco" - usually you can get some pretty good hints from the search results, including open issues and further troubleshooting hints.
|
||||
* If you do find and existing issue has **and the issue is still open**, add a comment to the existing issue if you have additional information. If you have the same problem and no new info to add, just "star" the issue.
|
||||
|
||||
Explain the problem and include additional details to help maintainers reproduce the problem. The following is a long description which we've boiled down into a few very simple questions in the issue tracker when you create a new issue. We're listing the following hints to indicate that the most successful reports usually have a lot of this ground covered:
|
||||
|
||||
* **Use a clear and descriptive title** for the issue to identify the problem.
|
||||
* **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining which steps you took in the backoffice to get to a certain undesireable result, e.g. you created a document type, inherting 3 levels deep, added a certain datatype, tried to save it and you got an error.
|
||||
* **Provide specific examples to demonstrate the steps**. If you wrote some code, try to provide a code sample as specific as possible to be able to reproduce the behavior.
|
||||
* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
|
||||
* **Explain which behavior you expected to see instead and why.**
|
||||
|
||||
Provide more context by answering these questions:
|
||||
|
||||
* **Can you reproduce the problem** when `debug="false"` in your `web.config` file?
|
||||
* **Did the problem start happening recently** (e.g. after updating to a new version of Umbraco) or was this always a problem?
|
||||
* **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens.
|
||||
|
||||
Include details about your configuration and environment:
|
||||
|
||||
* **Which version of Umbraco are you using?**
|
||||
* **What is the environment you're using Umbraco in?** Is this a problem on your local machine or on a server. Tell us about your configuration: Windows version, IIS/IISExpress, database type, etc.
|
||||
* **Which packages do you have installed?**
|
||||
|
||||
### Suggesting Enhancements
|
||||
|
||||
This section guides you through submitting an enhancement suggestion for Umbraco, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion 📝 and find related suggestions 🔎.
|
||||
|
||||
Most of the suggestions in the [reporting bugs](#reporting-bugs) section also count for suggesting enhancements.
|
||||
|
||||
Some additional hints that may be helpful:
|
||||
|
||||
* **Include screenshots and animated GIFs** which help you demonstrate the steps or point out the part of Umbraco which the suggestion is related to.
|
||||
* **Explain why this enhancement would be useful to most Umbraco users** and isn't something that can or should be implemented as a [community package](https://our.umbraco.com/projects/).
|
||||
|
||||
### Your First Code Contribution
|
||||
|
||||
Unsure where to begin contributing to Umbraco? You can start by looking through [these `Up for grabs` and issues](https://issues.umbraco.org/issues?q=&project=U4&tagValue=upforgrabs&release=&issueType=&search=search) or on the [new issue tracker](https://github.com/umbraco/Umbraco-CMS/issues?q=is%3Aopen+is%3Aissue+label%3Acommunity%2Fup-for-grabs).
|
||||
|
||||
### Pull Requests
|
||||
|
||||
The most successful pull requests usually look a like this:
|
||||
|
||||
* 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
|
||||
|
||||
Again, these are guidelines, not strict requirements.
|
||||
|
||||
## 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!
|
||||
|
||||
## Styleguides
|
||||
|
||||
To be honest, we don't like rules very much. We trust you have the best of intentions and we encourage you to create working code. If it doesn't look perfect then we'll happily help clean it up.
|
||||
|
||||
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.
|
||||
|
||||
## What should I know before I get started?
|
||||
|
||||
### Working with the source code
|
||||
|
||||
Some parts of our source code is over 10 years old now. And when we say "old", we mean "mature" of course!
|
||||
|
||||
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:
|
||||
```
|
||||
npm cache clean
|
||||
npm install -g gulp
|
||||
npm install -g gulp-cli
|
||||
npm install
|
||||
gulp build
|
||||
```
|
||||
2. "The rest" is a C# based codebase, with some traces of our WebForms past but mostly ASP.NET MVC based these days. You can make changes, build them in Visual Studio, and hit `F5` to see the result.
|
||||
|
||||
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 rest](https://our.umbraco.com/apidocs/csharp/)
|
||||
|
||||
### What branch should I target for my contributions?
|
||||
|
||||
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 `dev-v7`. Whatever the default is, that's where we'd like you to target your contributions.
|
||||
|
||||

|
||||
|
||||
### Building Umbraco from source code
|
||||
|
||||
In order to build the Umbraco source code locally, first make sure you have the following installed.
|
||||
|
||||
* Visual Studio 2017 v15.3+
|
||||
* Node v10+ (Installed via `build.bat` script. If you already have it installed, make sure you're running at least v10)
|
||||
* npm v6.4.1+ (Installed via `build.bat` script. If you already have it installed, make sure you're running at least v6.4.1)
|
||||
|
||||
The easiest way to get started is to run `build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `gulp dev` in `src\Umbraco.Web.UI.Client`. See [this page](BUILD.md) for more details.
|
||||
|
||||
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 (version 15.3 or higher, [the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||
### Keeping your Umbraco fork in sync with the main repository
|
||||
|
||||
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'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:
|
||||
|
||||
```
|
||||
git remote add upstream https://github.com/umbraco/Umbraco-CMS.git
|
||||
```
|
||||
|
||||
Then when you want to get the changes from the main repository:
|
||||
|
||||
```
|
||||
git fetch upstream
|
||||
git rebase upstream/dev-v7
|
||||
```
|
||||
|
||||
In this command we're syncing with the `dev-v7` 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))
|
||||
@@ -0,0 +1,33 @@
|
||||
# Contributing to Umbraco CMS
|
||||
|
||||
When you’re considering creating a pull request for Umbraco CMS, we will categorize them in two different sizes, small and large.
|
||||
|
||||
The process for both sizes is very similar, as [explained in the contribution document](CONTRIBUTING.md#how-do-i-begin).
|
||||
|
||||
## Small PRs
|
||||
Bug fixes and small improvements - can be recognized by seeing a small number of changes and possibly a small number of new files.
|
||||
|
||||
We’re usually able to handle small PRs pretty quickly. A community volunteer will do the initial review and flag it for Umbraco HQ as “community tested”. If everything looks good, it will be merged pretty quickly [as per the described process](REVIEW_PROCESS.md).
|
||||
|
||||
### Up for grabs
|
||||
|
||||
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. These issues are usually small enough to fit in the "Small PRs" category and 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.
|
||||
|
||||
## 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.).
|
||||
|
||||
We would love to follow the same process for larger PRs but this is not always possible due to time limitations and priorities that need to be aligned. We don’t want to put up any barriers, but this document should set the correct expectations.
|
||||
|
||||
Please make sure to describe your idea in an issue, it helps to put in mockup screenshots or videos.
|
||||
|
||||
If the change makes sense for HQ to include in Umbraco CMS we will leave you some feedback on how we’d like to see it being implemented.
|
||||
|
||||
If a larger pull request is encouraged by Umbraco HQ, the process will be similar to what is described in the [small PRs process](#small-prs) above, we’ll get feedback to you within 14 days. Finalizing and merging the PR might take longer though as it will likely need to be picked up by the development team to make sure everything is in order. We’ll keep you posted on the progress.
|
||||
|
||||
### 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 to fix bugs.
|
||||
|
||||
Eventually, a package could "graduate" to be included in the CMS.
|
||||
@@ -12,7 +12,7 @@ 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
|
||||
See: https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/.github/CONTRIBUTING.md
|
||||
|
||||
-->
|
||||
|
||||
|
||||
@@ -2,20 +2,11 @@
|
||||
|
||||
- [ ] I have added steps to test this contribution in the description below
|
||||
|
||||
If there's an existing issue for this PR then this fixes <!-- link to the issue here! -->
|
||||
If there's an existing issue for this PR then this fixes: <!-- link to the issue here! -->
|
||||
|
||||
### Description
|
||||
<!--
|
||||
A description of the changes proposed in the pull-request and how to test these changes.
|
||||
<!-- A description of the changes proposed in the pull-request and how to test these changes -->
|
||||
|
||||
The most successful pull requests usually look a like this:
|
||||
|
||||
* Fill in this template with details: what did you do, why did you do it, how can we test the changes?
|
||||
* Include screenshots and animated GIFs in your pull request whenever possible.
|
||||
* Unit tests, while optional are awesome, thank you!
|
||||
|
||||
While these are guidelines and not strict requirements, they really help us evaluate your PR quicker.
|
||||
-->
|
||||
|
||||
|
||||
<!-- Thanks for contributing to Umbraco CMS! -->
|
||||
|
||||
+62
-40
@@ -1,40 +1,62 @@
|
||||
# [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.
|
||||
|
||||
Learn more at [umbraco.com](https://umbraco.com)
|
||||
|
||||
<p align="center">
|
||||
<img src="img/logo.png" alt="Umbraco Logo" />
|
||||
</p>
|
||||
|
||||
See the official [Umbraco website](https://umbraco.com) for an introduction, core mission and values of the product and team behind it.
|
||||
|
||||
- [Getting Started](#getting-started)
|
||||
- [Documentation](#documentation)
|
||||
- [Community](#join-the-umbraco-community)
|
||||
- [Contributing](#contributing)
|
||||
|
||||
Please also see our [Code of Conduct](CODE_OF_CONDUCT.md).
|
||||
|
||||
## Getting Started
|
||||
|
||||
[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, 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
|
||||
|
||||
The documentation for Umbraco CMS can be found [on Our Umbraco](https://our.umbraco.com/documentation/). The source for the Umbraco docs is [open source as well](https://github.com/umbraco/UmbracoDocs) and we're happy to look at your documentation contributions.
|
||||
|
||||
## 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.
|
||||
|
||||
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)
|
||||
|
||||
|
||||
## 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).
|
||||
|
||||
_You are browsing the Umbraco v8 branch. Umbraco 8 is currently under development._
|
||||
[](https://pullreminders.com?ref=badge)
|
||||
|
||||
_Looking for Umbraco version 7? [Click here](https://github.com/umbraco/Umbraco-CMS) to go to the v7 branch._
|
||||
|
||||
_Ready to try out Version 8? [See the quick start guide](V8_GETTING_STARTED.md)._
|
||||
|
||||
When is Umbraco 8 coming?
|
||||
=========================
|
||||
When it's ready. We're done with the major parts of the architecture work and are focusing on three separate tracks to prepare Umbraco 8 for release:
|
||||
1) Editor Track (_currently in progress_). Without editors, there's no market for Umbraco. So we want to make sure that Umbraco 8 is full of love for editors.
|
||||
2) Partner Track. Without anyone implementing Umbraco, there's nothing for editors to update. So we want to make sure that Umbraco 8 is a joy to implement
|
||||
3) Contributor Track. Without our fabulous ecosystem of both individual Umbracians and 3rd party ISVs, Umbraco wouldn't be as rich a platform as it is today. We want to make sure that it's easy, straight forward and as backwards-compatible as possible to create packages for Umbraco
|
||||
|
||||
Once a track is done, we start releasing previews where we ask people to test the features we believe are ready. While the testing is going on and we gather feedback, we move on to the next track. This doesn't mean that there hasn't already been work done in the area, but that a track focuses on finalizing, polishing and preparing the features for release.
|
||||
|
||||
Umbraco CMS
|
||||
===========
|
||||
The friendliest, most flexible and fastest growing ASP.NET CMS, and used by more than 443,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
|
||||
|
||||
[](https://vimeo.com/172382998/)
|
||||
|
||||
## Umbraco CMS
|
||||
Umbraco is a free open source Content Management System built on the ASP.NET platform. Our mission is to help you deliver delightful digital experiences by making Umbraco friendly, simpler and social.
|
||||
|
||||
## Watch an introduction video
|
||||
|
||||
[](https://umbraco.tv/videos/umbraco-v7/content-editor/basics/introduction/cms-explanation/)
|
||||
|
||||
## Umbraco - The Friendly CMS
|
||||
|
||||
For the first time on the Microsoft platform, there is a free user- and developer-friendly CMS that makes it quick and easy to create websites - and a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, right out of the box.
|
||||
|
||||
Umbraco is not only loved by developers, but is a content editor's dream. Enjoy intuitive editing tools, media management, responsive views, and approval workflows to send your content live.
|
||||
|
||||
Used by more than 443,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scalable. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 220,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
|
||||
|
||||
To view more examples, please visit [https://umbraco.com/case-studies-testimonials/](https://umbraco.com/case-studies-testimonials/)
|
||||
|
||||
## Why Open Source?
|
||||
As an Open Source platform, Umbraco is more than just a CMS. We are transparent with our roadmap for future versions, our incremental sprint planning notes are publicly accessible, and community contributions and packages are available for all to use.
|
||||
|
||||
## Trying out Umbraco CMS
|
||||
|
||||
[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, 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## Contribute to Umbraco
|
||||
|
||||
Umbraco is contribution-focused and community-driven. If you want to contribute back to Umbraco, please check out our [guide to contributing](CONTRIBUTING.md).
|
||||
|
||||
## Found a bug?
|
||||
|
||||
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](CONTRIBUTING_DETAILED.md#reporting-bugs).
|
||||
|
||||
You can comment and report issues on the [github issue tracker](https://github.com/umbraco/Umbraco-CMS/issues).
|
||||
Since [September 2018](https://umbraco.com/blog/a-second-take-on-umbraco-issue-tracker-hello-github-issues/), the old issue tracker is in read-only mode, but can still be found at [http://issues.umbraco.org](http://issues.umbraco.org).
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# Review process
|
||||
|
||||
You're an awesome person and have sent us your contribution in the form of a pull request! It's now time to relax for a bit and wait for our response.
|
||||
|
||||
In order to set some expectations, here's what happens next.
|
||||
|
||||
## Review process
|
||||
|
||||
You will get an initial reply within 48 hours (workdays) to acknowledge that we’ve seen your PR and we’ll pick it up as soon as we can.
|
||||
|
||||
You will get feedback within at most 14 days after opening the PR. You’ll most likely get feedback sooner though. Then there are a few possible outcomes:
|
||||
|
||||
- Your proposed change is awesome! We merge it in and it will be included in the next minor release of Umbraco
|
||||
- If the change is a high priority bug fix, we will cherry-pick it into the next patch release as well so that we can release it as soon as possible
|
||||
- Your proposed change is awesome but needs a bit more work, we’ll give you feedback on the changes we’d like to see
|
||||
- Your proposed change is awesome but.. not something we’re looking to include at this point. We’ll close your PR and the related issue (we’ll be nice about it!)
|
||||
|
||||
## Are you still available?
|
||||
|
||||
We understand you have other things to do and can't just drop everything to help us out.
|
||||
So if we’re asking for your help to improve the PR we’ll wait for two weeks to give you a fair chance to make changes. We’ll ask for an update if we don’t hear back from you after that time.
|
||||
|
||||
If we don’t hear back from you for 4 weeks, we’ll close the PR so that it doesn’t just hang around forever. You’re very welcome to re-open it once you have some more time to spend on it.
|
||||
|
||||
There will be times that we really like your proposed changes and we’ll finish the final improvements we’d like to see ourselves. You still get the credits and your commits will live on in the git repository.
|
||||
@@ -0,0 +1,37 @@
|
||||
## A quick start guide for getting up and runnning with Umbraco v8
|
||||
|
||||
### What you need:
|
||||
|
||||
* [Visual Studio 2017 Community (Free)](https://www.visualstudio.com/vs/community/), or Professional, Enterprise, etc... _(**Minimum of Version 15.7** or higher, this is important, you WILL get issues with lesser versions)_
|
||||
* .NET Framework 4.7.2 installed, get it here: https://www.microsoft.com/net/download/thank-you/net472?survey=false
|
||||
* .NET Framework 4.7.2 developer pack, get it here: https://www.microsoft.com/net/download/thank-you/net472-developer-pack _(be sure this is the ENU file which will be named `NDP472-DevPack-ENU.exe`)_
|
||||
* Clone the Umbraco repository using the `temp8` branch. If your git client doesn't support specifying the branch as you clone then use the command `git clone --single-branch -b temp8 <your fork url>`. _(If you clone the repo using the default v7 branch and then checkout the `temp8` branch you **might** get problems)_
|
||||
|
||||
### Start the solution
|
||||
|
||||
* Open the `/src/umbraco.sln` Visual Studio solution
|
||||
* Start the solution (easiest way is to use `ctrl + F5`)
|
||||
* When the solution is first built this may take some time since it will restore all nuget and npm packages, build the .net solution and also build the angular solution
|
||||
* When the website starts you'll see the Umbraco installer and just follow the prompts
|
||||
* You're all set!
|
||||
|
||||
### Want to run from a zip instead?
|
||||
|
||||
If you just want to try out a few things, you can run the site from a zip file which you can download from here https://github.com/umbraco/Umbraco-CMS/releases/tag/temp8-cg18.
|
||||
|
||||
We recommend running the site with the Visual Studio since you'll be able to remain up to date with the latest source code changes.
|
||||
|
||||
### Making code changes
|
||||
|
||||
* _[The process for making code changes in v8 is the same as v7](https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/.github/CONTRIBUTING.md)_
|
||||
* Any .NET changes you make you just need to compile
|
||||
* Any Angular/JS changes you make you will need to make sure you are running the Gulp build. Easiest way to do this is from within Visual Studio in the `Task Runner Explorer`. You can find this window by pressing `ctrl + q` and typing in `Task Runner Explorer`. In this window you'll see all Gulp tasks, double click on the `dev` task, this will compile the angular solution and start a file watcher, then any html/js changes you make are automatically built.
|
||||
* When making js changes, you should have the chrome developer tools open to ensure that cache is disabled
|
||||
* If you are only making C# changes and are not touching the UI code at all, you can significantly speed up the VS build by adding an empty file specifically called `~/src/preserve.belle`. The UI (Belle) build will then be skipped during a Rebuild.
|
||||
|
||||
### What to work on?
|
||||
|
||||
We are keeping track of [known issues and limitations here](http://issues.umbraco.org/issue/U4-11279). These line items will eventually be turned into actual tasks to be worked on. Feel free to help us keep this list updated if you find issues and even help fix some of these items. If there is a particular item you'd like to help fix please mention this on the task and we'll create a sub task for the item to continue discussion there.
|
||||
|
||||
There's [a list of tasks for v8 that haven't been completed](https://github.com/umbraco/Umbraco-CMS/labels/release%2F8.0.0). If you are interested in helping out with any of these please mention this on the task. This list will be constantly updated as we begin to document and design some of the other tasks that still need to get done.
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 18 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 8.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
@@ -161,4 +161,3 @@ build/temp/
|
||||
|
||||
# eof
|
||||
/src/Umbraco.Web.UI.Client/TESTS-*.xml
|
||||
/src/ApiDocs/api/*
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<repository type="git" url="https://github.com/umbraco/umbraco-cms" />
|
||||
<dependencies>
|
||||
|
||||
<group targetFramework="net472">
|
||||
@@ -23,6 +22,7 @@
|
||||
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="AutoMapper" version="[8.0.0,8.999999)" />
|
||||
<dependency id="LightInject" version="[5.4.0,5.999999)" />
|
||||
<dependency id="LightInject.Annotation" version="[1.1.0,1.999999)" />
|
||||
<dependency id="LightInject.Web" version="[2.0.0,2.999999)" />
|
||||
@@ -40,12 +40,10 @@
|
||||
<dependency id="Serilog.Formatting.Compact.Reader" version="[1.0.3,1.999999)" />
|
||||
<dependency id="Serilog.Settings.AppSettings" version="[2.2.2,2.999999)" />
|
||||
<dependency id="Serilog.Sinks.File" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Serilog.Sinks.Map" version="[1.0.0,1.999999)" />
|
||||
<dependency id="Serilog.Sinks.Async" version="[1.3.0,1.999999)" />
|
||||
<dependency id="Umbraco.SqlServerCE" version="[4.0.0.1,4.999999)" />
|
||||
<dependency id="NPoco" version="[3.9.4,3.999999)" />
|
||||
</group>
|
||||
|
||||
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
@@ -53,9 +51,10 @@
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.dll" target="lib\net472\Umbraco.Core.dll" />
|
||||
|
||||
<!-- docs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.xml" target="lib\net472\Umbraco.Core.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.xml" target="lib\Umbraco.Core.xml" />
|
||||
|
||||
<!-- symbols -->
|
||||
<file src="$BuildTmp$\bin\Umbraco.Core.pdb" target="lib\net472\Umbraco.Core.pdb" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Core.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Core\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Core" />
|
||||
</files>
|
||||
</package>
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<repository type="git" url="https://github.com/umbraco/umbraco-cms" />
|
||||
<dependencies>
|
||||
|
||||
<group targetFramework="net472">
|
||||
@@ -44,7 +43,7 @@
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.9.0,4.999999)" />
|
||||
|
||||
</group>
|
||||
|
||||
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
@@ -54,12 +53,14 @@
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.dll" target="lib\net472\Umbraco.Examine.dll" />
|
||||
|
||||
<!-- docs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.xml" target="lib\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.Web.xml" target="lib\Umbraco.Web.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.xml" target="lib\Umbraco.Web.UI.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.xml" target="lib\Umbraco.Examine.xml" />
|
||||
|
||||
<!-- symbols -->
|
||||
<file src="$BuildTmp$\bin\Umbraco.Web.pdb" target="lib\net472\Umbraco.Web.pdb" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Examine.pdb" target="lib\net472\Umbraco.Examine.pdb" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Web.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Web\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Web" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Examine.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Examine\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Examine" />
|
||||
</files>
|
||||
</package>
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
<summary>Installs Umbraco Cms in your Visual Studio ASP.NET project</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<repository type="git" url="https://github.com/umbraco/umbraco-cms" />
|
||||
<dependencies>
|
||||
|
||||
<group targetFramework="net472">
|
||||
@@ -26,7 +25,7 @@
|
||||
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="Umbraco.ModelsBuilder.Ui" version="[8.0.4]" />
|
||||
<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)" />
|
||||
@@ -59,7 +58,6 @@
|
||||
<!-- config transforms -->
|
||||
<!-- beware! config transforms not supported by PackageReference -->
|
||||
<file src="tools\Web.config.install.xdt" target="Content\Web.config.install.xdt" />
|
||||
<file src="tools\serilog.config.install.xdt" target="Content\config\serilog.config.install.xdt" />
|
||||
<file src="tools\ClientDependency.config.install.xdt" target="Content\config\ClientDependency.config.install.xdt" />
|
||||
<file src="tools\umbracoSettings.config.install.xdt" target="Content\config\umbracoSettings.config.install.xdt" />
|
||||
<file src="tools\Views.Web.config.install.xdt" target="Views\Web.config.install.xdt" /> <!-- FIXME: Content\ !! and then... transform?! -->
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
|
||||
888
|
||||
888
|
||||
888 888 88888b.d88b. 88888b. 888d888 8888b. .d8888b .d88b.
|
||||
888 888 888 "888 "88b 888 "88b 888P" "88b d88P" d88""88b
|
||||
888 888 888 888 888 888 888 888 .d888888 888 888 888
|
||||
Y88b 888 888 888 888 888 d88P 888 888 888 Y88b. Y88..88P
|
||||
"Y88888 888 888 888 88888P" 888 "Y888888 "Y8888P "Y88P"
|
||||
_ _ __ __ ____ _____ _____ ____
|
||||
| | | | \/ | _ \| __ \ /\ / ____/ __ \
|
||||
| | | | \ / | |_) | |__) | / \ | | | | | |
|
||||
| | | | |\/| | _ <| _ / / /\ \| | | | | |
|
||||
| |__| | | | | |_) | | \ \ / ____ | |___| |__| |
|
||||
\____/|_| |_|____/|_| \_/_/ \_\_____\____/
|
||||
|
||||
------------------------------------------------------------------
|
||||
----------------------------------------------------
|
||||
|
||||
Don't forget to build!
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</configSections>
|
||||
|
||||
<system.web.webPages.razor>
|
||||
<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)" />
|
||||
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(factoryType)" xdt:Transform="SetAttributes(factoryType)" />
|
||||
<pages pageBaseType="System.Web.Mvc.WebViewPage">
|
||||
<namespaces>
|
||||
<add namespace="Umbraco.Web.PublishedContentModels" xdt:Transform="InsertIfMissing" />
|
||||
@@ -18,13 +18,13 @@
|
||||
|
||||
<system.web>
|
||||
<pages
|
||||
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
xdt:Locator="Match(pageParserFilterType,pageBaseType,userControlBaseType)"
|
||||
xdt:Transform="SetAttributes(pageParserFilterType,pageBaseType,userControlBaseType)">
|
||||
<controls>
|
||||
<add assembly="System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" xdt:Locator="Match(namespace)" xdt:Transform="SetAttributes(assembly)" />
|
||||
<add assembly="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" xdt:Locator="Match(namespace)" xdt:Transform="SetAttributes(assembly)" />
|
||||
</controls>
|
||||
</pages>
|
||||
</system.web>
|
||||
|
||||
@@ -18,20 +18,9 @@ if ($project) {
|
||||
|
||||
# Copy umbraco and umbraco_files from package to project folder
|
||||
$umbracoFolder = Join-Path $projectPath "Umbraco"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoFolder
|
||||
New-Item -ItemType Directory -Force -Path $umbracoFolder
|
||||
$umbracoFolderSource = Join-Path $installPath "UmbracoFiles\Umbraco"
|
||||
|
||||
Write-Host "copying files to $umbracoFolder ..."
|
||||
# see https://support.microsoft.com/en-us/help/954404/return-codes-that-are-used-by-the-robocopy-utility-in-windows-server-2
|
||||
robocopy $umbracoFolderSource $umbracoFolder /is /it /e
|
||||
if (($lastexitcode -eq 1) -or ($lastexitcode -eq 3) -or ($lastexitcode -eq 5) -or ($lastexitcode -eq 7))
|
||||
{
|
||||
write-host "Copy succeeded!"
|
||||
}
|
||||
else
|
||||
{
|
||||
write-host "Copy failed with exit code:" $lastexitcode
|
||||
}
|
||||
robocopy $umbracoFolderSource $umbracoFolder /is /it /e /xf UI.xml /LOG:$copyLogsPath\UmbracoCopy.log
|
||||
|
||||
$copyWebconfig = $true
|
||||
$destinationWebConfig = Join-Path $projectPath "Web.config"
|
||||
@@ -51,11 +40,7 @@ if ($project) {
|
||||
}
|
||||
}
|
||||
}
|
||||
Catch
|
||||
{
|
||||
Write-Host "An error occurred:"
|
||||
Write-Host $_
|
||||
}
|
||||
Catch { }
|
||||
}
|
||||
|
||||
if($copyWebconfig -eq $true)
|
||||
@@ -89,9 +74,7 @@ if ($project) {
|
||||
}
|
||||
Catch
|
||||
{
|
||||
# Not a big problem if this fails, let it go
|
||||
# Write-Host "An error occurred:"
|
||||
# Write-Host $_
|
||||
# Not a big problem if this fails, let it go
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">>
|
||||
<appSettings>
|
||||
|
||||
<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>
|
||||
</configuration>
|
||||
@@ -1,44 +0,0 @@
|
||||
$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
|
||||
+5
-67
@@ -11,21 +11,11 @@
|
||||
[Alias("loc")]
|
||||
[switch] $local = $false,
|
||||
|
||||
# enable docfx
|
||||
[Parameter(Mandatory=$false)]
|
||||
[Alias("doc")]
|
||||
[switch] $docfx = $false,
|
||||
|
||||
# keep the build directories, don't clear them
|
||||
[Parameter(Mandatory=$false)]
|
||||
[Alias("c")]
|
||||
[Alias("cont")]
|
||||
[switch] $continue = $false,
|
||||
|
||||
# execute a command
|
||||
[Parameter(Mandatory=$false, ValueFromRemainingArguments=$true)]
|
||||
[String[]]
|
||||
$command
|
||||
[switch] $continue = $false
|
||||
)
|
||||
|
||||
# ################################################################
|
||||
@@ -36,7 +26,7 @@
|
||||
$ubuild = &"$PSScriptRoot\build-bootstrap.ps1"
|
||||
if (-not $?) { return }
|
||||
$ubuild.Boot($PSScriptRoot,
|
||||
@{ Local = $local; WithDocFx = $docfx },
|
||||
@{ Local = $local; },
|
||||
@{ Continue = $continue })
|
||||
if ($ubuild.OnError()) { return }
|
||||
|
||||
@@ -392,13 +382,13 @@
|
||||
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.Core.nuspec" `
|
||||
-Properties BuildTmp="$($this.BuildTemp)" `
|
||||
-Version "$($this.Version.Semver.ToString())" `
|
||||
-Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmscore.log"
|
||||
-Symbols -Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmscore.log"
|
||||
if (-not $?) { throw "Failed to pack NuGet UmbracoCms.Core." }
|
||||
|
||||
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.Web.nuspec" `
|
||||
-Properties BuildTmp="$($this.BuildTemp)" `
|
||||
-Version "$($this.Version.Semver.ToString())" `
|
||||
-Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmsweb.log"
|
||||
-Symbols -Verbosity detailed -outputDirectory "$($this.BuildOutput)" > "$($this.BuildTemp)\nupack.cmsweb.log"
|
||||
if (-not $?) { throw "Failed to pack NuGet UmbracoCms.Web." }
|
||||
|
||||
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.nuspec" `
|
||||
@@ -430,53 +420,6 @@
|
||||
$this.CopyFile("$($this.SolutionRoot)\build\Azure\azuregalleryrelease.ps1", $this.BuildOutput)
|
||||
})
|
||||
|
||||
$ubuild.DefineMethod("PrepareCSharpDocs",
|
||||
{
|
||||
Write-Host "Prepare C# Documentation"
|
||||
|
||||
$src = "$($this.SolutionRoot)\src"
|
||||
$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
|
||||
|
||||
& $DocFx metadata $DocFxJson
|
||||
& $DocFx build $DocFxJson
|
||||
|
||||
# zip it
|
||||
& $this.BuildEnv.Zip a -tzip -r "$out\csharp-docs.zip" $DocFxSiteOutput
|
||||
})
|
||||
|
||||
$ubuild.DefineMethod("PrepareAngularDocs",
|
||||
{
|
||||
Write-Host "Prepare Angular Documentation"
|
||||
|
||||
$src = "$($this.SolutionRoot)\src"
|
||||
$out = $this.BuildOutput
|
||||
|
||||
$this.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
|
||||
& $this.BuildEnv.Zip a -tzip -r "$out\ui-docs.zip" "$src\Umbraco.Web.UI.Client\docs\api\*.*"
|
||||
})
|
||||
|
||||
$ubuild.DefineMethod("Build",
|
||||
{
|
||||
$error.Clear()
|
||||
@@ -508,7 +451,6 @@
|
||||
if ($this.OnError()) { return }
|
||||
$this.PostPackageHook()
|
||||
if ($this.OnError()) { return }
|
||||
|
||||
Write-Host "Done"
|
||||
})
|
||||
|
||||
@@ -533,11 +475,7 @@
|
||||
# run
|
||||
if (-not $get)
|
||||
{
|
||||
if ($command.Length -eq 0)
|
||||
{
|
||||
$command = @( "Build" )
|
||||
}
|
||||
$ubuild.RunMethod($command);
|
||||
$ubuild.Build()
|
||||
if ($ubuild.OnError()) { return }
|
||||
}
|
||||
if ($get) { return $ubuild }
|
||||
|
||||
+24
-10
@@ -2,20 +2,21 @@
|
||||
"metadata": [
|
||||
{
|
||||
"src": [
|
||||
{
|
||||
"src": "../",
|
||||
{
|
||||
"files": [
|
||||
"Umbraco.Core/Umbraco.Core.csproj",
|
||||
"Umbraco.Web/Umbraco.Web.csproj"
|
||||
],
|
||||
"exclude": [
|
||||
"**/obj/**",
|
||||
"**/bin/**"
|
||||
]
|
||||
"**/bin/**",
|
||||
"_site/**"
|
||||
],
|
||||
"cwd": "../src"
|
||||
}
|
||||
],
|
||||
"dest": "api",
|
||||
"filter": "docfx.filter.yml"
|
||||
"dest": "../apidocs/api",
|
||||
"filter": "../apidocs/docfx.filter.yml"
|
||||
}
|
||||
],
|
||||
"build": {
|
||||
@@ -34,7 +35,19 @@
|
||||
"*.md"
|
||||
],
|
||||
"exclude": [
|
||||
"obj/**"
|
||||
"obj/**",
|
||||
"_site/**"
|
||||
]
|
||||
}
|
||||
],
|
||||
"resource": [
|
||||
{
|
||||
"files": [
|
||||
"images/**"
|
||||
],
|
||||
"exclude": [
|
||||
"obj/**",
|
||||
"_site/**"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -44,7 +57,8 @@
|
||||
"**.md"
|
||||
],
|
||||
"exclude": [
|
||||
"obj/**"
|
||||
"obj/**",
|
||||
"_site/**"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -53,9 +67,9 @@
|
||||
"_enableSearch": true,
|
||||
"_disableContribution": false
|
||||
},
|
||||
"dest": "../../build.tmp/_site",
|
||||
"dest": "_site",
|
||||
"template": [
|
||||
"default", "umbracotemplate"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -18,5 +18,5 @@ using System.Resources;
|
||||
[assembly: AssemblyVersion("8.0.0")]
|
||||
|
||||
// these are FYI and changed automatically
|
||||
[assembly: AssemblyFileVersion("8.2.0")]
|
||||
[assembly: AssemblyInformationalVersion("8.2.0")]
|
||||
[assembly: AssemblyFileVersion("8.0.2")]
|
||||
[assembly: AssemblyInformationalVersion("8.0.2")]
|
||||
|
||||
@@ -67,34 +67,31 @@ 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();
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
//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);
|
||||
//}
|
||||
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()
|
||||
{
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using Umbraco.Core;
|
||||
|
||||
// no binding redirect for now = de-activate
|
||||
//[assembly: PreApplicationStartMethod(typeof(BindingRedirects), "Initialize")]
|
||||
[assembly: PreApplicationStartMethod(typeof(BindingRedirects), "Initialize")]
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -18,7 +18,7 @@ namespace Umbraco.Core
|
||||
// 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>
|
||||
@@ -27,19 +27,14 @@ namespace Umbraco.Core
|
||||
/// <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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
using Umbraco.Core.Scoping;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
@@ -12,6 +13,11 @@ namespace Umbraco.Core.Cache
|
||||
|
||||
public static NoCacheRepositoryCachePolicy<TEntity, TId> Instance { get; } = new NoCacheRepositoryCachePolicy<TEntity, TId>();
|
||||
|
||||
public IRepositoryCachePolicy<TEntity, TId> Scoped(IAppPolicyCache runtimeCache, IScope scope)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public TEntity Get(TId id, Func<TId, TEntity> performGet, Func<TId[], IEnumerable<TEntity>> performGetAll)
|
||||
{
|
||||
return performGet(id);
|
||||
|
||||
@@ -44,22 +44,21 @@ namespace Umbraco.Core.Compose
|
||||
public void Terminate()
|
||||
{ }
|
||||
|
||||
internal static IUser UnknownUser => new User { Id = Constants.Security.UnknownUserId, Name = Constants.Security.UnknownUserName, Email = "" };
|
||||
|
||||
private IUser CurrentPerformingUser
|
||||
{
|
||||
get
|
||||
{
|
||||
var identity = Thread.CurrentPrincipal?.GetUmbracoIdentity();
|
||||
var user = identity == null ? null : _userService.GetUserById(Convert.ToInt32(identity.Id));
|
||||
return user ?? UnknownUser;
|
||||
return identity == null
|
||||
? new User { Id = 0, Name = "SYSTEM", Email = "" }
|
||||
: _userService.GetUserById(Convert.ToInt32(identity.Id));
|
||||
}
|
||||
}
|
||||
|
||||
private IUser GetPerformingUser(int userId)
|
||||
{
|
||||
var found = userId >= 0 ? _userService.GetUserById(userId) : null;
|
||||
return found ?? UnknownUser;
|
||||
return found ?? new User {Id = 0, Name = "SYSTEM", Email = ""};
|
||||
}
|
||||
|
||||
private string PerformingIp
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Umbraco.Core.Compose
|
||||
|
||||
private static void ContentService_Moved(IContentService sender, MoveEventArgs<IContent> e)
|
||||
{
|
||||
foreach (var item in e.MoveInfoCollection.Where(x => x.OriginalPath.Contains(Constants.System.RecycleBinContentString)))
|
||||
foreach (var item in e.MoveInfoCollection.Where(x => x.OriginalPath.Contains(Constants.System.RecycleBinContent.ToInvariantString())))
|
||||
{
|
||||
var relationService = Current.Services.RelationService;
|
||||
const string relationTypeAlias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias;
|
||||
@@ -37,7 +37,7 @@ namespace Umbraco.Core.Compose
|
||||
|
||||
private static void MediaService_Moved(IMediaService sender, MoveEventArgs<IMedia> e)
|
||||
{
|
||||
foreach (var item in e.MoveInfoCollection.Where(x => x.OriginalPath.Contains(Constants.System.RecycleBinMediaString)))
|
||||
foreach (var item in e.MoveInfoCollection.Where(x => x.OriginalPath.Contains(Constants.System.RecycleBinMedia.ToInvariantString())))
|
||||
{
|
||||
var relationService = Current.Services.RelationService;
|
||||
const string relationTypeAlias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias;
|
||||
|
||||
@@ -133,11 +133,7 @@ namespace Umbraco.Core.Composing
|
||||
|
||||
Configs.RegisterWith(_register);
|
||||
|
||||
IFactory factory = null;
|
||||
// ReSharper disable once AccessToModifiedClosure -- on purpose
|
||||
_register.Register(_ => factory, Lifetime.Singleton);
|
||||
factory = _register.CreateFactory();
|
||||
return factory;
|
||||
return _register.CreateFactory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Umbraco.Core.Mapping;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Models.Identity;
|
||||
|
||||
namespace Umbraco.Core.Composing.CompositionExtensions
|
||||
@@ -8,9 +8,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions
|
||||
{
|
||||
public static Composition ComposeCoreMappingProfiles(this Composition composition)
|
||||
{
|
||||
composition.RegisterUnique<UmbracoMapper>();
|
||||
composition.WithCollectionBuilder<MapDefinitionCollectionBuilder>()
|
||||
.Add<IdentityMapDefinition>();
|
||||
composition.Register<Profile, IdentityMapperProfile>();
|
||||
return composition;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ namespace Umbraco.Core.Composing.CompositionExtensions
|
||||
composition.RegisterUnique<IPartialViewRepository, PartialViewRepository>();
|
||||
composition.RegisterUnique<IScriptRepository, ScriptRepository>();
|
||||
composition.RegisterUnique<IStylesheetRepository, StylesheetRepository>();
|
||||
composition.RegisterUnique<IContentTypeCommonRepository, ContentTypeCommonRepository>();
|
||||
|
||||
return composition;
|
||||
}
|
||||
|
||||
@@ -98,6 +98,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions
|
||||
: appPlugins.GetDirectories()
|
||||
.SelectMany(x => x.GetDirectories("Lang"))
|
||||
.SelectMany(x => x.GetFiles("*.xml", SearchOption.TopDirectoryOnly))
|
||||
.Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 5)
|
||||
.Select(x => new LocalizedTextServiceSupplementaryFileSource(x, false));
|
||||
|
||||
//user defined langs that overwrite the default, these should not be used by plugin creators
|
||||
@@ -105,6 +106,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions
|
||||
? Enumerable.Empty<LocalizedTextServiceSupplementaryFileSource>()
|
||||
: configLangFolder
|
||||
.GetFiles("*.user.xml", SearchOption.TopDirectoryOnly)
|
||||
.Where(x => Path.GetFileNameWithoutExtension(x.FullName).Length == 10)
|
||||
.Select(x => new LocalizedTextServiceSupplementaryFileSource(x, true));
|
||||
|
||||
return new LocalizedTextServiceFileSources(
|
||||
|
||||
@@ -4,7 +4,6 @@ using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Dictionary;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.PackageActions;
|
||||
using Umbraco.Core.Packaging;
|
||||
@@ -104,9 +103,6 @@ namespace Umbraco.Core.Composing
|
||||
|
||||
#region Getters
|
||||
|
||||
public static UmbracoMapper Mapper
|
||||
=> _factory.GetInstance<UmbracoMapper>();
|
||||
|
||||
public static IShortStringHelper ShortStringHelper
|
||||
=> _shortStringHelper ?? (_shortStringHelper = _factory?.TryGetInstance<IShortStringHelper>()
|
||||
?? new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(Configs.Settings())));
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Composing
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements an un-ordered collection builder.
|
||||
/// </summary>
|
||||
/// <typeparam name="TBuilder">The type of the builder.</typeparam>
|
||||
/// <typeparam name="TCollection">The type of the collection.</typeparam>
|
||||
/// <typeparam name="TItem">The type of the items.</typeparam>
|
||||
/// <remarks>
|
||||
/// <para>A set collection builder is the most basic collection builder,
|
||||
/// where items are not ordered.</para>
|
||||
/// </remarks>
|
||||
public abstract class SetCollectionBuilderBase<TBuilder, TCollection, TItem> : CollectionBuilderBase<TBuilder, TCollection, TItem>
|
||||
where TBuilder : SetCollectionBuilderBase<TBuilder, TCollection, TItem>
|
||||
where TCollection : class, IBuilderCollection<TItem>
|
||||
{
|
||||
protected abstract TBuilder This { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Clears all types in the collection.
|
||||
/// </summary>
|
||||
/// <returns>The builder.</returns>
|
||||
public TBuilder Clear()
|
||||
{
|
||||
Configure(types => types.Clear());
|
||||
return This;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a type to the collection.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to append.</typeparam>
|
||||
/// <returns>The builder.</returns>
|
||||
public TBuilder Add<T>()
|
||||
where T : TItem
|
||||
{
|
||||
Configure(types =>
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (types.Contains(type)) types.Remove(type);
|
||||
types.Add(type);
|
||||
});
|
||||
return This;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a type to the collection.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to append.</param>
|
||||
/// <returns>The builder.</returns>
|
||||
public TBuilder Add(Type type)
|
||||
{
|
||||
Configure(types =>
|
||||
{
|
||||
EnsureType(type, "register");
|
||||
if (types.Contains(type)) types.Remove(type);
|
||||
types.Add(type);
|
||||
});
|
||||
return This;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds types to the collections.
|
||||
/// </summary>
|
||||
/// <param name="types">The types to append.</param>
|
||||
/// <returns>The builder.</returns>
|
||||
public TBuilder Add(IEnumerable<Type> types)
|
||||
{
|
||||
Configure(list =>
|
||||
{
|
||||
foreach (var type in types)
|
||||
{
|
||||
// would be detected by CollectionBuilderBase when registering, anyways, but let's fail fast
|
||||
EnsureType(type, "register");
|
||||
if (list.Contains(type)) list.Remove(type);
|
||||
list.Add(type);
|
||||
}
|
||||
});
|
||||
return This;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a type from the collection.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to remove.</typeparam>
|
||||
/// <returns>The builder.</returns>
|
||||
public TBuilder Remove<T>()
|
||||
where T : TItem
|
||||
{
|
||||
Configure(types =>
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (types.Contains(type)) types.Remove(type);
|
||||
});
|
||||
return This;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a type from the collection.
|
||||
/// </summary>
|
||||
/// <param name="type">The type to remove.</param>
|
||||
/// <returns>The builder.</returns>
|
||||
public TBuilder Remove(Type type)
|
||||
{
|
||||
Configure(types =>
|
||||
{
|
||||
EnsureType(type, "remove");
|
||||
if (types.Contains(type)) types.Remove(type);
|
||||
});
|
||||
return This;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces a type in the collection.
|
||||
/// </summary>
|
||||
/// <typeparam name="TReplaced">The type to replace.</typeparam>
|
||||
/// <typeparam name="T">The type to insert.</typeparam>
|
||||
/// <returns>The builder.</returns>
|
||||
/// <remarks>Throws if the type to replace does not already belong to the collection.</remarks>
|
||||
public TBuilder Replace<TReplaced, T>()
|
||||
where TReplaced : TItem
|
||||
where T : TItem
|
||||
{
|
||||
Configure(types =>
|
||||
{
|
||||
var typeReplaced = typeof(TReplaced);
|
||||
var type = typeof(T);
|
||||
if (typeReplaced == type) return;
|
||||
|
||||
var index = types.IndexOf(typeReplaced);
|
||||
if (index < 0) throw new InvalidOperationException();
|
||||
|
||||
if (types.Contains(type)) types.Remove(type);
|
||||
index = types.IndexOf(typeReplaced); // in case removing type changed index
|
||||
types.Insert(index, type);
|
||||
types.Remove(typeReplaced);
|
||||
});
|
||||
return This;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces a type in the collection.
|
||||
/// </summary>
|
||||
/// <param name="typeReplaced">The type to replace.</param>
|
||||
/// <param name="type">The type to insert.</param>
|
||||
/// <returns>The builder.</returns>
|
||||
/// <remarks>Throws if the type to replace does not already belong to the collection.</remarks>
|
||||
public TBuilder Replace(Type typeReplaced, Type type)
|
||||
{
|
||||
Configure(types =>
|
||||
{
|
||||
EnsureType(typeReplaced, "find");
|
||||
EnsureType(type, "register");
|
||||
|
||||
if (typeReplaced == type) return;
|
||||
|
||||
var index = types.IndexOf(typeReplaced);
|
||||
if (index < 0) throw new InvalidOperationException();
|
||||
|
||||
if (types.Contains(type)) types.Remove(type);
|
||||
index = types.IndexOf(typeReplaced); // in case removing type changed index
|
||||
types.Insert(index, type);
|
||||
types.Remove(typeReplaced);
|
||||
});
|
||||
return This;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,50 +6,30 @@ namespace Umbraco.Core.Composing
|
||||
/// <summary>
|
||||
/// Provides a base class for collections of types.
|
||||
/// </summary>
|
||||
public abstract class TypeCollectionBuilderBase<TBuilder, TCollection, TConstraint> : ICollectionBuilder<TCollection, Type>
|
||||
where TBuilder : TypeCollectionBuilderBase<TBuilder, TCollection, TConstraint>
|
||||
public abstract class TypeCollectionBuilderBase<TCollection, TConstraint> : ICollectionBuilder<TCollection, Type>
|
||||
where TCollection : class, IBuilderCollection<Type>
|
||||
{
|
||||
private readonly HashSet<Type> _types = new HashSet<Type>();
|
||||
|
||||
protected abstract TBuilder This { get; }
|
||||
|
||||
private static Type Validate(Type type, string action)
|
||||
private Type Validate(Type type, string action)
|
||||
{
|
||||
if (!typeof(TConstraint).IsAssignableFrom(type))
|
||||
throw new InvalidOperationException($"Cannot {action} type {type.FullName} as it does not inherit from/implement {typeof(TConstraint).FullName}.");
|
||||
return type;
|
||||
}
|
||||
|
||||
public TBuilder Add(Type type)
|
||||
{
|
||||
_types.Add(Validate(type, "add"));
|
||||
return This;
|
||||
}
|
||||
public void Add(Type type) => _types.Add(Validate(type, "add"));
|
||||
|
||||
public TBuilder Add<T>()
|
||||
{
|
||||
Add(typeof(T));
|
||||
return This;
|
||||
}
|
||||
public void Add<T>() => Add(typeof(T));
|
||||
|
||||
public TBuilder Add(IEnumerable<Type> types)
|
||||
public void Add(IEnumerable<Type> types)
|
||||
{
|
||||
foreach (var type in types) Add(type);
|
||||
return This;
|
||||
}
|
||||
|
||||
public TBuilder Remove(Type type)
|
||||
{
|
||||
_types.Remove(Validate(type, "remove"));
|
||||
return This;
|
||||
}
|
||||
public void Remove(Type type) => _types.Remove(Validate(type, "remove"));
|
||||
|
||||
public TBuilder Remove<T>()
|
||||
{
|
||||
Remove(typeof(T));
|
||||
return This;
|
||||
}
|
||||
public void Remove<T>() => Remove(typeof(T));
|
||||
|
||||
public TCollection CreateCollection(IFactory factory)
|
||||
{
|
||||
|
||||
@@ -42,8 +42,8 @@ namespace Umbraco.Core.Composing
|
||||
private string _currentAssembliesHash;
|
||||
private IEnumerable<Assembly> _assemblies;
|
||||
private bool _reportedChange;
|
||||
private readonly string _localTempPath;
|
||||
private string _fileBasePath;
|
||||
private static string _localTempPath;
|
||||
private static string _fileBasePath;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TypeLoader"/> class.
|
||||
|
||||
@@ -4,7 +4,6 @@ using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Dictionary;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging.Viewer;
|
||||
using Umbraco.Core.Manifest;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.PackageActions;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
@@ -67,16 +66,9 @@ namespace Umbraco.Core
|
||||
/// Gets the validators collection builder.
|
||||
/// </summary>
|
||||
/// <param name="composition">The composition.</param>
|
||||
internal static ManifestValueValidatorCollectionBuilder ManifestValueValidators(this Composition composition)
|
||||
internal static ManifestValueValidatorCollectionBuilder Validators(this Composition composition)
|
||||
=> composition.WithCollectionBuilder<ManifestValueValidatorCollectionBuilder>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the manifest filter collection builder.
|
||||
/// </summary>
|
||||
/// <param name="composition">The composition.</param>
|
||||
public static ManifestFilterCollectionBuilder ManifestFilters(this Composition composition)
|
||||
=> composition.WithCollectionBuilder<ManifestFilterCollectionBuilder>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the components collection builder.
|
||||
/// </summary>
|
||||
|
||||
@@ -7,7 +7,6 @@ using Umbraco.Core.Configuration.HealthChecks;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Manifest;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -42,12 +41,7 @@ namespace Umbraco.Core
|
||||
configs.Add(() => new CoreDebug());
|
||||
|
||||
// GridConfig depends on runtime caches, manifest parsers... and cannot be available during composition
|
||||
configs.Add<IGridConfig>(factory => new GridConfig(
|
||||
factory.GetInstance<ILogger>(),
|
||||
factory.GetInstance<AppCaches>(),
|
||||
configDir,
|
||||
factory.GetInstance<ManifestParser>(),
|
||||
factory.GetInstance<IRuntimeState>().Debug));
|
||||
configs.Add<IGridConfig>(factory => new GridConfig(factory.GetInstance<ILogger>(), factory.GetInstance<AppCaches>(), configDir, factory.GetInstance<IRuntimeState>().Debug));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Linq;
|
||||
using System.Net.Configuration;
|
||||
using System.Web;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Hosting;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
@@ -18,15 +17,16 @@ namespace Umbraco.Core.Configuration
|
||||
/// </summary>
|
||||
public class GlobalSettings : IGlobalSettings
|
||||
{
|
||||
private string _localTempPath;
|
||||
|
||||
// TODO these should not be static
|
||||
#region Private static fields
|
||||
|
||||
|
||||
private static string _reservedPaths;
|
||||
private static string _reservedUrls;
|
||||
|
||||
//ensure the built on (non-changeable) reserved paths are there at all times
|
||||
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!
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Used in unit testing to reset all config items that were set with property setters (i.e. did not come from config)
|
||||
@@ -131,7 +131,7 @@ namespace Umbraco.Core.Configuration
|
||||
: "~/App_Data/umbraco.config";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to umbraco's root directory (/umbraco by default).
|
||||
/// </summary>
|
||||
@@ -163,7 +163,7 @@ namespace Umbraco.Core.Configuration
|
||||
SaveSetting(Constants.AppSettings.ConfigurationStatus, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Saves a setting into the configuration file.
|
||||
/// </summary>
|
||||
@@ -206,7 +206,7 @@ namespace Umbraco.Core.Configuration
|
||||
ConfigurationManager.RefreshSection("appSettings");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether umbraco is running in [debug mode].
|
||||
/// </summary>
|
||||
@@ -250,7 +250,7 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of days that should take place between version checks.
|
||||
/// </summary>
|
||||
@@ -269,7 +269,7 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public LocalTempStorage LocalTempStorageLocation
|
||||
{
|
||||
@@ -288,43 +288,25 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_localTempPath != null)
|
||||
return _localTempPath;
|
||||
|
||||
switch (LocalTempStorageLocation)
|
||||
{
|
||||
case LocalTempStorage.AspNetTemp:
|
||||
return _localTempPath = System.IO.Path.Combine(HttpRuntime.CodegenDir, "UmbracoData");
|
||||
|
||||
return System.IO.Path.Combine(HttpRuntime.CodegenDir, "UmbracoData");
|
||||
case LocalTempStorage.EnvironmentTemp:
|
||||
|
||||
// environment temp is unique, we need a folder per site
|
||||
|
||||
// use a hash
|
||||
// combine site name and application id
|
||||
// site name is a Guid on Cloud
|
||||
// application id is eg /LM/W3SVC/123456/ROOT
|
||||
// the combination is unique on one server
|
||||
// and, if a site moves from worker A to B and then back to A...
|
||||
// hopefully it gets a new Guid or new application id?
|
||||
|
||||
var siteName = HostingEnvironment.SiteName;
|
||||
var applicationId = HostingEnvironment.ApplicationID; // ie HttpRuntime.AppDomainAppId
|
||||
|
||||
var hashString = siteName + "::" + applicationId;
|
||||
var hash = hashString.GenerateHash();
|
||||
var siteTemp = System.IO.Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData", hash);
|
||||
|
||||
return _localTempPath = siteTemp;
|
||||
|
||||
// include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
|
||||
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
|
||||
// utilizing an old path - assuming we cannot have SHA1 collisions on AppDomainAppId
|
||||
var appDomainHash = HttpRuntime.AppDomainAppId.GenerateHash();
|
||||
return System.IO.Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData", appDomainHash);
|
||||
//case LocalTempStorage.Default:
|
||||
//case LocalTempStorage.Unknown:
|
||||
default:
|
||||
return _localTempPath = IOHelper.MapPath("~/App_Data/TEMP");
|
||||
return IOHelper.MapPath("~/App_Data/TEMP");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default UI language.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
using System.IO;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Manifest;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Grid
|
||||
{
|
||||
class GridConfig : IGridConfig
|
||||
{
|
||||
public GridConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, ManifestParser manifestParser, bool isDebug)
|
||||
public GridConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, bool isDebug)
|
||||
{
|
||||
EditorsConfig = new GridEditorsConfig(logger, appCaches, configFolder, manifestParser, isDebug);
|
||||
EditorsConfig = new GridEditorsConfig(logger, appCaches, configFolder, isDebug);
|
||||
}
|
||||
|
||||
public IGridEditorsConfig EditorsConfig { get; }
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Manifest;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
@@ -13,15 +15,13 @@ namespace Umbraco.Core.Configuration.Grid
|
||||
private readonly ILogger _logger;
|
||||
private readonly AppCaches _appCaches;
|
||||
private readonly DirectoryInfo _configFolder;
|
||||
private readonly ManifestParser _manifestParser;
|
||||
private readonly bool _isDebug;
|
||||
|
||||
public GridEditorsConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, ManifestParser manifestParser, bool isDebug)
|
||||
public GridEditorsConfig(ILogger logger, AppCaches appCaches, DirectoryInfo configFolder, bool isDebug)
|
||||
{
|
||||
_logger = logger;
|
||||
_appCaches = appCaches;
|
||||
_configFolder = configFolder;
|
||||
_manifestParser = manifestParser;
|
||||
_isDebug = isDebug;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,9 @@ namespace Umbraco.Core.Configuration.Grid
|
||||
{
|
||||
List<GridEditor> GetResult()
|
||||
{
|
||||
// TODO: should use the common one somehow! + ignoring _appPlugins here!
|
||||
var parser = new ManifestParser(_appCaches, Current.ManifestValidators, _logger);
|
||||
|
||||
var editors = new List<GridEditor>();
|
||||
var gridConfig = Path.Combine(_configFolder.FullName, "grid.editors.config.js");
|
||||
if (File.Exists(gridConfig))
|
||||
@@ -39,7 +42,7 @@ namespace Umbraco.Core.Configuration.Grid
|
||||
|
||||
try
|
||||
{
|
||||
editors.AddRange(_manifestParser.ParseGridEditors(sourceString));
|
||||
editors.AddRange(parser.ParseGridEditors(sourceString));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -48,7 +51,7 @@ namespace Umbraco.Core.Configuration.Grid
|
||||
}
|
||||
|
||||
// add manifest editors, skip duplicates
|
||||
foreach (var gridEditor in _manifestParser.Manifest.GridEditors)
|
||||
foreach (var gridEditor in parser.Manifest.GridEditors)
|
||||
{
|
||||
if (editors.Contains(gridEditor) == false) editors.Add(gridEditor);
|
||||
}
|
||||
|
||||
@@ -93,6 +93,7 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string DisableElectionForSingleServer = "Umbraco.Core.DisableElectionForSingleServer";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Debug specific web.config AppSetting keys for Umbraco
|
||||
/// </summary>
|
||||
|
||||
@@ -145,11 +145,11 @@
|
||||
|
||||
public const string PartialViewMacros = "partialViewMacros";
|
||||
|
||||
public const string LogViewer = "logViewer";
|
||||
public const string LogViewer = "logViewer";
|
||||
|
||||
public static class Groups
|
||||
{
|
||||
public const string Settings = "settingsGroup";
|
||||
public const string Settings = "settingsGroup";
|
||||
|
||||
public const string Templating = "templatingGroup";
|
||||
|
||||
|
||||
@@ -92,10 +92,10 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string Extension = "umbracoExtension";
|
||||
|
||||
/// <summary>
|
||||
/// The default height/width of an image file if the size can't be determined from the metadata
|
||||
/// </summary>
|
||||
public const int DefaultSize = 200;
|
||||
/// <summary>
|
||||
/// The default height/width of an image file if the size can't be determined from the metadata
|
||||
/// </summary>
|
||||
public const int DefaultSize = 200;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -209,71 +209,71 @@ namespace Umbraco.Core
|
||||
public static Dictionary<string, PropertyType> GetStandardPropertyTypeStubs()
|
||||
{
|
||||
return new Dictionary<string, PropertyType>
|
||||
{
|
||||
{
|
||||
Comments,
|
||||
new PropertyType(PropertyEditors.Aliases.TextArea, ValueStorageType.Ntext, true, Comments)
|
||||
{
|
||||
Name = CommentsLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
FailedPasswordAttempts,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Integer, true, FailedPasswordAttempts)
|
||||
Comments,
|
||||
new PropertyType(PropertyEditors.Aliases.TextArea, ValueStorageType.Ntext, true, Comments)
|
||||
{
|
||||
Name = CommentsLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
Name = FailedPasswordAttemptsLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
IsApproved,
|
||||
new PropertyType(PropertyEditors.Aliases.Boolean, ValueStorageType.Integer, true, IsApproved)
|
||||
FailedPasswordAttempts,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Integer, true, FailedPasswordAttempts)
|
||||
{
|
||||
Name = FailedPasswordAttemptsLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
Name = IsApprovedLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
IsLockedOut,
|
||||
new PropertyType(PropertyEditors.Aliases.Boolean, ValueStorageType.Integer, true, IsLockedOut)
|
||||
IsApproved,
|
||||
new PropertyType(PropertyEditors.Aliases.Boolean, ValueStorageType.Integer, true, IsApproved)
|
||||
{
|
||||
Name = IsApprovedLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
Name = IsLockedOutLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
LastLockoutDate,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Date, true, LastLockoutDate)
|
||||
IsLockedOut,
|
||||
new PropertyType(PropertyEditors.Aliases.Boolean, ValueStorageType.Integer, true, IsLockedOut)
|
||||
{
|
||||
Name = IsLockedOutLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
Name = LastLockoutDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
LastLoginDate,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Date, true, LastLoginDate)
|
||||
LastLockoutDate,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Date, true, LastLockoutDate)
|
||||
{
|
||||
Name = LastLockoutDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
Name = LastLoginDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
LastPasswordChangeDate,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Date, true, LastPasswordChangeDate)
|
||||
LastLoginDate,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Date, true, LastLoginDate)
|
||||
{
|
||||
Name = LastLoginDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
Name = LastPasswordChangeDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
PasswordAnswer,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Nvarchar, true, PasswordAnswer)
|
||||
LastPasswordChangeDate,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Date, true, LastPasswordChangeDate)
|
||||
{
|
||||
Name = LastPasswordChangeDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
Name = PasswordAnswerLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
PasswordQuestion,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Nvarchar, true, PasswordQuestion)
|
||||
PasswordAnswer,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Nvarchar, true, PasswordAnswer)
|
||||
{
|
||||
Name = PasswordAnswerLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
Name = PasswordQuestionLabel
|
||||
PasswordQuestion,
|
||||
new PropertyType(PropertyEditors.Aliases.Label, ValueStorageType.Nvarchar, true, PasswordQuestion)
|
||||
{
|
||||
Name = PasswordQuestionLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,375 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
{
|
||||
public static class DataTypes
|
||||
{
|
||||
//NOTE: unfortunately due to backwards compat we can't move/rename these, with the addition of the GUID
|
||||
//constants, it would make more sense to have these suffixed with "ID" or in a Subclass called "INT", for
|
||||
//now all we can do is make a subclass called Guids to put the GUID IDs.
|
||||
|
||||
public const int LabelString = System.DefaultLabelDataTypeId;
|
||||
public const int LabelString = -92;
|
||||
public const int LabelInt = -91;
|
||||
public const int LabelBigint = -93;
|
||||
public const int LabelDateTime = -94;
|
||||
public const int LabelTime = -98;
|
||||
public const int LabelDecimal = -99;
|
||||
|
||||
public const int Textarea = -89;
|
||||
public const int Textbox = -88;
|
||||
public const int RichtextEditor = -87;
|
||||
public const int Boolean = -49;
|
||||
public const int DateTime = -36;
|
||||
public const int DropDownSingle = -39;
|
||||
public const int DropDownMultiple = -42;
|
||||
public const int Upload = -90;
|
||||
|
||||
public const int DefaultContentListView = -95;
|
||||
public const int DefaultMediaListView = -96;
|
||||
public const int DefaultMembersListView = -97;
|
||||
|
||||
public const int ImageCropper = 1043;
|
||||
public const int Tags = 1041;
|
||||
|
||||
public static class ReservedPreValueKeys
|
||||
{
|
||||
public const string IgnoreUserStartNodes = "ignoreUserStartNodes";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the identifiers for Umbraco data types as constants for easy centralized access/management.
|
||||
/// </summary>
|
||||
public static class Guids
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Content Picker as string
|
||||
/// </summary>
|
||||
public const string ContentPicker = "FD1E0DA5-5606-4862-B679-5D0CF3A52A59";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Content Picker
|
||||
/// </summary>
|
||||
public static readonly Guid ContentPickerGuid = new Guid(ContentPicker);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Member Picker as string
|
||||
/// </summary>
|
||||
public const string MemberPicker = "1EA2E01F-EBD8-4CE1-8D71-6B1149E63548";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Member Picker
|
||||
/// </summary>
|
||||
public static readonly Guid MemberPickerGuid = new Guid(MemberPicker);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Media Picker as string
|
||||
/// </summary>
|
||||
public const string MediaPicker = "135D60E0-64D9-49ED-AB08-893C9BA44AE5";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Media Picker
|
||||
/// </summary>
|
||||
public static readonly Guid MediaPickerGuid = new Guid(MediaPicker);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Multiple Media Picker as string
|
||||
/// </summary>
|
||||
public const string MultipleMediaPicker = "9DBBCBBB-2327-434A-B355-AF1B84E5010A";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Multiple Media Picker
|
||||
/// </summary>
|
||||
public static readonly Guid MultipleMediaPickerGuid = new Guid(MultipleMediaPicker);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Related Links as string
|
||||
/// </summary>
|
||||
public const string RelatedLinks = "B4E3535A-1753-47E2-8568-602CF8CFEE6F";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Related Links
|
||||
/// </summary>
|
||||
public static readonly Guid RelatedLinksGuid = new Guid(RelatedLinks);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Member as string
|
||||
/// </summary>
|
||||
public const string Member = "d59be02f-1df9-4228-aa1e-01917d806cda";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Member
|
||||
/// </summary>
|
||||
public static readonly Guid MemberGuid = new Guid(Member);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Image Cropper as string
|
||||
/// </summary>
|
||||
public const string ImageCropper = "1df9f033-e6d4-451f-b8d2-e0cbc50a836f";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Image Cropper
|
||||
/// </summary>
|
||||
public static readonly Guid ImageCropperGuid = new Guid(ImageCropper);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Tags as string
|
||||
/// </summary>
|
||||
public const string Tags = "b6b73142-b9c1-4bf8-a16d-e1c23320b549";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Tags
|
||||
/// </summary>
|
||||
public static readonly Guid TagsGuid = new Guid(Tags);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for List View - Content as string
|
||||
/// </summary>
|
||||
public const string ListViewContent = "C0808DD3-8133-4E4B-8CE8-E2BEA84A96A4";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for List View - Content
|
||||
/// </summary>
|
||||
public static readonly Guid ListViewContentGuid = new Guid(ListViewContent);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for List View - Media as string
|
||||
/// </summary>
|
||||
public const string ListViewMedia = "3A0156C4-3B8C-4803-BDC1-6871FAA83FFF";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for List View - Media
|
||||
/// </summary>
|
||||
public static readonly Guid ListViewMediaGuid = new Guid(ListViewMedia);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for List View - Members as string
|
||||
/// </summary>
|
||||
public const string ListViewMembers = "AA2C52A0-CE87-4E65-A47C-7DF09358585D";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for List View - Members
|
||||
/// </summary>
|
||||
public static readonly Guid ListViewMembersGuid = new Guid(ListViewMembers);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Date Picker with time as string
|
||||
/// </summary>
|
||||
public const string DatePickerWithTime = "e4d66c0f-b935-4200-81f0-025f7256b89a";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Date Picker with time
|
||||
/// </summary>
|
||||
public static readonly Guid DatePickerWithTimeGuid = new Guid(DatePickerWithTime);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Approved Color as string
|
||||
/// </summary>
|
||||
public const string ApprovedColor = "0225af17-b302-49cb-9176-b9f35cab9c17";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Approved Color
|
||||
/// </summary>
|
||||
public static readonly Guid ApprovedColorGuid = new Guid(ApprovedColor);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Dropdown multiple as string
|
||||
/// </summary>
|
||||
public const string DropdownMultiple = "f38f0ac7-1d27-439c-9f3f-089cd8825a53";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Dropdown multiple
|
||||
/// </summary>
|
||||
public static readonly Guid DropdownMultipleGuid = new Guid(DropdownMultiple);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Radiobox as string
|
||||
/// </summary>
|
||||
public const string Radiobox = "bb5f57c9-ce2b-4bb9-b697-4caca783a805";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Radiobox
|
||||
/// </summary>
|
||||
public static readonly Guid RadioboxGuid = new Guid(Radiobox);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Date Picker as string
|
||||
/// </summary>
|
||||
public const string DatePicker = "5046194e-4237-453c-a547-15db3a07c4e1";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Date Picker
|
||||
/// </summary>
|
||||
public static readonly Guid DatePickerGuid = new Guid(DatePicker);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Dropdown as string
|
||||
/// </summary>
|
||||
public const string Dropdown = "0b6a45e7-44ba-430d-9da5-4e46060b9e03";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Dropdown
|
||||
/// </summary>
|
||||
public static readonly Guid DropdownGuid = new Guid(Dropdown);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Checkbox list as string
|
||||
/// </summary>
|
||||
public const string CheckboxList = "fbaf13a8-4036-41f2-93a3-974f678c312a";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Checkbox list
|
||||
/// </summary>
|
||||
public static readonly Guid CheckboxListGuid = new Guid(CheckboxList);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Checkbox as string
|
||||
/// </summary>
|
||||
public const string Checkbox = "92897bc6-a5f3-4ffe-ae27-f2e7e33dda49";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Checkbox
|
||||
/// </summary>
|
||||
public static readonly Guid CheckboxGuid = new Guid(Checkbox);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Numeric as string
|
||||
/// </summary>
|
||||
public const string Numeric = "2e6d3631-066e-44b8-aec4-96f09099b2b5";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Dropdown
|
||||
/// </summary>
|
||||
public static readonly Guid NumericGuid = new Guid(Numeric);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Richtext editor as string
|
||||
/// </summary>
|
||||
public const string RichtextEditor = "ca90c950-0aff-4e72-b976-a30b1ac57dad";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Richtext editor
|
||||
/// </summary>
|
||||
public static readonly Guid RichtextEditorGuid = new Guid(RichtextEditor);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Textstring as string
|
||||
/// </summary>
|
||||
public const string Textstring = "0cc0eba1-9960-42c9-bf9b-60e150b429ae";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Textstring
|
||||
/// </summary>
|
||||
public static readonly Guid TextstringGuid = new Guid(Textstring);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Textarea as string
|
||||
/// </summary>
|
||||
public const string Textarea = "c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Dropdown
|
||||
/// </summary>
|
||||
public static readonly Guid TextareaGuid = new Guid(Textarea);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Upload as string
|
||||
/// </summary>
|
||||
public const string Upload = "84c6b441-31df-4ffe-b67e-67d5bc3ae65a";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Upload
|
||||
/// </summary>
|
||||
public static readonly Guid UploadGuid = new Guid(Upload);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Label as string
|
||||
/// </summary>
|
||||
public const string LabelString = "f0bc4bfb-b499-40d6-ba86-058885a5178c";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Label string
|
||||
/// </summary>
|
||||
public static readonly Guid LabelStringGuid = new Guid(LabelString);
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Label as int
|
||||
/// </summary>
|
||||
public const string LabelInt = "8e7f995c-bd81-4627-9932-c40e568ec788";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Label int
|
||||
/// </summary>
|
||||
public static readonly Guid LabelIntGuid = new Guid(LabelInt);
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Label as big int
|
||||
/// </summary>
|
||||
public const string LabelBigInt = "930861bf-e262-4ead-a704-f99453565708";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Label big int
|
||||
/// </summary>
|
||||
public static readonly Guid LabelBigIntGuid = new Guid(LabelBigInt);
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Label as date time
|
||||
/// </summary>
|
||||
public const string LabelDateTime = "0e9794eb-f9b5-4f20-a788-93acd233a7e4";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Label date time
|
||||
/// </summary>
|
||||
public static readonly Guid LabelDateTimeGuid = new Guid(LabelDateTime);
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Label as time
|
||||
/// </summary>
|
||||
public const string LabelTime = "a97cec69-9b71-4c30-8b12-ec398860d7e8";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Label time
|
||||
/// </summary>
|
||||
public static readonly Guid LabelTimeGuid = new Guid(LabelTime);
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Label as decimal
|
||||
/// </summary>
|
||||
public const string LabelDecimal = "8f1ef1e1-9de4-40d3-a072-6673f631ca64";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for Label decimal
|
||||
/// </summary>
|
||||
public static readonly Guid LabelDecimalGuid = new Guid(LabelDecimal);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,93 +1,53 @@
|
||||
namespace Umbraco.Core
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
{
|
||||
public static class Icons
|
||||
{
|
||||
/// <summary>
|
||||
/// System default icon
|
||||
/// </summary>
|
||||
public const string DefaultIcon = Content;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// System content icon
|
||||
/// System contenttype icon
|
||||
/// </summary>
|
||||
public const string Content = "icon-document";
|
||||
public const string ContentType = "icon-arrangement";
|
||||
|
||||
/// <summary>
|
||||
/// System content type icon
|
||||
/// </summary>
|
||||
public const string ContentType = "icon-item-arrangement";
|
||||
|
||||
/// <summary>
|
||||
/// System data type icon
|
||||
/// System datatype icon
|
||||
/// </summary>
|
||||
public const string DataType = "icon-autofill";
|
||||
|
||||
/// <summary>
|
||||
/// System list view icon
|
||||
/// </summary>
|
||||
public const string ListView = "icon-thumbnail-list";
|
||||
|
||||
/// <summary>
|
||||
/// System macro icon
|
||||
/// </summary>
|
||||
public const string Macro = "icon-settings-alt";
|
||||
|
||||
/// <summary>
|
||||
/// System media file icon
|
||||
/// </summary>
|
||||
public const string MediaFile = "icon-document";
|
||||
|
||||
/// <summary>
|
||||
/// System media folder icon
|
||||
/// </summary>
|
||||
public const string MediaFolder = "icon-folder";
|
||||
|
||||
/// <summary>
|
||||
/// System media image icon
|
||||
/// </summary>
|
||||
public const string MediaImage = "icon-picture";
|
||||
|
||||
/// <summary>
|
||||
/// System media type icon
|
||||
/// </summary>
|
||||
public const string MediaType = "icon-thumbnails";
|
||||
|
||||
/// <summary>
|
||||
/// System member icon
|
||||
/// </summary>
|
||||
public const string Member = "icon-user";
|
||||
|
||||
/// <summary>
|
||||
/// System member group icon
|
||||
/// </summary>
|
||||
public const string MemberGroup = "icon-users-alt";
|
||||
|
||||
/// <summary>
|
||||
/// System member type icon
|
||||
/// </summary>
|
||||
public const string MemberType = "icon-users";
|
||||
|
||||
/// <summary>
|
||||
/// System property editor icon
|
||||
/// </summary>
|
||||
public const string PropertyEditor = "icon-autofill";
|
||||
|
||||
/// <summary>
|
||||
/// System macro icon
|
||||
/// </summary>
|
||||
public const string Macro = "icon-settings-alt";
|
||||
|
||||
/// <summary>
|
||||
/// System member icon
|
||||
/// </summary>
|
||||
public const string Member = "icon-user";
|
||||
|
||||
/// <summary>
|
||||
/// System member icon
|
||||
/// </summary>
|
||||
public const string MemberType = "icon-users";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// System member icon
|
||||
/// </summary>
|
||||
public const string Template = "icon-layout";
|
||||
|
||||
/// <summary>
|
||||
/// System user icon
|
||||
/// </summary>
|
||||
public const string User = "icon-user";
|
||||
|
||||
/// <summary>
|
||||
/// System user group icon
|
||||
/// </summary>
|
||||
public const string UserGroup = "icon-users";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
namespace Umbraco.Core
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
{
|
||||
|
||||
@@ -123,6 +123,7 @@ namespace Umbraco.Core
|
||||
public static readonly Guid Template = new Guid(Strings.Template);
|
||||
|
||||
public static readonly Guid ContentItem = new Guid(Strings.ContentItem);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
public static partial class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the constants used for the Umbraco package repository
|
||||
/// Defines the constants used for the Umbraco package repository
|
||||
/// </summary>
|
||||
public static class PackageRepository
|
||||
{
|
||||
|
||||
@@ -14,23 +14,6 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string InternalGenericPropertiesPrefix = "_umb_";
|
||||
|
||||
public static class Legacy
|
||||
{
|
||||
public static class Aliases
|
||||
{
|
||||
public const string Textbox = "Umbraco.Textbox";
|
||||
public const string Date = "Umbraco.Date";
|
||||
public const string ContentPicker2 = "Umbraco.ContentPicker2";
|
||||
public const string MediaPicker2 = "Umbraco.MediaPicker2";
|
||||
public const string MemberPicker2 = "Umbraco.MemberPicker2";
|
||||
public const string MultiNodeTreePicker2 = "Umbraco.MultiNodeTreePicker2";
|
||||
public const string TextboxMultiple = "Umbraco.TextboxMultiple";
|
||||
public const string RelatedLinks2 = "Umbraco.RelatedLinks2";
|
||||
public const string RelatedLinks = "Umbraco.RelatedLinks";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines Umbraco built-in property editor aliases.
|
||||
/// </summary>
|
||||
@@ -51,6 +34,7 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string ContentPicker = "Umbraco.ContentPicker";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// DateTime.
|
||||
/// </summary>
|
||||
@@ -203,24 +187,6 @@ namespace Umbraco.Core
|
||||
/// <remarks>Must be a valid <see cref="ValueTypes"/> value.</remarks>
|
||||
public const string DataValueType = "umbracoDataValueType";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines Umbraco's built-in property editor groups.
|
||||
/// </summary>
|
||||
public static class Groups
|
||||
{
|
||||
public const string Common = "Common";
|
||||
|
||||
public const string Lists = "Lists";
|
||||
|
||||
public const string Media = "Media";
|
||||
|
||||
public const string People = "People";
|
||||
|
||||
public const string Pickers = "Pickers";
|
||||
|
||||
public const string RichContent = "Rich Content";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,18 +15,13 @@ namespace Umbraco.Core
|
||||
public const int SuperUserId = -1;
|
||||
|
||||
/// <summary>
|
||||
/// The id for the 'unknown' user.
|
||||
/// The id for the 'unknown' user
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a user row that exists in the DB only for referential integrity but the user is never returned from any of the services
|
||||
/// </remarks>
|
||||
public const int UnknownUserId = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The name of the 'unknown' user.
|
||||
/// </summary>
|
||||
public const string UnknownUserName = "SYTEM";
|
||||
|
||||
public const string AdminGroupAlias = "admin";
|
||||
public const string SensitiveDataGroupAlias = "sensitiveData";
|
||||
public const string TranslatorGroupAlias = "translator";
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
namespace Umbraco.Core
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
{
|
||||
@@ -19,6 +22,7 @@
|
||||
public const string PreviewCookieName = "UMB_PREVIEW";
|
||||
|
||||
public const string InstallerCookieName = "umb_installId";
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,44 +66,44 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Determines whether the content type is invariant.
|
||||
/// </summary>
|
||||
public static bool VariesByNothing(this IPublishedContentType contentType) => contentType.Variations.VariesByNothing();
|
||||
public static bool VariesByNothing(this PublishedContentType contentType) => contentType.Variations.VariesByNothing();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by culture.
|
||||
/// </summary>
|
||||
/// <remarks>And then it could also vary by segment.</remarks>
|
||||
public static bool VariesByCulture(this IPublishedContentType contentType) => contentType.Variations.VariesByCulture();
|
||||
public static bool VariesByCulture(this PublishedContentType contentType) => contentType.Variations.VariesByCulture();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by segment.
|
||||
/// </summary>
|
||||
/// <remarks>And then it could also vary by culture.</remarks>
|
||||
public static bool VariesBySegment(this IPublishedContentType contentType) => contentType.Variations.VariesBySegment();
|
||||
public static bool VariesBySegment(this PublishedContentType contentType) => contentType.Variations.VariesBySegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the content type varies by culture and segment.
|
||||
/// </summary>
|
||||
public static bool VariesByCultureAndSegment(this IPublishedContentType contentType) => contentType.Variations.VariesByCultureAndSegment();
|
||||
public static bool VariesByCultureAndSegment(this PublishedContentType contentType) => contentType.Variations.VariesByCultureAndSegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type is invariant.
|
||||
/// </summary>
|
||||
public static bool VariesByNothing(this IPublishedPropertyType propertyType) => propertyType.Variations.VariesByNothing();
|
||||
public static bool VariesByNothing(this PublishedPropertyType propertyType) => propertyType.Variations.VariesByNothing();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type varies by culture.
|
||||
/// </summary>
|
||||
public static bool VariesByCulture(this IPublishedPropertyType propertyType) => propertyType.Variations.VariesByCulture();
|
||||
public static bool VariesByCulture(this PublishedPropertyType propertyType) => propertyType.Variations.VariesByCulture();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type varies by segment.
|
||||
/// </summary>
|
||||
public static bool VariesBySegment(this IPublishedPropertyType propertyType) => propertyType.Variations.VariesBySegment();
|
||||
public static bool VariesBySegment(this PublishedPropertyType propertyType) => propertyType.Variations.VariesBySegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the property type varies by culture and segment.
|
||||
/// </summary>
|
||||
public static bool VariesByCultureAndSegment(this IPublishedPropertyType propertyType) => propertyType.Variations.VariesByCultureAndSegment();
|
||||
public static bool VariesByCultureAndSegment(this PublishedPropertyType propertyType) => propertyType.Variations.VariesByCultureAndSegment();
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a variation is invariant.
|
||||
|
||||
@@ -10,15 +10,18 @@ namespace Umbraco.Core
|
||||
///</summary>
|
||||
public static class EnumerableExtensions
|
||||
{
|
||||
internal static bool IsCollectionEmpty<T>(this IReadOnlyCollection<T> list) => list == null || list.Count == 0;
|
||||
|
||||
internal static bool HasDuplicates<T>(this IEnumerable<T> items, bool includeNull)
|
||||
{
|
||||
var hs = new HashSet<T>();
|
||||
foreach (var item in items)
|
||||
{
|
||||
if ((item != null || includeNull) && !hs.Add(item))
|
||||
return true;
|
||||
if (item != null || includeNull)
|
||||
{
|
||||
if (!hs.Add(item))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -114,6 +117,7 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if all items in the other collection exist in this collection
|
||||
/// </summary>
|
||||
|
||||
@@ -8,9 +8,12 @@ namespace Umbraco.Core.IO.MediaPathSchemes
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Path is "{combinedGuid}/{filename}" where combinedGuid is a combination of itemGuid and propertyGuid.</para>
|
||||
/// <para>This scheme is dangerous, as it does not prevent potential collisions.</para>
|
||||
/// </remarks>
|
||||
public class CombinedGuidsMediaPathScheme : IMediaPathScheme
|
||||
{
|
||||
private const int DirectoryLength = 8;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetFilePath(IMediaFileSystem fileSystem, Guid itemGuid, Guid propertyGuid, string filename, string previous = null)
|
||||
{
|
||||
@@ -18,7 +21,7 @@ namespace Umbraco.Core.IO.MediaPathSchemes
|
||||
// for a single content cannot store two different files with the same name
|
||||
|
||||
var combinedGuid = GuidUtils.Combine(itemGuid, propertyGuid);
|
||||
var directory = HexEncoder.Encode(combinedGuid.ToByteArray()/*'/', 2, 4*/); // could use ext to fragment path eg 12/e4/f2/...
|
||||
var directory = GuidUtils.ToBase32String(combinedGuid, DirectoryLength); // see also HexEncoder, we may want to fragment path eg 12/e4/f3...
|
||||
return Path.Combine(directory, filename).Replace('\\', '/');
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Umbraco.Core.IO.MediaPathSchemes
|
||||
/// Implements a unique directory media path scheme.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>This scheme provides deterministic short paths, with potential collisions.</para>
|
||||
/// <para>This scheme provides short paths, yet handle potential collisions.</para>
|
||||
/// </remarks>
|
||||
public class UniqueMediaPathScheme : IMediaPathScheme
|
||||
{
|
||||
@@ -16,22 +16,23 @@ namespace Umbraco.Core.IO.MediaPathSchemes
|
||||
/// <inheritdoc />
|
||||
public string GetFilePath(IMediaFileSystem fileSystem, Guid itemGuid, Guid propertyGuid, string filename, string previous = null)
|
||||
{
|
||||
var combinedGuid = GuidUtils.Combine(itemGuid, propertyGuid);
|
||||
var directory = GuidUtils.ToBase32String(combinedGuid, DirectoryLength);
|
||||
string directory;
|
||||
|
||||
// no point "combining" guids if all we want is some random guid - just get a new one
|
||||
// and then, because we don't want collisions, ensure that the directory does not already exist
|
||||
// (should be quite rare, but eh...)
|
||||
|
||||
do
|
||||
{
|
||||
var combinedGuid = Guid.NewGuid();
|
||||
directory = GuidUtils.ToBase32String(combinedGuid, DirectoryLength); // see also HexEncoder, we may want to fragment path eg 12/e4/f3...
|
||||
|
||||
} while (fileSystem.DirectoryExists(directory));
|
||||
|
||||
return Path.Combine(directory, filename).Replace('\\', '/');
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <remarks>
|
||||
/// <para>Returning null so that <see cref="MediaFileSystem.DeleteMediaFiles"/> does *not*
|
||||
/// delete any directory. This is because the above shortening of the Guid to 8 chars
|
||||
/// means we're increasing the risk of collision, and we don't want to delete files
|
||||
/// belonging to other media items.</para>
|
||||
/// <para>And, at the moment, we cannot delete directory "only if it is empty" because of
|
||||
/// race conditions. We'd need to implement locks in <see cref="MediaFileSystem"/> for
|
||||
/// this.</para>
|
||||
/// </remarks>
|
||||
public string GetDeleteDirectory(IMediaFileSystem fileSystem, string filepath) => null;
|
||||
public string GetDeleteDirectory(IMediaFileSystem fileSystem, string filepath) => Path.GetDirectoryName(filepath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,7 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using Serilog;
|
||||
using Serilog.Configuration;
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
using Serilog.Formatting;
|
||||
using Serilog.Formatting.Compact;
|
||||
using Umbraco.Core.Logging.Serilog.Enrichers;
|
||||
|
||||
@@ -13,7 +9,6 @@ namespace Umbraco.Core.Logging.Serilog
|
||||
{
|
||||
public static class LoggerConfigExtensions
|
||||
{
|
||||
private const string AppDomainId = "AppDomainId";
|
||||
/// <summary>
|
||||
/// This configures Serilog with some defaults
|
||||
/// Such as adding ProcessID, Thread, AppDomain etc
|
||||
@@ -33,14 +28,14 @@ namespace Umbraco.Core.Logging.Serilog
|
||||
.Enrich.WithProcessId()
|
||||
.Enrich.WithProcessName()
|
||||
.Enrich.WithThreadId()
|
||||
.Enrich.WithProperty(AppDomainId, AppDomain.CurrentDomain.Id)
|
||||
.Enrich.WithProperty("AppDomainId", AppDomain.CurrentDomain.Id)
|
||||
.Enrich.WithProperty("AppDomainAppId", HttpRuntime.AppDomainAppId.ReplaceNonAlphanumericChars(string.Empty))
|
||||
.Enrich.WithProperty("MachineName", Environment.MachineName)
|
||||
.Enrich.With<Log4NetLevelMapperEnricher>()
|
||||
.Enrich.With<HttpSessionIdEnricher>()
|
||||
.Enrich.With<HttpRequestNumberEnricher>()
|
||||
.Enrich.With<HttpRequestIdEnricher>();
|
||||
|
||||
|
||||
return logConfig;
|
||||
}
|
||||
|
||||
@@ -55,51 +50,15 @@ namespace Umbraco.Core.Logging.Serilog
|
||||
//Main .txt logfile - in similar format to older Log4Net output
|
||||
//Ends with ..txt as Date is inserted before file extension substring
|
||||
logConfig.WriteTo.File($@"{AppDomain.CurrentDomain.BaseDirectory}\App_Data\Logs\UmbracoTraceLog.{Environment.MachineName}..txt",
|
||||
shared: true,
|
||||
rollingInterval: RollingInterval.Day,
|
||||
restrictedToMinimumLevel: minimumLevel,
|
||||
retainedFileCountLimit: null, //Setting to null means we keep all files - default is 31 days
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss,fff} [P{ProcessId}/D{AppDomainId}/T{ThreadId}] {Log4NetLevel} {SourceContext} - {Message:lj}{NewLine}{Exception}");
|
||||
shared: true,
|
||||
rollingInterval: RollingInterval.Day,
|
||||
restrictedToMinimumLevel: minimumLevel,
|
||||
retainedFileCountLimit: null, //Setting to null means we keep all files - default is 31 days
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss,fff} [P{ProcessId}/D{AppDomainId}/T{ThreadId}] {Log4NetLevel} {SourceContext} - {Message:lj}{NewLine}{Exception}");
|
||||
|
||||
return logConfig;
|
||||
}
|
||||
|
||||
|
||||
/// <remarks>
|
||||
/// Used in config - If renamed or moved to other assembly the config file also has be updated.
|
||||
/// </remarks>
|
||||
public static LoggerConfiguration File(this LoggerSinkConfiguration configuration, ITextFormatter formatter,
|
||||
string path,
|
||||
LogEventLevel restrictedToMinimumLevel = LogEventLevel.Verbose,
|
||||
LoggingLevelSwitch levelSwitch = null,
|
||||
long? fileSizeLimitBytes = 1073741824,
|
||||
TimeSpan? flushToDiskInterval = null,
|
||||
RollingInterval rollingInterval = RollingInterval.Infinite,
|
||||
bool rollOnFileSizeLimit = false,
|
||||
int? retainedFileCountLimit = 31,
|
||||
Encoding encoding = null
|
||||
)
|
||||
{
|
||||
return configuration.Async(
|
||||
asyncConfiguration => asyncConfiguration.Map(AppDomainId, (_,mapConfiguration) =>
|
||||
mapConfiguration.File(
|
||||
formatter,
|
||||
path,
|
||||
restrictedToMinimumLevel,
|
||||
fileSizeLimitBytes,
|
||||
levelSwitch,
|
||||
buffered:true,
|
||||
shared:false,
|
||||
flushToDiskInterval,
|
||||
rollingInterval,
|
||||
rollOnFileSizeLimit,
|
||||
retainedFileCountLimit,
|
||||
encoding),
|
||||
sinkMapCountLimit:0)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Outputs a CLEF format JSON log at /App_Data/Logs/
|
||||
/// </summary>
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Logging.Serilog
|
||||
///<summary>
|
||||
/// Implements <see cref="ILogger"/> on top of Serilog.
|
||||
///</summary>
|
||||
public class SerilogLogger : ILogger, IDisposable
|
||||
public class SerilogLogger : ILogger
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize a new instance of the <see cref="SerilogLogger"/> class with a configuration file.
|
||||
@@ -271,10 +271,5 @@ namespace Umbraco.Core.Logging.Serilog
|
||||
{
|
||||
LoggerFor(reporting).Verbose(messageTemplate, propertyValues);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Log.CloseAndFlush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,26 +26,26 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
/// A count of number of errors
|
||||
/// By counting Warnings with Exceptions, Errors & Fatal messages
|
||||
/// </summary>
|
||||
int GetNumberOfErrors(LogTimePeriod logTimePeriod);
|
||||
int GetNumberOfErrors(DateTimeOffset startDate, DateTimeOffset endDate);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a number of the different log level entries
|
||||
/// </summary>
|
||||
LogLevelCounts GetLogLevelCounts(LogTimePeriod logTimePeriod);
|
||||
LogLevelCounts GetLogLevelCounts(DateTimeOffset startDate, DateTimeOffset endDate);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of all unique message templates and their counts
|
||||
/// </summary>
|
||||
IEnumerable<LogTemplate> GetMessageTemplates(LogTimePeriod logTimePeriod);
|
||||
IEnumerable<LogTemplate> GetMessageTemplates(DateTimeOffset startDate, DateTimeOffset endDate);
|
||||
|
||||
bool CanHandleLargeLogs { get; }
|
||||
|
||||
bool CheckCanOpenLogs(LogTimePeriod logTimePeriod);
|
||||
bool CheckCanOpenLogs(DateTimeOffset startDate, DateTimeOffset endDate);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the collection of logs
|
||||
/// </summary>
|
||||
PagedResult<LogMessage> GetLogs(LogTimePeriod logTimePeriod,
|
||||
PagedResult<LogMessage> GetLogs(DateTimeOffset startDate, DateTimeOffset endDate,
|
||||
int pageNumber = 1,
|
||||
int pageSize = 100,
|
||||
Direction orderDirection = Direction.Descending,
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Serilog.Events;
|
||||
using Serilog.Formatting.Compact.Reader;
|
||||
|
||||
@@ -11,22 +10,20 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
internal class JsonLogViewer : LogViewerSourceBase
|
||||
{
|
||||
private readonly string _logsPath;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public JsonLogViewer(ILogger logger, string logsPath = "", string searchPath = "") : base(searchPath)
|
||||
public JsonLogViewer(string logsPath = "", string searchPath = "") : base(searchPath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(logsPath))
|
||||
logsPath = $@"{AppDomain.CurrentDomain.BaseDirectory}\App_Data\Logs\";
|
||||
|
||||
_logsPath = logsPath;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
private const int FileSizeCap = 100;
|
||||
|
||||
public override bool CanHandleLargeLogs => false;
|
||||
|
||||
public override bool CheckCanOpenLogs(LogTimePeriod logTimePeriod)
|
||||
public override bool CheckCanOpenLogs(DateTimeOffset startDate, DateTimeOffset endDate)
|
||||
{
|
||||
//Log Directory
|
||||
var logDirectory = _logsPath;
|
||||
@@ -36,10 +33,10 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
|
||||
//foreach full day in the range - see if we can find one or more filenames that end with
|
||||
//yyyyMMdd.json - Ends with due to MachineName in filenames - could be 1 or more due to load balancing
|
||||
for (var day = logTimePeriod.StartTime.Date; day.Date <= logTimePeriod.EndTime.Date; day = day.AddDays(1))
|
||||
for (var day = startDate.Date; day.Date <= endDate.Date; day = day.AddDays(1))
|
||||
{
|
||||
//Filename ending to search for (As could be multiple)
|
||||
var filesToFind = GetSearchPattern(day);
|
||||
var filesToFind = $"*{day:yyyyMMdd}.json";
|
||||
|
||||
var filesForCurrentDay = Directory.GetFiles(logDirectory, filesToFind);
|
||||
|
||||
@@ -52,12 +49,7 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
return logSizeAsMegabytes <= FileSizeCap;
|
||||
}
|
||||
|
||||
private string GetSearchPattern(DateTime day)
|
||||
{
|
||||
return $"*{day:yyyyMMdd}*.json";
|
||||
}
|
||||
|
||||
protected override IReadOnlyList<LogEvent> GetLogs(LogTimePeriod logTimePeriod, ILogFilter filter, int skip, int take)
|
||||
protected override IReadOnlyList<LogEvent> GetLogs(DateTimeOffset startDate, DateTimeOffset endDate, ILogFilter filter, int skip, int take)
|
||||
{
|
||||
var logs = new List<LogEvent>();
|
||||
|
||||
@@ -68,10 +60,10 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
|
||||
//foreach full day in the range - see if we can find one or more filenames that end with
|
||||
//yyyyMMdd.json - Ends with due to MachineName in filenames - could be 1 or more due to load balancing
|
||||
for (var day = logTimePeriod.StartTime.Date; day.Date <= logTimePeriod.EndTime.Date; day = day.AddDays(1))
|
||||
for (var day = startDate.Date; day.Date <= endDate.Date; day = day.AddDays(1))
|
||||
{
|
||||
//Filename ending to search for (As could be multiple)
|
||||
var filesToFind = GetSearchPattern(day);
|
||||
var filesToFind = $"*{day:yyyyMMdd}.json";
|
||||
|
||||
var filesForCurrentDay = Directory.GetFiles(logDirectory, filesToFind);
|
||||
|
||||
@@ -85,14 +77,8 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
using (var stream = new StreamReader(fs))
|
||||
{
|
||||
var reader = new LogEventReader(stream);
|
||||
while (TryRead(reader, out var evt))
|
||||
while (reader.TryRead(out var evt))
|
||||
{
|
||||
//We may get a null if log line is malformed
|
||||
if (evt == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (count > skip + take)
|
||||
{
|
||||
break;
|
||||
@@ -119,21 +105,5 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
return logs;
|
||||
}
|
||||
|
||||
private bool TryRead(LogEventReader reader, out LogEvent evt)
|
||||
{
|
||||
try
|
||||
{
|
||||
return reader.TryRead(out evt);
|
||||
}
|
||||
catch (JsonReaderException ex)
|
||||
{
|
||||
// As we are reading/streaming one line at a time in the JSON file
|
||||
// Thus we can not report the line number, as it will always be 1
|
||||
_logger.Error<JsonLogViewer>(ex, "Unable to parse a line in the JSON log file");
|
||||
|
||||
evt = null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Logging.Viewer
|
||||
{
|
||||
public class LogTimePeriod
|
||||
{
|
||||
public LogTimePeriod(DateTime startTime, DateTime endTime)
|
||||
{
|
||||
StartTime = startTime;
|
||||
EndTime = endTime;
|
||||
}
|
||||
|
||||
public DateTime StartTime { get; }
|
||||
public DateTime EndTime { get; }
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
{
|
||||
public void Compose(Composition composition)
|
||||
{
|
||||
composition.SetLogViewer(_ => new JsonLogViewer(composition.Logger));
|
||||
composition.SetLogViewer(_ => new JsonLogViewer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
/// <summary>
|
||||
/// Get all logs from your chosen data source back as Serilog LogEvents
|
||||
/// </summary>
|
||||
protected abstract IReadOnlyList<LogEvent> GetLogs(LogTimePeriod logTimePeriod, ILogFilter filter, int skip, int take);
|
||||
protected abstract IReadOnlyList<LogEvent> GetLogs(DateTimeOffset startDate, DateTimeOffset endDate, ILogFilter filter, int skip, int take);
|
||||
|
||||
public abstract bool CheckCanOpenLogs(LogTimePeriod logTimePeriod);
|
||||
public abstract bool CheckCanOpenLogs(DateTimeOffset startDate, DateTimeOffset endDate);
|
||||
|
||||
public virtual IReadOnlyList<SavedLogSearch> GetSavedSearches()
|
||||
{
|
||||
@@ -82,24 +82,24 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
return searches;
|
||||
}
|
||||
|
||||
public int GetNumberOfErrors(LogTimePeriod logTimePeriod)
|
||||
public int GetNumberOfErrors(DateTimeOffset startDate, DateTimeOffset endDate)
|
||||
{
|
||||
var errorCounter = new ErrorCounterFilter();
|
||||
GetLogs(logTimePeriod, errorCounter, 0, int.MaxValue);
|
||||
GetLogs(startDate, endDate, errorCounter, 0, int.MaxValue);
|
||||
return errorCounter.Count;
|
||||
}
|
||||
|
||||
public LogLevelCounts GetLogLevelCounts(LogTimePeriod logTimePeriod)
|
||||
public LogLevelCounts GetLogLevelCounts(DateTimeOffset startDate, DateTimeOffset endDate)
|
||||
{
|
||||
var counter = new CountingFilter();
|
||||
GetLogs(logTimePeriod, counter, 0, int.MaxValue);
|
||||
GetLogs(startDate, endDate, counter, 0, int.MaxValue);
|
||||
return counter.Counts;
|
||||
}
|
||||
|
||||
public IEnumerable<LogTemplate> GetMessageTemplates(LogTimePeriod logTimePeriod)
|
||||
public IEnumerable<LogTemplate> GetMessageTemplates(DateTimeOffset startDate, DateTimeOffset endDate)
|
||||
{
|
||||
var messageTemplates = new MessageTemplateFilter();
|
||||
GetLogs(logTimePeriod, messageTemplates, 0, int.MaxValue);
|
||||
GetLogs(startDate, endDate, messageTemplates, 0, int.MaxValue);
|
||||
|
||||
var templates = messageTemplates.Counts.
|
||||
Select(x => new LogTemplate { MessageTemplate = x.Key, Count = x.Value })
|
||||
@@ -108,14 +108,14 @@ namespace Umbraco.Core.Logging.Viewer
|
||||
return templates;
|
||||
}
|
||||
|
||||
public PagedResult<LogMessage> GetLogs(LogTimePeriod logTimePeriod,
|
||||
public PagedResult<LogMessage> GetLogs(DateTimeOffset startDate, DateTimeOffset endDate,
|
||||
int pageNumber = 1, int pageSize = 100,
|
||||
Direction orderDirection = Direction.Descending,
|
||||
string filterExpression = null,
|
||||
string[] logLevels = null)
|
||||
{
|
||||
var expression = new ExpressionFilter(filterExpression);
|
||||
var filteredLogs = GetLogs(logTimePeriod, expression, 0, int.MaxValue);
|
||||
var filteredLogs = GetLogs(startDate, endDate, expression, 0, int.MaxValue);
|
||||
|
||||
//This is user used the checkbox UI to toggle which log levels they wish to see
|
||||
//If an empty array or null - its implied all levels to be viewed
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web.Hosting;
|
||||
@@ -114,7 +113,7 @@ namespace Umbraco.Core
|
||||
|
||||
lock (_locko)
|
||||
{
|
||||
_logger.Debug<MainDom>("Signaled ({Signaled}) ({SignalSource})", _signaled ? "again" : "first", source);
|
||||
_logger.Debug<MainDom>("Signaled {Signaled} ({SignalSource})", _signaled ? "(again)" : string.Empty, source);
|
||||
if (_signaled) return;
|
||||
if (_isMainDom == false) return; // probably not needed
|
||||
_signaled = true;
|
||||
@@ -172,7 +171,6 @@ namespace Umbraco.Core
|
||||
// if more than 1 instance reach that point, one will get the lock
|
||||
// and the other one will timeout, which is accepted
|
||||
|
||||
//TODO: This can throw a TimeoutException - in which case should this be in a try/finally to ensure the signal is always reset?
|
||||
_asyncLocker = _asyncLock.Lock(LockTimeoutMilliseconds);
|
||||
_isMainDom = true;
|
||||
|
||||
@@ -183,9 +181,6 @@ namespace Umbraco.Core
|
||||
// which is accepted
|
||||
|
||||
_signal.Reset();
|
||||
|
||||
//WaitOneAsync (ext method) will wait for a signal without blocking the main thread, the waiting is done on a background thread
|
||||
|
||||
_signal.WaitOneAsync()
|
||||
.ContinueWith(_ => OnSignal("signal"));
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Manifest
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides filtering for package manifests.
|
||||
/// </summary>
|
||||
public interface IManifestFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// Filters package manifests.
|
||||
/// </summary>
|
||||
/// <param name="manifests">The package manifests.</param>
|
||||
/// <remarks>
|
||||
/// <para>It is possible to remove, change, or add manifests.</para>
|
||||
/// </remarks>
|
||||
void Filter(List<PackageManifest> manifests);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.Manifest
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the manifest filters.
|
||||
/// </summary>
|
||||
public class ManifestFilterCollection : BuilderCollectionBase<IManifestFilter>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ManifestFilterCollection"/> class.
|
||||
/// </summary>
|
||||
public ManifestFilterCollection(IEnumerable<IManifestFilter> items)
|
||||
: base(items)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Filters package manifests.
|
||||
/// </summary>
|
||||
/// <param name="manifests">The package manifests.</param>
|
||||
public void Filter(List<PackageManifest> manifests)
|
||||
{
|
||||
foreach (var filter in this)
|
||||
filter.Filter(manifests);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.Manifest
|
||||
{
|
||||
public class ManifestFilterCollectionBuilder : OrderedCollectionBuilderBase<ManifestFilterCollectionBuilder, ManifestFilterCollection, IManifestFilter>
|
||||
{
|
||||
protected override ManifestFilterCollectionBuilder This => this;
|
||||
|
||||
// do NOT cache this, it's only used once
|
||||
protected override Lifetime CollectionLifetime => Lifetime.Transient;
|
||||
}
|
||||
}
|
||||
@@ -22,26 +22,24 @@ namespace Umbraco.Core.Manifest
|
||||
private readonly IAppPolicyCache _cache;
|
||||
private readonly ILogger _logger;
|
||||
private readonly ManifestValueValidatorCollection _validators;
|
||||
private readonly ManifestFilterCollection _filters;
|
||||
|
||||
private string _path;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ManifestParser"/> class.
|
||||
/// </summary>
|
||||
public ManifestParser(AppCaches appCaches, ManifestValueValidatorCollection validators, ManifestFilterCollection filters, ILogger logger)
|
||||
: this(appCaches, validators, filters, "~/App_Plugins", logger)
|
||||
public ManifestParser(AppCaches appCaches, ManifestValueValidatorCollection validators, ILogger logger)
|
||||
: this(appCaches, validators, "~/App_Plugins", logger)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ManifestParser"/> class.
|
||||
/// </summary>
|
||||
private ManifestParser(AppCaches appCaches, ManifestValueValidatorCollection validators, ManifestFilterCollection filters, string path, ILogger logger)
|
||||
private ManifestParser(AppCaches appCaches, ManifestValueValidatorCollection validators, string path, ILogger logger)
|
||||
{
|
||||
if (appCaches == null) throw new ArgumentNullException(nameof(appCaches));
|
||||
_cache = appCaches.RuntimeCache;
|
||||
_validators = validators ?? throw new ArgumentNullException(nameof(validators));
|
||||
_filters = filters ?? throw new ArgumentNullException(nameof(filters));
|
||||
if (string.IsNullOrWhiteSpace(path)) throw new ArgumentNullOrEmptyException(nameof(path));
|
||||
Path = path;
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
@@ -80,7 +78,6 @@ namespace Umbraco.Core.Manifest
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
continue;
|
||||
var manifest = ParseManifest(text);
|
||||
manifest.Source = path;
|
||||
manifests.Add(manifest);
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -89,8 +86,6 @@ namespace Umbraco.Core.Manifest
|
||||
}
|
||||
}
|
||||
|
||||
_filters.Filter(manifests);
|
||||
|
||||
return manifests;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,16 +9,6 @@ namespace Umbraco.Core.Manifest
|
||||
/// </summary>
|
||||
public class PackageManifest
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the source path of the manifest.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Gets the full absolute file path of the manifest,
|
||||
/// using system directory separators.</para>
|
||||
/// </remarks>
|
||||
[JsonIgnore]
|
||||
public string Source { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the scripts listed in the manifest.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace Umbraco.Core.Mapping
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines maps for <see cref="UmbracoMapper"/>.
|
||||
/// </summary>
|
||||
public interface IMapDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines maps.
|
||||
/// </summary>
|
||||
void DefineMaps(UmbracoMapper mapper);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.Mapping
|
||||
{
|
||||
public class MapDefinitionCollection : BuilderCollectionBase<IMapDefinition>
|
||||
{
|
||||
public MapDefinitionCollection(IEnumerable<IMapDefinition> items)
|
||||
: base(items)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.Mapping
|
||||
{
|
||||
public class MapDefinitionCollectionBuilder : SetCollectionBuilderBase<MapDefinitionCollectionBuilder, MapDefinitionCollection, IMapDefinition>
|
||||
{
|
||||
protected override MapDefinitionCollectionBuilder This => this;
|
||||
|
||||
protected override Lifetime CollectionLifetime => Lifetime.Transient;
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Mapping
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a mapper context.
|
||||
/// </summary>
|
||||
public class MapperContext
|
||||
{
|
||||
private readonly UmbracoMapper _mapper;
|
||||
private IDictionary<string, object> _items;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MapperContext"/> class.
|
||||
/// </summary>
|
||||
public MapperContext(UmbracoMapper mapper)
|
||||
{
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the context has items.
|
||||
/// </summary>
|
||||
public bool HasItems => _items != null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the context items.
|
||||
/// </summary>
|
||||
public IDictionary<string, object> Items => _items ?? (_items = new Dictionary<string, object>());
|
||||
|
||||
#region Map
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TTarget>(object source)
|
||||
=> _mapper.Map<TTarget>(source, this);
|
||||
|
||||
// let's say this is a bad (dangerous) idea, and leave it out for now
|
||||
/*
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="f">A mapper context preparation method.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TTarget>(object source, Action<MapperContext> f)
|
||||
{
|
||||
f(this);
|
||||
return _mapper.Map<TTarget>(source, this);
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source)
|
||||
=> _mapper.Map<TSource, TTarget>(source, this);
|
||||
|
||||
// let's say this is a bad (dangerous) idea, and leave it out for now
|
||||
/*
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="f">A mapper context preparation method.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, Action<MapperContext> f)
|
||||
{
|
||||
f(this);
|
||||
return _mapper.Map<TSource, TTarget>(source, this);
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to an existing target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, TTarget target)
|
||||
=> _mapper.Map(source, target, this);
|
||||
|
||||
// let's say this is a bad (dangerous) idea, and leave it out for now
|
||||
/*
|
||||
/// <summary>
|
||||
/// Maps a source object to an existing target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <param name="f">A mapper context preparation method.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, TTarget target, Action<MapperContext> f)
|
||||
{
|
||||
f(this);
|
||||
return _mapper.Map(source, target, this);
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Maps an enumerable of source objects to a new list of target objects.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSourceElement">The type of the source objects.</typeparam>
|
||||
/// <typeparam name="TTargetElement">The type of the target objects.</typeparam>
|
||||
/// <param name="source">The source objects.</param>
|
||||
/// <returns>A list containing the target objects.</returns>
|
||||
public List<TTargetElement> MapEnumerable<TSourceElement, TTargetElement>(IEnumerable<TSourceElement> source)
|
||||
{
|
||||
return source.Select(Map<TSourceElement, TTargetElement>).ToList();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,430 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Mapping
|
||||
{
|
||||
// notes:
|
||||
// AutoMapper maps null to empty arrays, lists, etc
|
||||
|
||||
// TODO:
|
||||
// when mapping from TSource, and no map is found, consider the actual source.GetType()?
|
||||
// when mapping to TTarget, and no map is found, consider the actual target.GetType()?
|
||||
// not sure we want to add magic to this simple mapper class, though
|
||||
|
||||
/// <summary>
|
||||
/// Umbraco Mapper.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>When a map is defined from TSource to TTarget, the mapper automatically knows how to map
|
||||
/// from IEnumerable{TSource} to IEnumerable{TTarget} (using a List{TTarget}) and to TTarget[].</para>
|
||||
/// <para>When a map is defined from TSource to TTarget, the mapper automatically uses that map
|
||||
/// for any source type that inherits from, or implements, TSource.</para>
|
||||
/// <para>When a map is defined from TSource to TTarget, the mapper can map to TTarget exclusively
|
||||
/// and cannot re-use that map for types that would inherit from, or implement, TTarget.</para>
|
||||
/// <para>When using the Map{TSource, TTarget}(TSource source, ...) overloads, TSource is explicit. When
|
||||
/// using the Map{TTarget}(object source, ...) TSource is defined as source.GetType().</para>
|
||||
/// <para>In both cases, TTarget is explicit and not typeof(target).</para>
|
||||
/// </remarks>
|
||||
public class UmbracoMapper
|
||||
{
|
||||
// note
|
||||
//
|
||||
// the outer dictionary *can* be modified, see GetCtor and GetMap, hence have to be ConcurrentDictionary
|
||||
// the inner dictionaries are never modified and therefore can be simple Dictionary
|
||||
|
||||
private readonly ConcurrentDictionary<Type, Dictionary<Type, Func<object, MapperContext, object>>> _ctors
|
||||
= new ConcurrentDictionary<Type, Dictionary<Type, Func<object, MapperContext, object>>>();
|
||||
|
||||
private readonly ConcurrentDictionary<Type, Dictionary<Type, Action<object, object, MapperContext>>> _maps
|
||||
= new ConcurrentDictionary<Type, Dictionary<Type, Action<object, object, MapperContext>>>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoMapper"/> class.
|
||||
/// </summary>
|
||||
/// <param name="profiles"></param>
|
||||
public UmbracoMapper(MapDefinitionCollection profiles)
|
||||
{
|
||||
foreach (var profile in profiles)
|
||||
profile.DefineMaps(this);
|
||||
}
|
||||
|
||||
#region Define
|
||||
|
||||
private static TTarget ThrowCtor<TSource, TTarget>(TSource source, MapperContext context)
|
||||
=> throw new InvalidOperationException($"Don't know how to create {typeof(TTarget).FullName} instances.");
|
||||
|
||||
private static void Identity<TSource, TTarget>(TSource source, TTarget target, MapperContext context)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Defines a mapping.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
public void Define<TSource, TTarget>()
|
||||
=> Define<TSource, TTarget>(ThrowCtor<TSource, TTarget>, Identity);
|
||||
|
||||
/// <summary>
|
||||
/// Defines a mapping.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="map">A mapping method.</param>
|
||||
public void Define<TSource, TTarget>(Action<TSource, TTarget, MapperContext> map)
|
||||
=> Define(ThrowCtor<TSource, TTarget>, map);
|
||||
|
||||
/// <summary>
|
||||
/// Defines a mapping.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="ctor">A constructor method.</param>
|
||||
public void Define<TSource, TTarget>(Func<TSource, MapperContext, TTarget> ctor)
|
||||
=> Define(ctor, Identity);
|
||||
|
||||
/// <summary>
|
||||
/// Defines a mapping.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="ctor">A constructor method.</param>
|
||||
/// <param name="map">A mapping method.</param>
|
||||
public void Define<TSource, TTarget>(Func<TSource, MapperContext, TTarget> ctor, Action<TSource, TTarget, MapperContext> map)
|
||||
{
|
||||
var sourceType = typeof(TSource);
|
||||
var targetType = typeof(TTarget);
|
||||
|
||||
var sourceCtors = DefineCtors(sourceType);
|
||||
if (ctor != null)
|
||||
sourceCtors[targetType] = (source, context) => ctor((TSource)source, context);
|
||||
|
||||
var sourceMaps = DefineMaps(sourceType);
|
||||
sourceMaps[targetType] = (source, target, context) => map((TSource)source, (TTarget)target, context);
|
||||
}
|
||||
|
||||
private Dictionary<Type, Func<object, MapperContext, object>> DefineCtors(Type sourceType)
|
||||
{
|
||||
return _ctors.GetOrAdd(sourceType, _ => new Dictionary<Type, Func<object, MapperContext, object>>());
|
||||
}
|
||||
|
||||
private Dictionary<Type, Action<object, object, MapperContext>> DefineMaps(Type sourceType)
|
||||
{
|
||||
return _maps.GetOrAdd(sourceType, _ => new Dictionary<Type, Action<object, object, MapperContext>>());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Map
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TTarget>(object source)
|
||||
=> Map<TTarget>(source, new MapperContext(this));
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="f">A mapper context preparation method.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TTarget>(object source, Action<MapperContext> f)
|
||||
{
|
||||
var context = new MapperContext(this);
|
||||
f(context);
|
||||
return Map<TTarget>(source, context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="context">A mapper context.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TTarget>(object source, MapperContext context)
|
||||
=> Map<TTarget>(source, source?.GetType(), context);
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source)
|
||||
=> Map<TSource, TTarget>(source, new MapperContext(this));
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="f">A mapper context preparation method.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, Action<MapperContext> f)
|
||||
{
|
||||
var context = new MapperContext(this);
|
||||
f(context);
|
||||
return Map<TSource, TTarget>(source, context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to a new target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="context">A mapper context.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, MapperContext context)
|
||||
=> Map<TTarget>(source, typeof(TSource), context);
|
||||
|
||||
private TTarget Map<TTarget>(object source, Type sourceType, MapperContext context)
|
||||
{
|
||||
if (source == null)
|
||||
return default;
|
||||
|
||||
var targetType = typeof(TTarget);
|
||||
|
||||
var ctor = GetCtor(sourceType, targetType);
|
||||
var map = GetMap(sourceType, targetType);
|
||||
|
||||
// if there is a direct constructor, map
|
||||
if (ctor != null && map != null)
|
||||
{
|
||||
var target = ctor(source, context);
|
||||
map(source, target, context);
|
||||
return (TTarget)target;
|
||||
}
|
||||
|
||||
// otherwise, see if we can deal with enumerable
|
||||
|
||||
var ienumerableOfT = typeof(IEnumerable<>);
|
||||
|
||||
bool IsIEnumerableOfT(Type type) =>
|
||||
type.IsGenericType &&
|
||||
type.GenericTypeArguments.Length == 1 &&
|
||||
type.GetGenericTypeDefinition() == ienumerableOfT;
|
||||
|
||||
// try to get source as an IEnumerable<T>
|
||||
var sourceIEnumerable = IsIEnumerableOfT(sourceType) ? sourceType : sourceType.GetInterfaces().FirstOrDefault(IsIEnumerableOfT);
|
||||
|
||||
// if source is an IEnumerable<T> and target is T[] or IEnumerable<T>, we can create a map
|
||||
if (sourceIEnumerable != null && IsEnumerableOrArrayOfType(targetType))
|
||||
{
|
||||
var sourceGenericArg = sourceIEnumerable.GenericTypeArguments[0];
|
||||
var targetGenericArg = GetEnumerableOrArrayTypeArgument(targetType);
|
||||
|
||||
ctor = GetCtor(sourceGenericArg, targetGenericArg);
|
||||
map = GetMap(sourceGenericArg, targetGenericArg);
|
||||
|
||||
// if there is a constructor for the underlying type, create & invoke the map
|
||||
if (ctor != null && map != null)
|
||||
{
|
||||
// register (for next time) and do it now (for this time)
|
||||
object NCtor(object s, MapperContext c) => MapEnumerableInternal<TTarget>((IEnumerable) s, targetGenericArg, ctor, map, c);
|
||||
DefineCtors(sourceType)[targetType] = NCtor;
|
||||
DefineMaps(sourceType)[targetType] = Identity;
|
||||
return (TTarget) NCtor(source, context);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Don't know how to map {sourceGenericArg.FullName} to {targetGenericArg.FullName}, so don't know how to map {sourceType.FullName} to {targetType.FullName}.");
|
||||
}
|
||||
|
||||
throw new InvalidOperationException($"Don't know how to map {sourceType.FullName} to {targetType.FullName}.");
|
||||
}
|
||||
|
||||
private TTarget MapEnumerableInternal<TTarget>(IEnumerable source, Type targetGenericArg, Func<object, MapperContext, object> ctor, Action<object, object, MapperContext> map, MapperContext context)
|
||||
{
|
||||
var targetList = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(targetGenericArg));
|
||||
|
||||
foreach (var sourceItem in source)
|
||||
{
|
||||
var targetItem = ctor(sourceItem, context);
|
||||
map(sourceItem, targetItem, context);
|
||||
targetList.Add(targetItem);
|
||||
}
|
||||
|
||||
object target = targetList;
|
||||
|
||||
if (typeof(TTarget).IsArray)
|
||||
{
|
||||
var elementType = typeof(TTarget).GetElementType();
|
||||
if (elementType == null) throw new Exception("panic");
|
||||
var targetArray = Array.CreateInstance(elementType, targetList.Count);
|
||||
targetList.CopyTo(targetArray, 0);
|
||||
target = targetArray;
|
||||
}
|
||||
|
||||
return (TTarget) target;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to an existing target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, TTarget target)
|
||||
=> Map(source, target, new MapperContext(this));
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to an existing target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <param name="f">A mapper context preparation method.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, TTarget target, Action<MapperContext> f)
|
||||
{
|
||||
var context = new MapperContext(this);
|
||||
f(context);
|
||||
return Map(source, target, context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps a source object to an existing target object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource">The source type.</typeparam>
|
||||
/// <typeparam name="TTarget">The target type.</typeparam>
|
||||
/// <param name="source">The source object.</param>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <param name="context">A mapper context.</param>
|
||||
/// <returns>The target object.</returns>
|
||||
public TTarget Map<TSource, TTarget>(TSource source, TTarget target, MapperContext context)
|
||||
{
|
||||
var sourceType = typeof(TSource);
|
||||
var targetType = typeof(TTarget);
|
||||
|
||||
var map = GetMap(sourceType, targetType);
|
||||
|
||||
// if there is a direct map, map
|
||||
if (map != null)
|
||||
{
|
||||
map(source, target, context);
|
||||
return target;
|
||||
}
|
||||
|
||||
// we cannot really map to an existing enumerable - give up
|
||||
|
||||
throw new InvalidOperationException($"Don't know how to map {typeof(TSource).FullName} to {typeof(TTarget).FullName}.");
|
||||
}
|
||||
|
||||
private Func<object, MapperContext, object> GetCtor(Type sourceType, Type targetType)
|
||||
{
|
||||
if (_ctors.TryGetValue(sourceType, out var sourceCtor) && sourceCtor.TryGetValue(targetType, out var ctor))
|
||||
return ctor;
|
||||
|
||||
// we *may* run this more than once but it does not matter
|
||||
|
||||
ctor = null;
|
||||
foreach (var (stype, sctors) in _ctors)
|
||||
{
|
||||
if (!stype.IsAssignableFrom(sourceType)) continue;
|
||||
if (!sctors.TryGetValue(targetType, out ctor)) continue;
|
||||
|
||||
sourceCtor = sctors;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ctor == null) return null;
|
||||
|
||||
_ctors[sourceType] = sourceCtor;
|
||||
return ctor;
|
||||
}
|
||||
|
||||
private Action<object, object, MapperContext> GetMap(Type sourceType, Type targetType)
|
||||
{
|
||||
if (_maps.TryGetValue(sourceType, out var sourceMap) && sourceMap.TryGetValue(targetType, out var map))
|
||||
return map;
|
||||
|
||||
// we *may* run this more than once but it does not matter
|
||||
|
||||
map = null;
|
||||
foreach (var (stype, smap) in _maps)
|
||||
{
|
||||
if (!stype.IsAssignableFrom(sourceType)) continue;
|
||||
|
||||
// TODO: consider looking for assignable types for target too?
|
||||
if (!smap.TryGetValue(targetType, out map)) continue;
|
||||
|
||||
sourceMap = smap;
|
||||
break;
|
||||
}
|
||||
|
||||
if (map == null) return null;
|
||||
|
||||
_maps[sourceType] = sourceMap;
|
||||
return map;
|
||||
}
|
||||
|
||||
private static bool IsEnumerableOrArrayOfType(Type type)
|
||||
{
|
||||
if (type.IsArray && type.GetArrayRank() == 1) return true;
|
||||
if (type.IsGenericType && type.GenericTypeArguments.Length == 1) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Type GetEnumerableOrArrayTypeArgument(Type type)
|
||||
{
|
||||
if (type.IsArray) return type.GetElementType();
|
||||
if (type.IsGenericType) return type.GenericTypeArguments[0];
|
||||
throw new Exception("panic");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps an enumerable of source objects to a new list of target objects.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSourceElement">The type of the source objects.</typeparam>
|
||||
/// <typeparam name="TTargetElement">The type of the target objects.</typeparam>
|
||||
/// <param name="source">The source objects.</param>
|
||||
/// <returns>A list containing the target objects.</returns>
|
||||
public List<TTargetElement> MapEnumerable<TSourceElement, TTargetElement>(IEnumerable<TSourceElement> source)
|
||||
{
|
||||
return source.Select(Map<TSourceElement, TTargetElement>).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps an enumerable of source objects to a new list of target objects.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSourceElement">The type of the source objects.</typeparam>
|
||||
/// <typeparam name="TTargetElement">The type of the target objects.</typeparam>
|
||||
/// <param name="source">The source objects.</param>
|
||||
/// <param name="f">A mapper context preparation method.</param>
|
||||
/// <returns>A list containing the target objects.</returns>
|
||||
public List<TTargetElement> MapEnumerable<TSourceElement, TTargetElement>(IEnumerable<TSourceElement> source, Action<MapperContext> f)
|
||||
{
|
||||
var context = new MapperContext(this);
|
||||
f(context);
|
||||
return source.Select(x => Map<TSourceElement, TTargetElement>(x, context)).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps an enumerable of source objects to a new list of target objects.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSourceElement">The type of the source objects.</typeparam>
|
||||
/// <typeparam name="TTargetElement">The type of the target objects.</typeparam>
|
||||
/// <param name="source">The source objects.</param>
|
||||
/// <param name="context">A mapper context.</param>
|
||||
/// <returns>A list containing the target objects.</returns>
|
||||
public List<TTargetElement> MapEnumerable<TSourceElement, TTargetElement>(IEnumerable<TSourceElement> source, MapperContext context)
|
||||
{
|
||||
return source.Select(x => Map<TSourceElement, TTargetElement>(x, context)).ToList();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -83,25 +83,17 @@ namespace Umbraco.Core.Migrations.Expressions.Create
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICreateConstraintOnTableBuilder PrimaryKey() => PrimaryKey(true);
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICreateConstraintOnTableBuilder PrimaryKey(bool clustered)
|
||||
public ICreateConstraintOnTableBuilder PrimaryKey()
|
||||
{
|
||||
var expression = new CreateConstraintExpression(_context, ConstraintType.PrimaryKey);
|
||||
expression.Constraint.IsPrimaryKeyClustered = clustered;
|
||||
return new CreateConstraintBuilder(expression);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICreateConstraintOnTableBuilder PrimaryKey(string primaryKeyName) => PrimaryKey(primaryKeyName, true);
|
||||
|
||||
/// <inheritdoc />
|
||||
public ICreateConstraintOnTableBuilder PrimaryKey(string primaryKeyName, bool clustered)
|
||||
public ICreateConstraintOnTableBuilder PrimaryKey(string primaryKeyName)
|
||||
{
|
||||
var expression = new CreateConstraintExpression(_context, ConstraintType.PrimaryKey);
|
||||
expression.Constraint.ConstraintName = primaryKeyName;
|
||||
expression.Constraint.IsPrimaryKeyClustered = clustered;
|
||||
return new CreateConstraintBuilder(expression);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ namespace Umbraco.Core.Migrations.Expressions.Create.Expressions
|
||||
var constraintType = (Constraint.IsPrimaryKeyConstraint) ? "PRIMARY KEY" : "UNIQUE";
|
||||
|
||||
if (Constraint.IsPrimaryKeyConstraint && SqlSyntax.SupportsClustered())
|
||||
constraintType += Constraint.IsPrimaryKeyClustered ? " CLUSTERED" : " NONCLUSTERED";
|
||||
constraintType += " CLUSTERED";
|
||||
|
||||
if (Constraint.IsNonUniqueConstraint)
|
||||
constraintType = string.Empty;
|
||||
|
||||
@@ -68,16 +68,6 @@ namespace Umbraco.Core.Migrations.Expressions.Create
|
||||
/// </summary>
|
||||
ICreateConstraintOnTableBuilder PrimaryKey(string primaryKeyName);
|
||||
|
||||
/// <summary>
|
||||
/// Builds a Create Primary Key expression.
|
||||
/// </summary>
|
||||
ICreateConstraintOnTableBuilder PrimaryKey(bool clustered);
|
||||
|
||||
/// <summary>
|
||||
/// Builds a Create Primary Key expression.
|
||||
/// </summary>
|
||||
ICreateConstraintOnTableBuilder PrimaryKey(string primaryKeyName, bool clustered);
|
||||
|
||||
/// <summary>
|
||||
/// Builds a Create Unique Constraint expression.
|
||||
/// </summary>
|
||||
|
||||
-14
@@ -25,25 +25,11 @@ namespace Umbraco.Core.Migrations.Expressions.Create.KeysAndIndexes
|
||||
var syntax = _context.SqlContext.SqlSyntax;
|
||||
var tableDefinition = DefinitionFactory.GetTableDefinition(TypeOfDto, syntax);
|
||||
|
||||
// note: of course we are creating the keys and indexes as per the DTO, so
|
||||
// changing the DTO may break old migrations - or, better, these migrations
|
||||
// should capture a copy of the DTO class that will not change
|
||||
|
||||
ExecuteSql(syntax.FormatPrimaryKey(tableDefinition));
|
||||
foreach (var sql in syntax.Format(tableDefinition.Indexes))
|
||||
ExecuteSql(sql);
|
||||
foreach (var sql in syntax.Format(tableDefinition.ForeignKeys))
|
||||
ExecuteSql(sql);
|
||||
|
||||
// note: we do *not* create the DF_ default constraints
|
||||
/*
|
||||
foreach (var column in tableDefinition.Columns)
|
||||
{
|
||||
var sql = syntax.FormatDefaultConstraint(column);
|
||||
if (!sql.IsNullOrWhiteSpace())
|
||||
ExecuteSql(sql);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private void ExecuteSql(string sql)
|
||||
|
||||
+2
-9
@@ -10,13 +10,9 @@ namespace Umbraco.Core.Migrations.Expressions.Delete.DefaultConstraint
|
||||
IDeleteDefaultConstraintOnTableBuilder,
|
||||
IDeleteDefaultConstraintOnColumnBuilder
|
||||
{
|
||||
private readonly IMigrationContext _context;
|
||||
|
||||
public DeleteDefaultConstraintBuilder(IMigrationContext context, DeleteDefaultConstraintExpression expression)
|
||||
public DeleteDefaultConstraintBuilder(DeleteDefaultConstraintExpression expression)
|
||||
: base(expression)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
{ }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IDeleteDefaultConstraintOnColumnBuilder OnTable(string tableName)
|
||||
@@ -29,9 +25,6 @@ namespace Umbraco.Core.Migrations.Expressions.Delete.DefaultConstraint
|
||||
public IExecutableBuilder OnColumn(string columnName)
|
||||
{
|
||||
Expression.ColumnName = columnName;
|
||||
Expression.HasDefaultConstraint = _context.SqlContext.SqlSyntax.TryGetDefaultConstraint(_context.Database, Expression.TableName, columnName, out var constraintName);
|
||||
Expression.ConstraintName = constraintName ?? string.Empty;
|
||||
|
||||
return new ExecutableBuilder(Expression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Umbraco.Core.Exceptions;
|
||||
using NPoco;
|
||||
using Umbraco.Core.Migrations.Expressions.Common;
|
||||
using Umbraco.Core.Migrations.Expressions.Delete.Column;
|
||||
using Umbraco.Core.Migrations.Expressions.Delete.Constraint;
|
||||
@@ -29,19 +29,9 @@ namespace Umbraco.Core.Migrations.Expressions.Delete
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IExecutableBuilder KeysAndIndexes<TDto>(bool local = true, bool foreign = true)
|
||||
public IExecutableBuilder KeysAndIndexes(string tableName = null)
|
||||
{
|
||||
var syntax = _context.SqlContext.SqlSyntax;
|
||||
var tableDefinition = DefinitionFactory.GetTableDefinition(typeof(TDto), syntax);
|
||||
return KeysAndIndexes(tableDefinition.Name, local, foreign);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IExecutableBuilder KeysAndIndexes(string tableName, bool local = true, bool foreign = true)
|
||||
{
|
||||
if (tableName.IsNullOrWhiteSpace())
|
||||
throw new ArgumentNullOrEmptyException(nameof(tableName));
|
||||
return new DeleteKeysAndIndexesBuilder(_context) { TableName = tableName, DeleteLocal = local, DeleteForeign = foreign };
|
||||
return new DeleteKeysAndIndexesBuilder(_context) { TableName = tableName };
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -110,7 +100,7 @@ namespace Umbraco.Core.Migrations.Expressions.Delete
|
||||
public IDeleteDefaultConstraintOnTableBuilder DefaultConstraint()
|
||||
{
|
||||
var expression = new DeleteDefaultConstraintExpression(_context);
|
||||
return new DeleteDefaultConstraintBuilder(_context, expression);
|
||||
return new DeleteDefaultConstraintBuilder(expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-8
@@ -10,17 +10,12 @@ namespace Umbraco.Core.Migrations.Expressions.Delete.Expressions
|
||||
|
||||
public virtual string TableName { get; set; }
|
||||
public virtual string ColumnName { get; set; }
|
||||
public virtual string ConstraintName { get; set; }
|
||||
public virtual bool HasDefaultConstraint { get; set; }
|
||||
|
||||
protected override string GetSql()
|
||||
{
|
||||
return HasDefaultConstraint
|
||||
? string.Format(SqlSyntax.DeleteDefaultConstraint,
|
||||
SqlSyntax.GetQuotedTableName(TableName),
|
||||
SqlSyntax.GetQuotedColumnName(ColumnName),
|
||||
SqlSyntax.GetQuotedName(ConstraintName))
|
||||
: string.Empty;
|
||||
return string.Format(SqlSyntax.DeleteDefaultConstraint,
|
||||
SqlSyntax.GetQuotedTableName(TableName),
|
||||
SqlSyntax.GetQuotedColumnName(ColumnName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,14 +19,9 @@ namespace Umbraco.Core.Migrations.Expressions.Delete
|
||||
IExecutableBuilder Table(string tableName);
|
||||
|
||||
/// <summary>
|
||||
/// Builds a Delete Keys and Indexes expression, and executes.
|
||||
/// Specifies the table to delete keys and indexes for.
|
||||
/// </summary>
|
||||
IExecutableBuilder KeysAndIndexes<TDto>(bool local = true, bool foreign = true);
|
||||
|
||||
/// <summary>
|
||||
/// Builds a Delete Keys and Indexes expression, and executes.
|
||||
/// </summary>
|
||||
IExecutableBuilder KeysAndIndexes(string tableName, bool local = true, bool foreign = true);
|
||||
IExecutableBuilder KeysAndIndexes(string tableName = null);
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the column to delete.
|
||||
|
||||
+21
-25
@@ -18,38 +18,34 @@ namespace Umbraco.Core.Migrations.Expressions.Delete.KeysAndIndexes
|
||||
|
||||
public string TableName { get; set; }
|
||||
|
||||
public bool DeleteLocal { get; set; }
|
||||
|
||||
public bool DeleteForeign { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Do()
|
||||
{
|
||||
_context.BuildingExpression = false;
|
||||
|
||||
// drop keys
|
||||
if (DeleteLocal || DeleteForeign)
|
||||
if (TableName == null)
|
||||
{
|
||||
// table, constraint
|
||||
var tableKeys = _context.SqlContext.SqlSyntax.GetConstraintsPerTable(_context.Database).DistinctBy(x => x.Item2).ToList();
|
||||
if (DeleteForeign)
|
||||
{
|
||||
foreach (var key in tableKeys.Where(x => x.Item1 == TableName && x.Item2.StartsWith("FK_")))
|
||||
Delete.ForeignKey(key.Item2).OnTable(key.Item1).Do();
|
||||
}
|
||||
if (DeleteLocal)
|
||||
{
|
||||
foreach (var key in tableKeys.Where(x => x.Item1 == TableName && x.Item2.StartsWith("PK_")))
|
||||
Delete.PrimaryKey(key.Item2).FromTable(key.Item1).Do();
|
||||
// drop keys
|
||||
var keys = _context.SqlContext.SqlSyntax.GetConstraintsPerTable(_context.Database).DistinctBy(x => x.Item2).ToArray();
|
||||
foreach (var key in keys.Where(x => x.Item2.StartsWith("FK_")))
|
||||
Delete.ForeignKey(key.Item2).OnTable(key.Item1).Do();
|
||||
foreach (var key in keys.Where(x => x.Item2.StartsWith("PK_")))
|
||||
Delete.PrimaryKey(key.Item2).FromTable(key.Item1).Do();
|
||||
|
||||
// note: we do *not* delete the DEFAULT constraints
|
||||
}
|
||||
// drop indexes
|
||||
var indexes = _context.SqlContext.SqlSyntax.GetDefinedIndexesDefinitions(_context.Database).DistinctBy(x => x.IndexName).ToArray();
|
||||
foreach (var index in indexes)
|
||||
Delete.Index(index.IndexName).OnTable(index.TableName).Do();
|
||||
}
|
||||
|
||||
// drop indexes
|
||||
if (DeleteLocal)
|
||||
else
|
||||
{
|
||||
var indexes = _context.SqlContext.SqlSyntax.GetDefinedIndexesDefinitions(_context.Database).DistinctBy(x => x.IndexName).ToList();
|
||||
// drop keys
|
||||
var keys = _context.SqlContext.SqlSyntax.GetConstraintsPerTable(_context.Database).DistinctBy(x => x.Item2).ToArray();
|
||||
foreach (var key in keys.Where(x => x.Item1 == TableName && x.Item2.StartsWith("FK_")))
|
||||
Delete.ForeignKey(key.Item2).OnTable(key.Item1).Do();
|
||||
foreach (var key in keys.Where(x => x.Item1 == TableName && x.Item2.StartsWith("PK_")))
|
||||
Delete.PrimaryKey(key.Item2).FromTable(key.Item1).Do();
|
||||
|
||||
// drop indexes
|
||||
var indexes = _context.SqlContext.SqlSyntax.GetDefinedIndexesDefinitions(_context.Database).DistinctBy(x => x.IndexName).ToArray();
|
||||
foreach (var index in indexes.Where(x => x.TableName == TableName))
|
||||
Delete.Index(index.IndexName).OnTable(index.TableName).Do();
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Migrations
|
||||
bool BuildingExpression { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a post-migration.
|
||||
/// Adds a post-migrations.
|
||||
/// </summary>
|
||||
void AddPostMigration<TMigration>()
|
||||
where TMigration : IMigration;
|
||||
|
||||
@@ -389,7 +389,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
|
||||
private DatabaseSchemaResult ValidateSchema(IScope scope)
|
||||
{
|
||||
if (_databaseFactory.Initialized == false)
|
||||
if (_databaseFactory.Configured == false)
|
||||
return new DatabaseSchemaResult(_databaseFactory.SqlContext.SqlSyntax);
|
||||
|
||||
if (_databaseSchemaValidationResult != null)
|
||||
@@ -513,7 +513,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
|
||||
private Attempt<Result> CheckReadyForInstall()
|
||||
{
|
||||
if (_databaseFactory.CanConnect == false)
|
||||
if (_databaseFactory.Configured == false)
|
||||
{
|
||||
return Attempt.Fail(new Result
|
||||
{
|
||||
@@ -539,7 +539,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
{
|
||||
Message =
|
||||
"The database configuration failed with the following message: " + ex.Message +
|
||||
"\n Please check log file for additional information (can be found in '/App_Data/Logs/')",
|
||||
"\n Please check log file for additional information (can be found in '/App_Data/Logs/UmbracoTraceLog.txt')",
|
||||
Success = false,
|
||||
Percentage = "90"
|
||||
};
|
||||
|
||||
@@ -101,33 +101,33 @@ namespace Umbraco.Core.Migrations.Install
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -1, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1", SortOrder = 0, UniqueId = new Guid("916724a5-173d-4619-b97e-b9de133dd6f5"), Text = "SYSTEM DATA: umbraco master root", NodeObjectType = Constants.ObjectTypes.SystemRoot, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -20, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,-20", SortOrder = 0, UniqueId = new Guid("0F582A79-1E41-4CF0-BFA0-76340651891A"), Text = "Recycle Bin", NodeObjectType = Constants.ObjectTypes.ContentRecycleBin, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -21, Trashed = false, ParentId = -1, UserId = -1, Level = 0, Path = "-1,-21", SortOrder = 0, UniqueId = new Guid("BF7C7CBC-952F-4518-97A2-69E9C7B33842"), Text = "Recycle Bin", NodeObjectType = Constants.ObjectTypes.MediaRecycleBin, CreateDate = DateTime.Now });
|
||||
InsertDataTypeNodeDto(Constants.DataTypes.LabelString, 35, Constants.DataTypes.Guids.LabelString, "Label (string)");
|
||||
InsertDataTypeNodeDto(Constants.DataTypes.LabelInt, 36, Constants.DataTypes.Guids.LabelInt, "Label (integer)");
|
||||
InsertDataTypeNodeDto(Constants.DataTypes.LabelBigint, 36, Constants.DataTypes.Guids.LabelBigInt, "Label (bigint)");
|
||||
InsertDataTypeNodeDto(Constants.DataTypes.LabelDateTime, 37, Constants.DataTypes.Guids.LabelDateTime, "Label (datetime)");
|
||||
InsertDataTypeNodeDto(Constants.DataTypes.LabelTime, 38, Constants.DataTypes.Guids.LabelTime, "Label (time)");
|
||||
InsertDataTypeNodeDto(Constants.DataTypes.LabelDecimal, 39, Constants.DataTypes.Guids.LabelDecimal, "Label (decimal)");
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.Upload, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.Upload}", SortOrder = 34, UniqueId = Constants.DataTypes.Guids.UploadGuid, Text = "Upload", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.Textarea, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.Textarea}", SortOrder = 33, UniqueId = Constants.DataTypes.Guids.TextareaGuid, Text = "Textarea", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.Textbox, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.Textbox}", SortOrder = 32, UniqueId = Constants.DataTypes.Guids.TextstringGuid, Text = "Textstring", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.RichtextEditor, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.RichtextEditor}", SortOrder = 4, UniqueId = Constants.DataTypes.Guids.RichtextEditorGuid, Text = "Richtext editor", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -51, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-51", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.NumericGuid, Text = "Numeric", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.Boolean, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.Boolean}", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.CheckboxGuid, Text = "True/false", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -43, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-43", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.CheckboxListGuid, Text = "Checkbox list", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DropDownSingle, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DropDownSingle}", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.DropdownGuid, Text = "Dropdown", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -41, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-41", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.DatePickerGuid, Text = "Date Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -40, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-40", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.RadioboxGuid, Text = "Radiobox", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DropDownMultiple, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DropDownMultiple}", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.DropdownMultipleGuid, Text = "Dropdown multiple", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -37, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-37", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.ApprovedColorGuid, Text = "Approved Color", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DateTime, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DateTime}", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.DatePickerWithTimeGuid, Text = "Date Picker with time", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultContentListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DefaultContentListView}", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.ListViewContentGuid, Text = Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultMediaListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DefaultMediaListView}", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.ListViewMediaGuid, Text = Constants.Conventions.DataTypes.ListViewPrefix + "Media", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultMembersListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DefaultMembersListView}", SortOrder = 2, UniqueId = Constants.DataTypes.Guids.ListViewMembersGuid, Text = Constants.Conventions.DataTypes.ListViewPrefix + "Members", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
InsertDataTypeNodeDto(Constants.DataTypes.LabelString, 35, "f0bc4bfb-b499-40d6-ba86-058885a5178c", "Label");
|
||||
InsertDataTypeNodeDto(Constants.DataTypes.LabelInt, 36, "8e7f995c-bd81-4627-9932-c40e568ec788", "Label (integer)");
|
||||
InsertDataTypeNodeDto(Constants.DataTypes.LabelBigint, 36, "930861bf-e262-4ead-a704-f99453565708", "Label (bigint)");
|
||||
InsertDataTypeNodeDto(Constants.DataTypes.LabelDateTime, 37, "0e9794eb-f9b5-4f20-a788-93acd233a7e4", "Label (datetime)");
|
||||
InsertDataTypeNodeDto(Constants.DataTypes.LabelTime, 38, "a97cec69-9b71-4c30-8b12-ec398860d7e8", "Label (time)");
|
||||
InsertDataTypeNodeDto(Constants.DataTypes.LabelDecimal, 39, "8f1ef1e1-9de4-40d3-a072-6673f631ca64", "Label (decimal)");
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -90, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-90", SortOrder = 34, UniqueId = new Guid("84c6b441-31df-4ffe-b67e-67d5bc3ae65a"), Text = "Upload", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -89, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-89", SortOrder = 33, UniqueId = new Guid("c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3"), Text = "Textarea", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -88, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-88", SortOrder = 32, UniqueId = new Guid("0cc0eba1-9960-42c9-bf9b-60e150b429ae"), Text = "Textstring", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -87, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-87", SortOrder = 4, UniqueId = new Guid("ca90c950-0aff-4e72-b976-a30b1ac57dad"), Text = "Richtext editor", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -51, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-51", SortOrder = 2, UniqueId = new Guid("2e6d3631-066e-44b8-aec4-96f09099b2b5"), Text = "Numeric", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -49, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-49", SortOrder = 2, UniqueId = new Guid("92897bc6-a5f3-4ffe-ae27-f2e7e33dda49"), Text = "True/false", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -43, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-43", SortOrder = 2, UniqueId = new Guid("fbaf13a8-4036-41f2-93a3-974f678c312a"), Text = "Checkbox list", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DropDownSingle, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DropDownSingle}", SortOrder = 2, UniqueId = new Guid("0b6a45e7-44ba-430d-9da5-4e46060b9e03"), Text = "Dropdown", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -41, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-41", SortOrder = 2, UniqueId = new Guid("5046194e-4237-453c-a547-15db3a07c4e1"), Text = "Date Picker", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -40, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-40", SortOrder = 2, UniqueId = new Guid("bb5f57c9-ce2b-4bb9-b697-4caca783a805"), Text = "Radiobox", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DropDownMultiple, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DropDownMultiple}", SortOrder = 2, UniqueId = new Guid("f38f0ac7-1d27-439c-9f3f-089cd8825a53"), Text = "Dropdown multiple", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -37, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-37", SortOrder = 2, UniqueId = new Guid("0225af17-b302-49cb-9176-b9f35cab9c17"), Text = "Approved Color", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = -36, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,-36", SortOrder = 2, UniqueId = new Guid("e4d66c0f-b935-4200-81f0-025f7256b89a"), Text = "Date Picker with time", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultContentListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DefaultContentListView}", SortOrder = 2, UniqueId = new Guid("C0808DD3-8133-4E4B-8CE8-E2BEA84A96A4"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Content", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultMediaListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DefaultMediaListView}", SortOrder = 2, UniqueId = new Guid("3A0156C4-3B8C-4803-BDC1-6871FAA83FFF"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Media", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.DefaultMembersListView, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.DefaultMembersListView}", SortOrder = 2, UniqueId = new Guid("AA2C52A0-CE87-4E65-A47C-7DF09358585D"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Members", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1031, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1031", SortOrder = 2, UniqueId = new Guid("f38bd2d7-65d0-48e6-95dc-87ce06ec2d3d"), Text = Constants.Conventions.MediaTypes.Folder, NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1032, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1032", SortOrder = 2, UniqueId = new Guid("cc07b313-0843-4aa8-bbda-871c8da728c8"), Text = Constants.Conventions.MediaTypes.Image, NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1033, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1033", SortOrder = 2, UniqueId = new Guid("4c52d8ab-54e6-40cd-999c-7a5f24903e4d"), Text = Constants.Conventions.MediaTypes.File, NodeObjectType = Constants.ObjectTypes.MediaType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.Tags, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.Tags}", SortOrder = 2, UniqueId = new Guid("b6b73142-b9c1-4bf8-a16d-e1c23320b549"), Text = "Tags", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = Constants.DataTypes.ImageCropper, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = $"-1,{Constants.DataTypes.ImageCropper}", SortOrder = 2, UniqueId = new Guid("1df9f033-e6d4-451f-b8d2-e0cbc50a836f"), Text = "Image Cropper", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1041, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1041", SortOrder = 2, UniqueId = new Guid("b6b73142-b9c1-4bf8-a16d-e1c23320b549"), Text = "Tags", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1043, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1043", SortOrder = 2, UniqueId = new Guid("1df9f033-e6d4-451f-b8d2-e0cbc50a836f"), Text = "Image Cropper", NodeObjectType = Constants.ObjectTypes.DataType, CreateDate = DateTime.Now });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.Node, "id", false, new NodeDto { NodeId = 1044, Trashed = false, ParentId = -1, UserId = -1, Level = 1, Path = "-1,1044", SortOrder = 0, UniqueId = new Guid("d59be02f-1df9-4228-aa1e-01917d806cda"), Text = Constants.Conventions.MemberTypes.DefaultAlias, NodeObjectType = Constants.ObjectTypes.MemberType, CreateDate = DateTime.Now });
|
||||
|
||||
//New UDI pickers with newer Ids
|
||||
@@ -155,10 +155,10 @@ namespace Umbraco.Core.Migrations.Install
|
||||
|
||||
private void CreateContentTypeData()
|
||||
{
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 532, NodeId = 1031, Alias = Constants.Conventions.MediaTypes.Folder, Icon = Constants.Icons.MediaFolder, Thumbnail = Constants.Icons.MediaFolder, IsContainer = false, AllowAtRoot = true, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 533, NodeId = 1032, Alias = Constants.Conventions.MediaTypes.Image, Icon = Constants.Icons.MediaImage, Thumbnail = Constants.Icons.MediaImage, AllowAtRoot = true, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 534, NodeId = 1033, Alias = Constants.Conventions.MediaTypes.File, Icon = Constants.Icons.MediaFile, Thumbnail = Constants.Icons.MediaFile, AllowAtRoot = true, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 531, NodeId = 1044, Alias = Constants.Conventions.MemberTypes.DefaultAlias, Icon = Constants.Icons.Member, Thumbnail = Constants.Icons.Member, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 532, NodeId = 1031, Alias = Constants.Conventions.MediaTypes.Folder, Icon = "icon-folder", Thumbnail = "icon-folder", IsContainer = false, AllowAtRoot = true, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 533, NodeId = 1032, Alias = Constants.Conventions.MediaTypes.Image, Icon = "icon-picture", Thumbnail = "icon-picture", AllowAtRoot = true, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 534, NodeId = 1033, Alias = Constants.Conventions.MediaTypes.File, Icon = "icon-document", Thumbnail = "icon-document", AllowAtRoot = true, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.ContentType, "pk", false, new ContentTypeDto { PrimaryKey = 531, NodeId = 1044, Alias = Constants.Conventions.MemberTypes.DefaultAlias, Icon = "icon-user", Thumbnail = "icon-user", Variations = (byte) ContentVariation.Nothing });
|
||||
}
|
||||
|
||||
private void CreateUserData()
|
||||
@@ -210,19 +210,19 @@ namespace Umbraco.Core.Migrations.Install
|
||||
|
||||
private void CreatePropertyTypeData()
|
||||
{
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 6, UniqueId = 6.ToGuid(), DataTypeId = Constants.DataTypes.ImageCropper, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.File, Name = "Upload image", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 6, UniqueId = 6.ToGuid(), DataTypeId = 1043, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.File, Name = "Upload image", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 7, UniqueId = 7.ToGuid(), DataTypeId = Constants.DataTypes.LabelInt, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Width, Name = "Width", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in pixels", Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 8, UniqueId = 8.ToGuid(), DataTypeId = Constants.DataTypes.LabelInt, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Height, Name = "Height", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in pixels", Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 9, UniqueId = 9.ToGuid(), DataTypeId = Constants.DataTypes.LabelBigint, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 10, UniqueId = 10.ToGuid(), DataTypeId = -92, ContentTypeId = 1032, PropertyTypeGroupId = 3, Alias = Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 24, UniqueId = 24.ToGuid(), DataTypeId = Constants.DataTypes.Upload, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.File, Name = "Upload file", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 24, UniqueId = 24.ToGuid(), DataTypeId = -90, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.File, Name = "Upload file", SortOrder = 0, Mandatory = true, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 25, UniqueId = 25.ToGuid(), DataTypeId = -92, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.Extension, Name = "Type", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 26, UniqueId = 26.ToGuid(), DataTypeId = Constants.DataTypes.LabelBigint, ContentTypeId = 1033, PropertyTypeGroupId = 4, Alias = Constants.Conventions.Media.Bytes, Name = "Size", SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = "in bytes", Variations = (byte) ContentVariation.Nothing });
|
||||
//membership property types
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 28, UniqueId = 28.ToGuid(), DataTypeId = Constants.DataTypes.Textarea, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.Comments, Name = Constants.Conventions.Member.CommentsLabel, SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 28, UniqueId = 28.ToGuid(), DataTypeId = -89, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.Comments, Name = Constants.Conventions.Member.CommentsLabel, SortOrder = 0, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 29, UniqueId = 29.ToGuid(), DataTypeId = Constants.DataTypes.LabelInt, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.FailedPasswordAttempts, Name = Constants.Conventions.Member.FailedPasswordAttemptsLabel, SortOrder = 1, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 30, UniqueId = 30.ToGuid(), DataTypeId = Constants.DataTypes.Boolean, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.IsApproved, Name = Constants.Conventions.Member.IsApprovedLabel, SortOrder = 2, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 31, UniqueId = 31.ToGuid(), DataTypeId = Constants.DataTypes.Boolean, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.IsLockedOut, Name = Constants.Conventions.Member.IsLockedOutLabel, SortOrder = 3, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 30, UniqueId = 30.ToGuid(), DataTypeId = -49, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.IsApproved, Name = Constants.Conventions.Member.IsApprovedLabel, SortOrder = 2, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 31, UniqueId = 31.ToGuid(), DataTypeId = -49, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.IsLockedOut, Name = Constants.Conventions.Member.IsLockedOutLabel, SortOrder = 3, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 32, UniqueId = 32.ToGuid(), DataTypeId = Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastLockoutDate, Name = Constants.Conventions.Member.LastLockoutDateLabel, SortOrder = 4, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 33, UniqueId = 33.ToGuid(), DataTypeId = Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastLoginDate, Name = Constants.Conventions.Member.LastLoginDateLabel, SortOrder = 5, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 34, UniqueId = 34.ToGuid(), DataTypeId = Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastPasswordChangeDate, Name = Constants.Conventions.Member.LastPasswordChangeDateLabel, SortOrder = 6, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing });
|
||||
@@ -266,30 +266,30 @@ namespace Umbraco.Core.Migrations.Install
|
||||
const string layouts = "[" + cardLayout + "," + listLayout + "]";
|
||||
|
||||
// TODO: Check which of the DataTypeIds below doesn't exist in umbracoNode, which results in a foreign key constraint errors.
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Constants.DataTypes.Boolean, EditorAlias = Constants.PropertyEditors.Aliases.Boolean, DbType = "Integer" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -49, EditorAlias = Constants.PropertyEditors.Aliases.Boolean, DbType = "Integer" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -51, EditorAlias = Constants.PropertyEditors.Aliases.Integer, DbType = "Integer" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -87, EditorAlias = Constants.PropertyEditors.Aliases.TinyMce, DbType = "Ntext",
|
||||
Configuration = "{\"value\":\",code,undo,redo,cut,copy,mcepasteword,stylepicker,bold,italic,bullist,numlist,outdent,indent,mcelink,unlink,mceinsertanchor,mceimage,umbracomacro,mceinserttable,umbracoembed,mcecharmap,|1|1,2,3,|0|500,400|1049,|true|\"}" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Constants.DataTypes.Textbox, EditorAlias = Constants.PropertyEditors.Aliases.TextBox, DbType = "Nvarchar" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Constants.DataTypes.Textarea, EditorAlias = Constants.PropertyEditors.Aliases.TextArea, DbType = "Ntext" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Constants.DataTypes.Upload, EditorAlias = Constants.PropertyEditors.Aliases.UploadField, DbType = "Nvarchar" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -88, EditorAlias = Constants.PropertyEditors.Aliases.TextBox, DbType = "Nvarchar" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -89, EditorAlias = Constants.PropertyEditors.Aliases.TextArea, DbType = "Ntext" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -90, EditorAlias = Constants.PropertyEditors.Aliases.UploadField, DbType = "Nvarchar" });
|
||||
InsertDataTypeDto(Constants.DataTypes.LabelString, Constants.PropertyEditors.Aliases.Label, "Nvarchar", "{\"umbracoDataValueType\":\"STRING\"}");
|
||||
InsertDataTypeDto(Constants.DataTypes.LabelInt, Constants.PropertyEditors.Aliases.Label, "Integer", "{\"umbracoDataValueType\":\"INT\"}");
|
||||
InsertDataTypeDto(Constants.DataTypes.LabelBigint, Constants.PropertyEditors.Aliases.Label, "Nvarchar", "{\"umbracoDataValueType\":\"BIGINT\"}");
|
||||
InsertDataTypeDto(Constants.DataTypes.LabelDateTime, Constants.PropertyEditors.Aliases.Label, "Date", "{\"umbracoDataValueType\":\"DATETIME\"}");
|
||||
InsertDataTypeDto(Constants.DataTypes.LabelDecimal, Constants.PropertyEditors.Aliases.Label, "Decimal", "{\"umbracoDataValueType\":\"DECIMAL\"}");
|
||||
InsertDataTypeDto(Constants.DataTypes.LabelTime, Constants.PropertyEditors.Aliases.Label, "Date", "{\"umbracoDataValueType\":\"TIME\"}");
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Constants.DataTypes.DateTime, EditorAlias = Constants.PropertyEditors.Aliases.DateTime, DbType = "Date" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -36, EditorAlias = Constants.PropertyEditors.Aliases.DateTime, DbType = "Date" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -37, EditorAlias = Constants.PropertyEditors.Aliases.ColorPicker, DbType = "Nvarchar" });
|
||||
InsertDataTypeDto(Constants.DataTypes.DropDownSingle, Constants.PropertyEditors.Aliases.DropDownListFlexible, "Nvarchar", "{\"multiple\":false}");
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -40, EditorAlias = Constants.PropertyEditors.Aliases.RadioButtonList, DbType = "Nvarchar" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -41, EditorAlias = "Umbraco.DateTime", DbType = "Date", Configuration = "{\"format\":\"YYYY-MM-DD\"}" });
|
||||
InsertDataTypeDto(Constants.DataTypes.DropDownMultiple, Constants.PropertyEditors.Aliases.DropDownListFlexible, "Nvarchar", "{\"multiple\":true}");
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = -43, EditorAlias = Constants.PropertyEditors.Aliases.CheckBoxList, DbType = "Nvarchar" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Constants.DataTypes.Tags, EditorAlias = Constants.PropertyEditors.Aliases.Tags, DbType = "Ntext",
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1041, EditorAlias = Constants.PropertyEditors.Aliases.Tags, DbType = "Ntext",
|
||||
Configuration = "{\"group\":\"default\", \"storageType\":\"Json\"}"
|
||||
});
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Constants.DataTypes.ImageCropper, EditorAlias = Constants.PropertyEditors.Aliases.ImageCropper, DbType = "Ntext" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = 1043, EditorAlias = Constants.PropertyEditors.Aliases.ImageCropper, DbType = "Ntext" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Constants.DataTypes.DefaultContentListView, EditorAlias = Constants.PropertyEditors.Aliases.ListView, DbType = "Nvarchar",
|
||||
Configuration = "{\"pageSize\":100, \"orderBy\":\"updateDate\", \"orderDirection\":\"desc\", \"layouts\":" + layouts + ", \"includeProperties\":[{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1},{\"alias\":\"owner\",\"header\":\"Updated by\",\"isSystem\":1}]}" });
|
||||
_database.Insert(Constants.DatabaseSchema.Tables.DataType, "pk", false, new DataTypeDto { NodeId = Constants.DataTypes.DefaultMediaListView, EditorAlias = Constants.PropertyEditors.Aliases.ListView, DbType = "Nvarchar",
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace Umbraco.Core.Migrations.Install
|
||||
typeof (LogDto),
|
||||
typeof (MacroDto),
|
||||
typeof (MacroPropertyDto),
|
||||
typeof (MemberPropertyTypeDto),
|
||||
typeof (MemberTypeDto),
|
||||
typeof (MemberDto),
|
||||
typeof (Member2MemberGroupDto),
|
||||
typeof (PropertyTypeGroupDto),
|
||||
|
||||
@@ -41,7 +41,6 @@ namespace Umbraco.Core.Migrations
|
||||
public void AddPostMigration<TMigration>()
|
||||
where TMigration : IMigration
|
||||
{
|
||||
// just adding - will be de-duplicated when executing
|
||||
PostMigrations.Add(typeof(TMigration));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,6 @@ namespace Umbraco.Core.Migrations
|
||||
if (_executed)
|
||||
throw new InvalidOperationException("This expression has already been executed.");
|
||||
_executed = true;
|
||||
Context.BuildingExpression = false;
|
||||
|
||||
if (sql == null)
|
||||
{
|
||||
|
||||
@@ -240,8 +240,7 @@ namespace Umbraco.Core.Migrations
|
||||
if (finalState == null)
|
||||
finalState = kvp.Key;
|
||||
else
|
||||
throw new InvalidOperationException($"Multiple final states have been detected in the plan (\"{finalState}\", \"{kvp.Key}\")."
|
||||
+ " Make sure the plan contains only one final state.");
|
||||
throw new Exception("Multiple final states have been detected.");
|
||||
}
|
||||
|
||||
// now check for loops
|
||||
@@ -255,8 +254,7 @@ namespace Umbraco.Core.Migrations
|
||||
while (nextTransition != null && !verified.Contains(nextTransition.SourceState))
|
||||
{
|
||||
if (visited.Contains(nextTransition.SourceState))
|
||||
throw new InvalidOperationException($"A loop has been detected in the plan around state \"{nextTransition.SourceState}\"."
|
||||
+ " Make sure the plan does not contain circular transition paths.");
|
||||
throw new Exception("A loop has been detected.");
|
||||
visited.Add(nextTransition.SourceState);
|
||||
nextTransition = _transitions[nextTransition.TargetState];
|
||||
}
|
||||
@@ -266,14 +264,6 @@ namespace Umbraco.Core.Migrations
|
||||
_finalState = finalState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throws an exception when the initial state is unknown.
|
||||
/// </summary>
|
||||
protected virtual void ThrowOnUnknownInitialState(string state)
|
||||
{
|
||||
throw new InvalidOperationException($"The migration plan does not support migrating from state \"{state}\".");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the plan.
|
||||
/// </summary>
|
||||
@@ -297,15 +287,13 @@ namespace Umbraco.Core.Migrations
|
||||
logger.Info<MigrationPlan>("At {OrigState}", string.IsNullOrWhiteSpace(origState) ? "origin": origState);
|
||||
|
||||
if (!_transitions.TryGetValue(origState, out var transition))
|
||||
ThrowOnUnknownInitialState(origState);
|
||||
throw new Exception($"Unknown state \"{origState}\".");
|
||||
|
||||
var context = new MigrationContext(scope.Database, logger);
|
||||
context.PostMigrations.AddRange(_postMigrationTypes);
|
||||
|
||||
while (transition != null)
|
||||
{
|
||||
logger.Info<MigrationPlan>("Execute {MigrationType}", transition.MigrationType.Name);
|
||||
|
||||
var migration = migrationBuilder.Build(transition.MigrationType, context);
|
||||
migration.Migrate();
|
||||
|
||||
@@ -314,8 +302,6 @@ namespace Umbraco.Core.Migrations
|
||||
|
||||
logger.Info<MigrationPlan>("At {OrigState}", origState);
|
||||
|
||||
// throw a raw exception here: this should never happen as the plan has
|
||||
// been validated - this is just a paranoid safety test
|
||||
if (!_transitions.TryGetValue(origState, out transition))
|
||||
throw new Exception($"Unknown state \"{origState}\".");
|
||||
}
|
||||
@@ -336,8 +322,7 @@ namespace Umbraco.Core.Migrations
|
||||
|
||||
logger.Info<MigrationPlan>("Done (pending scope completion).");
|
||||
|
||||
// safety check - again, this should never happen as the plan has been validated,
|
||||
// and this is just a paranoid safety test
|
||||
// safety check
|
||||
if (origState != _finalState)
|
||||
throw new Exception($"Internal error, reached state {origState} which is not final state {_finalState}");
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
using Umbraco.Core.Migrations.Install;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.Common
|
||||
{
|
||||
public class CreateKeysAndIndexes : MigrationBase
|
||||
{
|
||||
public CreateKeysAndIndexes(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
// remove those that may already have keys
|
||||
Delete.KeysAndIndexes(Constants.DatabaseSchema.Tables.KeyValue).Do();
|
||||
|
||||
// re-create *all* keys and indexes
|
||||
foreach (var x in DatabaseSchemaCreator.OrderedTables)
|
||||
Create.KeysAndIndexes(x).Do();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
namespace Umbraco.Core.Migrations.Upgrade.Common
|
||||
{
|
||||
public class DeleteKeysAndIndexes : MigrationBase
|
||||
{
|
||||
public DeleteKeysAndIndexes(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
// all v7.14 tables
|
||||
var tables = new[]
|
||||
{
|
||||
"cmsContent",
|
||||
"cmsContentType",
|
||||
"cmsContentType2ContentType",
|
||||
"cmsContentTypeAllowedContentType",
|
||||
"cmsContentVersion",
|
||||
"cmsContentXml",
|
||||
"cmsDataType",
|
||||
"cmsDataTypePreValues",
|
||||
"cmsDictionary",
|
||||
"cmsDocument",
|
||||
"cmsDocumentType",
|
||||
"cmsLanguageText",
|
||||
"cmsMacro",
|
||||
"cmsMacroProperty",
|
||||
"cmsMedia",
|
||||
"cmsMember",
|
||||
"cmsMember2MemberGroup",
|
||||
"cmsMemberType",
|
||||
"cmsPreviewXml",
|
||||
"cmsPropertyData",
|
||||
"cmsPropertyType",
|
||||
"cmsPropertyTypeGroup",
|
||||
"cmsTagRelationship",
|
||||
"cmsTags",
|
||||
"cmsTask",
|
||||
"cmsTaskType",
|
||||
"cmsTemplate",
|
||||
"umbracoAccess",
|
||||
"umbracoAccessRule",
|
||||
"umbracoAudit",
|
||||
"umbracoCacheInstruction",
|
||||
"umbracoConsent",
|
||||
"umbracoDomains",
|
||||
"umbracoExternalLogin",
|
||||
"umbracoLanguage",
|
||||
"umbracoLock",
|
||||
"umbracoLog",
|
||||
"umbracoMigration",
|
||||
"umbracoNode",
|
||||
"umbracoRedirectUrl",
|
||||
"umbracoRelation",
|
||||
"umbracoRelationType",
|
||||
"umbracoServer",
|
||||
"umbracoUser",
|
||||
"umbracoUser2NodeNotify",
|
||||
"umbracoUser2UserGroup",
|
||||
"umbracoUserGroup",
|
||||
"umbracoUserGroup2App",
|
||||
"umbracoUserGroup2NodePermission",
|
||||
"umbracoUserLogin",
|
||||
"umbracoUserStartNode",
|
||||
};
|
||||
|
||||
// delete *all* keys and indexes - because of FKs
|
||||
// on known v7 tables only
|
||||
foreach (var table in tables)
|
||||
Delete.KeysAndIndexes(table, false, true).Do();
|
||||
foreach (var table in tables)
|
||||
Delete.KeysAndIndexes(table, true, false).Do();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,10 @@
|
||||
using System.Configuration;
|
||||
using Semver;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Migrations.Upgrade.Common;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_7_12_0;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_7_14_0;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_8_0_0;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_8_0_1;
|
||||
using Umbraco.Core.Migrations.Upgrade.V_8_1_0;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade
|
||||
{
|
||||
@@ -14,9 +14,6 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
/// </summary>
|
||||
public class UmbracoPlan : MigrationPlan
|
||||
{
|
||||
private const string InitPrefix = "{init-";
|
||||
private const string InitSuffix = "}";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoPlan"/> class.
|
||||
/// </summary>
|
||||
@@ -26,27 +23,6 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
DefinePlan();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the initial state corresponding to a version.
|
||||
/// </summary>
|
||||
private static string GetInitState(SemVersion version)
|
||||
=> InitPrefix + version + InitSuffix;
|
||||
|
||||
/// <summary>
|
||||
/// Tries to extract a version from an initial state.
|
||||
/// </summary>
|
||||
private static bool TryGetInitStateVersion(string state, out string version)
|
||||
{
|
||||
if (state.StartsWith(InitPrefix) && state.EndsWith(InitSuffix))
|
||||
{
|
||||
version = state.TrimStart(InitPrefix).TrimEnd(InitSuffix);
|
||||
return true;
|
||||
}
|
||||
|
||||
version = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <remarks>
|
||||
/// <para>The default initial state in plans is string.Empty.</para>
|
||||
@@ -64,37 +40,23 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
if (!SemVersion.TryParse(ConfigurationManager.AppSettings[Constants.AppSettings.ConfigurationStatus], out var currentVersion))
|
||||
throw new InvalidOperationException($"Could not get current version from web.config {Constants.AppSettings.ConfigurationStatus} appSetting.");
|
||||
|
||||
// we currently support upgrading from 7.10.0 and later
|
||||
if (currentVersion < new SemVersion(7, 10))
|
||||
throw new InvalidOperationException($"Version {currentVersion} cannot be migrated to {UmbracoVersion.SemanticVersion}.");
|
||||
|
||||
// cannot go back in time
|
||||
if (currentVersion > UmbracoVersion.SemanticVersion)
|
||||
throw new InvalidOperationException($"Version {currentVersion} cannot be downgraded to {UmbracoVersion.SemanticVersion}.");
|
||||
|
||||
// only from 7.14.0 and above
|
||||
var minVersion = new SemVersion(7, 14);
|
||||
if (currentVersion < minVersion)
|
||||
throw new InvalidOperationException($"Version {currentVersion} cannot be migrated to {UmbracoVersion.SemanticVersion}."
|
||||
+ $" Please upgrade first to at least {minVersion}.");
|
||||
// upgrading from version 7 => initial state is eg "{init-7.10.0}"
|
||||
// anything else is not supported - ie if 8 and above, we should have an initial state already
|
||||
if (currentVersion.Major != 7)
|
||||
throw new InvalidOperationException($"Version {currentVersion} is not supported by the migration plan.");
|
||||
|
||||
// Force versions between 7.14.*-7.15.* into into 7.14 initial state. Because there is no db-changes,
|
||||
// and we don't want users to workaround my putting in version 7.14.0 them self.
|
||||
if (minVersion <= currentVersion && currentVersion < new SemVersion(7, 16))
|
||||
return GetInitState(minVersion);
|
||||
|
||||
// initial state is eg "{init-7.14.0}"
|
||||
return GetInitState(currentVersion);
|
||||
return "{init-" + currentVersion + "}";
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ThrowOnUnknownInitialState(string state)
|
||||
{
|
||||
if (TryGetInitStateVersion(state, out var initVersion))
|
||||
{
|
||||
throw new InvalidOperationException($"Version {UmbracoVersion.SemanticVersion} does not support migrating from {initVersion}."
|
||||
+ $" Please verify which versions support migrating from {initVersion}.");
|
||||
}
|
||||
|
||||
base.ThrowOnUnknownInitialState(state);
|
||||
}
|
||||
|
||||
// define the plan
|
||||
protected void DefinePlan()
|
||||
{
|
||||
@@ -107,23 +69,21 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
//
|
||||
// If the new migration causes a merge conflict, because someone else also added another
|
||||
// new migration, you NEED to fix the conflict by providing one default path, and paths
|
||||
// out of the conflict states (see examples below).
|
||||
// out of the conflict states (see example below).
|
||||
//
|
||||
// * Porting from version 7:
|
||||
// Append the ported migration to the main chain, using a new guid (same as above).
|
||||
// Create a new special chain from the {init-...} state to the main chain.
|
||||
// Create a new special chain from the {init-...} state to the main chain (see example
|
||||
// below).
|
||||
|
||||
|
||||
// plan starts at 7.14.0 (anything before 7.14.0 is not supported)
|
||||
// plan starts at 7.10.0 (anything before 7.10.0 is not supported)
|
||||
// upgrades from 7 to 8, and then takes care of all eventual upgrades
|
||||
//
|
||||
From(GetInitState(new SemVersion(7, 14, 0)));
|
||||
|
||||
// begin migrating from v7 - remove all keys and indexes
|
||||
To<DeleteKeysAndIndexes>("{B36B9ABD-374E-465B-9C5F-26AB0D39326F}");
|
||||
|
||||
From("{init-7.10.0}");
|
||||
To<AddLockObjects>("{7C447271-CA3F-4A6A-A913-5D77015655CB}");
|
||||
To<AddContentNuTable>("{CBFF58A2-7B50-4F75-8E98-249920DB0F37}");
|
||||
To<RenameMediaVersionTable>("{5CB66059-45F4-48BA-BCBD-C5035D79206B}");
|
||||
To<RefactorXmlColumns>("{3D18920C-E84D-405C-A06A-B7CEE52FE5DD}");
|
||||
To<VariantsMigration>("{FB0A5429-587E-4BD0-8A67-20F0E7E62FF7}");
|
||||
To<DropMigrationsTable>("{F0C42457-6A3B-4912-A7EA-F27ED85A2092}");
|
||||
To<DataTypeMigration>("{8640C9E4-A1C0-4C59-99BB-609B4E604981}");
|
||||
@@ -134,55 +94,90 @@ namespace Umbraco.Core.Migrations.Upgrade
|
||||
ToWithReplace<AddVariationTables2, AddVariationTables1A>("{941B2ABA-2D06-4E04-81F5-74224F1DB037}", "{76DF5CD7-A884-41A5-8DC6-7860D95B1DF5}"); // kill AddVariationTable1
|
||||
To<RefactorMacroColumns>("{A7540C58-171D-462A-91C5-7A9AA5CB8BFD}");
|
||||
|
||||
Merge()
|
||||
.To<UserForeignKeys>("{3E44F712-E2E3-473A-AE49-5D7F8E67CE3F}")
|
||||
.With()
|
||||
.To<AddTypedLabels>("{65D6B71C-BDD5-4A2E-8D35-8896325E9151}")
|
||||
Merge().To<UserForeignKeys>("{3E44F712-E2E3-473A-AE49-5D7F8E67CE3F}") // shannon added that one
|
||||
.With().To<AddTypedLabels>("{65D6B71C-BDD5-4A2E-8D35-8896325E9151}") // stephan added that one
|
||||
.As("{4CACE351-C6B9-4F0C-A6BA-85A02BBD39E4}");
|
||||
|
||||
To<ContentVariationMigration>("{1350617A-4930-4D61-852F-E3AA9E692173}");
|
||||
To<FallbackLanguage>("{CF51B39B-9B9A-4740-BB7C-EAF606A7BFBF}");
|
||||
To<UpdateDefaultMandatoryLanguage>("{5F4597F4-A4E0-4AFE-90B5-6D2F896830EB}");
|
||||
To<RefactorVariantsModel>("{290C18EE-B3DE-4769-84F1-1F467F3F76DA}");
|
||||
To<UpdateUmbracoConsent>("{39E5B1F7-A50B-437E-B768-1723AEC45B65}"); // from 7.12.0
|
||||
|
||||
Merge()
|
||||
.To<AddRelationTypeForMediaFolderOnDelete>("{0541A62B-EF87-4CA2-8225-F0EB98ECCC9F}") // from 7.12.0
|
||||
.To<IncreaseLanguageIsoCodeColumnLength>("{EB34B5DC-BB87-4005-985E-D983EA496C38}") // from 7.12.0
|
||||
.To<RenameTrueFalseField>("{517CE9EA-36D7-472A-BF4B-A0D6FB1B8F89}") // from 7.12.0
|
||||
.To<SetDefaultTagsStorageType>("{BBD99901-1545-40E4-8A5A-D7A675C7D2F2}") // from 7.12.0
|
||||
.With()
|
||||
.To<FallbackLanguage>("{CF51B39B-9B9A-4740-BB7C-EAF606A7BFBF}") // andy added that one
|
||||
.As("{8B14CEBD-EE47-4AAD-A841-93551D917F11}");
|
||||
|
||||
ToWithReplace<UpdateDefaultMandatoryLanguage>("{2C87AA47-D1BC-4ECB-8A73-2D8D1046C27F}", "{5F4597F4-A4E0-4AFE-90B5-6D2F896830EB}"); // merge
|
||||
ToWithReplace<RefactorVariantsModel>("{B19BF0F2-E1C6-4AEB-A146-BC559D97A2C6}", "{290C18EE-B3DE-4769-84F1-1F467F3F76DA}"); // merge
|
||||
To<DropTaskTables>("{6A2C7C1B-A9DB-4EA9-B6AB-78E7D5B722A7}");
|
||||
To<FixLockTablePrimaryKey>("{77874C77-93E5-4488-A404-A630907CEEF0}");
|
||||
To<AddLogTableColumns>("{8804D8E8-FE62-4E3A-B8A2-C047C2118C38}");
|
||||
To<DropPreValueTable>("{23275462-446E-44C7-8C2C-3B8C1127B07D}");
|
||||
To<DropDownPropertyEditorsMigration>("{6B251841-3069-4AD5-8AE9-861F9523E8DA}");
|
||||
To<TagsMigrationFix>("{EE429F1B-9B26-43CA-89F8-A86017C809A3}");
|
||||
To<DropTemplateDesignColumn>("{08919C4B-B431-449C-90EC-2B8445B5C6B1}");
|
||||
To<TablesForScheduledPublishing>("{7EB0254C-CB8B-4C75-B15B-D48C55B449EB}");
|
||||
To<DropTaskTables>("{648A2D5F-7467-48F8-B309-E99CEEE00E2A}"); // fixed version
|
||||
To<MakeTagsVariant>("{C39BF2A7-1454-4047-BBFE-89E40F66ED63}");
|
||||
To<MakeRedirectUrlVariant>("{64EBCE53-E1F0-463A-B40B-E98EFCCA8AE2}");
|
||||
To<AddContentTypeIsElementColumn>("{0009109C-A0B8-4F3F-8FEB-C137BBDDA268}");
|
||||
To<UpdateMemberGroupPickerData>("{8A027815-D5CD-4872-8B88-9A51AB5986A6}"); // from 7.14.0
|
||||
To<ConvertRelatedLinksToMultiUrlPicker>("{ED28B66A-E248-4D94-8CDB-9BDF574023F0}");
|
||||
To<UpdatePickerIntegerValuesToUdi>("{38C809D5-6C34-426B-9BEA-EFD39162595C}");
|
||||
To<RenameUmbracoDomainsTable>("{6017F044-8E70-4E10-B2A3-336949692ADD}");
|
||||
To<AddUserLoginDtoDateIndex>("{98339BEF-E4B2-48A8-B9D1-D173DC842BBE}");
|
||||
|
||||
Merge()
|
||||
.To<DropXmlTables>("{CDBEDEE4-9496-4903-9CF2-4104E00FF960}")
|
||||
.With()
|
||||
.To<RadioAndCheckboxPropertyEditorsMigration>("{940FD19A-00A8-4D5C-B8FF-939143585726}")
|
||||
.To<RadioAndCheckboxAndDropdownPropertyEditorsMigration>("{940FD19A-00A8-4D5C-B8FF-939143585726}")
|
||||
.As("{0576E786-5C30-4000-B969-302B61E90CA3}");
|
||||
|
||||
To<FixLanguageIsoCodeLength>("{48AD6CCD-C7A4-4305-A8AB-38728AD23FC5}");
|
||||
|
||||
// finish migrating from v7 - recreate all keys and indexes
|
||||
To<CreateKeysAndIndexes>("{3F9764F5-73D0-4D45-8804-1240A66E43A2}");
|
||||
|
||||
To<RenameLabelAndRichTextPropertyEditorAliases>("{E0CBE54D-A84F-4A8F-9B13-900945FD7ED9}");
|
||||
To<MergeDateAndDateTimePropertyEditor>("{78BAF571-90D0-4D28-8175-EF96316DA789}");
|
||||
// release-8.0.0
|
||||
|
||||
// to 8.0.1...
|
||||
To<ChangeNuCacheJsonFormat>("{80C0A0CB-0DD5-4573-B000-C4B7C313C70D}");
|
||||
// release-8.0.1
|
||||
|
||||
// to 8.1.0...
|
||||
To<ConvertTinyMceAndGridMediaUrlsToLocalLink>("{B69B6E8C-A769-4044-A27E-4A4E18D1645A}");
|
||||
To<RenameUserLoginDtoDateIndex>("{0372A42B-DECF-498D-B4D1-6379E907EB94}");
|
||||
To<FixContentNuCascade>("{5B1E0D93-F5A3-449B-84BA-65366B84E2D4}");
|
||||
|
||||
//FINAL
|
||||
|
||||
|
||||
|
||||
|
||||
// and then, need to support upgrading from more recent 7.x
|
||||
//
|
||||
From("{init-7.10.1}").To("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.10.2}").To("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.10.3}").To("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.10.4}").To("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.10.5}").To("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.11.0}").To("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.11.1}").To("{init-7.10.0}"); // same as 7.10.0
|
||||
From("{init-7.11.2}").To("{init-7.10.0}"); // same as 7.10.0
|
||||
|
||||
// 7.12.0 has migrations, define a custom chain which copies the chain
|
||||
// going from {init-7.10.0} to former final (1350617A) , and then goes straight to
|
||||
// main chain, skipping the migrations
|
||||
//
|
||||
From("{init-7.12.0}");
|
||||
// clone start / clone stop / target
|
||||
ToWithClone("{init-7.10.0}", "{1350617A-4930-4D61-852F-E3AA9E692173}", "{BBD99901-1545-40E4-8A5A-D7A675C7D2F2}");
|
||||
|
||||
From("{init-7.12.1}").To("{init-7.10.0}"); // same as 7.12.0
|
||||
From("{init-7.12.2}").To("{init-7.10.0}"); // same as 7.12.0
|
||||
From("{init-7.12.3}").To("{init-7.10.0}"); // same as 7.12.0
|
||||
From("{init-7.12.4}").To("{init-7.10.0}"); // same as 7.12.0
|
||||
From("{init-7.13.0}").To("{init-7.10.0}"); // same as 7.12.0
|
||||
From("{init-7.13.1}").To("{init-7.10.0}"); // same as 7.12.0
|
||||
|
||||
// 7.14.0 has migrations, handle it...
|
||||
// clone going from 7.10 to 1350617A (the last one before we started to merge 7.12 migrations), then
|
||||
// clone going from CF51B39B (after 7.12 migrations) to 0009109C (the last one before we started to merge 7.12 migrations),
|
||||
// ending in 8A027815 (after 7.14 migrations)
|
||||
From("{init-7.14.0}")
|
||||
.ToWithClone("{init-7.10.0}", "{1350617A-4930-4D61-852F-E3AA9E692173}", "{9109B8AF-6B34-46EE-9484-7434196D0C79}")
|
||||
.ToWithClone("{CF51B39B-9B9A-4740-BB7C-EAF606A7BFBF}", "{0009109C-A0B8-4F3F-8FEB-C137BBDDA268}", "{8A027815-D5CD-4872-8B88-9A51AB5986A6}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.IO;
|
||||
using Umbraco.Core.IO;
|
||||
using File = System.IO.File;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_7_10_0
|
||||
{
|
||||
/// <summary>
|
||||
/// Renames the preview folder containing static HTML files to ensure it does not interfere with the MVC route
|
||||
/// that is now supposed to render these views dynamically. We don't want to delete as people may have made
|
||||
/// customizations to these files that would need to be migrated to the new .cshtml view files.
|
||||
/// </summary>
|
||||
public class RenamePreviewFolder : MigrationBase
|
||||
{
|
||||
public RenamePreviewFolder(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
var previewFolderPath = IOHelper.MapPath(SystemDirectories.Umbraco + "/preview");
|
||||
if (Directory.Exists(previewFolderPath))
|
||||
{
|
||||
var newPath = previewFolderPath.Replace("preview", "preview.old");
|
||||
if (Directory.Exists(newPath) == false)
|
||||
{
|
||||
Directory.Move(previewFolderPath, newPath);
|
||||
var readmeText =
|
||||
$"Static HTML files used for preview and canvas editing functionality no longer live in this directory.\r\n" +
|
||||
$"Instead they have been recreated as MVC views and can now be found in '~/Umbraco/Views/Preview'.\r\n" +
|
||||
$"See issue: http://issues.umbraco.org/issue/U4-11090";
|
||||
File.WriteAllText(Path.Combine(newPath, "readme.txt"), readmeText);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_7_12_0
|
||||
{
|
||||
public class AddRelationTypeForMediaFolderOnDelete : MigrationBase
|
||||
{
|
||||
|
||||
public AddRelationTypeForMediaFolderOnDelete(IMigrationContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
var relationTypeCount = Context.Database.ExecuteScalar<int>("SELECT COUNT(*) FROM umbracoRelationType WHERE alias=@alias",
|
||||
new { alias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias });
|
||||
|
||||
if (relationTypeCount > 0)
|
||||
return;
|
||||
|
||||
var uniqueId = (Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias + "____" + Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName).ToGuid();
|
||||
Insert.IntoTable("umbracoRelationType").Row(new
|
||||
{
|
||||
typeUniqueId = uniqueId,
|
||||
alias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias,
|
||||
name = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName,
|
||||
childObjectType = Constants.ObjectTypes.MediaType,
|
||||
parentObjectType = Constants.ObjectTypes.MediaType,
|
||||
dual = false
|
||||
}).Do();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_7_12_0
|
||||
{
|
||||
public class IncreaseLanguageIsoCodeColumnLength : MigrationBase
|
||||
{
|
||||
public IncreaseLanguageIsoCodeColumnLength(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
// Some people seem to have a constraint in their DB instead of an index, we'd need to drop that one
|
||||
// See: https://our.umbraco.com/forum/using-umbraco-and-getting-started/93282-upgrade-from-711-to-712-fails
|
||||
var constraints = SqlSyntax.GetConstraintsPerTable(Context.Database).Distinct().ToArray();
|
||||
if (constraints.Any(x => x.Item2.InvariantEquals("IX_umbracoLanguage_languageISOCode")))
|
||||
{
|
||||
Delete.UniqueConstraint("IX_umbracoLanguage_languageISOCode").FromTable("umbracoLanguage").Do();
|
||||
}
|
||||
|
||||
//Now check for indexes of that name and drop that if it exists
|
||||
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database);
|
||||
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoLanguage_languageISOCode")))
|
||||
{
|
||||
Delete.Index("IX_umbracoLanguage_languageISOCode").OnTable("umbracoLanguage").Do();
|
||||
}
|
||||
|
||||
Alter.Table("umbracoLanguage")
|
||||
.AlterColumn("languageISOCode")
|
||||
.AsString(14)
|
||||
.Nullable()
|
||||
.Do();
|
||||
|
||||
Create.Index("IX_umbracoLanguage_languageISOCode")
|
||||
.OnTable("umbracoLanguage")
|
||||
.OnColumn("languageISOCode")
|
||||
.Ascending()
|
||||
.WithOptions()
|
||||
.Unique()
|
||||
.Do();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_7_12_0
|
||||
{
|
||||
public class RenameTrueFalseField : MigrationBase
|
||||
{
|
||||
public RenameTrueFalseField(IMigrationContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
//rename the existing true/false field
|
||||
Update.Table(NodeDto.TableName).Set(new { text = "Checkbox" }).Where(new { id = Constants.DataTypes.Boolean }).Do();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Dtos;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Core.Migrations.Upgrade.V_7_12_0
|
||||
{
|
||||
/// <summary>
|
||||
/// Set the default storageType for the tags datatype to "CSV" to ensure backwards compatibility since the default is going to be JSON in new versions.
|
||||
/// </summary>
|
||||
public class SetDefaultTagsStorageType : MigrationBase
|
||||
{
|
||||
public SetDefaultTagsStorageType(IMigrationContext context)
|
||||
: base(context)
|
||||
{ }
|
||||
|
||||
// dummy editor for deserialization
|
||||
private class TagConfigurationEditor : ConfigurationEditor<TagConfiguration>
|
||||
{ }
|
||||
|
||||
public override void Migrate()
|
||||
{
|
||||
// get all Umbraco.Tags datatypes
|
||||
var dataTypeDtos = Database.Fetch<DataTypeDto>(Context.SqlContext.Sql()
|
||||
.Select<DataTypeDto>()
|
||||
.From<DataTypeDto>()
|
||||
.Where<DataTypeDto>(x => x.EditorAlias == Constants.PropertyEditors.Aliases.Tags));
|
||||
|
||||
// get a dummy editor for deserialization
|
||||
var editor = new TagConfigurationEditor();
|
||||
|
||||
foreach (var dataTypeDto in dataTypeDtos)
|
||||
{
|
||||
// need to check storageType on raw dictionary, as TagConfiguration would have a default value
|
||||
var dictionary = JsonConvert.DeserializeObject<JObject>(dataTypeDto.Configuration);
|
||||
|
||||
// if missing, use TagConfiguration to properly update the configuration
|
||||
// due to ... reasons ... the key can start with a lower or upper 'S'
|
||||
if (!dictionary.ContainsKey("storageType") && !dictionary.ContainsKey("StorageType"))
|
||||
{
|
||||
var configuration = (TagConfiguration)editor.FromDatabase(dataTypeDto.Configuration);
|
||||
configuration.StorageType = TagsStorageType.Csv;
|
||||
dataTypeDto.Configuration = ConfigurationEditor.ToDatabase(configuration);
|
||||
Database.Update(dataTypeDto);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user