Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e154e8bc9 | |||
| 1ffdd1abd1 | |||
| a06de1b165 | |||
| 0fd3af6828 | |||
| fafb207799 | |||
| b1aea424e8 | |||
| 3598acaddc | |||
| 8e03a1ffca | |||
| ded8afa8fc | |||
| dcd2b1eb6b | |||
| c04ef47be3 | |||
| 62f3c87e8a | |||
| 1b9776ecfb | |||
| 3f3db006e7 | |||
| 7801cdf9ff | |||
| de9c5b88ab | |||
| 77981f889f | |||
| 0a132ed5ed | |||
| 27ee192c8f | |||
| dfa58183c6 | |||
| e8668f3ed4 | |||
| c84e3dac38 | |||
| 72ab51ea60 | |||
| 1bfb63fe86 | |||
| 2cf68ab263 | |||
| 215bc64a83 | |||
| 73f0b1992d | |||
| 21f54dd4ff | |||
| a5903ec419 | |||
| a9c7a7a405 | |||
| ce8286dadd | |||
| 504aac0350 | |||
| fd0cb7da23 | |||
| 6344ad28aa | |||
| eadc3c8c5a |
@@ -1,3 +1,3 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.6.0
|
||||
beta03
|
||||
beta04
|
||||
|
||||
+1
-1
@@ -12,4 +12,4 @@ using System.Resources;
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.6.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.0-beta03")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.0-beta04")]
|
||||
@@ -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 "beta03"; } }
|
||||
public static string CurrentComment { get { return "beta04"; } }
|
||||
|
||||
// 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
|
||||
|
||||
@@ -295,22 +295,5 @@ namespace Umbraco.Core
|
||||
return list1Groups.Count == list2Groups.Count
|
||||
&& 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,10 @@ namespace Umbraco.Core.Models
|
||||
return path
|
||||
.Replace('\\', System.IO.Path.DirectorySeparatorChar)
|
||||
.Replace('/', System.IO.Path.DirectorySeparatorChar);
|
||||
//.TrimStart(System.IO.Path.DirectorySeparatorChar);
|
||||
|
||||
//Don't strip the start - this was a bug fixed in 7.3, see ScriptRepositoryTests.PathTests
|
||||
//.TrimStart(System.IO.Path.DirectorySeparatorChar)
|
||||
//.TrimStart('/');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -101,7 +101,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
var translator = new SqlTranslator<PropertyType>(sqlClause, query);
|
||||
var sql = translator.Translate()
|
||||
.OrderBy<PropertyTypeDto>(x => x.PropertyTypeGroupId, SqlSyntax);
|
||||
//must be sorted this way for the relator to work
|
||||
.OrderBy<PropertyTypeGroupDto>(x => x.Id, SqlSyntax);
|
||||
|
||||
var dtos = Database.Fetch<PropertyTypeGroupDto, PropertyTypeDto, DataTypeDto, PropertyTypeGroupDto>(new GroupPropertyTypeRelator().Map, sql);
|
||||
|
||||
@@ -468,7 +469,8 @@ AND umbracoNode.id <> @id",
|
||||
.LeftJoin<DataTypeDto>()
|
||||
.On<PropertyTypeDto, DataTypeDto>(left => left.DataTypeId, right => right.DataTypeId)
|
||||
.Where<PropertyTypeGroupDto>(x => x.ContentTypeNodeId == id)
|
||||
.OrderBy<PropertyTypeGroupDto>(x => x.Id);
|
||||
//must be sorted this way for the relator to work
|
||||
.OrderBy<PropertyTypeGroupDto>(x => x.Id, SqlSyntax);
|
||||
|
||||
var dtos = Database.Fetch<PropertyTypeGroupDto, PropertyTypeDto, DataTypeDto, PropertyTypeGroupDto>(new GroupPropertyTypeRelator().Map, sql);
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
var sql = GetBaseQuery(false)
|
||||
.Where(GetBaseWhereClause(), new { Id = id })
|
||||
//must be sorted this way for the relator to work
|
||||
.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
|
||||
|
||||
var dto = Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql).FirstOrDefault();
|
||||
@@ -64,6 +65,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
sql.Where("cmsDictionary.pk in (@ids)", new { ids = ids });
|
||||
}
|
||||
|
||||
//must be sorted this way for the relator to work
|
||||
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
|
||||
|
||||
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql)
|
||||
.Select(dto => ConvertFromDto(dto));
|
||||
}
|
||||
@@ -73,6 +77,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var sqlClause = GetBaseQuery(false);
|
||||
var translator = new SqlTranslator<IDictionaryItem>(sqlClause, query);
|
||||
var sql = translator.Translate();
|
||||
//must be sorted this way for the relator to work
|
||||
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
|
||||
|
||||
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql)
|
||||
@@ -94,9 +99,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
else
|
||||
{
|
||||
sql.Select("*")
|
||||
.From<DictionaryDto>(SqlSyntax)
|
||||
.LeftJoin<LanguageTextDto>(SqlSyntax)
|
||||
.On<DictionaryDto, LanguageTextDto>(SqlSyntax, left => left.UniqueId, right => right.UniqueId);
|
||||
.From<DictionaryDto>(SqlSyntax)
|
||||
.LeftJoin<LanguageTextDto>(SqlSyntax)
|
||||
.On<DictionaryDto, LanguageTextDto>(SqlSyntax, left => left.UniqueId, right => right.UniqueId);
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
@@ -270,6 +275,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
var translator = new SqlTranslator<IDictionaryItem>(sqlClause, Query<IDictionaryItem>.Builder);
|
||||
var sql = translator.Translate();
|
||||
|
||||
//must be sorted this way for the relator to work
|
||||
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
|
||||
|
||||
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql)
|
||||
@@ -297,6 +304,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
protected override IEnumerable<DictionaryDto> PerformFetch(Sql sql)
|
||||
{
|
||||
//must be sorted this way for the relator to work
|
||||
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
|
||||
|
||||
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql);
|
||||
}
|
||||
|
||||
@@ -349,6 +359,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
protected override IEnumerable<DictionaryDto> PerformFetch(Sql sql)
|
||||
{
|
||||
//must be sorted this way for the relator to work
|
||||
sql.OrderBy<DictionaryDto>(x => x.UniqueId, SqlSyntax);
|
||||
|
||||
return Database.Fetch<DictionaryDto, LanguageTextDto, DictionaryDto>(new DictionaryLanguageTextRelator().Map, sql);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
private IMacro GetBySql(Sql sql)
|
||||
{
|
||||
//must be sorted this way for the relator to work
|
||||
sql.OrderBy<MacroDto>(x => x.Id, SqlSyntax);
|
||||
|
||||
var macroDto = Database.Fetch<MacroDto, MacroPropertyDto, MacroDto>(new MacroPropertyRelator().Map, sql).FirstOrDefault();
|
||||
if (macroDto == null)
|
||||
return null;
|
||||
@@ -68,7 +71,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
private IEnumerable<IMacro> GetAllNoIds()
|
||||
{
|
||||
var sql = GetBaseQuery(false);
|
||||
var sql = GetBaseQuery(false)
|
||||
//must be sorted this way for the relator to work
|
||||
.OrderBy<MacroDto>(x => x.Id, SqlSyntax);
|
||||
|
||||
return ConvertFromDtos(Database.Fetch<MacroDto, MacroPropertyDto, MacroDto>(new MacroPropertyRelator().Map, sql))
|
||||
.ToArray();// we don't want to re-iterate again!
|
||||
}
|
||||
@@ -92,6 +98,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var translator = new SqlTranslator<IMacro>(sqlClause, query);
|
||||
var sql = translator.Translate();
|
||||
|
||||
//must be sorted this way for the relator to work
|
||||
sql.OrderBy<MacroDto>(x => x.Id, SqlSyntax);
|
||||
|
||||
var dtos = Database.Fetch<MacroDto, MacroPropertyDto, MacroDto>(new MacroPropertyRelator().Map, sql);
|
||||
|
||||
foreach (var dto in dtos)
|
||||
@@ -114,13 +123,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return sql;
|
||||
}
|
||||
|
||||
private static Sql GetBaseQuery()
|
||||
private Sql GetBaseQuery()
|
||||
{
|
||||
var sql = new Sql();
|
||||
sql.Select("*")
|
||||
.From<MacroDto>()
|
||||
.LeftJoin<MacroPropertyDto>()
|
||||
.On<MacroDto, MacroPropertyDto>(left => left.Id, right => right.Macro);
|
||||
.From<MacroDto>()
|
||||
.LeftJoin<MacroPropertyDto>()
|
||||
.On<MacroDto, MacroPropertyDto>(left => left.Id, right => right.Macro);
|
||||
return sql;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var statement = string.Join(" OR ", ids.Select(x => string.Format("umbracoNode.id='{0}'", x)));
|
||||
sql.Where(statement);
|
||||
}
|
||||
sql.OrderByDescending<NodeDto>(x => x.NodeId, SqlSyntax);
|
||||
|
||||
//must be sorted this way for the relator to work
|
||||
sql.OrderBy<MemberTypeReadOnlyDto>(x => x.UniqueId, SqlSyntax);
|
||||
|
||||
var dtos =
|
||||
Database.Fetch<MemberTypeReadOnlyDto, PropertyTypeReadOnlyDto, PropertyTypeGroupReadOnlyDto, MemberTypeReadOnlyDto>(
|
||||
@@ -62,7 +64,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var subquery = translator.Translate();
|
||||
var sql = GetBaseQuery(false)
|
||||
.Append(new Sql("WHERE umbracoNode.id IN (" + subquery.SQL + ")", subquery.Arguments))
|
||||
.OrderBy<NodeDto>(x => x.SortOrder, SqlSyntax);
|
||||
//must be sorted this way for the relator to work
|
||||
.OrderBy<MemberTypeReadOnlyDto>(x => x.UniqueId, SqlSyntax);
|
||||
|
||||
var dtos =
|
||||
Database.Fetch<MemberTypeReadOnlyDto, PropertyTypeReadOnlyDto, PropertyTypeGroupReadOnlyDto, MemberTypeReadOnlyDto>(
|
||||
|
||||
@@ -40,7 +40,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
|
||||
var factory = new PublicAccessEntryFactory();
|
||||
|
||||
//MUST be ordered by this GUID ID for the AccessRulesRelator to work
|
||||
sql.OrderBy<AccessDto>(dto => dto.Id, SqlSyntax);
|
||||
|
||||
var dtos = Database.Fetch<AccessDto, AccessRuleDto, AccessDto>(new AccessRulesRelator().Map, sql);
|
||||
return dtos.Select(factory.BuildEntity);
|
||||
}
|
||||
@@ -52,7 +55,10 @@ 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
|
||||
sql.OrderBy<AccessDto>(dto => dto.Id, SqlSyntax);
|
||||
|
||||
var dtos = Database.Fetch<AccessDto, AccessRuleDto, AccessDto>(new AccessRulesRelator().Map, sql);
|
||||
return dtos.Select(factory.BuildEntity);
|
||||
}
|
||||
@@ -63,9 +69,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
sql.Select("*")
|
||||
.From<AccessDto>(SqlSyntax)
|
||||
.LeftJoin<AccessRuleDto>(SqlSyntax)
|
||||
.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);
|
||||
.On<AccessDto, AccessRuleDto>(SqlSyntax, left => left.Id, right => right.AccessId);
|
||||
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
var sql = GetBaseQuery(false);
|
||||
sql.Where(GetBaseWhereClause(), new { Id = id });
|
||||
//must be sorted this way for the relator to work
|
||||
sql.OrderBy<UserDto>(x => x.Id, SqlSyntax);
|
||||
|
||||
var dto = Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql).FirstOrDefault();
|
||||
|
||||
@@ -60,7 +62,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
sql.Where("umbracoUser.id in (@ids)", new {ids = ids});
|
||||
}
|
||||
|
||||
|
||||
//must be sorted this way for the relator to work
|
||||
sql.OrderBy<UserDto>(x => x.Id, SqlSyntax);
|
||||
|
||||
return ConvertFromDtos(Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql))
|
||||
.ToArray(); // important so we don't iterate twice, if we don't do this we can end up with null values in cache if we were caching.
|
||||
}
|
||||
@@ -71,6 +76,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var translator = new SqlTranslator<IUser>(sqlClause, query);
|
||||
var sql = translator.Translate();
|
||||
|
||||
//must be sorted this way for the relator to work
|
||||
sql.OrderBy<UserDto>(x => x.Id, SqlSyntax);
|
||||
|
||||
var dtos = Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql)
|
||||
.DistinctBy(x => x.Id);
|
||||
|
||||
@@ -96,13 +104,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return sql;
|
||||
}
|
||||
|
||||
private static Sql GetBaseQuery(string columns)
|
||||
private Sql GetBaseQuery(string columns)
|
||||
{
|
||||
var sql = new Sql();
|
||||
sql.Select(columns)
|
||||
.From<UserDto>()
|
||||
.LeftJoin<User2AppDto>()
|
||||
.On<UserDto, User2AppDto>(left => left.Id, right => right.UserId);
|
||||
.From<UserDto>()
|
||||
.LeftJoin<User2AppDto>()
|
||||
.On<UserDto, User2AppDto>(left => left.Id, right => right.UserId);
|
||||
return sql;
|
||||
}
|
||||
|
||||
@@ -300,6 +308,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var innerSql = GetBaseQuery("umbracoUser.id");
|
||||
innerSql.Where("umbracoUser2app.app = " + SqlSyntax.GetQuotedValue(sectionAlias));
|
||||
sql.Where(string.Format("umbracoUser.id IN ({0})", innerSql.SQL));
|
||||
//must be sorted this way for the relator to work
|
||||
sql.OrderBy<UserDto>(x => x.Id, SqlSyntax);
|
||||
|
||||
return ConvertFromDtos(Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models;
|
||||
@@ -88,13 +89,26 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
/// </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;
|
||||
// GetPreValuesCollectionByDataTypeId is cached at repository level;
|
||||
// still, the collection is deep-cloned so this is kinda expensive,
|
||||
// better to cache here + trigger refresh in DataTypeCacheRefresher
|
||||
|
||||
return enableRange != null && enableRange.Value.TryConvertTo<bool>().Result;
|
||||
return Storages.GetOrAdd(dataTypeId, id =>
|
||||
{
|
||||
var preValue = _dataTypeService.GetPreValuesCollectionByDataTypeId(id)
|
||||
.PreValuesAsDictionary
|
||||
.FirstOrDefault(x => string.Equals(x.Key, "enableRange", StringComparison.InvariantCultureIgnoreCase))
|
||||
.Value;
|
||||
|
||||
return preValue != null && preValue.Value.TryConvertTo<bool>().Result;
|
||||
});
|
||||
}
|
||||
|
||||
private static readonly ConcurrentDictionary<int, bool> Storages = new ConcurrentDictionary<int, bool>();
|
||||
|
||||
internal static void ClearCaches()
|
||||
{
|
||||
Storages.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
@@ -74,18 +77,26 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
/// </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;
|
||||
// GetPreValuesCollectionByDataTypeId is cached at repository level;
|
||||
// still, the collection is deep-cloned so this is kinda expensive,
|
||||
// better to cache here + trigger refresh in DataTypeCacheRefresher
|
||||
|
||||
if (storageType != null && storageType.Value.InvariantEquals("Json"))
|
||||
return Storages.GetOrAdd(dataTypeId, id =>
|
||||
{
|
||||
return true;
|
||||
}
|
||||
var preValue = _dataTypeService.GetPreValuesCollectionByDataTypeId(id)
|
||||
.PreValuesAsDictionary
|
||||
.FirstOrDefault(x => string.Equals(x.Key, "storageType", StringComparison.InvariantCultureIgnoreCase))
|
||||
.Value;
|
||||
|
||||
return false;
|
||||
return preValue != null && preValue.Value.InvariantEquals("json");
|
||||
});
|
||||
}
|
||||
|
||||
private static readonly ConcurrentDictionary<int, bool> Storages = new ConcurrentDictionary<int, bool>();
|
||||
|
||||
internal static void ClearCaches()
|
||||
{
|
||||
Storages.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
var result = _runtimeCache.GetCacheItem<int?>(CacheKeys.IdToKeyCacheKey + key, () =>
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
switch (umbracoObjectType)
|
||||
{
|
||||
@@ -92,7 +92,6 @@ namespace Umbraco.Core.Services
|
||||
case UmbracoObjectTypes.Member:
|
||||
case UmbracoObjectTypes.DataType:
|
||||
case UmbracoObjectTypes.DocumentTypeContainer:
|
||||
uow.Commit();
|
||||
return uow.Database.ExecuteScalar<int?>(new Sql().Select("id").From<NodeDto>().Where<NodeDto>(dto => dto.UniqueId == key));
|
||||
case UmbracoObjectTypes.RecycleBin:
|
||||
case UmbracoObjectTypes.Stylesheet:
|
||||
@@ -119,7 +118,7 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
var result = _runtimeCache.GetCacheItem<Guid?>(CacheKeys.KeyToIdCacheKey + id, () =>
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
switch (umbracoObjectType)
|
||||
{
|
||||
@@ -131,7 +130,6 @@ namespace Umbraco.Core.Services
|
||||
case UmbracoObjectTypes.DocumentType:
|
||||
case UmbracoObjectTypes.Member:
|
||||
case UmbracoObjectTypes.DataType:
|
||||
uow.Commit();
|
||||
return uow.Database.ExecuteScalar<Guid?>(new Sql().Select("uniqueID").From<NodeDto>().Where<NodeDto>(dto => dto.NodeId == id));
|
||||
case UmbracoObjectTypes.RecycleBin:
|
||||
case UmbracoObjectTypes.Stylesheet:
|
||||
@@ -185,11 +183,10 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
if (loadBaseType)
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var ret = repository.Get(id);
|
||||
uow.Commit();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -207,11 +204,10 @@ namespace Umbraco.Core.Services
|
||||
if (loadBaseType)
|
||||
{
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var ret = repository.GetByKey(key, objectTypeId);
|
||||
uow.Commit();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -241,11 +237,10 @@ namespace Umbraco.Core.Services
|
||||
if (loadBaseType)
|
||||
{
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var ret = repository.Get(id, objectTypeId);
|
||||
uow.Commit();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -276,11 +271,10 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
if (loadBaseType)
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var ret = repository.Get(id);
|
||||
uow.Commit();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -303,7 +297,7 @@ namespace Umbraco.Core.Services
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
public virtual IUmbracoEntity GetParent(int id)
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var entity = repository.Get(id);
|
||||
@@ -311,7 +305,6 @@ namespace Umbraco.Core.Services
|
||||
if (entity.ParentId == -1 || entity.ParentId == -20 || entity.ParentId == -21)
|
||||
return null;
|
||||
var ret = repository.Get(entity.ParentId);
|
||||
uow.Commit();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -324,7 +317,7 @@ namespace Umbraco.Core.Services
|
||||
/// <returns>An <see cref="IUmbracoEntity"/></returns>
|
||||
public virtual IUmbracoEntity GetParent(int id, UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var entity = repository.Get(id);
|
||||
@@ -334,7 +327,6 @@ namespace Umbraco.Core.Services
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
|
||||
var ret = repository.Get(entity.ParentId, objectTypeId);
|
||||
uow.Commit();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -346,13 +338,12 @@ namespace Umbraco.Core.Services
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
public virtual IEnumerable<IUmbracoEntity> GetChildren(int parentId)
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId);
|
||||
|
||||
var contents = repository.GetByQuery(query);
|
||||
uow.Commit();
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
@@ -366,13 +357,12 @@ namespace Umbraco.Core.Services
|
||||
public virtual IEnumerable<IUmbracoEntity> GetChildren(int parentId, UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId);
|
||||
|
||||
var contents = repository.GetByQuery(query, objectTypeId);
|
||||
uow.Commit();
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
@@ -393,7 +383,7 @@ namespace Umbraco.Core.Services
|
||||
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "")
|
||||
{
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId && x.Trashed == false);
|
||||
@@ -405,7 +395,6 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
|
||||
uow.Commit();
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
@@ -426,7 +415,7 @@ namespace Umbraco.Core.Services
|
||||
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "")
|
||||
{
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
|
||||
@@ -442,7 +431,6 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
|
||||
uow.Commit();
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
@@ -463,7 +451,7 @@ namespace Umbraco.Core.Services
|
||||
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "", bool includeTrashed = true)
|
||||
{
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
|
||||
@@ -481,7 +469,6 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
|
||||
uow.Commit();
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
@@ -493,7 +480,7 @@ namespace Umbraco.Core.Services
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
public virtual IEnumerable<IUmbracoEntity> GetDescendents(int id)
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var entity = repository.Get(id);
|
||||
@@ -501,7 +488,6 @@ namespace Umbraco.Core.Services
|
||||
var query = Query<IUmbracoEntity>.Builder.Where(x => x.Path.StartsWith(pathMatch) && x.Id != id);
|
||||
|
||||
var entities = repository.GetByQuery(query);
|
||||
uow.Commit();
|
||||
return entities;
|
||||
}
|
||||
}
|
||||
@@ -515,14 +501,13 @@ namespace Umbraco.Core.Services
|
||||
public virtual IEnumerable<IUmbracoEntity> GetDescendents(int id, UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var entity = repository.Get(id);
|
||||
var query = Query<IUmbracoEntity>.Builder.Where(x => x.Path.StartsWith(entity.Path) && x.Id != id);
|
||||
|
||||
var entities = repository.GetByQuery(query, objectTypeId);
|
||||
uow.Commit();
|
||||
return entities;
|
||||
}
|
||||
}
|
||||
@@ -541,11 +526,10 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var entities = repository.GetByQuery(_rootEntityQuery, objectTypeId);
|
||||
uow.Commit();
|
||||
return entities;
|
||||
}
|
||||
}
|
||||
@@ -585,11 +569,10 @@ namespace Umbraco.Core.Services
|
||||
});
|
||||
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var ret = repository.GetAll(objectTypeId, ids);
|
||||
uow.Commit();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -605,11 +588,10 @@ namespace Umbraco.Core.Services
|
||||
});
|
||||
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var ret = repository.GetAll(objectTypeId, keys);
|
||||
uow.Commit();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -631,11 +613,10 @@ namespace Umbraco.Core.Services
|
||||
("The passed in type is not supported");
|
||||
});
|
||||
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var ret = repository.GetAll(objectTypeId, ids);
|
||||
uow.Commit();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -721,22 +702,20 @@ namespace Umbraco.Core.Services
|
||||
|
||||
public bool Exists(Guid key)
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var exists = repository.Exists(key);
|
||||
uow.Commit();
|
||||
return exists;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Exists(int id)
|
||||
{
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var exists = repository.Exists(id);
|
||||
uow.Commit();
|
||||
return exists;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -868,7 +868,7 @@ namespace Umbraco.Core.Services
|
||||
if (partialView == null)
|
||||
{
|
||||
uow.Commit();
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (uow.Events.DispatchCancelable(DeletingPartialView, this, new DeleteEventArgs<IPartialView>(partialView)))
|
||||
|
||||
@@ -237,6 +237,14 @@ namespace Umbraco.Tests.Persistence.Repositories
|
||||
Assert.AreEqual("test-path-1.js", script.Path);
|
||||
Assert.AreEqual("/scripts/test-path-1.js", script.VirtualPath);
|
||||
|
||||
//ensure you can prefix the same path as the root path name
|
||||
script = new Script("scripts/path-2/test-path-2.js") { Content = "// script" };
|
||||
repository.AddOrUpdate(script);
|
||||
unitOfWork.Commit();
|
||||
Assert.IsTrue(_fileSystem.FileExists("scripts/path-2/test-path-2.js"));
|
||||
Assert.AreEqual("scripts\\path-2\\test-path-2.js", script.Path);
|
||||
Assert.AreEqual("/scripts/scripts/path-2/test-path-2.js", script.VirtualPath);
|
||||
|
||||
script = new Script("path-2/test-path-2.js") { Content = "// script" };
|
||||
repository.AddOrUpdate(script);
|
||||
unitOfWork.Commit();
|
||||
|
||||
@@ -191,27 +191,34 @@ tinymce.PluginManager.add('umbracolink', function(editor) {
|
||||
callback: function (data) {
|
||||
if (data) {
|
||||
var href = data.url;
|
||||
|
||||
// We want to use the Udi. If it is set, we use it, else fallback to id, and finally to null
|
||||
var hasUdi = data.udi ? true : false;
|
||||
var id = hasUdi ? data.udi : (data.id ? data.id : null);
|
||||
|
||||
//Create a json obj used to create the attributes for the tag
|
||||
function createElemAttributes() {
|
||||
var a = {
|
||||
href: href,
|
||||
title: data.name,
|
||||
target: data.target ? data.target : null,
|
||||
rel: data.rel ? data.rel : null
|
||||
};
|
||||
if (hasUdi) {
|
||||
a["data-udi"] = data.udi;
|
||||
}
|
||||
else if (data.id) {
|
||||
a["data-id"] = data.id;
|
||||
}
|
||||
}
|
||||
|
||||
function insertLink() {
|
||||
if (anchorElm) {
|
||||
dom.setAttribs(anchorElm, {
|
||||
href: href,
|
||||
title: data.name,
|
||||
target: data.target ? data.target : null,
|
||||
rel: data.rel ? data.rel : null,
|
||||
'data-id': data.id ? data.id : null
|
||||
});
|
||||
dom.setAttribs(anchorElm, createElemAttributes());
|
||||
|
||||
selection.select(anchorElm);
|
||||
editor.execCommand('mceEndTyping');
|
||||
} else {
|
||||
editor.execCommand('mceInsertLink', false, {
|
||||
href: href,
|
||||
title: data.name,
|
||||
target: data.target ? data.target : null,
|
||||
rel: data.rel ? data.rel : null,
|
||||
'data-id': data.id ? data.id : null
|
||||
});
|
||||
editor.execCommand('mceInsertLink', false, createElemAttributes());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,15 +228,11 @@ tinymce.PluginManager.add('umbracolink', function(editor) {
|
||||
}
|
||||
|
||||
//if we have an id, it must be a locallink:id, aslong as the isMedia flag is not set
|
||||
if(data.id && (angular.isUndefined(data.isMedia) || !data.isMedia)){
|
||||
if (target.udi) {
|
||||
href = "/{localLink:" + target.udi + "}";
|
||||
}
|
||||
else {
|
||||
//This shouldn't happen! but just in case we'll leave this here
|
||||
href = "/{localLink:" + target.id + "}";
|
||||
}
|
||||
insertLink();
|
||||
if (id && (angular.isUndefined(data.isMedia) || !data.isMedia)){
|
||||
|
||||
href = "/{localLink:" + id + "}";
|
||||
|
||||
insertLink();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -108,8 +108,10 @@ angular.module("umbraco.directives")
|
||||
$image.load(function(){
|
||||
$timeout(function(){
|
||||
setDimensions();
|
||||
scope.loaded = true;
|
||||
scope.onImageLoaded();
|
||||
scope.loaded = true;
|
||||
if (scope.onImageLoaded) {
|
||||
scope.onImageLoaded();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+2
-1
@@ -87,7 +87,8 @@ Use this directive to generate a list of folders presented as a flexbox grid.
|
||||
|
||||
scope.clickFolder = function(folder, $event, $index) {
|
||||
if(scope.onClick) {
|
||||
scope.onClick(folder, $event, $index);
|
||||
scope.onClick(folder, $event, $index);
|
||||
$event.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -247,6 +247,7 @@ Use this directive to generate a thumbnail grid of media items.
|
||||
scope.clickItem = function(item, $event, $index) {
|
||||
if (scope.onClick) {
|
||||
scope.onClick(item, $event, $index);
|
||||
$event.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+10
-8
@@ -9,7 +9,7 @@ function valServerField(serverValidationManager) {
|
||||
return {
|
||||
require: 'ngModel',
|
||||
restrict: "A",
|
||||
link: function (scope, element, attr, ctrl) {
|
||||
link: function (scope, element, attr, ngModel) {
|
||||
|
||||
var fieldName = null;
|
||||
var eventBindings = [];
|
||||
@@ -23,23 +23,25 @@ function valServerField(serverValidationManager) {
|
||||
// resubmitted. So once a field is changed that has a server error assigned to it
|
||||
// we need to re-validate it for the server side validator so the user can resubmit
|
||||
// the form. Of course normal client-side validators will continue to execute.
|
||||
eventBindings.push(scope.$watch('ngModel', function(newValue){
|
||||
if (ctrl.$invalid) {
|
||||
ctrl.$setValidity('valServerField', true);
|
||||
eventBindings.push(scope.$watch(function() {
|
||||
return ngModel.$modelValue;
|
||||
}, function(newValue){
|
||||
if (ngModel.$invalid) {
|
||||
ngModel.$setValidity('valServerField', true);
|
||||
}
|
||||
}));
|
||||
|
||||
//subscribe to the server validation changes
|
||||
serverValidationManager.subscribe(null, fieldName, function (isValid, fieldErrors, allErrors) {
|
||||
if (!isValid) {
|
||||
ctrl.$setValidity('valServerField', false);
|
||||
ngModel.$setValidity('valServerField', false);
|
||||
//assign an error msg property to the current validator
|
||||
ctrl.errorMsg = fieldErrors[0].errorMsg;
|
||||
ngModel.errorMsg = fieldErrors[0].errorMsg;
|
||||
}
|
||||
else {
|
||||
ctrl.$setValidity('valServerField', true);
|
||||
ngModel.$setValidity('valServerField', true);
|
||||
//reset the error message
|
||||
ctrl.errorMsg = "";
|
||||
ngModel.errorMsg = "";
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -199,11 +199,17 @@ function codefileResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
*/
|
||||
|
||||
getScaffold: function (type, id, snippetName) {
|
||||
|
||||
var queryString = "?type=" + type + "&id=" + id;
|
||||
if (snippetName) {
|
||||
queryString += "&snippetName=" + snippetName;
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"codeFileApiBaseUrl",
|
||||
"GetScaffold?type=" + type + "&id=" + id + "&snippetName=" + snippetName)),
|
||||
"codeFileApiBaseUrl",
|
||||
"GetScaffold" + queryString)),
|
||||
"Failed to get scaffold for" + type);
|
||||
},
|
||||
|
||||
|
||||
@@ -522,6 +522,26 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.contentEditingHelper#redirectToRenamedContent
|
||||
* @methodOf umbraco.services.contentEditingHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* For some editors like scripts or entites that have names as ids, these names can change and we need to redirect
|
||||
* to their new paths, this is helper method to do that.
|
||||
*/
|
||||
redirectToRenamedContent: function (id) {
|
||||
//clear the query strings
|
||||
$location.search("");
|
||||
//change to new path
|
||||
$location.path("/" + $routeParams.section + "/" + $routeParams.tree + "/" + $routeParams.method + "/" + id);
|
||||
//don't add a browser history for this
|
||||
$location.replace();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -21,7 +21,9 @@ function mediaTypeHelper(mediaTypeResource, $q) {
|
||||
},
|
||||
|
||||
getAllowedImagetypes: function (mediaId){
|
||||
|
||||
|
||||
//TODO: This is horribly inneficient - why make one request per type!?
|
||||
|
||||
// Get All allowedTypes
|
||||
return mediaTypeResource.getAllowedTypes(mediaId)
|
||||
.then(function(types){
|
||||
|
||||
@@ -95,11 +95,20 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
||||
|
||||
if(selectedElm.nodeName === 'IMG'){
|
||||
var img = $(selectedElm);
|
||||
|
||||
var hasUdi = img.attr("data-udi") ? true : false;
|
||||
|
||||
currentTarget = {
|
||||
altText: img.attr("alt"),
|
||||
url: img.attr("src"),
|
||||
id: img.attr("rel")
|
||||
url: img.attr("src")
|
||||
};
|
||||
|
||||
if (hasUdi) {
|
||||
currentTarget["udi"] = img.attr("data-udi");
|
||||
}
|
||||
else {
|
||||
currentTarget["id"] = img.attr("rel");
|
||||
}
|
||||
}
|
||||
|
||||
userService.getCurrentUser().then(function(userData) {
|
||||
@@ -115,13 +124,23 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
||||
insertMediaInEditor: function(editor, img) {
|
||||
if(img) {
|
||||
|
||||
var hasUdi = img.udi ? true : false;
|
||||
|
||||
var data = {
|
||||
alt: img.altText || "",
|
||||
src: (img.url) ? img.url : "nothing.jpg",
|
||||
rel: img.id,
|
||||
'data-id': img.id,
|
||||
src: (img.url) ? img.url : "nothing.jpg",
|
||||
id: '__mcenew'
|
||||
};
|
||||
};
|
||||
|
||||
if (hasUdi) {
|
||||
data["data-udi"] = img.udi;
|
||||
}
|
||||
else {
|
||||
//Considering these fixed because UDI will now be used and thus
|
||||
// we have no need for rel http://issues.umbraco.org/issue/U4-6228, http://issues.umbraco.org/issue/U4-6595
|
||||
data["rel"] = img.id;
|
||||
data["data-id"] = img.id;
|
||||
}
|
||||
|
||||
editor.insertContent(editor.dom.createHTML('img', data));
|
||||
|
||||
@@ -725,27 +744,36 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
||||
insertLinkInEditor: function(editor, target, anchorElm) {
|
||||
|
||||
var href = target.url;
|
||||
// We want to use the Udi. If it is set, we use it, else fallback to id, and finally to null
|
||||
var hasUdi = target.udi ? true : false;
|
||||
var id = hasUdi ? target.udi : (target.id ? target.id : null);
|
||||
|
||||
//Create a json obj used to create the attributes for the tag
|
||||
function createElemAttributes() {
|
||||
var a = {
|
||||
href: href,
|
||||
title: target.name,
|
||||
target: target.target ? target.target : null,
|
||||
rel: target.rel ? target.rel : null
|
||||
};
|
||||
if (hasUdi) {
|
||||
a["data-udi"] = target.udi;
|
||||
}
|
||||
else if (target.id) {
|
||||
a["data-id"] = target.id;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
function insertLink() {
|
||||
if (anchorElm) {
|
||||
editor.dom.setAttribs(anchorElm, {
|
||||
href: href,
|
||||
title: target.name,
|
||||
target: target.target ? target.target : null,
|
||||
rel: target.rel ? target.rel : null,
|
||||
'data-id': target.id ? target.id : null
|
||||
});
|
||||
editor.dom.setAttribs(anchorElm, createElemAttributes());
|
||||
|
||||
editor.selection.select(anchorElm);
|
||||
editor.execCommand('mceEndTyping');
|
||||
} else {
|
||||
editor.execCommand('mceInsertLink', false, {
|
||||
href: href,
|
||||
title: target.name,
|
||||
target: target.target ? target.target : null,
|
||||
rel: target.rel ? target.rel : null,
|
||||
'data-id': target.id ? target.id : null
|
||||
});
|
||||
}
|
||||
else {
|
||||
editor.execCommand('mceInsertLink', false, createElemAttributes());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -755,14 +783,9 @@ function tinyMceService(dialogService, $log, imageHelper, $http, $timeout, macro
|
||||
}
|
||||
|
||||
//if we have an id, it must be a locallink:id, aslong as the isMedia flag is not set
|
||||
if(target.id && (angular.isUndefined(target.isMedia) || !target.isMedia)){
|
||||
if (target.udi) {
|
||||
href = "/{localLink:" + target.udi + "}";
|
||||
}
|
||||
else {
|
||||
//This shouldn't happen! but just in case we'll leave this here
|
||||
href = "/{localLink:" + target.id + "}";
|
||||
}
|
||||
if(id && (angular.isUndefined(target.isMedia) || !target.isMedia)){
|
||||
|
||||
href = "/{localLink:" + id + "}";
|
||||
|
||||
insertLink();
|
||||
return;
|
||||
|
||||
@@ -22,17 +22,19 @@ angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController",
|
||||
$scope.target = dialogOptions.currentTarget;
|
||||
|
||||
//if we have a node ID, we fetch the current node to build the form data
|
||||
if ($scope.target.id) {
|
||||
if ($scope.target.id || $scope.target.udi) {
|
||||
|
||||
var id = $scope.target.udi ? $scope.target.udi : $scope.target.id;
|
||||
|
||||
if (!$scope.target.path) {
|
||||
entityResource.getPath($scope.target.id, "Document").then(function (path) {
|
||||
entityResource.getPath(id, "Document").then(function (path) {
|
||||
$scope.target.path = path;
|
||||
//now sync the tree to this path
|
||||
$scope.dialogTreeEventHandler.syncTree({ path: $scope.target.path, tree: "content" });
|
||||
});
|
||||
}
|
||||
|
||||
contentResource.getNiceUrl($scope.target.id).then(function (url) {
|
||||
contentResource.getNiceUrl(id).then(function (url) {
|
||||
$scope.target.url = url;
|
||||
});
|
||||
}
|
||||
@@ -59,7 +61,8 @@ angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController",
|
||||
|
||||
$scope.currentNode = args.node;
|
||||
$scope.currentNode.selected = true;
|
||||
$scope.target.id = args.node.id;
|
||||
$scope.target.id = args.node.id;
|
||||
$scope.target.udi = args.node.udi;
|
||||
$scope.target.name = args.node.name;
|
||||
|
||||
if (args.node.id < 0) {
|
||||
|
||||
+49
-23
@@ -119,7 +119,7 @@ angular.module("umbraco")
|
||||
localStorageService.set("umbLastOpenedMediaNodeId", folder.id);
|
||||
};
|
||||
|
||||
$scope.clickHandler = function(image, event, index) {
|
||||
$scope.clickHandler = function (image, event, index) {
|
||||
if (image.isFolder) {
|
||||
if ($scope.disableFolderSelect) {
|
||||
$scope.gotoFolder(image);
|
||||
@@ -179,27 +179,49 @@ angular.module("umbraco")
|
||||
$scope.activeDrag = false;
|
||||
};
|
||||
|
||||
function ensureWithinStartNode(node) {
|
||||
// make sure that last opened node is on the same path as start node
|
||||
var nodePath = node.path.split(",");
|
||||
|
||||
if (nodePath.indexOf($scope.startNodeId.toString()) !== -1) {
|
||||
$scope.gotoFolder({ id: $scope.lastOpenedNode, name: "Media", icon: "icon-folder" });
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function gotoStartNode(err) {
|
||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||
}
|
||||
|
||||
//default root item
|
||||
if (!$scope.target) {
|
||||
if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) {
|
||||
entityResource.getById($scope.lastOpenedNode, "media")
|
||||
.then(function(node) {
|
||||
// make sure that las opened node is on the same path as start node
|
||||
var nodePath = node.path.split(",");
|
||||
|
||||
if (nodePath.indexOf($scope.startNodeId.toString()) !== -1) {
|
||||
$scope
|
||||
.gotoFolder({ id: $scope.lastOpenedNode, name: "Media", icon: "icon-folder" });
|
||||
} else {
|
||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||
}
|
||||
},
|
||||
function(err) {
|
||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||
});
|
||||
} else {
|
||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||
.then(ensureWithinStartNode, gotoStartNode);
|
||||
}
|
||||
else {
|
||||
gotoStartNode();
|
||||
}
|
||||
}
|
||||
else {
|
||||
//if a target is specified, go look it up - generally this target will just contain ids not the actual full
|
||||
//media object so we need to look it up
|
||||
var id = $scope.target.udi ? $scope.target.udi : $scope.target.id
|
||||
var altText = $scope.target.altText;
|
||||
mediaResource.getById(id)
|
||||
.then(function (node) {
|
||||
$scope.target = node;
|
||||
if (ensureWithinStartNode(node)) {
|
||||
selectImage(node);
|
||||
$scope.target.url = mediaHelper.resolveFile(node);
|
||||
$scope.target.altText = altText;
|
||||
$scope.openDetailsDialog();
|
||||
}
|
||||
}, gotoStartNode);
|
||||
}
|
||||
|
||||
$scope.openDetailsDialog = function() {
|
||||
@@ -308,15 +330,19 @@ angular.module("umbraco")
|
||||
var folderImage = $scope.images[folderImageIndex];
|
||||
var imageIsSelected = false;
|
||||
|
||||
for (var selectedImageIndex = 0;
|
||||
selectedImageIndex < $scope.model.selectedImages.length;
|
||||
selectedImageIndex++) {
|
||||
var selectedImage = $scope.model.selectedImages[selectedImageIndex];
|
||||
if ($scope.model && angular.isArray($scope.model.selectedImages)) {
|
||||
for (var selectedImageIndex = 0;
|
||||
selectedImageIndex < $scope.model.selectedImages.length;
|
||||
selectedImageIndex++) {
|
||||
var selectedImage = $scope.model.selectedImages[selectedImageIndex];
|
||||
|
||||
if (folderImage.key === selectedImage.key) {
|
||||
imageIsSelected = true;
|
||||
if (folderImage.key === selectedImage.key) {
|
||||
imageIsSelected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (imageIsSelected) {
|
||||
folderImage.selected = true;
|
||||
}
|
||||
|
||||
+8
-3
@@ -122,9 +122,14 @@
|
||||
query.filters.push({});
|
||||
}
|
||||
|
||||
function trashFilter(query) {
|
||||
query.filters.splice(query, 1);
|
||||
|
||||
function trashFilter(query, filter) {
|
||||
for (var i = 0; i < query.filters.length; i++)
|
||||
{
|
||||
if (query.filters[i] == filter)
|
||||
{
|
||||
query.filters.splice(i, 1);
|
||||
}
|
||||
}
|
||||
//if we remove the last one, add a new one to generate ui for it.
|
||||
if (query.filters.length == 0) {
|
||||
query.filters.push({});
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
<i class="icon-add"></i>
|
||||
</a>
|
||||
|
||||
<a href ng-click="vm.trashFilter(vm.query)">
|
||||
<a href ng-click="vm.trashFilter(vm.query, filter)">
|
||||
<i class="icon-trash"></i>
|
||||
</a>
|
||||
|
||||
|
||||
@@ -12,10 +12,8 @@ function PartialViewMacrosDeleteController($scope, codefileResource, treeService
|
||||
|
||||
//mark it for deletion (used in the UI)
|
||||
$scope.currentNode.loading = true;
|
||||
|
||||
var virtualPath = $scope.currentNode.parentId + $scope.currentNode.name;
|
||||
|
||||
codefileResource.deleteByPath('partialViewMacros', virtualPath)
|
||||
|
||||
codefileResource.deleteByPath('partialViewMacros', $scope.currentNode.id)
|
||||
.then(function() {
|
||||
$scope.currentNode.loading = false;
|
||||
//get the root node before we remove it
|
||||
|
||||
@@ -48,20 +48,25 @@
|
||||
});
|
||||
});
|
||||
|
||||
vm.page.saveButtonState = "success";
|
||||
vm.partialViewMacro = saved;
|
||||
//check if the name changed, if so we need to redirect
|
||||
if (vm.partialViewMacro.id !== saved.id) {
|
||||
contentEditingHelper.redirectToRenamedContent(saved.id);
|
||||
}
|
||||
else {
|
||||
vm.page.saveButtonState = "success";
|
||||
vm.partialViewMacro = saved;
|
||||
|
||||
//sync state
|
||||
editorState.set(vm.partialViewMacro);
|
||||
//sync state
|
||||
editorState.set(vm.partialViewMacro);
|
||||
|
||||
// normal tree sync
|
||||
navigationService.syncTree({ tree: "partialViewMacros", path: vm.partialViewMacro.path, forceReload: true }).then(function (syncArgs) {
|
||||
vm.page.menu.currentNode = syncArgs.node;
|
||||
});
|
||||
|
||||
// clear $dirty state on form
|
||||
setFormState("pristine");
|
||||
// normal tree sync
|
||||
navigationService.syncTree({ tree: "partialViewMacros", path: vm.partialViewMacro.path, forceReload: true }).then(function (syncArgs) {
|
||||
vm.page.menu.currentNode = syncArgs.node;
|
||||
});
|
||||
|
||||
// clear $dirty state on form
|
||||
setFormState("pristine");
|
||||
}
|
||||
}, function (err) {
|
||||
|
||||
vm.page.saveButtonState = "error";
|
||||
@@ -237,26 +242,29 @@
|
||||
}
|
||||
|
||||
codefileResource.getScaffold("partialViewMacros", $routeParams.id, snippet).then(function (partialViewMacro) {
|
||||
ready(partialViewMacro);
|
||||
ready(partialViewMacro, false);
|
||||
});
|
||||
|
||||
} else {
|
||||
codefileResource.getByPath('partialViewMacros', $routeParams.id).then(function (partialViewMacro) {
|
||||
ready(partialViewMacro);
|
||||
ready(partialViewMacro, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function ready(partialViewMacro) {
|
||||
function ready(partialViewMacro, syncTree) {
|
||||
|
||||
vm.page.loading = false;
|
||||
vm.partialViewMacro = partialViewMacro;
|
||||
|
||||
//sync state
|
||||
editorState.set(vm.partialViewMacro);
|
||||
navigationService.syncTree({ tree: "partialViewMacros", path: vm.partialViewMacro.virtualPath, forceReload: true }).then(function (syncArgs) {
|
||||
vm.page.menu.currentNode = syncArgs.node;
|
||||
});
|
||||
|
||||
if (syncTree) {
|
||||
navigationService.syncTree({ tree: "partialViewMacros", path: vm.partialViewMacro.path, forceReload: true }).then(function (syncArgs) {
|
||||
vm.page.menu.currentNode = syncArgs.node;
|
||||
});
|
||||
}
|
||||
|
||||
// ace configuration
|
||||
vm.aceOption = {
|
||||
|
||||
@@ -12,10 +12,8 @@ function PartialViewsDeleteController($scope, codefileResource, treeService, nav
|
||||
|
||||
//mark it for deletion (used in the UI)
|
||||
$scope.currentNode.loading = true;
|
||||
|
||||
var virtualPath = $scope.currentNode.parentId + $scope.currentNode.name;
|
||||
|
||||
codefileResource.deleteByPath('partialViews', virtualPath)
|
||||
|
||||
codefileResource.deleteByPath('partialViews', $scope.currentNode.id)
|
||||
.then(function() {
|
||||
$scope.currentNode.loading = false;
|
||||
//get the root node before we remove it
|
||||
|
||||
@@ -58,20 +58,25 @@
|
||||
});
|
||||
});
|
||||
|
||||
vm.page.saveButtonState = "success";
|
||||
vm.partialView = saved;
|
||||
//check if the name changed, if so we need to redirect
|
||||
if (vm.partialView.id !== saved.id) {
|
||||
contentEditingHelper.redirectToRenamedContent(saved.id);
|
||||
}
|
||||
else {
|
||||
vm.page.saveButtonState = "success";
|
||||
vm.partialView = saved;
|
||||
|
||||
//sync state
|
||||
editorState.set(vm.partialView);
|
||||
//sync state
|
||||
editorState.set(vm.partialView);
|
||||
|
||||
// normal tree sync
|
||||
navigationService.syncTree({ tree: "partialViews", path: vm.partialView.path, forceReload: true }).then(function (syncArgs) {
|
||||
vm.page.menu.currentNode = syncArgs.node;
|
||||
});
|
||||
|
||||
// clear $dirty state on form
|
||||
setFormState("pristine");
|
||||
// normal tree sync
|
||||
navigationService.syncTree({ tree: "partialViews", path: vm.partialView.path, forceReload: true }).then(function (syncArgs) {
|
||||
vm.page.menu.currentNode = syncArgs.node;
|
||||
});
|
||||
|
||||
// clear $dirty state on form
|
||||
setFormState("pristine");
|
||||
}
|
||||
}, function (err) {
|
||||
|
||||
vm.page.saveButtonState = "error";
|
||||
@@ -247,18 +252,18 @@
|
||||
}
|
||||
|
||||
codefileResource.getScaffold("partialViews", $routeParams.id, snippet).then(function (partialView) {
|
||||
ready(partialView);
|
||||
ready(partialView, false);
|
||||
});
|
||||
|
||||
} else {
|
||||
codefileResource.getByPath('partialViews', $routeParams.id).then(function (partialView) {
|
||||
ready(partialView);
|
||||
ready(partialView, true);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function ready(partialView) {
|
||||
function ready(partialView, syncTree) {
|
||||
|
||||
vm.page.loading = false;
|
||||
vm.partialView = partialView;
|
||||
@@ -266,9 +271,11 @@
|
||||
//sync state
|
||||
editorState.set(vm.partialView);
|
||||
|
||||
navigationService.syncTree({ tree: "partialViews", path: vm.partialView.path, forceReload: true }).then(function (syncArgs) {
|
||||
vm.page.menu.currentNode = syncArgs.node;
|
||||
});
|
||||
if (syncTree) {
|
||||
navigationService.syncTree({ tree: "partialViews", path: vm.partialView.path, forceReload: true }).then(function (syncArgs) {
|
||||
vm.page.menu.currentNode = syncArgs.node;
|
||||
});
|
||||
}
|
||||
|
||||
// ace configuration
|
||||
vm.aceOption = {
|
||||
|
||||
@@ -12,10 +12,8 @@ function ScriptsDeleteController($scope, codefileResource, treeService, navigati
|
||||
|
||||
//mark it for deletion (used in the UI)
|
||||
$scope.currentNode.loading = true;
|
||||
|
||||
var virtualPath = $scope.currentNode.parentId + $scope.currentNode.name;
|
||||
|
||||
codefileResource.deleteByPath('scripts', virtualPath)
|
||||
|
||||
codefileResource.deleteByPath('scripts', $scope.currentNode.id)
|
||||
.then(function() {
|
||||
$scope.currentNode.loading = false;
|
||||
//get the root node before we remove it
|
||||
|
||||
@@ -55,16 +55,22 @@
|
||||
notificationsService.success(header, message);
|
||||
});
|
||||
|
||||
vm.page.saveButtonState = "success";
|
||||
vm.script = saved;
|
||||
//check if the name changed, if so we need to redirect
|
||||
if (vm.script.id !== saved.id) {
|
||||
contentEditingHelper.redirectToRenamedContent(saved.id);
|
||||
}
|
||||
else {
|
||||
vm.page.saveButtonState = "success";
|
||||
vm.script = saved;
|
||||
|
||||
//sync state
|
||||
editorState.set(vm.script);
|
||||
|
||||
// sync tree
|
||||
navigationService.syncTree({ tree: "scripts", path: vm.script.virtualPath, forceReload: true }).then(function (syncArgs) {
|
||||
vm.page.menu.currentNode = syncArgs.node;
|
||||
});
|
||||
//sync state
|
||||
editorState.set(vm.script);
|
||||
|
||||
// sync tree
|
||||
navigationService.syncTree({ tree: "scripts", path: vm.script.path, forceReload: true }).then(function (syncArgs) {
|
||||
vm.page.menu.currentNode = syncArgs.node;
|
||||
});
|
||||
}
|
||||
|
||||
}, function (err) {
|
||||
|
||||
@@ -90,17 +96,17 @@
|
||||
|
||||
if ($routeParams.create) {
|
||||
codefileResource.getScaffold("scripts", $routeParams.id).then(function (script) {
|
||||
ready(script);
|
||||
ready(script, false);
|
||||
});
|
||||
} else {
|
||||
codefileResource.getByPath('scripts', $routeParams.id).then(function (script) {
|
||||
ready(script);
|
||||
ready(script, true);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function ready(script) {
|
||||
function ready(script, syncTree) {
|
||||
|
||||
vm.page.loading = false;
|
||||
|
||||
@@ -109,9 +115,11 @@
|
||||
//sync state
|
||||
editorState.set(vm.script);
|
||||
|
||||
navigationService.syncTree({ tree: "scripts", path: vm.script.virtualPath, forceReload: true }).then(function (syncArgs) {
|
||||
vm.page.menu.currentNode = syncArgs.node;
|
||||
});
|
||||
if (syncTree) {
|
||||
navigationService.syncTree({ tree: "scripts", path: vm.script.path, forceReload: true }).then(function (syncArgs) {
|
||||
vm.page.menu.currentNode = syncArgs.node;
|
||||
});
|
||||
}
|
||||
|
||||
vm.aceOption = {
|
||||
mode: "javascript",
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
<command>
|
||||
<umbracoAlias>undo</umbracoAlias>
|
||||
<name>Undo</name>
|
||||
<name>Remove Format</name>
|
||||
<icon>images/editor/undo.gif</icon>
|
||||
<tinyMceCommand value="" userInterface="false" frontendCommand="undo">undo</tinyMceCommand>
|
||||
<priority>11</priority>
|
||||
@@ -233,7 +232,6 @@
|
||||
<plugin loadOnFrontend="true">code</plugin>
|
||||
<plugin loadOnFrontend="true">codemirror</plugin>
|
||||
<plugin loadOnFrontend="true">paste</plugin>
|
||||
<plugin loadOnFrontend="true">umbracolink</plugin>
|
||||
<plugin loadOnFrontend="true">anchor</plugin>
|
||||
<plugin loadOnFrontend="true">charmap</plugin>
|
||||
<plugin loadOnFrontend="true">table</plugin>
|
||||
@@ -241,7 +239,7 @@
|
||||
<plugin loadOnFrontend="true">hr</plugin>
|
||||
</plugins>
|
||||
<validElements>
|
||||
<![CDATA[+a[id|style|rel|data-id|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|
|
||||
<![CDATA[+a[id|style|rel|data-id|data-udi|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|
|
||||
ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],
|
||||
-strike[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|reversed|start|style|type],-ul[class|style],-li[class|style],br[class],
|
||||
img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align|umbracoorgwidth|umbracoorgheight|onresize|onresizestart|onresizeend|rel|data-id],
|
||||
|
||||
@@ -239,7 +239,7 @@
|
||||
<plugin loadOnFrontend="true">hr</plugin>
|
||||
</plugins>
|
||||
<validElements>
|
||||
<![CDATA[+a[id|style|rel|data-id|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|
|
||||
<![CDATA[+a[id|style|rel|data-id|data-udi|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|
|
||||
ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],
|
||||
-strike[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|reversed|start|style|type],-ul[class|style],-li[class|style],br[class],
|
||||
img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align|umbracoorgwidth|umbracoorgheight|onresize|onresizestart|onresizeend|rel|data-id],
|
||||
|
||||
@@ -5,6 +5,8 @@ using Umbraco.Core.Cache;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.PropertyEditors.ValueConverters;
|
||||
using Umbraco.Web.PropertyEditors.ValueConverters;
|
||||
|
||||
|
||||
namespace Umbraco.Web.Cache
|
||||
@@ -111,6 +113,10 @@ namespace Umbraco.Web.Cache
|
||||
PublishedContentType.ClearDataType(payload.Id);
|
||||
});
|
||||
|
||||
TagsValueConverter.ClearCaches();
|
||||
MultipleMediaPickerPropertyConverter.ClearCaches();
|
||||
SliderValueConverter.ClearCaches();
|
||||
|
||||
base.Refresh(jsonPayload);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AutoMapper;
|
||||
using System;
|
||||
using AutoMapper;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -18,9 +19,11 @@ using Umbraco.Web.Trees;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
//TODO: Put some exception filters in our webapi to return 404 instead of 500 when we throw ArgumentNullException
|
||||
// ref: https://www.exceptionnotfound.net/the-asp-net-web-api-exception-handling-pipeline-a-guided-tour/
|
||||
[PluginController("UmbracoApi")]
|
||||
[PrefixlessBodyModelValidator]
|
||||
[UmbracoApplicationAuthorizeAttribute(Core.Constants.Applications.Settings)]
|
||||
[UmbracoApplicationAuthorize(Core.Constants.Applications.Settings)]
|
||||
public class CodeFileController : BackOfficeNotificationsController
|
||||
{
|
||||
|
||||
@@ -33,6 +36,9 @@ namespace Umbraco.Web.Editors
|
||||
[ValidationFilter]
|
||||
public HttpResponseMessage PostCreate(string type, CodeFileDisplay display)
|
||||
{
|
||||
if (display == null) throw new ArgumentNullException("display");
|
||||
if (string.IsNullOrWhiteSpace(type)) throw new ArgumentException("Value cannot be null or whitespace.", "type");
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case Core.Constants.Trees.PartialViews:
|
||||
@@ -67,12 +73,11 @@ namespace Umbraco.Web.Editors
|
||||
[HttpPost]
|
||||
public CodeFileDisplay PostCreateContainer(string type, string parentId, string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(type) || string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.BadRequest);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(type)) throw new ArgumentException("Value cannot be null or whitespace.", "type");
|
||||
if (string.IsNullOrWhiteSpace(parentId)) throw new ArgumentException("Value cannot be null or whitespace.", "parentId");
|
||||
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", "name");
|
||||
|
||||
// if the parentId is root (-1) then we just need an empty string as we are
|
||||
// if the parentId is root (-1) then we just need an empty string as we are
|
||||
// creating the path below and we don't wan't -1 in the path
|
||||
if (parentId == Core.Constants.System.Root.ToInvariantString())
|
||||
{
|
||||
@@ -120,10 +125,8 @@ namespace Umbraco.Web.Editors
|
||||
/// <returns>The file and its contents from the virtualPath</returns>
|
||||
public CodeFileDisplay GetByPath(string type, string virtualPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(type) || string.IsNullOrWhiteSpace(virtualPath))
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(type)) throw new ArgumentException("Value cannot be null or whitespace.", "type");
|
||||
if (string.IsNullOrWhiteSpace(virtualPath)) throw new ArgumentException("Value cannot be null or whitespace.", "virtualPath");
|
||||
|
||||
virtualPath = System.Web.HttpUtility.UrlDecode(virtualPath);
|
||||
|
||||
@@ -139,7 +142,7 @@ namespace Umbraco.Web.Editors
|
||||
display.Id = System.Web.HttpUtility.UrlEncode(view.Path);
|
||||
return display;
|
||||
}
|
||||
return null;
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
|
||||
case Core.Constants.Trees.PartialViewMacros:
|
||||
var viewMacro = Services.FileService.GetPartialViewMacro(virtualPath);
|
||||
@@ -151,7 +154,7 @@ namespace Umbraco.Web.Editors
|
||||
display.Id = System.Web.HttpUtility.UrlEncode(viewMacro.Path);
|
||||
return display;
|
||||
}
|
||||
return null;
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
|
||||
case Core.Constants.Trees.Scripts:
|
||||
var script = Services.FileService.GetScriptByName(virtualPath);
|
||||
@@ -163,7 +166,7 @@ namespace Umbraco.Web.Editors
|
||||
display.Id = System.Web.HttpUtility.UrlEncode(script.Path);
|
||||
return display;
|
||||
}
|
||||
return null;
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
@@ -176,10 +179,7 @@ namespace Umbraco.Web.Editors
|
||||
/// <returns>Returns a list of <see cref="SnippetDisplay"/> if a correct type is sent</returns>
|
||||
public IEnumerable<SnippetDisplay> GetSnippets(string type)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(type))
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.BadRequest);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(type)) throw new ArgumentException("Value cannot be null or whitespace.", "type");
|
||||
|
||||
IEnumerable<string> snippets;
|
||||
switch (type)
|
||||
@@ -209,15 +209,10 @@ namespace Umbraco.Web.Editors
|
||||
/// <param name="id"></param>
|
||||
/// <param name="snippetName"></param>
|
||||
/// <returns></returns>
|
||||
public CodeFileDisplay GetScaffold(string type, string id = null, string snippetName = null)
|
||||
public CodeFileDisplay GetScaffold(string type, string id, string snippetName = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(type))
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.BadRequest);
|
||||
}
|
||||
|
||||
if (id.IsNullOrWhiteSpace())
|
||||
id = string.Empty;
|
||||
if (string.IsNullOrWhiteSpace(type)) throw new ArgumentException("Value cannot be null or whitespace.", "type");
|
||||
if (string.IsNullOrWhiteSpace(id)) throw new ArgumentException("Value cannot be null or whitespace.", "id");
|
||||
|
||||
CodeFileDisplay codeFileDisplay;
|
||||
|
||||
@@ -246,15 +241,15 @@ namespace Umbraco.Web.Editors
|
||||
// Make sure that the root virtual path ends with '/'
|
||||
codeFileDisplay.VirtualPath = codeFileDisplay.VirtualPath.EnsureEndsWith("/");
|
||||
|
||||
if (id.IsNullOrWhiteSpace() == false && id != Core.Constants.System.Root.ToInvariantString())
|
||||
if (id != Core.Constants.System.Root.ToInvariantString())
|
||||
{
|
||||
codeFileDisplay.VirtualPath += id.TrimStart("/").EnsureEndsWith("/");
|
||||
//if it's not new then it will have a path, otherwise it won't
|
||||
codeFileDisplay.Path = Url.GetTreePathFromFilePath(id);
|
||||
}
|
||||
|
||||
codeFileDisplay.VirtualPath = codeFileDisplay.VirtualPath.TrimStart("~");
|
||||
codeFileDisplay.Path = Url.GetTreePathFromFilePath(id);
|
||||
codeFileDisplay.VirtualPath = codeFileDisplay.VirtualPath.TrimStart("~");
|
||||
codeFileDisplay.FileType = type;
|
||||
|
||||
return codeFileDisplay;
|
||||
}
|
||||
|
||||
@@ -268,52 +263,52 @@ namespace Umbraco.Web.Editors
|
||||
[HttpPost]
|
||||
public HttpResponseMessage Delete(string type, string virtualPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(type) == false && string.IsNullOrWhiteSpace(virtualPath) == false)
|
||||
if (string.IsNullOrWhiteSpace(type)) throw new ArgumentException("Value cannot be null or whitespace.", "type");
|
||||
if (string.IsNullOrWhiteSpace(virtualPath)) throw new ArgumentException("Value cannot be null or whitespace.", "virtualPath");
|
||||
|
||||
virtualPath = System.Web.HttpUtility.UrlDecode(virtualPath);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
virtualPath = System.Web.HttpUtility.UrlDecode(virtualPath);
|
||||
case Core.Constants.Trees.PartialViews:
|
||||
if (IsDirectory(virtualPath, SystemDirectories.PartialViews))
|
||||
{
|
||||
Services.FileService.DeletePartialViewFolder(virtualPath);
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
if (Services.FileService.DeletePartialView(virtualPath, Security.CurrentUser.Id))
|
||||
{
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No Partial View or folder found with the specified path");
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case Core.Constants.Trees.PartialViews:
|
||||
if (IsDirectory(virtualPath, SystemDirectories.PartialViews))
|
||||
{
|
||||
Services.FileService.DeletePartialViewFolder(virtualPath);
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
if (Services.FileService.DeletePartialView(virtualPath, Security.CurrentUser.Id))
|
||||
{
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No Partial View or folder found with the specified path");
|
||||
case Core.Constants.Trees.PartialViewMacros:
|
||||
if (IsDirectory(virtualPath, SystemDirectories.MacroPartials))
|
||||
{
|
||||
Services.FileService.DeletePartialViewMacroFolder(virtualPath);
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
if (Services.FileService.DeletePartialViewMacro(virtualPath, Security.CurrentUser.Id))
|
||||
{
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No Partial View Macro or folder found with the specified path");
|
||||
|
||||
case Core.Constants.Trees.PartialViewMacros:
|
||||
if (IsDirectory(virtualPath, SystemDirectories.MacroPartials))
|
||||
{
|
||||
Services.FileService.DeletePartialViewMacroFolder(virtualPath);
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
if (Services.FileService.DeletePartialViewMacro(virtualPath, Security.CurrentUser.Id))
|
||||
{
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No Partial View Macro or folder found with the specified path");
|
||||
case Core.Constants.Trees.Scripts:
|
||||
if (IsDirectory(virtualPath, SystemDirectories.Scripts))
|
||||
{
|
||||
Services.FileService.DeleteScriptFolder(virtualPath);
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
if (Services.FileService.GetScriptByName(virtualPath) != null)
|
||||
{
|
||||
Services.FileService.DeleteScript(virtualPath, Security.CurrentUser.Id);
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No Script or folder found with the specified path");
|
||||
|
||||
case Core.Constants.Trees.Scripts:
|
||||
if (IsDirectory(virtualPath, SystemDirectories.Scripts))
|
||||
{
|
||||
Services.FileService.DeleteScriptFolder(virtualPath);
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
if (Services.FileService.GetScriptByName(virtualPath) != null)
|
||||
{
|
||||
Services.FileService.DeleteScript(virtualPath, Security.CurrentUser.Id);
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "No Script or folder found with the specified path");
|
||||
|
||||
default:
|
||||
return Request.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
default:
|
||||
return Request.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
@@ -326,16 +321,13 @@ namespace Umbraco.Web.Editors
|
||||
/// <returns>The updated CodeFileDisplay model</returns>
|
||||
public CodeFileDisplay PostSave(CodeFileDisplay display)
|
||||
{
|
||||
if (display == null) throw new ArgumentNullException("display");
|
||||
|
||||
if (ModelState.IsValid == false)
|
||||
{
|
||||
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState));
|
||||
}
|
||||
|
||||
if (display == null || string.IsNullOrWhiteSpace(display.FileType))
|
||||
{
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
switch (display.FileType)
|
||||
{
|
||||
case Core.Constants.Trees.PartialViews:
|
||||
@@ -362,35 +354,29 @@ namespace Umbraco.Web.Editors
|
||||
display.Id = System.Web.HttpUtility.UrlEncode(partialViewMacroResult.Result.Path);
|
||||
return display;
|
||||
}
|
||||
|
||||
|
||||
display.AddErrorNotification(
|
||||
Services.TextService.Localize("speechBubbles/partialViewErrorHeader"),
|
||||
Services.TextService.Localize("speechBubbles/partialViewErrorText"));
|
||||
break;
|
||||
|
||||
case Core.Constants.Trees.Scripts:
|
||||
var virtualPath = display.VirtualPath;
|
||||
var script = Services.FileService.GetScriptByName(display.VirtualPath);
|
||||
if (script != null)
|
||||
{
|
||||
script.Path = display.Name;
|
||||
display = Mapper.Map(script, display);
|
||||
display.Path = Url.GetTreePathFromFilePath(script.Path);
|
||||
display.Id = System.Web.HttpUtility.UrlEncode(script.Path);
|
||||
return display;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var fileName = EnsurePartialViewExtension(display.Name, ".js");
|
||||
script = new Script(virtualPath + fileName);
|
||||
}
|
||||
|
||||
script.Content = display.Content;
|
||||
var scriptResult = CreateOrUpdateScript(display);
|
||||
display = Mapper.Map(scriptResult, display);
|
||||
display.Path = Url.GetTreePathFromFilePath(scriptResult.Path);
|
||||
display.Id = System.Web.HttpUtility.UrlEncode(scriptResult.Path);
|
||||
return display;
|
||||
|
||||
//display.AddErrorNotification(
|
||||
// Services.TextService.Localize("speechBubbles/partialViewErrorHeader"),
|
||||
// Services.TextService.Localize("speechBubbles/partialViewErrorText"));
|
||||
|
||||
Services.FileService.SaveScript(script, Security.CurrentUser.Id);
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
default:
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
@@ -398,11 +384,86 @@ namespace Umbraco.Web.Editors
|
||||
return display;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create or Update a Script
|
||||
/// </summary>
|
||||
/// <param name="display"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// It's important to note that Scripts are DIFFERENT from cshtml files since scripts use IFileSystem and cshtml files
|
||||
/// use a normal file system because they must exist on a real file system for ASP.NET to work.
|
||||
/// </remarks>
|
||||
private Script CreateOrUpdateScript(CodeFileDisplay display)
|
||||
{
|
||||
//must always end with the correct extension
|
||||
display.Name = EnsureCorrectFileExtension(display.Name, ".js");
|
||||
|
||||
var virtualPath = display.VirtualPath ?? string.Empty;
|
||||
// this is all weird, should be using relative paths everywhere!
|
||||
var relPath = FileSystemProviderManager.Current.ScriptsFileSystem.GetRelativePath(virtualPath);
|
||||
|
||||
if (relPath.EndsWith(".js") == false)
|
||||
{
|
||||
//this would typically mean it's new
|
||||
relPath = relPath.IsNullOrWhiteSpace()
|
||||
? relPath + display.Name
|
||||
: relPath.EnsureEndsWith('/') + display.Name;
|
||||
}
|
||||
|
||||
var script = Services.FileService.GetScriptByName(relPath);
|
||||
if (script != null)
|
||||
{
|
||||
// might need to find the path
|
||||
var orgPath = script.OriginalPath.Substring(0, script.OriginalPath.IndexOf(script.Name));
|
||||
script.Path = orgPath + display.Name;
|
||||
|
||||
script.Content = display.Content;
|
||||
//try/catch? since this doesn't return an Attempt?
|
||||
Services.FileService.SaveScript(script, Security.CurrentUser.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
script = new Script(relPath);
|
||||
script.Content = display.Content;
|
||||
Services.FileService.SaveScript(script, Security.CurrentUser.Id);
|
||||
}
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
private Attempt<IPartialView> CreateOrUpdatePartialView(CodeFileDisplay display)
|
||||
{
|
||||
return CreateOrUpdatePartialView(display, SystemDirectories.MacroPartials,
|
||||
Services.FileService.GetPartialView, Services.FileService.SavePartialView, Services.FileService.CreatePartialView);
|
||||
}
|
||||
|
||||
private Attempt<IPartialView> CreateOrUpdatePartialViewMacro(CodeFileDisplay display)
|
||||
{
|
||||
return CreateOrUpdatePartialView(display, SystemDirectories.MacroPartials,
|
||||
Services.FileService.GetPartialViewMacro, Services.FileService.SavePartialViewMacro, Services.FileService.CreatePartialViewMacro);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to take care of persisting partial views or partial view macros - so we're not duplicating the same logic
|
||||
/// </summary>
|
||||
/// <param name="display"></param>
|
||||
/// <param name="systemDirectory"></param>
|
||||
/// <param name="getView"></param>
|
||||
/// <param name="saveView"></param>
|
||||
/// <param name="createView"></param>
|
||||
/// <returns></returns>
|
||||
private Attempt<IPartialView> CreateOrUpdatePartialView(
|
||||
CodeFileDisplay display, string systemDirectory,
|
||||
Func<string, IPartialView> getView,
|
||||
Func<IPartialView, int, Attempt<IPartialView>> saveView,
|
||||
Func<IPartialView, string, int, Attempt<IPartialView>> createView)
|
||||
{
|
||||
//must always end with the correct extension
|
||||
display.Name = EnsureCorrectFileExtension(display.Name, ".cshtml");
|
||||
|
||||
Attempt<IPartialView> partialViewResult;
|
||||
string virtualPath = NormalizeVirtualPath(display.VirtualPath, SystemDirectories.PartialViews);
|
||||
var view = Services.FileService.GetPartialView(virtualPath);
|
||||
var virtualPath = NormalizeVirtualPath(display.VirtualPath, systemDirectory);
|
||||
var view = getView(virtualPath);
|
||||
if (view != null)
|
||||
{
|
||||
// might need to find the path
|
||||
@@ -410,14 +471,13 @@ namespace Umbraco.Web.Editors
|
||||
view.Path = orgPath + display.Name;
|
||||
|
||||
view.Content = display.Content;
|
||||
partialViewResult = Services.FileService.SavePartialView(view, Security.CurrentUser.Id);
|
||||
partialViewResult = saveView(view, Security.CurrentUser.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
var fileName = EnsurePartialViewExtension(display.Name, ".cshtml");
|
||||
view = new PartialView(virtualPath + fileName);
|
||||
view = new PartialView(virtualPath + display.Name);
|
||||
view.Content = display.Content;
|
||||
partialViewResult = Services.FileService.CreatePartialView(view, display.Snippet, Security.CurrentUser.Id);
|
||||
partialViewResult = createView(view, display.Snippet, Security.CurrentUser.Id);
|
||||
}
|
||||
|
||||
return partialViewResult;
|
||||
@@ -437,29 +497,7 @@ namespace Umbraco.Web.Editors
|
||||
return virtualPath;
|
||||
}
|
||||
|
||||
private Attempt<IPartialView> CreateOrUpdatePartialViewMacro(CodeFileDisplay display)
|
||||
{
|
||||
Attempt<IPartialView> partialViewMacroResult;
|
||||
var virtualPath = display.VirtualPath ?? string.Empty;
|
||||
var viewMacro = Services.FileService.GetPartialViewMacro(virtualPath);
|
||||
if (viewMacro != null)
|
||||
{
|
||||
viewMacro.Content = display.Content;
|
||||
viewMacro.Path = display.Name;
|
||||
partialViewMacroResult = Services.FileService.SavePartialViewMacro(viewMacro, Security.CurrentUser.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
var fileName = EnsurePartialViewExtension(display.Name, ".cshtml");
|
||||
viewMacro = new PartialView(virtualPath + fileName);
|
||||
viewMacro.Content = display.Content;
|
||||
partialViewMacroResult = Services.FileService.CreatePartialViewMacro(viewMacro, display.Snippet, Security.CurrentUser.Id);
|
||||
}
|
||||
|
||||
return partialViewMacroResult;
|
||||
}
|
||||
|
||||
private string EnsurePartialViewExtension(string value, string extension)
|
||||
private string EnsureCorrectFileExtension(string value, string extension)
|
||||
{
|
||||
if (value.EndsWith(extension) == false)
|
||||
value += extension;
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace Umbraco.Web.Editors
|
||||
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
|
||||
{
|
||||
controllerSettings.Services.Replace(typeof(IHttpActionSelector), new ParameterSwapControllerActionSelector(
|
||||
new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetById", "id", typeof(int), typeof(Guid), typeof(Udi)),
|
||||
new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetChildren", "id", typeof(int), typeof(Guid), typeof(Udi), typeof(string))));
|
||||
}
|
||||
}
|
||||
@@ -122,7 +123,7 @@ namespace Umbraco.Web.Editors
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content json for the content id
|
||||
/// Gets the media item by id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
@@ -141,6 +142,43 @@ namespace Umbraco.Web.Editors
|
||||
return Mapper.Map<IMedia, MediaItemDisplay>(foundContent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media item by id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[OutgoingEditorModelEvent]
|
||||
[EnsureUserPermissionForMedia("id")]
|
||||
public MediaItemDisplay GetById(Guid id)
|
||||
{
|
||||
var foundContent = GetObjectFromRequest(() => Services.MediaService.GetById(id));
|
||||
|
||||
if (foundContent == null)
|
||||
{
|
||||
HandleContentNotFound(id);
|
||||
//HandleContentNotFound will throw an exception
|
||||
return null;
|
||||
}
|
||||
return Mapper.Map<IMedia, MediaItemDisplay>(foundContent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media item by id
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[OutgoingEditorModelEvent]
|
||||
[EnsureUserPermissionForMedia("id")]
|
||||
public MediaItemDisplay GetById(Udi id)
|
||||
{
|
||||
var guidUdi = id as GuidUdi;
|
||||
if (guidUdi != null)
|
||||
{
|
||||
return GetById(guidUdi.Guid);
|
||||
}
|
||||
throw new HttpResponseException(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return media for the specified ids
|
||||
/// </summary>
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Web.Models.ContentEditing
|
||||
{
|
||||
[DataContract(Name = "scriptFile", Namespace = "")]
|
||||
public class CodeFileDisplay : INotificationModel
|
||||
public class CodeFileDisplay : INotificationModel, IValidatableObject
|
||||
{
|
||||
public CodeFileDisplay()
|
||||
{
|
||||
Notifications = new List<Notification>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// VirtualPath is the path to the file on disk
|
||||
/// /views/partials/file.cshtml
|
||||
@@ -47,5 +54,27 @@ namespace Umbraco.Web.Models.ContentEditing
|
||||
public string Id { get; set; }
|
||||
|
||||
public List<Notification> Notifications { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Some custom validation is required for valid file names
|
||||
/// </summary>
|
||||
/// <param name="validationContext"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
||||
{
|
||||
var illegalChars = System.IO.Path.GetInvalidFileNameChars();
|
||||
if (Name.ContainsAny(illegalChars))
|
||||
{
|
||||
yield return new ValidationResult(
|
||||
"The file name cannot contain illegal characters",
|
||||
new[] { "Name" });
|
||||
}
|
||||
else if (System.IO.Path.GetFileNameWithoutExtension(Name).IsNullOrWhiteSpace())
|
||||
{
|
||||
yield return new ValidationResult(
|
||||
"The file name cannot be empty",
|
||||
new[] { "Name" });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-5
@@ -132,7 +132,6 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
if (nodeIds.Length > 0)
|
||||
{
|
||||
var umbHelper = new UmbracoHelper(UmbracoContext.Current);
|
||||
|
||||
var objectType = UmbracoObjectTypes.Unknown;
|
||||
|
||||
foreach (var nodeId in nodeIds)
|
||||
@@ -148,8 +147,8 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
}
|
||||
}
|
||||
}
|
||||
//TODO: Get rid of this Yield thing
|
||||
return multiNodeTreePicker.Yield().Where(x => x != null);
|
||||
|
||||
return multiNodeTreePicker;
|
||||
}
|
||||
|
||||
// return the first nodeId as this is one of the excluded properties that expects a single id
|
||||
@@ -170,11 +169,13 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
{
|
||||
var item = udi.ToPublishedContent();
|
||||
if (item != null)
|
||||
{
|
||||
multiNodeTreePicker.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
//TODO: Get rid of this Yield thing
|
||||
return multiNodeTreePicker.Yield().Where(x => x != null);
|
||||
|
||||
return multiNodeTreePicker;
|
||||
}
|
||||
|
||||
// return the first nodeId as this is one of the excluded properties that expects a single id
|
||||
|
||||
+20
-6
@@ -8,6 +8,7 @@
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
@@ -223,13 +224,26 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters
|
||||
/// </returns>
|
||||
public bool IsMultipleDataType(int dataTypeId)
|
||||
{
|
||||
// ** This must be cached (U4-8862) **
|
||||
var multiPickerPreValue =
|
||||
_dataTypeService.GetPreValuesCollectionByDataTypeId(dataTypeId)
|
||||
.PreValuesAsDictionary.FirstOrDefault(
|
||||
x => string.Equals(x.Key, "multiPicker", StringComparison.InvariantCultureIgnoreCase)).Value;
|
||||
// GetPreValuesCollectionByDataTypeId is cached at repository level;
|
||||
// still, the collection is deep-cloned so this is kinda expensive,
|
||||
// better to cache here + trigger refresh in DataTypeCacheRefresher
|
||||
|
||||
return multiPickerPreValue != null && multiPickerPreValue.Value.TryConvertTo<bool>().Result;
|
||||
return Storages.GetOrAdd(dataTypeId, id =>
|
||||
{
|
||||
var preValue = _dataTypeService.GetPreValuesCollectionByDataTypeId(id)
|
||||
.PreValuesAsDictionary
|
||||
.FirstOrDefault(x => string.Equals(x.Key, "multiPicker", StringComparison.InvariantCultureIgnoreCase))
|
||||
.Value;
|
||||
|
||||
return preValue != null && preValue.Value.TryConvertTo<bool>().Result;
|
||||
});
|
||||
}
|
||||
|
||||
private static readonly ConcurrentDictionary<int, bool> Storages = new ConcurrentDictionary<int, bool>();
|
||||
|
||||
internal static void ClearCaches()
|
||||
{
|
||||
Storages.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,90 +1,71 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http.Formatting;
|
||||
using umbraco.BusinessLogic.Actions;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Models.Trees;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Web.Trees
|
||||
{
|
||||
public abstract class FileSystemTreeController : TreeController
|
||||
{
|
||||
protected abstract string FilePath { get; }
|
||||
protected abstract string FileSearchPattern { get; }
|
||||
protected abstract IFileSystem2 FileSystem { get; }
|
||||
protected abstract string[] Extensions { get; }
|
||||
protected abstract string FileIcon { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Inheritors can override this method to modify the file node that is created.
|
||||
/// </summary>
|
||||
/// <param name="xNode"></param>
|
||||
/// <param name="treeNode"></param>
|
||||
protected virtual void OnRenderFileNode(ref TreeNode treeNode) { }
|
||||
|
||||
/// <summary>
|
||||
/// Inheritors can override this method to modify the folder node that is created.
|
||||
/// </summary>
|
||||
/// <param name="xNode"></param>
|
||||
/// <param name="treeNode"></param>
|
||||
protected virtual void OnRenderFolderNode(ref TreeNode treeNode) { }
|
||||
|
||||
protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings)
|
||||
{
|
||||
string orgPath = "";
|
||||
string path = "";
|
||||
if (!string.IsNullOrEmpty(id) && id != "-1")
|
||||
{
|
||||
orgPath = System.Web.HttpUtility.UrlDecode(id);
|
||||
path = IOHelper.MapPath(FilePath + "/" + orgPath);
|
||||
orgPath += "/";
|
||||
}
|
||||
else
|
||||
{
|
||||
path = IOHelper.MapPath(FilePath);
|
||||
}
|
||||
var path = string.IsNullOrEmpty(id) == false && id != Constants.System.Root.ToInvariantString()
|
||||
? HttpUtility.UrlDecode(id).TrimStart("/")
|
||||
: "";
|
||||
|
||||
DirectoryInfo dirInfo = new DirectoryInfo(path);
|
||||
DirectoryInfo[] dirInfos = dirInfo.GetDirectories();
|
||||
var directories = FileSystem.GetDirectories(path);
|
||||
|
||||
var nodes = new TreeNodeCollection();
|
||||
foreach (DirectoryInfo dir in dirInfos)
|
||||
foreach (var directory in directories)
|
||||
{
|
||||
if ((dir.Attributes & FileAttributes.Hidden) == 0)
|
||||
{
|
||||
var HasChildren = dir.GetFiles().Length > 0 || dir.GetDirectories().Length > 0;
|
||||
var node = CreateTreeNode(System.Web.HttpUtility.UrlEncode(orgPath + dir.Name), orgPath, queryStrings, dir.Name, "icon-folder", HasChildren);
|
||||
var hasChildren = FileSystem.GetFiles(directory).Any() || FileSystem.GetDirectories(directory).Any();
|
||||
|
||||
OnRenderFolderNode(ref node);
|
||||
if(node != null)
|
||||
nodes.Add(node);
|
||||
}
|
||||
var name = Path.GetFileName(directory);
|
||||
var node = CreateTreeNode(HttpUtility.UrlEncode(directory), path, queryStrings, name, "icon-folder", hasChildren);
|
||||
OnRenderFolderNode(ref node);
|
||||
if(node != null)
|
||||
nodes.Add(node);
|
||||
}
|
||||
|
||||
//this is a hack to enable file system tree to support multiple file extension look-up
|
||||
//so the pattern both support *.* *.xml and xml,js,vb for lookups
|
||||
string[] allowedExtensions = new string[0];
|
||||
bool filterByMultipleExtensions = FileSearchPattern.Contains(",");
|
||||
FileInfo[] fileInfo;
|
||||
|
||||
if (filterByMultipleExtensions)
|
||||
var files = FileSystem.GetFiles(path).Where(x =>
|
||||
{
|
||||
fileInfo = dirInfo.GetFiles();
|
||||
allowedExtensions = FileSearchPattern.ToLower().Split(',');
|
||||
}
|
||||
else
|
||||
fileInfo = dirInfo.GetFiles(FileSearchPattern);
|
||||
var extension = Path.GetExtension(x);
|
||||
return extension != null && Extensions.Contains(extension.Trim('.'), StringComparer.InvariantCultureIgnoreCase);
|
||||
});
|
||||
|
||||
foreach (FileInfo file in fileInfo)
|
||||
{
|
||||
if ((file.Attributes & FileAttributes.Hidden) == 0)
|
||||
foreach (var file in files)
|
||||
{
|
||||
var withoutExt = Path.GetFileNameWithoutExtension(file);
|
||||
if (withoutExt.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
if (filterByMultipleExtensions && Array.IndexOf<string>(allowedExtensions, file.Extension.ToLower().Trim('.')) < 0)
|
||||
continue;
|
||||
|
||||
var node = CreateTreeNode(System.Web.HttpUtility.UrlEncode(orgPath + file.Name), orgPath, queryStrings, file.Name, FileIcon, false);
|
||||
|
||||
var name = Path.GetFileName(file);
|
||||
var node = CreateTreeNode(HttpUtility.UrlEncode(file), path, queryStrings, name, FileIcon, false);
|
||||
OnRenderFileNode(ref node);
|
||||
|
||||
if(node != null)
|
||||
if (node != null)
|
||||
nodes.Add(node);
|
||||
}
|
||||
}
|
||||
@@ -109,27 +90,22 @@ namespace Umbraco.Web.Trees
|
||||
return menu;
|
||||
}
|
||||
|
||||
string path;
|
||||
if (string.IsNullOrEmpty(id) == false)
|
||||
{
|
||||
var orgPath = System.Web.HttpUtility.UrlDecode(id);
|
||||
path = IOHelper.MapPath(FilePath + "/" + orgPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
path = IOHelper.MapPath(FilePath);
|
||||
}
|
||||
var path = string.IsNullOrEmpty(id) == false && id != Constants.System.Root.ToInvariantString()
|
||||
? System.Web.HttpUtility.UrlDecode(id).TrimStart("/")
|
||||
: "";
|
||||
|
||||
var dirInfo = new DirectoryInfo(path);
|
||||
//check if it's a directory
|
||||
if (dirInfo.Attributes == FileAttributes.Directory)
|
||||
var isFile = FileSystem.FileExists(path);
|
||||
var isDirectory = FileSystem.DirectoryExists(path);
|
||||
|
||||
if (isDirectory)
|
||||
{
|
||||
//set the default to create
|
||||
menu.DefaultMenuAlias = ActionNew.Instance.Alias;
|
||||
//create action
|
||||
menu.Items.Add<ActionNew>(Services.TextService.Localize(string.Format("actions/{0}", ActionNew.Instance.Alias)));
|
||||
|
||||
var hasChildren = dirInfo.GetFiles().Length > 0 || dirInfo.GetDirectories().Length > 0;
|
||||
|
||||
var hasChildren = FileSystem.GetFiles(path).Any() || FileSystem.GetDirectories(path).Any();
|
||||
|
||||
//We can only delete folders if it doesn't have any children (folders or files)
|
||||
if (hasChildren == false)
|
||||
{
|
||||
@@ -140,10 +116,9 @@ namespace Umbraco.Web.Trees
|
||||
//refresh action
|
||||
menu.Items.Add<RefreshNode, ActionRefresh>(Services.TextService.Localize(string.Format("actions/{0}", ActionRefresh.Instance.Alias)), true);
|
||||
}
|
||||
//if it's not a directory then we only allow to delete the item
|
||||
else
|
||||
else if (isFile)
|
||||
{
|
||||
//delete action
|
||||
//if it's not a directory then we only allow to delete the item
|
||||
menu.Items.Add<ActionDelete>(Services.TextService.Localize(string.Format("actions/{0}", ActionDelete.Instance.Alias)));
|
||||
}
|
||||
|
||||
|
||||
@@ -10,14 +10,16 @@ namespace Umbraco.Web.Trees
|
||||
[Tree(Constants.Applications.Developer, "partialViewMacros", "Partial View Macro Files", sortOrder: 6)]
|
||||
public class PartialViewMacrosTreeController : FileSystemTreeController
|
||||
{
|
||||
protected override string FilePath
|
||||
protected override IFileSystem2 FileSystem
|
||||
{
|
||||
get { return SystemDirectories.MacroPartials; }
|
||||
get { return FileSystemProviderManager.Current.MacroPartialsFileSystem; }
|
||||
}
|
||||
|
||||
protected override string FileSearchPattern
|
||||
private static readonly string[] ExtensionsStatic = { "cshtml" };
|
||||
|
||||
protected override string[] Extensions
|
||||
{
|
||||
get { return "*.cshtml"; }
|
||||
get { return ExtensionsStatic; }
|
||||
}
|
||||
|
||||
protected override string FileIcon
|
||||
@@ -25,11 +27,6 @@ namespace Umbraco.Web.Trees
|
||||
get { return "icon-article"; }
|
||||
}
|
||||
|
||||
protected override void OnRenderFileNode(ref TreeNode treeNode)
|
||||
{
|
||||
base.OnRenderFileNode(ref treeNode);
|
||||
}
|
||||
|
||||
protected override void OnRenderFolderNode(ref TreeNode treeNode)
|
||||
{
|
||||
//TODO: This isn't the best way to ensure a noop process for clicking a node but it works for now.
|
||||
|
||||
@@ -10,25 +10,23 @@ namespace Umbraco.Web.Trees
|
||||
[Tree(Constants.Applications.Settings, "partialViews", "Partial Views", sortOrder: 2)]
|
||||
public class PartialViewsTreeController : FileSystemTreeController
|
||||
{
|
||||
protected override string FilePath
|
||||
protected override IFileSystem2 FileSystem
|
||||
{
|
||||
get { return SystemDirectories.PartialViews; }
|
||||
get { return FileSystemProviderManager.Current.PartialViewsFileSystem; }
|
||||
}
|
||||
|
||||
protected override string FileSearchPattern
|
||||
{
|
||||
get { return "*.cshtml"; }
|
||||
}
|
||||
private static readonly string[] ExtensionsStatic = { "cshtml" };
|
||||
|
||||
protected override string[] Extensions
|
||||
{
|
||||
get { return ExtensionsStatic; }
|
||||
}
|
||||
|
||||
protected override string FileIcon
|
||||
{
|
||||
get { return "icon-article"; }
|
||||
}
|
||||
|
||||
protected override void OnRenderFileNode(ref TreeNode treeNode)
|
||||
{
|
||||
base.OnRenderFileNode(ref treeNode);
|
||||
}
|
||||
|
||||
protected override void OnRenderFolderNode(ref TreeNode treeNode)
|
||||
{
|
||||
//TODO: This isn't the best way to ensure a noop process for clicking a node but it works for now.
|
||||
|
||||
@@ -7,14 +7,16 @@ namespace Umbraco.Web.Trees
|
||||
[Tree(Constants.Applications.Settings, "scripts", "Scripts", sortOrder: 4)]
|
||||
public class ScriptTreeController : FileSystemTreeController
|
||||
{
|
||||
protected override string FilePath
|
||||
protected override IFileSystem2 FileSystem
|
||||
{
|
||||
get { return SystemDirectories.Scripts; }
|
||||
get { return FileSystemProviderManager.Current.ScriptsFileSystem; }
|
||||
}
|
||||
|
||||
protected override string FileSearchPattern
|
||||
private static readonly string[] ExtensionsStatic = { "js" };
|
||||
|
||||
protected override string[] Extensions
|
||||
{
|
||||
get { return "*.js"; }
|
||||
get { return ExtensionsStatic; }
|
||||
}
|
||||
protected override string FileIcon
|
||||
{
|
||||
@@ -26,10 +28,5 @@ namespace Umbraco.Web.Trees
|
||||
//TODO: This isn't the best way to ensure a noop process for clicking a node but it works for now.
|
||||
treeNode.AdditionalData["jsClickCallback"] = "javascript:void(0);";
|
||||
}
|
||||
|
||||
protected override void OnRenderFileNode(ref TreeNode treeNode)
|
||||
{
|
||||
base.OnRenderFileNode(ref treeNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ namespace Umbraco.Web.WebApi.Filters
|
||||
{
|
||||
private readonly int? _nodeId;
|
||||
private readonly string _paramName;
|
||||
private DictionarySource _source;
|
||||
|
||||
public enum DictionarySource
|
||||
{
|
||||
@@ -43,14 +42,12 @@ namespace Umbraco.Web.WebApi.Filters
|
||||
{
|
||||
Mandate.ParameterNotNullOrEmpty(paramName, "paramName");
|
||||
_paramName = paramName;
|
||||
_source = DictionarySource.ActionArguments;
|
||||
}
|
||||
|
||||
public EnsureUserPermissionForMediaAttribute(string paramName, DictionarySource source)
|
||||
{
|
||||
Mandate.ParameterNotNullOrEmpty(paramName, "paramName");
|
||||
_paramName = paramName;
|
||||
_source = source;
|
||||
}
|
||||
|
||||
public override bool AllowMultiple
|
||||
@@ -58,6 +55,33 @@ namespace Umbraco.Web.WebApi.Filters
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
private int GetNodeIdFromParameter(object parameterValue)
|
||||
{
|
||||
if (parameterValue is int)
|
||||
{
|
||||
return (int) parameterValue;
|
||||
}
|
||||
|
||||
var guidId = Guid.Empty;
|
||||
if (parameterValue is Guid)
|
||||
{
|
||||
guidId = (Guid)parameterValue;
|
||||
}
|
||||
else if (parameterValue is GuidUdi)
|
||||
{
|
||||
guidId = ((GuidUdi) parameterValue).Guid;
|
||||
}
|
||||
|
||||
if (guidId != Guid.Empty)
|
||||
{
|
||||
var found = ApplicationContext.Current.Services.EntityService.GetIdForKey(guidId, UmbracoObjectTypes.Media);
|
||||
if (found)
|
||||
return found.Result;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("The id type: " + parameterValue.GetType() + " is not a supported id");
|
||||
}
|
||||
|
||||
public override void OnActionExecuting(HttpActionContext actionContext)
|
||||
{
|
||||
if (UmbracoContext.Current.Security.CurrentUser == null)
|
||||
@@ -68,7 +92,7 @@ namespace Umbraco.Web.WebApi.Filters
|
||||
int nodeId;
|
||||
if (_nodeId.HasValue == false)
|
||||
{
|
||||
var parts = _paramName.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var parts = _paramName.Split(new [] { '.' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (actionContext.ActionArguments[parts[0]] == null)
|
||||
{
|
||||
@@ -77,7 +101,7 @@ namespace Umbraco.Web.WebApi.Filters
|
||||
|
||||
if (parts.Length == 1)
|
||||
{
|
||||
nodeId = (int)actionContext.ActionArguments[parts[0]];
|
||||
nodeId = GetNodeIdFromParameter(actionContext.ActionArguments[parts[0]]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -88,7 +112,7 @@ namespace Umbraco.Web.WebApi.Filters
|
||||
{
|
||||
throw new InvalidOperationException("No argument found for the current action with the name: " + _paramName);
|
||||
}
|
||||
nodeId = (int)prop.GetValue(actionContext.ActionArguments[parts[0]]);
|
||||
nodeId = GetNodeIdFromParameter(prop.GetValue(actionContext.ActionArguments[parts[0]]));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -109,22 +133,7 @@ namespace Umbraco.Web.WebApi.Filters
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//private object GetValueFromSource(HttpActionContext actionContext, string key)
|
||||
//{
|
||||
// switch (_source)
|
||||
// {
|
||||
// case DictionarySource.ActionArguments:
|
||||
// return actionContext.ActionArguments[key];
|
||||
// case DictionarySource.RequestForm:
|
||||
// return actionContext.Request.Properties
|
||||
// case DictionarySource.RequestQueryString:
|
||||
// break;
|
||||
// default:
|
||||
// throw new ArgumentOutOfRangeException();
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user