Compare commits
133 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 30f63eefb3 | |||
| 6114193fd5 | |||
| 82420605ef | |||
| 3bddceb17b | |||
| 27fab61646 | |||
| 05f8870424 | |||
| 4a829154db | |||
| f8073f429f | |||
| 04d37c590b | |||
| 7753993987 | |||
| 8f48da8bb0 | |||
| aba325e109 | |||
| 2dd31f0f05 | |||
| d42d96e166 | |||
| 3571c238b4 | |||
| 2087332b69 | |||
| dc71f9cd5e | |||
| 99ed4d6cb9 | |||
| 3646cfb47e | |||
| 1b7ce8bcde | |||
| 1c7b374c42 | |||
| 7100a00ef1 | |||
| df04100ff6 | |||
| b893df035b | |||
| 67c6146f96 | |||
| 13aa615745 | |||
| b8c0d4c4ea | |||
| 6992b0319a | |||
| d1111009e3 | |||
| 6c624ca08a | |||
| 1722831bf5 | |||
| 5291558b23 | |||
| a3f6fb78f5 | |||
| 736b3565d0 | |||
| ed782998ef | |||
| 31d980b0c5 | |||
| 9f6e4d4fd5 | |||
| d90658d814 | |||
| 7fa8f04b11 | |||
| bf2232258e | |||
| 8a133938e6 | |||
| c1b3f1977d | |||
| f086156d48 | |||
| 7080013dd6 | |||
| 5bbb44479f | |||
| 9e55f5835c | |||
| b080825bb2 | |||
| 8bb696bf9a | |||
| 55e8451513 | |||
| 7e4e2a1d5d | |||
| 6de76571d7 | |||
| 0f535f233e | |||
| 56da13fa79 | |||
| 79d4956b75 | |||
| 9acfd8f5d2 | |||
| 0b530ce181 | |||
| 402835d72d | |||
| 08d579ec87 | |||
| 8b92755487 | |||
| 01b48107f3 | |||
| a546803970 | |||
| 96c28c2611 | |||
| 65a22417f7 | |||
| 6c271e7af9 | |||
| a85cafe7ab | |||
| 41d91ae791 | |||
| dca5a26fe4 | |||
| 7e8f6d391f | |||
| 7aa00ee6e0 | |||
| 2e027e6195 | |||
| a9c5877e5b | |||
| 337ba4ef34 | |||
| 0f32c2d680 | |||
| 96a18ec8e9 | |||
| 65c39a3117 | |||
| 15150f9a16 | |||
| 259879c964 | |||
| ed87789abe | |||
| 09492fa779 | |||
| 8122c0b352 | |||
| 28f0ab1001 | |||
| 266f82b6c5 | |||
| 813a8956d3 | |||
| 0a8fa2be4d | |||
| 6e347dd32c | |||
| 33c9e2b58d | |||
| 16f8f6036c | |||
| 76b696e3bf | |||
| 7cadbb6398 | |||
| bf22399aba | |||
| 0b9a3ef68a | |||
| f8d6c7e7d0 | |||
| 90ba9a1a3a | |||
| 6815731da1 | |||
| 52dce66598 | |||
| 255fec84bd | |||
| 9142314d39 | |||
| 27164093ea | |||
| 67312d03d0 | |||
| ad9ae867c0 | |||
| af287c387e | |||
| acf10eeef0 | |||
| 44b90bd4f3 | |||
| 3e558af18f | |||
| 3774d4fc62 | |||
| a24acdb8ce | |||
| f91d5b53c1 | |||
| c053adc9b2 | |||
| e3bc588164 | |||
| 392319d26c | |||
| 584638977c | |||
| be8632db1c | |||
| 094514b91a | |||
| 3c43f4f3c5 | |||
| 12f9392db9 | |||
| d787cb6ad9 | |||
| db02c3b73c | |||
| a10214d82b | |||
| bc61054931 | |||
| 0becdccb68 | |||
| cee92518ea | |||
| a34a8e180d | |||
| f9f48753de | |||
| c9af13df78 | |||
| f66b456d7c | |||
| 6d722c5591 | |||
| 9ed9aef1d3 | |||
| 0cc398130d | |||
| 927f48985e | |||
| 3b31b92f1f | |||
| aaf725a498 | |||
| 36aa166a95 | |||
| e7754d313e |
@@ -24,7 +24,7 @@
|
||||
<dependency id="Microsoft.Owin.Security.OAuth" version="[3.0.1, 4.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[3.0.1, 4.0.0)" />
|
||||
<dependency id="MiniProfiler" version="[2.1.0, 3.0.0)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.4.9, 2.0.0)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.4.9.5, 2.0.0)" />
|
||||
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
|
||||
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.9.8, 7.0.0)" />
|
||||
@@ -37,9 +37,8 @@
|
||||
<dependency id="ImageProcessor" version="[2.5.2, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.8.2, 5.0.0)" />
|
||||
<dependency id="semver" version="[2.0.4, 3.0.0)" />
|
||||
<dependency id="UrlRewritingNet" version="[2.0.7, 3.0.0)" />
|
||||
<!-- Markdown can not be updated due to: https://github.com/hey-red/markdownsharp/issues/71#issuecomment-233585487 -->
|
||||
<dependency id="Markdown" version="[1.14.7, 2.0.0)" />
|
||||
<dependency id="Markdown" version="[1.14.7, 2.0.0)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.6.0, 5.0.0)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
|
||||
@@ -41,16 +41,6 @@
|
||||
views/dashboard/developer/examinemanagement.html
|
||||
</control>
|
||||
</tab>
|
||||
<tab caption="Health Check" xdt:Transform="InsertIfMissing" xdt:Locator="Match(caption)">
|
||||
<control>
|
||||
views/dashboard/developer/healthcheck.html
|
||||
</control>
|
||||
</tab>
|
||||
<tab caption="Redirect URL Management" xdt:Transform="InsertIfMissing" xdt:Locator="Match(caption)">
|
||||
<control>
|
||||
views/dashboard/developer/redirecturls.html
|
||||
</control>
|
||||
</tab>
|
||||
</section>
|
||||
|
||||
<section alias="StartupMediaDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
|
||||
@@ -80,4 +70,26 @@
|
||||
<tab caption="Change Password" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
<tab caption="Last Edits" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
</section>
|
||||
|
||||
<section alias="RedirectUrlManagement" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
|
||||
<areas>
|
||||
<area>content</area>
|
||||
</areas>
|
||||
<tab caption="Redirect URL Management">
|
||||
<control>
|
||||
views/dashboard/developer/redirecturls.html
|
||||
</control>
|
||||
</tab>
|
||||
</section>
|
||||
|
||||
<section alias="UmbracoHealthCheck" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
|
||||
<areas>
|
||||
<area>developer</area>
|
||||
</areas>
|
||||
<tab caption="Health Check">
|
||||
<control>
|
||||
views/dashboard/developer/healthcheck.html
|
||||
</control>
|
||||
</tab>
|
||||
</section>
|
||||
</dashBoard>
|
||||
@@ -53,7 +53,6 @@ if ($project) {
|
||||
if(Test-Path $umbracoBinFolder\umbraco.providers.dll) { Remove-Item $umbracoBinFolder\umbraco.providers.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Umbraco.Web.UI.dll) { Remove-Item $umbracoBinFolder\Umbraco.Web.UI.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\UmbracoExamine.dll) { Remove-Item $umbracoBinFolder\UmbracoExamine.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\UrlRewritingNet.UrlRewriter.dll) { Remove-Item $umbracoBinFolder\UrlRewritingNet.UrlRewriter.dll -Force -Confirm:$false }
|
||||
|
||||
# Delete files Umbraco depends upon
|
||||
$amd64Folder = Join-Path $umbracoBinFolder "amd64"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.6.0
|
||||
alpha072
|
||||
alpha075
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SQLCE4Umbraco</RootNamespace>
|
||||
<AssemblyName>SQLCE4Umbraco</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
@@ -49,9 +49,11 @@
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
|
||||
@@ -32,4 +32,4 @@
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" /></startup></configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /></startup></configuration>
|
||||
|
||||
+1
-1
@@ -12,4 +12,4 @@ using System.Resources;
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.6.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.0-alpha072")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.0-alpha075")]
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
internal enum ContentXmlStorage
|
||||
{
|
||||
Default,
|
||||
AspNetTemp,
|
||||
EnvironmentTemp
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
internal static class CoreDebugExtensions
|
||||
{
|
||||
private static CoreDebug _coreDebug;
|
||||
|
||||
public static CoreDebug CoreDebug(this UmbracoConfig config)
|
||||
{
|
||||
return _coreDebug ?? (_coreDebug = new CoreDebug());
|
||||
}
|
||||
}
|
||||
|
||||
internal class CoreDebug
|
||||
{
|
||||
public CoreDebug()
|
||||
{
|
||||
var appSettings = System.Configuration.ConfigurationManager.AppSettings;
|
||||
LogUncompletedScopes = string.Equals("true", appSettings["Umbraco.CoreDebug.LogUncompletedScopes"], StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
// when true, Scope logs the stack trace for any scope that gets disposed without being completed.
|
||||
// this helps troubleshooting rogue scopes that we forget to complete
|
||||
public bool LogUncompletedScopes { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -517,12 +517,25 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
|
||||
internal static bool ContentCacheXmlStoredInCodeGen
|
||||
{
|
||||
get { return ContentCacheXmlStorageLocation == ContentXmlStorage.AspNetTemp; }
|
||||
}
|
||||
|
||||
internal static ContentXmlStorage ContentCacheXmlStorageLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
//defaults to false
|
||||
return ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLUseLocalTemp")
|
||||
&& bool.Parse(ConfigurationManager.AppSettings["umbracoContentXMLUseLocalTemp"]); //default to false
|
||||
if (ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLStorage"))
|
||||
{
|
||||
return Enum<ContentXmlStorage>.Parse(ConfigurationManager.AppSettings["umbracoContentXMLStorage"]);
|
||||
}
|
||||
if (ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLUseLocalTemp"))
|
||||
{
|
||||
return bool.Parse(ConfigurationManager.AppSettings["umbracoContentXMLUseLocalTemp"])
|
||||
? ContentXmlStorage.AspNetTemp
|
||||
: ContentXmlStorage.Default;
|
||||
}
|
||||
return ContentXmlStorage.Default;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -177,6 +177,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return GetOptionalTextElement("EnableInheritedMediaTypes", true); }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("EnablePropertyValueConverters")]
|
||||
internal InnerTextConfigurationElement<bool> EnablePropertyValueConverters
|
||||
{
|
||||
get { return GetOptionalTextElement("EnablePropertyValueConverters", false); }
|
||||
}
|
||||
|
||||
string IContentSection.NotificationEmailAddress
|
||||
{
|
||||
get { return Notifications.NotificationEmailAddress; }
|
||||
@@ -326,5 +332,9 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
get { return EnableInheritedMediaTypes; }
|
||||
}
|
||||
bool IContentSection.EnablePropertyValueConverters
|
||||
{
|
||||
get { return EnablePropertyValueConverters; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,5 +69,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
bool EnableInheritedDocumentTypes { get; }
|
||||
|
||||
bool EnableInheritedMediaTypes { get; }
|
||||
|
||||
bool EnablePropertyValueConverters { get; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// Gets the version comment (like beta or RC).
|
||||
/// </summary>
|
||||
/// <value>The version comment.</value>
|
||||
public static string CurrentComment { get { return "alpha072"; } }
|
||||
public static string CurrentComment { get { return "alpha075"; } }
|
||||
|
||||
// Get the version of the umbraco.dll by looking at a class in that dll
|
||||
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
|
||||
|
||||
@@ -289,11 +289,14 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
[Obsolete("GUIDs are no longer used to reference Property Editors, use the Alias constant instead. This will be removed in future versions")]
|
||||
public const string RelatedLinks = "71B8AD1A-8DC2-425C-B6B8-FAA158075E63";
|
||||
|
||||
[Obsolete("This is an obsoleted picker, use RelatedLinks2Alias instead")]
|
||||
public const string RelatedLinksAlias = "Umbraco.RelatedLinks";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the Related Links datatype.
|
||||
/// Alias for the Related Links property editor.
|
||||
/// </summary>
|
||||
public const string RelatedLinksAlias = "Umbraco.RelatedLinks";
|
||||
public const string RelatedLinks2Alias = "Umbraco.RelatedLinks2";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for the Slider datatype.
|
||||
|
||||
@@ -296,5 +296,21 @@ namespace Umbraco.Core
|
||||
&& list1Groups.All(g => g.Count() == list2Groups[g.Key].Count());
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// Returns the items of the given enumerable as a pure enumerable.
|
||||
/// <remarks>
|
||||
/// When quering lists using methods such as <see cref="M:List.Where"/>, the result, despite appearing to look like and quack like an
|
||||
/// <see cref="T:Enumerable{T}"/> the type is actually an instance of <see cref="T:System.Linq.Enumerable.WhereEnumerableIterator"/>
|
||||
/// </remarks>
|
||||
/// </summary>
|
||||
///<param name="source">The item to find.</param>
|
||||
///<returns>The index of the first matching item, or -1 if the item was not found.</returns>
|
||||
internal static IEnumerable<T> Yield<T>(this IEnumerable<T> source)
|
||||
{
|
||||
foreach (var element in source)
|
||||
{
|
||||
yield return element;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a guid-based entity identifier.
|
||||
/// </summary>
|
||||
[TypeConverter(typeof(UdiTypeConverter))]
|
||||
public class GuidUdi : Udi
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -12,25 +12,18 @@ namespace Umbraco.Core.IO
|
||||
public class FileSystemProviderManager
|
||||
{
|
||||
private readonly FileSystemProvidersSection _config;
|
||||
private readonly WeakSet<ShadowWrapper> _wrappers = new WeakSet<ShadowWrapper>();
|
||||
private readonly ConcurrentSet<ShadowWrapper> _wrappers = new ConcurrentSet<ShadowWrapper>();
|
||||
|
||||
// actual well-known filesystems returned by properties
|
||||
private readonly IFileSystem2 _macroPartialFileSystem;
|
||||
private readonly IFileSystem2 _partialViewsFileSystem;
|
||||
private readonly IFileSystem2 _stylesheetsFileSystem;
|
||||
private readonly IFileSystem2 _scriptsFileSystem;
|
||||
private readonly IFileSystem2 _xsltFileSystem;
|
||||
private readonly IFileSystem2 _masterPagesFileSystem;
|
||||
private readonly IFileSystem2 _mvcViewsFileSystem;
|
||||
private readonly ConcurrentDictionary<string, ProviderConstructionInfo> _providerLookup = new ConcurrentDictionary<string, ProviderConstructionInfo>();
|
||||
private readonly ConcurrentDictionary<string, IFileSystem2> _filesystems = new ConcurrentDictionary<string, IFileSystem2>();
|
||||
|
||||
// when shadowing is enabled, above filesystems, as wrappers
|
||||
private readonly ShadowWrapper _macroPartialFileSystemWrapper;
|
||||
private readonly ShadowWrapper _partialViewsFileSystemWrapper;
|
||||
private readonly ShadowWrapper _stylesheetsFileSystemWrapper;
|
||||
private readonly ShadowWrapper _scriptsFileSystemWrapper;
|
||||
private readonly ShadowWrapper _xsltFileSystemWrapper;
|
||||
private readonly ShadowWrapper _masterPagesFileSystemWrapper;
|
||||
private readonly ShadowWrapper _mvcViewsFileSystemWrapper;
|
||||
private ShadowWrapper _macroPartialFileSystem;
|
||||
private ShadowWrapper _partialViewsFileSystem;
|
||||
private ShadowWrapper _stylesheetsFileSystem;
|
||||
private ShadowWrapper _scriptsFileSystem;
|
||||
private ShadowWrapper _xsltFileSystem;
|
||||
private ShadowWrapper _masterPagesFileSystem;
|
||||
private ShadowWrapper _mvcViewsFileSystem;
|
||||
|
||||
#region Singleton & Constructor
|
||||
|
||||
@@ -41,31 +34,45 @@ namespace Umbraco.Core.IO
|
||||
get { return Instance; }
|
||||
}
|
||||
|
||||
// for tests only, totally unsafe
|
||||
internal void Reset()
|
||||
{
|
||||
_wrappers.Clear();
|
||||
_providerLookup.Clear();
|
||||
_filesystems.Clear();
|
||||
CreateWellKnownFileSystems();
|
||||
}
|
||||
|
||||
private IScopeProviderInternal ScopeProvider
|
||||
{
|
||||
// fixme - 'course this is bad, but enough for now
|
||||
// beware: means that we capture the "current" scope provider - take care in tests!
|
||||
get { return ApplicationContext.Current == null ? null : ApplicationContext.Current.ScopeProvider as IScopeProviderInternal; }
|
||||
}
|
||||
|
||||
internal FileSystemProviderManager()
|
||||
{
|
||||
_config = (FileSystemProvidersSection) ConfigurationManager.GetSection("umbracoConfiguration/FileSystemProviders");
|
||||
CreateWellKnownFileSystems();
|
||||
}
|
||||
|
||||
_macroPartialFileSystem = new PhysicalFileSystem(SystemDirectories.MacroPartials);
|
||||
_partialViewsFileSystem = new PhysicalFileSystem(SystemDirectories.PartialViews);
|
||||
_stylesheetsFileSystem = new PhysicalFileSystem(SystemDirectories.Css);
|
||||
_scriptsFileSystem = new PhysicalFileSystem(SystemDirectories.Scripts);
|
||||
_xsltFileSystem = new PhysicalFileSystem(SystemDirectories.Xslt);
|
||||
_masterPagesFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages);
|
||||
_mvcViewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews);
|
||||
private void CreateWellKnownFileSystems()
|
||||
{
|
||||
var macroPartialFileSystem = new PhysicalFileSystem(SystemDirectories.MacroPartials);
|
||||
var partialViewsFileSystem = new PhysicalFileSystem(SystemDirectories.PartialViews);
|
||||
var stylesheetsFileSystem = new PhysicalFileSystem(SystemDirectories.Css);
|
||||
var scriptsFileSystem = new PhysicalFileSystem(SystemDirectories.Scripts);
|
||||
var xsltFileSystem = new PhysicalFileSystem(SystemDirectories.Xslt);
|
||||
var masterPagesFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages);
|
||||
var mvcViewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews);
|
||||
|
||||
_macroPartialFileSystem = _macroPartialFileSystemWrapper = new ShadowWrapper(_macroPartialFileSystem, "Views/MacroPartials", ScopeProvider);
|
||||
_partialViewsFileSystem = _partialViewsFileSystemWrapper = new ShadowWrapper(_partialViewsFileSystem, "Views/Partials", ScopeProvider);
|
||||
_stylesheetsFileSystem = _stylesheetsFileSystemWrapper = new ShadowWrapper(_stylesheetsFileSystem, "css", ScopeProvider);
|
||||
_scriptsFileSystem = _scriptsFileSystemWrapper = new ShadowWrapper(_scriptsFileSystem, "scripts", ScopeProvider);
|
||||
_xsltFileSystem = _xsltFileSystemWrapper = new ShadowWrapper(_xsltFileSystem, "xslt", ScopeProvider);
|
||||
_masterPagesFileSystem = _masterPagesFileSystemWrapper = new ShadowWrapper(_masterPagesFileSystem, "masterpages", ScopeProvider);
|
||||
_mvcViewsFileSystem = _mvcViewsFileSystemWrapper = new ShadowWrapper(_mvcViewsFileSystem, "Views", ScopeProvider);
|
||||
_macroPartialFileSystem = new ShadowWrapper(macroPartialFileSystem, "Views/MacroPartials", ScopeProvider);
|
||||
_partialViewsFileSystem = new ShadowWrapper(partialViewsFileSystem, "Views/Partials", ScopeProvider);
|
||||
_stylesheetsFileSystem = new ShadowWrapper(stylesheetsFileSystem, "css", ScopeProvider);
|
||||
_scriptsFileSystem = new ShadowWrapper(scriptsFileSystem, "scripts", ScopeProvider);
|
||||
_xsltFileSystem = new ShadowWrapper(xsltFileSystem, "xslt", ScopeProvider);
|
||||
_masterPagesFileSystem = new ShadowWrapper(masterPagesFileSystem, "masterpages", ScopeProvider);
|
||||
_mvcViewsFileSystem = new ShadowWrapper(mvcViewsFileSystem, "Views", ScopeProvider);
|
||||
|
||||
// filesystems obtained from GetFileSystemProvider are already wrapped and do not need to be wrapped again
|
||||
MediaFileSystem = GetFileSystemProvider<MediaFileSystem>();
|
||||
@@ -80,7 +87,7 @@ namespace Umbraco.Core.IO
|
||||
public IFileSystem2 StylesheetsFileSystem { get { return _stylesheetsFileSystem; } }
|
||||
public IFileSystem2 ScriptsFileSystem { get { return _scriptsFileSystem; } }
|
||||
public IFileSystem2 XsltFileSystem { get { return _xsltFileSystem; } }
|
||||
public IFileSystem2 MasterPagesFileSystem { get { return _masterPagesFileSystem; } }
|
||||
public IFileSystem2 MasterPagesFileSystem { get { return _mvcViewsFileSystem; } }
|
||||
public IFileSystem2 MvcViewsFileSystem { get { return _mvcViewsFileSystem; } }
|
||||
public MediaFileSystem MediaFileSystem { get; private set; }
|
||||
|
||||
@@ -98,56 +105,74 @@ namespace Umbraco.Core.IO
|
||||
//public string ProviderAlias { get; set; }
|
||||
}
|
||||
|
||||
private readonly ConcurrentDictionary<string, ProviderConstructionInfo> _providerLookup = new ConcurrentDictionary<string, ProviderConstructionInfo>();
|
||||
private readonly ConcurrentDictionary<Type, string> _aliases = new ConcurrentDictionary<Type, string>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an underlying (non-typed) filesystem supporting a strongly-typed filesystem.
|
||||
/// </summary>
|
||||
/// <param name="alias">The alias of the strongly-typed filesystem.</param>
|
||||
/// <returns>The non-typed filesystem supporting the strongly-typed filesystem with the specified alias.</returns>
|
||||
/// <remarks>This method should not be used directly, used <see cref="GetFileSystemProvider{TFileSystem}"/> instead.</remarks>
|
||||
/// <remarks>This method should not be used directly, used <see cref="GetFileSystemProvider{TFileSystem}()"/> instead.</remarks>
|
||||
public IFileSystem GetUnderlyingFileSystemProvider(string alias)
|
||||
{
|
||||
return GetUnderlyingFileSystemProvider(alias, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an underlying (non-typed) filesystem supporting a strongly-typed filesystem.
|
||||
/// </summary>
|
||||
/// <param name="alias">The alias of the strongly-typed filesystem.</param>
|
||||
/// /// <param name="fallback">A fallback creator for the filesystem.</param>
|
||||
/// <returns>The non-typed filesystem supporting the strongly-typed filesystem with the specified alias.</returns>
|
||||
/// <remarks>This method should not be used directly, used <see cref="GetFileSystemProvider{TFileSystem}()"/> instead.</remarks>
|
||||
private IFileSystem GetUnderlyingFileSystemProvider(string alias, Func<IFileSystem> fallback)
|
||||
{
|
||||
// either get the constructor info from cache or create it and add to cache
|
||||
var ctorInfo = _providerLookup.GetOrAdd(alias, s =>
|
||||
{
|
||||
// get config
|
||||
var providerConfig = _config.Providers[s];
|
||||
if (providerConfig == null)
|
||||
throw new ArgumentException(string.Format("No provider found with alias {0}.", s));
|
||||
var ctorInfo = _providerLookup.GetOrAdd(alias, _ => GetUnderlyingFileSystemCtor(alias, fallback));
|
||||
return ctorInfo == null ? fallback() : (IFileSystem) ctorInfo.Constructor.Invoke(ctorInfo.Parameters);
|
||||
}
|
||||
|
||||
// get the filesystem type
|
||||
var providerType = Type.GetType(providerConfig.Type);
|
||||
if (providerType == null)
|
||||
throw new InvalidOperationException(string.Format("Could not find type {0}.", providerConfig.Type));
|
||||
private IFileSystem GetUnderlyingFileSystemNoCache(string alias, Func<IFileSystem> fallback)
|
||||
{
|
||||
var ctorInfo = GetUnderlyingFileSystemCtor(alias, fallback);
|
||||
return ctorInfo == null ? fallback() : (IFileSystem) ctorInfo.Constructor.Invoke(ctorInfo.Parameters);
|
||||
}
|
||||
|
||||
// ensure it implements IFileSystem
|
||||
if (providerType.IsAssignableFrom(typeof (IFileSystem)))
|
||||
throw new InvalidOperationException(string.Format("Type {0} does not implement IFileSystem.", providerType.FullName));
|
||||
private ProviderConstructionInfo GetUnderlyingFileSystemCtor(string alias, Func<IFileSystem> fallback)
|
||||
{
|
||||
// get config
|
||||
var providerConfig = _config.Providers[alias];
|
||||
if (providerConfig == null)
|
||||
{
|
||||
if (fallback != null) return null;
|
||||
throw new ArgumentException(string.Format("No provider found with alias {0}.", alias));
|
||||
}
|
||||
|
||||
// find a ctor matching the config parameters
|
||||
var paramCount = providerConfig.Parameters != null ? providerConfig.Parameters.Count : 0;
|
||||
var constructor = providerType.GetConstructors().SingleOrDefault(x
|
||||
=> x.GetParameters().Length == paramCount && x.GetParameters().All(y => providerConfig.Parameters.AllKeys.Contains(y.Name)));
|
||||
if (constructor == null)
|
||||
throw new InvalidOperationException(string.Format("Type {0} has no ctor matching the {1} configuration parameter(s).", providerType.FullName, paramCount));
|
||||
// get the filesystem type
|
||||
var providerType = Type.GetType(providerConfig.Type);
|
||||
if (providerType == null)
|
||||
throw new InvalidOperationException(string.Format("Could not find type {0}.", providerConfig.Type));
|
||||
|
||||
var parameters = new object[paramCount];
|
||||
if (providerConfig.Parameters != null) // keeps ReSharper happy
|
||||
for (var i = 0; i < paramCount; i++)
|
||||
parameters[i] = providerConfig.Parameters[providerConfig.Parameters.AllKeys[i]].Value;
|
||||
// ensure it implements IFileSystem
|
||||
if (providerType.IsAssignableFrom(typeof(IFileSystem)))
|
||||
throw new InvalidOperationException(string.Format("Type {0} does not implement IFileSystem.", providerType.FullName));
|
||||
|
||||
return new ProviderConstructionInfo
|
||||
{
|
||||
Constructor = constructor,
|
||||
Parameters = parameters,
|
||||
//ProviderAlias = s
|
||||
};
|
||||
});
|
||||
// find a ctor matching the config parameters
|
||||
var paramCount = providerConfig.Parameters != null ? providerConfig.Parameters.Count : 0;
|
||||
var constructor = providerType.GetConstructors().SingleOrDefault(x
|
||||
=> x.GetParameters().Length == paramCount && x.GetParameters().All(y => providerConfig.Parameters.AllKeys.Contains(y.Name)));
|
||||
if (constructor == null)
|
||||
throw new InvalidOperationException(string.Format("Type {0} has no ctor matching the {1} configuration parameter(s).", providerType.FullName, paramCount));
|
||||
|
||||
// create the fs and return
|
||||
return (IFileSystem) ctorInfo.Constructor.Invoke(ctorInfo.Parameters);
|
||||
var parameters = new object[paramCount];
|
||||
if (providerConfig.Parameters != null) // keeps ReSharper happy
|
||||
for (var i = 0; i < paramCount; i++)
|
||||
parameters[i] = providerConfig.Parameters[providerConfig.Parameters.AllKeys[i]].Value;
|
||||
|
||||
return new ProviderConstructionInfo
|
||||
{
|
||||
Constructor = constructor,
|
||||
Parameters = parameters,
|
||||
//ProviderAlias = s
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -155,38 +180,68 @@ namespace Umbraco.Core.IO
|
||||
/// </summary>
|
||||
/// <typeparam name="TFileSystem">The type of the filesystem.</typeparam>
|
||||
/// <returns>A strongly-typed filesystem of the specified type.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Ideally, this should cache the instances, but that would break backward compatibility, so we
|
||||
/// only do it for our own MediaFileSystem - for everything else, it's the responsibility of the caller
|
||||
/// to ensure that they maintain singletons. This is important for singletons, as each filesystem maintains
|
||||
/// its own shadow and having multiple instances would lead to inconsistencies.</para>
|
||||
/// <para>Note that any filesystem created by this method *after* shadowing begins, will *not* be
|
||||
/// shadowing (and an exception will be thrown by the ShadowWrapper).</para>
|
||||
/// </remarks>
|
||||
public TFileSystem GetFileSystemProvider<TFileSystem>()
|
||||
where TFileSystem : FileSystemWrapper
|
||||
where TFileSystem : FileSystemWrapper
|
||||
{
|
||||
// deal with known types - avoid infinite loops!
|
||||
if (typeof(TFileSystem) == typeof(MediaFileSystem) && MediaFileSystem != null)
|
||||
return MediaFileSystem as TFileSystem; // else create and return
|
||||
return GetFileSystemProvider<TFileSystem>(null);
|
||||
}
|
||||
|
||||
// get/cache the alias for the filesystem type
|
||||
var alias = _aliases.GetOrAdd(typeof (TFileSystem), fsType =>
|
||||
{
|
||||
// validate the ctor
|
||||
var constructor = fsType.GetConstructors().SingleOrDefault(x
|
||||
=> x.GetParameters().Length == 1 && TypeHelper.IsTypeAssignableFrom<IFileSystem>(x.GetParameters().Single().ParameterType));
|
||||
if (constructor == null)
|
||||
throw new InvalidOperationException("Type " + fsType.FullName + " must inherit from FileSystemWrapper and have a constructor that accepts one parameter of type " + typeof(IFileSystem).FullName + ".");
|
||||
/// <summary>
|
||||
/// Gets a strongly-typed filesystem.
|
||||
/// </summary>
|
||||
/// <typeparam name="TFileSystem">The type of the filesystem.</typeparam>
|
||||
/// <param name="fallback">A fallback creator for the inner filesystem.</param>
|
||||
/// <returns>A strongly-typed filesystem of the specified type.</returns>
|
||||
/// <remarks>
|
||||
/// <para>The fallback creator is used only if nothing is configured.</para>
|
||||
/// <para>Ideally, this should cache the instances, but that would break backward compatibility, so we
|
||||
/// only do it for our own MediaFileSystem - for everything else, it's the responsibility of the caller
|
||||
/// to ensure that they maintain singletons. This is important for singletons, as each filesystem maintains
|
||||
/// its own shadow and having multiple instances would lead to inconsistencies.</para>
|
||||
/// <para>Note that any filesystem created by this method *after* shadowing begins, will *not* be
|
||||
/// shadowing (and an exception will be thrown by the ShadowWrapper).</para>
|
||||
/// </remarks>
|
||||
public TFileSystem GetFileSystemProvider<TFileSystem>(Func<IFileSystem> fallback)
|
||||
where TFileSystem : FileSystemWrapper
|
||||
{
|
||||
var alias = GetFileSystemAlias<TFileSystem>();
|
||||
return (TFileSystem) _filesystems.GetOrAdd(alias, _ =>
|
||||
{
|
||||
// gets the inner fs, create the strongly-typed fs wrapping the inner fs, register & return
|
||||
// so we are double-wrapping here
|
||||
// could be optimized by having FileSystemWrapper inherit from ShadowWrapper, maybe
|
||||
var innerFs = GetUnderlyingFileSystemNoCache(alias, fallback);
|
||||
var shadowWrapper = new ShadowWrapper(innerFs, "typed/" + alias, ScopeProvider);
|
||||
var fs = (IFileSystem2) Activator.CreateInstance(typeof (TFileSystem), shadowWrapper);
|
||||
_wrappers.Add(shadowWrapper); // keeping a reference to the wrapper
|
||||
return fs;
|
||||
});
|
||||
}
|
||||
|
||||
// find the attribute and get the alias
|
||||
var attr = (FileSystemProviderAttribute) fsType.GetCustomAttributes(typeof(FileSystemProviderAttribute), false).SingleOrDefault();
|
||||
if (attr == null)
|
||||
throw new InvalidOperationException("Type " + fsType.FullName + "is missing the required FileSystemProviderAttribute.");
|
||||
private string GetFileSystemAlias<TFileSystem>()
|
||||
{
|
||||
var fsType = typeof(TFileSystem);
|
||||
|
||||
return attr.Alias;
|
||||
});
|
||||
// validate the ctor
|
||||
var constructor = fsType.GetConstructors().SingleOrDefault(x
|
||||
=> x.GetParameters().Length == 1 && TypeHelper.IsTypeAssignableFrom<IFileSystem>(x.GetParameters().Single().ParameterType));
|
||||
if (constructor == null)
|
||||
throw new InvalidOperationException("Type " + fsType.FullName + " must inherit from FileSystemWrapper and have a constructor that accepts one parameter of type " + typeof(IFileSystem).FullName + ".");
|
||||
|
||||
// gets the inner fs, create the strongly-typed fs wrapping the inner fs, register & return
|
||||
// so we are double-wrapping here
|
||||
// could be optimized by having FileSystemWrapper inherit from ShadowWrapper, maybe
|
||||
var innerFs = GetUnderlyingFileSystemProvider(alias);
|
||||
var shadowWrapper = new ShadowWrapper(innerFs, "typed/" + alias, ScopeProvider);
|
||||
var fs = (TFileSystem) Activator.CreateInstance(typeof (TFileSystem), shadowWrapper);
|
||||
_wrappers.Add(shadowWrapper); // keeping a weak reference to the wrapper
|
||||
return fs;
|
||||
// find the attribute and get the alias
|
||||
var attr = (FileSystemProviderAttribute)fsType.GetCustomAttributes(typeof(FileSystemProviderAttribute), false).SingleOrDefault();
|
||||
if (attr == null)
|
||||
throw new InvalidOperationException("Type " + fsType.FullName + "is missing the required FileSystemProviderAttribute.");
|
||||
|
||||
return attr.Alias;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -199,30 +254,37 @@ namespace Umbraco.Core.IO
|
||||
var wrappers = new ShadowWrapper[typed.Length + 7];
|
||||
var i = 0;
|
||||
while (i < typed.Length) wrappers[i] = typed[i++];
|
||||
wrappers[i++] = _macroPartialFileSystemWrapper;
|
||||
wrappers[i++] = _partialViewsFileSystemWrapper;
|
||||
wrappers[i++] = _stylesheetsFileSystemWrapper;
|
||||
wrappers[i++] = _scriptsFileSystemWrapper;
|
||||
wrappers[i++] = _xsltFileSystemWrapper;
|
||||
wrappers[i++] = _masterPagesFileSystemWrapper;
|
||||
wrappers[i] = _mvcViewsFileSystemWrapper;
|
||||
wrappers[i++] = _macroPartialFileSystem;
|
||||
wrappers[i++] = _partialViewsFileSystem;
|
||||
wrappers[i++] = _stylesheetsFileSystem;
|
||||
wrappers[i++] = _scriptsFileSystem;
|
||||
wrappers[i++] = _xsltFileSystem;
|
||||
wrappers[i++] = _masterPagesFileSystem;
|
||||
wrappers[i] = _mvcViewsFileSystem;
|
||||
|
||||
return new ShadowFileSystems(id, wrappers);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private class WeakSet<T>
|
||||
private class ConcurrentSet<T>
|
||||
where T : class
|
||||
{
|
||||
private readonly HashSet<WeakReference<T>> _set = new HashSet<WeakReference<T>>();
|
||||
private readonly HashSet<T> _set = new HashSet<T>();
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
lock (_set)
|
||||
{
|
||||
_set.Add(new WeakReference<T>(item));
|
||||
CollectLocked();
|
||||
_set.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (_set)
|
||||
{
|
||||
_set.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,23 +292,9 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
lock (_set)
|
||||
{
|
||||
CollectLocked();
|
||||
return _set.Select(x =>
|
||||
{
|
||||
T target;
|
||||
return x.TryGetTarget(out target) ? target : null;
|
||||
}).WhereNotNull().ToArray();
|
||||
return _set.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private void CollectLocked()
|
||||
{
|
||||
_set.RemoveWhere(x =>
|
||||
{
|
||||
T target;
|
||||
return x.TryGetTarget(out target) == false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,11 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
var isScoped = _scopeProvider != null && _scopeProvider.AmbientScope != null && _scopeProvider.AmbientScope.ScopedFileSystems;
|
||||
|
||||
// if the filesystem is created *after* shadowing starts, it won't be shadowing
|
||||
// better not ignore that situation and raised a meaningful (?) exception
|
||||
if (isScoped && _shadowFileSystem == null)
|
||||
throw new Exception("The filesystems are shadowing, but this filesystem is not.");
|
||||
|
||||
return isScoped
|
||||
? _shadowFileSystem
|
||||
: _innerFileSystem;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -72,15 +73,28 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GlobalSettings.ContentCacheXmlStoredInCodeGen && SystemUtilities.GetCurrentTrustLevel() == AspNetHostingPermissionLevel.Unrestricted)
|
||||
{
|
||||
return Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData\umbraco.config");
|
||||
switch (GlobalSettings.ContentCacheXmlStorageLocation)
|
||||
{
|
||||
case ContentXmlStorage.AspNetTemp:
|
||||
return Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData\umbraco.config");
|
||||
case ContentXmlStorage.EnvironmentTemp:
|
||||
var appDomainHash = HttpRuntime.AppDomainAppId.ToSHA1();
|
||||
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoXml",
|
||||
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
|
||||
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
|
||||
// utilizing an old path
|
||||
appDomainHash);
|
||||
return Path.Combine(cachePath, "umbraco.config");
|
||||
case ContentXmlStorage.Default:
|
||||
return IOHelper.ReturnPath("umbracoContentXML", "~/App_Data/umbraco.config");
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
return IOHelper.ReturnPath("umbracoContentXML", "~/App_Data/umbraco.config");
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Use GlobalSettings.ContentCacheXmlStoredInCodeGen instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
internal static bool ContentCacheXmlStoredInCodeGen
|
||||
{
|
||||
get { return GlobalSettings.ContentCacheXmlStoredInCodeGen; }
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using log4net;
|
||||
@@ -62,12 +63,34 @@ namespace Umbraco.Core.Logging
|
||||
|
||||
public void Error(Type callingType, string message, Exception exception)
|
||||
{
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger != null)
|
||||
logger.Error((message), exception);
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null) return;
|
||||
|
||||
if (IsTimeoutThreadAbortException(exception))
|
||||
{
|
||||
message += "\r\nThe thread has been aborted, because the request has timed out.";
|
||||
}
|
||||
|
||||
logger.Error(message, exception);
|
||||
}
|
||||
|
||||
public void Warn(Type callingType, string message, params Func<object>[] formatItems)
|
||||
private static bool IsTimeoutThreadAbortException(Exception exception)
|
||||
{
|
||||
var abort = exception as ThreadAbortException;
|
||||
if (abort == null) return false;
|
||||
|
||||
if (abort.ExceptionState == null) return false;
|
||||
|
||||
var stateType = abort.ExceptionState.GetType();
|
||||
if (stateType.FullName != "System.Web.HttpApplication+CancelModuleException") return false;
|
||||
|
||||
var timeoutField = stateType.GetField("_timeout", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (timeoutField == null) return false;
|
||||
|
||||
return (bool) timeoutField.GetValue(abort.ExceptionState);
|
||||
}
|
||||
|
||||
public void Warn(Type callingType, string message, params Func<object>[] formatItems)
|
||||
{
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||
|
||||
@@ -69,6 +69,7 @@ namespace Umbraco.Core.Models
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
//TODO: Instead of 'new' this should explicitly implement one of the collection interfaces members
|
||||
internal new void Add(PropertyType item)
|
||||
{
|
||||
using (new WriteLock(_addLocker))
|
||||
|
||||
@@ -110,6 +110,12 @@ namespace Umbraco.Core.Models
|
||||
_ruleCollection.Clear();
|
||||
}
|
||||
|
||||
|
||||
internal void ClearRemovedRules()
|
||||
{
|
||||
_removedRules.Clear();
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public int LoginNodeId
|
||||
{
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
/// <summary>
|
||||
/// The published content enumerable, this model is to allow ToString to be overriden for value converters to support legacy requests for string values
|
||||
/// </summary>
|
||||
public class PublishedContentEnumerable : IEnumerable<IPublishedContent>
|
||||
{
|
||||
/// <summary>
|
||||
/// The items in the collection
|
||||
/// </summary>
|
||||
private readonly IEnumerable<IPublishedContent> _items;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedContentEnumerable"/> class.
|
||||
/// </summary>
|
||||
/// <param name="publishedContent">
|
||||
/// The published content items
|
||||
/// </param>
|
||||
public PublishedContentEnumerable(IEnumerable<IPublishedContent> publishedContent)
|
||||
{
|
||||
if (publishedContent == null) throw new ArgumentNullException("publishedContent");
|
||||
_items = publishedContent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The ToString method to convert the objects back to CSV
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The <see cref="string"/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(",", _items.Select(x => x.Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The get enumerator.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The <see cref="IEnumerator"/>.
|
||||
/// </returns>
|
||||
public IEnumerator<IPublishedContent> GetEnumerator()
|
||||
{
|
||||
return _items.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The get enumerator.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The <see cref="IEnumerator"/>.
|
||||
/// </returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
|
||||
[TypeConverter(typeof(PublishedContentTypeConverter))]
|
||||
public class PublishedContentExtended : PublishedContentWrapped, IPublishedContentExtended
|
||||
{
|
||||
#region Constructor
|
||||
@@ -186,6 +187,11 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Id.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
internal class PublishedContentTypeConverter : TypeConverter
|
||||
{
|
||||
private static readonly Type[] ConvertableTypes = new[]
|
||||
{
|
||||
typeof(int)
|
||||
};
|
||||
|
||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||
{
|
||||
return ConvertableTypes.Any(x => TypeHelper.IsTypeAssignableFrom(x, destinationType))
|
||||
|| base.CanConvertFrom(context, destinationType);
|
||||
}
|
||||
|
||||
public override object ConvertTo(
|
||||
ITypeDescriptorContext context,
|
||||
CultureInfo culture,
|
||||
object value,
|
||||
Type destinationType)
|
||||
{
|
||||
var publishedContent = value as IPublishedContent;
|
||||
if (publishedContent == null)
|
||||
return null;
|
||||
|
||||
if (TypeHelper.IsTypeAssignableFrom<int>(destinationType))
|
||||
{
|
||||
return publishedContent.Id;
|
||||
}
|
||||
|
||||
return base.ConvertTo(context, culture, value, destinationType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
// <summary>The Range class. Adapted from http://stackoverflow.com/questions/5343006/is-there-a-c-sharp-type-for-representing-an-integer-range</summary>
|
||||
/// <typeparam name="T">Generic parameter.</typeparam>
|
||||
public class Range<T> where T : IComparable<T>
|
||||
{
|
||||
/// <summary>Minimum value of the range.</summary>
|
||||
public T Minimum { get; set; }
|
||||
|
||||
/// <summary>Maximum value of the range.</summary>
|
||||
public T Maximum { get; set; }
|
||||
|
||||
/// <summary>Presents the Range in readable format.</summary>
|
||||
/// <returns>String representation of the Range</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0},{1}", this.Minimum, this.Maximum);
|
||||
}
|
||||
|
||||
/// <summary>Determines if the range is valid.</summary>
|
||||
/// <returns>True if range is valid, else false</returns>
|
||||
public bool IsValid()
|
||||
{
|
||||
return this.Minimum.CompareTo(this.Maximum) <= 0;
|
||||
}
|
||||
|
||||
/// <summary>Determines if the provided value is inside the range.</summary>
|
||||
/// <param name="value">The value to test</param>
|
||||
/// <returns>True if the value is inside Range, else false</returns>
|
||||
public bool ContainsValue(T value)
|
||||
{
|
||||
return (this.Minimum.CompareTo(value) <= 0) && (value.CompareTo(this.Maximum) <= 0);
|
||||
}
|
||||
|
||||
/// <summary>Determines if this Range is inside the bounds of another range.</summary>
|
||||
/// <param name="Range">The parent range to test on</param>
|
||||
/// <returns>True if range is inclusive, else false</returns>
|
||||
public bool IsInsideRange(Range<T> range)
|
||||
{
|
||||
return this.IsValid() && range.IsValid() && range.ContainsValue(this.Minimum) && range.ContainsValue(this.Maximum);
|
||||
}
|
||||
|
||||
/// <summary>Determines if another range is inside the bounds of this range.</summary>
|
||||
/// <param name="Range">The child range to test</param>
|
||||
/// <returns>True if range is inside, else false</returns>
|
||||
public bool ContainsRange(Range<T> range)
|
||||
{
|
||||
return this.IsValid() && range.IsValid() && this.ContainsValue(range.Minimum) && this.ContainsValue(range.Maximum);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
internal class DataTypeDto
|
||||
{
|
||||
[Column("pk")]
|
||||
[PrimaryKeyColumn(IdentitySeed = 30)]
|
||||
[PrimaryKeyColumn(IdentitySeed = 40)]
|
||||
public int PrimaryKey { get; set; }
|
||||
|
||||
[Column("nodeId")]
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
[ExplicitColumns]
|
||||
internal class NodeDto
|
||||
{
|
||||
public const int NodeIdSeed = 1050;
|
||||
public const int NodeIdSeed = 1060;
|
||||
|
||||
[Column("id")]
|
||||
[PrimaryKeyColumn(Name = "PK_structure", IdentitySeed = NodeIdSeed)]
|
||||
|
||||
@@ -28,17 +28,17 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
|
||||
#region Implementation of IEntityFactory<IMedia,ContentVersionDto>
|
||||
|
||||
public IMember BuildEntity(MemberDto dto)
|
||||
public static IMember BuildEntity(MemberDto dto, IMemberType contentType)
|
||||
{
|
||||
var member = new Member(
|
||||
dto.ContentVersionDto.ContentDto.NodeDto.Text,
|
||||
dto.Email, dto.LoginName, dto.Password, _contentType);
|
||||
dto.Email, dto.LoginName, dto.Password, contentType);
|
||||
|
||||
try
|
||||
{
|
||||
member.DisableChangeTracking();
|
||||
|
||||
member.Id = _id;
|
||||
member.Id = dto.NodeId;
|
||||
member.Key = dto.ContentVersionDto.ContentDto.NodeDto.UniqueId;
|
||||
member.Path = dto.ContentVersionDto.ContentDto.NodeDto.Path;
|
||||
member.CreatorId = dto.ContentVersionDto.ContentDto.NodeDto.UserId.Value;
|
||||
@@ -62,6 +62,12 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Use the static BuildEntity instead so we don't have to allocate one of these objects everytime we want to map values")]
|
||||
public IMember BuildEntity(MemberDto dto)
|
||||
{
|
||||
return BuildEntity(dto, _contentType);
|
||||
}
|
||||
|
||||
public MemberDto BuildDto(IMember entity)
|
||||
{
|
||||
var dto = new MemberDto
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Reflection;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Strings;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
@@ -17,7 +18,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
|
||||
//figure out what extra properties we have that are not on the IUmbracoEntity and add them to additional data
|
||||
foreach (var k in originalEntityProperties.Keys
|
||||
.Select(x => new { orig = x, title = x.ConvertCase(StringAliasCaseType.PascalCase) })
|
||||
.Select(x => new { orig = x, title = x.ToCleanString(CleanStringType.PascalCase | CleanStringType.Ascii | CleanStringType.ConvertCase) })
|
||||
.Where(x => entityProps.InvariantContains(x.title) == false))
|
||||
{
|
||||
entity.AdditionalData[k.title] = originalEntityProperties[k.orig];
|
||||
@@ -75,65 +76,6 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
entity.EnableChangeTracking();
|
||||
}
|
||||
}
|
||||
|
||||
public UmbracoEntity BuildEntity(EntityRepository.UmbracoEntityDto dto)
|
||||
{
|
||||
var entity = new UmbracoEntity(dto.Trashed)
|
||||
{
|
||||
CreateDate = dto.CreateDate,
|
||||
CreatorId = dto.UserId.Value,
|
||||
Id = dto.NodeId,
|
||||
Key = dto.UniqueId,
|
||||
Level = dto.Level,
|
||||
Name = dto.Text,
|
||||
NodeObjectTypeId = dto.NodeObjectType.Value,
|
||||
ParentId = dto.ParentId,
|
||||
Path = dto.Path,
|
||||
SortOrder = dto.SortOrder,
|
||||
HasChildren = dto.Children > 0,
|
||||
ContentTypeAlias = dto.Alias ?? string.Empty,
|
||||
ContentTypeIcon = dto.Icon ?? string.Empty,
|
||||
ContentTypeThumbnail = dto.Thumbnail ?? string.Empty,
|
||||
};
|
||||
|
||||
entity.IsPublished = dto.PublishedVersion != default(Guid) || (dto.NewestVersion != default(Guid) && dto.PublishedVersion == dto.NewestVersion);
|
||||
entity.IsDraft = dto.NewestVersion != default(Guid) && (dto.PublishedVersion == default(Guid) || dto.PublishedVersion != dto.NewestVersion);
|
||||
entity.HasPendingChanges = (dto.PublishedVersion != default(Guid) && dto.NewestVersion != default(Guid)) && dto.PublishedVersion != dto.NewestVersion;
|
||||
|
||||
if (dto.UmbracoPropertyDtos != null)
|
||||
{
|
||||
foreach (var propertyDto in dto.UmbracoPropertyDtos)
|
||||
{
|
||||
entity.AdditionalData[propertyDto.PropertyAlias] = new UmbracoEntity.EntityProperty
|
||||
{
|
||||
PropertyEditorAlias = propertyDto.PropertyEditorAlias,
|
||||
Value = propertyDto.NTextValue.IsNullOrWhiteSpace()
|
||||
? propertyDto.NVarcharValue
|
||||
: propertyDto.NTextValue.ConvertToJsonIfPossible()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
public EntityRepository.UmbracoEntityDto BuildDto(UmbracoEntity entity)
|
||||
{
|
||||
var node = new EntityRepository.UmbracoEntityDto
|
||||
{
|
||||
CreateDate = entity.CreateDate,
|
||||
Level = short.Parse(entity.Level.ToString(CultureInfo.InvariantCulture)),
|
||||
NodeId = entity.Id,
|
||||
NodeObjectType = entity.NodeObjectTypeId,
|
||||
ParentId = entity.ParentId,
|
||||
Path = entity.Path,
|
||||
SortOrder = entity.SortOrder,
|
||||
Text = entity.Name,
|
||||
Trashed = entity.Trashed,
|
||||
UniqueId = entity.Key,
|
||||
UserId = entity.CreatorId
|
||||
};
|
||||
return node;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
internal BaseMapper ResolveMapperByType(Type type)
|
||||
public virtual BaseMapper ResolveMapperByType(Type type)
|
||||
{
|
||||
return _mapperCache.GetOrAdd(type, type1 =>
|
||||
{
|
||||
@@ -67,7 +67,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
return Attempt<BaseMapper>.Succeed(mapper);
|
||||
}
|
||||
|
||||
internal string GetMapping(Type type, string propertyName)
|
||||
public virtual string GetMapping(Type type, string propertyName)
|
||||
{
|
||||
var mapper = ResolveMapperByType(type);
|
||||
var result = mapper.Map(propertyName);
|
||||
|
||||
@@ -130,8 +130,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.System.DefaultMembersListViewDataTypeId, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-97", SortOrder = 2, UniqueId = new Guid("AA2C52A0-CE87-4E65-A47C-7DF09358585D"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Members", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1031, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1031", SortOrder = 2, UniqueId = new Guid("f38bd2d7-65d0-48e6-95dc-87ce06ec2d3d"), Text = Constants.Conventions.MediaTypes.Folder, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1032, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1032", SortOrder = 2, UniqueId = new Guid("cc07b313-0843-4aa8-bbda-871c8da728c8"), Text = Constants.Conventions.MediaTypes.Image, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1033, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1033", SortOrder = 2, UniqueId = new Guid("4c52d8ab-54e6-40cd-999c-7a5f24903e4d"), Text = Constants.Conventions.MediaTypes.File, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1040, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1040", SortOrder = 2, UniqueId = new Guid("21e798da-e06e-4eda-a511-ed257f78d4fa"), Text = "Related Links", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1033, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1033", SortOrder = 2, UniqueId = new Guid("4c52d8ab-54e6-40cd-999c-7a5f24903e4d"), Text = Constants.Conventions.MediaTypes.File, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1041, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1041", SortOrder = 2, UniqueId = new Guid("b6b73142-b9c1-4bf8-a16d-e1c23320b549"), Text = "Tags", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1043, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1043", SortOrder = 2, UniqueId = new Guid("1df9f033-e6d4-451f-b8d2-e0cbc50a836f"), Text = "Image Cropper", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1044, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1044", SortOrder = 0, UniqueId = new Guid("d59be02f-1df9-4228-aa1e-01917d806cda"), Text = Constants.Conventions.MemberTypes.DefaultAlias, NodeObjectType = new Guid(Constants.ObjectTypes.MemberType), CreateDate = DateTime.Now });
|
||||
@@ -141,6 +140,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1047, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1047", SortOrder = 2, UniqueId = new Guid("1EA2E01F-EBD8-4CE1-8D71-6B1149E63548"), Text = "Member Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1048, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1048", SortOrder = 2, UniqueId = new Guid("135D60E0-64D9-49ED-AB08-893C9BA44AE5"), Text = "Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1049, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1049", SortOrder = 2, UniqueId = new Guid("9DBBCBBB-2327-434A-B355-AF1B84E5010A"), Text = "Multiple Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1050, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1050", SortOrder = 2, UniqueId = new Guid("B4E3535A-1753-47E2-8568-602CF8CFEE6F"), Text = "Related Links", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
|
||||
//TODO: We're not creating these for 7.0
|
||||
//_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1039, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1039", SortOrder = 2, UniqueId = new Guid("06f349a9-c949-4b6a-8660-59c10451af42"), Text = "Ultimate Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
@@ -246,8 +246,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 12, DataTypeId = -40, PropertyEditorAlias = Constants.PropertyEditors.RadioButtonListAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 13, DataTypeId = -41, PropertyEditorAlias = Constants.PropertyEditors.DateAlias, DbType = "Date" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 14, DataTypeId = -42, PropertyEditorAlias = Constants.PropertyEditors.DropDownListAlias, DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, PropertyEditorAlias = Constants.PropertyEditors.CheckBoxListAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 21, DataTypeId = 1040, PropertyEditorAlias = Constants.PropertyEditors.RelatedLinksAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, PropertyEditorAlias = Constants.PropertyEditors.CheckBoxListAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 22, DataTypeId = 1041, PropertyEditorAlias = Constants.PropertyEditors.TagsAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 24, DataTypeId = 1043, PropertyEditorAlias = Constants.PropertyEditors.ImageCropperAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -26, DataTypeId = Constants.System.DefaultContentListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
@@ -259,6 +258,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 27, DataTypeId = 1047, PropertyEditorAlias = Constants.PropertyEditors.MemberPicker2Alias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 28, DataTypeId = 1048, PropertyEditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 29, DataTypeId = 1049, PropertyEditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 30, DataTypeId = 1050, PropertyEditorAlias = Constants.PropertyEditors.RelatedLinks2Alias, DbType = "Ntext" });
|
||||
|
||||
//TODO: We're not creating these for 7.0
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 19, DataTypeId = 1038, PropertyEditorAlias = Constants.PropertyEditors.MarkdownEditorAlias, DbType = "Ntext" });
|
||||
|
||||
@@ -546,7 +546,7 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
&& methodArgs.Length == 1
|
||||
&& methodArgs[0].NodeType == ExpressionType.MemberAccess
|
||||
&& TypeHelper.IsTypeAssignableFrom<IEnumerable>(m.Arguments[0].Type))
|
||||
{
|
||||
{
|
||||
goto case "SqlIn";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
@@ -12,17 +13,19 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
/// <remarks>This object is stateful and cannot be re-used to parse an expression.</remarks>
|
||||
internal class ModelToSqlExpressionVisitor<T> : ExpressionVisitorBase
|
||||
{
|
||||
private readonly MappingResolver _mappingResolver;
|
||||
private readonly BaseMapper _mapper;
|
||||
|
||||
public ModelToSqlExpressionVisitor(ISqlSyntaxProvider sqlSyntax, BaseMapper mapper)
|
||||
public ModelToSqlExpressionVisitor(ISqlSyntaxProvider sqlSyntax, MappingResolver mappingResolver)
|
||||
: base(sqlSyntax)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_mapper = mappingResolver.ResolveMapperByType(typeof(T));
|
||||
_mappingResolver = mappingResolver;
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload the specifies a SqlSyntaxProvider")]
|
||||
public ModelToSqlExpressionVisitor()
|
||||
: this(SqlSyntaxContext.SqlSyntaxProvider, MappingResolver.Current.ResolveMapperByType(typeof(T)))
|
||||
: this(SqlSyntaxContext.SqlSyntaxProvider, MappingResolver.Current)
|
||||
{ }
|
||||
|
||||
protected override string VisitMemberAccess(MemberExpression m)
|
||||
@@ -36,7 +39,7 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
var field = _mapper.Map(m.Member.Name, true);
|
||||
if (field.IsNullOrWhiteSpace())
|
||||
throw new InvalidOperationException("The mapper returned an empty field for the member name: " + m.Member.Name);
|
||||
throw new InvalidOperationException(string.Format("The mapper returned an empty field for the member name: {0} for type: {1}", m.Member.Name, m.Expression.Type));
|
||||
return field;
|
||||
}
|
||||
//already compiled, return
|
||||
@@ -50,13 +53,42 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
var field = _mapper.Map(m.Member.Name, true);
|
||||
if (field.IsNullOrWhiteSpace())
|
||||
throw new InvalidOperationException("The mapper returned an empty field for the member name: " + m.Member.Name);
|
||||
throw new InvalidOperationException(string.Format("The mapper returned an empty field for the member name: {0} for type: {1}", m.Member.Name, m.Expression.Type));
|
||||
return field;
|
||||
}
|
||||
//already compiled, return
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (m.Expression != null
|
||||
&& m.Expression.Type != typeof(T)
|
||||
&& TypeHelper.IsTypeAssignableFrom<IUmbracoEntity>(m.Expression.Type)
|
||||
&& EndsWithConstant(m) == false)
|
||||
{
|
||||
//if this is the case, it means we have a sub expression / nested property access, such as: x.ContentType.Alias == "Test";
|
||||
//and since the sub type (x.ContentType) is not the same as x, we need to resolve a mapper for x.ContentType to get it's mapped SQL column
|
||||
|
||||
//don't execute if compiled
|
||||
if (Visited == false)
|
||||
{
|
||||
var subMapper = _mappingResolver.ResolveMapperByType(m.Expression.Type);
|
||||
if (subMapper == null)
|
||||
throw new NullReferenceException("No mapper found for type " + m.Expression.Type);
|
||||
var field = subMapper.Map(m.Member.Name, true);
|
||||
if (field.IsNullOrWhiteSpace())
|
||||
throw new InvalidOperationException(string.Format("The mapper returned an empty field for the member name: {0} for type: {1}", m.Member.Name, m.Expression.Type));
|
||||
return field;
|
||||
}
|
||||
//already compiled, return
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
//TODO: When m.Expression.NodeType == ExpressionType.Constant and it's an expression like: content => aliases.Contains(content.ContentType.Alias);
|
||||
// then an SQL parameter will be added for aliases as an array, however in SqlIn on the subclass it will manually add these SqlParameters anyways,
|
||||
// however the query will still execute because the SQL that is written will only contain the correct indexes of SQL parameters, this would be ignored,
|
||||
// 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.
|
||||
|
||||
var member = Expression.Convert(m, typeof(object));
|
||||
var lambda = Expression.Lambda<Func<object>>(member);
|
||||
var getter = lambda.Compile();
|
||||
@@ -71,5 +103,24 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
return string.Empty;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the MemberExpression ends in a Constant value
|
||||
/// </summary>
|
||||
/// <param name="m"></param>
|
||||
/// <returns></returns>
|
||||
private bool EndsWithConstant(MemberExpression m)
|
||||
{
|
||||
Expression expr = m;
|
||||
|
||||
while (expr is MemberExpression)
|
||||
{
|
||||
var memberExpr = expr as MemberExpression;
|
||||
expr = memberExpr.Expression;
|
||||
}
|
||||
|
||||
var constExpr = expr as ConstantExpression;
|
||||
return constExpr != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
if (dto == null)
|
||||
return null;
|
||||
|
||||
var content = CreateContentFromDto(dto, dto.ContentVersionDto.VersionId, sql);
|
||||
var content = CreateContentFromDto(dto, sql);
|
||||
|
||||
return content;
|
||||
}
|
||||
@@ -134,6 +134,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
.On<ContentVersionDto, ContentDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<NodeDto>(SqlSyntax)
|
||||
.On<ContentDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId);
|
||||
//TODO: IF we want to enable querying on content type information this will need to be joined
|
||||
//.InnerJoin<ContentTypeDto>(SqlSyntax)
|
||||
//.On<ContentDto, ContentTypeDto>(SqlSyntax, left => left.ContentTypeId, right => right.NodeId, SqlSyntax);
|
||||
|
||||
if (queryType == BaseQueryType.FullSingle)
|
||||
{
|
||||
@@ -260,6 +263,39 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
baseId = xmlItems[xmlItems.Count - 1].NodeId;
|
||||
}
|
||||
|
||||
//now delete the items that shouldn't be there
|
||||
var sqlAllIds = translate(0, GetBaseQuery(BaseQueryType.Ids));
|
||||
var allContentIds = Database.Fetch<int>(sqlAllIds);
|
||||
var docObjectType = Guid.Parse(Constants.ObjectTypes.Document);
|
||||
var xmlIdsQuery = new Sql()
|
||||
.Select("DISTINCT cmsContentXml.nodeId")
|
||||
.From<ContentXmlDto>(SqlSyntax)
|
||||
.InnerJoin<NodeDto>(SqlSyntax)
|
||||
.On<ContentXmlDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId);
|
||||
|
||||
if (contentTypeIdsA.Length > 0)
|
||||
{
|
||||
xmlIdsQuery.InnerJoin<ContentDto>(SqlSyntax)
|
||||
.On<ContentDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<ContentTypeDto>(SqlSyntax)
|
||||
.On<ContentTypeDto, ContentDto>(SqlSyntax, left => left.NodeId, right => right.ContentTypeId)
|
||||
.WhereIn<ContentDto>(x => x.ContentTypeId, contentTypeIdsA, SqlSyntax);
|
||||
}
|
||||
|
||||
xmlIdsQuery.Where<NodeDto>(dto => dto.NodeObjectType == docObjectType, SqlSyntax);
|
||||
|
||||
var allXmlIds = Database.Fetch<int>(xmlIdsQuery);
|
||||
|
||||
var toRemove = allXmlIds.Except(allContentIds).ToArray();
|
||||
if (toRemove.Length > 0)
|
||||
{
|
||||
foreach (var idGroup in toRemove.InGroupsOf(2000))
|
||||
{
|
||||
Database.Execute("DELETE FROM cmsContentXml WHERE nodeId IN (@ids)", new { ids = idGroup });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override IEnumerable<IContent> GetAllVersions(int id)
|
||||
@@ -273,12 +309,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var sqlFull = translate(GetBaseQuery(BaseQueryType.FullMultiple));
|
||||
var sqlIds = translate(GetBaseQuery(BaseQueryType.Ids));
|
||||
|
||||
return ProcessQuery(sqlFull, new PagingSqlQuery(sqlIds), true);
|
||||
return ProcessQuery(sqlFull, new PagingSqlQuery(sqlIds), true, includeAllVersions:true);
|
||||
}
|
||||
|
||||
public override IContent GetByVersion(Guid versionId)
|
||||
{
|
||||
var sql = GetBaseQuery(BaseQueryType.FullSingle);
|
||||
//TODO: cmsContentVersion.VersionId has a Unique Index constraint applied, seems silly then to also add OrderByDescending since it would be impossible to return more than one.
|
||||
sql.Where("cmsContentVersion.VersionId = @VersionId", new { VersionId = versionId });
|
||||
sql.OrderByDescending<ContentVersionDto>(x => x.VersionDate, SqlSyntax);
|
||||
|
||||
@@ -287,7 +324,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
if (dto == null)
|
||||
return null;
|
||||
|
||||
var content = CreateContentFromDto(dto, versionId, sql);
|
||||
var content = CreateContentFromDto(dto, sql);
|
||||
|
||||
return content;
|
||||
}
|
||||
@@ -297,7 +334,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var sql = new Sql()
|
||||
.Select("*")
|
||||
.From<DocumentDto>(SqlSyntax)
|
||||
.InnerJoin<ContentVersionDto>(SqlSyntax).On<ContentVersionDto, DocumentDto>(SqlSyntax, left => left.VersionId, right => right.VersionId)
|
||||
.InnerJoin<ContentVersionDto>(SqlSyntax)
|
||||
.On<ContentVersionDto, DocumentDto>(SqlSyntax, left => left.VersionId, right => right.VersionId)
|
||||
.Where<ContentVersionDto>(x => x.VersionId == versionId, SqlSyntax)
|
||||
.Where<DocumentDto>(x => x.Newest != true, SqlSyntax);
|
||||
var dto = Database.Fetch<DocumentDto, ContentVersionDto>(sql).FirstOrDefault();
|
||||
@@ -317,7 +355,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var sql = new Sql()
|
||||
.Select("*")
|
||||
.From<DocumentDto>()
|
||||
.InnerJoin<ContentVersionDto>().On<ContentVersionDto, DocumentDto>(left => left.VersionId, right => right.VersionId)
|
||||
.InnerJoin<ContentVersionDto>()
|
||||
.On<ContentVersionDto, DocumentDto>(left => left.VersionId, right => right.VersionId)
|
||||
.Where<ContentVersionDto>(x => x.NodeId == id)
|
||||
.Where<ContentVersionDto>(x => x.VersionDate < versionDate)
|
||||
.Where<DocumentDto>(x => x.Newest != true);
|
||||
@@ -558,6 +597,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
//if (((ICanBeDirty)entity).IsPropertyDirty("Published") && (entity.Published || publishedState == PublishedState.Unpublished))
|
||||
if (entity.ShouldClearPublishedFlagForPreviousVersions(publishedState, shouldCreateNewVersion))
|
||||
{
|
||||
//TODO: This perf can be improved, it could easily be UPDATE WHERE.... (one SQL call instead of many)
|
||||
var publishedDocs = Database.Fetch<DocumentDto>("WHERE nodeId = @Id AND published = @IsPublished", new { Id = entity.Id, IsPublished = true });
|
||||
foreach (var doc in publishedDocs)
|
||||
{
|
||||
@@ -571,6 +611,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
|
||||
//Look up (newest) entries by id in cmsDocument table to set newest = false
|
||||
//TODO: This perf can be improved, it could easily be UPDATE WHERE.... (one SQL call instead of many)
|
||||
var documentDtos = Database.Fetch<DocumentDto>("WHERE nodeId = @Id AND newest = @IsNewest", new { Id = entity.Id, IsNewest = true });
|
||||
foreach (var documentDto in documentDtos)
|
||||
{
|
||||
@@ -898,7 +939,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
|
||||
|
||||
return base.GetDatabaseFieldNameForOrderBy(orderBy);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This is the underlying method that processes most queries for this repository
|
||||
/// </summary>
|
||||
@@ -909,8 +950,12 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
|
||||
/// The Id SQL without the outer join to just return all document ids - used to process the properties for the content item
|
||||
/// </param>
|
||||
/// <param name="withCache"></param>
|
||||
/// <param name="includeAllVersions">
|
||||
/// Generally when querying for content we only want to return the most recent version of the content item, however in some cases like when
|
||||
/// we want to return all versions of a content item, we can't simply return the latest
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<IContent> ProcessQuery(Sql sqlFull, PagingSqlQuery pagingSqlQuery, bool withCache = false)
|
||||
private IEnumerable<IContent> ProcessQuery(Sql sqlFull, PagingSqlQuery pagingSqlQuery, bool withCache = false, bool includeAllVersions = false)
|
||||
{
|
||||
// fetch returns a list so it's ok to iterate it in this method
|
||||
var dtos = Database.Fetch<DocumentDto, ContentVersionDto, ContentDto, NodeDto>(sqlFull);
|
||||
@@ -929,13 +974,12 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
|
||||
parsedOriginalSql = parsedOriginalSql.Substring(0, parsedOriginalSql.LastIndexOf("ORDER BY ", StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
var publishedSql = new Sql(@"SELECT *
|
||||
FROM cmsDocument AS doc2
|
||||
INNER JOIN
|
||||
(" + parsedOriginalSql + @") as docData
|
||||
ON doc2.nodeId = docData.nodeId
|
||||
WHERE doc2.published = 1
|
||||
ORDER BY doc2.nodeId
|
||||
//order by update date DESC, if there is corrupted published flags we only want the latest!
|
||||
var publishedSql = new Sql(@"SELECT cmsDocument.nodeId, cmsDocument.published, cmsDocument.versionId, cmsDocument.newest
|
||||
FROM cmsDocument INNER JOIN cmsContentVersion ON cmsContentVersion.VersionId = cmsDocument.versionId
|
||||
WHERE cmsDocument.published = 1 AND cmsDocument.nodeId IN
|
||||
(" + parsedOriginalSql + @")
|
||||
ORDER BY cmsContentVersion.id DESC
|
||||
", sqlFull.Arguments);
|
||||
|
||||
//go and get the published version data, we do a Query here and not a Fetch so we are
|
||||
@@ -950,9 +994,9 @@ ORDER BY doc2.nodeId
|
||||
publishedDataCollection.Add(publishedDto);
|
||||
}
|
||||
|
||||
|
||||
var content = new IContent[dtos.Count];
|
||||
var defs = new List<DocumentDefinition>();
|
||||
//This is a tuple list identifying if the content item came from the cache or not
|
||||
var content = new List<Tuple<IContent, bool>>();
|
||||
var defs = new DocumentDefinitionCollection(includeAllVersions);
|
||||
var templateIds = new List<int>();
|
||||
|
||||
//track the looked up content types, even though the content types are cached
|
||||
@@ -960,9 +1004,8 @@ ORDER BY doc2.nodeId
|
||||
// the overhead of deep cloning them on every item in this loop
|
||||
var contentTypes = new Dictionary<int, IContentType>();
|
||||
|
||||
for (var i = 0; i < dtos.Count; i++)
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
var dto = dtos[i];
|
||||
DocumentPublishedReadOnlyDto publishedDto;
|
||||
publishedDataCollection.TryGetValue(dto.NodeId, out publishedDto);
|
||||
|
||||
@@ -970,10 +1013,10 @@ ORDER BY doc2.nodeId
|
||||
if (withCache)
|
||||
{
|
||||
var cached = IsolatedCache.GetCacheItem<IContent>(GetCacheIdKey<IContent>(dto.NodeId));
|
||||
//only use this cached version if the dto returned is also the publish version, they must match
|
||||
if (cached != null && cached.Published && dto.Published)
|
||||
//only use this cached version if the dto returned is also the publish version, they must match and be teh same version
|
||||
if (cached != null && cached.Version == dto.VersionId && cached.Published && dto.Published)
|
||||
{
|
||||
content[i] = cached;
|
||||
content.Add(new Tuple<IContent, bool>(cached, true));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -991,21 +1034,16 @@ ORDER BY doc2.nodeId
|
||||
contentType = _contentTypeRepository.Get(dto.ContentVersionDto.ContentDto.ContentTypeId);
|
||||
contentTypes[dto.ContentVersionDto.ContentDto.ContentTypeId] = contentType;
|
||||
}
|
||||
|
||||
content[i] = ContentFactory.BuildEntity(dto, contentType, publishedDto);
|
||||
|
||||
// need template
|
||||
if (dto.TemplateId.HasValue && dto.TemplateId.Value > 0)
|
||||
templateIds.Add(dto.TemplateId.Value);
|
||||
// track the definition and if it's successfully added or updated then processed
|
||||
if (defs.AddOrUpdate(new DocumentDefinition(dto, contentType)))
|
||||
{
|
||||
// assign template
|
||||
if (dto.TemplateId.HasValue && dto.TemplateId.Value > 0)
|
||||
templateIds.Add(dto.TemplateId.Value);
|
||||
|
||||
// need properties
|
||||
defs.Add(new DocumentDefinition(
|
||||
dto.NodeId,
|
||||
dto.VersionId,
|
||||
dto.ContentVersionDto.VersionDate,
|
||||
dto.ContentVersionDto.ContentDto.NodeDto.CreateDate,
|
||||
contentType
|
||||
));
|
||||
content.Add(new Tuple<IContent, bool>(ContentFactory.BuildEntity(dto, contentType, publishedDto), false));
|
||||
}
|
||||
}
|
||||
|
||||
// load all required templates in 1 query
|
||||
@@ -1015,38 +1053,38 @@ ORDER BY doc2.nodeId
|
||||
// load all properties for all documents from database in 1 query
|
||||
var propertyData = GetPropertyCollection(pagingSqlQuery, defs);
|
||||
|
||||
// assign
|
||||
var dtoIndex = 0;
|
||||
foreach (var def in defs)
|
||||
// assign template and property data
|
||||
foreach (var contentItem in content)
|
||||
{
|
||||
// move to corresponding item (which has to exist)
|
||||
while (dtos[dtoIndex].NodeId != def.Id) dtoIndex++;
|
||||
var cc = contentItem.Item1;
|
||||
var fromCache = contentItem.Item2;
|
||||
|
||||
//if this has come from cache, we do not need to build up it's structure
|
||||
if (fromCache) continue;
|
||||
|
||||
var def = defs[includeAllVersions ? (ValueType)cc.Version : cc.Id];
|
||||
|
||||
// complete the item
|
||||
var cc = content[dtoIndex];
|
||||
var dto = dtos[dtoIndex];
|
||||
ITemplate template = null;
|
||||
if (dto.TemplateId.HasValue)
|
||||
templates.TryGetValue(dto.TemplateId.Value, out template); // else null
|
||||
if (def.DocumentDto.TemplateId.HasValue)
|
||||
templates.TryGetValue(def.DocumentDto.TemplateId.Value, out template); // else null
|
||||
cc.Template = template;
|
||||
cc.Properties = propertyData[cc.Id];
|
||||
cc.Properties = propertyData[cc.Version];
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
cc.ResetDirtyProperties(false);
|
||||
}
|
||||
|
||||
return content;
|
||||
return content.Select(x => x.Item1).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private method to create a content object from a DocumentDto, which is used by Get and GetByVersion.
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <param name="versionId"></param>
|
||||
/// <param name="docSql"></param>
|
||||
/// <returns></returns>
|
||||
private IContent CreateContentFromDto(DocumentDto dto, Guid versionId, Sql docSql)
|
||||
private IContent CreateContentFromDto(DocumentDto dto, Sql docSql)
|
||||
{
|
||||
var contentType = _contentTypeRepository.Get(dto.ContentVersionDto.ContentDto.ContentTypeId);
|
||||
|
||||
@@ -1058,11 +1096,11 @@ ORDER BY doc2.nodeId
|
||||
content.Template = _templateRepository.Get(dto.TemplateId.Value);
|
||||
}
|
||||
|
||||
var docDef = new DocumentDefinition(dto.NodeId, versionId, content.UpdateDate, content.CreateDate, contentType);
|
||||
var docDef = new DocumentDefinition(dto, contentType);
|
||||
|
||||
var properties = GetPropertyCollection(docSql, new[] { docDef });
|
||||
|
||||
content.Properties = properties[dto.NodeId];
|
||||
content.Properties = properties[dto.VersionId];
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
|
||||
@@ -104,7 +104,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
if (objectTypes.Any())
|
||||
{
|
||||
sql = sql.Where("umbracoNode.nodeObjectType IN (@objectTypes)", objectTypes);
|
||||
sql = sql.Where("umbracoNode.nodeObjectType IN (@objectTypes)", new {objectTypes = objectTypes});
|
||||
}
|
||||
|
||||
return Database.Fetch<string>(sql);
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Globalization;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Core.Strings;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
@@ -187,10 +182,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
|
||||
var sql = GetFullSqlForEntityType(key, isContent, isMedia, objectTypeId);
|
||||
|
||||
|
||||
var factory = new UmbracoEntityFactory();
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
//Treat media differently for now, as an Entity it will be returned with ALL of it's properties in the AdditionalData bag!
|
||||
//for now treat media differently and include all property data too
|
||||
var entities = _work.Database.Fetch<dynamic, UmbracoPropertyDto, UmbracoEntity>(
|
||||
new UmbracoEntityRelator().Map, sql);
|
||||
|
||||
@@ -198,14 +195,16 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
else
|
||||
{
|
||||
var nodeDto = _work.Database.FirstOrDefault<dynamic>(sql);
|
||||
if (nodeDto == null)
|
||||
return null;
|
||||
|
||||
var factory = new UmbracoEntityFactory();
|
||||
var entity = factory.BuildEntityFromDynamic(nodeDto);
|
||||
|
||||
return entity;
|
||||
//query = read forward data reader, do not load everything into mem
|
||||
var dtos = _work.Database.Query<dynamic>(sql);
|
||||
var collection = new EntityDefinitionCollection();
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
collection.AddOrUpdate(new EntityDefinition(factory, dto, isContent, false));
|
||||
}
|
||||
var found = collection.FirstOrDefault();
|
||||
return found != null ? found.BuildFromDynamic() : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -230,28 +229,29 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media);
|
||||
|
||||
var sql = GetFullSqlForEntityType(id, isContent, isMedia, objectTypeId);
|
||||
|
||||
|
||||
var factory = new UmbracoEntityFactory();
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
//Treat media differently for now, as an Entity it will be returned with ALL of it's properties in the AdditionalData bag!
|
||||
//for now treat media differently and include all property data too
|
||||
var entities = _work.Database.Fetch<dynamic, UmbracoPropertyDto, UmbracoEntity>(
|
||||
new UmbracoEntityRelator().Map, sql);
|
||||
|
||||
return entities.FirstOrDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
var nodeDto = _work.Database.FirstOrDefault<dynamic>(sql);
|
||||
if (nodeDto == null)
|
||||
return null;
|
||||
|
||||
var factory = new UmbracoEntityFactory();
|
||||
var entity = factory.BuildEntityFromDynamic(nodeDto);
|
||||
|
||||
return entity;
|
||||
{
|
||||
//query = read forward data reader, do not load everything into mem
|
||||
var dtos = _work.Database.Query<dynamic>(sql);
|
||||
var collection = new EntityDefinitionCollection();
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
collection.AddOrUpdate(new EntityDefinition(factory, dto, isContent, false));
|
||||
}
|
||||
var found = collection.FirstOrDefault();
|
||||
return found != null ? found.BuildFromDynamic() : null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public virtual IEnumerable<IUmbracoEntity> GetAll(Guid objectTypeId, params int[] ids)
|
||||
@@ -288,21 +288,21 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
if (isMedia)
|
||||
{
|
||||
//Treat media differently for now, as an Entity it will be returned with ALL of it's properties in the AdditionalData bag!
|
||||
//for now treat media differently and include all property data too
|
||||
var entities = _work.Database.Fetch<dynamic, UmbracoPropertyDto, UmbracoEntity>(
|
||||
new UmbracoEntityRelator().Map, sql);
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
yield return entity;
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
else
|
||||
{
|
||||
var dtos = _work.Database.Fetch<dynamic>(sql);
|
||||
foreach (var entity in dtos.Select(dto => factory.BuildEntityFromDynamic(dto)))
|
||||
//query = read forward data reader, do not load everything into mem
|
||||
var dtos = _work.Database.Query<dynamic>(sql);
|
||||
var collection = new EntityDefinitionCollection();
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
yield return entity;
|
||||
collection.AddOrUpdate(new EntityDefinition(factory, dto, isContent, false));
|
||||
}
|
||||
return collection.Select(x => x.BuildFromDynamic()).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,7 +347,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
});
|
||||
|
||||
//Treat media differently for now, as an Entity it will be returned with ALL of it's properties in the AdditionalData bag!
|
||||
//for now treat media differently and include all property data too
|
||||
var entities = _work.Database.Fetch<dynamic, UmbracoPropertyDto, UmbracoEntity>(
|
||||
new UmbracoEntityRelator().Map, mediaSql);
|
||||
return entities;
|
||||
@@ -356,8 +356,15 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
//use dynamic so that we can get ALL properties from the SQL so we can chuck that data into our AdditionalData
|
||||
var finalSql = entitySql.Append(GetGroupBy(isContent, false));
|
||||
var dtos = _work.Database.Fetch<dynamic>(finalSql);
|
||||
return dtos.Select(factory.BuildEntityFromDynamic).Cast<IUmbracoEntity>().ToList();
|
||||
|
||||
//query = read forward data reader, do not load everything into mem
|
||||
var dtos = _work.Database.Query<dynamic>(finalSql);
|
||||
var collection = new EntityDefinitionCollection();
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
collection.AddOrUpdate(new EntityDefinition(factory, dto, isContent, false));
|
||||
}
|
||||
return collection.Select(x => x.BuildFromDynamic()).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,9 +475,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
if (isContent)
|
||||
{
|
||||
//only content has this info
|
||||
//only content has/needs this info
|
||||
columns.Add("published.versionId as publishedVersion");
|
||||
columns.Add("document.versionId as newestVersion");
|
||||
columns.Add("contentversion.id as versionId");
|
||||
}
|
||||
|
||||
columns.Add("contenttype.alias");
|
||||
@@ -485,21 +493,22 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var entitySql = new Sql()
|
||||
.Select(columns.ToArray())
|
||||
.From("umbracoNode umbracoNode");
|
||||
|
||||
|
||||
if (isContent || isMedia)
|
||||
{
|
||||
entitySql.InnerJoin("cmsContent content").On("content.nodeId = umbracoNode.id");
|
||||
|
||||
if (isContent)
|
||||
{
|
||||
//only content has this info
|
||||
entitySql
|
||||
//only content has/needs this info
|
||||
entitySql
|
||||
.InnerJoin("cmsDocument document").On("document.nodeId = umbracoNode.id")
|
||||
.InnerJoin("cmsContentVersion contentversion").On("contentversion.VersionId = document.versionId")
|
||||
.LeftJoin("(SELECT nodeId, versionId FROM cmsDocument WHERE published = 1) as published")
|
||||
.On("umbracoNode.id = published.nodeId");
|
||||
}
|
||||
|
||||
entitySql.LeftJoin("cmsContentType contenttype").On("contenttype.nodeId = content.contentType");
|
||||
entitySql.LeftJoin("cmsContentType contenttype").On("contenttype.nodeId = content.contentType");
|
||||
}
|
||||
|
||||
if (isCount == false)
|
||||
@@ -546,7 +555,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
protected virtual Sql GetBaseWhere(Func<bool, bool, Action<Sql>, Sql> baseQuery, bool isContent, bool isMedia, Guid key)
|
||||
{
|
||||
var sql = baseQuery(isContent, isMedia, null)
|
||||
.Where("umbracoNode.uniqueID = @UniqueID", new { UniqueID = key });
|
||||
.Where("umbracoNode.uniqueID = @UniqueID", new {UniqueID = key});
|
||||
|
||||
if (isContent)
|
||||
{
|
||||
@@ -609,13 +618,14 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
columns.Add("published.versionId");
|
||||
columns.Add("document.versionId");
|
||||
columns.Add("contentversion.id");
|
||||
}
|
||||
columns.Add("contenttype.alias");
|
||||
columns.Add("contenttype.icon");
|
||||
columns.Add("contenttype.thumbnail");
|
||||
columns.Add("contenttype.isContainer");
|
||||
columns.Add("contenttype.isContainer");
|
||||
}
|
||||
|
||||
|
||||
var sql = new Sql()
|
||||
.GroupBy(columns.ToArray());
|
||||
|
||||
@@ -626,7 +636,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -652,33 +662,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return _work.Database.ExecuteScalar<int>(sql) > 0;
|
||||
}
|
||||
|
||||
#region umbracoNode POCO - Extends NodeDto
|
||||
[TableName("umbracoNode")]
|
||||
[PrimaryKey("id")]
|
||||
[ExplicitColumns]
|
||||
internal class UmbracoEntityDto : NodeDto
|
||||
{
|
||||
[Column("children")]
|
||||
public int Children { get; set; }
|
||||
|
||||
[Column("publishedVersion")]
|
||||
public Guid PublishedVersion { get; set; }
|
||||
|
||||
[Column("newestVersion")]
|
||||
public Guid NewestVersion { get; set; }
|
||||
|
||||
[Column("alias")]
|
||||
public string Alias { get; set; }
|
||||
|
||||
[Column("icon")]
|
||||
public string Icon { get; set; }
|
||||
|
||||
[Column("thumbnail")]
|
||||
public string Thumbnail { get; set; }
|
||||
|
||||
[ResultColumn]
|
||||
public List<UmbracoPropertyDto> UmbracoPropertyDtos { get; set; }
|
||||
}
|
||||
#region private classes
|
||||
|
||||
[ExplicitColumns]
|
||||
internal class UmbracoPropertyDto
|
||||
@@ -762,6 +746,99 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
|
||||
private class EntityDefinitionCollection : KeyedCollection<int, EntityDefinition>
|
||||
{
|
||||
protected override int GetKeyForItem(EntityDefinition item)
|
||||
{
|
||||
return item.Id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// if this key already exists if it does then we need to check
|
||||
/// if the existing item is 'older' than the new item and if that is the case we'll replace the older one
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public bool AddOrUpdate(EntityDefinition item)
|
||||
{
|
||||
if (Dictionary == null)
|
||||
{
|
||||
base.Add(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
var key = GetKeyForItem(item);
|
||||
EntityDefinition found;
|
||||
if (TryGetValue(key, out found))
|
||||
{
|
||||
//it already exists and it's older so we need to replace it
|
||||
if (item.VersionId > found.VersionId)
|
||||
{
|
||||
var currIndex = Items.IndexOf(found);
|
||||
if (currIndex == -1)
|
||||
throw new IndexOutOfRangeException("Could not find the item in the list: " + found.Id);
|
||||
|
||||
//replace the current one with the newer one
|
||||
SetItem(currIndex, item);
|
||||
return true;
|
||||
}
|
||||
//could not add or update
|
||||
return false;
|
||||
}
|
||||
|
||||
base.Add(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryGetValue(int key, out EntityDefinition val)
|
||||
{
|
||||
if (Dictionary == null)
|
||||
{
|
||||
val = null;
|
||||
return false;
|
||||
}
|
||||
return Dictionary.TryGetValue(key, out val);
|
||||
}
|
||||
}
|
||||
|
||||
private class EntityDefinition
|
||||
{
|
||||
private readonly UmbracoEntityFactory _factory;
|
||||
private readonly dynamic _entity;
|
||||
private readonly bool _isContent;
|
||||
private readonly bool _isMedia;
|
||||
|
||||
public EntityDefinition(UmbracoEntityFactory factory, dynamic entity, bool isContent, bool isMedia)
|
||||
{
|
||||
_factory = factory;
|
||||
_entity = entity;
|
||||
_isContent = isContent;
|
||||
_isMedia = isMedia;
|
||||
}
|
||||
|
||||
public IUmbracoEntity BuildFromDynamic()
|
||||
{
|
||||
return _factory.BuildEntityFromDynamic(_entity);
|
||||
}
|
||||
|
||||
public int Id
|
||||
{
|
||||
get { return _entity.id; }
|
||||
}
|
||||
|
||||
public int VersionId
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_isContent || _isMedia)
|
||||
{
|
||||
return _entity.versionId;
|
||||
}
|
||||
return _entity.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <param name="serializer">The serializer to convert TEntity to Xml</param>
|
||||
/// <param name="groupSize">Structures will be rebuilt in chunks of this size</param>
|
||||
/// <param name="contentTypeIds"></param>
|
||||
void RebuildXmlStructures(Func<TEntity, XElement> serializer, int groupSize = 5000, IEnumerable<int> contentTypeIds = null);
|
||||
void RebuildXmlStructures(Func<TEntity, XElement> serializer, int groupSize = 200, IEnumerable<int> contentTypeIds = null);
|
||||
|
||||
/// <summary>
|
||||
/// Get the total count of entities
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
if (dto == null)
|
||||
return null;
|
||||
|
||||
var content = CreateMediaFromDto(dto, dto.VersionId, sql);
|
||||
var content = CreateMediaFromDto(dto, sql);
|
||||
|
||||
return content;
|
||||
}
|
||||
@@ -94,6 +94,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
.On<ContentVersionDto, ContentDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<NodeDto>(SqlSyntax)
|
||||
.On<ContentDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId, SqlSyntax)
|
||||
//TODO: IF we want to enable querying on content type information this will need to be joined
|
||||
//.InnerJoin<ContentTypeDto>(SqlSyntax)
|
||||
//.On<ContentDto, ContentTypeDto>(SqlSyntax, left => left.ContentTypeId, right => right.NodeId, SqlSyntax);
|
||||
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId, SqlSyntax);
|
||||
return sql;
|
||||
}
|
||||
@@ -161,25 +164,27 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
// fetch returns a list so it's ok to iterate it in this method
|
||||
var dtos = Database.Fetch<ContentVersionDto, ContentDto, NodeDto>(sqlFull);
|
||||
var content = new IMedia[dtos.Count];
|
||||
var defs = new List<DocumentDefinition>();
|
||||
|
||||
//This is a tuple list identifying if the content item came from the cache or not
|
||||
var content = new List<Tuple<IMedia, bool>>();
|
||||
var defs = new DocumentDefinitionCollection();
|
||||
|
||||
//track the looked up content types, even though the content types are cached
|
||||
// they still need to be deep cloned out of the cache and we don't want to add
|
||||
// the overhead of deep cloning them on every item in this loop
|
||||
var contentTypes = new Dictionary<int, IMediaType>();
|
||||
|
||||
for (var i = 0; i < dtos.Count; i++)
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
var dto = dtos[i];
|
||||
|
||||
// if the cache contains the item, use it
|
||||
if (withCache)
|
||||
{
|
||||
var cached = IsolatedCache.GetCacheItem<IMedia>(GetCacheIdKey<IMedia>(dto.NodeId));
|
||||
if (cached != null)
|
||||
//only use this cached version if the dto returned is the same version - this is just a safety check, media doesn't
|
||||
//store different versions, but just in case someone corrupts some data we'll double check to be sure.
|
||||
if (cached != null && cached.Version == dto.VersionId)
|
||||
{
|
||||
content[i] = cached;
|
||||
content.Add(new Tuple<IMedia, bool>(cached, true));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -197,39 +202,34 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
contentType = _mediaTypeRepository.Get(dto.ContentDto.ContentTypeId);
|
||||
contentTypes[dto.ContentDto.ContentTypeId] = contentType;
|
||||
}
|
||||
|
||||
content[i] = MediaFactory.BuildEntity(dto, contentType);
|
||||
|
||||
// need properties
|
||||
defs.Add(new DocumentDefinition(
|
||||
dto.NodeId,
|
||||
dto.VersionId,
|
||||
dto.VersionDate,
|
||||
dto.ContentDto.NodeDto.CreateDate,
|
||||
contentType
|
||||
));
|
||||
// track the definition and if it's successfully added or updated then processed
|
||||
if (defs.AddOrUpdate(new DocumentDefinition(dto, contentType)))
|
||||
{
|
||||
content.Add(new Tuple<IMedia, bool>(MediaFactory.BuildEntity(dto, contentType), false));
|
||||
}
|
||||
}
|
||||
|
||||
// load all properties for all documents from database in 1 query
|
||||
var propertyData = GetPropertyCollection(pagingSqlQuery, defs);
|
||||
|
||||
// assign
|
||||
var dtoIndex = 0;
|
||||
foreach (var def in defs)
|
||||
// assign property data
|
||||
foreach (var contentItem in content)
|
||||
{
|
||||
// move to corresponding item (which has to exist)
|
||||
while (dtos[dtoIndex].NodeId != def.Id) dtoIndex++;
|
||||
var cc = contentItem.Item1;
|
||||
var fromCache = contentItem.Item2;
|
||||
|
||||
// complete the item
|
||||
var cc = content[dtoIndex];
|
||||
cc.Properties = propertyData[cc.Id];
|
||||
//if this has come from cache, we do not need to build up it's structure
|
||||
if (fromCache) continue;
|
||||
|
||||
cc.Properties = propertyData[cc.Version];
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
cc.ResetDirtyProperties(false);
|
||||
}
|
||||
|
||||
return content;
|
||||
return content.Select(x => x.Item1).ToArray();
|
||||
}
|
||||
|
||||
public override IMedia GetByVersion(Guid versionId)
|
||||
@@ -243,7 +243,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
if (dto == null)
|
||||
return null;
|
||||
|
||||
var content = CreateMediaFromDto(dto, versionId, sql);
|
||||
var content = CreateMediaFromDto(dto, sql);
|
||||
|
||||
return content;
|
||||
}
|
||||
@@ -263,10 +263,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
// get the next group of nodes
|
||||
var query = GetBaseQuery(false);
|
||||
if (contentTypeIdsA.Length > 0)
|
||||
query = query
|
||||
.WhereIn<ContentDto>(x => x.ContentTypeId, contentTypeIdsA, SqlSyntax);
|
||||
{
|
||||
query = query.WhereIn<ContentDto>(x => x.ContentTypeId, contentTypeIdsA, SqlSyntax);
|
||||
}
|
||||
query = query
|
||||
.Where<NodeDto>(x => x.NodeId > baseId, SqlSyntax)
|
||||
.Where<NodeDto>(x => x.Trashed == false, SqlSyntax)
|
||||
.OrderBy<NodeDto>(x => x.NodeId, SqlSyntax);
|
||||
var sql = SqlSyntax.SelectTop(query, groupSize);
|
||||
var xmlItems = ProcessQuery(sql, new PagingSqlQuery(sql))
|
||||
@@ -290,7 +292,38 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
Logger.Error<MediaRepository>("Could not rebuild XML for nodeId=" + xmlItem.NodeId, e);
|
||||
}
|
||||
}
|
||||
baseId = xmlItems.Last().NodeId;
|
||||
baseId = xmlItems[xmlItems.Count - 1].NodeId;
|
||||
}
|
||||
|
||||
//now delete the items that shouldn't be there
|
||||
var allMediaIds = Database.Fetch<int>(GetBaseQuery(BaseQueryType.Ids).Where<NodeDto>(x => x.Trashed == false, SqlSyntax));
|
||||
var mediaObjectType = Guid.Parse(Constants.ObjectTypes.Media);
|
||||
var xmlIdsQuery = new Sql()
|
||||
.Select("DISTINCT cmsContentXml.nodeId")
|
||||
.From<ContentXmlDto>(SqlSyntax)
|
||||
.InnerJoin<NodeDto>(SqlSyntax)
|
||||
.On<ContentXmlDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId);
|
||||
|
||||
if (contentTypeIdsA.Length > 0)
|
||||
{
|
||||
xmlIdsQuery.InnerJoin<ContentDto>(SqlSyntax)
|
||||
.On<ContentDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<ContentTypeDto>(SqlSyntax)
|
||||
.On<ContentTypeDto, ContentDto>(SqlSyntax, left => left.NodeId, right => right.ContentTypeId)
|
||||
.WhereIn<ContentDto>(x => x.ContentTypeId, contentTypeIdsA, SqlSyntax);
|
||||
}
|
||||
|
||||
xmlIdsQuery.Where<NodeDto>(dto => dto.NodeObjectType == mediaObjectType, SqlSyntax);
|
||||
|
||||
var allXmlIds = Database.Fetch<int>(xmlIdsQuery);
|
||||
|
||||
var toRemove = allXmlIds.Except(allMediaIds).ToArray();
|
||||
if (toRemove.Length > 0)
|
||||
{
|
||||
foreach (var idGroup in toRemove.InGroupsOf(2000))
|
||||
{
|
||||
Database.Execute("DELETE FROM cmsContentXml WHERE nodeId IN (@ids)", new { ids = idGroup });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,20 +559,19 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// Private method to create a media object from a ContentDto
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <param name="versionId"></param>
|
||||
/// <param name="docSql"></param>
|
||||
/// <returns></returns>
|
||||
private IMedia CreateMediaFromDto(ContentVersionDto dto, Guid versionId, Sql docSql)
|
||||
private IMedia CreateMediaFromDto(ContentVersionDto dto, Sql docSql)
|
||||
{
|
||||
var contentType = _mediaTypeRepository.Get(dto.ContentDto.ContentTypeId);
|
||||
|
||||
var media = MediaFactory.BuildEntity(dto, contentType);
|
||||
|
||||
var docDef = new DocumentDefinition(dto.NodeId, versionId, media.UpdateDate, media.CreateDate, contentType);
|
||||
var docDef = new DocumentDefinition(dto, contentType);
|
||||
|
||||
var properties = GetPropertyCollection(new PagingSqlQuery(docSql), new[] { docDef });
|
||||
|
||||
media.Properties = properties[dto.NodeId];
|
||||
media.Properties = properties[dto.VersionId];
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
if (dto == null)
|
||||
return null;
|
||||
|
||||
var content = CreateMemberFromDto(dto, dto.ContentVersionDto.VersionId, sql);
|
||||
var content = CreateMemberFromDto(dto, sql);
|
||||
|
||||
return content;
|
||||
|
||||
@@ -448,16 +448,16 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var memberType = _memberTypeRepository.Get(dto.ContentVersionDto.ContentDto.ContentTypeId);
|
||||
|
||||
var factory = new MemberFactory(memberType, NodeObjectTypeId, dto.NodeId);
|
||||
var media = factory.BuildEntity(dto);
|
||||
var member = factory.BuildEntity(dto);
|
||||
|
||||
var properties = GetPropertyCollection(new PagingSqlQuery(sql), new[] { new DocumentDefinition(dto.NodeId, dto.ContentVersionDto.VersionId, media.UpdateDate, media.CreateDate, memberType) });
|
||||
var properties = GetPropertyCollection(new PagingSqlQuery(sql), new[] { new DocumentDefinition(dto.ContentVersionDto, memberType) });
|
||||
|
||||
media.Properties = properties[dto.NodeId];
|
||||
member.Properties = properties[dto.ContentVersionDto.VersionId];
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
((Entity)media).ResetDirtyProperties(false);
|
||||
return media;
|
||||
((Entity)member).ResetDirtyProperties(false);
|
||||
return member;
|
||||
|
||||
}
|
||||
|
||||
@@ -658,20 +658,21 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
// fetch returns a list so it's ok to iterate it in this method
|
||||
var dtos = Database.Fetch<MemberDto, ContentVersionDto, ContentDto, NodeDto>(sqlFull);
|
||||
|
||||
var content = new IMember[dtos.Count];
|
||||
var defs = new List<DocumentDefinition>();
|
||||
//This is a tuple list identifying if the content item came from the cache or not
|
||||
var content = new List<Tuple<IMember, bool>>();
|
||||
var defs = new DocumentDefinitionCollection();
|
||||
|
||||
for (var i = 0; i < dtos.Count; i++)
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
var dto = dtos[i];
|
||||
|
||||
// if the cache contains the item, use it
|
||||
if (withCache)
|
||||
{
|
||||
var cached = IsolatedCache.GetCacheItem<IMember>(GetCacheIdKey<IMember>(dto.NodeId));
|
||||
if (cached != null)
|
||||
//only use this cached version if the dto returned is the same version - this is just a safety check, members dont
|
||||
//store different versions, but just in case someone corrupts some data we'll double check to be sure.
|
||||
if (cached != null && cached.Version == dto.ContentVersionDto.VersionId)
|
||||
{
|
||||
content[i] = cached;
|
||||
content.Add(new Tuple<IMember, bool>(cached, true));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -679,60 +680,54 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
// else, need to fetch from the database
|
||||
// content type repository is full-cache so OK to get each one independently
|
||||
var contentType = _memberTypeRepository.Get(dto.ContentVersionDto.ContentDto.ContentTypeId);
|
||||
var factory = new MemberFactory(contentType, NodeObjectTypeId, dto.NodeId);
|
||||
content[i] = factory.BuildEntity(dto);
|
||||
|
||||
// need properties
|
||||
defs.Add(new DocumentDefinition(
|
||||
dto.NodeId,
|
||||
dto.ContentVersionDto.VersionId,
|
||||
dto.ContentVersionDto.VersionDate,
|
||||
dto.ContentVersionDto.ContentDto.NodeDto.CreateDate,
|
||||
contentType
|
||||
));
|
||||
if (defs.AddOrUpdate(new DocumentDefinition(dto.ContentVersionDto, contentType)))
|
||||
{
|
||||
content.Add(new Tuple<IMember, bool>(MemberFactory.BuildEntity(dto, contentType), false));
|
||||
}
|
||||
}
|
||||
|
||||
// load all properties for all documents from database in 1 query
|
||||
var propertyData = GetPropertyCollection(pagingSqlQuery, defs);
|
||||
|
||||
// assign
|
||||
var dtoIndex = 0;
|
||||
foreach (var def in defs)
|
||||
// assign property data
|
||||
foreach (var contentItem in content)
|
||||
{
|
||||
// move to corresponding item (which has to exist)
|
||||
while (dtos[dtoIndex].NodeId != def.Id) dtoIndex++;
|
||||
var cc = contentItem.Item1;
|
||||
var fromCache = contentItem.Item2;
|
||||
|
||||
// complete the item
|
||||
var cc = content[dtoIndex];
|
||||
cc.Properties = propertyData[cc.Id];
|
||||
//if this has come from cache, we do not need to build up it's structure
|
||||
if (fromCache) continue;
|
||||
|
||||
cc.Properties = propertyData[cc.Version];
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
((Entity)cc).ResetDirtyProperties(false);
|
||||
cc.ResetDirtyProperties(false);
|
||||
}
|
||||
|
||||
return content;
|
||||
return content.Select(x => x.Item1).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private method to create a member object from a MemberDto
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <param name="versionId"></param>
|
||||
/// <param name="docSql"></param>
|
||||
/// <returns></returns>
|
||||
private IMember CreateMemberFromDto(MemberDto dto, Guid versionId, Sql docSql)
|
||||
private IMember CreateMemberFromDto(MemberDto dto, Sql docSql)
|
||||
{
|
||||
var memberType = _memberTypeRepository.Get(dto.ContentVersionDto.ContentDto.ContentTypeId);
|
||||
|
||||
var factory = new MemberFactory(memberType, NodeObjectTypeId, dto.ContentVersionDto.NodeId);
|
||||
var member = factory.BuildEntity(dto);
|
||||
|
||||
var docDef = new DocumentDefinition(dto.ContentVersionDto.NodeId, versionId, member.UpdateDate, member.CreateDate, memberType);
|
||||
var docDef = new DocumentDefinition(dto.ContentVersionDto, memberType);
|
||||
|
||||
var properties = GetPropertyCollection(docSql, new[] { docDef });
|
||||
|
||||
member.Properties = properties[dto.ContentVersionDto.NodeId];
|
||||
member.Properties = properties[dto.ContentVersionDto.VersionId];
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
|
||||
@@ -38,10 +38,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
sql.Where("umbracoAccess.id IN (@ids)", new { ids = ids });
|
||||
}
|
||||
|
||||
sql.OrderBy<AccessDto>(x => x.NodeId, SqlSyntax);
|
||||
|
||||
|
||||
var factory = new PublicAccessEntryFactory();
|
||||
//MUST be ordered by this GUID ID for the AccessRulesRelator to work
|
||||
var dtos = Database.Fetch<AccessDto, AccessRuleDto, AccessDto>(new AccessRulesRelator().Map, sql);
|
||||
return dtos.Select(factory.BuildEntity);
|
||||
}
|
||||
@@ -53,6 +52,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var sql = translator.Translate();
|
||||
|
||||
var factory = new PublicAccessEntryFactory();
|
||||
//MUST be ordered by this GUID ID for the AccessRulesRelator to work
|
||||
var dtos = Database.Fetch<AccessDto, AccessRuleDto, AccessDto>(new AccessRulesRelator().Map, sql);
|
||||
return dtos.Select(factory.BuildEntity);
|
||||
}
|
||||
@@ -63,7 +63,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
sql.Select("*")
|
||||
.From<AccessDto>(SqlSyntax)
|
||||
.LeftJoin<AccessRuleDto>(SqlSyntax)
|
||||
.On<AccessDto, AccessRuleDto>(SqlSyntax, left => left.Id, right => right.AccessId);
|
||||
.On<AccessDto, AccessRuleDto>(SqlSyntax, left => left.Id, right => right.AccessId)
|
||||
//MUST be ordered by this GUID ID for the AccessRulesRelator to work
|
||||
.OrderBy<AccessDto>(dto => dto.Id, SqlSyntax);
|
||||
|
||||
return sql;
|
||||
}
|
||||
@@ -104,6 +106,11 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
rule.AccessId = entity.Key;
|
||||
Database.Insert(rule);
|
||||
//update the id so HasEntity is correct
|
||||
var entityRule = entity.Rules.First(x => x.Key == rule.Id);
|
||||
entityRule.Id = entityRule.Key.GetHashCode();
|
||||
//double make sure that this is set since it is possible to add rules via ctor without AddRule
|
||||
entityRule.AccessEntryId = entity.Key;
|
||||
}
|
||||
|
||||
entity.ResetDirtyProperties();
|
||||
@@ -124,7 +131,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
if (rule.HasIdentity)
|
||||
{
|
||||
var count = Database.Update(dto.Rules.Single(x => x.Id == rule.Key));
|
||||
var count = Database.Update(dto.Rules.First(x => x.Id == rule.Key));
|
||||
if (count == 0)
|
||||
{
|
||||
throw new InvalidOperationException("No rows were updated for the access rule");
|
||||
@@ -150,6 +157,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
Database.Delete<AccessRuleDto>("WHERE id=@Id", new {Id = removedRule});
|
||||
}
|
||||
|
||||
entity.ClearRemovedRules();
|
||||
|
||||
entity.ResetDirtyProperties();
|
||||
}
|
||||
|
||||
@@ -158,4 +167,4 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return entity.Key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Data.SqlTypes;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -33,6 +34,11 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
private readonly IContentSection _contentSection;
|
||||
|
||||
/// <summary>
|
||||
/// This is used for unit tests ONLY
|
||||
/// </summary>
|
||||
internal static bool ThrowOnWarning = false;
|
||||
|
||||
protected VersionableRepositoryBase(IScopeUnitOfWork work, CacheHelper cache, ILogger logger, ISqlSyntaxProvider sqlSyntax, IContentSection contentSection)
|
||||
: base(work, cache, logger, sqlSyntax)
|
||||
{
|
||||
@@ -503,7 +509,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <param name="sql"></param>
|
||||
/// <param name="documentDefs"></param>
|
||||
/// <returns></returns>
|
||||
protected IDictionary<int, PropertyCollection> GetPropertyCollection(
|
||||
protected IDictionary<Guid, PropertyCollection> GetPropertyCollection(
|
||||
Sql sql,
|
||||
IReadOnlyCollection<DocumentDefinition> documentDefs)
|
||||
{
|
||||
@@ -516,11 +522,11 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <param name="pagingSqlQuery"></param>
|
||||
/// <param name="documentDefs"></param>
|
||||
/// <returns></returns>
|
||||
protected IDictionary<int, PropertyCollection> GetPropertyCollection(
|
||||
protected IDictionary<Guid, PropertyCollection> GetPropertyCollection(
|
||||
PagingSqlQuery pagingSqlQuery,
|
||||
IReadOnlyCollection<DocumentDefinition> documentDefs)
|
||||
{
|
||||
if (documentDefs.Count == 0) return new Dictionary<int, PropertyCollection>();
|
||||
if (documentDefs.Count == 0) return new Dictionary<Guid, PropertyCollection>();
|
||||
|
||||
//initialize to the query passed in
|
||||
var docSql = pagingSqlQuery.PrePagedSql;
|
||||
@@ -576,16 +582,16 @@ ON cmsPropertyData.propertytypeid = cmsPropertyType.id
|
||||
INNER JOIN
|
||||
(" + string.Format(parsedOriginalSql, "cmsContent.nodeId, cmsContentVersion.VersionId") + @") as docData
|
||||
ON cmsPropertyData.versionId = docData.VersionId AND cmsPropertyData.contentNodeId = docData.nodeId
|
||||
ORDER BY contentNodeId, propertytypeid
|
||||
ORDER BY contentNodeId, versionId, propertytypeid
|
||||
", docSql.Arguments);
|
||||
|
||||
|
||||
//This does NOT fetch all data into memory in a list, this will read
|
||||
// over the records as a data reader, this is much better for performance and memory,
|
||||
// but it means that during the reading of this data set, nothing else can be read
|
||||
// from SQL server otherwise we'll get an exception.
|
||||
var allPropertyData = Database.Query<PropertyDataDto>(propSql);
|
||||
|
||||
var result = new Dictionary<int, PropertyCollection>();
|
||||
var result = new Dictionary<Guid, PropertyCollection>();
|
||||
var propertiesWithTagSupport = new Dictionary<string, SupportTagsAttribute>();
|
||||
//used to track the resolved composition property types per content type so we don't have to re-resolve (ToArray) the list every time
|
||||
var resolvedCompositionProperties = new Dictionary<int, PropertyType[]>();
|
||||
@@ -594,11 +600,13 @@ ORDER BY contentNodeId, propertytypeid
|
||||
var propertyDataSetEnumerator = allPropertyData.GetEnumerator();
|
||||
var hasCurrent = false; // initially there is no enumerator.Current
|
||||
|
||||
var comparer = new DocumentDefinitionComparer(SqlSyntax);
|
||||
|
||||
try
|
||||
{
|
||||
//This must be sorted by node id because this is how we are sorting the query to lookup property types above,
|
||||
// which allows us to more efficiently iterate over the large data set of property values
|
||||
foreach (var def in documentDefs.OrderBy(x => x.Id))
|
||||
foreach (var def in documentDefs.OrderBy(x => x.Id).ThenBy(x => x.Version, comparer))
|
||||
{
|
||||
// get the resolved properties from our local cache, or resolve them and put them in cache
|
||||
PropertyType[] compositionProperties;
|
||||
@@ -617,15 +625,17 @@ ORDER BY contentNodeId, propertytypeid
|
||||
var propertyDataDtos = new List<PropertyDataDto>();
|
||||
while (hasCurrent || propertyDataSetEnumerator.MoveNext())
|
||||
{
|
||||
if (propertyDataSetEnumerator.Current.NodeId == def.Id)
|
||||
//Not checking null on VersionId because it can never be null - no idea why it's set to nullable
|
||||
// ReSharper disable once PossibleInvalidOperationException
|
||||
if (propertyDataSetEnumerator.Current.VersionId.Value == def.Version)
|
||||
{
|
||||
hasCurrent = false; // enumerator.Current is not available
|
||||
propertyDataDtos.Add(propertyDataSetEnumerator.Current);
|
||||
}
|
||||
else
|
||||
{
|
||||
hasCurrent = true; // enumerator.Current is available for another def
|
||||
break; // no more propertyDataDto for this def
|
||||
hasCurrent = true; // enumerator.Current is available for another def
|
||||
break; // no more propertyDataDto for this def
|
||||
}
|
||||
}
|
||||
|
||||
@@ -660,11 +670,19 @@ ORDER BY contentNodeId, propertytypeid
|
||||
}
|
||||
}
|
||||
|
||||
if (result.ContainsKey(def.Id))
|
||||
if (result.ContainsKey(def.Version))
|
||||
{
|
||||
Logger.Warn<VersionableRepositoryBase<TId, TEntity>>("The query returned multiple property sets for document definition " + def.Id + ", " + def.Composition.Name);
|
||||
var msg = string.Format("The query returned multiple property sets for document definition {0}, {1}, {2}", def.Id, def.Version, def.Composition.Name);
|
||||
if (ThrowOnWarning)
|
||||
{
|
||||
throw new InvalidOperationException(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Warn<VersionableRepositoryBase<TId, TEntity>>(msg);
|
||||
}
|
||||
}
|
||||
result[def.Id] = new PropertyCollection(properties);
|
||||
result[def.Version] = new PropertyCollection(properties);
|
||||
}
|
||||
}
|
||||
finally
|
||||
@@ -687,8 +705,8 @@ ORDER BY contentNodeId, propertytypeid
|
||||
case "NAME":
|
||||
return "umbracoNode.text";
|
||||
case "PUBLISHED":
|
||||
return "cmsDocument.published";
|
||||
case "OWNER":
|
||||
return "cmsDocument.published";
|
||||
//TODO: This isn't going to work very nicely because it's going to order by ID, not by letter
|
||||
return "umbracoNode.nodeUser";
|
||||
// Members only
|
||||
@@ -772,25 +790,159 @@ ORDER BY contentNodeId, propertytypeid
|
||||
/// <returns></returns>
|
||||
protected abstract Sql GetBaseQuery(BaseQueryType queryType);
|
||||
|
||||
internal class DocumentDefinitionCollection : KeyedCollection<ValueType, DocumentDefinition>
|
||||
{
|
||||
private readonly bool _includeAllVersions;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor specifying if all versions should be allowed, in that case the key for the collection becomes the versionId (GUID)
|
||||
/// </summary>
|
||||
/// <param name="includeAllVersions"></param>
|
||||
public DocumentDefinitionCollection(bool includeAllVersions = false)
|
||||
{
|
||||
_includeAllVersions = includeAllVersions;
|
||||
}
|
||||
|
||||
protected override ValueType GetKeyForItem(DocumentDefinition item)
|
||||
{
|
||||
return _includeAllVersions ? (ValueType)item.Version : item.Id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// if this key already exists if it does then we need to check
|
||||
/// if the existing item is 'older' than the new item and if that is the case we'll replace the older one
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public bool AddOrUpdate(DocumentDefinition item)
|
||||
{
|
||||
//if we are including all versions then just add, we aren't checking for latest
|
||||
if (_includeAllVersions)
|
||||
{
|
||||
base.Add(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Dictionary == null)
|
||||
{
|
||||
base.Add(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
var key = GetKeyForItem(item);
|
||||
DocumentDefinition found;
|
||||
if (TryGetValue(key, out found))
|
||||
{
|
||||
//it already exists and it's older so we need to replace it
|
||||
if (item.VersionId > found.VersionId)
|
||||
{
|
||||
var currIndex = Items.IndexOf(found);
|
||||
if (currIndex == -1)
|
||||
throw new IndexOutOfRangeException("Could not find the item in the list: " + found.Version);
|
||||
|
||||
//replace the current one with the newer one
|
||||
SetItem(currIndex, item);
|
||||
return true;
|
||||
}
|
||||
//could not add or update
|
||||
return false;
|
||||
}
|
||||
|
||||
base.Add(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryGetValue(ValueType key, out DocumentDefinition val)
|
||||
{
|
||||
if (Dictionary == null)
|
||||
{
|
||||
val = null;
|
||||
return false;
|
||||
}
|
||||
return Dictionary.TryGetValue(key, out val);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A custom comparer required for sorting entities by GUIDs to match how the sorting of GUIDs works on SQL server
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// MySql sorts GUIDs as a string, MSSQL sorts based on byte sections, this comparer will allow sorting GUIDs to be the same as how SQL server does
|
||||
/// </remarks>
|
||||
private class DocumentDefinitionComparer : IComparer<Guid>
|
||||
{
|
||||
private readonly ISqlSyntaxProvider _sqlSyntax;
|
||||
|
||||
public DocumentDefinitionComparer(ISqlSyntaxProvider sqlSyntax)
|
||||
{
|
||||
_sqlSyntax = sqlSyntax;
|
||||
}
|
||||
|
||||
public int Compare(Guid x, Guid y)
|
||||
{
|
||||
//MySql sorts on GUIDs as strings (i.e. normal)
|
||||
if (_sqlSyntax is MySqlSyntaxProvider)
|
||||
{
|
||||
return x.CompareTo(y);
|
||||
}
|
||||
|
||||
//MSSQL doesn't it sorts them on byte sections!
|
||||
return new SqlGuid(x).CompareTo(new SqlGuid(y));
|
||||
}
|
||||
}
|
||||
|
||||
internal class DocumentDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:System.Object"/> class.
|
||||
/// </summary>
|
||||
public DocumentDefinition(int id, Guid version, DateTime versionDate, DateTime createDate, IContentTypeComposition composition)
|
||||
public DocumentDefinition(DocumentDto dto, IContentTypeComposition composition)
|
||||
{
|
||||
Id = id;
|
||||
Version = version;
|
||||
VersionDate = versionDate;
|
||||
CreateDate = createDate;
|
||||
DocumentDto = dto;
|
||||
ContentVersionDto = dto.ContentVersionDto;
|
||||
Composition = composition;
|
||||
}
|
||||
|
||||
public int Id { get; set; }
|
||||
public Guid Version { get; set; }
|
||||
public DateTime VersionDate { get; set; }
|
||||
public DateTime CreateDate { get; set; }
|
||||
public IContentTypeComposition Composition { get; set; }
|
||||
public DocumentDefinition(ContentVersionDto dto, IContentTypeComposition composition)
|
||||
{
|
||||
ContentVersionDto = dto;
|
||||
Composition = composition;
|
||||
}
|
||||
|
||||
public DocumentDto DocumentDto { get; private set; }
|
||||
public ContentVersionDto ContentVersionDto { get; private set; }
|
||||
|
||||
public int Id
|
||||
{
|
||||
get { return ContentVersionDto.NodeId; }
|
||||
}
|
||||
|
||||
public Guid Version
|
||||
{
|
||||
get { return DocumentDto != null ? DocumentDto.VersionId : ContentVersionDto.VersionId; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is used to determien which version is the most recent
|
||||
/// </summary>
|
||||
public int VersionId
|
||||
{
|
||||
get { return ContentVersionDto.Id; }
|
||||
}
|
||||
|
||||
public DateTime VersionDate
|
||||
{
|
||||
get { return ContentVersionDto.VersionDate; }
|
||||
}
|
||||
|
||||
public DateTime CreateDate
|
||||
{
|
||||
get { return ContentVersionDto.ContentDto.NodeDto.CreateDate; }
|
||||
}
|
||||
|
||||
public IContentTypeComposition Composition { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -47,5 +47,9 @@ using System.Security.Permissions;
|
||||
[assembly: InternalsVisibleTo("Umbraco.Deploy.UI")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Deploy.Cloud")]
|
||||
|
||||
[assembly: InternalsVisibleTo("Umbraco.Forms.Core")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Forms.Core.Providers")]
|
||||
[assembly: InternalsVisibleTo("Umbraco.Forms.Web")]
|
||||
|
||||
//allow this to be mocked in our unit tests
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(IEnumerable<string>))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class CheckboxListValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.EnablePropertyValueConverters)
|
||||
{
|
||||
return propertyType.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditors.CheckBoxListAlias);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override object ConvertSourceToObject(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
var sourceString = (source ?? string.Empty).ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(sourceString))
|
||||
return Enumerable.Empty<string>();
|
||||
|
||||
var values =
|
||||
sourceString.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => v.Trim());
|
||||
|
||||
return values;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,28 @@
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using System;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(string))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class ColorPickerValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
{
|
||||
return propertyType.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditors.ColorPickerAlias);
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.EnablePropertyValueConverters)
|
||||
{
|
||||
return propertyType.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditors.ColorPickerAlias);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
// make sure it's a string
|
||||
return source.ToString();
|
||||
return source == null ? string.Empty : source.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(DateTime))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class DatePickerValueConverter : PropertyValueConverterBase
|
||||
|
||||
@@ -3,6 +3,7 @@ using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(decimal))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class DecimalValueConverter : PropertyValueConverterBase
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(IEnumerable<string>))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class DropdownListMultipleValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.EnablePropertyValueConverters)
|
||||
{
|
||||
return propertyType.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditors.DropDownListMultipleAlias);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override object ConvertSourceToObject(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
var sourceString = (source ?? "").ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(sourceString))
|
||||
return Enumerable.Empty<string>();
|
||||
|
||||
var values =
|
||||
sourceString.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => v.Trim());
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(IEnumerable<int>))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class DropdownListMultipleWithKeysValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.EnablePropertyValueConverters)
|
||||
{
|
||||
return propertyType.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditors.DropdownlistMultiplePublishKeysAlias);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
if (source == null)
|
||||
return new int[] { };
|
||||
|
||||
var prevalueIds = source.ToString()
|
||||
.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(p => p.Trim())
|
||||
.Select(int.Parse)
|
||||
.ToArray();
|
||||
|
||||
return prevalueIds;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(string))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class DropdownListValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.EnablePropertyValueConverters)
|
||||
{
|
||||
return propertyType.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditors.DropDownListAlias);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
return source == null ? string.Empty : source.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(int))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class DropdownListWithKeysValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.EnablePropertyValueConverters)
|
||||
{
|
||||
return propertyType.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditors.DropdownlistPublishingKeysAlias);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
var intAttempt = source.TryConvertTo<int>();
|
||||
if (intAttempt.Success)
|
||||
return intAttempt.Result;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(string))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class EmailAddressValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.EnablePropertyValueConverters)
|
||||
{
|
||||
return propertyType.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditors.EmailAddressAlias);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override object ConvertSourceToObject(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
return source.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(int))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class IntegerValueConverter : PropertyValueConverterBase
|
||||
|
||||
@@ -4,6 +4,7 @@ using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(IHtmlString))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class MarkdownEditorValueConverter : PropertyValueConverterBase
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(string))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class MemberGroupPickerValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.EnablePropertyValueConverters)
|
||||
{
|
||||
return propertyType.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditors.MemberGroupPickerAlias);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
return source == null ? string.Empty : source.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(IEnumerable<string>))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class MultipleTextStringValueConverter : PropertyValueConverterBase
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(int))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class RadioButtonListValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.EnablePropertyValueConverters)
|
||||
{
|
||||
return propertyType.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditors.RadioButtonListAlias);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
var intAttempt = source.TryConvertTo<int>();
|
||||
if (intAttempt.Success)
|
||||
return intAttempt.Result;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
public class SliderValueConverter : PropertyValueConverterBase, IPropertyValueConverterMeta
|
||||
{
|
||||
private readonly IDataTypeService _dataTypeService;
|
||||
|
||||
//TODO: Remove this ctor in v8 since the other one will use IoC
|
||||
public SliderValueConverter()
|
||||
: this(ApplicationContext.Current.Services.DataTypeService)
|
||||
{
|
||||
}
|
||||
|
||||
public SliderValueConverter(IDataTypeService dataTypeService)
|
||||
{
|
||||
if (dataTypeService == null) throw new ArgumentNullException("dataTypeService");
|
||||
_dataTypeService = dataTypeService;
|
||||
}
|
||||
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.EnablePropertyValueConverters)
|
||||
{
|
||||
return propertyType.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditors.SliderAlias);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override object ConvertSourceToObject(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (IsRangeDataType(propertyType.DataTypeId))
|
||||
{
|
||||
var rangeRawValues = source.ToString().Split(',');
|
||||
var minimumAttempt = rangeRawValues[0].TryConvertTo<decimal>();
|
||||
var maximumAttempt = rangeRawValues[1].TryConvertTo<decimal>();
|
||||
|
||||
if (minimumAttempt.Success && maximumAttempt.Success)
|
||||
{
|
||||
return new Range<decimal>() { Maximum = maximumAttempt.Result, Minimum = minimumAttempt.Result };
|
||||
}
|
||||
}
|
||||
|
||||
var valueAttempt = source.ToString().TryConvertTo<decimal>();
|
||||
if (valueAttempt.Success)
|
||||
{
|
||||
return valueAttempt.Result;
|
||||
}
|
||||
|
||||
// Something failed in the conversion of the strings to decimals
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
public Type GetPropertyValueType(PublishedPropertyType propertyType)
|
||||
{
|
||||
if (IsRangeDataType(propertyType.DataTypeId))
|
||||
{
|
||||
return typeof(Range<decimal>);
|
||||
}
|
||||
return typeof(decimal);
|
||||
}
|
||||
|
||||
public PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType, PropertyCacheValue cacheValue)
|
||||
{
|
||||
return PropertyCacheLevel.Content;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Discovers if the slider is set to range mode.
|
||||
/// </summary>
|
||||
/// <param name="dataTypeId">
|
||||
/// The data type id.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The <see cref="bool"/>.
|
||||
/// </returns>
|
||||
private bool IsRangeDataType(int dataTypeId)
|
||||
{
|
||||
// ** This must be cached (U4-8862) **
|
||||
var enableRange =
|
||||
_dataTypeService.GetPreValuesCollectionByDataTypeId(dataTypeId)
|
||||
.PreValuesAsDictionary.FirstOrDefault(
|
||||
x => string.Equals(x.Key, "enableRange", StringComparison.InvariantCultureIgnoreCase)).Value;
|
||||
|
||||
return enableRange != null && enableRange.Value.TryConvertTo<bool>().Result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(IEnumerable<string>))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class TagsValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
private readonly IDataTypeService _dataTypeService;
|
||||
|
||||
//TODO: Remove this ctor in v8 since the other one will use IoC
|
||||
public TagsValueConverter()
|
||||
: this(ApplicationContext.Current.Services.DataTypeService)
|
||||
{
|
||||
}
|
||||
|
||||
public TagsValueConverter(IDataTypeService dataTypeService)
|
||||
{
|
||||
if (dataTypeService == null) throw new ArgumentNullException("dataTypeService");
|
||||
_dataTypeService = dataTypeService;
|
||||
}
|
||||
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.EnablePropertyValueConverters)
|
||||
{
|
||||
return propertyType.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditors.TagsAlias);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
// if Json storage type deserialzie and return as string array
|
||||
if (JsonStorageType(propertyType.DataTypeId))
|
||||
{
|
||||
var jArray = JsonConvert.DeserializeObject<JArray>(source.ToString());
|
||||
return jArray.ToObject<string[]>();
|
||||
}
|
||||
|
||||
// Otherwise assume CSV storage type and return as string array
|
||||
var csvTags =
|
||||
source.ToString()
|
||||
.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.ToArray();
|
||||
return csvTags;
|
||||
}
|
||||
|
||||
public override object ConvertSourceToObject(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return (string[]) source;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Discovers if the tags data type is storing its data in a Json format
|
||||
/// </summary>
|
||||
/// <param name="dataTypeId">
|
||||
/// The data type id.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The <see cref="bool"/>.
|
||||
/// </returns>
|
||||
private bool JsonStorageType(int dataTypeId)
|
||||
{
|
||||
// ** This must be cached (U4-8862) **
|
||||
var storageType =
|
||||
_dataTypeService.GetPreValuesCollectionByDataTypeId(dataTypeId)
|
||||
.PreValuesAsDictionary.FirstOrDefault(
|
||||
x => string.Equals(x.Key, "storageType", StringComparison.InvariantCultureIgnoreCase)).Value;
|
||||
|
||||
if (storageType.Value.InvariantEquals("Json"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,12 @@ using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(string))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class TextStringValueConverter : PropertyValueConverterBase
|
||||
{
|
||||
private readonly static string[] PropertyTypeAliases =
|
||||
private static readonly string[] PropertyTypeAliases =
|
||||
{
|
||||
Constants.PropertyEditors.TextboxAlias,
|
||||
Constants.PropertyEditors.TextboxMultipleAlias
|
||||
|
||||
@@ -4,10 +4,11 @@ using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
/// <summary>
|
||||
/// Value converter for the RTE so that it always returns IHtmlString so that Html.Raw doesn't have to be used.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Value converter for the RTE so that it always returns IHtmlString so that Html.Raw doesn't have to be used.
|
||||
/// </summary>
|
||||
// PropertyCacheLevel.Content is ok here because that version of RTE converter does not parse {locallink} nor executes macros
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(IHtmlString))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class TinyMceValueConverter : PropertyValueConverterBase
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
/// <summary>
|
||||
/// The upload property value converter.
|
||||
/// </summary>
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(string))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class UploadPropertyConverter : PropertyValueConverterBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if this converter can convert the property editor and registers if it can.
|
||||
/// </summary>
|
||||
/// <param name="propertyType">
|
||||
/// The published property type.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The <see cref="bool"/>.
|
||||
/// </returns>
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.EnablePropertyValueConverters)
|
||||
{
|
||||
return propertyType.PropertyEditorAlias.Equals(Constants.PropertyEditors.UploadFieldAlias);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the source object to a string
|
||||
/// </summary>
|
||||
/// <param name="propertyType">
|
||||
/// The published property type.
|
||||
/// </param>
|
||||
/// <param name="source">
|
||||
/// The value of the property
|
||||
/// </param>
|
||||
/// <param name="preview">
|
||||
/// The preview.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The <see cref="object"/>.
|
||||
/// </returns>
|
||||
public override object ConvertSourceToObject(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
return (source ?? "").ToString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(bool))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class YesNoValueConverter : PropertyValueConverterBase
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Persistence;
|
||||
@@ -341,7 +342,11 @@ namespace Umbraco.Core.Scoping
|
||||
{
|
||||
// if child did not complete we cannot complete
|
||||
if (completed.HasValue == false || completed.Value == false)
|
||||
{
|
||||
if (LogUncompletedScopes)
|
||||
Logging.LogHelper.Debug<Scope>("Uncompleted Child Scope at\r\n" + Environment.StackTrace);
|
||||
_completed = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureNotDisposed()
|
||||
@@ -493,5 +498,15 @@ namespace Umbraco.Core.Scoping
|
||||
TryFinally(index + 1, actions);
|
||||
}
|
||||
}
|
||||
|
||||
// backing field for LogUncompletedScopes
|
||||
private static bool? _logUncompletedScopes;
|
||||
|
||||
// caching config
|
||||
// true if Umbraco.CoreDebug.LogUncompletedScope appSetting is set to "true"
|
||||
private static bool LogUncompletedScopes
|
||||
{
|
||||
get { return (_logUncompletedScopes ?? (_logUncompletedScopes = UmbracoConfig.For.CoreDebug().LogUncompletedScopes)).Value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -578,11 +578,9 @@ namespace Umbraco.Core.Services
|
||||
var repository = RepositoryFactory.CreateContentRepository(uow);
|
||||
|
||||
var query = Query<IContent>.Builder;
|
||||
//if the id is System Root, then just get all
|
||||
if (id != Constants.System.Root)
|
||||
{
|
||||
query.Where(x => x.ParentId == id);
|
||||
}
|
||||
// always check for a parent - else it will also get decendants (and then you should use the GetPagedDescendants method)
|
||||
query.Where(x => x.ParentId == id);
|
||||
|
||||
IQuery<IContent> filterQuery = null;
|
||||
if (filter.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
@@ -2245,6 +2243,7 @@ namespace Umbraco.Core.Services
|
||||
//We need to check if children and their publish state to ensure that we 'republish' content that was previously published
|
||||
if (published && previouslyPublished == false && HasChildren(content.Id))
|
||||
{
|
||||
//TODO: Horrible for performance if there are lots of descendents! We should page if anything but this is crazy
|
||||
var descendants = GetPublishedDescendants(content);
|
||||
|
||||
_publishingStrategy.PublishingFinalized(uow, descendants, false);
|
||||
|
||||
@@ -81,6 +81,7 @@ namespace Umbraco.Core.Services
|
||||
/// </param>
|
||||
void RebuildXmlStructures(params int[] contentTypeIds);
|
||||
|
||||
int CountNotTrashed(string contentTypeAlias = null);
|
||||
int Count(string contentTypeAlias = null);
|
||||
int CountChildren(int parentId, string contentTypeAlias = null);
|
||||
int CountDescendants(int parentId, string contentTypeAlias = null);
|
||||
@@ -167,6 +168,22 @@ namespace Umbraco.Core.Services
|
||||
IEnumerable<IMedia> GetPagedChildren(int id, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy, Direction orderDirection, bool orderBySystemField, string filter);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of <see cref="IMedia"/> objects by Parent Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the Parent to retrieve Children from</param>
|
||||
/// <param name="pageIndex">Page number</param>
|
||||
/// <param name="pageSize">Page size</param>
|
||||
/// <param name="totalRecords">Total records query would return without paging</param>
|
||||
/// <param name="orderBy">Field to order by</param>
|
||||
/// <param name="orderDirection">Direction to order by</param>
|
||||
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
|
||||
/// <param name="filter">Search text filter</param>
|
||||
/// <param name="contentTypeFilter">A list of content type Ids to filter the list by</param>
|
||||
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
|
||||
IEnumerable<IMedia> GetPagedChildren(int id, long pageIndex, int pageSize, out long totalRecords,
|
||||
string orderBy, Direction orderDirection, bool orderBySystemField, string filter, int[] contentTypeFilter);
|
||||
|
||||
[Obsolete("Use the overload with 'long' parameter types instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IEnumerable<IMedia> GetPagedDescendants(int id, int pageIndex, int pageSize, out int totalRecords,
|
||||
|
||||
@@ -261,6 +261,29 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
public int CountNotTrashed(string contentTypeAlias = null)
|
||||
{
|
||||
var uow = UowProvider.GetUnitOfWork();
|
||||
using (var repository = RepositoryFactory.CreateMediaRepository(uow))
|
||||
using (var mediaTypeRepository = RepositoryFactory.CreateMediaTypeRepository(uow))
|
||||
{
|
||||
var mediaTypeId = 0;
|
||||
if (contentTypeAlias.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
var mediaType = mediaTypeRepository.Get(contentTypeAlias);
|
||||
if (mediaType == null) return 0;
|
||||
mediaTypeId = mediaType.Id;
|
||||
}
|
||||
|
||||
var query = Query<IMedia>.Builder.Where(media => media.Trashed == false);
|
||||
if (mediaTypeId > 0)
|
||||
{
|
||||
query.Where(media => media.ContentTypeId == mediaTypeId);
|
||||
}
|
||||
return repository.Count(query);
|
||||
}
|
||||
}
|
||||
|
||||
public int Count(string contentTypeAlias = null)
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork(commit: true))
|
||||
@@ -448,6 +471,25 @@ namespace Umbraco.Core.Services
|
||||
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
|
||||
public IEnumerable<IMedia> GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren,
|
||||
string orderBy, Direction orderDirection, bool orderBySystemField, string filter)
|
||||
{
|
||||
return GetPagedChildren(id, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, true, filter, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of <see cref="IMedia"/> objects by Parent Id
|
||||
/// </summary>
|
||||
/// <param name="id">Id of the Parent to retrieve Children from</param>
|
||||
/// <param name="pageIndex">Page number</param>
|
||||
/// <param name="pageSize">Page size</param>
|
||||
/// <param name="totalChildren">Total records query would return without paging</param>
|
||||
/// <param name="orderBy">Field to order by</param>
|
||||
/// <param name="orderDirection">Direction to order by</param>
|
||||
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
|
||||
/// <param name="filter">Search text filter</param>
|
||||
/// <param name="contentTypeFilter">A list of content type Ids to filter the list by</param>
|
||||
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
|
||||
public IEnumerable<IMedia> GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren,
|
||||
string orderBy, Direction orderDirection, bool orderBySystemField, string filter, int[] contentTypeFilter)
|
||||
{
|
||||
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
|
||||
Mandate.ParameterCondition(pageSize > 0, "pageSize");
|
||||
@@ -457,11 +499,14 @@ namespace Umbraco.Core.Services
|
||||
var repository = RepositoryFactory.CreateMediaRepository(uow);
|
||||
|
||||
var query = Query<IMedia>.Builder;
|
||||
//if the id is System Root, then just get all
|
||||
if (id != Constants.System.Root)
|
||||
// always check for a parent - else it will also get decendants (and then you should use the GetPagedDescendants method)
|
||||
query.Where(x => x.ParentId == id);
|
||||
|
||||
if (contentTypeFilter != null && contentTypeFilter.Length > 0)
|
||||
{
|
||||
query.Where(x => x.ParentId == id);
|
||||
query.Where(x => contentTypeFilter.Contains(x.ContentTypeId));
|
||||
}
|
||||
|
||||
IQuery<IMedia> filterQuery = null;
|
||||
if (filter.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a string-based entity identifier.
|
||||
/// </summary>
|
||||
[TypeConverter(typeof(UdiTypeConverter))]
|
||||
public class StringUdi : Udi
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Umbraco.Core</RootNamespace>
|
||||
<AssemblyName>Umbraco.Core</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
@@ -39,15 +39,19 @@
|
||||
<ItemGroup>
|
||||
<Reference Include="AutoMapper, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="HtmlAgilityPack, Version=1.4.9.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\HtmlAgilityPack.1.4.9\lib\Net45\HtmlAgilityPack.dll</HintPath>
|
||||
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="ImageProcessor, Version=2.5.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ImageProcessor.2.5.2\lib\net45\ImageProcessor.dll</HintPath>
|
||||
@@ -55,49 +59,64 @@
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.5\lib\net45-full\log4net.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AspNet.Identity.Core.2.2.1\lib\net45\Microsoft.AspNet.Identity.Core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AspNet.Identity.Owin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.AspNet.Identity.Owin.2.2.1\lib\net45\Microsoft.AspNet.Identity.Owin.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin.Security, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin.Security.Cookies, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Owin.Security.Cookies.3.0.1\lib\net45\Microsoft.Owin.Security.Cookies.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Owin.Security.OAuth, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Owin.Security.OAuth.3.0.1\lib\net45\Microsoft.Owin.Security.OAuth.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="MiniProfiler, Version=2.1.0.0, Culture=neutral, PublicKeyToken=b44f9351044011a3, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MiniProfiler.2.1.0\lib\net40\MiniProfiler.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MySql.Data.6.9.8\lib\net45\MySql.Data.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Semver, Version=2.0.4.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Semver.2.0.4\lib\net452\Semver.dll</HintPath>
|
||||
<HintPath>..\packages\Semver.2.0.4\lib\netstandard1.1\Semver.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Data.Entity" />
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.DirectoryServices.AccountManagement" />
|
||||
<Reference Include="System.Drawing" />
|
||||
@@ -179,6 +198,7 @@
|
||||
<Compile Include="Configuration\BaseRest\ExtensionElement.cs" />
|
||||
<Compile Include="Configuration\BaseRest\ExtensionElementCollection.cs" />
|
||||
<Compile Include="Configuration\BaseRest\MethodElement.cs" />
|
||||
<Compile Include="Configuration\ContentXmlStorage.cs" />
|
||||
<Compile Include="Configuration\Dashboard\AccessElement.cs" />
|
||||
<Compile Include="Configuration\Dashboard\AccessItem.cs" />
|
||||
<Compile Include="Configuration\Dashboard\AccessType.cs" />
|
||||
@@ -199,6 +219,7 @@
|
||||
<Compile Include="Configuration\Dashboard\SectionElement.cs" />
|
||||
<Compile Include="Configuration\Dashboard\TabCollection.cs" />
|
||||
<Compile Include="Configuration\Dashboard\TabElement.cs" />
|
||||
<Compile Include="Configuration\CoreDebug.cs" />
|
||||
<Compile Include="Configuration\FileSystemProviderElement.cs" />
|
||||
<Compile Include="Configuration\FileSystemProviderElementCollection.cs" />
|
||||
<Compile Include="Configuration\FileSystemProvidersSection.cs" />
|
||||
@@ -318,6 +339,7 @@
|
||||
<Compile Include="Events\ScopeEventDispatcherBase.cs" />
|
||||
<Compile Include="Events\ScopeLifespanMessagesFactory.cs" />
|
||||
<Compile Include="IHttpContextAccessor.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentTypeConverter.cs" />
|
||||
<Compile Include="OrderedHashSet.cs" />
|
||||
<Compile Include="Events\UninstallPackageEventArgs.cs" />
|
||||
<Compile Include="Models\GridValue.cs" />
|
||||
@@ -426,9 +448,11 @@
|
||||
<Compile Include="Models\PartialViewType.cs" />
|
||||
<Compile Include="Models\PublicAccessEntry.cs" />
|
||||
<Compile Include="Models\PublicAccessRule.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentEnumerable.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentWithKeyExtended.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentWithKeyModel.cs" />
|
||||
<Compile Include="Models\PublishedContent\PublishedContentWithKeyWrapped.cs" />
|
||||
<Compile Include="Models\Range.cs" />
|
||||
<Compile Include="Models\Rdbms\AccessDto.cs" />
|
||||
<Compile Include="Media\Exif\BitConverterEx.cs" />
|
||||
<Compile Include="Media\Exif\ExifBitConverter.cs" />
|
||||
@@ -559,10 +583,21 @@
|
||||
<Compile Include="Persistence\UnitOfWork\ScopeUnitOfWorkProvider.cs" />
|
||||
<Compile Include="PropertyEditors\DecimalValidator.cs" />
|
||||
<Compile Include="PropertyEditors\PropertyEditorValueTypes.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\CheckboxListValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\DropdownListMultipleValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\DropdownListMultipleWithKeysValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\DropdownListValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\DropdownListWithKeysValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\EmailAddressValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\GridValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\DecimalValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\LabelValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\ImageCropperValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\MemberGroupPickerValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\RadioButtonListValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\SliderValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\TagsValueConverter.cs" />
|
||||
<Compile Include="PropertyEditors\ValueConverters\UploadPropertyConverter.cs" />
|
||||
<Compile Include="Publishing\UnPublishedStatusType.cs" />
|
||||
<Compile Include="Publishing\UnPublishStatus.cs" />
|
||||
<Compile Include="SafeCallContext.cs" />
|
||||
|
||||
@@ -16,32 +16,6 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
internal static class XmlExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Saves the xml document async
|
||||
/// </summary>
|
||||
/// <param name="xdoc"></param>
|
||||
/// <param name="filename"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task SaveAsync(this XmlDocument xdoc, string filename)
|
||||
{
|
||||
if (xdoc.DocumentElement == null)
|
||||
throw new XmlException("Cannot save xml document, there is no root element");
|
||||
|
||||
using (var fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Read, bufferSize: 4096, useAsync: true))
|
||||
using (var xmlWriter = XmlWriter.Create(fs, new XmlWriterSettings
|
||||
{
|
||||
Async = true,
|
||||
Encoding = Encoding.UTF8,
|
||||
Indent = true
|
||||
}))
|
||||
{
|
||||
//NOTE: There are no nice methods to write it async, only flushing it async. We
|
||||
// could implement this ourselves but it'd be a very manual process.
|
||||
xdoc.WriteTo(xmlWriter);
|
||||
await xmlWriter.FlushAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool HasAttribute(this XmlAttributeCollection attributes, string attributeName)
|
||||
{
|
||||
return attributes.Cast<XmlAttribute>().Any(x => x.Name == attributeName);
|
||||
|
||||
@@ -32,4 +32,9 @@
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" /></startup></configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /></startup><system.data>
|
||||
<DbProviderFactories>
|
||||
<remove invariant="MySql.Data.MySqlClient" />
|
||||
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
|
||||
</DbProviderFactories>
|
||||
</system.data></configuration>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
|
||||
<package id="HtmlAgilityPack" version="1.4.9" targetFramework="net45" />
|
||||
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
|
||||
<package id="ImageProcessor" version="2.5.2" targetFramework="net45" />
|
||||
<package id="log4net" version="2.0.5" targetFramework="net45" />
|
||||
<package id="Microsoft.AspNet.Identity.Core" version="2.2.1" targetFramework="net45" />
|
||||
@@ -12,9 +12,13 @@
|
||||
<package id="Microsoft.Owin.Security.OAuth" version="3.0.1" targetFramework="net45" />
|
||||
<package id="MiniProfiler" version="2.1.0" targetFramework="net45" />
|
||||
<package id="MySql.Data" version="6.9.8" targetFramework="net45" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net462" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
|
||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||
<package id="Semver" version="2.0.4" targetFramework="net462" />
|
||||
<package id="Semver" version="2.0.4" targetFramework="net45" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="System.Runtime" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.Extensions" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.InteropServices" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Text.RegularExpressions" version="4.1.0" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
|
||||
@@ -16,6 +16,7 @@ using BenchmarkDotNet.Loggers;
|
||||
using BenchmarkDotNet.Reports;
|
||||
using BenchmarkDotNet.Running;
|
||||
using BenchmarkDotNet.Validators;
|
||||
using Moq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -43,15 +44,18 @@ namespace Umbraco.Tests.Benchmarks
|
||||
|
||||
public ModelToSqlExpressionHelperBenchmarks()
|
||||
{
|
||||
_contentMapper = new ContentMapper(_syntaxProvider);
|
||||
_contentMapper.BuildMap();
|
||||
var contentMapper = new ContentMapper(_syntaxProvider);
|
||||
contentMapper.BuildMap();
|
||||
_cachedExpression = new CachedExpression();
|
||||
var mappingResolver = new Mock<MappingResolver>();
|
||||
mappingResolver.Setup(resolver => resolver.ResolveMapperByType(It.IsAny<Type>())).Returns(contentMapper);
|
||||
_mappingResolver = mappingResolver.Object;
|
||||
}
|
||||
|
||||
private readonly ISqlSyntaxProvider _syntaxProvider = new SqlCeSyntaxProvider();
|
||||
private readonly BaseMapper _contentMapper;
|
||||
private readonly CachedExpression _cachedExpression;
|
||||
|
||||
private readonly MappingResolver _mappingResolver;
|
||||
|
||||
[Benchmark(Baseline = true)]
|
||||
public void WithNonCached()
|
||||
{
|
||||
@@ -62,7 +66,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
Expression<Func<IContent, bool>> predicate = content =>
|
||||
content.Path.StartsWith("-1") && content.Published && (content.ContentTypeId == a || content.ContentTypeId == b);
|
||||
|
||||
var modelToSqlExpressionHelper = new ModelToSqlExpressionVisitor<IContent>(_syntaxProvider, _contentMapper);
|
||||
var modelToSqlExpressionHelper = new ModelToSqlExpressionVisitor<IContent>(_syntaxProvider, _mappingResolver);
|
||||
var result = modelToSqlExpressionHelper.Visit(predicate);
|
||||
}
|
||||
|
||||
@@ -80,7 +84,7 @@ namespace Umbraco.Tests.Benchmarks
|
||||
Expression<Func<IContent, bool>> predicate = content =>
|
||||
content.Path.StartsWith("-1") && content.Published && (content.ContentTypeId == a || content.ContentTypeId == b);
|
||||
|
||||
var modelToSqlExpressionHelper = new ModelToSqlExpressionVisitor<IContent>(_syntaxProvider, _contentMapper);
|
||||
var modelToSqlExpressionHelper = new ModelToSqlExpressionVisitor<IContent>(_syntaxProvider, _mappingResolver);
|
||||
|
||||
//wrap it!
|
||||
_cachedExpression.Wrap(predicate);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Umbraco.Tests.Benchmarks</RootNamespace>
|
||||
<AssemblyName>Umbraco.Tests.Benchmarks</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
@@ -40,101 +40,61 @@
|
||||
<ItemGroup>
|
||||
<Reference Include="BenchmarkDotNet, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BenchmarkDotNet.0.9.9\lib\net45\BenchmarkDotNet.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="BenchmarkDotNet.Core, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BenchmarkDotNet.Core.0.9.9\lib\net45\BenchmarkDotNet.Core.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="BenchmarkDotNet.Diagnostics.Windows, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BenchmarkDotNet.Diagnostics.Windows.0.9.9\lib\net45\BenchmarkDotNet.Diagnostics.Windows.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="BenchmarkDotNet.Toolchains.Roslyn, Version=0.9.9.0, Culture=neutral, PublicKeyToken=aa0ca2f9092cefc4, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\BenchmarkDotNet.Toolchains.Roslyn.0.9.9\lib\net45\BenchmarkDotNet.Toolchains.Roslyn.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CodeAnalysis, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.CodeAnalysis.Common.1.3.2\lib\net45\Microsoft.CodeAnalysis.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=1.3.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.CodeAnalysis.CSharp.1.3.2\lib\net45\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Diagnostics.Tracing.TraceEvent, Version=1.0.41.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Diagnostics.Tracing.TraceEvent.1.0.41\lib\net40\Microsoft.Diagnostics.Tracing.TraceEvent.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.AppContext, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.AppContext.4.1.0\lib\net46\System.AppContext.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Moq, Version=4.7.0.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Moq.4.7.0\lib\net45\Moq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Collections.Immutable, Version=1.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Collections.Immutable.1.2.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Console, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Console.4.0.0\lib\net46\System.Console.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Diagnostics.FileVersionInfo, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Diagnostics.FileVersionInfo.4.0.0\lib\net46\System.Diagnostics.FileVersionInfo.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Diagnostics.StackTrace, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Diagnostics.StackTrace.4.0.1\lib\net46\System.Diagnostics.StackTrace.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.FileSystem, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.IO.FileSystem.4.0.1\lib\net46\System.IO.FileSystem.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.IO.FileSystem.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.IO.FileSystem.Primitives.4.0.1\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Reflection, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Reflection.4.1.0\lib\net462\System.Reflection.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reflection.Metadata, Version=1.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Reflection.Metadata.1.3.0\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Runtime.4.1.0\lib\net462\System.Runtime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Extensions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Runtime.Extensions.4.1.0\lib\net462\System.Runtime.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.InteropServices, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Runtime.InteropServices.4.1.0\lib\net462\System.Runtime.InteropServices.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.Cryptography.Algorithms.4.2.0\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.Cryptography.Encoding.4.0.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.Cryptography.Primitives.4.0.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.1.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Text.Encoding.CodePages, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Text.Encoding.CodePages.4.0.1\lib\net46\System.Text.Encoding.CodePages.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Threading.Tasks.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.0.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Threading.Thread, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Threading.Thread.4.0.0\lib\net46\System.Threading.Thread.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
@@ -143,18 +103,6 @@
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Xml.XmlDocument, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Xml.XmlDocument.4.0.1\lib\net46\System.Xml.XmlDocument.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.XPath, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Xml.XPath.4.0.1\lib\net46\System.Xml.XPath.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.XPath.XDocument, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Xml.XPath.XDocument.4.0.1\lib\net46\System.Xml.XPath.XDocument.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="LinqCastBenchmarks.cs" />
|
||||
@@ -168,6 +116,7 @@
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="_TraceEventProgrammersGuide.docx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj">
|
||||
@@ -187,6 +136,10 @@
|
||||
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll" />
|
||||
<Analyzer Include="..\packages\Microsoft.CodeAnalysis.Analyzers.1.1.0\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="TraceEvent.ReadMe.txt" />
|
||||
<Content Include="TraceEvent.ReleaseNotes.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
|
||||
@@ -4,51 +4,37 @@
|
||||
<package id="BenchmarkDotNet.Core" version="0.9.9" targetFramework="net45" />
|
||||
<package id="BenchmarkDotNet.Diagnostics.Windows" version="0.9.9" targetFramework="net45" />
|
||||
<package id="BenchmarkDotNet.Toolchains.Roslyn" version="0.9.9" targetFramework="net45" />
|
||||
<package id="Castle.Core" version="4.0.0" targetFramework="net45" />
|
||||
<package id="Microsoft.CodeAnalysis.Analyzers" version="1.1.0" targetFramework="net45" />
|
||||
<package id="Microsoft.CodeAnalysis.Common" version="1.3.2" targetFramework="net45" />
|
||||
<package id="Microsoft.CodeAnalysis.CSharp" version="1.3.2" targetFramework="net45" />
|
||||
<package id="Microsoft.Diagnostics.Tracing.TraceEvent" version="1.0.41" targetFramework="net45" />
|
||||
<package id="Microsoft.SqlServer.Compact" version="4.0.8854.1" targetFramework="net45" />
|
||||
<package id="Moq" version="4.7.0" targetFramework="net45" />
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="System.AppContext" version="4.1.0" targetFramework="net462" />
|
||||
<package id="System.Collections" version="4.0.11" targetFramework="net462" />
|
||||
<package id="System.Collections.Concurrent" version="4.0.12" targetFramework="net462" />
|
||||
<package id="System.Collections.Immutable" version="1.2.0" targetFramework="net462" />
|
||||
<package id="System.Console" version="4.0.0" targetFramework="net462" />
|
||||
<package id="System.Diagnostics.Debug" version="4.0.11" targetFramework="net462" />
|
||||
<package id="System.Diagnostics.FileVersionInfo" version="4.0.0" targetFramework="net462" />
|
||||
<package id="System.Diagnostics.StackTrace" version="4.0.1" targetFramework="net462" />
|
||||
<package id="System.Diagnostics.Tools" version="4.0.1" targetFramework="net462" />
|
||||
<package id="System.Dynamic.Runtime" version="4.0.11" targetFramework="net462" />
|
||||
<package id="System.Globalization" version="4.0.11" targetFramework="net462" />
|
||||
<package id="System.IO.FileSystem" version="4.0.1" targetFramework="net462" />
|
||||
<package id="System.IO.FileSystem.Primitives" version="4.0.1" targetFramework="net462" />
|
||||
<package id="System.Linq" version="4.1.0" targetFramework="net462" />
|
||||
<package id="System.Linq.Expressions" version="4.1.0" targetFramework="net462" />
|
||||
<package id="System.Reflection" version="4.1.0" targetFramework="net462" />
|
||||
<package id="System.Reflection.Metadata" version="1.3.0" targetFramework="net462" />
|
||||
<package id="System.Reflection.Primitives" version="4.0.1" targetFramework="net462" />
|
||||
<package id="System.Resources.ResourceManager" version="4.0.1" targetFramework="net462" />
|
||||
<package id="System.Runtime" version="4.1.0" targetFramework="net462" />
|
||||
<package id="System.Runtime.Extensions" version="4.1.0" targetFramework="net462" />
|
||||
<package id="System.Runtime.Handles" version="4.0.1" targetFramework="net462" />
|
||||
<package id="System.Runtime.InteropServices" version="4.1.0" targetFramework="net462" />
|
||||
<package id="System.Runtime.Numerics" version="4.0.1" targetFramework="net462" />
|
||||
<package id="System.Security.Cryptography.Algorithms" version="4.2.0" targetFramework="net462" />
|
||||
<package id="System.Security.Cryptography.Encoding" version="4.0.0" targetFramework="net462" />
|
||||
<package id="System.Security.Cryptography.Primitives" version="4.0.0" targetFramework="net462" />
|
||||
<package id="System.Security.Cryptography.X509Certificates" version="4.1.0" targetFramework="net462" />
|
||||
<package id="System.Text.Encoding" version="4.0.11" targetFramework="net462" />
|
||||
<package id="System.Text.Encoding.CodePages" version="4.0.1" targetFramework="net462" />
|
||||
<package id="System.Text.Encoding.Extensions" version="4.0.11" targetFramework="net462" />
|
||||
<package id="System.Threading" version="4.0.11" targetFramework="net462" />
|
||||
<package id="System.Threading.Tasks" version="4.0.11" targetFramework="net462" />
|
||||
<package id="System.Collections" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Collections.Concurrent" version="4.0.12" targetFramework="net45" />
|
||||
<package id="System.Collections.Immutable" version="1.2.0" targetFramework="net45" />
|
||||
<package id="System.Diagnostics.Debug" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Diagnostics.Tools" version="4.0.1" targetFramework="net45" />
|
||||
<package id="System.Dynamic.Runtime" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Globalization" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Linq" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Linq.Expressions" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Reflection" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Reflection.Metadata" version="1.3.0" targetFramework="net45" />
|
||||
<package id="System.Reflection.Primitives" version="4.0.1" targetFramework="net45" />
|
||||
<package id="System.Resources.ResourceManager" version="4.0.1" targetFramework="net45" />
|
||||
<package id="System.Runtime" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.Extensions" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.InteropServices" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.Numerics" version="4.0.1" targetFramework="net45" />
|
||||
<package id="System.Text.Encoding" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Text.Encoding.Extensions" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Threading" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Threading.Tasks" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Threading.Tasks.Extensions" version="4.0.0" targetFramework="net45" />
|
||||
<package id="System.Threading.Tasks.Parallel" version="4.0.1" targetFramework="net462" />
|
||||
<package id="System.Threading.Thread" version="4.0.0" targetFramework="net462" />
|
||||
<package id="System.Xml.ReaderWriter" version="4.0.11" targetFramework="net462" />
|
||||
<package id="System.Xml.XDocument" version="4.0.11" targetFramework="net462" />
|
||||
<package id="System.Xml.XmlDocument" version="4.0.1" targetFramework="net462" />
|
||||
<package id="System.Xml.XPath" version="4.0.1" targetFramework="net462" />
|
||||
<package id="System.Xml.XPath.XDocument" version="4.0.1" targetFramework="net462" />
|
||||
<package id="System.Threading.Tasks.Parallel" version="4.0.1" targetFramework="net45" />
|
||||
<package id="System.Xml.ReaderWriter" version="4.0.11" targetFramework="net45" />
|
||||
<package id="System.Xml.XDocument" version="4.0.11" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -91,7 +91,7 @@
|
||||
</siteMap>
|
||||
</system.web>
|
||||
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" /></startup>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /></startup>
|
||||
<runtime>
|
||||
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
|
||||
@@ -21,6 +21,17 @@ namespace Umbraco.Tests.IO
|
||||
|
||||
// media fs wants this
|
||||
ApplicationContext.Current = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||
|
||||
// start clean
|
||||
// because some tests will create corrupt or weird filesystems
|
||||
FileSystemProviderManager.Current.Reset();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
// stay clean (see note in SetUp)
|
||||
FileSystemProviderManager.Current.Reset();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -39,22 +50,53 @@ namespace Umbraco.Tests.IO
|
||||
Assert.NotNull(fs);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Test]
|
||||
public void Singleton_Typed_File_System()
|
||||
{
|
||||
var fs1 = FileSystemProviderManager.Current.GetFileSystemProvider<MediaFileSystem>();
|
||||
var fs2 = FileSystemProviderManager.Current.GetFileSystemProvider<MediaFileSystem>();
|
||||
|
||||
Assert.AreSame(fs1, fs2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Exception_Thrown_On_Invalid_Typed_File_System()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() => FileSystemProviderManager.Current.GetFileSystemProvider<InvalidTypedFileSystem>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used in unit tests, for a typed file system we need to inherit from FileSystemWrapper and they MUST have a ctor
|
||||
/// that only accepts a base IFileSystem object
|
||||
/// </summary>
|
||||
internal class InvalidTypedFileSystem : FileSystemWrapper
|
||||
[Test]
|
||||
public void Exception_Thrown_On_NonConfigured_Typed_File_System()
|
||||
{
|
||||
// note: we need to reset the manager between tests else the Accept_Fallback test would corrupt that one
|
||||
Assert.Throws<ArgumentException>(() => FileSystemProviderManager.Current.GetFileSystemProvider<NonConfiguredTypeFileSystem>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Accept_Fallback_On_NonConfigured_Typed_File_System()
|
||||
{
|
||||
var fs = FileSystemProviderManager.Current.GetFileSystemProvider<NonConfiguredTypeFileSystem>(() => new PhysicalFileSystem("~/App_Data/foo"));
|
||||
|
||||
Assert.NotNull(fs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used in unit tests, for a typed file system we need to inherit from FileSystemWrapper and they MUST have a ctor
|
||||
/// that only accepts a base IFileSystem object
|
||||
/// </summary>
|
||||
internal class InvalidTypedFileSystem : FileSystemWrapper
|
||||
{
|
||||
public InvalidTypedFileSystem(IFileSystem wrapped, string invalidParam) : base(wrapped)
|
||||
{
|
||||
}
|
||||
public InvalidTypedFileSystem(IFileSystem wrapped, string invalidParam)
|
||||
: base(wrapped)
|
||||
{ }
|
||||
}
|
||||
|
||||
[FileSystemProvider("noconfig")]
|
||||
internal class NonConfiguredTypeFileSystem : FileSystemWrapper
|
||||
{
|
||||
public NonConfiguredTypeFileSystem(IFileSystem wrapped)
|
||||
: base(wrapped)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -806,6 +806,7 @@ namespace Umbraco.Tests.IO
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore("Does not work on all environments, Directory.GetFiles is broken.")]
|
||||
public void ShadowGetFilesUsingWildcardAndSingleCharacterFilter()
|
||||
{
|
||||
// Arrange
|
||||
@@ -846,6 +847,7 @@ namespace Umbraco.Tests.IO
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore("Does not work on all environments, Directory.GetFiles is broken.")]
|
||||
public void ShadowFileSystemFilterIsAsBrokenAsRealFileSystemFilter()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests.Issues
|
||||
{
|
||||
[TestFixture]
|
||||
[DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)]
|
||||
public class U9560 : BaseDatabaseFactoryTest
|
||||
{
|
||||
[Test]
|
||||
public void Test()
|
||||
{
|
||||
// create a content type and some properties
|
||||
var contentType = new ContentType(-1);
|
||||
contentType.Alias = "test";
|
||||
contentType.Name = "test";
|
||||
var propertyType = new PropertyType("test", DataTypeDatabaseType.Ntext, "prop") { Name = "Prop", Description = "", Mandatory = false, SortOrder = 1, DataTypeDefinitionId = -88 };
|
||||
contentType.PropertyTypeCollection.Add(propertyType);
|
||||
ServiceContext.ContentTypeService.Save(contentType);
|
||||
|
||||
var aliasName = string.Empty;
|
||||
|
||||
// read fields, same as what we do with PetaPoco Fetch<dynamic>
|
||||
var db = DatabaseContext.Database;
|
||||
db.OpenSharedConnection();
|
||||
try
|
||||
{
|
||||
var conn = db.Connection;
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "SELECT mandatory, dataTypeId, propertyTypeGroupId, contentTypeId, sortOrder, alias, name, validationRegExp, description from cmsPropertyType where id=" + propertyType.Id;
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
for (var i = 0; i < reader.FieldCount; i++)
|
||||
Console.WriteLine(reader.GetName(i));
|
||||
aliasName = reader.GetName(5);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
db.CloseSharedConnection();
|
||||
}
|
||||
|
||||
// note that although the query is for 'alias' the field is named 'Alias'
|
||||
Assert.AreEqual("Alias", aliasName);
|
||||
|
||||
// try differently
|
||||
db.OpenSharedConnection();
|
||||
try
|
||||
{
|
||||
var conn = db.Connection;
|
||||
var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = "SELECT mandatory, dataTypeId, propertyTypeGroupId, contentTypeId, sortOrder, alias as alias, name, validationRegExp, description from cmsPropertyType where id=" + propertyType.Id;
|
||||
using (var reader = cmd.ExecuteReader())
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
for (var i = 0; i < reader.FieldCount; i++)
|
||||
Console.WriteLine(reader.GetName(i));
|
||||
aliasName = reader.GetName(5);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
db.CloseSharedConnection();
|
||||
}
|
||||
|
||||
// and now it is OK
|
||||
Assert.AreEqual("alias", aliasName);
|
||||
|
||||
// get the legacy content type
|
||||
var legacyContentType = new umbraco.cms.businesslogic.ContentType(contentType.Id);
|
||||
Assert.AreEqual("test", legacyContentType.Alias);
|
||||
|
||||
// get the legacy properties
|
||||
var legacyProperties = legacyContentType.PropertyTypes;
|
||||
|
||||
// without the fix, due to some (swallowed) inner exception, we have no properties
|
||||
//Assert.IsNull(legacyProperties);
|
||||
|
||||
// thanks to the fix, it works
|
||||
Assert.IsNotNull(legacyProperties);
|
||||
Assert.AreEqual(1, legacyProperties.Count);
|
||||
Assert.AreEqual("prop", legacyProperties[0].Alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,13 @@ namespace Umbraco.Tests.Persistence
|
||||
ApplicationContext.Current = null;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Database_Connection()
|
||||
{
|
||||
var db = _dbContext.Database;
|
||||
Assert.IsNull(db.Connection);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Verify_Single_Database_Instance()
|
||||
{
|
||||
|
||||
@@ -17,19 +17,52 @@ namespace Umbraco.Tests.Persistence.Querying
|
||||
[TestFixture]
|
||||
public class ExpressionTests : BaseUsingSqlCeSyntax
|
||||
{
|
||||
// [Test]
|
||||
// public void Can_Query_With_Content_Type_Alias()
|
||||
// {
|
||||
// //Arrange
|
||||
// Expression<Func<IMedia, bool>> predicate = content => content.ContentType.Alias == "Test";
|
||||
// var modelToSqlExpressionHelper = new ModelToSqlExpressionVisitor<IContent>();
|
||||
// var result = modelToSqlExpressionHelper.Visit(predicate);
|
||||
[Test]
|
||||
public void Equals_Claus_With_Two_Entity_Values()
|
||||
{
|
||||
var dataType = new DataTypeDefinition(-1, "Test")
|
||||
{
|
||||
Id = 12345
|
||||
};
|
||||
Expression<Func<PropertyType, bool>> predicate = p => p.DataTypeDefinitionId == dataType.Id;
|
||||
var modelToSqlExpressionHelper = new ModelToSqlExpressionVisitor<PropertyType>();
|
||||
var result = modelToSqlExpressionHelper.Visit(predicate);
|
||||
|
||||
// Debug.Print("Model to Sql ExpressionHelper: \n" + result);
|
||||
Debug.Print("Model to Sql ExpressionHelper: \n" + result);
|
||||
|
||||
// Assert.AreEqual("[cmsContentType].[alias] = @0", result);
|
||||
// Assert.AreEqual("Test", modelToSqlExpressionHelper.GetSqlParameters()[0]);
|
||||
// }
|
||||
Assert.AreEqual("([cmsPropertyType].[dataTypeId] = @0)", result);
|
||||
Assert.AreEqual(12345, modelToSqlExpressionHelper.GetSqlParameters()[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Query_With_Content_Type_Alias()
|
||||
{
|
||||
//Arrange
|
||||
Expression<Func<IMedia, bool>> predicate = content => content.ContentType.Alias == "Test";
|
||||
var modelToSqlExpressionHelper = new ModelToSqlExpressionVisitor<IContent>();
|
||||
var result = modelToSqlExpressionHelper.Visit(predicate);
|
||||
|
||||
Debug.Print("Model to Sql ExpressionHelper: \n" + result);
|
||||
|
||||
Assert.AreEqual("([cmsContentType].[alias] = @0)", result);
|
||||
Assert.AreEqual("Test", modelToSqlExpressionHelper.GetSqlParameters()[0]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Query_With_Content_Type_Aliases()
|
||||
{
|
||||
//Arrange
|
||||
var aliases = new[] {"Test1", "Test2"};
|
||||
Expression<Func<IMedia, bool>> predicate = content => aliases.Contains(content.ContentType.Alias);
|
||||
var modelToSqlExpressionHelper = new ModelToSqlExpressionVisitor<IContent>();
|
||||
var result = modelToSqlExpressionHelper.Visit(predicate);
|
||||
|
||||
Debug.Print("Model to Sql ExpressionHelper: \n" + result);
|
||||
|
||||
Assert.AreEqual("[cmsContentType].[alias] IN (@1,@2)", result);
|
||||
Assert.AreEqual("Test1", modelToSqlExpressionHelper.GetSqlParameters()[1]);
|
||||
Assert.AreEqual("Test2", modelToSqlExpressionHelper.GetSqlParameters()[2]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CachedExpression_Can_Verify_Path_StartsWith_Predicate_In_Same_Result()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml.Linq;
|
||||
@@ -21,7 +22,6 @@ using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
using umbraco.editorControls.tinyMCE3;
|
||||
using umbraco.interfaces;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
|
||||
namespace Umbraco.Tests.Persistence.Repositories
|
||||
@@ -36,11 +36,15 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
base.Initialize();
|
||||
|
||||
CreateTestData();
|
||||
|
||||
VersionableRepositoryBase<int, IContent>.ThrowOnWarning = true;
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public override void TearDown()
|
||||
{
|
||||
VersionableRepositoryBase<int, IContent>.ThrowOnWarning = false;
|
||||
|
||||
base.TearDown();
|
||||
}
|
||||
|
||||
@@ -67,6 +71,131 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
return repository;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Always_Returns_Latest_Version()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
ContentTypeRepository contentTypeRepository;
|
||||
IContent content1;
|
||||
|
||||
var versions = new List<Guid>();
|
||||
using (var repository = CreateRepository(unitOfWork, out contentTypeRepository))
|
||||
{
|
||||
var hasPropertiesContentType = MockedContentTypes.CreateSimpleContentType("umbTextpage1", "Textpage");
|
||||
content1 = MockedContent.CreateSimpleContent(hasPropertiesContentType);
|
||||
|
||||
//save version
|
||||
contentTypeRepository.AddOrUpdate(hasPropertiesContentType);
|
||||
repository.AddOrUpdate(content1);
|
||||
unitOfWork.Commit();
|
||||
versions.Add(content1.Version);
|
||||
|
||||
//publish version
|
||||
content1.ChangePublishedState(PublishedState.Published);
|
||||
repository.AddOrUpdate(content1);
|
||||
unitOfWork.Commit();
|
||||
versions.Add(content1.Version);
|
||||
|
||||
//change something and make a pending version
|
||||
content1.Name = "new name";
|
||||
content1.ChangePublishedState(PublishedState.Saved);
|
||||
repository.AddOrUpdate(content1);
|
||||
unitOfWork.Commit();
|
||||
versions.Add(content1.Version);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(3, versions.Distinct().Count());
|
||||
using (var repository = CreateRepository(unitOfWork, out contentTypeRepository))
|
||||
{
|
||||
var content = repository.GetByQuery(new Query<IContent>().Where(c => c.Id == content1.Id)).ToArray()[0];
|
||||
Assert.AreEqual(versions[2], content.Version);
|
||||
|
||||
content = repository.Get(content1.Id);
|
||||
Assert.AreEqual(versions[2], content.Version);
|
||||
|
||||
foreach (var version in versions)
|
||||
{
|
||||
content = repository.GetByVersion(version);
|
||||
Assert.IsNotNull(content);
|
||||
Assert.AreEqual(version, content.Version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Deal_With_Corrupt_Duplicate_Newest_Published_Flags()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
ContentTypeRepository contentTypeRepository;
|
||||
IContent content1;
|
||||
|
||||
using (var repository = CreateRepository(unitOfWork, out contentTypeRepository))
|
||||
{
|
||||
var hasPropertiesContentType = MockedContentTypes.CreateSimpleContentType("umbTextpage1", "Textpage");
|
||||
content1 = MockedContent.CreateSimpleContent(hasPropertiesContentType);
|
||||
|
||||
contentTypeRepository.AddOrUpdate(hasPropertiesContentType);
|
||||
repository.AddOrUpdate(content1);
|
||||
unitOfWork.Commit();
|
||||
}
|
||||
|
||||
var versionDtos = new List<ContentVersionDto>();
|
||||
|
||||
//Now manually corrupt the data
|
||||
var versions = new[] { Guid.NewGuid(), Guid.NewGuid() };
|
||||
for (var index = 0; index < versions.Length; index++)
|
||||
{
|
||||
var version = versions[index];
|
||||
var versionDate = DateTime.Now.AddMinutes(index);
|
||||
var versionDto = new ContentVersionDto
|
||||
{
|
||||
NodeId = content1.Id,
|
||||
VersionDate = versionDate,
|
||||
VersionId = version
|
||||
};
|
||||
this.DatabaseContext.Database.Insert(versionDto);
|
||||
versionDtos.Add(versionDto);
|
||||
this.DatabaseContext.Database.Insert(new DocumentDto
|
||||
{
|
||||
Newest = true,
|
||||
NodeId = content1.Id,
|
||||
Published = true,
|
||||
Text = content1.Name,
|
||||
VersionId = version,
|
||||
WriterUserId = 0,
|
||||
UpdateDate = versionDate,
|
||||
TemplateId = content1.Template == null || content1.Template.Id <= 0 ? null : (int?) content1.Template.Id
|
||||
});
|
||||
}
|
||||
|
||||
// Assert
|
||||
using (var repository = CreateRepository(unitOfWork, out contentTypeRepository))
|
||||
{
|
||||
var content = repository.GetByQuery(new Query<IContent>().Where(c => c.Id == content1.Id)).ToArray();
|
||||
Assert.AreEqual(1, content.Length);
|
||||
Assert.AreEqual(content[0].Version, versionDtos.Single(x => x.Id == versionDtos.Max(y => y.Id)).VersionId);
|
||||
Assert.AreEqual(content[0].UpdateDate.ToString(CultureInfo.InvariantCulture), versionDtos.Single(x => x.Id == versionDtos.Max(y => y.Id)).VersionDate.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
var contentItem = repository.GetByVersion(content1.Version);
|
||||
Assert.IsNotNull(contentItem);
|
||||
|
||||
contentItem = repository.Get(content1.Id);
|
||||
Assert.IsNotNull(contentItem);
|
||||
Assert.AreEqual(contentItem.UpdateDate.ToString(CultureInfo.InvariantCulture), versionDtos.Single(x => x.Id == versionDtos.Max(y => y.Id)).VersionDate.ToString(CultureInfo.InvariantCulture));
|
||||
Assert.AreEqual(contentItem.Version, versionDtos.Single(x => x.Id == versionDtos.Max(y => y.Id)).VersionId);
|
||||
|
||||
var allVersions = repository.GetAllVersions(content[0].Id);
|
||||
var allKnownVersions = versionDtos.Select(x => x.VersionId).Union(new[]{ content1.Version }).ToArray();
|
||||
Assert.IsTrue(allKnownVersions.ContainsAll(allVersions.Select(x => x.Version)));
|
||||
Assert.IsTrue(allVersions.Select(x => x.Version).ContainsAll(allKnownVersions));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This tests the regression issue of U4-9438
|
||||
/// </summary>
|
||||
@@ -226,6 +355,62 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Rebuild_All_Xml_Structures_Ensure_Orphaned_Are_Removed()
|
||||
{
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
ContentTypeRepository contentTypeRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out contentTypeRepository))
|
||||
{
|
||||
//delete all xml
|
||||
unitOfWork.Database.Execute("DELETE FROM cmsContentXml");
|
||||
|
||||
var contentType1 = MockedContentTypes.CreateSimpleContentType("Textpage1", "Textpage1");
|
||||
contentTypeRepository.AddOrUpdate(contentType1);
|
||||
var allCreated = new List<IContent>();
|
||||
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
//These will be non-published so shouldn't show up
|
||||
var c1 = MockedContent.CreateSimpleContent(contentType1);
|
||||
repository.AddOrUpdate(c1);
|
||||
allCreated.Add(c1);
|
||||
}
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
var c1 = MockedContent.CreateSimpleContent(contentType1);
|
||||
c1.ChangePublishedState(PublishedState.Published);
|
||||
repository.AddOrUpdate(c1);
|
||||
allCreated.Add(c1);
|
||||
}
|
||||
unitOfWork.Commit();
|
||||
|
||||
//now create some versions of this content - this shouldn't affect the xml structures saved
|
||||
for (int i = 0; i < allCreated.Count; i++)
|
||||
{
|
||||
allCreated[i].Name = "blah" + i;
|
||||
repository.AddOrUpdate(allCreated[i]);
|
||||
}
|
||||
unitOfWork.Commit();
|
||||
|
||||
//Add some extra orphaned rows that shouldn't be there
|
||||
var notPublished = MockedContent.CreateSimpleContent(contentType1);
|
||||
repository.AddOrUpdate(notPublished);
|
||||
unitOfWork.Commit();
|
||||
//Force add it
|
||||
unitOfWork.Database.Insert(new ContentXmlDto
|
||||
{
|
||||
NodeId = notPublished.Id,
|
||||
Xml = "<test></test>"
|
||||
});
|
||||
|
||||
repository.RebuildXmlStructures(media => new XElement("test"), 10);
|
||||
|
||||
Assert.AreEqual(100, unitOfWork.Database.ExecuteScalar<int>("SELECT COUNT(*) FROM cmsContentXml"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Rebuild_All_Xml_Structures_For_Content_Type()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Tests.TestHelpers.Entities;
|
||||
|
||||
namespace Umbraco.Tests.Persistence.Repositories
|
||||
{
|
||||
[DatabaseTestBehavior(DatabaseBehavior.NewDbFileAndSchemaPerTest)]
|
||||
[TestFixture]
|
||||
public class EntityRepositoryTest : BaseDatabaseFactoryTest
|
||||
{
|
||||
[SetUp]
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
}
|
||||
|
||||
private ContentRepository CreateContentRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository)
|
||||
{
|
||||
TemplateRepository tr;
|
||||
return CreateContentRepository(unitOfWork, out contentTypeRepository, out tr);
|
||||
}
|
||||
|
||||
private ContentRepository CreateContentRepository(IScopeUnitOfWork unitOfWork, out ContentTypeRepository contentTypeRepository, out TemplateRepository templateRepository)
|
||||
{
|
||||
templateRepository = new TemplateRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, Mock.Of<IFileSystem>(), Mock.Of<IFileSystem>(), Mock.Of<ITemplatesSection>());
|
||||
var tagRepository = new TagRepository(unitOfWork, CacheHelper, Logger, SqlSyntax);
|
||||
contentTypeRepository = new ContentTypeRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, templateRepository);
|
||||
var repository = new ContentRepository(unitOfWork, CacheHelper, Logger, SqlSyntax, contentTypeRepository, templateRepository, tagRepository, Mock.Of<IContentSection>());
|
||||
return repository;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Deal_With_Corrupt_Duplicate_Newest_Published_Flags_Full_Model()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
ContentTypeRepository contentTypeRepository;
|
||||
IContent content1;
|
||||
|
||||
using (var repository = CreateContentRepository(unitOfWork, out contentTypeRepository))
|
||||
{
|
||||
var hasPropertiesContentType = MockedContentTypes.CreateSimpleContentType("umbTextpage1", "Textpage");
|
||||
content1 = MockedContent.CreateSimpleContent(hasPropertiesContentType);
|
||||
|
||||
contentTypeRepository.AddOrUpdate(hasPropertiesContentType);
|
||||
repository.AddOrUpdate(content1);
|
||||
unitOfWork.Commit();
|
||||
}
|
||||
|
||||
var versionDtos = new List<ContentVersionDto>();
|
||||
|
||||
//Now manually corrupt the data
|
||||
var versions = new[] {Guid.NewGuid(), Guid.NewGuid()};
|
||||
for (var index = 0; index < versions.Length; index++)
|
||||
{
|
||||
var version = versions[index];
|
||||
var versionDate = DateTime.Now.AddMinutes(index);
|
||||
var versionDto = new ContentVersionDto
|
||||
{
|
||||
NodeId = content1.Id,
|
||||
VersionDate = versionDate,
|
||||
VersionId = version
|
||||
};
|
||||
this.DatabaseContext.Database.Insert(versionDto);
|
||||
versionDtos.Add(versionDto);
|
||||
this.DatabaseContext.Database.Insert(new DocumentDto
|
||||
{
|
||||
Newest = true,
|
||||
NodeId = content1.Id,
|
||||
Published = true,
|
||||
Text = content1.Name,
|
||||
VersionId = version,
|
||||
WriterUserId = 0,
|
||||
UpdateDate = versionDate,
|
||||
TemplateId = content1.Template == null || content1.Template.Id <= 0 ? null : (int?)content1.Template.Id
|
||||
});
|
||||
}
|
||||
|
||||
// Assert
|
||||
using (var repository = new EntityRepository(unitOfWork))
|
||||
{
|
||||
var content = repository.GetByQuery(new Query<IUmbracoEntity>().Where(c => c.Id == content1.Id), Constants.ObjectTypes.DocumentGuid).ToArray();
|
||||
Assert.AreEqual(1, content.Length);
|
||||
Assert.AreEqual(versionDtos.Max(x => x.Id), content[0].AdditionalData["VersionId"]);
|
||||
|
||||
content = repository.GetAll(Constants.ObjectTypes.DocumentGuid, content[0].Key).ToArray();
|
||||
Assert.AreEqual(1, content.Length);
|
||||
Assert.AreEqual(versionDtos.Max(x => x.Id), content[0].AdditionalData["VersionId"]);
|
||||
|
||||
content = repository.GetAll(Constants.ObjectTypes.DocumentGuid, content[0].Id).ToArray();
|
||||
Assert.AreEqual(1, content.Length);
|
||||
Assert.AreEqual(versionDtos.Max(x => x.Id), content[0].AdditionalData["VersionId"]);
|
||||
|
||||
var contentItem = repository.Get(content[0].Id, Constants.ObjectTypes.DocumentGuid);
|
||||
Assert.AreEqual(versionDtos.Max(x => x.Id), contentItem.AdditionalData["VersionId"]);
|
||||
|
||||
contentItem = repository.GetByKey(content[0].Key, Constants.ObjectTypes.DocumentGuid);
|
||||
Assert.AreEqual(versionDtos.Max(x => x.Id), contentItem.AdditionalData["VersionId"]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Slim model will test the EntityRepository when it doesn't know the object type so it will
|
||||
/// make the simplest (slim) query
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void Deal_With_Corrupt_Duplicate_Newest_Published_Flags_Slim_Model()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
ContentTypeRepository contentTypeRepository;
|
||||
IContent content1;
|
||||
|
||||
using (var repository = CreateContentRepository(unitOfWork, out contentTypeRepository))
|
||||
{
|
||||
var hasPropertiesContentType = MockedContentTypes.CreateSimpleContentType("umbTextpage1", "Textpage");
|
||||
content1 = MockedContent.CreateSimpleContent(hasPropertiesContentType);
|
||||
|
||||
contentTypeRepository.AddOrUpdate(hasPropertiesContentType);
|
||||
repository.AddOrUpdate(content1);
|
||||
unitOfWork.Commit();
|
||||
}
|
||||
|
||||
//Now manually corrupt the data
|
||||
var versions = new[] { Guid.NewGuid(), Guid.NewGuid() };
|
||||
for (var index = 0; index < versions.Length; index++)
|
||||
{
|
||||
var version = versions[index];
|
||||
var versionDate = DateTime.Now.AddMinutes(index);
|
||||
var versionDto = new ContentVersionDto
|
||||
{
|
||||
NodeId = content1.Id,
|
||||
VersionDate = versionDate,
|
||||
VersionId = version
|
||||
};
|
||||
this.DatabaseContext.Database.Insert(versionDto);
|
||||
this.DatabaseContext.Database.Insert(new DocumentDto
|
||||
{
|
||||
Newest = true,
|
||||
NodeId = content1.Id,
|
||||
Published = true,
|
||||
Text = content1.Name,
|
||||
VersionId = version,
|
||||
WriterUserId = 0,
|
||||
UpdateDate = versionDate,
|
||||
TemplateId = content1.Template == null || content1.Template.Id <= 0 ? null : (int?)content1.Template.Id
|
||||
});
|
||||
}
|
||||
|
||||
// Assert
|
||||
using (var repository = new EntityRepository(unitOfWork))
|
||||
{
|
||||
var content = repository.GetByQuery(new Query<IUmbracoEntity>().Where(c => c.Id == content1.Id)).ToArray();
|
||||
Assert.AreEqual(1, content.Length);
|
||||
var contentItem = repository.Get(content[0].Id);
|
||||
Assert.IsNotNull(contentItem);
|
||||
contentItem = repository.GetByKey(content[0].Key);
|
||||
Assert.IsNotNull(contentItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -70,6 +71,44 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Rebuild_All_Xml_Structures_Ensure_Orphaned_Are_Removed()
|
||||
{
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
MediaTypeRepository mediaTypeRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository))
|
||||
{
|
||||
//delete all xml
|
||||
unitOfWork.Database.Execute("DELETE FROM cmsContentXml");
|
||||
|
||||
var mediaType = mediaTypeRepository.Get(1032);
|
||||
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
var image = MockedMedia.CreateMediaImage(mediaType, -1);
|
||||
repository.AddOrUpdate(image);
|
||||
}
|
||||
unitOfWork.Commit();
|
||||
|
||||
//Add some extra orphaned rows that shouldn't be there
|
||||
var trashed = MockedMedia.CreateMediaImage(mediaType, -1);
|
||||
trashed.ChangeTrashedState(true, Constants.System.RecycleBinMedia);
|
||||
repository.AddOrUpdate(trashed);
|
||||
unitOfWork.Commit();
|
||||
//Force add it
|
||||
unitOfWork.Database.Insert(new ContentXmlDto
|
||||
{
|
||||
NodeId = trashed.Id,
|
||||
Xml = "<test></test>"
|
||||
});
|
||||
|
||||
repository.RebuildXmlStructures(media => new XElement("test"), 10);
|
||||
|
||||
Assert.AreEqual(103, unitOfWork.Database.ExecuteScalar<int>("SELECT COUNT(*) FROM cmsContentXml"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Rebuild_Some_Xml_Structures()
|
||||
{
|
||||
@@ -345,6 +384,61 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_GetByQuery_On_MediaRepository_With_ContentType_Id_Filter()
|
||||
{
|
||||
// Arrange
|
||||
var folderMediaType = ServiceContext.ContentTypeService.GetMediaType(1031);
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
MediaTypeRepository mediaTypeRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository))
|
||||
{
|
||||
// Act
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var folder = MockedMedia.CreateMediaFolder(folderMediaType, -1);
|
||||
repository.AddOrUpdate(folder);
|
||||
}
|
||||
unitOfWork.Commit();
|
||||
|
||||
var types = new[] { 1031 };
|
||||
var query = Query<IMedia>.Builder.Where(x => types.Contains(x.ContentTypeId));
|
||||
var result = repository.GetByQuery(query);
|
||||
|
||||
// Assert
|
||||
Assert.That(result.Count(), Is.GreaterThanOrEqualTo(11));
|
||||
}
|
||||
}
|
||||
|
||||
[Ignore("We could allow this to work but it requires an extra join on the query used which currently we don't absolutely need so leaving this out for now")]
|
||||
[Test]
|
||||
public void Can_Perform_GetByQuery_On_MediaRepository_With_ContentType_Alias_Filter()
|
||||
{
|
||||
// Arrange
|
||||
var folderMediaType = ServiceContext.ContentTypeService.GetMediaType(1031);
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
MediaTypeRepository mediaTypeRepository;
|
||||
using (var repository = CreateRepository(unitOfWork, out mediaTypeRepository))
|
||||
{
|
||||
// Act
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var folder = MockedMedia.CreateMediaFolder(folderMediaType, -1);
|
||||
repository.AddOrUpdate(folder);
|
||||
}
|
||||
unitOfWork.Commit();
|
||||
|
||||
var types = new[] { "Folder" };
|
||||
var query = Query<IMedia>.Builder.Where(x => types.Contains(x.ContentType.Alias));
|
||||
var result = repository.GetByQuery(query);
|
||||
|
||||
// Assert
|
||||
Assert.That(result.Count(), Is.GreaterThanOrEqualTo(11));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_GetPagedResultsByQuery_ForFirstPage_On_MediaRepository()
|
||||
{
|
||||
@@ -472,7 +566,7 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
Assert.That(result.First().Name, Is.EqualTo("Test File"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Can_Perform_GetPagedResultsByQuery_WithFilterMatchingAll_On_MediaRepository()
|
||||
{
|
||||
|
||||
@@ -154,36 +154,61 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
[Test]
|
||||
public void Get_All()
|
||||
{
|
||||
var content = CreateTestData(3).ToArray();
|
||||
var content = CreateTestData(30).ToArray();
|
||||
|
||||
var provider = new PetaPocoUnitOfWorkProvider(Logger);
|
||||
var unitOfWork = provider.GetUnitOfWork();
|
||||
using (var repo = new PublicAccessRepository(unitOfWork, CacheHelper, Logger, SqlSyntax))
|
||||
{
|
||||
var entry1 = new PublicAccessEntry(content[0], content[1], content[2], new[]
|
||||
{
|
||||
var allEntries = new List<PublicAccessEntry>();
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
new PublicAccessRule
|
||||
var rules = new List<PublicAccessRule>();
|
||||
for (int j = 0; j < 50; j++)
|
||||
{
|
||||
RuleValue = "test",
|
||||
RuleType = "RoleName"
|
||||
},
|
||||
});
|
||||
repo.AddOrUpdate(entry1);
|
||||
rules.Add(new PublicAccessRule
|
||||
{
|
||||
RuleValue = "test" + j,
|
||||
RuleType = "RoleName" + j
|
||||
});
|
||||
}
|
||||
var entry1 = new PublicAccessEntry(content[i], content[i+1], content[i+2], rules);
|
||||
repo.AddOrUpdate(entry1);
|
||||
unitOfWork.Commit();
|
||||
allEntries.Add(entry1);
|
||||
}
|
||||
|
||||
var entry2 = new PublicAccessEntry(content[1], content[0], content[2], new[]
|
||||
//now remove a few rules from a few of the items and then add some more, this will put things 'out of order' which
|
||||
//we need to verify our sort order is working for the relator
|
||||
for (int i = 0; i < allEntries.Count; i++)
|
||||
{
|
||||
new PublicAccessRule
|
||||
//all the even ones
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
RuleValue = "test",
|
||||
RuleType = "RoleName"
|
||||
},
|
||||
});
|
||||
repo.AddOrUpdate(entry2);
|
||||
|
||||
unitOfWork.Commit();
|
||||
var rules = allEntries[i].Rules.ToArray();
|
||||
for (int j = 0; j < rules.Length; j++)
|
||||
{
|
||||
//all the even ones
|
||||
if (j % 2 == 0)
|
||||
{
|
||||
allEntries[i].RemoveRule(rules[j]);
|
||||
}
|
||||
}
|
||||
allEntries[i].AddRule("newrule" + i, "newrule" + i);
|
||||
repo.AddOrUpdate(allEntries[i]);
|
||||
unitOfWork.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
var found = repo.GetAll().ToArray();
|
||||
Assert.AreEqual(2, found.Count());
|
||||
Assert.AreEqual(10, found.Length);
|
||||
|
||||
foreach (var publicAccessEntry in found)
|
||||
{
|
||||
var matched = allEntries.First(x => x.Key == publicAccessEntry.Key);
|
||||
|
||||
Assert.AreEqual(matched.Rules.Count(), publicAccessEntry.Rules.Count());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.PropertyEditors.ValueConverters;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests.PropertyEditors
|
||||
{
|
||||
@@ -58,5 +57,44 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
[TestCase("apples", new[] { "apples" })]
|
||||
[TestCase("apples,oranges", new[] { "apples", "oranges" })]
|
||||
[TestCase(" apples, oranges, pears ", new[] { "apples", "oranges", "pears" })]
|
||||
[TestCase("", new string[] { })]
|
||||
[TestCase(null, new string[] { })]
|
||||
public void CanConvertCheckboxListPropertyEditor(object value, IEnumerable<string> expected)
|
||||
{
|
||||
var converter = new CheckboxListValueConverter();
|
||||
var result = converter.ConvertSourceToObject(null, value, false);
|
||||
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
[TestCase("apples", new[] {"apples"})]
|
||||
[TestCase("apples,oranges", new[] {"apples", "oranges"})]
|
||||
[TestCase("apples , oranges, pears ", new[] {"apples", "oranges", "pears"})]
|
||||
[TestCase("", new string[] {})]
|
||||
[TestCase(null, new string[] {})]
|
||||
public void CanConvertDropdownListMultiplePropertyEditor(object value, IEnumerable<string> expected)
|
||||
{
|
||||
var converter = new DropdownListMultipleValueConverter();
|
||||
var result = converter.ConvertSourceToObject(null, value, false);
|
||||
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
[TestCase("100", new[] {100})]
|
||||
[TestCase("100,200", new[] {100, 200})]
|
||||
[TestCase("100 , 200, 300 ", new[] {100, 200, 300})]
|
||||
[TestCase("", new int[] {})]
|
||||
[TestCase(null, new int[] {})]
|
||||
public void CanConvertDropdownListMultipleWithKeysPropertyEditor(object value, IEnumerable<int> expected)
|
||||
{
|
||||
var converter = new DropdownListMultipleWithKeysValueConverter();
|
||||
var result = converter.ConvertDataToSource(null, value, false);
|
||||
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace Umbraco.Tests.Scoping
|
||||
|
||||
private static void ClearFiles()
|
||||
{
|
||||
TestHelper.DeleteDirectory(IOHelper.MapPath("media"));
|
||||
TestHelper.DeleteDirectory(IOHelper.MapPath("FileSysTests"));
|
||||
TestHelper.DeleteDirectory(IOHelper.MapPath("App_Data"));
|
||||
}
|
||||
@@ -43,6 +44,8 @@ namespace Umbraco.Tests.Scoping
|
||||
var physMediaFileSystem = new PhysicalFileSystem(IOHelper.MapPath("media"), "ignore");
|
||||
var mediaFileSystem = FileSystemProviderManager.Current.MediaFileSystem;
|
||||
|
||||
Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt"));
|
||||
|
||||
var scopeProvider = ApplicationContext.ScopeProvider;
|
||||
using (var scope = scopeProvider.CreateScope(scopeFileSystems: true))
|
||||
{
|
||||
|
||||
@@ -36,11 +36,15 @@ namespace Umbraco.Tests.Services
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
VersionableRepositoryBase<int, IContent>.ThrowOnWarning = true;
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public override void TearDown()
|
||||
{
|
||||
VersionableRepositoryBase<int, IContent>.ThrowOnWarning = false;
|
||||
|
||||
base.TearDown();
|
||||
}
|
||||
|
||||
@@ -762,16 +766,26 @@ namespace Umbraco.Tests.Services
|
||||
var parent = ServiceContext.ContentService.GetById(NodeDto.NodeIdSeed + 1);
|
||||
ServiceContext.ContentService.Publish(parent);//Publishing root, so Text Page 2 can be updated.
|
||||
var subpage2 = contentService.GetById(NodeDto.NodeIdSeed + 3);
|
||||
|
||||
subpage2.Name = "Text Page 2 Updated";
|
||||
subpage2.SetValue("author", "Jane Doe");
|
||||
contentService.SaveAndPublishWithStatus(subpage2, 0);//NOTE New versions are only added between publish-state-changed, so publishing to ensure addition version.
|
||||
|
||||
subpage2.Name = "Text Page 2 Updated again";
|
||||
subpage2.SetValue("author", "Bob Hope");
|
||||
contentService.SaveAndPublishWithStatus(subpage2, 0);//NOTE New versions are only added between publish-state-changed, so publishing to ensure addition version.
|
||||
|
||||
// Act
|
||||
var versions = contentService.GetVersions(NodeDto.NodeIdSeed + 3).ToList();
|
||||
|
||||
// Assert
|
||||
Assert.That(versions.Any(), Is.True);
|
||||
Assert.That(versions.Count(), Is.GreaterThanOrEqualTo(2));
|
||||
|
||||
//ensure each version contains the correct property values
|
||||
Assert.AreEqual("John Doe", versions[2].GetValue("author"));
|
||||
Assert.AreEqual("Jane Doe", versions[1].GetValue("author"));
|
||||
Assert.AreEqual("Bob Hope", versions[0].GetValue("author"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -1785,6 +1799,74 @@ namespace Umbraco.Tests.Services
|
||||
Assert.IsTrue(content.HasPublishedVersion());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Get_Paged_Children()
|
||||
{
|
||||
var service = ServiceContext.ContentService;
|
||||
// Start by cleaning the "db"
|
||||
var umbTextPage = service.GetById(new Guid("B58B3AD4-62C2-4E27-B1BE-837BD7C533E0"));
|
||||
service.Delete(umbTextPage);
|
||||
|
||||
var contentType = MockedContentTypes.CreateSimpleContentType();
|
||||
ServiceContext.ContentTypeService.Save(contentType);
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var c1 = MockedContent.CreateSimpleContent(contentType);
|
||||
ServiceContext.ContentService.Save(c1);
|
||||
}
|
||||
|
||||
long total;
|
||||
var entities = service.GetPagedChildren(-1, 0, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(6));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
entities = service.GetPagedChildren(-1, 1, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(4));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Get_Paged_Children_Dont_Get_Descendants()
|
||||
{
|
||||
var service = ServiceContext.ContentService;
|
||||
// Start by cleaning the "db"
|
||||
var umbTextPage = service.GetById(new Guid("B58B3AD4-62C2-4E27-B1BE-837BD7C533E0"));
|
||||
service.Delete(umbTextPage);
|
||||
|
||||
var contentType = MockedContentTypes.CreateSimpleContentType();
|
||||
ServiceContext.ContentTypeService.Save(contentType);
|
||||
// only add 9 as we also add a content with children
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
var c1 = MockedContent.CreateSimpleContent(contentType);
|
||||
ServiceContext.ContentService.Save(c1);
|
||||
}
|
||||
|
||||
var willHaveChildren = MockedContent.CreateSimpleContent(contentType);
|
||||
ServiceContext.ContentService.Save(willHaveChildren);
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var c1 = MockedContent.CreateSimpleContent(contentType, "Content" + i, willHaveChildren.Id);
|
||||
ServiceContext.ContentService.Save(c1);
|
||||
}
|
||||
|
||||
long total;
|
||||
// children in root including the folder - not the descendants in the folder
|
||||
var entities = service.GetPagedChildren(-1, 0, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(6));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
entities = service.GetPagedChildren(-1, 1, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(4));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
|
||||
// children in folder
|
||||
entities = service.GetPagedChildren(willHaveChildren.Id, 0, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(6));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
entities = service.GetPagedChildren(willHaveChildren.Id, 1, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(4));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
private IEnumerable<IContent> CreateContentHierarchy()
|
||||
{
|
||||
var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage");
|
||||
|
||||
@@ -7,6 +7,7 @@ using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
@@ -30,6 +31,33 @@ namespace Umbraco.Tests.Services
|
||||
base.TearDown();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Get_Paged_Children_With_Media_Type_Filter()
|
||||
{
|
||||
var mediaService = ServiceContext.MediaService;
|
||||
var mediaType1 = MockedContentTypes.CreateImageMediaType("Image2");
|
||||
ServiceContext.ContentTypeService.Save(mediaType1);
|
||||
var mediaType2 = MockedContentTypes.CreateImageMediaType("Image3");
|
||||
ServiceContext.ContentTypeService.Save(mediaType2);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var m1 = MockedMedia.CreateMediaImage(mediaType1, -1);
|
||||
mediaService.Save(m1);
|
||||
var m2 = MockedMedia.CreateMediaImage(mediaType2, -1);
|
||||
mediaService.Save(m2);
|
||||
}
|
||||
|
||||
long total;
|
||||
var result = ServiceContext.MediaService.GetPagedChildren(-1, 0, 11, out total, "SortOrder", Direction.Ascending, true, null, new[] {mediaType1.Id, mediaType2.Id});
|
||||
Assert.AreEqual(11, result.Count());
|
||||
Assert.AreEqual(20, total);
|
||||
|
||||
result = ServiceContext.MediaService.GetPagedChildren(-1, 1, 11, out total, "SortOrder", Direction.Ascending, true, null, new[] { mediaType1.Id, mediaType2.Id });
|
||||
Assert.AreEqual(9, result.Count());
|
||||
Assert.AreEqual(20, total);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Move_Media()
|
||||
{
|
||||
@@ -145,6 +173,70 @@ namespace Umbraco.Tests.Services
|
||||
Assert.That(resolvedMedia.GetValue(Constants.Conventions.Media.File).ToString().Contains(mediaPath));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Get_Paged_Children()
|
||||
{
|
||||
var mediaType = MockedContentTypes.CreateImageMediaType("Image2");
|
||||
ServiceContext.ContentTypeService.Save(mediaType);
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var c1 = MockedMedia.CreateMediaImage(mediaType, -1);
|
||||
ServiceContext.MediaService.Save(c1);
|
||||
}
|
||||
|
||||
var service = ServiceContext.MediaService;
|
||||
|
||||
long total;
|
||||
var entities = service.GetPagedChildren(-1, 0, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(6));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
entities = service.GetPagedChildren(-1, 1, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(4));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Get_Paged_Children_Dont_Get_Descendants()
|
||||
{
|
||||
var mediaType = MockedContentTypes.CreateImageMediaType("Image2");
|
||||
ServiceContext.ContentTypeService.Save(mediaType);
|
||||
// only add 9 as we also add a folder with children
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
var m1 = MockedMedia.CreateMediaImage(mediaType, -1);
|
||||
ServiceContext.MediaService.Save(m1);
|
||||
}
|
||||
|
||||
var mediaTypeForFolder = MockedContentTypes.CreateImageMediaType("Folder2");
|
||||
ServiceContext.ContentTypeService.Save(mediaTypeForFolder);
|
||||
var mediaFolder = MockedMedia.CreateMediaFolder(mediaTypeForFolder, -1);
|
||||
ServiceContext.MediaService.Save(mediaFolder);
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var m1 = MockedMedia.CreateMediaImage(mediaType, mediaFolder.Id);
|
||||
ServiceContext.MediaService.Save(m1);
|
||||
}
|
||||
|
||||
var service = ServiceContext.MediaService;
|
||||
|
||||
long total;
|
||||
// children in root including the folder - not the descendants in the folder
|
||||
var entities = service.GetPagedChildren(-1, 0, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(6));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
entities = service.GetPagedChildren(-1, 1, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(4));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
|
||||
// children in folder
|
||||
entities = service.GetPagedChildren(mediaFolder.Id, 0, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(6));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
entities = service.GetPagedChildren(mediaFolder.Id, 1, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(4));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
private Tuple<IMedia, IMedia, IMedia, IMedia, IMedia> CreateTrashedTestMedia()
|
||||
{
|
||||
//Create and Save folder-Media -> 1050
|
||||
|
||||
@@ -24,6 +24,7 @@ using Umbraco.Web.PublishedCache.XmlPublishedCache;
|
||||
using Umbraco.Web.Security;
|
||||
using umbraco.BusinessLogic;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Scoping;
|
||||
|
||||
namespace Umbraco.Tests.TestHelpers
|
||||
@@ -110,6 +111,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
{
|
||||
IsReady = true
|
||||
};
|
||||
|
||||
return _appContext;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ using Umbraco.Web;
|
||||
using Umbraco.Web.Models.Mapping;
|
||||
using umbraco.BusinessLogic;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Scoping;
|
||||
|
||||
namespace Umbraco.Tests.TestHelpers
|
||||
@@ -150,6 +151,11 @@ namespace Umbraco.Tests.TestHelpers
|
||||
{
|
||||
var applicationContext = CreateApplicationContext();
|
||||
ApplicationContext.Current = applicationContext;
|
||||
|
||||
// FileSystemProviderManager captures the current ApplicationContext ScopeProvider
|
||||
// in its current static instance (yea...) so we need to reset it here to ensure
|
||||
// it is using the proper ScopeProvider
|
||||
FileSystemProviderManager.Current.Reset();
|
||||
}
|
||||
|
||||
protected virtual ApplicationContext CreateApplicationContext()
|
||||
@@ -170,6 +176,7 @@ namespace Umbraco.Tests.TestHelpers
|
||||
{
|
||||
IsReady = true
|
||||
};
|
||||
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
|
||||
@@ -361,7 +361,7 @@ namespace Umbraco.Tests.TestHelpers.Entities
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.ContentPicker2Alias, DataTypeDatabaseType.Integer) { Alias = "contentPicker", Name = "Content Picker", Mandatory = false, SortOrder = 16, DataTypeDefinitionId = 1046 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.MediaPicker2Alias, DataTypeDatabaseType.Integer) { Alias = "mediaPicker", Name = "Media Picker", Mandatory = false, SortOrder = 17, DataTypeDefinitionId = 1048 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.MemberPicker2Alias, DataTypeDatabaseType.Integer) { Alias = "memberPicker", Name = "Member Picker", Mandatory = false, SortOrder = 18, DataTypeDefinitionId = 1047 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.RelatedLinksAlias, DataTypeDatabaseType.Ntext) { Alias = "relatedLinks", Name = "Related Links", Mandatory = false, SortOrder = 21, DataTypeDefinitionId = 1040 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.RelatedLinks2Alias, DataTypeDatabaseType.Ntext) { Alias = "relatedLinks", Name = "Related Links", Mandatory = false, SortOrder = 21, DataTypeDefinitionId = 1050 });
|
||||
contentCollection.Add(new PropertyType(Constants.PropertyEditors.TagsAlias, DataTypeDatabaseType.Ntext) { Alias = "tags", Name = "Tags", Mandatory = false, SortOrder = 22, DataTypeDefinitionId = 1041 });
|
||||
|
||||
//contentCollection.Add(new PropertyType(Constants.PropertyEditors.UltraSimpleEditorAlias, DataTypeDatabaseType.Ntext) { Alias = "simpleEditor", Name = "Ultra Simple Editor", Mandatory = false, SortOrder = 19, DataTypeDefinitionId = 1038 });
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Umbraco.Tests</RootNamespace>
|
||||
<AssemblyName>Umbraco.Tests</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
@@ -92,9 +92,11 @@
|
||||
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Semver, Version=2.0.4.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Semver.2.0.4\lib\net452\Semver.dll</HintPath>
|
||||
<HintPath>..\packages\Semver.2.0.4\lib\netstandard1.1\Semver.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
||||
<Reference Include="System.configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
@@ -157,6 +159,7 @@
|
||||
<Compile Include="Cache\CacheRefresherEventHandlerTests.cs" />
|
||||
<Compile Include="Dependencies\NuGet.cs" />
|
||||
<Compile Include="CallContextTests.cs" />
|
||||
<Compile Include="Issues\U9560.cs" />
|
||||
<Compile Include="Collections\OrderedHashSetTests.cs" />
|
||||
<Compile Include="IO\ShadowFileSystemTests.cs" />
|
||||
<Compile Include="Logging\ConsoleLogger.cs" />
|
||||
@@ -168,6 +171,7 @@
|
||||
<Compile Include="Persistence\PetaPocoCachesTest.cs" />
|
||||
<Compile Include="Persistence\PetaPocoExpressionsTests.cs" />
|
||||
<Compile Include="Persistence\Repositories\LockedRepositoryTests.cs" />
|
||||
<Compile Include="Persistence\Repositories\EntityRepositoryTest.cs" />
|
||||
<Compile Include="Persistence\Repositories\RedirectUrlRepositoryTests.cs" />
|
||||
<Compile Include="Scheduling\BackgroundTaskRunnerTests2.cs" />
|
||||
<Compile Include="Routing\NiceUrlRoutesTests.cs" />
|
||||
|
||||
@@ -21,7 +21,11 @@
|
||||
<package id="NUnit" version="2.6.2" targetFramework="net45" />
|
||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||
<package id="Selenium.WebDriver" version="2.32.0" targetFramework="net45" />
|
||||
<package id="Semver" version="2.0.4" targetFramework="net462" />
|
||||
<package id="Semver" version="2.0.4" targetFramework="net45" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
|
||||
<package id="SqlServerCE" version="4.0.0.1" targetFramework="net45" />
|
||||
<package id="System.Runtime" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.Extensions" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Runtime.InteropServices" version="4.1.0" targetFramework="net45" />
|
||||
<package id="System.Text.RegularExpressions" version="4.1.0" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -152,12 +152,12 @@ function entityResource($q, $http, umbRequestHelper) {
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"entityApiBaseUrl",
|
||||
"GetById",
|
||||
[{ id: id}, {type: type }])),
|
||||
'Failed to retrieve entity data for id ' + id);
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"entityApiBaseUrl",
|
||||
"GetById",
|
||||
[{ id: id }, { type: type }])),
|
||||
'Failed to retrieve entity data for id ' + id);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -427,7 +427,9 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
* Retrieves all media children with types used as folders.
|
||||
* Uses the convention of looking for media items with mediaTypes ending in
|
||||
* *Folder so will match "Folder", "bannerFolder", "secureFolder" etc,
|
||||
*
|
||||
*
|
||||
* NOTE: This will return a max of 500 folders, if more is required it needs to be paged
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* mediaResource.getChildFolders(1234)
|
||||
@@ -445,14 +447,15 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
parentId = -1;
|
||||
}
|
||||
|
||||
//NOTE: This will return a max of 500 folders, if more is required it needs to be paged
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaApiBaseUrl",
|
||||
"GetChildFolders",
|
||||
[
|
||||
{ id: parentId }
|
||||
])),
|
||||
{
|
||||
id: parentId
|
||||
})),
|
||||
'Failed to retrieve child folders for media item ' + parentId);
|
||||
},
|
||||
|
||||
|
||||
@@ -19,15 +19,20 @@ angular.module('umbraco.security.interceptor')
|
||||
return promise;
|
||||
}, function(originalResponse) {
|
||||
// Intercept failed requests
|
||||
|
||||
// Make sure we have the configuration of the request (don't we always?)
|
||||
var config = originalResponse.config ? originalResponse.config : {};
|
||||
|
||||
// Make sure we have an object for the headers of the request
|
||||
var headers = config.headers ? config.headers : {};
|
||||
|
||||
//Here we'll check if we should ignore the error, this will be based on an original header set
|
||||
var headers = originalResponse.config ? originalResponse.config.headers : {};
|
||||
if (headers["x-umb-ignore-error"] === "ignore") {
|
||||
//Here we'll check if we should ignore the error (either based on the original header set or the request configuration)
|
||||
if (headers["x-umb-ignore-error"] === "ignore" || config.umbIgnoreErrors === true || (angular.isArray(config.umbIgnoreStatus) && config.umbIgnoreStatus.indexOf(originalResponse.status) !== -1)) {
|
||||
//exit/ignore
|
||||
return promise;
|
||||
}
|
||||
var filtered = _.find(requestInterceptorFilter(), function(val) {
|
||||
return originalResponse.config.url.indexOf(val) > 0;
|
||||
return config.url.indexOf(val) > 0;
|
||||
});
|
||||
if (filtered) {
|
||||
return promise;
|
||||
@@ -99,4 +104,4 @@ angular.module('umbraco.security.interceptor')
|
||||
// We have to add the interceptor to the queue as a string because the interceptor depends upon service instances that are not available in the config block.
|
||||
.config(['$httpProvider', function ($httpProvider) {
|
||||
$httpProvider.responseInterceptors.push('securityInterceptor');
|
||||
}]);
|
||||
}]);
|
||||
|
||||
@@ -7,6 +7,19 @@ function mediaTypeHelper(mediaTypeResource, $q) {
|
||||
|
||||
var mediaTypeHelperService = {
|
||||
|
||||
isFolderType: function(mediaEntity) {
|
||||
if (!mediaEntity) {
|
||||
throw "mediaEntity is null";
|
||||
}
|
||||
if (!mediaEntity.contentTypeAlias) {
|
||||
throw "mediaEntity.contentTypeAlias is null";
|
||||
}
|
||||
|
||||
//if you create a media type, which has an alias that ends with ...Folder then its a folder: ex: "secureFolder", "bannerFolder", "Folder"
|
||||
//this is the exact same logic that is performed in MediaController.GetChildFolders
|
||||
return mediaEntity.contentTypeAlias.endsWith("Folder");
|
||||
},
|
||||
|
||||
getAllowedImagetypes: function (mediaId){
|
||||
|
||||
// Get All allowedTypes
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user