Compare commits

..

5 Commits

Author SHA1 Message Date
Stephan b3867d9d55 Post-merge fixes 2019-06-27 12:47:40 +02:00
Stephan 834aeee107 Fix slimmed down ModelsBuilder 2019-06-27 12:47:40 +02:00
Stephan f3643747b3 Publicize IEditorValidator 2019-06-27 12:47:20 +02:00
Stephan ee83c02424 Import slimmed down ModelsBuilder 2019-06-27 12:47:19 +02:00
Stephan 355a5e0eb4 Remove ModelsBuilder NuGet dependency, add project 2019-06-27 12:47:19 +02:00
371 changed files with 5547 additions and 7359 deletions
+1 -1
View File
@@ -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 -3
View File
@@ -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">
@@ -45,7 +44,7 @@
<dependency id="Umbraco.SqlServerCE" version="[4.0.0.1,4.999999)" />
<dependency id="NPoco" version="[3.9.4,3.999999)" />
</group>
</dependencies>
</metadata>
<files>
@@ -56,6 +55,6 @@
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.xml" target="lib\net472\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" />
</files>
</package>
+6 -4
View File
@@ -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>
@@ -52,14 +51,17 @@
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.dll" target="lib\net472\Umbraco.Web.dll" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.dll" target="lib\net472\Umbraco.Web.UI.dll" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.dll" target="lib\net472\Umbraco.Examine.dll" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.ModelsBuilder.dll" target="lib\net472\Umbraco.ModelsBuilder.dll" />
<!-- docs -->
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.xml" target="lib\net472\Umbraco.Web.xml" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.xml" target="lib\net472\Umbraco.Web.UI.xml" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.xml" target="lib\net472\Umbraco.Examine.xml" />
<file src="$BuildTmp$\WebApp\bin\Umbraco.ModelsBuilder.xml" target="lib\net472\Umbraco.ModelsBuilder.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$\bin\Umbraco.Examine.pdb" target="lib" />
<file src="$BuildTmp$\bin\Umbraco.ModelsBuilder.pdb" target="lib" />
</files>
</package>
-2
View File
@@ -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,6 @@
not want this to happen as the alpha of the next major is, really, the next major already.
-->
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.4.0, 2.999999)" />
<dependency id="Umbraco.ModelsBuilder.Ui" version="[8.1.0]" />
<dependency id="ImageProcessor.Web" version="[4.10.0.100,4.999999)" />
<dependency id="ImageProcessor.Web.Config" version="[2.5.0.100,2.999999)" />
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[2.0.1,2.999999)" />
@@ -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>
+4 -21
View File
@@ -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
}
}
+10 -10
View File
@@ -15,7 +15,7 @@
[Parameter(Mandatory=$false)]
[Alias("doc")]
[switch] $docfx = $false,
# keep the build directories, don't clear them
[Parameter(Mandatory=$false)]
[Alias("c")]
@@ -392,13 +392,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 -SymbolPackageFormat snupkg -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 -SymbolPackageFormat snupkg -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" `
@@ -429,37 +429,37 @@
Write-Host "Prepare Azure Gallery"
$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"
+2 -2
View File
@@ -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.1.0")]
[assembly: AssemblyInformationalVersion("8.1.0")]
+22 -25
View File
@@ -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()
{
+2 -2
View File
@@ -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.
+2 -350
View File
@@ -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);
}
}
}
}
+18 -68
View File
@@ -5,89 +5,39 @@
public static class Icons
{
/// <summary>
/// System default icon
/// System contenttype icon
/// </summary>
public const string DefaultIcon = Content;
public const string ContentType = "icon-arrangement";
/// <summary>
/// System content icon
/// </summary>
public const string Content = "icon-document";
/// <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";
}
}
}
@@ -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>
@@ -203,24 +186,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";
}
}
}
}
+1 -2
View File
@@ -10,8 +10,6 @@ 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>();
@@ -114,6 +112,7 @@ namespace Umbraco.Core
}
}
/// <summary>
/// Returns true if all items in the other collection exist in this collection
/// </summary>
+1 -6
View File
@@ -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"));
@@ -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",
@@ -74,11 +74,6 @@ namespace Umbraco.Core.Migrations.Upgrade
throw new InvalidOperationException($"Version {currentVersion} cannot be migrated to {UmbracoVersion.SemanticVersion}."
+ $" Please upgrade first to at least {minVersion}.");
// 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);
}
@@ -19,8 +19,8 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
var sqlDataTypes = Sql()
.Select<DataTypeDto>()
.From<DataTypeDto>()
.Where<DataTypeDto>(x => x.EditorAlias == Constants.PropertyEditors.Legacy.Aliases.RelatedLinks
|| x.EditorAlias == Constants.PropertyEditors.Legacy.Aliases.RelatedLinks2);
.Where<DataTypeDto>(x => x.EditorAlias == "Umbraco.RelatedLinks"
|| x.EditorAlias == "Umbraco.RelatedLinks2");
var dataTypes = Database.Fetch<DataTypeDto>(sqlDataTypes);
var dataTypeIds = dataTypes.Select(x => x.NodeId).ToList();
@@ -50,10 +50,10 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
var properties = Database.Fetch<PropertyDataDto>(sqlPropertyData);
// Create a Multi URL Picker datatype for the converted RelatedLinks data
foreach (var property in properties)
{
var value = property.Value?.ToString();
var value = property.Value.ToString();
if (string.IsNullOrWhiteSpace(value))
continue;
@@ -89,7 +89,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
Name = relatedLink.Caption,
Target = relatedLink.NewWindow ? "_blank" : null,
Udi = udi,
// Should only have a URL if it's an external link otherwise it wil be a UDI
// Should only have a URL if it's an external link otherwise it wil be a UDI
Url = relatedLink.IsInternal == false ? relatedLink.Link : null
};
@@ -103,7 +103,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
Database.Update(property);
}
}
}
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Umbraco.Core.Composing;
@@ -19,18 +18,6 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
private readonly PropertyEditorCollection _propertyEditors;
private readonly ILogger _logger;
private static readonly ISet<string> LegacyAliases = new HashSet<string>()
{
Constants.PropertyEditors.Legacy.Aliases.Date,
Constants.PropertyEditors.Legacy.Aliases.Textbox,
Constants.PropertyEditors.Legacy.Aliases.ContentPicker2,
Constants.PropertyEditors.Legacy.Aliases.MediaPicker2,
Constants.PropertyEditors.Legacy.Aliases.MemberPicker2,
Constants.PropertyEditors.Legacy.Aliases.RelatedLinks2,
Constants.PropertyEditors.Legacy.Aliases.TextboxMultiple,
Constants.PropertyEditors.Legacy.Aliases.MultiNodeTreePicker2,
};
public DataTypeMigration(IMigrationContext context, PreValueMigratorCollection preValueMigrators, PropertyEditorCollection propertyEditors, ILogger logger)
: base(context)
{
@@ -83,23 +70,16 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
var newAlias = migrator.GetNewAlias(dataType.EditorAlias);
if (newAlias == null)
{
if (!LegacyAliases.Contains(dataType.EditorAlias))
{
_logger.Warn<DataTypeMigration>(
"Skipping validation of configuration for data type {NodeId} : {EditorAlias}."
+ " Please ensure that the configuration is valid. The site may fail to start and / or load data types and run.",
dataType.NodeId, dataType.EditorAlias);
}
_logger.Warn<DataTypeMigration>("Skipping validation of configuration for data type {NodeId} : {EditorAlias}."
+ " Please ensure that the configuration is valid. The site may fail to start and / or load data types and run.",
dataType.NodeId, dataType.EditorAlias);
}
else if (!_propertyEditors.TryGet(newAlias, out var propertyEditor))
{
if (!LegacyAliases.Contains(newAlias))
{
_logger.Warn<DataTypeMigration>("Skipping validation of configuration for data type {NodeId} : {NewEditorAlias} (was: {EditorAlias})"
+ " because no property editor with that alias was found."
+ " Please ensure that the configuration is valid. The site may fail to start and / or load data types and run.",
dataType.NodeId, newAlias, dataType.EditorAlias);
}
_logger.Warn<DataTypeMigration>("Skipping validation of configuration for data type {NodeId} : {NewEditorAlias} (was: {EditorAlias})"
+ " because no property editor with that alias was found."
+ " Please ensure that the configuration is valid. The site may fail to start and / or load data types and run.",
dataType.NodeId, newAlias, dataType.EditorAlias);
}
else
{
@@ -3,7 +3,7 @@
class ContentPickerPreValueMigrator : DefaultPreValueMigrator
{
public override bool CanMigrate(string editorAlias)
=> editorAlias == Constants.PropertyEditors.Legacy.Aliases.ContentPicker2;
=> editorAlias == "Umbraco.ContentPicker2";
public override string GetNewAlias(string editorAlias)
=> null;
@@ -1,32 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0.DataTypes
{
class DropDownFlexiblePreValueMigrator : IPreValueMigrator
{
public bool CanMigrate(string editorAlias)
=> editorAlias == "Umbraco.DropDown.Flexible";
public virtual string GetNewAlias(string editorAlias)
=> null;
public object GetConfiguration(int dataTypeId, string editorAlias, Dictionary<string, PreValueDto> preValues)
{
var config = new DropDownFlexibleConfiguration();
foreach (var preValue in preValues.Values)
{
if (preValue.Alias == "multiple")
{
config.Multiple = (preValue.Value == "1");
}
else
{
config.Items.Add(new ValueListConfiguration.ValueListItem { Id = preValue.Id, Value = preValue.Value });
}
}
return config;
}
}
}
@@ -6,15 +6,15 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0.DataTypes
{
private readonly string[] _editors =
{
Constants.PropertyEditors.Legacy.Aliases.MediaPicker2,
Constants.PropertyEditors.Aliases.MediaPicker
"Umbraco.MediaPicker2",
"Umbraco.MediaPicker"
};
public override bool CanMigrate(string editorAlias)
=> _editors.Contains(editorAlias);
public override string GetNewAlias(string editorAlias)
=> Constants.PropertyEditors.Aliases.MediaPicker;
=> "Umbraco.MediaPicker";
// you wish - but MediaPickerConfiguration lives in Umbraco.Web
/*
@@ -2,25 +2,24 @@
namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0.DataTypes
{
[RuntimeLevel(MinLevel = RuntimeLevel.Upgrade, MaxLevel = RuntimeLevel.Upgrade)] // only on upgrades
public class PreValueMigratorComposer : ICoreComposer
{
public void Compose(Composition composition)
[RuntimeLevel(MinLevel = RuntimeLevel.Upgrade, MaxLevel = RuntimeLevel.Upgrade)] // only on upgrades
public class PreValueMigratorComposer : ICoreComposer
{
// do NOT add DefaultPreValueMigrator to this list!
// it will be automatically used if nothing matches
public void Compose(Composition composition)
{
// do NOT add DefaultPreValueMigrator to this list!
// it will be automatically used if nothing matches
composition.WithCollectionBuilder<PreValueMigratorCollectionBuilder>()
.Append<RenamingPreValueMigrator>()
.Append<RichTextPreValueMigrator>()
.Append<UmbracoSliderPreValueMigrator>()
.Append<MediaPickerPreValueMigrator>()
.Append<ContentPickerPreValueMigrator>()
.Append<NestedContentPreValueMigrator>()
.Append<DecimalPreValueMigrator>()
.Append<ListViewPreValueMigrator>()
.Append<DropDownFlexiblePreValueMigrator>()
.Append<ValueListPreValueMigrator>();
composition.WithCollectionBuilder<PreValueMigratorCollectionBuilder>()
.Append<RenamingPreValueMigrator>()
.Append<RichTextPreValueMigrator>()
.Append<UmbracoSliderPreValueMigrator>()
.Append<MediaPickerPreValueMigrator>()
.Append<ContentPickerPreValueMigrator>()
.Append<NestedContentPreValueMigrator>()
.Append<DecimalPreValueMigrator>()
.Append<ListViewPreValueMigrator>()
.Append<ValueListPreValueMigrator>();
}
}
}
}
@@ -9,7 +9,6 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0.DataTypes
private readonly string[] _editors =
{
"Umbraco.RadioButtonList",
"Umbraco.CheckBoxList",
"Umbraco.DropDown",
"Umbraco.DropdownlistPublishingKeys",
"Umbraco.DropDownMultiple",
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
public override void Migrate()
{
var dataTypes = GetDataTypes(Constants.PropertyEditors.Legacy.Aliases.Date);
var dataTypes = GetDataTypes("Umbraco.Date");
foreach (var dataType in dataTypes)
{
@@ -25,14 +25,6 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
{
config = (DateTimeConfiguration) new CustomDateTimeConfigurationEditor().FromDatabase(
dataType.Configuration);
// If the Umbraco.Date type is the default from V7 and it has never been updated, then the
// configuration is empty, and the format stuff is handled by in JS by moment.js. - We can't do that
// after the migration, so we force the format to the default from V7.
if (string.IsNullOrEmpty(dataType.Configuration))
{
config.Format = "YYYY-MM-DD";
};
}
catch (Exception ex)
{
@@ -12,12 +12,12 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
public override void Migrate()
{
RenameDataType(Constants.PropertyEditors.Legacy.Aliases.ContentPicker2, Constants.PropertyEditors.Aliases.ContentPicker);
RenameDataType(Constants.PropertyEditors.Legacy.Aliases.MediaPicker2, Constants.PropertyEditors.Aliases.MediaPicker);
RenameDataType(Constants.PropertyEditors.Legacy.Aliases.MemberPicker2, Constants.PropertyEditors.Aliases.MemberPicker);
RenameDataType(Constants.PropertyEditors.Legacy.Aliases.MultiNodeTreePicker2, Constants.PropertyEditors.Aliases.MultiNodeTreePicker);
RenameDataType(Constants.PropertyEditors.Legacy.Aliases.TextboxMultiple, Constants.PropertyEditors.Aliases.TextArea, false);
RenameDataType(Constants.PropertyEditors.Legacy.Aliases.Textbox, Constants.PropertyEditors.Aliases.TextBox, false);
RenameDataType(Constants.PropertyEditors.Aliases.ContentPicker + "2", Constants.PropertyEditors.Aliases.ContentPicker);
RenameDataType(Constants.PropertyEditors.Aliases.MediaPicker + "2", Constants.PropertyEditors.Aliases.MediaPicker);
RenameDataType(Constants.PropertyEditors.Aliases.MemberPicker + "2", Constants.PropertyEditors.Aliases.MemberPicker);
RenameDataType(Constants.PropertyEditors.Aliases.MultiNodeTreePicker + "2", Constants.PropertyEditors.Aliases.MultiNodeTreePicker);
RenameDataType("Umbraco.TextboxMultiple", Constants.PropertyEditors.Aliases.TextArea, false);
RenameDataType("Umbraco.Textbox", Constants.PropertyEditors.Aliases.TextBox, false);
}
private void RenameDataType(string fromAlias, string toAlias, bool checkCollision = true)
@@ -30,20 +30,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
.Where<DataTypeDto>(x => x.EditorAlias == toAlias));
if (oldCount > 0)
{
// If we throw it means that the upgrade will exit and cannot continue.
// This will occur if a v7 site has the old "Obsolete" property editors that are already named with the `toAlias` name.
// TODO: We should have an additional upgrade step when going from 7 -> 8 like we did with 6 -> 7 that shows a compatibility report,
// this would include this check and then we can provide users with information on what they should do (i.e. before upgrading to v8 they will
// need to migrate these old obsolete editors to non-obsolete editors)
throw new InvalidOperationException(
$"Cannot rename datatype alias \"{fromAlias}\" to \"{toAlias}\" because the target alias is already used." +
$"This is generally because when upgrading from a v7 to v8 site, the v7 site contains Data Types that reference old and already Obsolete " +
$"Property Editors. Before upgrading to v8, any Data Types using property editors that are named with the prefix '(Obsolete)' must be migrated " +
$"to the non-obsolete v7 property editors of the same type.");
}
throw new InvalidOperationException($"Cannot rename datatype alias \"{fromAlias}\" to \"{toAlias}\" because the target alias is already used.");
}
Database.Execute(Sql()
@@ -14,18 +14,11 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
public override void Migrate()
{
//Get anything currently scheduled
var releaseSql = new Sql()
.Select("nodeId", "releaseDate")
var scheduleSql = new Sql()
.Select("nodeId", "releaseDate", "expireDate")
.From("umbracoDocument")
.Where("releaseDate IS NOT NULL");
var releases = Database.Dictionary<int, DateTime> (releaseSql);
var expireSql = new Sql()
.Select("nodeId", "expireDate")
.From("umbracoDocument")
.Where("expireDate IS NOT NULL");
var expires = Database.Dictionary<int, DateTime>(expireSql);
.Where("releaseDate IS NOT NULL OR expireDate IS NOT NULL");
var schedules = Database.Dictionary<int, (DateTime? releaseDate, DateTime? expireDate)> (scheduleSql);
//drop old cols
Delete.Column("releaseDate").FromTable("umbracoDocument").Do();
@@ -34,25 +27,20 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0
Create.Table<ContentScheduleDto>(true).Do();
//migrate the schedule
foreach(var s in releases)
foreach(var s in schedules)
{
var date = s.Value;
var date = s.Value.releaseDate;
var action = ContentScheduleAction.Release.ToString();
if (!date.HasValue)
{
date = s.Value.expireDate;
action = ContentScheduleAction.Expire.ToString();
}
Insert.IntoTable(ContentScheduleDto.TableName)
.Row(new { id = Guid.NewGuid(), nodeId = s.Key, date = date, action = action })
.Row(new { nodeId = s.Key, date = date.Value, action = action })
.Do();
}
foreach (var s in expires)
{
var date = s.Value;
var action = ContentScheduleAction.Expire.ToString();
Insert.IntoTable(ContentScheduleDto.TableName)
.Row(new { id = Guid.NewGuid(), nodeId = s.Key, date = date, action = action })
.Do();
}
}
}
}
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
@@ -37,7 +36,6 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_1_0
var properties = Database.Fetch<PropertyDataDto>(sqlPropertyData);
var exceptions = new List<Exception>();
foreach (var property in properties)
{
var value = property.TextValue;
@@ -45,34 +43,19 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_1_0
if (property.PropertyTypeDto.DataTypeDto.EditorAlias == Constants.PropertyEditors.Aliases.Grid)
{
try
{
var obj = JsonConvert.DeserializeObject<JObject>(value);
var allControls = obj.SelectTokens("$.sections..rows..areas..controls");
var obj = JsonConvert.DeserializeObject<JObject>(value);
var allControls = obj.SelectTokens("$.sections..rows..areas..controls");
foreach (var control in allControls.SelectMany(c => c))
foreach (var control in allControls.SelectMany(c => c))
{
var controlValue = control["value"];
if (controlValue.Type == JTokenType.String)
{
var controlValue = control["value"];
if (controlValue.Type == JTokenType.String)
{
control["value"] = UpdateMediaUrls(mediaLinkPattern, controlValue.Value<string>());
}
control["value"] = UpdateMediaUrls(mediaLinkPattern, controlValue.Value<string>());
}
property.TextValue = JsonConvert.SerializeObject(obj);
}
catch (JsonException e)
{
exceptions.Add(new InvalidOperationException(
"Cannot deserialize the value as json. This can be because the property editor " +
"type is changed from another type into a grid. Old versions of the value in this " +
"property can have the structure from the old property editor type. This needs to be " +
"changed manually before updating the database.\n" +
$"Property info: Id = {property.Id}, LanguageId = {property.LanguageId}, VersionId = {property.VersionId}, Value = {property.Value}"
, e));
continue;
}
property.TextValue = JsonConvert.SerializeObject(obj);
}
else
{
@@ -82,12 +65,6 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_1_0
Database.Update(property);
}
if (exceptions.Any())
{
throw new AggregateException("One or more errors related to unexpected data in grid values occurred.", exceptions);
}
Context.AddPostMigration<RebuildPublishedSnapshot>();
}
@@ -35,58 +35,5 @@ namespace Umbraco.Core.Models
throw new InvalidCastException($"Cannot cast dataType configuration, of type {configuration.GetType().Name}, to {typeof(T).Name}.");
}
private static readonly ISet<Guid> IdsOfBuildInDataTypes = new HashSet<Guid>()
{
Constants.DataTypes.Guids.ContentPickerGuid,
Constants.DataTypes.Guids.MemberPickerGuid,
Constants.DataTypes.Guids.MediaPickerGuid,
Constants.DataTypes.Guids.MultipleMediaPickerGuid,
Constants.DataTypes.Guids.RelatedLinksGuid,
Constants.DataTypes.Guids.MemberGuid,
Constants.DataTypes.Guids.ImageCropperGuid,
Constants.DataTypes.Guids.TagsGuid,
Constants.DataTypes.Guids.ListViewContentGuid,
Constants.DataTypes.Guids.ListViewMediaGuid,
Constants.DataTypes.Guids.ListViewMembersGuid,
Constants.DataTypes.Guids.DatePickerWithTimeGuid,
Constants.DataTypes.Guids.ApprovedColorGuid,
Constants.DataTypes.Guids.DropdownMultipleGuid,
Constants.DataTypes.Guids.RadioboxGuid,
Constants.DataTypes.Guids.DatePickerGuid,
Constants.DataTypes.Guids.DropdownGuid,
Constants.DataTypes.Guids.CheckboxListGuid,
Constants.DataTypes.Guids.CheckboxGuid,
Constants.DataTypes.Guids.NumericGuid,
Constants.DataTypes.Guids.RichtextEditorGuid,
Constants.DataTypes.Guids.TextstringGuid,
Constants.DataTypes.Guids.TextareaGuid,
Constants.DataTypes.Guids.UploadGuid,
Constants.DataTypes.Guids.LabelStringGuid,
Constants.DataTypes.Guids.LabelDecimalGuid,
Constants.DataTypes.Guids.LabelDateTimeGuid,
Constants.DataTypes.Guids.LabelBigIntGuid,
Constants.DataTypes.Guids.LabelTimeGuid,
Constants.DataTypes.Guids.LabelDateTimeGuid,
};
/// <summary>
/// Returns true if this date type is build-in/default.
/// </summary>
/// <param name="dataType">The data type definition.</param>
/// <returns></returns>
internal static bool IsBuildInDataType(this IDataType dataType)
{
return IsBuildInDataType(dataType.Key);
}
/// <summary>
/// Returns true if this date type is build-in/default.
/// </summary>
internal static bool IsBuildInDataType(Guid key)
{
return IdsOfBuildInDataTypes.Contains(key);
}
}
}
+31 -1
View File
@@ -81,7 +81,37 @@ namespace Umbraco.Core.Models.Entities
_key = Guid.Empty;
_hasIdentity = false;
}
/// <summary>
/// Updates the entity when it is being saved for the first time.
/// </summary>
internal virtual void AddingEntity()
{
var now = DateTime.Now;
// set the create and update dates, if not already set
if (IsPropertyDirty("CreateDate") == false || _createDate == default)
CreateDate = now;
if (IsPropertyDirty("UpdateDate") == false || _updateDate == default)
UpdateDate = now;
}
/// <summary>
/// Updates the entity when it is being saved.
/// </summary>
internal virtual void UpdatingEntity()
{
var now = DateTime.Now;
// just in case
if (_createDate == default)
CreateDate = now;
// set the update date if not already set
if (IsPropertyDirty("UpdateDate") == false || _updateDate == default)
UpdateDate = now;
}
public virtual bool Equals(EntityBase other)
{
return other != null && (ReferenceEquals(this, other) || SameIdentityAs(other));
@@ -1,46 +0,0 @@
using System;
namespace Umbraco.Core.Models.Entities
{
internal static class EntityExtensions
{
/// <summary>
/// Updates the entity when it is being saved.
/// </summary>
internal static void UpdatingEntity(this IEntity entity)
{
var now = DateTime.Now;
// just in case
if (entity.CreateDate == default)
{
entity.CreateDate = now;
}
// set the update date if not already set
if (entity.UpdateDate == default || (entity is ICanBeDirty canBeDirty && canBeDirty.IsPropertyDirty("UpdateDate") == false))
{
entity.UpdateDate = now;
}
}
/// <summary>
/// Updates the entity when it is being saved for the first time.
/// </summary>
internal static void AddingEntity(this IEntity entity)
{
var now = DateTime.Now;
var canBeDirty = entity as ICanBeDirty;
// set the create and update dates, if not already set
if (entity.CreateDate == default || canBeDirty?.IsPropertyDirty("CreateDate") == false)
{
entity.CreateDate = now;
}
if (entity.UpdateDate == default || canBeDirty?.IsPropertyDirty("UpdateDate") == false)
{
entity.UpdateDate = now;
}
}
}
}
+13
View File
@@ -478,6 +478,19 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _providerUserKey, nameof(ProviderUserKey));
}
/// <summary>
/// Method to call when Entity is being saved
/// </summary>
/// <remarks>Created date is set and a Unique key is assigned</remarks>
internal override void AddingEntity()
{
base.AddingEntity();
if (ProviderUserKey == null)
ProviderUserKey = Key;
}
/* Internal experiment - only used for mapping queries.
* Adding these to have first level properties instead of the Properties collection.
*/
+1 -9
View File
@@ -21,7 +21,6 @@ namespace Umbraco.Core.Models
private string _alias;
private string _description;
private int _dataTypeId;
private Guid _dataTypeKey;
private Lazy<int> _propertyGroupId;
private string _propertyEditorAlias;
private ValueStorageType _valueStorageType;
@@ -114,7 +113,7 @@ namespace Umbraco.Core.Models
/// Gets of sets the alias of the property type.
/// </summary>
[DataMember]
public virtual string Alias
public string Alias
{
get => _alias;
set => SetPropertyValueAndDetectChanges(SanitizeAlias(value), ref _alias, nameof(Alias));
@@ -140,13 +139,6 @@ namespace Umbraco.Core.Models
set => SetPropertyValueAndDetectChanges(value, ref _dataTypeId, nameof(DataTypeId));
}
[DataMember]
public Guid DataTypeKey
{
get => _dataTypeKey;
set => SetPropertyValueAndDetectChanges(value, ref _dataTypeKey, nameof(DataTypeKey));
}
/// <summary>
/// Gets or sets the alias of the property editor for this property type.
/// </summary>
@@ -13,10 +13,6 @@
/// <summary>
/// Refreshes the factory.
/// </summary>
/// <remarks>
/// <para>This will typically re-compiled models/classes into a new DLL that are used to populate the cache.</para>
/// <para>This is called prior to refreshing the cache.</para>
/// </remarks>
void Refresh();
}
}
+13
View File
@@ -193,6 +193,19 @@ namespace Umbraco.Core.Models
return ContentPermissionsHelper.HasPathAccess(entity.Path, user.CalculateMediaStartNodeIds(entityService), Constants.System.RecycleBinMedia);
}
internal static bool IsInBranchOfStartNode(this IUser user, IUmbracoEntity entity, IEntityService entityService, int recycleBinId, out bool hasPathAccess)
{
switch (recycleBinId)
{
case Constants.System.RecycleBinMedia:
return ContentPermissionsHelper.IsInBranchOfStartNode(entity.Path, user.CalculateMediaStartNodeIds(entityService), user.GetMediaStartNodePaths(entityService), out hasPathAccess);
case Constants.System.RecycleBinContent:
return ContentPermissionsHelper.IsInBranchOfStartNode(entity.Path, user.CalculateContentStartNodeIds(entityService), user.GetContentStartNodePaths(entityService), out hasPathAccess);
default:
throw new NotSupportedException("Path access is only determined on content or media");
}
}
/// <summary>
/// Determines whether this user has access to view sensitive data
/// </summary>
@@ -54,7 +54,6 @@ namespace Umbraco.Core.Persistence.Factories
propertyType.Alias = typeDto.Alias;
propertyType.DataTypeId = typeDto.DataTypeId;
propertyType.DataTypeKey = typeDto.DataTypeDto.NodeDto.UniqueId;
propertyType.Description = typeDto.Description;
propertyType.Id = typeDto.Id;
propertyType.Key = typeDto.UniqueId;
@@ -18,8 +18,7 @@ namespace Umbraco.Core.Persistence.Mappers
DefineMap<AuditItem, LogDto>(nameof(AuditItem.Id), nameof(LogDto.NodeId));
DefineMap<AuditItem, LogDto>(nameof(AuditItem.CreateDate), nameof(LogDto.Datestamp));
DefineMap<AuditItem, LogDto>(nameof(AuditItem.UserId), nameof(LogDto.UserId));
// we cannot map that one - because AuditType is an enum but Header is a string
//DefineMap<AuditItem, LogDto>(nameof(AuditItem.AuditType), nameof(LogDto.Header));
DefineMap<AuditItem, LogDto>(nameof(AuditItem.AuditType), nameof(LogDto.Header));
DefineMap<AuditItem, LogDto>(nameof(AuditItem.Comment), nameof(LogDto.Comment));
}
}
@@ -85,17 +85,6 @@ namespace Umbraco.Core.Persistence.Querying
// I'm just unsure right now due to time constraints how to make it correct. It won't matter right now and has been working already with this bug but I've
// only just discovered what it is actually doing.
// TODO
// in most cases we want to convert the value to a plain object,
// but for in some rare cases, we may want to do it differently,
// for instance a Models.AuditType (an enum) may in some cases
// need to be converted to its string value.
// but - we cannot have specific code here, really - and how would
// we configure this? is it even possible?
/*
var toString = typeof(object).GetMethod("ToString");
var member = Expression.Call(m, toString);
*/
var member = Expression.Convert(m, typeof(object));
var lambda = Expression.Lambda<Func<object>>(member);
var getter = lambda.Compile();
@@ -33,7 +33,5 @@ namespace Umbraco.Core.Persistence.Repositories
Direction orderDirection,
AuditType[] auditTypeFilter,
IQuery<IAuditItem> customFilter);
IEnumerable<IAuditItem> Get(AuditType type, IQuery<IAuditItem> query);
}
}
@@ -100,7 +100,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
/// <inheritdoc />
protected override void PersistNewItem(IAuditEntry entity)
{
entity.AddingEntity();
((EntityBase) entity).AddingEntity();
var dto = AuditEntryFactory.BuildDto(entity);
Database.Insert(dto);
@@ -74,18 +74,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
return dtos.Select(x => new AuditItem(x.NodeId, Enum<AuditType>.Parse(x.Header), x.UserId ?? Constants.Security.UnknownUserId, x.EntityType, x.Comment, x.Parameters)).ToList();
}
public IEnumerable<IAuditItem> Get(AuditType type, IQuery<IAuditItem> query)
{
var sqlClause = GetBaseQuery(false)
.Where<LogDto>(x => x.Header == type.ToString());
var translator = new SqlTranslator<IAuditItem>(sqlClause, query);
var sql = translator.Translate();
var dtos = Database.Fetch<LogDto>(sql);
return dtos.Select(x => new AuditItem(x.NodeId, Enum<AuditType>.Parse(x.Header), x.UserId ?? Constants.Security.UnknownUserId, x.EntityType, x.Comment, x.Parameters)).ToList();
}
protected override Sql<ISqlContext> GetBaseQuery(bool isCount)
{
var sql = SqlContext.Sql();
@@ -69,7 +69,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
/// <inheritdoc />
protected override void PersistNewItem(IConsent entity)
{
entity.AddingEntity();
((EntityBase) entity).AddingEntity();
var dto = ConsentFactory.BuildDto(entity);
Database.Insert(dto);
@@ -80,7 +80,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
/// <inheritdoc />
protected override void PersistUpdatedItem(IConsent entity)
{
entity.UpdatingEntity();
((EntityBase) entity).UpdatingEntity();
var dto = ConsentFactory.BuildDto(entity);
Database.Update(dto);
@@ -7,7 +7,6 @@ using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Scoping;
using static Umbraco.Core.Persistence.NPocoSqlExtensions.Statics;
namespace Umbraco.Core.Persistence.Repositories.Implement
{
@@ -189,11 +188,10 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
var groupDtos = Database.Fetch<PropertyTypeGroupDto>(sql1);
var sql2 = Sql()
.Select<PropertyTypeDto>(r => r.Select(x => x.DataTypeDto, r1 => r1.Select(x => x.NodeDto)))
.Select<PropertyTypeDto>(r => r.Select(x => x.DataTypeDto))
.AndSelect<MemberPropertyTypeDto>()
.From<PropertyTypeDto>()
.InnerJoin<DataTypeDto>().On<PropertyTypeDto, DataTypeDto>((pt, dt) => pt.DataTypeId == dt.NodeId)
.InnerJoin<NodeDto>().On<DataTypeDto, NodeDto>((dt, n) => dt.NodeId == n.NodeId)
.InnerJoin<ContentTypeDto>().On<PropertyTypeDto, ContentTypeDto>((pt, ct) => pt.ContentTypeId == ct.NodeId)
.LeftJoin<PropertyTypeGroupDto>().On<PropertyTypeDto, PropertyTypeGroupDto>((pt, ptg) => pt.PropertyTypeGroupId == ptg.Id)
.LeftJoin<MemberPropertyTypeDto>().On<PropertyTypeDto, MemberPropertyTypeDto>((pt, mpt) => pt.Id == mpt.PropertyTypeId)
@@ -292,7 +290,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
{
Description = dto.Description,
DataTypeId = dto.DataTypeId,
DataTypeKey = dto.DataTypeDto.NodeDto.UniqueId,
Id = dto.Id,
Key = dto.UniqueId,
Mandatory = dto.Mandatory,
@@ -5,7 +5,6 @@ using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.SqlSyntax;
@@ -231,7 +230,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
throw ex;
}
entity.AddingEntity();
((ContentType)entity).AddingEntity();
PersistNewBaseContentType(entity);
PersistTemplates(entity, false);
@@ -271,7 +270,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
ValidateAlias(entity);
//Updates Modified date
entity.UpdatingEntity();
((ContentType)entity).UpdatingEntity();
//Look up parent to get and set the correct Path if ParentId has changed
if (entity.IsPropertyDirty("ParentId"))
@@ -1013,9 +1013,8 @@ AND umbracoNode.id <> @id",
if (propertyType.PropertyEditorAlias.IsNullOrWhiteSpace() == false)
{
var sql = Sql()
.Select<DataTypeDto>(dt => dt.Select(x => x.NodeDto))
.SelectAll()
.From<DataTypeDto>()
.InnerJoin<NodeDto>().On<DataTypeDto, NodeDto>((dt, n) => dt.NodeId == n.NodeId)
.Where("propertyEditorAlias = @propertyEditorAlias", new { propertyEditorAlias = propertyType.PropertyEditorAlias })
.OrderBy<DataTypeDto>(typeDto => typeDto.NodeId);
var datatype = Database.FirstOrDefault<DataTypeDto>(sql);
@@ -1023,7 +1022,6 @@ AND umbracoNode.id <> @id",
if (datatype != null)
{
propertyType.DataTypeId = datatype.NodeId;
propertyType.DataTypeKey = datatype.NodeDto.UniqueId;
}
else
{
@@ -9,7 +9,6 @@ using Umbraco.Core.Events;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.Querying;
@@ -107,7 +106,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistNewItem(IDataType entity)
{
entity.AddingEntity();
((DataType)entity).AddingEntity();
//ensure a datatype has a unique name before creating it
entity.Name = EnsureUniqueNodeName(entity.Name);
@@ -175,7 +174,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
}
//Updates Modified date
entity.UpdatingEntity();
((DataType)entity).UpdatingEntity();
//Look up parent to get and set the correct Path if ParentId has changed
if (entity.IsPropertyDirty("ParentId"))
@@ -148,7 +148,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistUpdatedItem(IDictionaryItem entity)
{
entity.UpdatingEntity();
((EntityBase)entity).UpdatingEntity();
foreach (var translation in entity.Translations)
translation.Value = translation.Value.ToValidXmlString();
@@ -6,7 +6,6 @@ using Umbraco.Core.Cache;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Persistence.Factories;
@@ -206,10 +205,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
"DELETE FROM " + Constants.DatabaseSchema.Tables.ContentVersionCultureVariation + " WHERE versionId IN (SELECT id FROM " + Constants.DatabaseSchema.Tables.ContentVersion + " WHERE nodeId = @id)",
"DELETE FROM " + Constants.DatabaseSchema.Tables.ContentVersion + " WHERE nodeId = @id",
"DELETE FROM " + Constants.DatabaseSchema.Tables.Content + " WHERE nodeId = @id",
"DELETE FROM " + Constants.DatabaseSchema.Tables.AccessRule + " WHERE accessId IN (SELECT id FROM " + Constants.DatabaseSchema.Tables.Access + " WHERE nodeId = @id OR loginNodeId = @id OR noAccessNodeId = @id)",
"DELETE FROM " + Constants.DatabaseSchema.Tables.Access + " WHERE nodeId = @id",
"DELETE FROM " + Constants.DatabaseSchema.Tables.Access + " WHERE loginNodeId = @id",
"DELETE FROM " + Constants.DatabaseSchema.Tables.Access + " WHERE noAccessNodeId = @id",
"DELETE FROM " + Constants.DatabaseSchema.Tables.Node + " WHERE id = @id"
};
return list;
@@ -264,16 +260,21 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistNewItem(IContent entity)
{
entity.AddingEntity();
// TODO: https://github.com/umbraco/Umbraco-CMS/issues/4234 - sort out IContent vs Content
// however, it's not just so we have access to AddingEntity
// there are tons of things at the end of the methods, that can only work with a true Content
// and basically, the repository requires a Content, not an IContent
var content = (Content)entity;
var publishing = entity.PublishedState == PublishedState.Publishing;
content.AddingEntity();
var publishing = content.PublishedState == PublishedState.Publishing;
// ensure that the default template is assigned
if (entity.TemplateId.HasValue == false)
entity.TemplateId = entity.ContentType.DefaultTemplate?.Id;
// sanitize names
SanitizeNames(entity, publishing);
SanitizeNames(content, publishing);
// ensure that strings don't contain characters that are invalid in xml
// TODO: do we really want to keep doing this here?
@@ -323,11 +324,11 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
contentVersionDto.NodeId = nodeDto.NodeId;
contentVersionDto.Current = !publishing;
Database.Insert(contentVersionDto);
entity.VersionId = contentVersionDto.Id;
content.VersionId = contentVersionDto.Id;
// persist the document version dto
var documentVersionDto = dto.DocumentVersionDto;
documentVersionDto.Id = entity.VersionId;
documentVersionDto.Id = content.VersionId;
if (publishing)
documentVersionDto.Published = true;
Database.Insert(documentVersionDto);
@@ -335,62 +336,62 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
// and again in case we're publishing immediately
if (publishing)
{
entity.PublishedVersionId = entity.VersionId;
content.PublishedVersionId = content.VersionId;
contentVersionDto.Id = 0;
contentVersionDto.Current = true;
contentVersionDto.Text = entity.Name;
contentVersionDto.Text = content.Name;
Database.Insert(contentVersionDto);
entity.VersionId = contentVersionDto.Id;
content.VersionId = contentVersionDto.Id;
documentVersionDto.Id = entity.VersionId;
documentVersionDto.Id = content.VersionId;
documentVersionDto.Published = false;
Database.Insert(documentVersionDto);
}
// persist the property data
var propertyDataDtos = PropertyFactory.BuildDtos(entity.ContentType.Variations, entity.VersionId, entity.PublishedVersionId, entity.Properties, LanguageRepository, out var edited, out var editedCultures);
var propertyDataDtos = PropertyFactory.BuildDtos(content.ContentType.Variations, content.VersionId, content.PublishedVersionId, entity.Properties, LanguageRepository, out var edited, out var editedCultures);
foreach (var propertyDataDto in propertyDataDtos)
Database.Insert(propertyDataDto);
// if !publishing, we may have a new name != current publish name,
// also impacts 'edited'
if (!publishing && entity.PublishName != entity.Name)
if (!publishing && content.PublishName != content.Name)
edited = true;
// persist the document dto
// at that point, when publishing, the entity still has its old Published value
// so we need to explicitly update the dto to persist the correct value
if (entity.PublishedState == PublishedState.Publishing)
if (content.PublishedState == PublishedState.Publishing)
dto.Published = true;
dto.NodeId = nodeDto.NodeId;
entity.Edited = dto.Edited = !dto.Published || edited; // if not published, always edited
content.Edited = dto.Edited = !dto.Published || edited; // if not published, always edited
Database.Insert(dto);
//insert the schedule
PersistContentSchedule(entity, false);
PersistContentSchedule(content, false);
// persist the variations
if (entity.ContentType.VariesByCulture())
if (content.ContentType.VariesByCulture())
{
// bump dates to align cultures to version
if (publishing)
entity.AdjustDates(contentVersionDto.VersionDate);
content.AdjustDates(contentVersionDto.VersionDate);
// names also impact 'edited'
// ReSharper disable once UseDeconstruction
foreach (var cultureInfo in entity.CultureInfos)
if (cultureInfo.Name != entity.GetPublishName(cultureInfo.Culture))
foreach (var cultureInfo in content.CultureInfos)
if (cultureInfo.Name != content.GetPublishName(cultureInfo.Culture))
(editedCultures ?? (editedCultures = new HashSet<string>(StringComparer.OrdinalIgnoreCase))).Add(cultureInfo.Culture);
// insert content variations
Database.BulkInsertRecords(GetContentVariationDtos(entity, publishing));
Database.BulkInsertRecords(GetContentVariationDtos(content, publishing));
// insert document variations
Database.BulkInsertRecords(GetDocumentVariationDtos(entity, publishing, editedCultures));
Database.BulkInsertRecords(GetDocumentVariationDtos(content, publishing, editedCultures));
}
// refresh content
entity.SetCultureEdited(editedCultures);
content.SetCultureEdited(editedCultures);
// trigger here, before we reset Published etc
OnUowRefreshedEntity(new ScopedEntityEventArgs(AmbientScope, entity));
@@ -398,23 +399,23 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
// flip the entity's published property
// this also flips its published state
// note: what depends on variations (eg PublishNames) is managed directly by the content
if (entity.PublishedState == PublishedState.Publishing)
if (content.PublishedState == PublishedState.Publishing)
{
entity.Published = true;
entity.PublishTemplateId = entity.TemplateId;
entity.PublisherId = entity.WriterId;
entity.PublishName = entity.Name;
entity.PublishDate = entity.UpdateDate;
content.Published = true;
content.PublishTemplateId = content.TemplateId;
content.PublisherId = content.WriterId;
content.PublishName = content.Name;
content.PublishDate = content.UpdateDate;
SetEntityTags(entity, _tagRepository);
}
else if (entity.PublishedState == PublishedState.Unpublishing)
else if (content.PublishedState == PublishedState.Unpublishing)
{
entity.Published = false;
entity.PublishTemplateId = null;
entity.PublisherId = null;
entity.PublishName = null;
entity.PublishDate = null;
content.Published = false;
content.PublishTemplateId = null;
content.PublisherId = null;
content.PublishName = null;
content.PublishDate = null;
ClearEntityTags(entity, _tagRepository);
}
@@ -436,33 +437,34 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistUpdatedItem(IContent entity)
{
var entityBase = entity as EntityBase;
var isEntityDirty = entityBase != null && entityBase.IsDirty();
// however, it's not just so we have access to AddingEntity
// there are tons of things at the end of the methods, that can only work with a true Content
// and basically, the repository requires a Content, not an IContent
var content = (Content)entity;
// check if we need to make any database changes at all
if ((entity.PublishedState == PublishedState.Published || entity.PublishedState == PublishedState.Unpublished)
&& !isEntityDirty && !entity.IsAnyUserPropertyDirty())
if ((content.PublishedState == PublishedState.Published || content.PublishedState == PublishedState.Unpublished)
&& !content.IsEntityDirty() && !content.IsAnyUserPropertyDirty())
return; // no change to save, do nothing, don't even update dates
// whatever we do, we must check that we are saving the current version
var version = Database.Fetch<ContentVersionDto>(SqlContext.Sql().Select<ContentVersionDto>().From<ContentVersionDto>().Where<ContentVersionDto>(x => x.Id == entity.VersionId)).FirstOrDefault();
var version = Database.Fetch<ContentVersionDto>(SqlContext.Sql().Select<ContentVersionDto>().From<ContentVersionDto>().Where<ContentVersionDto>(x => x.Id == content.VersionId)).FirstOrDefault();
if (version == null || !version.Current)
throw new InvalidOperationException("Cannot save a non-current version.");
// update
entity.UpdatingEntity();
var publishing = entity.PublishedState == PublishedState.Publishing;
content.UpdatingEntity();
var publishing = content.PublishedState == PublishedState.Publishing;
// check if we need to create a new version
if (publishing && entity.PublishedVersionId > 0)
if (publishing && content.PublishedVersionId > 0)
{
// published version is not published anymore
Database.Execute(Sql().Update<DocumentVersionDto>(u => u.Set(x => x.Published, false)).Where<DocumentVersionDto>(x => x.Id == entity.PublishedVersionId));
Database.Execute(Sql().Update<DocumentVersionDto>(u => u.Set(x => x.Published, false)).Where<DocumentVersionDto>(x => x.Id == content.PublishedVersionId));
}
// sanitize names
SanitizeNames(entity, publishing);
SanitizeNames(content, publishing);
// ensure that strings don't contain characters that are invalid in xml
// TODO: do we really want to keep doing this here?
@@ -502,13 +504,13 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
// and, if publishing, insert new content & document version dtos
if (publishing)
{
entity.PublishedVersionId = entity.VersionId;
content.PublishedVersionId = content.VersionId;
contentVersionDto.Id = 0; // want a new id
contentVersionDto.Current = true; // current version
contentVersionDto.Text = entity.Name;
contentVersionDto.Text = content.Name;
Database.Insert(contentVersionDto);
entity.VersionId = documentVersionDto.Id = contentVersionDto.Id; // get the new id
content.VersionId = documentVersionDto.Id = contentVersionDto.Id; // get the new id
documentVersionDto.Published = false; // non-published version
Database.Insert(documentVersionDto);
@@ -516,31 +518,31 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
// replace the property data (rather than updating)
// only need to delete for the version that existed, the new version (if any) has no property data yet
var versionToDelete = publishing ? entity.PublishedVersionId : entity.VersionId;
var versionToDelete = publishing ? content.PublishedVersionId : content.VersionId;
var deletePropertyDataSql = Sql().Delete<PropertyDataDto>().Where<PropertyDataDto>(x => x.VersionId == versionToDelete);
Database.Execute(deletePropertyDataSql);
// insert property data
var propertyDataDtos = PropertyFactory.BuildDtos(entity.ContentType.Variations, entity.VersionId, publishing ? entity.PublishedVersionId : 0,
var propertyDataDtos = PropertyFactory.BuildDtos(content.ContentType.Variations, content.VersionId, publishing ? content.PublishedVersionId : 0,
entity.Properties, LanguageRepository, out var edited, out var editedCultures);
foreach (var propertyDataDto in propertyDataDtos)
Database.Insert(propertyDataDto);
// if !publishing, we may have a new name != current publish name,
// also impacts 'edited'
if (!publishing && entity.PublishName != entity.Name)
if (!publishing && content.PublishName != content.Name)
edited = true;
if (entity.ContentType.VariesByCulture())
if (content.ContentType.VariesByCulture())
{
// bump dates to align cultures to version
if (publishing)
entity.AdjustDates(contentVersionDto.VersionDate);
content.AdjustDates(contentVersionDto.VersionDate);
// names also impact 'edited'
// ReSharper disable once UseDeconstruction
foreach (var cultureInfo in entity.CultureInfos)
if (cultureInfo.Name != entity.GetPublishName(cultureInfo.Culture))
foreach (var cultureInfo in content.CultureInfos)
if (cultureInfo.Name != content.GetPublishName(cultureInfo.Culture))
{
edited = true;
(editedCultures ?? (editedCultures = new HashSet<string>(StringComparer.OrdinalIgnoreCase))).Add(cultureInfo.Culture);
@@ -558,7 +560,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
Database.Execute(deleteContentVariations);
// replace the document version variations (rather than updating)
var deleteDocumentVariations = Sql().Delete<DocumentCultureVariationDto>().Where<DocumentCultureVariationDto>(x => x.NodeId == entity.Id);
var deleteDocumentVariations = Sql().Delete<DocumentCultureVariationDto>().Where<DocumentCultureVariationDto>(x => x.NodeId == content.Id);
Database.Execute(deleteDocumentVariations);
// TODO: NPoco InsertBulk issue?
@@ -568,32 +570,32 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
// (same in PersistNewItem above)
// insert content variations
Database.BulkInsertRecords(GetContentVariationDtos(entity, publishing));
Database.BulkInsertRecords(GetContentVariationDtos(content, publishing));
// insert document variations
Database.BulkInsertRecords(GetDocumentVariationDtos(entity, publishing, editedCultures));
Database.BulkInsertRecords(GetDocumentVariationDtos(content, publishing, editedCultures));
}
// refresh content
entity.SetCultureEdited(editedCultures);
content.SetCultureEdited(editedCultures);
// update the document dto
// at that point, when un/publishing, the entity still has its old Published value
// so we need to explicitly update the dto to persist the correct value
if (entity.PublishedState == PublishedState.Publishing)
if (content.PublishedState == PublishedState.Publishing)
dto.Published = true;
else if (entity.PublishedState == PublishedState.Unpublishing)
else if (content.PublishedState == PublishedState.Unpublishing)
dto.Published = false;
entity.Edited = dto.Edited = !dto.Published || edited; // if not published, always edited
content.Edited = dto.Edited = !dto.Published || edited; // if not published, always edited
Database.Update(dto);
//update the schedule
if (entity.IsPropertyDirty("ContentSchedule"))
PersistContentSchedule(entity, true);
if (content.IsPropertyDirty("ContentSchedule"))
PersistContentSchedule(content, true);
// if entity is publishing, update tags, else leave tags there
// means that implicitly unpublished, or trashed, entities *still* have tags in db
if (entity.PublishedState == PublishedState.Publishing)
if (content.PublishedState == PublishedState.Publishing)
SetEntityTags(entity, _tagRepository);
// trigger here, before we reset Published etc
@@ -601,23 +603,23 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
// flip the entity's published property
// this also flips its published state
if (entity.PublishedState == PublishedState.Publishing)
if (content.PublishedState == PublishedState.Publishing)
{
entity.Published = true;
entity.PublishTemplateId = entity.TemplateId;
entity.PublisherId = entity.WriterId;
entity.PublishName = entity.Name;
entity.PublishDate = entity.UpdateDate;
content.Published = true;
content.PublishTemplateId = content.TemplateId;
content.PublisherId = content.WriterId;
content.PublishName = content.Name;
content.PublishDate = content.UpdateDate;
SetEntityTags(entity, _tagRepository);
}
else if (entity.PublishedState == PublishedState.Unpublishing)
else if (content.PublishedState == PublishedState.Unpublishing)
{
entity.Published = false;
entity.PublishTemplateId = null;
entity.PublisherId = null;
entity.PublishName = null;
entity.PublishDate = null;
content.Published = false;
content.PublishTemplateId = null;
content.PublisherId = null;
content.PublishName = null;
content.PublishDate = null;
ClearEntityTags(entity, _tagRepository);
}
@@ -1333,7 +1335,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
#region Utilities
private void SanitizeNames(IContent content, bool publishing)
private void SanitizeNames(Content content, bool publishing)
{
// a content item *must* have an invariant name, and invariant published name
// else we just cannot write the invariant rows (node, content version...) to the database
@@ -1398,7 +1400,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
x.NodeId != SqlTemplate.Arg<int>("id"))
.OrderBy<ContentVersionCultureVariationDto>(x => x.LanguageId));
private void EnsureVariantNamesAreUnique(IContent content, bool publishing)
private void EnsureVariantNamesAreUnique(Content content, bool publishing)
{
if (!EnsureUniqueNaming || !content.ContentType.VariesByCulture() || content.CultureInfos.Count == 0) return;
@@ -6,7 +6,6 @@ using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Scoping;
@@ -102,7 +101,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
if (languageExists == 0) throw new NullReferenceException("No language exists with id " + entity.LanguageId.Value);
}
entity.AddingEntity();
((UmbracoDomain)entity).AddingEntity();
var factory = new DomainModelFactory();
var dto = factory.BuildDto(entity);
@@ -121,7 +120,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistUpdatedItem(IDomain entity)
{
entity.UpdatingEntity();
((UmbracoDomain)entity).UpdatingEntity();
var exists = Database.ExecuteScalar<int>("SELECT COUNT(*) FROM umbracoDomain WHERE domainName = @domainName AND umbracoDomain.id <> @id",
new { domainName = entity.DomainName, id = entity.Id });
@@ -139,7 +139,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistNewItem(IIdentityUserLogin entity)
{
entity.AddingEntity();
((EntityBase)entity).AddingEntity();
var dto = ExternalLoginFactory.BuildDto(entity);
@@ -151,7 +151,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistUpdatedItem(IIdentityUserLogin entity)
{
entity.UpdatingEntity();
((EntityBase)entity).UpdatingEntity();
var dto = ExternalLoginFactory.BuildDto(entity);
@@ -129,7 +129,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
if (entity.IsoCode.IsNullOrWhiteSpace() || entity.CultureName.IsNullOrWhiteSpace())
throw new InvalidOperationException("Cannot save a language without an ISO code and a culture name.");
entity.AddingEntity();
((EntityBase) entity).AddingEntity();
// deal with entity becoming the new default entity
if (entity.IsDefault)
@@ -156,7 +156,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
if (entity.IsoCode.IsNullOrWhiteSpace() || entity.CultureName.IsNullOrWhiteSpace())
throw new InvalidOperationException("Cannot save a language without an ISO code and a culture name.");
entity.UpdatingEntity();
((EntityBase) entity).UpdatingEntity();
if (entity.IsDefault)
{
@@ -132,7 +132,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistNewItem(IMacro entity)
{
entity.AddingEntity();
((EntityBase)entity).AddingEntity();
var dto = MacroFactory.BuildDto(entity);
@@ -152,7 +152,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistUpdatedItem(IMacro entity)
{
entity.UpdatingEntity();
((EntityBase)entity).UpdatingEntity();
;
var dto = MacroFactory.BuildDto(entity);
@@ -8,7 +8,6 @@ using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.Querying;
@@ -218,7 +217,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistNewItem(IMedia entity)
{
var media = (Models.Media) entity;
entity.AddingEntity();
media.AddingEntity();
// ensure unique name on the same level
entity.Name = EnsureUniqueNodeName(entity.ParentId, entity.Name);
@@ -5,7 +5,6 @@ using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Scoping;
@@ -103,7 +102,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistNewItem(IMediaType entity)
{
entity.AddingEntity();
((MediaType)entity).AddingEntity();
PersistNewBaseContentType(entity);
@@ -115,7 +114,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
ValidateAlias(entity);
//Updates Modified date
entity.UpdatingEntity();
((MediaType)entity).UpdatingEntity();
//Look up parent to get and set the correct Path if ParentId has changed
if (entity.IsPropertyDirty("ParentId"))
@@ -6,7 +6,6 @@ using Umbraco.Core.Cache;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.Querying;
@@ -92,8 +91,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistNewItem(IMemberGroup entity)
{
//Save to db
entity.AddingEntity();
var group = (MemberGroup)entity;
group.AddingEntity();
var dto = MemberGroupFactory.BuildDto(group);
var o = Database.IsNew(dto) ? Convert.ToInt32(Database.Insert(dto)) : Database.Update(dto);
group.Id = dto.NodeId; //Set Id on entity to ensure an Id is set
@@ -6,7 +6,6 @@ using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.Querying;
@@ -233,13 +232,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistNewItem(IMember entity)
{
if (entity.ProviderUserKey == null)
{
entity.ProviderUserKey = entity.Key;
}
entity.AddingEntity();
var member = (Member) entity;
member.AddingEntity();
// ensure that strings don't contain characters that are invalid in xml
// TODO: do we really want to keep doing this here?
@@ -5,7 +5,6 @@ using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.Querying;
@@ -132,12 +131,12 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
{
ValidateAlias(entity);
entity.AddingEntity();
((MemberType)entity).AddingEntity();
//set a default icon if one is not specified
if (entity.Icon.IsNullOrWhiteSpace())
{
entity.Icon = Constants.Icons.Member;
entity.Icon = "icon-user";
}
//By Convention we add 9 standard PropertyTypes to an Umbraco MemberType
@@ -166,7 +165,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
ValidateAlias(entity);
//Updates Modified date
entity.UpdatingEntity();
((MemberType)entity).UpdatingEntity();
//Look up parent to get and set the correct Path if ParentId has changed
if (entity.IsPropertyDirty("ParentId"))
@@ -225,7 +224,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
{
//this reset's its current data type reference which will be re-assigned based on the property editor assigned on the next line
propertyType.DataTypeId = 0;
propertyType.DataTypeKey = default;
}
}
}
@@ -5,7 +5,6 @@ using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.Querying;
@@ -134,7 +134,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistNewItem(IRelation entity)
{
entity.AddingEntity();
((EntityBase)entity).AddingEntity();
var factory = new RelationFactory(entity.RelationType);
var dto = factory.BuildDto(entity);
@@ -147,7 +147,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistUpdatedItem(IRelation entity)
{
entity.UpdatingEntity();
((EntityBase)entity).UpdatingEntity();
var factory = new RelationFactory(entity.RelationType);
var dto = factory.BuildDto(entity);
@@ -133,7 +133,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistNewItem(IRelationType entity)
{
entity.AddingEntity();
((EntityBase)entity).AddingEntity();
var dto = RelationTypeFactory.BuildDto(entity);
@@ -145,7 +145,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistUpdatedItem(IRelationType entity)
{
entity.UpdatingEntity();
((EntityBase)entity).UpdatingEntity();
var dto = RelationTypeFactory.BuildDto(entity);
Database.Update(dto);
@@ -5,7 +5,6 @@ using NPoco;
using Umbraco.Core.Cache;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence.Dtos;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.Querying;
@@ -97,7 +96,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistNewItem(IServerRegistration entity)
{
entity.AddingEntity();
((ServerRegistration)entity).AddingEntity();
var dto = ServerRegistrationFactory.BuildDto(entity);
@@ -109,7 +108,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistUpdatedItem(IServerRegistration entity)
{
entity.UpdatingEntity();
((ServerRegistration)entity).UpdatingEntity();
var dto = ServerRegistrationFactory.BuildDto(entity);
@@ -85,7 +85,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
/// <inheritdoc />
protected override void PersistNewItem(ITag entity)
{
entity.AddingEntity();
((EntityBase)entity).AddingEntity();
var dto = TagFactory.BuildDto(entity);
var id = Convert.ToInt32(Database.Insert(dto));
@@ -97,7 +97,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
/// <inheritdoc />
protected override void PersistUpdatedItem(ITag entity)
{
entity.UpdatingEntity();
((EntityBase)entity).UpdatingEntity();
var dto = TagFactory.BuildDto(entity);
Database.Update(dto);
@@ -290,7 +290,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistNewItem(IUserGroup entity)
{
entity.AddingEntity();
((UserGroup) entity).AddingEntity();
var userGroupDto = UserGroupFactory.BuildDto(entity);
@@ -304,7 +304,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
protected override void PersistUpdatedItem(IUserGroup entity)
{
entity.UpdatingEntity();
((UserGroup) entity).UpdatingEntity();
var userGroupDto = UserGroupFactory.BuildDto(entity);
@@ -445,7 +445,7 @@ ORDER BY colName";
return;
}
entity.AddingEntity();
((User) entity).AddingEntity();
// ensure security stamp if missing
if (entity.SecurityStamp.IsNullOrWhiteSpace())
@@ -495,7 +495,7 @@ ORDER BY colName";
protected override void PersistUpdatedItem(IUser entity)
{
// updates Modified date
entity.UpdatingEntity();
((User) entity).UpdatingEntity();
// ensure security stamp if missing
if (entity.SecurityStamp.IsNullOrWhiteSpace())
@@ -30,7 +30,7 @@ namespace Umbraco.Core.PropertyEditors
// defaults
Type = type;
Icon = Constants.Icons.PropertyEditor;
Group = Constants.PropertyEditors.Groups.Common;
Group = "common";
// assign properties based on the attribute, if it is found
Attribute = GetType().GetCustomAttribute<DataEditorAttribute>(false);
@@ -121,7 +121,7 @@ namespace Umbraco.Core.PropertyEditors
/// Gets or sets an optional group.
/// </summary>
/// <remarks>The group can be used for example to group the editors by category.</remarks>
public string Group { get; set; } = Constants.PropertyEditors.Groups.Common;
public string Group { get; set; } = "common";
/// <summary>
/// Gets or sets a value indicating whether the value editor is deprecated.
@@ -1,10 +0,0 @@
namespace Umbraco.Core.PropertyEditors
{
/// <summary>
/// Marker interface for any editor configuration that supports Ignoring user start nodes
/// </summary>
internal interface IIgnoreUserStartNodesConfig
{
bool IgnoreUserStartNodes { get; set; }
}
}
@@ -5,11 +5,7 @@ namespace Umbraco.Core.PropertyEditors
/// <summary>
/// Represents a property editor for label properties.
/// </summary>
[DataEditor(
Constants.PropertyEditors.Aliases.Label,
"Label",
"readonlyvalue",
Icon = "icon-readonly")]
[DataEditor(Constants.PropertyEditors.Aliases.Label, "Label", "readonlyvalue", Icon = "icon-readonly")]
public class LabelPropertyEditor : DataEditor
{
/// <summary>
+6 -14
View File
@@ -103,26 +103,18 @@ namespace Umbraco.Core
/// Gets the children of the content item.
/// </summary>
/// <param name="content">The content item.</param>
/// <param name="culture">
/// The specific culture to get the url children for. Default is null which will use the current culture in <see cref="VariationContext"/>
/// </param>
/// <param name="culture">The specific culture to get the url children for. If null is used the current culture is used (Default is null).</param>
/// <remarks>
/// <para>Gets children that are available for the specified culture.</para>
/// <para>Children are sorted by their sortOrder.</para>
/// <para>
/// For culture,
/// if null is used the current culture is used.
/// If an empty string is used only invariant children are returned.
/// If "*" is used all children are returned.
/// </para>
/// <para>
/// If a variant culture is specified or there is a current culture in the <see cref="VariationContext"/> then the Children returned
/// will include both the variant children matching the culture AND the invariant children because the invariant children flow with the current culture.
/// However, if an empty string is specified only invariant children are returned.
/// </para>
/// <para>The '*' culture and supported and returns everything.</para>
/// </remarks>
public static IEnumerable<IPublishedContent> Children(this IPublishedContent content, string culture = null)
{
// invariant has invariant value (whatever the requested culture)
if (!content.ContentType.VariesByCulture() && culture != "*")
culture = "";
// handle context culture for variant
if (culture == null)
culture = VariationContextAccessor?.VariationContext?.Culture ?? "";
@@ -9,14 +9,7 @@ namespace Umbraco.Core
public static class PublishedModelFactoryExtensions
{
/// <summary>
/// Returns true if the current <see cref="IPublishedModelFactory"/> is an implementation of <see cref="ILivePublishedModelFactory"/>
/// </summary>
/// <param name="factory"></param>
/// <returns></returns>
public static bool IsLiveFactory(this IPublishedModelFactory factory) => factory is ILivePublishedModelFactory;
/// <summary>
/// Executes an action with a safe live factory
/// Executes an action with a safe live factory/
/// </summary>
/// <remarks>
/// <para>If the factory is a live factory, ensures it is refreshed and locked while executing the action.</para>
@@ -27,7 +20,6 @@ namespace Umbraco.Core
{
lock (liveFactory.SyncRoot)
{
//Call refresh on the live factory to re-compile the models
liveFactory.Refresh();
action();
}
+3 -3
View File
@@ -139,7 +139,7 @@ namespace Umbraco.Core.Runtime
// there should be none, really - this is here "just in case"
Compose(composition);
// acquire the main domain - if this fails then anything that should be registered with MainDom will not operate
// acquire the main domain
AcquireMainDom(mainDom);
// determine our runtime level
@@ -218,13 +218,13 @@ namespace Umbraco.Core.Runtime
IOHelper.SetRootDirectory(path);
}
private bool AcquireMainDom(MainDom mainDom)
private void AcquireMainDom(MainDom mainDom)
{
using (var timer = ProfilingLogger.DebugDuration<CoreRuntime>("Acquiring MainDom.", "Acquired."))
{
try
{
return mainDom.Acquire();
mainDom.Acquire();
}
catch
{
-5
View File
@@ -97,11 +97,6 @@ namespace Umbraco.Core
/// <param name="request"></param>
internal void EnsureApplicationUrl(HttpRequestBase request = null)
{
//Fixme: This causes problems with site swap on azure because azure pre-warms a site by calling into `localhost` and when it does that
// it changes the URL to `localhost:80` which actually doesn't work for pinging itself, it only works internally in Azure. The ironic part
// about this is that this is here specifically for the slot swap scenario https://issues.umbraco.org/issue/U4-10626
// see U4-10626 - in some cases we want to reset the application url
// (this is a simplified version of what was in 7.x)
// note: should this be optional? is it expensive?
@@ -6,25 +6,9 @@ namespace Umbraco.Core.Services.Changes
public enum ContentTypeChangeTypes : byte
{
None = 0,
/// <summary>
/// Item type has been created, no impact
/// </summary>
Create = 1,
/// <summary>
/// Content type changes impact only the Content type being saved
/// </summary>
RefreshMain = 2,
/// <summary>
/// Content type changes impacts the content type being saved and others used that are composed of it
/// </summary>
RefreshOther = 4, // changed, other change
/// <summary>
/// Content type was removed
/// </summary>
Remove = 8
Create = 1, // item type has been created, no impact
RefreshMain = 2, // changed, impacts content (adding property or composition does NOT)
RefreshOther = 4, // changed, other changes
Remove = 8 // item type has been removed
}
}
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
@@ -12,42 +11,6 @@ namespace Umbraco.Core.Services
/// </summary>
public static class ContentServiceExtensions
{
#region RTE Anchor values
private static readonly Regex AnchorRegex = new Regex("<a id=\"(.*?)\">", RegexOptions.Compiled);
internal static IEnumerable<string> GetAnchorValuesFromRTEs(this IContentService contentService, int id, string culture = "*")
{
var result = new List<string>();
var content = contentService.GetById(id);
foreach (var contentProperty in content.Properties)
{
if (contentProperty.PropertyType.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.TinyMce))
{
var value = contentProperty.GetValue(culture)?.ToString();
if (!string.IsNullOrEmpty(value))
{
result.AddRange(contentService.GetAnchorValuesFromRTEContent(value));
}
}
}
return result;
}
internal static IEnumerable<string> GetAnchorValuesFromRTEContent(this IContentService contentService, string rteContent)
{
var result = new List<string>();
var matches = AnchorRegex.Matches(rteContent);
foreach (Match match in matches)
{
result.Add(match.Value.Split('\"')[1]);
}
return result;
}
#endregion
public static IEnumerable<IContent> GetByIds(this IContentService contentService, IEnumerable<Udi> ids)
{
var guids = new List<GuidUdi>();
@@ -1,21 +0,0 @@
using System;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors;
namespace Umbraco.Core.Services
{
internal static class DateTypeServiceExtensions
{
public static bool IsDataTypeIgnoringUserStartNodes(this IDataTypeService dataTypeService, Guid key)
{
if (DataTypeExtensions.IsBuildInDataType(key)) return false; //built in ones can never be ignoring start nodes
var dataType = dataTypeService.GetDataType(key);
if (dataType != null && dataType.Configuration is IIgnoreUserStartNodesConfig ignoreStartNodesConfig)
return ignoreStartNodesConfig.IgnoreUserStartNodes;
return false;
}
}
}
@@ -526,6 +526,5 @@ namespace Umbraco.Core.Services
OperationResult Rollback(int id, int versionId, string culture = "*", int userId = Constants.Security.SuperUserId);
#endregion
}
}
@@ -4,7 +4,6 @@ using Umbraco.Core.Models;
namespace Umbraco.Core.Services
{
/// <summary>
/// Defines the DataType Service, which is an easy access to operations involving <see cref="IDataType"/>
/// </summary>
@@ -51,8 +51,8 @@ namespace Umbraco.Core.Services.Implement
using (var scope = ScopeProvider.CreateScope())
{
var result = sinceDate.HasValue == false
? _auditRepository.Get(type, Query<IAuditItem>().Where(x => x.UserId == userId))
: _auditRepository.Get(type, Query<IAuditItem>().Where(x => x.UserId == userId && x.CreateDate >= sinceDate.Value));
? _auditRepository.Get(Query<IAuditItem>().Where(x => x.UserId == userId && x.AuditType == type))
: _auditRepository.Get(Query<IAuditItem>().Where(x => x.UserId == userId && x.AuditType == type && x.CreateDate >= sinceDate.Value));
scope.Complete();
return result;
}
@@ -63,8 +63,8 @@ namespace Umbraco.Core.Services.Implement
using (var scope = ScopeProvider.CreateScope())
{
var result = sinceDate.HasValue == false
? _auditRepository.Get(type, Query<IAuditItem>())
: _auditRepository.Get(type, Query<IAuditItem>().Where(x => x.CreateDate >= sinceDate.Value));
? _auditRepository.Get(Query<IAuditItem>().Where(x => x.AuditType == type))
: _auditRepository.Get(Query<IAuditItem>().Where(x => x.AuditType == type && x.CreateDate >= sinceDate.Value));
scope.Complete();
return result;
}
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using Umbraco.Core.Events;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
@@ -32,7 +31,6 @@ namespace Umbraco.Core.Services.Implement
private IQuery<IContent> _queryNotTrashed;
//TODO: The non-lazy object should be injected
private readonly Lazy<PropertyValidationService> _propertyValidationService = new Lazy<PropertyValidationService>(() => new PropertyValidationService());
#region Constructors
@@ -3026,8 +3024,5 @@ namespace Umbraco.Core.Services.Implement
}
#endregion
}
}
+2 -11
View File
@@ -13,7 +13,7 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>portable</DebugType>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG</DefineConstants>
@@ -23,7 +23,7 @@
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>portable</DebugType>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
@@ -55,11 +55,6 @@
</ItemGroup>
<ItemGroup>
<!-- note: NuGet deals with transitive references now -->
<PackageReference Include="Microsoft.SourceLink.GitHub">
<Version>1.0.0-beta2-19324-01</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Serilog.Sinks.Async">
<Version>1.3.0</Version>
</PackageReference>
@@ -241,9 +236,7 @@
<Compile Include="Migrations\Upgrade\V_8_0_0\DataTypes\DefaultPreValueMigrator.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\DataTypes\RenamingPreValueMigrator.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\DataTypes\RichTextPreValueMigrator.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\DataTypes\DropDownFlexiblePreValueMigrator.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\MergeDateAndDateTimePropertyEditor.cs" />
<Compile Include="Models\Entities\EntityExtensions.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\DataTypes\PreValueMigratorBase.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\DataTypes\PreValueDto.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\PropertyEditorsMigrationBase.cs" />
@@ -265,7 +258,6 @@
<Compile Include="Models\PublishedContent\ILivePublishedModelFactory.cs" />
<Compile Include="Models\PublishedContent\IPublishedContentType.cs" />
<Compile Include="Models\PublishedContent\IPublishedPropertyType.cs" />
<Compile Include="PropertyEditors\IIgnoreUserStartNodesConfig.cs" />
<Compile Include="PublishedContentExtensions.cs" />
<Compile Include="Models\PublishedContent\UrlMode.cs" />
<Compile Include="Persistence\Dtos\PropertyTypeCommonDto.cs" />
@@ -275,7 +267,6 @@
<Compile Include="PropertyEditors\DateTimeConfiguration.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\RenameLabelAndRichTextPropertyEditorAliases.cs" />
<Compile Include="PublishedModelFactoryExtensions.cs" />
<Compile Include="Services\DateTypeServiceExtensions.cs" />
<Compile Include="Services\PropertyValidationService.cs" />
<Compile Include="Composing\TypeCollectionBuilderBase.cs" />
<Compile Include="TypeLoaderExtensions.cs" />
-2
View File
@@ -23,8 +23,6 @@ namespace Umbraco.Core
handle,
(state, timedOut) =>
{
//TODO: We aren't checking if this is timed out
tcs.SetResult(null);
// we take a lock here to make sure the outer method has completed setting the local variable callbackHandle.
+1 -1
View File
@@ -45,7 +45,7 @@ namespace Umbraco.Examine
continue;
case string strVal:
{
if (strVal.IsNullOrWhiteSpace()) continue;
if (strVal.IsNullOrWhiteSpace()) return;
var key = $"{keyVal.Key}{cultureSuffix}";
if (values.TryGetValue(key, out var v))
values[key] = new List<object>(v) { val }.ToArray();
+1 -28
View File
@@ -48,31 +48,6 @@ namespace Umbraco.Examine
}
}
/// <summary>
/// Returns all index fields that are culture specific (suffixed) or invariant
/// </summary>
/// <param name="index"></param>
/// <param name="culture"></param>
/// <returns></returns>
public static IEnumerable<string> GetCultureAndInvariantFields(this IUmbracoIndex index, string culture)
{
var allFields = index.GetFields();
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var field in allFields)
{
var match = CultureIsoCodeFieldNameMatchExpression.Match(field);
if (match.Success && match.Groups.Count == 3 && culture.InvariantEquals(match.Groups[2].Value))
{
yield return field; //matches this culture field
}
else if (!match.Success)
{
yield return field; //matches no culture field (invariant)
}
}
}
internal static bool TryParseLuceneQuery(string query)
{
// TODO: I'd assume there would be a more strict way to parse the query but not that i can find yet, for now we'll
@@ -102,7 +77,7 @@ namespace Umbraco.Examine
/// <remarks>
/// This is not thread safe, use with care
/// </remarks>
internal static void ConfigureLuceneIndexes(this IExamineManager examineManager, ILogger logger, bool disableExamineIndexing)
internal static void UnlockLuceneIndexes(this IExamineManager examineManager, ILogger logger)
{
foreach (var luceneIndexer in examineManager.Indexes.OfType<LuceneIndex>())
{
@@ -111,8 +86,6 @@ namespace Umbraco.Examine
//that could end up halting shutdown for a very long time causing overlapping appdomains and many other problems.
luceneIndexer.WaitForIndexQueueOnShutdown = false;
if (disableExamineIndexing) continue; //exit if not enabled, we don't need to unlock them if we're not maindom
//we should check if the index is locked ... it shouldn't be! We are using simple fs lock now and we are also ensuring that
//the indexes are not operational unless MainDom is true
var dir = luceneIndexer.GetLuceneDirectory();
+2 -7
View File
@@ -13,7 +13,7 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>portable</DebugType>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
@@ -23,7 +23,7 @@
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>portable</DebugType>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
@@ -49,11 +49,6 @@
<ItemGroup>
<!-- note: NuGet deals with transitive references now -->
<PackageReference Include="Examine" Version="1.0.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub">
<Version>1.0.0-beta2-19324-01</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="NPoco" Version="3.9.4" />
</ItemGroup>
@@ -1,86 +0,0 @@
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Http.Controllers;
using System.Web.Security;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models.Membership;
namespace Umbraco.ModelsBuilder.Api
{
//TODO: This needs to be changed:
// * Authentication cannot happen in a filter, only Authorization
// * The filter must be an AuthorizationFilter, not an ActionFilter
// * Authorization must be done using the Umbraco logic - it is very specific for claim checking for ASP.Net Identity
// * Theoretically this shouldn't be required whatsoever because when we authenticate a request that has Basic Auth (i.e. for
// VS to work, it will add the correct Claims to the Identity and it will automatically be authorized.
//
// we *do* have POC supporting ASP.NET identity, however they require some config on the server
// we'll keep using this quick-and-dirty method for the time being
public class ApiBasicAuthFilter : System.Web.Http.Filters.ActionFilterAttribute // use the http one, not mvc, with api controllers!
{
private static readonly char[] Separator = ":".ToCharArray();
private readonly string _section;
public ApiBasicAuthFilter(string section)
{
_section = section;
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
try
{
var user = Authenticate(actionContext.Request);
if (user == null || !user.AllowedSections.Contains(_section))
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
}
//else
//{
// // note - would that be a proper way to pass data to the controller?
// // see http://stevescodingblog.co.uk/basic-authentication-with-asp-net-webapi/
// actionContext.ControllerContext.RouteData.Values["umbraco-user"] = user;
//}
base.OnActionExecuting(actionContext);
}
catch
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
}
}
private static IUser Authenticate(HttpRequestMessage request)
{
var ah = request.Headers.Authorization;
if (ah == null || ah.Scheme != "Basic")
return null;
var token = ah.Parameter;
var credentials = Encoding.ASCII
.GetString(Convert.FromBase64String(token))
.Split(Separator);
if (credentials.Length != 2)
return null;
var username = ApiClient.DecodeTokenElement(credentials[0]);
var password = ApiClient.DecodeTokenElement(credentials[1]);
var providerKey = UmbracoConfig.For.UmbracoSettings().Providers.DefaultBackOfficeUserProvider;
var provider = Membership.Providers[providerKey];
if (provider == null || !provider.ValidateUser(username, password))
return null;
var user = Current.Services.UserService.GetByUsername(username);
if (!user.IsApproved || user.IsLockedOut)
return null;
return user;
}
}
}
-159
View File
@@ -1,159 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Text;
namespace Umbraco.ModelsBuilder.Api
{
public class ApiClient
{
private readonly string _url;
private readonly string _user;
private readonly string _password;
private readonly JsonMediaTypeFormatter _formatter;
private readonly MediaTypeFormatter[] _formatters;
// fixme hardcoded?
// could be options - but we cannot "discover" them as the API client runs outside of the web app
// in addition, anything that references the controller forces API clients to reference Umbraco.Core
private const string ApiControllerUrl = "/Umbraco/BackOffice/ModelsBuilder/ModelsBuilderApi/";
public ApiClient(string url, string user, string password)
{
_url = url.TrimEnd('/');
_user = user;
_password = password;
_formatter = new JsonMediaTypeFormatter();
_formatters = new MediaTypeFormatter[] { _formatter };
}
private void SetBaseAddress(HttpClient client, string url)
{
try
{
client.BaseAddress = new Uri(url);
}
catch
{
throw new UriFormatException($"Invalid URI: the format of the URI \"{url}\" could not be determined.");
}
}
public void ValidateClientVersion()
{
// FIXME - add proxys support
var hch = new HttpClientHandler();
using (var client = new HttpClient(hch))
{
SetBaseAddress(client, _url);
Authorize(client);
var data = new ValidateClientVersionData
{
ClientVersion = ApiVersion.Current.Version,
MinServerVersionSupportingClient = ApiVersion.Current.MinServerVersionSupportingClient,
};
var result = client.PostAsync(_url + ApiControllerUrl + nameof(ModelsBuilderApiController.ValidateClientVersion),
data, _formatter).Result;
// this is not providing enough details in case of an error - do our own reporting
//result.EnsureSuccessStatusCode();
EnsureSuccess(result);
}
}
public IDictionary<string, string> GetModels(Dictionary<string, string> ourFiles, string modelsNamespace)
{
// FIXME - add proxys support
var hch = new HttpClientHandler();
//hch.Proxy = new WebProxy("path.to.proxy", 8888);
//hch.UseProxy = true;
using (var client = new HttpClient(hch))
{
SetBaseAddress(client, _url);
Authorize(client);
var data = new GetModelsData
{
Namespace = modelsNamespace,
ClientVersion = ApiVersion.Current.Version,
MinServerVersionSupportingClient = ApiVersion.Current.MinServerVersionSupportingClient,
Files = ourFiles
};
var result = client.PostAsync(_url + ApiControllerUrl + nameof(ModelsBuilderApiController.GetModels),
data, _formatter).Result;
// this is not providing enough details in case of an error - do our own reporting
//result.EnsureSuccessStatusCode();
EnsureSuccess(result);
var genFiles = result.Content.ReadAsAsync<IDictionary<string, string>>(_formatters).Result;
return genFiles;
}
}
private static void EnsureSuccess(HttpResponseMessage result)
{
if (result.IsSuccessStatusCode) return;
var text = result.Content.ReadAsStringAsync().Result;
throw new Exception($"Response status code does not indicate success ({result.StatusCode})\n{text}");
}
private void Authorize(HttpClient client)
{
AuthorizeBasic(client);
}
// fixme - for the time being, we don't cache the token and we auth on each API call
// not used at the moment
/*
private void AuthorizeIdentity(HttpClient client)
{
var formData = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("userName", _user),
new KeyValuePair<string, string>("password", _password),
});
var result = client.PostAsync(_url + UmbracoOAuthTokenUrl, formData).Result;
EnsureSuccess(result);
var token = result.Content.ReadAsAsync<TokenData>(_formatters).Result;
if (token.TokenType != "bearer")
throw new Exception($"Received invalid token type \"{token.TokenType}\", expected \"bearer\".");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.AccessToken);
}
*/
private void AuthorizeBasic(HttpClient client)
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(Encoding.UTF8.GetBytes(EncodeTokenElement(_user) + ':' + EncodeTokenElement(_password))));
}
public static string EncodeTokenElement(string s)
{
return s.Replace("%", "%a").Replace(":", "%b");
}
public static string DecodeTokenElement(string s)
{
return s.Replace("%b", ":").Replace("%a", "%");
}
}
}
@@ -1,27 +0,0 @@
using System.Collections.Generic;
using System.Text;
using Umbraco.ModelsBuilder.Building;
using Umbraco.ModelsBuilder.Umbraco;
namespace Umbraco.ModelsBuilder.Api
{
internal static class ApiHelper
{
public static Dictionary<string, string> GetModels(UmbracoServices umbracoServices, string modelsNamespace, IDictionary<string, string> files)
{
var typeModels = umbracoServices.GetAllTypes();
var parseResult = new CodeParser().ParseWithReferencedAssemblies(files);
var builder = new TextBuilder(typeModels, parseResult, modelsNamespace);
var models = new Dictionary<string, string>();
foreach (var typeModel in builder.GetModelsToGenerate())
{
var sb = new StringBuilder();
builder.Generate(sb, typeModel);
models[typeModel.ClrName] = sb.ToString();
}
return models;
}
}
}
+9 -61
View File
@@ -1,5 +1,6 @@
using System;
using System.Reflection;
using Semver;
namespace Umbraco.ModelsBuilder.Api
{
@@ -8,81 +9,28 @@ namespace Umbraco.ModelsBuilder.Api
/// </summary>
public class ApiVersion
{
#region Configure
// indicate the minimum version of the client API that is supported by this server's API.
// eg our Version = 4.8 but we support connections from VSIX down to version 3.2
// => as a server, we accept connections from client down to version ...
private static readonly Version MinClientVersionSupportedByServerConst = new Version(3, 0, 0, 0);
// indicate the minimum version of the server that can support the client API
// eg our Version = 4.8 and we know we're compatible with website server down to version 3.2
// => as a client, we tell the server down to version ... that it should accept us
private static readonly Version MinServerVersionSupportingClientConst = new Version(3, 0, 0, 0);
#endregion
/// <summary>
/// Initializes a new instance of the <see cref="ApiVersion"/> class.
/// </summary>
/// <param name="executingVersion">The currently executing version.</param>
/// <param name="minClientVersionSupportedByServer">The min client version supported by the server.</param>
/// <param name="minServerVersionSupportingClient">An opt min server version supporting the client.</param>
internal ApiVersion(Version executingVersion, Version minClientVersionSupportedByServer, Version minServerVersionSupportingClient = null)
/// <exception cref="ArgumentNullException"></exception>
internal ApiVersion(SemVersion executingVersion)
{
if (executingVersion == null) throw new ArgumentNullException(nameof(executingVersion));
if (minClientVersionSupportedByServer == null) throw new ArgumentNullException(nameof(minClientVersionSupportedByServer));
Version = executingVersion;
MinClientVersionSupportedByServer = minClientVersionSupportedByServer;
MinServerVersionSupportingClient = minServerVersionSupportingClient;
Version = executingVersion ?? throw new ArgumentNullException(nameof(executingVersion));
}
private static SemVersion CurrentAssemblyVersion
=> SemVersion.Parse(Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion);
/// <summary>
/// Gets the currently executing API version.
/// </summary>
public static ApiVersion Current { get; }
= new ApiVersion(Assembly.GetExecutingAssembly().GetName().Version,
MinClientVersionSupportedByServerConst, MinServerVersionSupportingClientConst);
= new ApiVersion(CurrentAssemblyVersion);
/// <summary>
/// Gets the executing version of the API.
/// </summary>
public Version Version { get; }
/// <summary>
/// Gets the min client version supported by the server.
/// </summary>
public Version MinClientVersionSupportedByServer { get; }
/// <summary>
/// Gets the min server version supporting the client.
/// </summary>
public Version MinServerVersionSupportingClient { get; }
/// <summary>
/// Gets a value indicating whether the API server is compatible with a client.
/// </summary>
/// <param name="clientVersion">The client version.</param>
/// <param name="minServerVersionSupportingClient">An opt min server version supporting the client.</param>
/// <remarks>
/// <para>A client is compatible with a server if the client version is greater-or-equal _minClientVersionSupportedByServer
/// (ie client can be older than server, up to a point) AND the client version is lower-or-equal the server version
/// (ie client cannot be more recent than server) UNLESS the server .</para>
/// </remarks>
public bool IsCompatibleWith(Version clientVersion, Version minServerVersionSupportingClient = null)
{
// client cannot be older than server's min supported version
if (clientVersion < MinClientVersionSupportedByServer)
return false;
// if we know about this client (client is older than server), it is supported
if (clientVersion <= Version) // if we know about this client (client older than server)
return true;
// if we don't know about this client (client is newer than server),
// give server a chance to tell client it is, indeed, ok to support it
return minServerVersionSupportingClient != null && minServerVersionSupportingClient <= Version;
}
public SemVersion Version { get; }
}
}
@@ -1,17 +0,0 @@
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Umbraco.ModelsBuilder.Api
{
[DataContract]
public class GetModelsData : ValidateClientVersionData
{
[DataMember]
public string Namespace { get; set; }
[DataMember]
public IDictionary<string, string> Files { get; set; }
public override bool IsValid => base.IsValid && Files != null;
}
}
@@ -1,85 +0,0 @@
using System;
using System.Net;
using System.Net.Http;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.ModelsBuilder.Configuration;
using Umbraco.ModelsBuilder.Umbraco;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi;
namespace Umbraco.ModelsBuilder.Api
{
// read http://umbraco.com/follow-us/blog-archive/2014/1/17/heads-up,-breaking-change-coming-in-702-and-62.aspx
// read http://our.umbraco.org/forum/developers/api-questions/43025-Web-API-authentication
// UmbracoAuthorizedApiController :: /Umbraco/BackOffice/Zbu/ModelsBuilderApi/GetTypeModels
// UmbracoApiController :: /Umbraco/Zbu/ModelsBuilderApi/GetTypeModels ?? UNLESS marked with isbackoffice
//
// BEWARE! the controller url is hard-coded in ModelsBuilderApi and needs to be in sync!
[PluginController(ControllerArea)]
[IsBackOffice]
//[UmbracoApplicationAuthorize(Constants.Applications.Developer)] // see ApiBasicAuthFilter - that one would be for ASP.NET identity
public class ModelsBuilderApiController : UmbracoApiController // UmbracoAuthorizedApiController - for ASP.NET identity
{
public const string ControllerArea = "ModelsBuilder";
private readonly UmbracoServices _umbracoServices;
public ModelsBuilderApiController(UmbracoServices umbracoServices)
{
_umbracoServices = umbracoServices;
}
// invoked by the API
[System.Web.Http.HttpPost] // use the http one, not mvc, with api controllers!
[ApiBasicAuthFilter("developer")] // have to use our own, non-cookie-based, auth
public HttpResponseMessage ValidateClientVersion(ValidateClientVersionData data)
{
if (!UmbracoConfig.For.ModelsBuilder().ApiServer)
return Request.CreateResponse(HttpStatusCode.Forbidden, "API server does not want to talk to you.");
if (!ModelState.IsValid || data == null || !data.IsValid)
return Request.CreateResponse(HttpStatusCode.BadRequest, "Invalid data.");
var checkResult = CheckVersion(data.ClientVersion, data.MinServerVersionSupportingClient);
return (checkResult.Success
? Request.CreateResponse(HttpStatusCode.OK, "OK", Configuration.Formatters.JsonFormatter)
: checkResult.Result);
}
// invoked by the API
[System.Web.Http.HttpPost] // use the http one, not mvc, with api controllers!
[ApiBasicAuthFilter("developer")] // have to use our own, non-cookie-based, auth
public HttpResponseMessage GetModels(GetModelsData data)
{
if (!UmbracoConfig.For.ModelsBuilder().ApiServer)
return Request.CreateResponse(HttpStatusCode.Forbidden, "API server does not want to talk to you.");
if (!ModelState.IsValid || data == null || !data.IsValid)
return Request.CreateResponse(HttpStatusCode.BadRequest, "Invalid data.");
var checkResult = CheckVersion(data.ClientVersion, data.MinServerVersionSupportingClient);
if (!checkResult.Success)
return checkResult.Result;
var models = ApiHelper.GetModels(_umbracoServices, data.Namespace, data.Files);
return Request.CreateResponse(HttpStatusCode.OK, models, Configuration.Formatters.JsonFormatter);
}
private Attempt<HttpResponseMessage> CheckVersion(Version clientVersion, Version minServerVersionSupportingClient)
{
if (clientVersion == null)
return Attempt<HttpResponseMessage>.Fail(Request.CreateResponse(HttpStatusCode.Forbidden,
$"API version conflict: client version (<null>) is not compatible with server version({ApiVersion.Current.Version})."));
// minServerVersionSupportingClient can be null
var isOk = ApiVersion.Current.IsCompatibleWith(clientVersion, minServerVersionSupportingClient);
var response = isOk ? null : Request.CreateResponse(HttpStatusCode.Forbidden,
$"API version conflict: client version ({clientVersion}) is not compatible with server version({ApiVersion.Current.Version}).");
return Attempt<HttpResponseMessage>.If(isOk, response);
}
}
}
@@ -1,17 +0,0 @@
using System.Runtime.Serialization;
namespace Umbraco.ModelsBuilder.Api
{
[DataContract]
class TokenData
{
[DataMember(Name = "access_token")]
public string AccessToken { get; set; }
[DataMember(Name = "token_type")]
public string TokenType { get; set; }
[DataMember(Name = "expires_in")]
public int ExpiresIn { get; set; }
}
}
@@ -1,57 +0,0 @@
using System;
using System.Runtime.Serialization;
namespace Umbraco.ModelsBuilder.Api
{
[DataContract]
public class ValidateClientVersionData
{
// issues 32, 34... problems when serializing versions
//
// make sure System.Version objects are transfered as strings
// depending on the JSON serializer version, it looks like versions are causing issues
// see
// http://stackoverflow.com/questions/13170386/why-system-version-in-json-string-does-not-deserialize-correctly
//
// if the class is marked with [DataContract] then only properties marked with [DataMember]
// are serialized and the rest is ignored, see
// http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization
[DataMember]
public string ClientVersionString
{
get { return VersionToString(ClientVersion); }
set { ClientVersion = ParseVersion(value, false, "client"); }
}
[DataMember]
public string MinServerVersionSupportingClientString
{
get { return VersionToString(MinServerVersionSupportingClient); }
set { MinServerVersionSupportingClient = ParseVersion(value, true, "minServer"); }
}
// not serialized
public Version ClientVersion { get; set; }
public Version MinServerVersionSupportingClient { get; set; }
private static string VersionToString(Version version)
{
return version?.ToString() ?? "0.0.0.0";
}
private static Version ParseVersion(string value, bool canBeNull, string name)
{
if (string.IsNullOrWhiteSpace(value) && canBeNull)
return null;
Version version;
if (Version.TryParse(value, out version))
return version;
throw new ArgumentException($"Failed to parse \"{value}\" as {name} version.");
}
public virtual bool IsValid => ClientVersion != null;
}
}
+34 -120
View File
@@ -5,6 +5,7 @@ using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.ModelsBuilder.Configuration;
@@ -25,7 +26,8 @@ namespace Umbraco.ModelsBuilder.Building
private readonly IList<TypeModel> _typeModels;
protected Dictionary<string, string> ModelsMap { get; } = new Dictionary<string, string>();
protected ParseResult ParseResult { get; }
private static Config Config => Current.Configs.ModelsBuilder();
// the list of assemblies that will be 'using' by default
protected readonly IList<string> TypesUsing = new List<string>
@@ -58,7 +60,7 @@ namespace Umbraco.ModelsBuilder.Building
/// <returns>The models to generate, ie those that are not ignored.</returns>
public IEnumerable<TypeModel> GetModelsToGenerate()
{
return _typeModels.Where(x => !x.IsContentIgnored);
return _typeModels;
}
/// <summary>
@@ -72,27 +74,25 @@ namespace Umbraco.ModelsBuilder.Building
/// and the result of code parsing.
/// </summary>
/// <param name="typeModels">The list of models to generate.</param>
/// <param name="parseResult">The result of code parsing.</param>
protected Builder(IList<TypeModel> typeModels, ParseResult parseResult)
{
_typeModels = typeModels ?? throw new ArgumentNullException(nameof(typeModels));
ParseResult = parseResult ?? throw new ArgumentNullException(nameof(parseResult));
Prepare();
}
protected Builder(IList<TypeModel> typeModels)
: this(typeModels, null)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="Builder"/> class with a list of models to generate,
/// the result of code parsing, and a models namespace.
/// </summary>
/// <param name="typeModels">The list of models to generate.</param>
/// <param name="parseResult">The result of code parsing.</param>
/// <param name="modelsNamespace">The models namespace.</param>
protected Builder(IList<TypeModel> typeModels, ParseResult parseResult, string modelsNamespace)
: this(typeModels, parseResult)
protected Builder(IList<TypeModel> typeModels, string modelsNamespace)
{
_typeModels = typeModels ?? throw new ArgumentNullException(nameof(typeModels));
// can be null or empty, we'll manage
ModelsNamespace = modelsNamespace;
// but we want it to prepare
Prepare();
}
// for unit tests only
@@ -108,49 +108,9 @@ namespace Umbraco.ModelsBuilder.Building
/// </remarks>
private void Prepare()
{
var pureLive = UmbracoConfig.For.ModelsBuilder().ModelsMode == ModelsMode.PureLive;
TypeModel.MapModelTypes(_typeModels, ModelsNamespace);
// mark IsContentIgnored models that we discovered should be ignored
// then propagate / ignore children of ignored contents
// ignore content = don't generate a class for it, don't generate children
foreach (var typeModel in _typeModels.Where(x => ParseResult.IsIgnored(x.Alias)))
typeModel.IsContentIgnored = true;
foreach (var typeModel in _typeModels.Where(x => !x.IsContentIgnored && x.EnumerateBaseTypes().Any(xx => xx.IsContentIgnored)))
typeModel.IsContentIgnored = true;
// handle model renames
foreach (var typeModel in _typeModels.Where(x => ParseResult.IsContentRenamed(x.Alias)))
{
typeModel.ClrName = ParseResult.ContentClrName(typeModel.Alias);
typeModel.IsRenamed = true;
ModelsMap[typeModel.Alias] = typeModel.ClrName;
}
// handle implement
foreach (var typeModel in _typeModels.Where(x => ParseResult.HasContentImplement(x.Alias)))
{
typeModel.HasImplement = true;
}
// mark OmitBase models that we discovered already have a base class
foreach (var typeModel in _typeModels.Where(x => ParseResult.HasContentBase(ParseResult.ContentClrName(x.Alias) ?? x.ClrName)))
typeModel.HasBase = true;
foreach (var typeModel in _typeModels)
{
// mark IsRemoved properties that we discovered should be ignored
// ie is marked as ignored on type, or on any parent type
var tm = typeModel;
foreach (var property in typeModel.Properties
.Where(property => tm.EnumerateBaseTypes(true).Any(x => ParseResult.IsPropertyIgnored(ParseResult.ContentClrName(x.Alias) ?? x.ClrName, property.Alias))))
{
property.IsIgnored = true;
}
// handle property renames
foreach (var property in typeModel.Properties)
property.ClrName = ParseResult.PropertyClrName(ParseResult.ContentClrName(typeModel.Alias) ?? typeModel.ClrName, property.Alias) ?? property.ClrName;
}
var pureLive = Config.ModelsMode == ModelsMode.PureLive;
// for the first two of these two tests,
// always throw, even in purelive: cannot happen unless ppl start fidling with attributes to rename
@@ -158,22 +118,22 @@ namespace Umbraco.ModelsBuilder.Building
// for the last one, don't throw in purelive, see comment
// ensure we have no duplicates type names
foreach (var xx in _typeModels.Where(x => !x.IsContentIgnored).GroupBy(x => x.ClrName).Where(x => x.Count() > 1))
foreach (var xx in _typeModels.GroupBy(x => x.ClrName).Where(x => x.Count() > 1))
throw new InvalidOperationException($"Type name \"{xx.Key}\" is used"
+ $" for types with alias {string.Join(", ", xx.Select(x => x.ItemType + ":\"" + x.Alias + "\""))}. Names have to be unique."
+ " Consider using an attribute to assign different names to conflicting types.");
// ensure we have no duplicates property names
foreach (var typeModel in _typeModels.Where(x => !x.IsContentIgnored))
foreach (var xx in typeModel.Properties.Where(x => !x.IsIgnored).GroupBy(x => x.ClrName).Where(x => x.Count() > 1))
foreach (var typeModel in _typeModels)
foreach (var xx in typeModel.Properties.GroupBy(x => x.ClrName).Where(x => x.Count() > 1))
throw new InvalidOperationException($"Property name \"{xx.Key}\" in type {typeModel.ItemType}:\"{typeModel.Alias}\""
+ $" is used for properties with alias {string.Join(", ", xx.Select(x => "\"" + x.Alias + "\""))}. Names have to be unique."
+ " Consider using an attribute to assign different names to conflicting properties.");
// ensure content & property type don't have identical name (csharp hates it)
foreach (var typeModel in _typeModels.Where(x => !x.IsContentIgnored))
foreach (var typeModel in _typeModels)
{
foreach (var xx in typeModel.Properties.Where(x => !x.IsIgnored && x.ClrName == typeModel.ClrName))
foreach (var xx in typeModel.Properties.Where(x => x.ClrName == typeModel.ClrName))
{
if (!pureLive)
throw new InvalidOperationException($"The model class for content type with alias \"{typeModel.Alias}\" is named \"{xx.ClrName}\"."
@@ -204,7 +164,7 @@ namespace Umbraco.ModelsBuilder.Building
// collect all the (non-removed) types implemented at parent level
// ie the parent content types and the mixins content types, recursively
var parentImplems = new List<TypeModel>();
if (typeModel.BaseType != null && !typeModel.BaseType.IsContentIgnored)
if (typeModel.BaseType != null)
TypeModel.CollectImplems(parentImplems, typeModel.BaseType);
// interfaces we must declare we implement (initially empty)
@@ -212,7 +172,6 @@ namespace Umbraco.ModelsBuilder.Building
// and except those that are already declared at the parent level
// in other words, DeclaringInterfaces is "local mixins"
var declaring = typeModel.MixinTypes
.Where(x => !x.IsContentIgnored)
.Except(parentImplems);
typeModel.DeclaringInterfaces.AddRange(declaring);
@@ -227,43 +186,16 @@ namespace Umbraco.ModelsBuilder.Building
typeModel.ImplementingInterfaces.AddRange(mixinImplems.Except(parentImplems));
}
// register using types
foreach (var usingNamespace in ParseResult.UsingNamespaces)
// ensure elements don't inherit from non-elements
foreach (var typeModel in _typeModels.Where(x => x.IsElement))
{
if (!TypesUsing.Contains(usingNamespace))
TypesUsing.Add(usingNamespace);
if (typeModel.BaseType != null && !typeModel.BaseType.IsElement)
throw new Exception($"Cannot generate model for type '{typeModel.Alias}' because it is an element type, but its parent type '{typeModel.BaseType.Alias}' is not.");
var errs = typeModel.MixinTypes.Where(x => !x.IsElement).ToList();
if (errs.Count > 0)
throw new Exception($"Cannot generate model for type '{typeModel.Alias}' because it is an element type, but it is composed of {string.Join(", ", errs.Select(x => "'" + x.Alias + "'"))} which {(errs.Count == 1 ? "is" : "are")} not.");
}
// discover static mixin methods
foreach (var typeModel in _typeModels)
typeModel.StaticMixinMethods.AddRange(ParseResult.StaticMixinMethods(typeModel.ClrName));
// handle ctor
foreach (var typeModel in _typeModels.Where(x => ParseResult.HasCtor(x.ClrName)))
typeModel.HasCtor = true;
}
private SemanticModel _ambiguousSymbolsModel;
private int _ambiguousSymbolsPos;
// internal for tests
internal void PrepareAmbiguousSymbols()
{
var codeBuilder = new StringBuilder();
foreach (var t in TypesUsing)
codeBuilder.AppendFormat("using {0};\n", t);
codeBuilder.AppendFormat("namespace {0}\n{{ }}\n", GetModelsNamespace());
var compiler = new Compiler();
SyntaxTree[] trees;
var compilation = compiler.GetCompilation("MyCompilation", new Dictionary<string, string> { { "code", codeBuilder.ToString() } }, out trees);
var tree = trees[0];
_ambiguousSymbolsModel = compilation.GetSemanticModel(tree);
var namespaceSyntax = tree.GetRoot().DescendantNodes().OfType<NamespaceDeclarationSyntax>().First();
//var namespaceSymbol = model.GetDeclaredSymbol(namespaceSyntax);
_ambiguousSymbolsPos = namespaceSyntax.OpenBraceToken.SpanStart;
}
// looking for a simple symbol eg 'Umbraco' or 'String'
@@ -273,20 +205,10 @@ namespace Umbraco.ModelsBuilder.Building
// - 1 symbol is found BUT not matching (implicitely ambiguous)
protected bool IsAmbiguousSymbol(string symbol, string match)
{
if (_ambiguousSymbolsModel == null)
PrepareAmbiguousSymbols();
if (_ambiguousSymbolsModel == null)
throw new Exception("Could not prepare ambiguous symbols.");
var symbols = _ambiguousSymbolsModel.LookupNamespacesAndTypes(_ambiguousSymbolsPos, null, symbol);
if (symbols.Length > 1) return true;
if (symbols.Length == 0) return false; // what else?
// only 1 - ensure it matches
var found = symbols[0].ToDisplayString();
var pos = found.IndexOf('<'); // generic?
if (pos > 0) found = found.Substring(0, pos); // strip
return found != match; // and compare
// cannot figure out is a symbol is ambiguous without Roslyn
// so... let's say everything is ambiguous - code won't be
// pretty but it'll work
return true;
}
internal string ModelsNamespaceForTests;
@@ -296,25 +218,17 @@ namespace Umbraco.ModelsBuilder.Building
if (ModelsNamespaceForTests != null)
return ModelsNamespaceForTests;
// code attribute overrides everything
if (ParseResult.HasModelsNamespace)
return ParseResult.ModelsNamespace;
// if builder was initialized with a namespace, use that one
if (!string.IsNullOrWhiteSpace(ModelsNamespace))
return ModelsNamespace;
// default
// fixme - should NOT reference config here, should make ModelsNamespace mandatory
return UmbracoConfig.For.ModelsBuilder().ModelsNamespace;
return Config.ModelsNamespace;
}
protected string GetModelsBaseClassName(TypeModel type)
{
// code attribute overrides everything
if (ParseResult.HasModelsBaseClassName)
return ParseResult.ModelsBaseClassName;
// default
return type.IsElement ? "PublishedElementModel" : "PublishedContentModel";
}
@@ -1,113 +0,0 @@
using System.CodeDom;
using System.Collections.Generic;
namespace Umbraco.ModelsBuilder.Building
{
// NOTE
// See nodes in Builder.cs class - that one does not work, is not complete,
// and was just some sort of experiment...
/// <summary>
/// Implements a builder that works by using CodeDom
/// </summary>
internal class CodeDomBuilder : Builder
{
/// <summary>
/// Initializes a new instance of the <see cref="CodeDomBuilder"/> class with a list of models to generate.
/// </summary>
/// <param name="typeModels">The list of models to generate.</param>
public CodeDomBuilder(IList<TypeModel> typeModels)
: base(typeModels, null)
{ }
/// <summary>
/// Outputs a generated model to a code namespace.
/// </summary>
/// <param name="ns">The code namespace.</param>
/// <param name="typeModel">The model to generate.</param>
public void Generate(CodeNamespace ns, TypeModel typeModel)
{
// what about USING?
// what about references?
if (typeModel.IsMixin)
{
var i = new CodeTypeDeclaration("I" + typeModel.ClrName)
{
IsInterface = true,
IsPartial = true,
Attributes = MemberAttributes.Public
};
i.BaseTypes.Add(typeModel.BaseType == null ? "IPublishedContent" : "I" + typeModel.BaseType.ClrName);
foreach (var mixinType in typeModel.DeclaringInterfaces)
i.BaseTypes.Add(mixinType.ClrName);
i.Comments.Add(new CodeCommentStatement($"Mixin content Type {typeModel.Id} with alias \"{typeModel.Alias}\""));
foreach (var propertyModel in typeModel.Properties)
{
var p = new CodeMemberProperty
{
Name = propertyModel.ClrName,
Type = new CodeTypeReference(propertyModel.ModelClrType),
Attributes = MemberAttributes.Public,
HasGet = true,
HasSet = false
};
i.Members.Add(p);
}
}
var c = new CodeTypeDeclaration(typeModel.ClrName)
{
IsClass = true,
IsPartial = true,
Attributes = MemberAttributes.Public
};
c.BaseTypes.Add(typeModel.BaseType == null ? "PublishedContentModel" : typeModel.BaseType.ClrName);
// if it's a missing it implements its own interface
if (typeModel.IsMixin)
c.BaseTypes.Add("I" + typeModel.ClrName);
// write the mixins, if any, as interfaces
// only if not a mixin because otherwise the interface already has them
if (typeModel.IsMixin == false)
foreach (var mixinType in typeModel.DeclaringInterfaces)
c.BaseTypes.Add("I" + mixinType.ClrName);
foreach (var mixin in typeModel.MixinTypes)
c.BaseTypes.Add("I" + mixin.ClrName);
c.Comments.Add(new CodeCommentStatement($"Content Type {typeModel.Id} with alias \"{typeModel.Alias}\""));
foreach (var propertyModel in typeModel.Properties)
{
var p = new CodeMemberProperty
{
Name = propertyModel.ClrName,
Type = new CodeTypeReference(propertyModel.ModelClrType),
Attributes = MemberAttributes.Public,
HasGet = true,
HasSet = false
};
p.GetStatements.Add(new CodeMethodReturnStatement( // return
new CodeMethodInvokeExpression(
new CodeMethodReferenceExpression(
new CodeThisReferenceExpression(), // this
"Value", // .Value
new[] // <T>
{
new CodeTypeReference(propertyModel.ModelClrType)
}),
new CodeExpression[] // ("alias")
{
new CodePrimitiveExpression(propertyModel.Alias)
})));
c.Members.Add(p);
}
}
}
}
@@ -1,238 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.ModelsBuilder.Building
{
/// <summary>
/// Implements code parsing.
/// </summary>
/// <remarks>Parses user's code and look for generator's instructions.</remarks>
internal class CodeParser
{
/// <summary>
/// Parses a set of file.
/// </summary>
/// <param name="files">A set of (filename,content) representing content to parse.</param>
/// <returns>The result of the code parsing.</returns>
/// <remarks>The set of files is a dictionary of name, content.</remarks>
public ParseResult Parse(IDictionary<string, string> files)
{
return Parse(files, Enumerable.Empty<PortableExecutableReference>());
}
/// <summary>
/// Parses a set of file.
/// </summary>
/// <param name="files">A set of (filename,content) representing content to parse.</param>
/// <param name="references">Assemblies to reference in compilations.</param>
/// <returns>The result of the code parsing.</returns>
/// <remarks>The set of files is a dictionary of name, content.</remarks>
public ParseResult Parse(IDictionary<string, string> files, IEnumerable<PortableExecutableReference> references)
{
SyntaxTree[] trees;
var compiler = new Compiler { References = references };
var compilation = compiler.GetCompilation("Umbraco.ModelsBuilder.Generated", files, out trees);
var disco = new ParseResult();
foreach (var tree in trees)
Parse(disco, compilation, tree);
return disco;
}
public ParseResult ParseWithReferencedAssemblies(IDictionary<string, string> files)
{
return Parse(files, ReferencedAssemblies.References);
}
private static void Parse(ParseResult disco, CSharpCompilation compilation, SyntaxTree tree)
{
var model = compilation.GetSemanticModel(tree);
//we quite probably have errors but that is normal
//var diags = model.GetDiagnostics();
var classDecls = tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>();
foreach (var classSymbol in classDecls.Select(x => model.GetDeclaredSymbol(x)))
{
ParseClassSymbols(disco, classSymbol);
var baseClassSymbol = classSymbol.BaseType;
if (baseClassSymbol != null)
//disco.SetContentBaseClass(SymbolDisplay.ToDisplayString(classSymbol), SymbolDisplay.ToDisplayString(baseClassSymbol));
disco.SetContentBaseClass(classSymbol.Name, baseClassSymbol.Name);
var interfaceSymbols = classSymbol.Interfaces;
disco.SetContentInterfaces(classSymbol.Name, //SymbolDisplay.ToDisplayString(classSymbol),
interfaceSymbols.Select(x => x.Name)); //SymbolDisplay.ToDisplayString(x)));
var hasCtor = classSymbol.Constructors
.Any(x =>
{
if (x.IsStatic) return false;
if (x.Parameters.Length != 1) return false;
var type1 = x.Parameters[0].Type;
var type2 = typeof (IPublishedContent);
return type1.ToDisplayString() == type2.FullName;
});
if (hasCtor)
disco.SetHasCtor(classSymbol.Name);
foreach (var propertySymbol in classSymbol.GetMembers().Where(x => x is IPropertySymbol))
ParsePropertySymbols(disco, classSymbol, propertySymbol);
foreach (var staticMethodSymbol in classSymbol.GetMembers().Where(x => x is IMethodSymbol))
ParseMethodSymbol(disco, classSymbol, staticMethodSymbol);
}
var interfaceDecls = tree.GetRoot().DescendantNodes().OfType<InterfaceDeclarationSyntax>();
foreach (var interfaceSymbol in interfaceDecls.Select(x => model.GetDeclaredSymbol(x)))
{
ParseClassSymbols(disco, interfaceSymbol);
var interfaceSymbols = interfaceSymbol.Interfaces;
disco.SetContentInterfaces(interfaceSymbol.Name, //SymbolDisplay.ToDisplayString(interfaceSymbol),
interfaceSymbols.Select(x => x.Name)); // SymbolDisplay.ToDisplayString(x)));
}
ParseAssemblySymbols(disco, compilation.Assembly);
}
private static void ParseClassSymbols(ParseResult disco, ISymbol symbol)
{
foreach (var attrData in symbol.GetAttributes())
{
var attrClassSymbol = attrData.AttributeClass;
// handle errors
if (attrClassSymbol is IErrorTypeSymbol) continue;
if (attrData.AttributeConstructor == null) continue;
var attrClassName = SymbolDisplay.ToDisplayString(attrClassSymbol);
switch (attrClassName)
{
case "Umbraco.ModelsBuilder.IgnorePropertyTypeAttribute":
var propertyAliasToIgnore = (string)attrData.ConstructorArguments[0].Value;
disco.SetIgnoredProperty(symbol.Name /*SymbolDisplay.ToDisplayString(symbol)*/, propertyAliasToIgnore);
break;
case "Umbraco.ModelsBuilder.RenamePropertyTypeAttribute":
var propertyAliasToRename = (string)attrData.ConstructorArguments[0].Value;
var propertyRenamed = (string)attrData.ConstructorArguments[1].Value;
disco.SetRenamedProperty(symbol.Name /*SymbolDisplay.ToDisplayString(symbol)*/, propertyAliasToRename, propertyRenamed);
break;
// that one causes all sorts of issues with references to Umbraco.Core in Roslyn
//case "Umbraco.Core.Models.PublishedContent.PublishedContentModelAttribute":
// var contentAliasToRename = (string)attrData.ConstructorArguments[0].Value;
// disco.SetRenamedContent(contentAliasToRename, symbol.Name /*SymbolDisplay.ToDisplayString(symbol)*/);
// break;
case "Umbraco.ModelsBuilder.ImplementContentTypeAttribute":
var contentAliasToRename = (string)attrData.ConstructorArguments[0].Value;
disco.SetRenamedContent(contentAliasToRename, symbol.Name, true /*SymbolDisplay.ToDisplayString(symbol)*/);
break;
}
}
}
private static void ParsePropertySymbols(ParseResult disco, ISymbol classSymbol, ISymbol symbol)
{
foreach (var attrData in symbol.GetAttributes())
{
var attrClassSymbol = attrData.AttributeClass;
// handle errors
if (attrClassSymbol is IErrorTypeSymbol) continue;
if (attrData.AttributeConstructor == null) continue;
var attrClassName = SymbolDisplay.ToDisplayString(attrClassSymbol);
// ReSharper disable once SwitchStatementMissingSomeCases
switch (attrClassName)
{
case "Umbraco.ModelsBuilder.ImplementPropertyTypeAttribute":
var propertyAliasToIgnore = (string)attrData.ConstructorArguments[0].Value;
disco.SetIgnoredProperty(classSymbol.Name /*SymbolDisplay.ToDisplayString(classSymbol)*/, propertyAliasToIgnore);
break;
}
}
}
private static void ParseAssemblySymbols(ParseResult disco, ISymbol symbol)
{
foreach (var attrData in symbol.GetAttributes())
{
var attrClassSymbol = attrData.AttributeClass;
// handle errors
if (attrClassSymbol is IErrorTypeSymbol) continue;
if (attrData.AttributeConstructor == null) continue;
var attrClassName = SymbolDisplay.ToDisplayString(attrClassSymbol);
switch (attrClassName)
{
case "Umbraco.ModelsBuilder.IgnoreContentTypeAttribute":
var contentAliasToIgnore = (string)attrData.ConstructorArguments[0].Value;
// see notes in IgnoreContentTypeAttribute
//var ignoreContent = (bool)attrData.ConstructorArguments[1].Value;
//var ignoreMixin = (bool)attrData.ConstructorArguments[1].Value;
//var ignoreMixinProperties = (bool)attrData.ConstructorArguments[1].Value;
disco.SetIgnoredContent(contentAliasToIgnore /*, ignoreContent, ignoreMixin, ignoreMixinProperties*/);
break;
case "Umbraco.ModelsBuilder.RenameContentTypeAttribute":
var contentAliasToRename = (string) attrData.ConstructorArguments[0].Value;
var contentRenamed = (string)attrData.ConstructorArguments[1].Value;
disco.SetRenamedContent(contentAliasToRename, contentRenamed, false);
break;
case "Umbraco.ModelsBuilder.ModelsBaseClassAttribute":
var modelsBaseClass = (INamedTypeSymbol) attrData.ConstructorArguments[0].Value;
if (modelsBaseClass is IErrorTypeSymbol)
throw new Exception($"Invalid base class type \"{modelsBaseClass.Name}\".");
disco.SetModelsBaseClassName(SymbolDisplay.ToDisplayString(modelsBaseClass));
break;
case "Umbraco.ModelsBuilder.ModelsNamespaceAttribute":
var modelsNamespace= (string) attrData.ConstructorArguments[0].Value;
disco.SetModelsNamespace(modelsNamespace);
break;
case "Umbraco.ModelsBuilder.ModelsUsingAttribute":
var usingNamespace = (string)attrData.ConstructorArguments[0].Value;
disco.SetUsingNamespace(usingNamespace);
break;
}
}
}
private static void ParseMethodSymbol(ParseResult disco, ISymbol classSymbol, ISymbol symbol)
{
var methodSymbol = symbol as IMethodSymbol;
if (methodSymbol == null
|| !methodSymbol.IsStatic
|| methodSymbol.IsGenericMethod
|| methodSymbol.ReturnsVoid
|| methodSymbol.IsExtensionMethod
|| methodSymbol.Parameters.Length != 1)
return;
var returnType = methodSymbol.ReturnType;
var paramSymbol = methodSymbol.Parameters[0];
var paramType = paramSymbol.Type;
// cannot do this because maybe the param type is ISomething and we don't have
// that type yet - will be generated - so cannot put any condition on it really
//const string iPublishedContent = "Umbraco.Core.Models.IPublishedContent";
//var implements = paramType.AllInterfaces.Any(x => x.ToDisplayString() == iPublishedContent);
//if (!implements)
// return;
disco.SetStaticMixinMethod(classSymbol.Name, methodSymbol.Name, returnType.Name, paramType.Name);
}
}
}
@@ -1,171 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Umbraco.Core.Configuration;
using Umbraco.ModelsBuilder.Configuration;
namespace Umbraco.ModelsBuilder.Building
{
// main Roslyn compiler
internal class Compiler
{
private readonly LanguageVersion _languageVersion;
public Compiler()
: this(UmbracoConfig.For.ModelsBuilder().LanguageVersion)
{ }
public Compiler(LanguageVersion languageVersion)
{
_languageVersion = languageVersion;
References = ReferencedAssemblies.References;
Debug = HttpContext.Current != null && HttpContext.Current.IsDebuggingEnabled;
}
// gets or sets the references
public IEnumerable<PortableExecutableReference> References { get; set; }
public bool Debug { get; set; }
// gets a compilation
public CSharpCompilation GetCompilation(string assemblyName, IDictionary<string, string> files)
{
SyntaxTree[] trees;
return GetCompilation(assemblyName, files, out trees);
}
// gets a compilation
// used by CodeParser to get a "compilation" of the existing files
public CSharpCompilation GetCompilation(string assemblyName, IDictionary<string, string> files, out SyntaxTree[] trees)
{
var options = new CSharpParseOptions(_languageVersion);
trees = files.Select(x =>
{
var text = x.Value;
var tree = CSharpSyntaxTree.ParseText(text, /*options:*/ options);
var diagnostic = tree.GetDiagnostics().FirstOrDefault(y => y.Severity == DiagnosticSeverity.Error);
if (diagnostic != null)
ThrowExceptionFromDiagnostic(x.Key, x.Value, diagnostic);
return tree;
}).ToArray();
var refs = References;
var compilationOptions = new CSharpCompilationOptions(
OutputKind.DynamicallyLinkedLibrary,
assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default,
optimizationLevel: Debug ? OptimizationLevel.Debug : OptimizationLevel.Release
);
var compilation = CSharpCompilation.Create(
assemblyName,
/*syntaxTrees:*/ trees,
/*references:*/ refs,
compilationOptions);
return compilation;
}
// compile files into a Dll
// used by ModelsBuilderBackOfficeController in [Live]Dll mode, to compile the models to disk
public void Compile(string assemblyName, IDictionary<string, string> files, string binPath)
{
var assemblyPath = Path.Combine(binPath, assemblyName + ".dll");
using (var stream = new FileStream(assemblyPath, FileMode.Create))
{
Compile(assemblyName, files, stream);
}
// this is how we'd create the pdb:
/*
var pdbPath = Path.Combine(binPath, assemblyName + ".pdb");
// create the compilation
var compilation = GetCompilation(assemblyName, files);
// check diagnostics for errors (not warnings)
foreach (var diag in compilation.GetDiagnostics().Where(x => x.Severity == DiagnosticSeverity.Error))
ThrowExceptionFromDiagnostic(files, diag);
// emit
var result = compilation.Emit(assemblyPath, pdbPath);
if (result.Success) return;
// deal with errors
var diagnostic = result.Diagnostics.First(x => x.Severity == DiagnosticSeverity.Error);
ThrowExceptionFromDiagnostic(files, diagnostic);
*/
}
// compile files into an assembly
public Assembly Compile(string assemblyName, IDictionary<string, string> files)
{
using (var stream = new MemoryStream())
{
Compile(assemblyName, files, stream);
return Assembly.Load(stream.GetBuffer());
}
}
// compile one file into an assembly
public Assembly Compile(string assemblyName, string path, string code)
{
using (var stream = new MemoryStream())
{
Compile(assemblyName, new Dictionary<string, string> { { path, code } }, stream);
return Assembly.Load(stream.GetBuffer());
}
}
// compiles files into a stream
public void Compile(string assemblyName, IDictionary<string, string> files, Stream stream)
{
// create the compilation
var compilation = GetCompilation(assemblyName, files);
// check diagnostics for errors (not warnings)
foreach (var diag in compilation.GetDiagnostics().Where(x => x.Severity == DiagnosticSeverity.Error))
ThrowExceptionFromDiagnostic(files, diag);
// emit
var result = compilation.Emit(stream);
if (result.Success) return;
// deal with errors
var diagnostic = result.Diagnostics.First(x => x.Severity == DiagnosticSeverity.Error);
ThrowExceptionFromDiagnostic(files, diagnostic);
}
// compiles one file into a stream
public void Compile(string assemblyName, string path, string code, Stream stream)
{
Compile(assemblyName, new Dictionary<string, string> { { path, code } }, stream);
}
private static void ThrowExceptionFromDiagnostic(IDictionary<string, string> files, Diagnostic diagnostic)
{
var message = diagnostic.GetMessage();
if (diagnostic.Location == Location.None)
throw new CompilerException(message);
var position = diagnostic.Location.GetLineSpan().StartLinePosition.Line + 1;
var path = diagnostic.Location.SourceTree.FilePath;
var code = files.ContainsKey(path) ? files[path] : string.Empty;
throw new CompilerException(message, path, code, position);
}
private static void ThrowExceptionFromDiagnostic(string path, string code, Diagnostic diagnostic)
{
var message = diagnostic.GetMessage();
if (diagnostic.Location == Location.None)
throw new CompilerException(message);
var position = diagnostic.Location.GetLineSpan().StartLinePosition.Line + 1;
throw new CompilerException(message, path, code, position);
}
}
}
@@ -1,25 +0,0 @@
using System;
namespace Umbraco.ModelsBuilder.Building
{
public class CompilerException : Exception
{
public CompilerException(string message)
: base(message)
{ }
public CompilerException(string message, string path, string sourceCode, int line)
: base(message)
{
Path = path;
SourceCode = sourceCode;
Line = line;
}
public string Path { get; } = string.Empty;
public string SourceCode { get; } = string.Empty;
public int Line { get; } = -1;
}
}
@@ -1,275 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Umbraco.ModelsBuilder.Building
{
/// <summary>
/// Contains the result of a code parsing.
/// </summary>
internal class ParseResult
{
// "alias" is the umbraco alias
// content "name" is the complete name eg Foo.Bar.Name
// property "name" is just the local name
// see notes in IgnoreContentTypeAttribute
private readonly HashSet<string> _ignoredContent
= new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
//private readonly HashSet<string> _ignoredMixin
// = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
//private readonly HashSet<string> _ignoredMixinProperties
// = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
private readonly Dictionary<string, string> _renamedContent
= new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
private readonly HashSet<string> _withImplementContent
= new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
private readonly Dictionary<string, HashSet<string>> _ignoredProperty
= new Dictionary<string, HashSet<string>>();
private readonly Dictionary<string, Dictionary<string, string>> _renamedProperty
= new Dictionary<string, Dictionary<string, string>>();
private readonly Dictionary<string, string> _contentBase
= new Dictionary<string, string>();
private readonly Dictionary<string, string[]> _contentInterfaces
= new Dictionary<string, string[]>();
private readonly List<string> _usingNamespaces
= new List<string>();
private readonly Dictionary<string, List<StaticMixinMethodInfo>> _staticMixins
= new Dictionary<string, List<StaticMixinMethodInfo>>();
private readonly HashSet<string> _withCtor
= new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
public static readonly ParseResult Empty = new ParseResult();
private class StaticMixinMethodInfo
{
public StaticMixinMethodInfo(string contentName, string methodName, string returnType, string paramType)
{
ContentName = contentName;
MethodName = methodName;
//ReturnType = returnType;
//ParamType = paramType;
}
// short name eg Type1
public string ContentName { get; private set; }
// short name eg GetProp1
public string MethodName { get; private set; }
// those types cannot be FQ because when parsing, some of them
// might not exist since we're generating them... and so prob.
// that info is worthless - not using it anyway at the moment...
//public string ReturnType { get; private set; }
//public string ParamType { get; private set; }
}
#region Declare
// content with that alias should not be generated
// alias can end with a * (wildcard)
public void SetIgnoredContent(string contentAlias /*, bool ignoreContent, bool ignoreMixin, bool ignoreMixinProperties*/)
{
//if (ignoreContent)
_ignoredContent.Add(contentAlias);
//if (ignoreMixin)
// _ignoredMixin.Add(contentAlias);
//if (ignoreMixinProperties)
// _ignoredMixinProperties.Add(contentAlias);
}
// content with that alias should be generated with a different name
public void SetRenamedContent(string contentAlias, string contentName, bool withImplement)
{
_renamedContent[contentAlias] = contentName;
if (withImplement)
_withImplementContent.Add(contentAlias);
}
// property with that alias should not be generated
// applies to content name and any content that implements it
// here, contentName may be an interface
// alias can end with a * (wildcard)
public void SetIgnoredProperty(string contentName, string propertyAlias)
{
HashSet<string> ignores;
if (!_ignoredProperty.TryGetValue(contentName, out ignores))
ignores = _ignoredProperty[contentName] = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
ignores.Add(propertyAlias);
}
// property with that alias should be generated with a different name
// applies to content name and any content that implements it
// here, contentName may be an interface
public void SetRenamedProperty(string contentName, string propertyAlias, string propertyName)
{
Dictionary<string, string> renames;
if (!_renamedProperty.TryGetValue(contentName, out renames))
renames = _renamedProperty[contentName] = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
renames[propertyAlias] = propertyName;
}
// content with that name has a base class so no need to generate one
public void SetContentBaseClass(string contentName, string baseName)
{
if (baseName.ToLowerInvariant() != "object")
_contentBase[contentName] = baseName;
}
// content with that name implements the interfaces
public void SetContentInterfaces(string contentName, IEnumerable<string> interfaceNames)
{
_contentInterfaces[contentName] = interfaceNames.ToArray();
}
public void SetModelsBaseClassName(string modelsBaseClassName)
{
ModelsBaseClassName = modelsBaseClassName;
}
public void SetModelsNamespace(string modelsNamespace)
{
ModelsNamespace = modelsNamespace;
}
public void SetUsingNamespace(string usingNamespace)
{
_usingNamespaces.Add(usingNamespace);
}
public void SetStaticMixinMethod(string contentName, string methodName, string returnType, string paramType)
{
if (!_staticMixins.ContainsKey(contentName))
_staticMixins[contentName] = new List<StaticMixinMethodInfo>();
_staticMixins[contentName].Add(new StaticMixinMethodInfo(contentName, methodName, returnType, paramType));
}
public void SetHasCtor(string contentName)
{
_withCtor.Add(contentName);
}
#endregion
#region Query
public bool IsIgnored(string contentAlias)
{
return IsContentOrMixinIgnored(contentAlias, _ignoredContent);
}
//public bool IsMixinIgnored(string contentAlias)
//{
// return IsContentOrMixinIgnored(contentAlias, _ignoredMixin);
//}
//public bool IsMixinPropertiesIgnored(string contentAlias)
//{
// return IsContentOrMixinIgnored(contentAlias, _ignoredMixinProperties);
//}
private static bool IsContentOrMixinIgnored(string contentAlias, HashSet<string> ignored)
{
if (ignored.Contains(contentAlias)) return true;
return ignored
.Where(x => x.EndsWith("*"))
.Select(x => x.Substring(0, x.Length - 1))
.Any(x => contentAlias.StartsWith(x, StringComparison.InvariantCultureIgnoreCase));
}
public bool HasContentBase(string contentName)
{
return _contentBase.ContainsKey(contentName);
}
public bool IsContentRenamed(string contentAlias)
{
return _renamedContent.ContainsKey(contentAlias);
}
public bool HasContentImplement(string contentAlias)
{
return _withImplementContent.Contains(contentAlias);
}
public string ContentClrName(string contentAlias)
{
string name;
return (_renamedContent.TryGetValue(contentAlias, out name)) ? name : null;
}
public bool IsPropertyIgnored(string contentName, string propertyAlias)
{
HashSet<string> ignores;
if (_ignoredProperty.TryGetValue(contentName, out ignores))
{
if (ignores.Contains(propertyAlias)) return true;
if (ignores
.Where(x => x.EndsWith("*"))
.Select(x => x.Substring(0, x.Length - 1))
.Any(x => propertyAlias.StartsWith(x, StringComparison.InvariantCultureIgnoreCase)))
return true;
}
string baseName;
if (_contentBase.TryGetValue(contentName, out baseName)
&& IsPropertyIgnored(baseName, propertyAlias)) return true;
string[] interfaceNames;
if (_contentInterfaces.TryGetValue(contentName, out interfaceNames)
&& interfaceNames.Any(interfaceName => IsPropertyIgnored(interfaceName, propertyAlias))) return true;
return false;
}
public string PropertyClrName(string contentName, string propertyAlias)
{
Dictionary<string, string> renames;
string name;
if (_renamedProperty.TryGetValue(contentName, out renames)
&& renames.TryGetValue(propertyAlias, out name)) return name;
string baseName;
if (_contentBase.TryGetValue(contentName, out baseName)
&& null != (name = PropertyClrName(baseName, propertyAlias))) return name;
string[] interfaceNames;
if (_contentInterfaces.TryGetValue(contentName, out interfaceNames)
&& null != (name = interfaceNames
.Select(interfaceName => PropertyClrName(interfaceName, propertyAlias))
.FirstOrDefault(x => x != null))) return name;
return null;
}
public bool HasModelsBaseClassName
{
get { return !string.IsNullOrWhiteSpace(ModelsBaseClassName); }
}
public string ModelsBaseClassName { get; private set; }
public bool HasModelsNamespace
{
get { return !string.IsNullOrWhiteSpace(ModelsNamespace); }
}
public string ModelsNamespace { get; private set; }
public IEnumerable<string> UsingNamespaces
{
get { return _usingNamespaces; }
}
public IEnumerable<string> StaticMixinMethods(string contentName)
{
return _staticMixins.ContainsKey(contentName)
? _staticMixins[contentName].Select(x => x.MethodName)
: Enumerable.Empty<string>() ;
}
public bool HasCtor(string contentName)
{
return _withCtor.Contains(contentName);
}
#endregion
}
}
@@ -41,11 +41,6 @@ namespace Umbraco.ModelsBuilder.Building
/// </summary>
public string ClrTypeName;
/// <summary>
/// Gets a value indicating whether this property should be excluded from generation.
/// </summary>
public bool IsIgnored;
/// <summary>
/// Gets the generation errors for the property.
/// </summary>
@@ -3,8 +3,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.ModelsBuilder.Api;
using Umbraco.ModelsBuilder.Configuration;
namespace Umbraco.ModelsBuilder.Building
@@ -19,9 +20,8 @@ namespace Umbraco.ModelsBuilder.Building
/// and the result of code parsing.
/// </summary>
/// <param name="typeModels">The list of models to generate.</param>
/// <param name="parseResult">The result of code parsing.</param>
public TextBuilder(IList<TypeModel> typeModels, ParseResult parseResult)
: base(typeModels, parseResult)
public TextBuilder(IList<TypeModel> typeModels)
: base(typeModels)
{ }
/// <summary>
@@ -29,21 +29,22 @@ namespace Umbraco.ModelsBuilder.Building
/// the result of code parsing, and a models namespace.
/// </summary>
/// <param name="typeModels">The list of models to generate.</param>
/// <param name="parseResult">The result of code parsing.</param>
/// <param name="modelsNamespace">The models namespace.</param>
public TextBuilder(IList<TypeModel> typeModels, ParseResult parseResult, string modelsNamespace)
: base(typeModels, parseResult, modelsNamespace)
public TextBuilder(IList<TypeModel> typeModels, string modelsNamespace)
: base(typeModels, modelsNamespace)
{ }
// internal for unit tests only
internal TextBuilder()
{ }
private static Config Config => Current.Configs.ModelsBuilder();
/// <summary>
/// Outputs a generated model to a string builder.
/// </summary>
/// <param name="sb">The string builder.</param>
/// <param name="typeModel">The model to generate.</param>
/// Outputs a generated model to a string builder.
/// </summary>
/// <param name="sb">The string builder.</param>
/// <param name="typeModel">The model to generate.</param>
public void Generate(StringBuilder sb, TypeModel typeModel)
{
WriteHeader(sb);
@@ -97,6 +98,20 @@ namespace Umbraco.ModelsBuilder.Building
TextHeaderWriter.WriteHeader(sb);
}
// writes an attribute that identifies code generated by a tool
// (helps reduce warnings, tools such as FxCop use it)
// see https://github.com/zpqrtbnk/Zbu.ModelsBuilder/issues/107
// see https://docs.microsoft.com/en-us/dotnet/api/system.codedom.compiler.generatedcodeattribute
// see https://blogs.msdn.microsoft.com/codeanalysis/2007/04/27/correct-usage-of-the-compilergeneratedattribute-and-the-generatedcodeattribute/
//
// note that the blog post above clearly states that "Nor should it be applied at the type level if the type being generated is a partial class."
// and since our models are partial classes, we have to apply the attribute against the individual members, not the class itself.
//
private static void WriteGeneratedCodeAttribute(StringBuilder sb, string tabs)
{
sb.AppendFormat("{0}[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"Umbraco.ModelsBuilder\", \"{1}\")]\n", tabs, ApiVersion.Current.Version);
}
private void WriteContentType(StringBuilder sb, TypeModel type)
{
string sep;
@@ -104,11 +119,11 @@ namespace Umbraco.ModelsBuilder.Building
if (type.IsMixin)
{
// write the interface declaration
sb.AppendFormat("\t// Mixin content Type {0} with alias \"{1}\"\n", type.Id, type.Alias);
sb.AppendFormat("\t// Mixin Content Type with alias \"{0}\"\n", type.Alias);
if (!string.IsNullOrWhiteSpace(type.Name))
sb.AppendFormat("\t/// <summary>{0}</summary>\n", XmlCommentString(type.Name));
sb.AppendFormat("\tpublic partial interface I{0}", type.ClrName);
var implements = type.BaseType == null || type.BaseType.IsContentIgnored
var implements = type.BaseType == null
? (type.HasBase ? null : (type.IsElement ? "PublishedElement" : "PublishedContent"))
: type.BaseType.ClrName;
if (implements != null)
@@ -126,7 +141,7 @@ namespace Umbraco.ModelsBuilder.Building
// write the properties - only the local (non-ignored) ones, we're an interface
var more = false;
foreach (var prop in type.Properties.Where(x => !x.IsIgnored).OrderBy(x => x.ClrName))
foreach (var prop in type.Properties.OrderBy(x => x.ClrName))
{
if (more) sb.Append("\n");
more = true;
@@ -137,8 +152,6 @@ namespace Umbraco.ModelsBuilder.Building
}
// write the class declaration
if (type.IsRenamed)
sb.AppendFormat("\t// Content Type {0} with alias \"{1}\"\n", type.Id, type.Alias);
if (!string.IsNullOrWhiteSpace(type.Name))
sb.AppendFormat("\t/// <summary>{0}</summary>\n", XmlCommentString(type.Name));
// cannot do it now. see note in ImplementContentTypeAttribute
@@ -148,7 +161,7 @@ namespace Umbraco.ModelsBuilder.Building
sb.AppendFormat("\tpublic partial class {0}", type.ClrName);
var inherits = type.HasBase
? null // has its own base already
: (type.BaseType == null || type.BaseType.IsContentIgnored
: (type.BaseType == null
? GetModelsBaseClassName(type)
: type.BaseType.ClrName);
if (inherits != null)
@@ -178,22 +191,25 @@ namespace Umbraco.ModelsBuilder.Building
// as 'new' since parent has its own - or maybe not - disable warning
sb.Append("\t\t// helpers\n");
sb.Append("#pragma warning disable 0109 // new is redundant\n");
WriteGeneratedCodeAttribute(sb, "\t\t");
sb.AppendFormat("\t\tpublic new const string ModelTypeAlias = \"{0}\";\n",
type.Alias);
var itemType = type.IsElement ? TypeModel.ItemTypes.Content : type.ItemType; // fixme
WriteGeneratedCodeAttribute(sb, "\t\t");
sb.AppendFormat("\t\tpublic new const PublishedItemType ModelItemType = PublishedItemType.{0};\n",
itemType);
WriteGeneratedCodeAttribute(sb, "\t\t");
sb.Append("\t\tpublic new static PublishedContentType GetModelContentType()\n");
sb.Append("\t\t\t=> PublishedModelUtility.GetModelContentType(ModelItemType, ModelTypeAlias);\n");
WriteGeneratedCodeAttribute(sb, "\t\t");
sb.AppendFormat("\t\tpublic static PublishedPropertyType GetModelPropertyType<TValue>(Expression<Func<{0}, TValue>> selector)\n",
type.ClrName);
sb.Append("\t\t\t=> PublishedModelUtility.GetModelPropertyType(GetModelContentType(), selector);\n");
sb.Append("#pragma warning restore 0109\n\n");
// write the ctor
if (!type.HasCtor)
sb.AppendFormat("\t\t// ctor\n\t\tpublic {0}(IPublished{1} content)\n\t\t\t: base(content)\n\t\t{{ }}\n\n",
type.ClrName, type.IsElement ? "Element" : "Content");
sb.AppendFormat("\t\t// ctor\n\t\tpublic {0}(IPublished{1} content)\n\t\t\t: base(content)\n\t\t{{ }}\n\n",
type.ClrName, type.IsElement ? "Element" : "Content");
// write the properties
sb.Append("\t\t// properties\n");
@@ -205,10 +221,10 @@ namespace Umbraco.ModelsBuilder.Building
private void WriteContentTypeProperties(StringBuilder sb, TypeModel type)
{
var staticMixinGetters = UmbracoConfig.For.ModelsBuilder().StaticMixinGetters;
var staticMixinGetters = true;
// write the properties
foreach (var prop in type.Properties.Where(x => !x.IsIgnored).OrderBy(x => x.ClrName))
foreach (var prop in type.Properties.OrderBy(x => x.ClrName))
WriteProperty(sb, type, prop, staticMixinGetters && type.IsMixin ? type.ClrName : null);
// no need to write the parent properties since we inherit from the parent
@@ -217,7 +233,7 @@ namespace Umbraco.ModelsBuilder.Building
// write the mixins properties
foreach (var mixinType in type.ImplementingInterfaces.OrderBy(x => x.ClrName))
foreach (var prop in mixinType.Properties.Where(x => !x.IsIgnored).OrderBy(x => x.ClrName))
foreach (var prop in mixinType.Properties.OrderBy(x => x.ClrName))
if (staticMixinGetters)
WriteMixinProperty(sb, prop, mixinType.ClrName);
else
@@ -242,6 +258,7 @@ namespace Umbraco.ModelsBuilder.Building
sb.Append("\t\t///</summary>\n");
}
WriteGeneratedCodeAttribute(sb, "\t\t");
sb.AppendFormat("\t\t[ImplementPropertyType(\"{0}\")]\n", property.Alias);
sb.Append("\t\tpublic ");
@@ -256,7 +273,7 @@ namespace Umbraco.ModelsBuilder.Building
private static string MixinStaticGetterName(string clrName)
{
return string.Format(UmbracoConfig.For.ModelsBuilder().StaticMixinGetterPattern, clrName);
return string.Format("Get{0}", clrName);
}
private void WriteProperty(StringBuilder sb, TypeModel type, PropertyModel property, string mixinClrName = null)
@@ -300,6 +317,7 @@ namespace Umbraco.ModelsBuilder.Building
sb.Append("\t\t///</summary>\n");
}
WriteGeneratedCodeAttribute(sb, "\t\t");
sb.AppendFormat("\t\t[ImplementPropertyType(\"{0}\")]\n", property.Alias);
if (mixinStatic)
@@ -343,6 +361,7 @@ namespace Umbraco.ModelsBuilder.Building
if (!string.IsNullOrWhiteSpace(property.Name))
sb.AppendFormat("\t\t/// <summary>Static getter for {0}</summary>\n", XmlCommentString(property.Name));
WriteGeneratedCodeAttribute(sb, "\t\t");
sb.Append("\t\tpublic static ");
WriteClrType(sb, property.ClrTypeName);
sb.AppendFormat(" {0}(I{1} that) => that.Value",
@@ -397,6 +416,7 @@ namespace Umbraco.ModelsBuilder.Building
if (!string.IsNullOrWhiteSpace(property.Name))
sb.AppendFormat("\t\t/// <summary>{0}</summary>\n", XmlCommentString(property.Name));
WriteGeneratedCodeAttribute(sb, "\t\t");
sb.Append("\t\t");
WriteClrType(sb, property.ClrTypeName);
sb.AppendFormat(" {0} {{ get; }}\n",
@@ -461,7 +481,7 @@ namespace Umbraco.ModelsBuilder.Building
s = Regex.Replace(s, @"\{(.*)\}\[\*\]", m => ModelsMap[m.Groups[1].Value + "[]"]);
// takes care eg of "System.Int32" vs. "int"
if (TypesMap.TryGetValue(s.ToLowerInvariant(), out string typeName))
if (TypesMap.TryGetValue(s, out string typeName))
{
sb.Append(typeName);
return;
@@ -481,6 +501,11 @@ namespace Umbraco.ModelsBuilder.Building
typeName = typeName.Substring(p + 1);
typeUsing = x;
}
else if (x == ModelsNamespace) // that one is used by default
{
typeName = typeName.Substring(p + 1);
typeUsing = ModelsNamespace;
}
}
// nested types *after* using
@@ -531,24 +556,24 @@ namespace Umbraco.ModelsBuilder.Building
return s.Replace('<', '{').Replace('>', '}').Replace('\r', ' ').Replace('\n', ' ');
}
private static readonly IDictionary<string, string> TypesMap = new Dictionary<string, string>
private static readonly IDictionary<string, string> TypesMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "system.int16", "short" },
{ "system.int32", "int" },
{ "system.int64", "long" },
{ "system.string", "string" },
{ "system.object", "object" },
{ "system.boolean", "bool" },
{ "system.void", "void" },
{ "system.char", "char" },
{ "system.byte", "byte" },
{ "system.uint16", "ushort" },
{ "system.uint32", "uint" },
{ "system.uint64", "ulong" },
{ "system.sbyte", "sbyte" },
{ "system.single", "float" },
{ "system.double", "double" },
{ "system.decimal", "decimal" }
{ "System.Int16", "short" },
{ "System.Int32", "int" },
{ "System.Int64", "long" },
{ "System.String", "string" },
{ "System.Object", "object" },
{ "System.Boolean", "bool" },
{ "System.Void", "void" },
{ "System.Char", "char" },
{ "System.Byte", "byte" },
{ "System.UInt16", "ushort" },
{ "System.UInt32", "uint" },
{ "System.UInt64", "ulong" },
{ "System.SByte", "sbyte" },
{ "System.Single", "float" },
{ "System.Double", "double" },
{ "System.Decimal", "decimal" }
};
}
}

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