U4-6003 List View - Order By Custom Property Fix

Original work done on https://github.com/umbraco/Umbraco-CMS/pull/711 but ported to the latest version

Content below for reference
With the current implementation of the list view you can only sort by system columns (Name, SortOrder etc.) and not custom columns you have added to your document types. This PR allows that.

The crux of it is a sub-query added to the ORDER BY clause when we are ordering by a custom field. This looks up the field's value from the most recent content version.

Provided here and not in the previous pull request is:

MySQL support
Have done some performance testing. On a local laptop with 1000 nodes in a list view, it's sorting in around 220-250ms. It's a little slower that sorting on native properties like node name, but still perfectly usable - there's no significant delay you see in use.
Please note also:

GetPagedResultsByQuery() in VersionableRepositoryBase was previously doing an ORDER BY in SQL and then repeating this via LINQ to Objects. I couldn't see that this second ordering was necessary so removed it, but wanted to flag here in case I've missed something around why this was necessary.
The PR also includes small amends to fix or hide sorting on a couple of the default columns for the member amd media list views.
This commit is contained in:
André Ferreira
2016-02-26 14:30:32 +00:00
parent ac2ebc4071
commit bd2a40d214
31 changed files with 2526 additions and 2457 deletions
@@ -241,8 +241,8 @@ namespace Umbraco.Core.Persistence.Repositories
// see: http://issues.umbraco.org/issue/U4-6322 & http://issues.umbraco.org/issue/U4-5982
var descendants = GetPagedResultsByQuery<DocumentDto, Content>(query, pageIndex, pageSize, out total,
new Tuple<string, string>("cmsDocument", "nodeId"),
ProcessQuery, "Path", Direction.Ascending);
ProcessQuery, "Path", Direction.Ascending, orderBySystemField: true);
var xmlItems = (from descendant in descendants
let xml = serializer(descendant)
select new ContentXmlDto { NodeId = descendant.Id, Xml = xml.ToDataString() }).ToArray();
@@ -766,10 +766,11 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="totalRecords">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
public IEnumerable<IContent> GetPagedResultsByQuery(IQuery<IContent> query, long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, string filter = "")
string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "")
{
//NOTE: This uses the GetBaseQuery method but that does not take into account the required 'newest' field which is
@@ -788,7 +789,7 @@ namespace Umbraco.Core.Persistence.Repositories
return GetPagedResultsByQuery<DocumentDto, Content>(query, pageIndex, pageSize, out totalRecords,
new Tuple<string, string>("cmsDocument", "nodeId"),
ProcessQuery, orderBy, orderDirection,
ProcessQuery, orderBy, orderDirection, orderBySystemField,
filterCallback);
}
@@ -84,9 +84,10 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="totalRecords">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
IEnumerable<IContent> GetPagedResultsByQuery(IQuery<IContent> query, long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, string filter = "");
string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "");
}
}
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
public interface IMediaRepository : IRepositoryVersionable<int, IMedia>, IRecycleBinRepository<IMedia>, IDeleteMediaFilesRepository
{
/// <summary>
/// Used to add/update published xml for the media item
/// </summary>
@@ -33,9 +33,10 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="totalRecords">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
IEnumerable<IMedia> GetPagedResultsByQuery(IQuery<IMedia> query, long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, string filter = "");
string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "");
}
}
@@ -44,16 +44,17 @@ namespace Umbraco.Core.Persistence.Repositories
/// <summary>
/// Gets paged member results
/// </summary>
/// <param name="query"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalRecords"></param>
/// <param name="orderBy"></param>
/// <param name="orderDirection"></param>
/// <param name="filter"></param>
/// <param name="query">The query.</param>
/// <param name="pageIndex">Index of the page.</param>
/// <param name="pageSize">Size of the page.</param>
/// <param name="totalRecords">The total records.</param>
/// <param name="orderBy">The order by column</param>
/// <param name="orderDirection">The order direction.</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search query</param>
/// <returns></returns>
IEnumerable<IMember> GetPagedResultsByQuery(IQuery<IMember> query, long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, string filter = "");
string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "");
//IEnumerable<IMember> GetPagedResultsByQuery<TDto>(
// Sql sql, int pageIndex, int pageSize, out int totalRecords,
@@ -232,7 +232,7 @@ namespace Umbraco.Core.Persistence.Repositories
var processed = 0;
do
{
var descendants = GetPagedResultsByQuery(query, pageIndex, pageSize, out total, "Path", Direction.Ascending);
var descendants = GetPagedResultsByQuery(query, pageIndex, pageSize, out total, "Path", Direction.Ascending, orderBySystemField: true);
var xmlItems = (from descendant in descendants
let xml = serializer(descendant)
@@ -442,10 +442,11 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="totalRecords">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IMedia"/> objects</returns>
public IEnumerable<IMedia> GetPagedResultsByQuery(IQuery<IMedia> query, long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, string filter = "")
string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "")
{
var args = new List<object>();
var sbWhere = new StringBuilder();
@@ -459,7 +460,7 @@ namespace Umbraco.Core.Persistence.Repositories
return GetPagedResultsByQuery<ContentVersionDto, Models.Media>(query, pageIndex, pageSize, out totalRecords,
new Tuple<string, string>("cmsContentVersion", "contentId"),
ProcessQuery, orderBy, orderDirection,
ProcessQuery, orderBy, orderDirection, orderBySystemField,
filterCallback);
}
@@ -468,7 +469,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
//NOTE: This doesn't allow properties to be part of the query
var dtos = Database.Fetch<ContentVersionDto, ContentDto, NodeDto>(sql);
var ids = dtos.Select(x => x.ContentDto.ContentTypeId).ToArray();
//content types
@@ -74,7 +74,7 @@ namespace Umbraco.Core.Persistence.Repositories
}
return ProcessQuery(sql);
}
protected override IEnumerable<IMember> PerformGetByQuery(IQuery<IMember> query)
@@ -95,7 +95,7 @@ namespace Umbraco.Core.Persistence.Repositories
baseQuery.Append(new Sql("WHERE umbracoNode.id IN (" + sql.SQL + ")", sql.Arguments))
.OrderBy<NodeDto>(x => x.SortOrder);
return ProcessQuery(baseQuery);
return ProcessQuery(baseQuery);
}
else
{
@@ -103,7 +103,7 @@ namespace Umbraco.Core.Persistence.Repositories
var sql = translator.Translate()
.OrderBy<NodeDto>(x => x.SortOrder);
return ProcessQuery(sql);
return ProcessQuery(sql);
}
}
@@ -118,7 +118,7 @@ namespace Umbraco.Core.Persistence.Repositories
sql.Select(isCount ? "COUNT(*)" : "*")
.From<MemberDto>()
.InnerJoin<ContentVersionDto>()
.On<ContentVersionDto, MemberDto>(left => left.NodeId, right => right.NodeId)
.On<ContentVersionDto, MemberDto>(left => left.NodeId, right => right.NodeId)
.InnerJoin<ContentDto>()
.On<ContentVersionDto, ContentDto>(left => left.NodeId, right => right.NodeId)
//We're joining the type so we can do a query against the member type - not sure if this adds much overhead or not?
@@ -269,7 +269,7 @@ namespace Umbraco.Core.Persistence.Repositories
//Ensure that strings don't contain characters that are invalid in XML
entity.SanitizeEntityPropertiesForXmlStorage();
var dirtyEntity = (ICanBeDirty) entity;
var dirtyEntity = (ICanBeDirty)entity;
//Look up parent to get and set the correct Path and update SortOrder if ParentId has changed
if (dirtyEntity.IsPropertyDirty("ParentId"))
@@ -308,9 +308,9 @@ namespace Umbraco.Core.Persistence.Repositories
//Updates the current version - cmsContentVersion
//Assumes a Version guid exists and Version date (modified date) has been set/updated
Database.Update(dto.ContentVersionDto);
//Updates the cmsMember entry if it has changed
//NOTE: these cols are the REAL column names in the db
var changedCols = new List<string>();
@@ -330,13 +330,13 @@ namespace Umbraco.Core.Persistence.Repositories
//only update the changed cols
if (changedCols.Count > 0)
{
Database.Update(dto, changedCols);
Database.Update(dto, changedCols);
}
//TODO ContentType for the Member entity
//Create the PropertyData for this version - cmsPropertyData
var propertyFactory = new PropertyFactory(entity.ContentType.CompositionPropertyTypes.ToArray(), entity.Version, entity.Id);
var propertyFactory = new PropertyFactory(entity.ContentType.CompositionPropertyTypes.ToArray(), entity.Version, entity.Id);
var keyDictionary = new Dictionary<int, int>();
//Add Properties
@@ -447,7 +447,7 @@ namespace Umbraco.Core.Persistence.Repositories
var processed = 0;
do
{
var descendants = GetPagedResultsByQuery(query, pageIndex, pageSize, out total, "Path", Direction.Ascending);
var descendants = GetPagedResultsByQuery(query, pageIndex, pageSize, out total, "Path", Direction.Ascending, orderBySystemField: true);
var xmlItems = (from descendant in descendants
let xml = serializer(descendant)
@@ -559,7 +559,7 @@ namespace Umbraco.Core.Persistence.Repositories
var grpQry = new Query<IMemberGroup>().Where(group => group.Name.Equals(groupName));
var memberGroup = _memberGroupRepository.GetByQuery(grpQry).FirstOrDefault();
if (memberGroup == null) return Enumerable.Empty<IMember>();
var subQuery = new Sql().Select("Member").From<Member2MemberGroupDto>().Where<Member2MemberGroupDto>(dto => dto.MemberGroup == memberGroup.Id);
var sql = GetBaseQuery(false)
@@ -568,7 +568,7 @@ namespace Umbraco.Core.Persistence.Repositories
.Append(new Sql("WHERE umbracoNode.id IN (" + subQuery.SQL + ")", subQuery.Arguments))
.OrderByDescending<ContentVersionDto>(x => x.VersionDate)
.OrderBy<NodeDto>(x => x.SortOrder);
return ProcessQuery(sql);
}
@@ -593,7 +593,7 @@ namespace Umbraco.Core.Persistence.Repositories
//get the COUNT base query
var fullSql = GetBaseQuery(true)
.Append(new Sql("WHERE umbracoNode.id IN (" + sql.SQL + ")", sql.Arguments));
return Database.ExecuteScalar<int>(fullSql);
}
@@ -603,18 +603,19 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="query">
/// The where clause, if this is null all records are queried
/// </param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalRecords"></param>
/// <param name="orderBy"></param>
/// <param name="orderDirection"></param>
/// <param name="filter"></param>
/// <param name="pageIndex">Index of the page.</param>
/// <param name="pageSize">Size of the page.</param>
/// <param name="totalRecords">The total records.</param>
/// <param name="orderBy">The order by column</param>
/// <param name="orderDirection">The order direction.</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search query</param>
/// <returns></returns>
/// <remarks>
/// The query supplied will ONLY work with data specifically on the cmsMember table because we are using PetaPoco paging (SQL paging)
/// </remarks>
public IEnumerable<IMember> GetPagedResultsByQuery(IQuery<IMember> query, long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, string filter = "")
string orderBy, Direction orderDirection, bool orderBySystemField, string filter = "")
{
var args = new List<object>();
var sbWhere = new StringBuilder();
@@ -625,14 +626,14 @@ namespace Umbraco.Core.Persistence.Repositories
"OR (cmsMember.LoginName LIKE @0" + args.Count + "))");
args.Add("%" + filter + "%");
filterCallback = () => new Tuple<string, object[]>(sbWhere.ToString().Trim(), args.ToArray());
}
}
return GetPagedResultsByQuery<MemberDto, Member>(query, pageIndex, pageSize, out totalRecords,
new Tuple<string, string>("cmsMember", "nodeId"),
ProcessQuery, orderBy, orderDirection,
ProcessQuery, orderBy, orderDirection, orderBySystemField,
filterCallback);
}
public void AddOrUpdateContentXml(IMember content, Func<IMember, XElement> xml)
{
_contentXmlRepository.AddOrUpdate(new ContentXmlEntity<IMember>(content, xml));
@@ -682,7 +683,7 @@ namespace Umbraco.Core.Persistence.Repositories
var dtosWithContentTypes = dtos
//This select into and null check are required because we don't have a foreign damn key on the contentType column
// http://issues.umbraco.org/issue/U4-5503
.Select(x => new {dto = x, contentType = contentTypes.FirstOrDefault(ct => ct.Id == x.ContentVersionDto.ContentDto.ContentTypeId)})
.Select(x => new { dto = x, contentType = contentTypes.FirstOrDefault(ct => ct.Id == x.ContentVersionDto.ContentDto.ContentTypeId) })
.Where(x => x.contentType != null)
.ToArray();
@@ -694,12 +695,12 @@ namespace Umbraco.Core.Persistence.Repositories
d.dto.ContentVersionDto.ContentDto.NodeDto.CreateDate,
d.contentType));
var propertyData = GetPropertyCollection(sql, docDefs);
var propertyData = GetPropertyCollection(sql, docDefs);
return dtosWithContentTypes.Select(d => CreateMemberFromDto(
d.dto,
contentTypes.First(ct => ct.Id == d.dto.ContentVersionDto.ContentDto.ContentTypeId),
propertyData[d.dto.NodeId]));
propertyData[d.dto.NodeId]));
}
/// <summary>
@@ -25,6 +25,7 @@ using Umbraco.Core.IO;
namespace Umbraco.Core.Persistence.Repositories
{
using SqlSyntax;
internal abstract class VersionableRepositoryBase<TId, TEntity> : PetaPocoRepositoryBase<TId, TEntity>
where TEntity : class, IAggregateRoot
{
@@ -61,11 +62,11 @@ namespace Umbraco.Core.Persistence.Repositories
public virtual void DeleteVersion(Guid versionId)
{
var dto = Database.FirstOrDefault<ContentVersionDto>("WHERE versionId = @VersionId", new { VersionId = versionId });
if(dto == null) return;
if (dto == null) return;
//Ensure that the lastest version is not deleted
var latestVersionDto = Database.FirstOrDefault<ContentVersionDto>("WHERE ContentId = @Id ORDER BY VersionDate DESC", new { Id = dto.NodeId });
if(latestVersionDto.VersionId == dto.VersionId)
if (latestVersionDto.VersionId == dto.VersionId)
return;
using (var transaction = Database.GetTransaction())
@@ -83,7 +84,7 @@ namespace Umbraco.Core.Persistence.Repositories
var list =
Database.Fetch<ContentVersionDto>(
"WHERE versionId <> @VersionId AND (ContentId = @Id AND VersionDate < @VersionDate)",
new {VersionId = latestVersionDto.VersionId, Id = id, VersionDate = versionDate});
new { VersionId = latestVersionDto.VersionId, Id = id, VersionDate = versionDate });
if (list.Any() == false) return;
using (var transaction = Database.GetTransaction())
@@ -244,23 +245,57 @@ namespace Umbraco.Core.Persistence.Repositories
return filteredSql;
}
private Sql GetSortedSqlForPagedResults(Sql sql, Direction orderDirection, string orderBy)
private Sql GetSortedSqlForPagedResults(Sql sql, Direction orderDirection, string orderBy, bool orderBySystemField)
{
//copy to var so that the original isn't changed
var sortedSql = new Sql(sql.SQL, sql.Arguments);
// Apply order according to parameters
if (string.IsNullOrEmpty(orderBy) == false)
if (orderBySystemField)
{
var orderByParams = new[] { GetDatabaseFieldNameForOrderBy(orderBy) };
if (orderDirection == Direction.Ascending)
// Apply order according to parameters
if (string.IsNullOrEmpty(orderBy) == false)
{
sortedSql.OrderBy(orderByParams);
var orderByParams = new[] { GetDatabaseFieldNameForOrderBy(orderBy) };
if (orderDirection == Direction.Ascending)
{
sortedSql.OrderBy(orderByParams);
}
else
{
sortedSql.OrderByDescending(orderByParams);
}
}
else
}
else
{
// Sorting by a custom field, so set-up sub-query for ORDER BY clause to pull through valie
// from most recent content version for the given order by field
var sortedInt = string.Format(SqlSyntaxContext.SqlSyntaxProvider.ConvertIntegerToOrderableString, "dataInt");
var sortedDate = string.Format(SqlSyntaxContext.SqlSyntaxProvider.ConvertDateToOrderableString, "dataDate");
var sortedString = string.Format(SqlSyntaxContext.SqlSyntaxProvider.IsNull, "dataNvarchar", "''");
var orderBySql = string.Format(@"ORDER BY (
SELECT CASE
WHEN dataInt Is Not Null THEN {0}
WHEN dataDate Is Not Null THEN {1}
ELSE {2}
END
FROM cmsContent c
INNER JOIN cmsContentVersion cv ON cv.ContentId = c.nodeId AND VersionDate = (
SELECT Max(VersionDate)
FROM cmsContentVersion
WHERE ContentId = c.nodeId
)
INNER JOIN cmsPropertyData cpd ON cpd.contentNodeId = c.nodeId
AND cpd.versionId = cv.VersionId
INNER JOIN cmsPropertyType cpt ON cpt.Id = cpd.propertytypeId
WHERE c.nodeId = umbracoNode.Id and cpt.Alias = @0)", sortedInt, sortedDate, sortedString);
sortedSql.Append(orderBySql, orderBy);
if (orderDirection == Direction.Descending)
{
sortedSql.OrderByDescending(orderByParams);
sortedSql.Append(" DESC");
}
return sortedSql;
}
return sortedSql;
}
@@ -279,13 +314,15 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="processQuery">A callback to process the query result</param>
/// <param name="orderBy">The order by column</param>
/// <param name="orderDirection">The order direction.</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <returns></returns>
/// <exception cref="System.ArgumentNullException">orderBy</exception>
protected IEnumerable<TEntity> GetPagedResultsByQuery<TDto, TContentBase>(IQuery<TEntity> query, long pageIndex, int pageSize, out long totalRecords,
Tuple<string, string> nodeIdSelect,
Func<Sql, IEnumerable<TEntity>> processQuery,
string orderBy,
string orderBy,
Direction orderDirection,
bool orderBySystemField,
Func<Tuple<string, object[]>> defaultFilter = null)
where TContentBase : class, IAggregateRoot, TEntity
{
@@ -297,18 +334,18 @@ namespace Umbraco.Core.Persistence.Repositories
if (query == null) query = new Query<TEntity>();
var translator = new SqlTranslator<TEntity>(sqlBase, query);
var sqlQuery = translator.Translate();
// Note we can't do multi-page for several DTOs like we can multi-fetch and are doing in PerformGetByQuery,
// but actually given we are doing a Get on each one (again as in PerformGetByQuery), we only need the node Id.
// So we'll modify the SQL.
var sqlNodeIds = new Sql(
sqlQuery.SQL.Replace("SELECT *", string.Format("SELECT {0}.{1}",nodeIdSelect.Item1, nodeIdSelect.Item2)),
sqlQuery.SQL.Replace("SELECT *", string.Format("SELECT {0}.{1}", nodeIdSelect.Item1, nodeIdSelect.Item2)),
sqlQuery.Arguments);
//get sorted and filtered sql
var sqlNodeIdsWithSort = GetSortedSqlForPagedResults(
GetFilteredSqlForPagedResults(sqlNodeIds, defaultFilter),
orderDirection, orderBy);
orderDirection, orderBy, orderBySystemField);
// Get page of results and total count
IEnumerable<TEntity> result;
@@ -324,7 +361,7 @@ namespace Umbraco.Core.Persistence.Repositories
var args = sqlNodeIdsWithSort.Arguments;
string sqlStringCount, sqlStringPage;
Database.BuildPageQueries<TDto>(pageIndex * pageSize, pageSize, sqlNodeIdsWithSort.SQL, ref args, out sqlStringCount, out sqlStringPage);
//if this is for sql server, the sqlPage will start with a SELECT * but we don't want that, we only want to return the nodeId
sqlStringPage = sqlStringPage
.Replace("SELECT *",
@@ -333,7 +370,7 @@ namespace Umbraco.Core.Persistence.Repositories
"SELECT " + nodeIdSelect.Item2);
//We need to make this an inner join on the paged query
var splitQuery = sqlQuery.SQL.Split(new[] {"WHERE "}, StringSplitOptions.None);
var splitQuery = sqlQuery.SQL.Split(new[] { "WHERE " }, StringSplitOptions.None);
var withInnerJoinSql = new Sql(splitQuery[0])
.Append("INNER JOIN (")
//join the paged query with the paged query arguments
@@ -345,23 +382,9 @@ namespace Umbraco.Core.Persistence.Repositories
//get sorted and filtered sql
var fullQuery = GetSortedSqlForPagedResults(
GetFilteredSqlForPagedResults(withInnerJoinSql, defaultFilter),
orderDirection, orderBy);
var content = processQuery(fullQuery)
.Cast<TContentBase>()
.AsQueryable();
// Now we need to ensure this result is also ordered by the same order by clause
var orderByProperty = GetEntityPropertyNameForOrderBy(orderBy);
if (orderDirection == Direction.Ascending)
{
result = content.OrderBy(orderByProperty);
}
else
{
result = content.OrderByDescending(orderByProperty);
}
GetFilteredSqlForPagedResults(withInnerJoinSql, defaultFilter),
orderDirection, orderBy, orderBySystemField);
return processQuery(fullQuery);
}
else
{
@@ -394,9 +417,9 @@ INNER JOIN
(" + string.Format(parsedOriginalSql, "cmsContent.nodeId, cmsContentVersion.VersionId") + @") as docData
ON cmsPropertyData.versionId = docData.VersionId AND cmsPropertyData.contentNodeId = docData.nodeId
LEFT OUTER JOIN cmsDataTypePreValues
ON cmsPropertyType.dataTypeId = cmsDataTypePreValues.datatypeNodeId", docSql.Arguments);
ON cmsPropertyType.dataTypeId = cmsDataTypePreValues.datatypeNodeId", docSql.Arguments);
var allPropertyData = Database.Fetch<PropertyDataDto>(propSql);
var allPropertyData = Database.Fetch<PropertyDataDto>(propSql);
//This is a lazy access call to get all prevalue data for the data types that make up all of these properties which we use
// below if any property requires tag support
@@ -414,7 +437,7 @@ WHERE EXISTS(
ON cmsPropertyType.contentTypeId = docData.contentType
WHERE a.id = b.id)", docSql.Arguments);
return Database.Fetch<DataTypePreValueDto>(preValsSql);
return Database.Fetch<DataTypePreValueDto>(preValsSql);
});
var result = new Dictionary<int, PropertyCollection>();
@@ -432,8 +455,8 @@ WHERE EXISTS(
var propertyDataDtos = allPropertyData.Where(x => x.NodeId == def.Id).Distinct();
var propertyFactory = new PropertyFactory(compositionProperties, def.Version, def.Id, def.CreateDate, def.VersionDate);
var properties = propertyFactory.BuildEntity(propertyDataDtos.ToArray()).ToArray();
var properties = propertyFactory.BuildEntity(propertyDataDtos.ToArray()).ToArray();
var newProperties = properties.Where(x => x.HasIdentity == false && x.PropertyType.HasIdentity);
foreach (var property in newProperties)
@@ -481,7 +504,7 @@ WHERE EXISTS(
Logger.Warn<VersionableRepositoryBase<TId, TEntity>>("The query returned multiple property sets for document definition " + def.Id + ", " + def.Composition.Name);
}
result[def.Id] = new PropertyCollection(properties);
}
}
}
return result;
@@ -521,6 +544,9 @@ WHERE EXISTS(
case "OWNER":
//TODO: This isn't going to work very nicely because it's going to order by ID, not by letter
return "umbracoNode.nodeUser";
// Members only
case "USERNAME":
return "cmsMember.LoginName";
default:
//ensure invalid SQL cannot be submitted
return Regex.Replace(orderBy, @"[^\w\.,`\[\]@-]", "");
@@ -70,6 +70,10 @@ namespace Umbraco.Core.Persistence.SqlSyntax
bool SupportsIdentityInsert();
bool? SupportsCaseInsensitiveQueries(Database db);
string IsNull { get; }
string ConvertIntegerToOrderableString { get; }
string ConvertDateToOrderableString { get; }
IEnumerable<string> GetTablesInSchema(Database db);
IEnumerable<ColumnInfo> GetColumnsInSchema(Database db);
IEnumerable<Tuple<string, string>> GetConstraintsPerTable(Database db);
@@ -18,7 +18,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
public MySqlSyntaxProvider(ILogger logger)
{
_logger = logger;
AutoIncrementDefinition = "AUTO_INCREMENT";
IntColumnDefinition = "int(11)";
BoolColumnDefinition = "tinyint(1)";
@@ -26,7 +26,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
TimeColumnDefinition = "time";
DecimalColumnDefinition = "decimal(38,6)";
GuidColumnDefinition = "char(36)";
DefaultValueFormat = "DEFAULT {0}";
InitColumnTypeMap();
@@ -326,13 +326,13 @@ ORDER BY TABLE_NAME, INDEX_NAME",
{
case SystemMethods.NewGuid:
return null; // NOT SUPPORTED!
//return "NEWID()";
//return "NEWID()";
case SystemMethods.CurrentDateTime:
return "CURRENT_TIMESTAMP";
//case SystemMethods.NewSequentialId:
// return "NEWSEQUENTIALID()";
//case SystemMethods.CurrentUTCDateTime:
// return "GETUTCDATE()";
//case SystemMethods.NewSequentialId:
// return "NEWSEQUENTIALID()";
//case SystemMethods.CurrentUTCDateTime:
// return "GETUTCDATE()";
}
return null;
@@ -360,6 +360,9 @@ ORDER BY TABLE_NAME, INDEX_NAME",
public override string DropIndex { get { return "DROP INDEX {0} ON {1}"; } }
public override string RenameColumn { get { return "ALTER TABLE {0} CHANGE {1} {2}"; } }
public override string IsNull { get { return "IFNULL({0},{1})"; } }
public override string ConvertIntegerToOrderableString { get { return "LPAD({0}, 8, '0')"; } }
public override string ConvertDateToOrderableString { get { return "DATE_FORMAT({0}, '%Y%m%d')"; } }
public override bool? SupportsCaseInsensitiveQueries(Database db)
{
@@ -322,7 +322,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
GetQuotedColumnName(foreignKey.ForeignColumns.First()),
GetQuotedTableName(foreignKey.PrimaryTable),
GetQuotedColumnName(foreignKey.PrimaryColumns.First()),
FormatCascade("DELETE", foreignKey.OnDelete),
FormatCascade("DELETE", foreignKey.OnDelete),
FormatCascade("UPDATE", foreignKey.OnUpdate));
}
@@ -331,7 +331,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
var sb = new StringBuilder();
foreach (var column in columns)
{
sb.Append(Format(column) +",\n");
sb.Append(Format(column) + ",\n");
}
return sb.ToString().TrimEnd(",\n");
}
@@ -431,11 +431,11 @@ namespace Umbraco.Core.Persistence.SqlSyntax
return GetSpecialDbType(column.DbType);
}
Type type = column.Type.HasValue
Type type = column.Type.HasValue
? DbTypeMap.ColumnDbTypeMap.First(x => x.Value == column.Type.Value).Key
: column.PropertyType;
if (type == typeof (string))
if (type == typeof(string))
{
var valueOrDefault = column.Size != default(int) ? column.Size : DefaultStringLength;
return string.Format(StringLengthColumnDefinitionFormat, valueOrDefault);
@@ -536,5 +536,9 @@ namespace Umbraco.Core.Persistence.SqlSyntax
public virtual string CreateConstraint { get { return "ALTER TABLE {0} ADD CONSTRAINT {1} {2} ({3})"; } }
public virtual string DeleteConstraint { get { return "ALTER TABLE {0} DROP CONSTRAINT {1}"; } }
public virtual string CreateForeignKeyConstraint { get { return "ALTER TABLE {0} ADD CONSTRAINT {1} FOREIGN KEY ({2}) REFERENCES {3} ({4}){5}{6}"; } }
public virtual string IsNull { get { return "ISNULL({0},{1})"; } }
public virtual string ConvertIntegerToOrderableString { get { return "RIGHT('00000000' + CAST({0} AS varchar(8)),8)"; } }
public virtual string ConvertDateToOrderableString { get { return "CONVERT(varchar, {0}, 102)"; } }
}
}
+21 -19
View File
@@ -231,7 +231,7 @@ namespace Umbraco.Core.Services
public IContent CreateContentWithIdentity(string name, int parentId, string contentTypeAlias, int userId = 0)
{
var contentType = FindContentTypeByAlias(contentTypeAlias);
var content = new Content(name, parentId, contentType);
var content = new Content(name, parentId, contentType);
//NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found
// out that in these 'WithIdentity' methods, the Saving/Saved events were not fired, wtf. Anyways, they're added now.
@@ -485,7 +485,7 @@ namespace Umbraco.Core.Services
[Obsolete("Use the overload with 'long' parameter types instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<IContent> GetPagedChildren(int id, int pageIndex, int pageSize, out int totalChildren,
string orderBy, Direction orderDirection, string filter = "")
string orderBy, Direction orderDirection, bool orderBySystemField = true, string filter = "")
{
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
@@ -499,7 +499,7 @@ namespace Umbraco.Core.Services
query.Where(x => x.ParentId == id);
}
long total;
var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out total, orderBy, orderDirection, filter);
var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out total, orderBy, orderDirection, orderBySystemField, filter);
totalChildren = Convert.ToInt32(total);
return contents;
}
@@ -514,10 +514,11 @@ namespace Umbraco.Core.Services
/// <param name="totalChildren">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
public IEnumerable<IContent> GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren,
string orderBy, Direction orderDirection, string filter = "")
string orderBy, Direction orderDirection, bool orderBySystemField = true, string filter = "")
{
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
@@ -530,7 +531,7 @@ namespace Umbraco.Core.Services
{
query.Where(x => x.ParentId == id);
}
var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, filter);
var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter);
return contents;
}
@@ -538,7 +539,7 @@ namespace Umbraco.Core.Services
[Obsolete("Use the overload with 'long' parameter types instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<IContent> GetPagedDescendants(int id, int pageIndex, int pageSize, out int totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "")
public IEnumerable<IContent> GetPagedDescendants(int id, int pageIndex, int pageSize, out int totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, bool orderBySystemField = true, string filter = "")
{
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
@@ -552,7 +553,7 @@ namespace Umbraco.Core.Services
query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar));
}
long total;
var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out total, orderBy, orderDirection, filter);
var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out total, orderBy, orderDirection, orderBySystemField, filter);
totalChildren = Convert.ToInt32(total);
return contents;
}
@@ -567,9 +568,10 @@ namespace Umbraco.Core.Services
/// <param name="totalChildren">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
public IEnumerable<IContent> GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "")
public IEnumerable<IContent> GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, bool orderBySystemField = true, string filter = "")
{
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
@@ -582,7 +584,7 @@ namespace Umbraco.Core.Services
{
query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar));
}
var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, filter);
var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter);
return contents;
}
@@ -906,7 +908,7 @@ namespace Umbraco.Core.Services
{
var originalPath = content.Path;
if (Trashing.IsRaisedEventCancelled(
if (Trashing.IsRaisedEventCancelled(
new MoveEventArgs<IContent>(evtMsgs, new MoveEventInfo<IContent>(content, originalPath, Constants.System.RecycleBinContent)),
this))
{
@@ -1022,7 +1024,7 @@ namespace Umbraco.Core.Services
/// <returns>True if unpublishing succeeded, otherwise False</returns>
public bool UnPublish(IContent content, int userId = 0)
{
return ((IContentServiceOperations) this).UnPublish(content, userId).Success;
return ((IContentServiceOperations)this).UnPublish(content, userId).Success;
}
/// <summary>
@@ -1143,7 +1145,7 @@ namespace Umbraco.Core.Services
using (new WriteLock(Locker))
{
if (Deleting.IsRaisedEventCancelled(
if (Deleting.IsRaisedEventCancelled(
new DeleteEventArgs<IContent>(content, evtMsgs),
this))
{
@@ -1168,10 +1170,10 @@ namespace Umbraco.Core.Services
{
repository.Delete(content);
uow.Commit();
var args = new DeleteEventArgs<IContent>(content, false, evtMsgs);
Deleted.RaiseEvent(args, this);
//remove any flagged media files
repository.DeleteMediaFiles(args.MediaFilesToDelete);
}
@@ -1350,7 +1352,7 @@ namespace Umbraco.Core.Services
/// <param name="userId">Optional Id of the User deleting the Content</param>
public void MoveToRecycleBin(IContent content, int userId = 0)
{
((IContentServiceOperations) this).MoveToRecycleBin(content, userId);
((IContentServiceOperations)this).MoveToRecycleBin(content, userId);
}
/// <summary>
@@ -1654,7 +1656,7 @@ namespace Umbraco.Core.Services
//TODO: This should not be an inner operation, but if we do this, it cannot raise events and cannot be cancellable!
_publishingStrategy.PublishingFinalized(shouldBePublished, false);
}
Audit(AuditType.Sort, "Sorting content performed by user", userId, 0);
@@ -1902,13 +1904,13 @@ namespace Umbraco.Core.Services
content = newest;
var evtMsgs = EventMessagesFactory.Get();
var published = content.Published ? content : GetPublishedVersion(content.Id); // get the published version
if (published == null)
{
return Attempt.Succeed(new UnPublishStatus(content, UnPublishedStatusType.SuccessAlreadyUnPublished, evtMsgs)); // already unpublished
}
var unpublished = _publishingStrategy.UnPublish(content, userId);
if (unpublished == false) return Attempt.Fail(new UnPublishStatus(content, UnPublishedStatusType.FailedCancelledByEvent, evtMsgs));
@@ -2046,7 +2048,7 @@ namespace Umbraco.Core.Services
if (raiseEvents)
{
if (Saving.IsRaisedEventCancelled(
if (Saving.IsRaisedEventCancelled(
new SaveEventArgs<IContent>(content, evtMsgs),
this))
{
+9 -7
View File
@@ -203,7 +203,7 @@ namespace Umbraco.Core.Services
[Obsolete("Use the overload with 'long' parameter types instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
IEnumerable<IContent> GetPagedChildren(int id, int pageIndex, int pageSize, out int totalRecords,
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "");
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, bool orderBySystemField = true, string filter = "");
/// <summary>
/// Gets a collection of <see cref="IContent"/> objects by Parent Id
@@ -214,15 +214,16 @@ namespace Umbraco.Core.Services
/// <param name="totalRecords">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
IEnumerable<IContent> GetPagedChildren(int id, long pageIndex, int pageSize, out long totalRecords,
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "");
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, bool orderBySystemField = true, string filter = "");
[Obsolete("Use the overload with 'long' parameter types instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
IEnumerable<IContent> GetPagedDescendants(int id, int pageIndex, int pageSize, out int totalRecords,
string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "");
string orderBy = "Path", Direction orderDirection = Direction.Ascending, bool orderBySystemField = true, string filter = "");
/// <summary>
/// Gets a collection of <see cref="IContent"/> objects by Parent Id
@@ -233,11 +234,12 @@ namespace Umbraco.Core.Services
/// <param name="totalRecords">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
IEnumerable<IContent> GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalRecords,
string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "");
string orderBy = "Path", Direction orderDirection = Direction.Ascending, bool orderBySystemField = true, string filter = "");
/// <summary>
/// Gets a collection of an <see cref="IContent"/> objects versions by its Id
/// </summary>
@@ -268,7 +270,7 @@ namespace Umbraco.Core.Services
/// </summary>
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
IEnumerable<IContent> GetContentInRecycleBin();
/// <summary>
/// Saves a single <see cref="IContent"/> object
/// </summary>
@@ -467,7 +469,7 @@ namespace Umbraco.Core.Services
/// <param name="raiseEvents">Optional boolean indicating whether or not to raise save events.</param>
/// <returns>True if publishing succeeded, otherwise False</returns>
Attempt<PublishStatus> SaveAndPublishWithStatus(IContent content, int userId = 0, bool raiseEvents = true);
/// <summary>
/// Permanently deletes an <see cref="IContent"/> object.
/// </summary>
+7 -5
View File
@@ -121,7 +121,7 @@ namespace Umbraco.Core.Services
[Obsolete("Use the overload with 'long' parameter types instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
IEnumerable<IMedia> GetPagedChildren(int id, int pageIndex, int pageSize, out int totalRecords,
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "");
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, bool orderBySystemField = true, string filter = "");
/// <summary>
/// Gets a collection of <see cref="IMedia"/> objects by Parent Id
@@ -132,15 +132,16 @@ namespace Umbraco.Core.Services
/// <param name="totalRecords">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
IEnumerable<IMedia> GetPagedChildren(int id, long pageIndex, int pageSize, out long totalRecords,
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "");
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, bool orderBySystemField = true, string filter = "");
[Obsolete("Use the overload with 'long' parameter types instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
IEnumerable<IMedia> GetPagedDescendants(int id, int pageIndex, int pageSize, out int totalRecords,
string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "");
string orderBy = "Path", Direction orderDirection = Direction.Ascending, bool orderBySystemField = true, string filter = "");
/// <summary>
/// Gets a collection of <see cref="IMedia"/> objects by Parent Id
@@ -151,10 +152,11 @@ namespace Umbraco.Core.Services
/// <param name="totalRecords">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
IEnumerable<IMedia> GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalRecords,
string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "");
string orderBy = "Path", Direction orderDirection = Direction.Ascending, bool orderBySystemField = true, string filter = "");
/// <summary>
/// Gets descendants of a <see cref="IMedia"/> object by its Id
@@ -220,7 +222,7 @@ namespace Umbraco.Core.Services
/// <param name="media">The <see cref="IMedia"/> to delete</param>
/// <param name="userId">Id of the User deleting the Media</param>
void Delete(IMedia media, int userId = 0);
/// <summary>
/// Saves a single <see cref="IMedia"/> object
/// </summary>
+10 -9
View File
@@ -25,7 +25,7 @@ namespace Umbraco.Core.Services
[Obsolete("Use the overload with 'long' parameter types instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
IEnumerable<IMember> GetAll(int pageIndex, int pageSize, out int totalRecords,
string orderBy, Direction orderDirection, string memberTypeAlias = null, string filter = "");
string orderBy, Direction orderDirection, bool orderBySystemField = true, string memberTypeAlias = null, string filter = "");
/// <summary>
/// Gets a list of paged <see cref="IMember"/> objects
@@ -34,14 +34,15 @@ namespace Umbraco.Core.Services
/// <param name="pageIndex">Current page index</param>
/// <param name="pageSize">Size of the page</param>
/// <param name="totalRecords">Total number of records found (out)</param>
/// <param name="orderBy"></param>
/// <param name="orderDirection"></param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="memberTypeAlias"></param>
/// <param name="filter"></param>
/// <param name="filter">Search text filter</param>
/// <returns><see cref="IEnumerable{T}"/></returns>
IEnumerable<IMember> GetAll(long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, string memberTypeAlias = null, string filter = "");
string orderBy, Direction orderDirection, bool orderBySystemField = true, string memberTypeAlias = null, string filter = "");
/// <summary>
/// Creates an <see cref="IMember"/> object without persisting it
/// </summary>
@@ -91,7 +92,7 @@ namespace Umbraco.Core.Services
/// <param name="memberType">MemberType the Member should be based on</param>
/// <returns><see cref="IMember"/></returns>
IMember CreateMemberWithIdentity(string username, string email, string name, IMemberType memberType);
/// <summary>
/// This is simply a helper method which essentially just wraps the MembershipProvider's ChangePassword method
/// </summary>
@@ -115,7 +116,7 @@ namespace Umbraco.Core.Services
/// <param name="id">Id of the Member</param>
/// <returns><c>True</c> if the Member exists otherwise <c>False</c></returns>
bool Exists(int id);
/// <summary>
/// Gets a Member by the unique key
/// </summary>
@@ -160,7 +161,7 @@ namespace Umbraco.Core.Services
/// <param name="ids">Optional list of Member Ids</param>
/// <returns><see cref="IEnumerable{IMember}"/></returns>
IEnumerable<IMember> GetAllMembers(params int[] ids);
/// <summary>
/// Delete Members of the specified MemberType id
/// </summary>
+18 -16
View File
@@ -35,7 +35,7 @@ namespace Umbraco.Core.Services
private readonly EntityXmlSerializer _entitySerializer = new EntityXmlSerializer();
private readonly IDataTypeService _dataTypeService;
private readonly IUserService _userService;
public MediaService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IDataTypeService dataTypeService, IUserService userService)
: base(provider, repositoryFactory, logger, eventMessagesFactory)
{
@@ -395,7 +395,7 @@ namespace Umbraco.Core.Services
[Obsolete("Use the overload with 'long' parameter types instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<IMedia> GetPagedChildren(int id, int pageIndex, int pageSize, out int totalChildren,
string orderBy, Direction orderDirection, string filter = "")
string orderBy, Direction orderDirection, bool orderBySystemField = true, string filter = "")
{
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
@@ -403,9 +403,9 @@ namespace Umbraco.Core.Services
{
var query = Query<IMedia>.Builder;
query.Where(x => x.ParentId == id);
long total;
var medias = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out total, orderBy, orderDirection, filter);
var medias = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out total, orderBy, orderDirection, orderBySystemField, filter);
totalChildren = Convert.ToInt32(total);
return medias;
@@ -421,10 +421,11 @@ namespace Umbraco.Core.Services
/// <param name="totalChildren">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
public IEnumerable<IMedia> GetPagedChildren(int id, long pageIndex, int pageSize, out long totalChildren,
string orderBy, Direction orderDirection, string filter = "")
string orderBy, Direction orderDirection, bool orderBySystemField = true, string filter = "")
{
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
@@ -432,8 +433,8 @@ namespace Umbraco.Core.Services
{
var query = Query<IMedia>.Builder;
query.Where(x => x.ParentId == id);
var medias = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, filter);
var medias = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter);
return medias;
}
@@ -441,7 +442,7 @@ namespace Umbraco.Core.Services
[Obsolete("Use the overload with 'long' parameter types instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<IMedia> GetPagedDescendants(int id, int pageIndex, int pageSize, out int totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "")
public IEnumerable<IMedia> GetPagedDescendants(int id, int pageIndex, int pageSize, out int totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, bool orderBySystemField = true, string filter = "")
{
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
@@ -455,7 +456,7 @@ namespace Umbraco.Core.Services
query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar));
}
long total;
var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out total, orderBy, orderDirection, filter);
var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out total, orderBy, orderDirection, orderBySystemField, filter);
totalChildren = Convert.ToInt32(total);
return contents;
}
@@ -470,9 +471,10 @@ namespace Umbraco.Core.Services
/// <param name="totalChildren">Total records query would return without paging</param>
/// <param name="orderBy">Field to order by</param>
/// <param name="orderDirection">Direction to order by</param>
/// <param name="orderBySystemField">Flag to indicate when ordering by system field</param>
/// <param name="filter">Search text filter</param>
/// <returns>An Enumerable list of <see cref="IContent"/> objects</returns>
public IEnumerable<IMedia> GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, string filter = "")
public IEnumerable<IMedia> GetPagedDescendants(int id, long pageIndex, int pageSize, out long totalChildren, string orderBy = "Path", Direction orderDirection = Direction.Ascending, bool orderBySystemField = true, string filter = "")
{
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
Mandate.ParameterCondition(pageSize > 0, "pageSize");
@@ -485,7 +487,7 @@ namespace Umbraco.Core.Services
{
query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar));
}
var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, filter);
var contents = repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalChildren, orderBy, orderDirection, orderBySystemField, filter);
return contents;
}
@@ -727,7 +729,7 @@ namespace Umbraco.Core.Services
/// <param name="userId">Id of the User deleting the Media</param>
public void MoveToRecycleBin(IMedia media, int userId = 0)
{
((IMediaServiceOperations) this).MoveToRecycleBin(media, userId);
((IMediaServiceOperations)this).MoveToRecycleBin(media, userId);
}
/// <summary>
@@ -744,7 +746,7 @@ namespace Umbraco.Core.Services
//TODO: IT would be much nicer to mass delete all in one trans in the repo level!
var evtMsgs = EventMessagesFactory.Get();
if (Deleting.IsRaisedEventCancelled(
if (Deleting.IsRaisedEventCancelled(
new DeleteEventArgs<IMedia>(media, evtMsgs), this))
{
return OperationStatus.Cancelled(evtMsgs);
@@ -1025,7 +1027,7 @@ namespace Umbraco.Core.Services
((IMediaServiceOperations)this).Delete(media, userId);
}
/// <summary>
/// Permanently deletes versions from an <see cref="IMedia"/> object prior to a specific date.
@@ -1081,7 +1083,7 @@ namespace Umbraco.Core.Services
Audit(AuditType.Delete, "Delete Media by version performed by user", userId, -1);
}
/// <summary>
/// Saves a single <see cref="IMedia"/> object
/// </summary>
@@ -1090,7 +1092,7 @@ namespace Umbraco.Core.Services
/// <param name="raiseEvents">Optional boolean indicating whether or not to raise events.</param>
public void Save(IMedia media, int userId = 0, bool raiseEvents = true)
{
((IMediaServiceOperations)this).Save (media, userId, raiseEvents);
((IMediaServiceOperations)this).Save(media, userId, raiseEvents);
}
/// <summary>
+51 -51
View File
@@ -30,7 +30,7 @@ namespace Umbraco.Core.Services
private readonly EntityXmlSerializer _entitySerializer = new EntityXmlSerializer();
private readonly IDataTypeService _dataTypeService;
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
public MemberService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, ILogger logger, IEventMessagesFactory eventMessagesFactory, IMemberGroupService memberGroupService, IDataTypeService dataTypeService)
: base(provider, repositoryFactory, logger, eventMessagesFactory)
{
@@ -52,7 +52,7 @@ namespace Umbraco.Core.Services
{
using (var repository = RepositoryFactory.CreateMemberTypeRepository(UowProvider.GetUnitOfWork()))
{
var types = repository.GetAll(new int[]{}).Select(x => x.Alias).ToArray();
var types = repository.GetAll(new int[] { }).Select(x => x.Alias).ToArray();
if (types.Any() == false)
{
@@ -289,7 +289,7 @@ namespace Umbraco.Core.Services
throw new ArgumentOutOfRangeException("matchType");
}
return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "Name", Direction.Ascending);
return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "Name", Direction.Ascending, orderBySystemField: true);
}
}
@@ -340,7 +340,7 @@ namespace Umbraco.Core.Services
throw new ArgumentOutOfRangeException("matchType");
}
return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "Email", Direction.Ascending);
return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "Email", Direction.Ascending, orderBySystemField: true);
}
}
@@ -391,7 +391,7 @@ namespace Umbraco.Core.Services
throw new ArgumentOutOfRangeException("matchType");
}
return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "LoginName", Direction.Ascending);
return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, "LoginName", Direction.Ascending, orderBySystemField: true);
}
}
@@ -688,33 +688,33 @@ namespace Umbraco.Core.Services
var uow = UowProvider.GetUnitOfWork();
using (var repository = RepositoryFactory.CreateMemberRepository(uow))
{
return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, "LoginName", Direction.Ascending);
return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, "LoginName", Direction.Ascending, orderBySystemField: true);
}
}
[Obsolete("Use the overload with 'long' parameter types instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<IMember> GetAll(int pageIndex, int pageSize, out int totalRecords,
string orderBy, Direction orderDirection, string memberTypeAlias = null, string filter = "")
string orderBy, Direction orderDirection, bool orderBySystemField = true, string memberTypeAlias = null, string filter = "")
{
long total;
var result = GetAll(Convert.ToInt64(pageIndex), pageSize, out total, orderBy, orderDirection, memberTypeAlias, filter);
var result = GetAll(Convert.ToInt64(pageIndex), pageSize, out total, orderBy, orderDirection, orderBySystemField, memberTypeAlias, filter);
totalRecords = Convert.ToInt32(total);
return result;
}
public IEnumerable<IMember> GetAll(long pageIndex, int pageSize, out long totalRecords,
string orderBy, Direction orderDirection, string memberTypeAlias = null, string filter = "")
string orderBy, Direction orderDirection, bool orderBySystemField = true, string memberTypeAlias = null, string filter = "")
{
var uow = UowProvider.GetUnitOfWork();
using (var repository = RepositoryFactory.CreateMemberRepository(uow))
{
if (memberTypeAlias == null)
{
return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filter);
return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, orderBySystemField, filter);
}
var query = new Query<IMember>().Where(x => x.ContentTypeAlias == memberTypeAlias);
return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filter);
return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, orderBySystemField, filter);
}
}
@@ -1253,52 +1253,52 @@ namespace Umbraco.Core.Services
var memType = new MemberType(-1);
var propGroup = new PropertyGroup
{
Name = "Membership",
Id = --identity
};
{
Name = "Membership",
Id = --identity
};
propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext, Constants.Conventions.Member.Comments)
{
Name = Constants.Conventions.Member.CommentsLabel,
SortOrder = 0,
Id = --identity,
Key = identity.ToGuid()
});
{
Name = Constants.Conventions.Member.CommentsLabel,
SortOrder = 0,
Id = --identity,
Key = identity.ToGuid()
});
propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer, Constants.Conventions.Member.IsApproved)
{
Name = Constants.Conventions.Member.IsApprovedLabel,
SortOrder = 3,
Id = --identity,
Key = identity.ToGuid()
});
{
Name = Constants.Conventions.Member.IsApprovedLabel,
SortOrder = 3,
Id = --identity,
Key = identity.ToGuid()
});
propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer, Constants.Conventions.Member.IsLockedOut)
{
Name = Constants.Conventions.Member.IsLockedOutLabel,
SortOrder = 4,
Id = --identity,
Key = identity.ToGuid()
});
{
Name = Constants.Conventions.Member.IsLockedOutLabel,
SortOrder = 4,
Id = --identity,
Key = identity.ToGuid()
});
propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, Constants.Conventions.Member.LastLockoutDate)
{
Name = Constants.Conventions.Member.LastLockoutDateLabel,
SortOrder = 5,
Id = --identity,
Key = identity.ToGuid()
});
{
Name = Constants.Conventions.Member.LastLockoutDateLabel,
SortOrder = 5,
Id = --identity,
Key = identity.ToGuid()
});
propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, Constants.Conventions.Member.LastLoginDate)
{
Name = Constants.Conventions.Member.LastLoginDateLabel,
SortOrder = 6,
Id = --identity,
Key = identity.ToGuid()
});
{
Name = Constants.Conventions.Member.LastLoginDateLabel,
SortOrder = 6,
Id = --identity,
Key = identity.ToGuid()
});
propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, Constants.Conventions.Member.LastPasswordChangeDate)
{
Name = Constants.Conventions.Member.LastPasswordChangeDateLabel,
SortOrder = 7,
Id = --identity,
Key = identity.ToGuid()
});
{
Name = Constants.Conventions.Member.LastPasswordChangeDateLabel,
SortOrder = 7,
Id = --identity,
Key = identity.ToGuid()
});
memType.PropertyGroups.Add(propGroup);
@@ -72,7 +72,7 @@ namespace Umbraco.Tests.Persistence.Repositories
//create 100 non published
for (var i = 0; i < 100; i++)
{
{
var c1 = MockedContent.CreateSimpleContent(contentType1);
repository.AddOrUpdate(c1);
allCreated.Add(c1);
@@ -176,7 +176,7 @@ namespace Umbraco.Tests.Persistence.Repositories
for (var i = 0; i < 30; i++)
{
//These will be non-published so shouldn't show up
var c1 = MockedContent.CreateSimpleContent(contentType1);
var c1 = MockedContent.CreateSimpleContent(contentType1);
repository.AddOrUpdate(c1);
allCreated.Add(c1);
}
@@ -275,7 +275,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Assert
Assert.That(contentType.HasIdentity, Is.True);
Assert.That(textpage.HasIdentity, Is.True);
}
}
@@ -299,7 +299,7 @@ namespace Umbraco.Tests.Persistence.Repositories
Content textpage = MockedContent.CreateSimpleContent(contentType);
// Act
contentTypeRepository.AddOrUpdate(contentType);
repository.AddOrUpdate(textpage);
unitOfWork.Commit();
@@ -520,7 +520,7 @@ namespace Umbraco.Tests.Persistence.Repositories
var unitOfWork = provider.GetUnitOfWork();
ContentTypeRepository contentTypeRepository;
using (var repository = CreateRepository(unitOfWork, out contentTypeRepository))
{
{
var result = repository.GetAll().ToArray();
foreach (var content in result)
{
@@ -555,7 +555,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Act
var query = Query<IContent>.Builder.Where(x => x.Level == 2);
long totalRecords;
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending);
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, orderBySystemField: true);
// Assert
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
@@ -576,7 +576,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Act
var query = Query<IContent>.Builder.Where(x => x.Level == 2);
long totalRecords;
var result = repository.GetPagedResultsByQuery(query, 1, 1, out totalRecords, "Name", Direction.Ascending);
var result = repository.GetPagedResultsByQuery(query, 1, 1, out totalRecords, "Name", Direction.Ascending, orderBySystemField: true);
// Assert
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
@@ -597,7 +597,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Act
var query = Query<IContent>.Builder.Where(x => x.Level == 2);
long totalRecords;
var result = repository.GetPagedResultsByQuery(query, 0, 2, out totalRecords, "Name", Direction.Ascending);
var result = repository.GetPagedResultsByQuery(query, 0, 2, out totalRecords, "Name", Direction.Ascending, orderBySystemField: true);
// Assert
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
@@ -618,7 +618,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Act
var query = Query<IContent>.Builder.Where(x => x.Level == 2);
long totalRecords;
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Descending);
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Descending, orderBySystemField: true);
// Assert
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
@@ -639,7 +639,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Act
var query = Query<IContent>.Builder.Where(x => x.Level == 2);
long totalRecords;
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, "Page 2");
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, true, "Page 2");
// Assert
Assert.That(totalRecords, Is.EqualTo(1));
@@ -660,7 +660,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Act
var query = Query<IContent>.Builder.Where(x => x.Level == 2);
long totalRecords;
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, "Page");
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, true, "Page");
// Assert
Assert.That(totalRecords, Is.EqualTo(2));
@@ -27,7 +27,7 @@ namespace Umbraco.Tests.Persistence.Repositories
[SetUp]
public override void Initialize()
{
{
base.Initialize();
CreateTestData();
@@ -51,12 +51,12 @@ namespace Umbraco.Tests.Persistence.Repositories
{
var mediaType = mediaTypeRepository.Get(1032);
for (var i = 0; i < 100; i++)
{
var image = MockedMedia.CreateMediaImage(mediaType, -1);
repository.AddOrUpdate(image);
}
}
unitOfWork.Commit();
//delete all xml
@@ -81,7 +81,7 @@ namespace Umbraco.Tests.Persistence.Repositories
var imageMediaType = mediaTypeRepository.Get(1032);
var fileMediaType = mediaTypeRepository.Get(1033);
var folderMediaType = mediaTypeRepository.Get(1031);
for (var i = 0; i < 30; i++)
{
var image = MockedMedia.CreateMediaImage(imageMediaType, -1);
@@ -103,12 +103,12 @@ namespace Umbraco.Tests.Persistence.Repositories
unitOfWork.Database.Execute("DELETE FROM cmsContentXml");
Assert.AreEqual(0, unitOfWork.Database.ExecuteScalar<int>("SELECT COUNT(*) FROM cmsContentXml"));
repository.RebuildXmlStructures(media => new XElement("test"), 10, contentTypeIds: new[] {1032, 1033});
repository.RebuildXmlStructures(media => new XElement("test"), 10, contentTypeIds: new[] { 1032, 1033 });
Assert.AreEqual(62, unitOfWork.Database.ExecuteScalar<int>("SELECT COUNT(*) FROM cmsContentXml"));
}
}
[Test]
public void Can_Perform_Add_On_MediaRepository()
{
@@ -207,7 +207,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Act
var media = repository.Get(NodeDto.NodeIdSeed + 1);
bool dirty = ((ICanBeDirty) media).IsDirty();
bool dirty = ((ICanBeDirty)media).IsDirty();
// Assert
Assert.That(dirty, Is.False);
@@ -319,7 +319,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Act
var query = Query<IMedia>.Builder.Where(x => x.Level == 2);
long totalRecords;
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending);
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending, orderBySystemField: true);
// Assert
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
@@ -340,7 +340,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Act
var query = Query<IMedia>.Builder.Where(x => x.Level == 2);
long totalRecords;
var result = repository.GetPagedResultsByQuery(query, 1, 1, out totalRecords, "SortOrder", Direction.Ascending);
var result = repository.GetPagedResultsByQuery(query, 1, 1, out totalRecords, "SortOrder", Direction.Ascending, orderBySystemField: true);
// Assert
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
@@ -361,7 +361,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Act
var query = Query<IMedia>.Builder.Where(x => x.Level == 2);
long totalRecords;
var result = repository.GetPagedResultsByQuery(query, 0, 2, out totalRecords, "SortOrder", Direction.Ascending);
var result = repository.GetPagedResultsByQuery(query, 0, 2, out totalRecords, "SortOrder", Direction.Ascending, orderBySystemField: true);
// Assert
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
@@ -382,7 +382,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Act
var query = Query<IMedia>.Builder.Where(x => x.Level == 2);
long totalRecords;
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Descending);
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Descending, orderBySystemField: true);
// Assert
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
@@ -403,7 +403,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Act
var query = Query<IMedia>.Builder.Where(x => x.Level == 2);
long totalRecords;
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending);
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "Name", Direction.Ascending, orderBySystemField: true);
// Assert
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
@@ -424,7 +424,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Act
var query = Query<IMedia>.Builder.Where(x => x.Level == 2);
long totalRecords;
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending, "File");
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending, true, "File");
// Assert
Assert.That(totalRecords, Is.EqualTo(1));
@@ -445,7 +445,7 @@ namespace Umbraco.Tests.Persistence.Repositories
// Act
var query = Query<IMedia>.Builder.Where(x => x.Level == 2);
long totalRecords;
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending, "Test");
var result = repository.GetPagedResultsByQuery(query, 0, 1, out totalRecords, "SortOrder", Direction.Ascending, true, "Test");
// Assert
Assert.That(totalRecords, Is.EqualTo(2));
@@ -20,33 +20,33 @@ using Version = Lucene.Net.Util.Version;
namespace Umbraco.Tests.UmbracoExamine
{
/// <summary>
/// Used internally by test classes to initialize a new index from the template
/// </summary>
internal static class IndexInitializer
{
public static UmbracoContentIndexer GetUmbracoIndexer(
Directory luceneDir,
Analyzer analyzer = null,
IDataService dataService = null,
IContentService contentService = null,
IMediaService mediaService = null,
IDataTypeService dataTypeService = null,
IMemberService memberService = null,
IUserService userService = null)
{
/// <summary>
/// Used internally by test classes to initialize a new index from the template
/// </summary>
internal static class IndexInitializer
{
public static UmbracoContentIndexer GetUmbracoIndexer(
Directory luceneDir,
Analyzer analyzer = null,
IDataService dataService = null,
IContentService contentService = null,
IMediaService mediaService = null,
IDataTypeService dataTypeService = null,
IMemberService memberService = null,
IUserService userService = null)
{
if (dataService == null)
{
dataService = new TestDataService();
}
if (contentService == null)
{
if (contentService == null)
{
contentService = Mock.Of<IContentService>();
}
if (userService == null)
{
userService = Mock.Of<IUserService>(x => x.GetProfileById(It.IsAny<int>()) == Mock.Of<IProfile>(p => p.Id == (object)0 && p.Name == "admin"));
}
}
if (userService == null)
{
userService = Mock.Of<IUserService>(x => x.GetProfileById(It.IsAny<int>()) == Mock.Of<IProfile>(p => p.Id == (object)0 && p.Name == "admin"));
}
if (mediaService == null)
{
long totalRecs;
@@ -56,25 +56,25 @@ namespace Umbraco.Tests.UmbracoExamine
.Elements()
.Select(x => Mock.Of<IMedia>(
m =>
m.Id == (int) x.Attribute("id") &&
m.ParentId == (int) x.Attribute("parentID") &&
m.Level == (int) x.Attribute("level") &&
m.Id == (int)x.Attribute("id") &&
m.ParentId == (int)x.Attribute("parentID") &&
m.Level == (int)x.Attribute("level") &&
m.CreatorId == 0 &&
m.SortOrder == (int) x.Attribute("sortOrder") &&
m.CreateDate == (DateTime) x.Attribute("createDate") &&
m.UpdateDate == (DateTime) x.Attribute("updateDate") &&
m.Name == (string) x.Attribute("nodeName") &&
m.Path == (string) x.Attribute("path") &&
m.SortOrder == (int)x.Attribute("sortOrder") &&
m.CreateDate == (DateTime)x.Attribute("createDate") &&
m.UpdateDate == (DateTime)x.Attribute("updateDate") &&
m.Name == (string)x.Attribute("nodeName") &&
m.Path == (string)x.Attribute("path") &&
m.Properties == new PropertyCollection() &&
m.ContentType == Mock.Of<IMediaType>(mt =>
mt.Alias == (string) x.Attribute("nodeTypeAlias") &&
mt.Id == (int) x.Attribute("nodeType"))))
mt.Alias == (string)x.Attribute("nodeTypeAlias") &&
mt.Id == (int)x.Attribute("nodeType"))))
.ToArray();
mediaService = Mock.Of<IMediaService>(
x => x.GetPagedDescendants(
It.IsAny<int>(), It.IsAny<long>(), It.IsAny<int>(), out totalRecs, It.IsAny<string>(), It.IsAny<Direction>(), It.IsAny<string>())
It.IsAny<int>(), It.IsAny<long>(), It.IsAny<int>(), out totalRecs, It.IsAny<string>(), It.IsAny<Direction>(), It.IsAny<bool>(), It.IsAny<string>())
==
allRecs);
}
@@ -82,7 +82,7 @@ namespace Umbraco.Tests.UmbracoExamine
{
dataTypeService = Mock.Of<IDataTypeService>();
}
if (memberService == null)
{
memberService = Mock.Of<IMemberService>();
@@ -93,51 +93,51 @@ namespace Umbraco.Tests.UmbracoExamine
analyzer = new StandardAnalyzer(Version.LUCENE_29);
}
var indexSet = new IndexSet();
var indexSet = new IndexSet();
var indexCriteria = indexSet.ToIndexCriteria(dataService, UmbracoContentIndexer.IndexFieldPolicies);
var i = new UmbracoContentIndexer(indexCriteria,
luceneDir, //custom lucene directory
dataService,
contentService,
mediaService,
dataTypeService,
userService,
analyzer,
false);
var i = new UmbracoContentIndexer(indexCriteria,
luceneDir, //custom lucene directory
dataService,
contentService,
mediaService,
dataTypeService,
userService,
analyzer,
false);
//i.IndexSecondsInterval = 1;
//i.IndexSecondsInterval = 1;
i.IndexingError += IndexingError;
i.IndexingError += IndexingError;
return i;
}
return i;
}
public static UmbracoExamineSearcher GetUmbracoSearcher(Directory luceneDir, Analyzer analyzer = null)
{
{
if (analyzer == null)
{
analyzer = new StandardAnalyzer(Version.LUCENE_29);
}
return new UmbracoExamineSearcher(luceneDir, analyzer);
}
public static LuceneSearcher GetLuceneSearcher(Directory luceneDir)
{
return new LuceneSearcher(luceneDir, new StandardAnalyzer(Version.LUCENE_29));
}
public static MultiIndexSearcher GetMultiSearcher(Directory pdfDir, Directory simpleDir, Directory conventionDir, Directory cwsDir)
{
var i = new MultiIndexSearcher(new[] { pdfDir, simpleDir, conventionDir, cwsDir }, new StandardAnalyzer(Version.LUCENE_29));
return i;
}
}
public static LuceneSearcher GetLuceneSearcher(Directory luceneDir)
{
return new LuceneSearcher(luceneDir, new StandardAnalyzer(Version.LUCENE_29));
}
public static MultiIndexSearcher GetMultiSearcher(Directory pdfDir, Directory simpleDir, Directory conventionDir, Directory cwsDir)
{
var i = new MultiIndexSearcher(new[] { pdfDir, simpleDir, conventionDir, cwsDir }, new StandardAnalyzer(Version.LUCENE_29));
return i;
}
internal static void IndexingError(object sender, IndexingErrorEventArgs e)
{
throw new ApplicationException(e.Message, e.InnerException);
}
internal static void IndexingError(object sender, IndexingErrorEventArgs e)
{
throw new ApplicationException(e.Message, e.InnerException);
}
}
}
}
@@ -1,71 +1,71 @@
(function() {
'use strict';
function TableDirective() {
function link(scope, el, attr, ctrl) {
scope.clickItem = function(item, $event) {
if(scope.onClick) {
scope.onClick(item);
$event.stopPropagation();
}
};
scope.selectItem = function(item, $index, $event) {
if(scope.onSelect) {
scope.onSelect(item, $index, $event);
$event.stopPropagation();
}
};
scope.selectAll = function($event) {
if(scope.onSelectAll) {
scope.onSelectAll($event);
}
};
scope.isSelectedAll = function() {
if(scope.onSelectedAll && scope.items && scope.items.length > 0) {
return scope.onSelectedAll();
}
};
scope.isSortDirection = function (col, direction) {
if (scope.onSortingDirection) {
return scope.onSortingDirection(col, direction);
}
};
scope.sort = function(field, allow) {
if(scope.onSort) {
scope.onSort(field, allow);
}
};
}
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/umb-table.html',
scope: {
items: '=',
itemProperties: '=',
allowSelectAll: '=',
onSelect: '=',
onClick: '=',
onSelectAll: '=',
onSelectedAll: '=',
onSortingDirection: '=',
onSort: '='
},
link: link
};
return directive;
}
angular.module('umbraco.directives').directive('umbTable', TableDirective);
})();
(function () {
'use strict';
function TableDirective() {
function link(scope, el, attr, ctrl) {
scope.clickItem = function (item, $event) {
if (scope.onClick) {
scope.onClick(item);
$event.stopPropagation();
}
};
scope.selectItem = function (item, $index, $event) {
if (scope.onSelect) {
scope.onSelect(item, $index, $event);
$event.stopPropagation();
}
};
scope.selectAll = function ($event) {
if (scope.onSelectAll) {
scope.onSelectAll($event);
}
};
scope.isSelectedAll = function () {
if (scope.onSelectedAll && scope.items && scope.items.length > 0) {
return scope.onSelectedAll();
}
};
scope.isSortDirection = function (col, direction) {
if (scope.onSortingDirection) {
return scope.onSortingDirection(col, direction);
}
};
scope.sort = function (field, allow, isSystem) {
if (scope.onSort) {
scope.onSort(field, allow, isSystem);
}
};
}
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/umb-table.html',
scope: {
items: '=',
itemProperties: '=',
allowSelectAll: '=',
onSelect: '=',
onClick: '=',
onSelectAll: '=',
onSelectedAll: '=',
onSortingDirection: '=',
onSort: '='
},
link: link
};
return directive;
}
angular.module('umbraco.directives').directive('umbTable', TableDirective);
})();
File diff suppressed because it is too large Load Diff
@@ -4,470 +4,472 @@
* @description Loads in data for media
**/
function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
/** internal method process the saving of data and post processing the result */
function saveMediaItem(content, action, files) {
return umbRequestHelper.postSaveContent({
restApiUrl: umbRequestHelper.getApiUrl(
/** internal method process the saving of data and post processing the result */
function saveMediaItem(content, action, files) {
return umbRequestHelper.postSaveContent({
restApiUrl: umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"PostSave"),
content: content,
action: action,
files: files,
dataFormatter: function (c, a) {
return umbDataFormatter.formatMediaPostData(c, a);
}
});
}
content: content,
action: action,
files: files,
dataFormatter: function (c, a) {
return umbDataFormatter.formatMediaPostData(c, a);
}
});
}
return {
getRecycleBin: function () {
return umbRequestHelper.resourcePromise(
return {
getRecycleBin: function () {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"GetRecycleBin")),
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"GetRecycleBin")),
'Failed to retrieve data for media recycle bin');
},
},
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#sort
* @methodOf umbraco.resources.mediaResource
*
* @description
* Sorts all children below a given parent node id, based on a collection of node-ids
*
* ##usage
* <pre>
* var ids = [123,34533,2334,23434];
* mediaResource.sort({ sortedIds: ids })
* .then(function() {
* $scope.complete = true;
* });
* </pre>
* @param {Object} args arguments object
* @param {Int} args.parentId the ID of the parent node
* @param {Array} options.sortedIds array of node IDs as they should be sorted
* @returns {Promise} resourcePromise object.
*
*/
sort: function (args) {
if (!args) {
throw "args cannot be null";
}
if (!args.parentId) {
throw "args.parentId cannot be null";
}
if (!args.sortedIds) {
throw "args.sortedIds cannot be null";
}
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#sort
* @methodOf umbraco.resources.mediaResource
*
* @description
* Sorts all children below a given parent node id, based on a collection of node-ids
*
* ##usage
* <pre>
* var ids = [123,34533,2334,23434];
* mediaResource.sort({ sortedIds: ids })
* .then(function() {
* $scope.complete = true;
* });
* </pre>
* @param {Object} args arguments object
* @param {Int} args.parentId the ID of the parent node
* @param {Array} options.sortedIds array of node IDs as they should be sorted
* @returns {Promise} resourcePromise object.
*
*/
sort: function (args) {
if (!args) {
throw "args cannot be null";
}
if (!args.parentId) {
throw "args.parentId cannot be null";
}
if (!args.sortedIds) {
throw "args.sortedIds cannot be null";
}
return umbRequestHelper.resourcePromise(
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("mediaApiBaseUrl", "PostSort"),
{
parentId: args.parentId,
idSortOrder: args.sortedIds
}),
{
parentId: args.parentId,
idSortOrder: args.sortedIds
}),
'Failed to sort media');
},
},
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#move
* @methodOf umbraco.resources.mediaResource
*
* @description
* Moves a node underneath a new parentId
*
* ##usage
* <pre>
* mediaResource.move({ parentId: 1244, id: 123 })
* .then(function() {
* alert("node was moved");
* }, function(err){
* alert("node didnt move:" + err.data.Message);
* });
* </pre>
* @param {Object} args arguments object
* @param {Int} args.idd the ID of the node to move
* @param {Int} args.parentId the ID of the parent node to move to
* @returns {Promise} resourcePromise object.
*
*/
move: function (args) {
if (!args) {
throw "args cannot be null";
}
if (!args.parentId) {
throw "args.parentId cannot be null";
}
if (!args.id) {
throw "args.id cannot be null";
}
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#move
* @methodOf umbraco.resources.mediaResource
*
* @description
* Moves a node underneath a new parentId
*
* ##usage
* <pre>
* mediaResource.move({ parentId: 1244, id: 123 })
* .then(function() {
* alert("node was moved");
* }, function(err){
* alert("node didnt move:" + err.data.Message);
* });
* </pre>
* @param {Object} args arguments object
* @param {Int} args.idd the ID of the node to move
* @param {Int} args.parentId the ID of the parent node to move to
* @returns {Promise} resourcePromise object.
*
*/
move: function (args) {
if (!args) {
throw "args cannot be null";
}
if (!args.parentId) {
throw "args.parentId cannot be null";
}
if (!args.id) {
throw "args.id cannot be null";
}
return umbRequestHelper.resourcePromise(
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("mediaApiBaseUrl", "PostMove"),
{
parentId: args.parentId,
id: args.id
}),
{
parentId: args.parentId,
id: args.id
}),
'Failed to move media');
},
},
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#getById
* @methodOf umbraco.resources.mediaResource
*
* @description
* Gets a media item with a given id
*
* ##usage
* <pre>
* mediaResource.getById(1234)
* .then(function(media) {
* var myMedia = media;
* alert('its here!');
* });
* </pre>
*
* @param {Int} id id of media item to return
* @returns {Promise} resourcePromise object containing the media item.
*
*/
getById: function (id) {
return umbRequestHelper.resourcePromise(
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#getById
* @methodOf umbraco.resources.mediaResource
*
* @description
* Gets a media item with a given id
*
* ##usage
* <pre>
* mediaResource.getById(1234)
* .then(function(media) {
* var myMedia = media;
* alert('its here!');
* });
* </pre>
*
* @param {Int} id id of media item to return
* @returns {Promise} resourcePromise object containing the media item.
*
*/
getById: function (id) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"GetById",
[{ id: id }])),
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"GetById",
[{ id: id }])),
'Failed to retrieve data for media id ' + id);
},
},
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#deleteById
* @methodOf umbraco.resources.mediaResource
*
* @description
* Deletes a media item with a given id
*
* ##usage
* <pre>
* mediaResource.deleteById(1234)
* .then(function() {
* alert('its gone!');
* });
* </pre>
*
* @param {Int} id id of media item to delete
* @returns {Promise} resourcePromise object.
*
*/
deleteById: function(id) {
return umbRequestHelper.resourcePromise(
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#deleteById
* @methodOf umbraco.resources.mediaResource
*
* @description
* Deletes a media item with a given id
*
* ##usage
* <pre>
* mediaResource.deleteById(1234)
* .then(function() {
* alert('its gone!');
* });
* </pre>
*
* @param {Int} id id of media item to delete
* @returns {Promise} resourcePromise object.
*
*/
deleteById: function (id) {
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"DeleteById",
[{ id: id }])),
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"DeleteById",
[{ id: id }])),
'Failed to delete item ' + id);
},
},
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#getByIds
* @methodOf umbraco.resources.mediaResource
*
* @description
* Gets an array of media items, given a collection of ids
*
* ##usage
* <pre>
* mediaResource.getByIds( [1234,2526,28262])
* .then(function(mediaArray) {
* var myDoc = contentArray;
* alert('they are here!');
* });
* </pre>
*
* @param {Array} ids ids of media items to return as an array
* @returns {Promise} resourcePromise object containing the media items array.
*
*/
getByIds: function (ids) {
var idQuery = "";
_.each(ids, function(item) {
idQuery += "ids=" + item + "&";
});
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#getByIds
* @methodOf umbraco.resources.mediaResource
*
* @description
* Gets an array of media items, given a collection of ids
*
* ##usage
* <pre>
* mediaResource.getByIds( [1234,2526,28262])
* .then(function(mediaArray) {
* var myDoc = contentArray;
* alert('they are here!');
* });
* </pre>
*
* @param {Array} ids ids of media items to return as an array
* @returns {Promise} resourcePromise object containing the media items array.
*
*/
getByIds: function (ids) {
return umbRequestHelper.resourcePromise(
var idQuery = "";
_.each(ids, function (item) {
idQuery += "ids=" + item + "&";
});
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"GetByIds",
idQuery)),
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"GetByIds",
idQuery)),
'Failed to retrieve data for media ids ' + ids);
},
},
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#getScaffold
* @methodOf umbraco.resources.mediaResource
*
* @description
* Returns a scaffold of an empty media item, given the id of the media item to place it underneath and the media type alias.
*
* - Parent Id must be provided so umbraco knows where to store the media
* - Media Type alias must be provided so umbraco knows which properties to put on the media scaffold
*
* The scaffold is used to build editors for media that has not yet been populated with data.
*
* ##usage
* <pre>
* mediaResource.getScaffold(1234, 'folder')
* .then(function(scaffold) {
* var myDoc = scaffold;
* myDoc.name = "My new media item";
*
* mediaResource.save(myDoc, true)
* .then(function(media){
* alert("Retrieved, updated and saved again");
* });
* });
* </pre>
*
* @param {Int} parentId id of media item to return
* @param {String} alias mediatype alias to base the scaffold on
* @returns {Promise} resourcePromise object containing the media scaffold.
*
*/
getScaffold: function (parentId, alias) {
return umbRequestHelper.resourcePromise(
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#getScaffold
* @methodOf umbraco.resources.mediaResource
*
* @description
* Returns a scaffold of an empty media item, given the id of the media item to place it underneath and the media type alias.
*
* - Parent Id must be provided so umbraco knows where to store the media
* - Media Type alias must be provided so umbraco knows which properties to put on the media scaffold
*
* The scaffold is used to build editors for media that has not yet been populated with data.
*
* ##usage
* <pre>
* mediaResource.getScaffold(1234, 'folder')
* .then(function(scaffold) {
* var myDoc = scaffold;
* myDoc.name = "My new media item";
*
* mediaResource.save(myDoc, true)
* .then(function(media){
* alert("Retrieved, updated and saved again");
* });
* });
* </pre>
*
* @param {Int} parentId id of media item to return
* @param {String} alias mediatype alias to base the scaffold on
* @returns {Promise} resourcePromise object containing the media scaffold.
*
*/
getScaffold: function (parentId, alias) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"GetEmpty",
[{ contentTypeAlias: alias }, { parentId: parentId }])),
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"GetEmpty",
[{ contentTypeAlias: alias }, { parentId: parentId }])),
'Failed to retrieve data for empty media item type ' + alias);
},
},
rootMedia: function () {
return umbRequestHelper.resourcePromise(
rootMedia: function () {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"GetRootMedia")),
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"GetRootMedia")),
'Failed to retrieve data for root media');
},
},
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#getChildren
* @methodOf umbraco.resources.mediaResource
*
* @description
* Gets children of a media item with a given id
*
* ##usage
* <pre>
* mediaResource.getChildren(1234, {pageSize: 10, pageNumber: 2})
* .then(function(contentArray) {
* var children = contentArray;
* alert('they are here!');
* });
* </pre>
*
* @param {Int} parentid id of content item to return children of
* @param {Object} options optional options object
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 0
* @param {Int} options.pageNumber if paging data, current page index, default = 0
* @param {String} options.filter if provided, query will only return those with names matching the filter
* @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Ascending`
* @param {String} options.orderBy property to order items by, default: `SortOrder`
* @returns {Promise} resourcePromise object containing an array of content items.
*
*/
getChildren: function (parentId, options) {
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#getChildren
* @methodOf umbraco.resources.mediaResource
*
* @description
* Gets children of a media item with a given id
*
* ##usage
* <pre>
* mediaResource.getChildren(1234, {pageSize: 10, pageNumber: 2})
* .then(function(contentArray) {
* var children = contentArray;
* alert('they are here!');
* });
* </pre>
*
* @param {Int} parentid id of content item to return children of
* @param {Object} options optional options object
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 0
* @param {Int} options.pageNumber if paging data, current page index, default = 0
* @param {String} options.filter if provided, query will only return those with names matching the filter
* @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Ascending`
* @param {String} options.orderBy property to order items by, default: `SortOrder`
* @returns {Promise} resourcePromise object containing an array of content items.
*
*/
getChildren: function (parentId, options) {
var defaults = {
pageSize: 0,
pageNumber: 0,
filter: '',
orderDirection: "Ascending",
orderBy: "SortOrder"
};
if (options === undefined) {
options = {};
}
//overwrite the defaults if there are any specified
angular.extend(defaults, options);
//now copy back to the options we will use
options = defaults;
//change asc/desct
if (options.orderDirection === "asc") {
options.orderDirection = "Ascending";
}
else if (options.orderDirection === "desc") {
options.orderDirection = "Descending";
}
var defaults = {
pageSize: 0,
pageNumber: 0,
filter: '',
orderDirection: "Ascending",
orderBy: "SortOrder",
orderBySystemField: true
};
if (options === undefined) {
options = {};
}
//overwrite the defaults if there are any specified
angular.extend(defaults, options);
//now copy back to the options we will use
options = defaults;
//change asc/desct
if (options.orderDirection === "asc") {
options.orderDirection = "Ascending";
}
else if (options.orderDirection === "desc") {
options.orderDirection = "Descending";
}
return umbRequestHelper.resourcePromise(
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"GetChildren",
[
{ id: parentId },
{ pageNumber: options.pageNumber },
{ pageSize: options.pageSize },
{ orderBy: options.orderBy },
{ orderDirection: options.orderDirection },
{ filter: options.filter }
])),
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"GetChildren",
[
{ id: parentId },
{ pageNumber: options.pageNumber },
{ pageSize: options.pageSize },
{ orderBy: options.orderBy },
{ orderDirection: options.orderDirection },
{ orderBySystemField: options.orderBySystemField },
{ filter: options.filter }
])),
'Failed to retrieve children for media item ' + parentId);
},
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#save
* @methodOf umbraco.resources.mediaResource
*
* @description
* Saves changes made to a media item, if the media item is new, the isNew paramater must be passed to force creation
* if the media item needs to have files attached, they must be provided as the files param and passed separately
*
*
* ##usage
* <pre>
* mediaResource.getById(1234)
* .then(function(media) {
* media.name = "I want a new name!";
* mediaResource.save(media, false)
* .then(function(media){
* alert("Retrieved, updated and saved again");
* });
* });
* </pre>
*
* @param {Object} media The media item object with changes applied
* @param {Bool} isNew set to true to create a new item or to update an existing
* @param {Array} files collection of files for the media item
* @returns {Promise} resourcePromise object containing the saved media item.
*
*/
save: function (media, isNew, files) {
return saveMediaItem(media, "save" + (isNew ? "New" : ""), files);
},
},
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#addFolder
* @methodOf umbraco.resources.mediaResource
*
* @description
* Shorthand for adding a media item of the type "Folder" under a given parent ID
*
* ##usage
* <pre>
* mediaResource.addFolder("My gallery", 1234)
* .then(function(folder) {
* alert('New folder');
* });
* </pre>
*
* @param {string} name Name of the folder to create
* @param {int} parentId Id of the media item to create the folder underneath
* @returns {Promise} resourcePromise object.
*
*/
addFolder: function(name, parentId){
return umbRequestHelper.resourcePromise(
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#save
* @methodOf umbraco.resources.mediaResource
*
* @description
* Saves changes made to a media item, if the media item is new, the isNew paramater must be passed to force creation
* if the media item needs to have files attached, they must be provided as the files param and passed separately
*
*
* ##usage
* <pre>
* mediaResource.getById(1234)
* .then(function(media) {
* media.name = "I want a new name!";
* mediaResource.save(media, false)
* .then(function(media){
* alert("Retrieved, updated and saved again");
* });
* });
* </pre>
*
* @param {Object} media The media item object with changes applied
* @param {Bool} isNew set to true to create a new item or to update an existing
* @param {Array} files collection of files for the media item
* @returns {Promise} resourcePromise object containing the saved media item.
*
*/
save: function (media, isNew, files) {
return saveMediaItem(media, "save" + (isNew ? "New" : ""), files);
},
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#addFolder
* @methodOf umbraco.resources.mediaResource
*
* @description
* Shorthand for adding a media item of the type "Folder" under a given parent ID
*
* ##usage
* <pre>
* mediaResource.addFolder("My gallery", 1234)
* .then(function(folder) {
* alert('New folder');
* });
* </pre>
*
* @param {string} name Name of the folder to create
* @param {int} parentId Id of the media item to create the folder underneath
* @returns {Promise} resourcePromise object.
*
*/
addFolder: function (name, parentId) {
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper
.getApiUrl("mediaApiBaseUrl", "PostAddFolder"),
{
name: name,
parentId: parentId
}),
.getApiUrl("mediaApiBaseUrl", "PostAddFolder"),
{
name: name,
parentId: parentId
}),
'Failed to add folder');
},
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#getChildFolders
* @methodOf umbraco.resources.mediaResource
*
* @description
* Retrieves all media children with types used as folders.
* Uses the convention of looking for media items with mediaTypes ending in
* *Folder so will match "Folder", "bannerFolder", "secureFolder" etc,
*
* ##usage
* <pre>
* mediaResource.getChildFolders(1234)
* .then(function(data) {
* alert('folders');
* });
* </pre>
*
* @param {int} parentId Id of the media item to query for child folders
* @returns {Promise} resourcePromise object.
*
*/
getChildFolders: function(parentId){
if(!parentId){
parentId = -1;
}
return umbRequestHelper.resourcePromise(
},
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#getChildFolders
* @methodOf umbraco.resources.mediaResource
*
* @description
* Retrieves all media children with types used as folders.
* Uses the convention of looking for media items with mediaTypes ending in
* *Folder so will match "Folder", "bannerFolder", "secureFolder" etc,
*
* ##usage
* <pre>
* mediaResource.getChildFolders(1234)
* .then(function(data) {
* alert('folders');
* });
* </pre>
*
* @param {int} parentId Id of the media item to query for child folders
* @returns {Promise} resourcePromise object.
*
*/
getChildFolders: function (parentId) {
if (!parentId) {
parentId = -1;
}
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"GetChildFolders",
[
{ id: parentId }
])),
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"GetChildFolders",
[
{ id: parentId }
])),
'Failed to retrieve child folders for media item ' + parentId);
},
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#emptyRecycleBin
* @methodOf umbraco.resources.mediaResource
*
* @description
* Empties the media recycle bin
*
* ##usage
* <pre>
* mediaResource.emptyRecycleBin()
* .then(function() {
* alert('its empty!');
* });
* </pre>
*
* @returns {Promise} resourcePromise object.
*
*/
emptyRecycleBin: function() {
return umbRequestHelper.resourcePromise(
},
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#emptyRecycleBin
* @methodOf umbraco.resources.mediaResource
*
* @description
* Empties the media recycle bin
*
* ##usage
* <pre>
* mediaResource.emptyRecycleBin()
* .then(function() {
* alert('its empty!');
* });
* </pre>
*
* @returns {Promise} resourcePromise object.
*
*/
emptyRecycleBin: function () {
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"EmptyRecycleBin")),
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"EmptyRecycleBin")),
'Failed to empty the recycle bin');
}
};
}
};
}
angular.module('umbraco.resources').factory('mediaResource', mediaResource);
@@ -4,230 +4,232 @@
* @description Loads in data for members
**/
function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
/** internal method process the saving of data and post processing the result */
function saveMember(content, action, files) {
return umbRequestHelper.postSaveContent({
restApiUrl: umbRequestHelper.getApiUrl(
/** internal method process the saving of data and post processing the result */
function saveMember(content, action, files) {
return umbRequestHelper.postSaveContent({
restApiUrl: umbRequestHelper.getApiUrl(
"memberApiBaseUrl",
"PostSave"),
content: content,
action: action,
files: files,
dataFormatter: function(c, a) {
return umbDataFormatter.formatMemberPostData(c, a);
}
});
}
content: content,
action: action,
files: files,
dataFormatter: function (c, a) {
return umbDataFormatter.formatMemberPostData(c, a);
}
});
}
return {
getPagedResults: function (memberTypeAlias, options) {
return {
if (memberTypeAlias === 'all-members') {
memberTypeAlias = null;
}
getPagedResults: function (memberTypeAlias, options) {
var defaults = {
pageSize: 25,
pageNumber: 1,
filter: '',
orderDirection: "Ascending",
orderBy: "LoginName"
};
if (options === undefined) {
options = {};
}
//overwrite the defaults if there are any specified
angular.extend(defaults, options);
//now copy back to the options we will use
options = defaults;
//change asc/desct
if (options.orderDirection === "asc") {
options.orderDirection = "Ascending";
}
else if (options.orderDirection === "desc") {
options.orderDirection = "Descending";
}
if (memberTypeAlias === 'all-members') {
memberTypeAlias = null;
}
var params = [
var defaults = {
pageSize: 25,
pageNumber: 1,
filter: '',
orderDirection: "Ascending",
orderBy: "LoginName",
orderBySystemField: true
};
if (options === undefined) {
options = {};
}
//overwrite the defaults if there are any specified
angular.extend(defaults, options);
//now copy back to the options we will use
options = defaults;
//change asc/desct
if (options.orderDirection === "asc") {
options.orderDirection = "Ascending";
}
else if (options.orderDirection === "desc") {
options.orderDirection = "Descending";
}
var params = [
{ pageNumber: options.pageNumber },
{ pageSize: options.pageSize },
{ orderBy: options.orderBy },
{ orderDirection: options.orderDirection },
{ orderBySystemField: options.orderBySystemField },
{ filter: options.filter }
];
if (memberTypeAlias != null) {
params.push({ memberTypeAlias: memberTypeAlias });
}
];
if (memberTypeAlias != null) {
params.push({ memberTypeAlias: memberTypeAlias });
}
return umbRequestHelper.resourcePromise(
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"memberApiBaseUrl",
"GetPagedResults",
params)),
umbRequestHelper.getApiUrl(
"memberApiBaseUrl",
"GetPagedResults",
params)),
'Failed to retrieve member paged result');
},
getListNode: function (listName) {
},
return umbRequestHelper.resourcePromise(
getListNode: function (listName) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"memberApiBaseUrl",
"GetListNodeDisplay",
[{ listName: listName }])),
umbRequestHelper.getApiUrl(
"memberApiBaseUrl",
"GetListNodeDisplay",
[{ listName: listName }])),
'Failed to retrieve data for member list ' + listName);
},
},
/**
* @ngdoc method
* @name umbraco.resources.memberResource#getByKey
* @methodOf umbraco.resources.memberResource
*
* @description
* Gets a member item with a given key
*
* ##usage
* <pre>
* memberResource.getByKey("0000-0000-000-00000-000")
* .then(function(member) {
* var mymember = member;
* alert('its here!');
* });
* </pre>
*
* @param {Guid} key key of member item to return
* @returns {Promise} resourcePromise object containing the member item.
*
*/
getByKey: function (key) {
return umbRequestHelper.resourcePromise(
/**
* @ngdoc method
* @name umbraco.resources.memberResource#getByKey
* @methodOf umbraco.resources.memberResource
*
* @description
* Gets a member item with a given key
*
* ##usage
* <pre>
* memberResource.getByKey("0000-0000-000-00000-000")
* .then(function(member) {
* var mymember = member;
* alert('its here!');
* });
* </pre>
*
* @param {Guid} key key of member item to return
* @returns {Promise} resourcePromise object containing the member item.
*
*/
getByKey: function (key) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"memberApiBaseUrl",
"GetByKey",
[{ key: key }])),
umbRequestHelper.getApiUrl(
"memberApiBaseUrl",
"GetByKey",
[{ key: key }])),
'Failed to retrieve data for member id ' + key);
},
},
/**
* @ngdoc method
* @name umbraco.resources.memberResource#deleteByKey
* @methodOf umbraco.resources.memberResource
*
* @description
* Deletes a member item with a given key
*
* ##usage
* <pre>
* memberResource.deleteByKey("0000-0000-000-00000-000")
* .then(function() {
* alert('its gone!');
* });
* </pre>
*
* @param {Guid} key id of member item to delete
* @returns {Promise} resourcePromise object.
*
*/
deleteByKey: function (key) {
return umbRequestHelper.resourcePromise(
/**
* @ngdoc method
* @name umbraco.resources.memberResource#deleteByKey
* @methodOf umbraco.resources.memberResource
*
* @description
* Deletes a member item with a given key
*
* ##usage
* <pre>
* memberResource.deleteByKey("0000-0000-000-00000-000")
* .then(function() {
* alert('its gone!');
* });
* </pre>
*
* @param {Guid} key id of member item to delete
* @returns {Promise} resourcePromise object.
*
*/
deleteByKey: function (key) {
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"memberApiBaseUrl",
"DeleteByKey",
[{ key: key }])),
umbRequestHelper.getApiUrl(
"memberApiBaseUrl",
"DeleteByKey",
[{ key: key }])),
'Failed to delete item ' + key);
},
},
/**
* @ngdoc method
* @name umbraco.resources.memberResource#getScaffold
* @methodOf umbraco.resources.memberResource
*
* @description
* Returns a scaffold of an empty member item, given the id of the member item to place it underneath and the member type alias.
*
* - Member Type alias must be provided so umbraco knows which properties to put on the member scaffold
*
* The scaffold is used to build editors for member that has not yet been populated with data.
*
* ##usage
* <pre>
* memberResource.getScaffold('client')
* .then(function(scaffold) {
* var myDoc = scaffold;
* myDoc.name = "My new member item";
*
* memberResource.save(myDoc, true)
* .then(function(member){
* alert("Retrieved, updated and saved again");
* });
* });
* </pre>
*
* @param {String} alias membertype alias to base the scaffold on
* @returns {Promise} resourcePromise object containing the member scaffold.
*
*/
getScaffold: function (alias) {
if (alias) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"memberApiBaseUrl",
"GetEmpty",
[{ contentTypeAlias: alias }])),
'Failed to retrieve data for empty member item type ' + alias);
}
else {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"memberApiBaseUrl",
"GetEmpty")),
'Failed to retrieve data for empty member item type ' + alias);
}
/**
* @ngdoc method
* @name umbraco.resources.memberResource#getScaffold
* @methodOf umbraco.resources.memberResource
*
* @description
* Returns a scaffold of an empty member item, given the id of the member item to place it underneath and the member type alias.
*
* - Member Type alias must be provided so umbraco knows which properties to put on the member scaffold
*
* The scaffold is used to build editors for member that has not yet been populated with data.
*
* ##usage
* <pre>
* memberResource.getScaffold('client')
* .then(function(scaffold) {
* var myDoc = scaffold;
* myDoc.name = "My new member item";
*
* memberResource.save(myDoc, true)
* .then(function(member){
* alert("Retrieved, updated and saved again");
* });
* });
* </pre>
*
* @param {String} alias membertype alias to base the scaffold on
* @returns {Promise} resourcePromise object containing the member scaffold.
*
*/
getScaffold: function (alias) {
},
/**
* @ngdoc method
* @name umbraco.resources.memberResource#save
* @methodOf umbraco.resources.memberResource
*
* @description
* Saves changes made to a member, if the member is new, the isNew paramater must be passed to force creation
* if the member needs to have files attached, they must be provided as the files param and passed separately
*
*
* ##usage
* <pre>
* memberResource.getBykey("23234-sd8djsd-3h8d3j-sdh8d")
* .then(function(member) {
* member.name = "Bob";
* memberResource.save(member, false)
* .then(function(member){
* alert("Retrieved, updated and saved again");
* });
* });
* </pre>
*
* @param {Object} media The member item object with changes applied
* @param {Bool} isNew set to true to create a new item or to update an existing
* @param {Array} files collection of files for the media item
* @returns {Promise} resourcePromise object containing the saved media item.
*
*/
save: function (member, isNew, files) {
return saveMember(member, "save" + (isNew ? "New" : ""), files);
}
};
if (alias) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"memberApiBaseUrl",
"GetEmpty",
[{ contentTypeAlias: alias }])),
'Failed to retrieve data for empty member item type ' + alias);
}
else {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"memberApiBaseUrl",
"GetEmpty")),
'Failed to retrieve data for empty member item type ' + alias);
}
},
/**
* @ngdoc method
* @name umbraco.resources.memberResource#save
* @methodOf umbraco.resources.memberResource
*
* @description
* Saves changes made to a member, if the member is new, the isNew paramater must be passed to force creation
* if the member needs to have files attached, they must be provided as the files param and passed separately
*
*
* ##usage
* <pre>
* memberResource.getBykey("23234-sd8djsd-3h8d3j-sdh8d")
* .then(function(member) {
* member.name = "Bob";
* memberResource.save(member, false)
* .then(function(member){
* alert("Retrieved, updated and saved again");
* });
* });
* </pre>
*
* @param {Object} media The member item object with changes applied
* @param {Bool} isNew set to true to create a new item or to update an existing
* @param {Array} files collection of files for the media item
* @returns {Promise} resourcePromise object containing the saved media item.
*
*/
save: function (member, isNew, files) {
return saveMember(member, "save" + (isNew ? "New" : ""), files);
}
};
}
angular.module('umbraco.resources').factory('memberResource', memberResource);
@@ -1,76 +1,60 @@
<div>
<div class="umb-table" ng-if="items">
<!-- Listviews head section -->
<div class="umb-table-head">
<div class="umb-table-row">
<div class="umb-table-cell">
<input class="umb-table__input" type="checkbox"
ng-if="allowSelectAll"
ng-click="selectAll($event)"
ng-checked="isSelectedAll()">
</div>
<div class="umb-table-cell umb-table__name">
<a class="umb-table-head__link sortable" href="#" ng-click="sort('Name', true)" prevent-default>
<localize key="general_name">Name</localize>
<i class="umb-table-head__icon icon" ng-class="{'icon-navigation-up': isSortDirection('Name', 'asc'), 'icon-navigation-down': isSortDirection('Name', 'desc')}"></i>
</a>
</div>
<div class="umb-table-cell" ng-repeat="column in itemProperties">
<a class="umb-table-head__link" title="Sort by {{ column.header }}" href="#"
ng-click="sort(column.alias, column.allowSorting)"
ng-class="{'sortable':column.allowSorting}" prevent-default>
<span ng-bind="column.header"></span>
<i class="umb-table-head__icon icon" ng-class="{'icon-navigation-up': isSortDirection(column.alias, 'asc'), 'icon-navigation-down': isSortDirection(column.alias, 'desc')}"></i>
</a>
</div>
</div>
</div>
<!-- Listview body section -->
<div class="umb-table-body">
<div class="umb-table-row"
ng-repeat="item in items"
ng-class="{
'-selected':item.selected,
'-published':item.published,
'-unpublished':!item.published
}"
ng-click="selectItem(item, $index, $event)">
<div class="umb-table-cell">
<i class="umb-table-body__icon umb-table-body__fileicon {{item.icon}}" ng-class="getIcon(item)"></i>
<i class="umb-table-body__icon umb-table-body__checkicon icon-check"></i>
</div>
<div class="umb-table-cell umb-table__name">
<a title="{{ item.name }}" class="umb-table-body__link" href=""
ng-click="clickItem(item, $event)"
ng-bind="item.name">
</a>
</div>
<div class="umb-table-cell" ng-repeat="column in itemProperties">
<span title="{{column.header}}: {{item[column.alias]}}">{{item[column.alias]}}</span>
</div>
</div>
</div>
</div>
<!-- If list is empty, then display -->
<umb-empty-state
ng-if="!items"
position="center">
<localize key="content_listViewNoItems">There are no items show in the list.</localize>
</umb-empty-state>
</div>
<div>
<div class="umb-table" ng-if="items">
<!-- Listviews head section -->
<div class="umb-table-head">
<div class="umb-table-row">
<div class="umb-table-cell">
<input class="umb-table__input" type="checkbox"
ng-if="allowSelectAll"
ng-click="selectAll($event)"
ng-checked="isSelectedAll()">
</div>
<div class="umb-table-cell umb-table__name">
<a class="umb-table-head__link sortable" href="#" ng-click="sort('Name', true)" prevent-default>
<localize key="general_name">Name</localize>
<i class="umb-table-head__icon icon" ng-class="{'icon-navigation-up': isSortDirection('Name', 'asc'), 'icon-navigation-down': isSortDirection('Name', 'desc')}"></i>
</a>
</div>
<div class="umb-table-cell" ng-repeat="column in itemProperties">
<a class="umb-table-head__link" title="Sort by {{ column.header }}" href="#"
ng-click="sort(column.alias, column.allowSorting, column.isSystem)"
ng-class="{'sortable':column.allowSorting}" prevent-default>
<span ng-bind="column.header"></span>
<i class="umb-table-head__icon icon" ng-class="{'icon-navigation-up': isSortDirection(column.alias, 'asc'), 'icon-navigation-down': isSortDirection(column.alias, 'desc')}"></i>
</a>
</div>
</div>
</div>
<!-- Listview body section -->
<div class="umb-table-body">
<div class="umb-table-row"
ng-repeat="item in items"
ng-class="{
'-selected':item.selected,
'-published':item.published,
'-unpublished':!item.published
}"
ng-click="selectItem(item, $index, $event)">
<div class="umb-table-cell">
<i class="umb-table-body__icon umb-table-body__fileicon {{item.icon}}" ng-class="getIcon(item)"></i>
<i class="umb-table-body__icon umb-table-body__checkicon icon-check"></i>
</div>
<div class="umb-table-cell umb-table__name">
<a title="{{ item.name }}" class="umb-table-body__link" href=""
ng-click="clickItem(item, $event)"
ng-bind="item.name">
</a>
</div>
<div class="umb-table-cell" ng-repeat="column in itemProperties">
<span title="{{column.header}}: {{item[column.alias]}}">{{item[column.alias]}}</span>
</div>
</div>
</div>
</div>
<!-- If list is empty, then display -->
<umb-empty-state ng-if="!items"
position="center">
<localize key="content_listViewNoItems">There are no items show in the list.</localize>
</umb-empty-state>
</div>
@@ -1,75 +1,76 @@
(function() {
"use strict";
function ListViewListLayoutController($scope, listViewHelper, $location, mediaHelper) {
var vm = this;
vm.nodeId = $scope.contentId;
//vm.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes);
//instead of passing in a whitelist, we pass in a blacklist by adding ! to the ext
vm.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.disallowedUploadFiles).replace(/./g, "!.");
vm.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB";
vm.activeDrag = false;
vm.isRecycleBin = $scope.contentId === '-21' || $scope.contentId === '-20';
vm.selectItem = selectItem;
vm.clickItem = clickItem;
vm.selectAll = selectAll;
vm.isSelectedAll = isSelectedAll;
vm.isSortDirection = isSortDirection;
vm.sort = sort;
vm.dragEnter = dragEnter;
vm.dragLeave = dragLeave;
vm.onFilesQueue = onFilesQueue;
vm.onUploadComplete = onUploadComplete;
function selectAll($event) {
listViewHelper.selectAllItems($scope.items, $scope.selection, $event);
}
function isSelectedAll() {
return listViewHelper.isSelectedAll($scope.items, $scope.selection);
}
function selectItem(selectedItem, $index, $event) {
listViewHelper.selectHandler(selectedItem, $index, $scope.items, $scope.selection, $event);
}
function clickItem(item) {
$location.path($scope.entityType + '/' + $scope.entityType + '/edit/' + item.id);
}
function isSortDirection(col, direction) {
return listViewHelper.setSortingDirection(col, direction, $scope.options);
}
function sort(field, allow) {
if (allow) {
listViewHelper.setSorting(field, allow, $scope.options);
$scope.getContent($scope.contentId);
}
}
// Dropzone upload functions
function dragEnter(el, event) {
vm.activeDrag = true;
}
function dragLeave(el, event) {
vm.activeDrag = false;
}
function onFilesQueue() {
vm.activeDrag = false;
}
function onUploadComplete() {
$scope.getContent($scope.contentId);
}
}
angular.module("umbraco").controller("Umbraco.PropertyEditors.ListView.ListLayoutController", ListViewListLayoutController);
})();
(function () {
"use strict";
function ListViewListLayoutController($scope, listViewHelper, $location, mediaHelper) {
var vm = this;
vm.nodeId = $scope.contentId;
//vm.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes);
//instead of passing in a whitelist, we pass in a blacklist by adding ! to the ext
vm.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.disallowedUploadFiles).replace(/./g, "!.");
vm.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB";
vm.activeDrag = false;
vm.isRecycleBin = $scope.contentId === '-21' || $scope.contentId === '-20';
vm.selectItem = selectItem;
vm.clickItem = clickItem;
vm.selectAll = selectAll;
vm.isSelectedAll = isSelectedAll;
vm.isSortDirection = isSortDirection;
vm.sort = sort;
vm.dragEnter = dragEnter;
vm.dragLeave = dragLeave;
vm.onFilesQueue = onFilesQueue;
vm.onUploadComplete = onUploadComplete;
function selectAll($event) {
listViewHelper.selectAllItems($scope.items, $scope.selection, $event);
}
function isSelectedAll() {
return listViewHelper.isSelectedAll($scope.items, $scope.selection);
}
function selectItem(selectedItem, $index, $event) {
listViewHelper.selectHandler(selectedItem, $index, $scope.items, $scope.selection, $event);
}
function clickItem(item) {
$location.path($scope.entityType + '/' +$scope.entityType + '/edit/' +item.id);
}
function isSortDirection(col, direction) {
return listViewHelper.setSortingDirection(col, direction, $scope.options);
}
function sort(field, allow, isSystem) {
if (allow) {
$scope.options.orderBySystemField = isSystem;
listViewHelper.setSorting(field, allow, $scope.options);
$scope.getContent($scope.contentId);
}
}
// Dropzone upload functions
function dragEnter(el, event) {
vm.activeDrag = true;
}
function dragLeave(el, event) {
vm.activeDrag = false;
}
function onFilesQueue() {
vm.activeDrag = false;
}
function onUploadComplete() {
$scope.getContent($scope.contentId);
}
}
angular.module("umbraco").controller("Umbraco.PropertyEditors.ListView.ListLayoutController", ListViewListLayoutController);
}) ();
File diff suppressed because it is too large Load Diff
+94 -90
View File
@@ -48,13 +48,13 @@ namespace Umbraco.Web.Editors
[PluginController("UmbracoApi")]
[UmbracoApplicationAuthorizeAttribute(Constants.Applications.Content)]
public class ContentController : ContentControllerBase
{
{
/// <summary>
/// Constructor
/// </summary>
public ContentController()
: this(UmbracoContext.Current)
{
: this(UmbracoContext.Current)
{
}
/// <summary>
@@ -62,8 +62,8 @@ namespace Umbraco.Web.Editors
/// </summary>
/// <param name="umbracoContext"></param>
public ContentController(UmbracoContext umbracoContext)
: base(umbracoContext)
{
: base(umbracoContext)
{
}
/// <summary>
@@ -110,15 +110,15 @@ namespace Umbraco.Web.Editors
[EnsureUserPermissionForContent("id")]
public ContentItemDisplay GetById(int id)
{
var foundContent = GetObjectFromRequest(() => Services.ContentService.GetById(id));
var foundContent = GetObjectFromRequest(() => Services.ContentService.GetById(id));
if (foundContent == null)
{
HandleContentNotFound(id);
}
var content = Mapper.Map<IContent, ContentItemDisplay>(foundContent);
return content;
}
}
[EnsureUserPermissionForContent("id")]
public ContentItemDisplay GetWithTreeDefinition(int id)
@@ -156,7 +156,7 @@ namespace Umbraco.Web.Editors
//remove this tab if it exists: umbContainerView
var containerTab = mapped.Tabs.FirstOrDefault(x => x.Alias == Constants.Conventions.PropertyGroups.ListViewGroupName);
mapped.Tabs = mapped.Tabs.Except(new[] {containerTab});
mapped.Tabs = mapped.Tabs.Except(new[] { containerTab });
return mapped;
}
@@ -169,7 +169,7 @@ namespace Umbraco.Web.Editors
{
var url = Umbraco.NiceUrl(id);
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(url, Encoding.UTF8, "application/json");
response.Content = new StringContent(url, Encoding.UTF8, "application/json");
return response;
}
@@ -179,18 +179,22 @@ namespace Umbraco.Web.Editors
/// <returns></returns>
[FilterAllowedOutgoingContent(typeof(IEnumerable<ContentItemBasic<ContentPropertyBasic, IContent>>), "Items")]
public PagedResult<ContentItemBasic<ContentPropertyBasic, IContent>> GetChildren(
int id,
int pageNumber = 0, //TODO: This should be '1' as it's not the index
int pageSize = 0,
string orderBy = "SortOrder",
Direction orderDirection = Direction.Ascending,
string filter = "")
int id,
int pageNumber = 0, //TODO: This should be '1' as it's not the index
int pageSize = 0,
string orderBy = "SortOrder",
Direction orderDirection = Direction.Ascending,
int? orderBySystemField = 2,
string filter = "")
{
var orderBySystemFieldBool = orderBySystemField == 1 || orderBySystemField == 2;
long totalChildren;
IContent[] children;
if (pageNumber > 0 && pageSize > 0)
{
children = Services.ContentService.GetPagedChildren(id, (pageNumber - 1), pageSize, out totalChildren, orderBy, orderDirection, filter).ToArray();
children = Services.ContentService
.GetPagedChildren(id, (pageNumber - 1), pageSize, out totalChildren
, orderBy, orderDirection, orderBySystemFieldBool, filter).ToArray();
}
else
{
@@ -205,7 +209,7 @@ namespace Umbraco.Web.Editors
var pagedResult = new PagedResult<ContentItemBasic<ContentPropertyBasic, IContent>>(totalChildren, pageNumber, pageSize);
pagedResult.Items = children
.Select(Mapper.Map<IContent, ContentItemBasic<ContentPropertyBasic, IContent>>);
.Select(Mapper.Map<IContent, ContentItemBasic<ContentPropertyBasic, IContent>>);
return pagedResult;
}
@@ -213,7 +217,7 @@ namespace Umbraco.Web.Editors
[Obsolete("Dont use this, it is incorrectly named, use HasPermission instead")]
public bool GetHasPermission(string permissionToCheck, int nodeId)
{
return HasPermission(permissionToCheck, nodeId);
return HasPermission(permissionToCheck, nodeId);
}
/// <summary>
@@ -225,8 +229,8 @@ namespace Umbraco.Web.Editors
public Dictionary<int, string[]> GetPermissions(int[] nodeIds)
{
return Services.UserService
.GetPermissions(Security.CurrentUser, nodeIds)
.ToDictionary(x => x.EntityId, x => x.AssignedPermissions);
.GetPermissions(Security.CurrentUser, nodeIds)
.ToDictionary(x => x.EntityId, x => x.AssignedPermissions);
}
[HttpGet]
@@ -240,7 +244,7 @@ namespace Umbraco.Web.Editors
return false;
}
/// <summary>
/// Saves content
/// </summary>
@@ -248,16 +252,16 @@ namespace Umbraco.Web.Editors
[FileUploadCleanupFilter]
[ContentPostValidate]
public ContentItemDisplay PostSave(
[ModelBinder(typeof(ContentItemBinder))]
ContentItemSave contentItem)
{
[ModelBinder(typeof(ContentItemBinder))]
ContentItemSave contentItem)
{
//If we've reached here it means:
// * Our model has been bound
// * and validated
// * any file attachments have been saved to their temporary location for us to use
// * we have a reference to the DTO object and the persisted object
// * Permissions are valid
MapPropertyValues(contentItem);
//We need to manually check the validation results here because:
@@ -275,7 +279,7 @@ namespace Umbraco.Web.Editors
var forDisplay = Mapper.Map<IContent, ContentItemDisplay>(contentItem.PersistedContent);
forDisplay.Errors = ModelState.ToErrorDictionary();
throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay));
}
//if the model state is not valid we cannot publish so change it to save
@@ -292,7 +296,7 @@ namespace Umbraco.Web.Editors
//initialize this to successful
var publishStatus = Attempt<PublishStatus>.Succeed();
var wasCancelled = false;
var wasCancelled = false;
if (contentItem.Action == ContentSaveAction.Save || contentItem.Action == ContentSaveAction.SaveNew)
{
@@ -327,8 +331,8 @@ namespace Umbraco.Web.Editors
if (wasCancelled == false)
{
display.AddSuccessNotification(
Services.TextService.Localize("speechBubbles/editContentSavedHeader"),
Services.TextService.Localize("speechBubbles/editContentSavedText"));
Services.TextService.Localize("speechBubbles/editContentSavedHeader"),
Services.TextService.Localize("speechBubbles/editContentSavedText"));
}
else
{
@@ -340,8 +344,8 @@ namespace Umbraco.Web.Editors
if (wasCancelled == false)
{
display.AddSuccessNotification(
Services.TextService.Localize("speechBubbles/editContentSendToPublish"),
Services.TextService.Localize("speechBubbles/editContentSendToPublishText"));
Services.TextService.Localize("speechBubbles/editContentSendToPublish"),
Services.TextService.Localize("speechBubbles/editContentSendToPublishText"));
}
else
{
@@ -366,7 +370,7 @@ namespace Umbraco.Web.Editors
return display;
}
/// <summary>
/// Publishes a document with a given ID
/// </summary>
@@ -392,7 +396,7 @@ namespace Umbraco.Web.Editors
{
var notificationModel = new SimpleNotificationModel();
ShowMessageForPublishStatus(publishResult.Result, notificationModel);
return Request.CreateValidationErrorResponse(notificationModel);
return Request.CreateValidationErrorResponse(notificationModel);
}
//return ok
@@ -440,7 +444,7 @@ namespace Umbraco.Web.Editors
//returning an object of INotificationModel will ensure that any pending
// notification messages are added to the response.
return Request.CreateValidationErrorResponse(new SimpleNotificationModel());
}
}
}
return Request.CreateResponse(HttpStatusCode.OK);
@@ -457,7 +461,7 @@ namespace Umbraco.Web.Editors
[HttpPost]
[EnsureUserPermissionForContent(Constants.System.RecycleBinContent)]
public HttpResponseMessage EmptyRecycleBin()
{
{
Services.ContentService.EmptyRecycleBin();
return Request.CreateResponse(HttpStatusCode.OK);
}
@@ -516,7 +520,7 @@ namespace Umbraco.Web.Editors
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(toMove.Path, Encoding.UTF8, "application/json");
return response;
return response;
}
/// <summary>
@@ -548,7 +552,7 @@ namespace Umbraco.Web.Editors
if (foundContent == null)
HandleContentNotFound(id);
var unpublishResult = Services.ContentService.WithResult().UnPublish(foundContent, Security.CurrentUser.Id);
var content = Mapper.Map<IContent, ContentItemDisplay>(foundContent);
@@ -559,7 +563,7 @@ namespace Umbraco.Web.Editors
throw new HttpResponseException(Request.CreateValidationErrorResponse(content));
}
else
{
{
content.AddSuccessNotification(Services.TextService.Localize("content/unPublish"), Services.TextService.Localize("speechBubbles/contentUnpublished"));
return content;
}
@@ -597,8 +601,8 @@ namespace Umbraco.Web.Editors
contentItem.PersistedContent.ReleaseDate = contentItem.ReleaseDate;
//only set the template if it didn't change
var templateChanged = (contentItem.PersistedContent.Template == null && contentItem.TemplateAlias.IsNullOrWhiteSpace() == false)
|| (contentItem.PersistedContent.Template != null && contentItem.PersistedContent.Template.Alias != contentItem.TemplateAlias)
|| (contentItem.PersistedContent.Template != null && contentItem.TemplateAlias.IsNullOrWhiteSpace());
|| (contentItem.PersistedContent.Template != null && contentItem.PersistedContent.Template.Alias != contentItem.TemplateAlias)
|| (contentItem.PersistedContent.Template != null && contentItem.TemplateAlias.IsNullOrWhiteSpace());
if (templateChanged)
{
var template = Services.FileService.GetTemplate(contentItem.TemplateAlias);
@@ -641,8 +645,8 @@ namespace Umbraco.Web.Editors
if (toMove.ContentType.AllowedAsRoot == false)
{
throw new HttpResponseException(
Request.CreateNotificationValidationErrorResponse(
Services.TextService.Localize("moveOrCopy/notAllowedAtRoot")));
Request.CreateNotificationValidationErrorResponse(
Services.TextService.Localize("moveOrCopy/notAllowedAtRoot")));
}
}
else
@@ -655,19 +659,19 @@ namespace Umbraco.Web.Editors
//check if the item is allowed under this one
if (parent.ContentType.AllowedContentTypes.Select(x => x.Id).ToArray()
.Any(x => x.Value == toMove.ContentType.Id) == false)
.Any(x => x.Value == toMove.ContentType.Id) == false)
{
throw new HttpResponseException(
Request.CreateNotificationValidationErrorResponse(
Services.TextService.Localize("moveOrCopy/notAllowedByContentType")));
Request.CreateNotificationValidationErrorResponse(
Services.TextService.Localize("moveOrCopy/notAllowedByContentType")));
}
// Check on paths
if ((string.Format(",{0},", parent.Path)).IndexOf(string.Format(",{0},", toMove.Id), StringComparison.Ordinal) > -1)
{
{
throw new HttpResponseException(
Request.CreateNotificationValidationErrorResponse(
Services.TextService.Localize("moveOrCopy/notAllowedByPath")));
Request.CreateNotificationValidationErrorResponse(
Services.TextService.Localize("moveOrCopy/notAllowedByPath")));
}
}
@@ -681,52 +685,52 @@ namespace Umbraco.Web.Editors
case PublishStatusType.Success:
case PublishStatusType.SuccessAlreadyPublished:
display.AddSuccessNotification(
Services.TextService.Localize("speechBubbles/editContentPublishedHeader"),
Services.TextService.Localize("speechBubbles/editContentPublishedText"));
Services.TextService.Localize("speechBubbles/editContentPublishedHeader"),
Services.TextService.Localize("speechBubbles/editContentPublishedText"));
break;
case PublishStatusType.FailedPathNotPublished:
display.AddWarningNotification(
Services.TextService.Localize("publish"),
Services.TextService.Localize("publish/contentPublishedFailedByParent",
new[] {string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id)}).Trim());
Services.TextService.Localize("publish"),
Services.TextService.Localize("publish/contentPublishedFailedByParent",
new[] { string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id) }).Trim());
break;
case PublishStatusType.FailedCancelledByEvent:
AddCancelMessage(display, "publish", "speechBubbles/contentPublishedFailedByEvent");
break;
break;
case PublishStatusType.FailedAwaitingRelease:
display.AddWarningNotification(
Services.TextService.Localize("publish"),
Services.TextService.Localize("publish/contentPublishedFailedAwaitingRelease",
new[] {string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id)}).Trim());
Services.TextService.Localize("publish"),
Services.TextService.Localize("publish/contentPublishedFailedAwaitingRelease",
new[] { string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id) }).Trim());
break;
case PublishStatusType.FailedHasExpired:
display.AddWarningNotification(
Services.TextService.Localize("publish"),
Services.TextService.Localize("publish/contentPublishedFailedExpired",
new[]
{
string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id),
}).Trim());
Services.TextService.Localize("publish"),
Services.TextService.Localize("publish/contentPublishedFailedExpired",
new[]
{
string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id),
}).Trim());
break;
case PublishStatusType.FailedIsTrashed:
//TODO: We should add proper error messaging for this!
break;
case PublishStatusType.FailedContentInvalid:
display.AddWarningNotification(
Services.TextService.Localize("publish"),
Services.TextService.Localize("publish/contentPublishedFailedInvalid",
new[]
{
string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id),
string.Join(",", status.InvalidProperties.Select(x => x.Alias))
}).Trim());
Services.TextService.Localize("publish"),
Services.TextService.Localize("publish/contentPublishedFailedInvalid",
new[]
{
string.Format("{0} ({1})", status.ContentItem.Name, status.ContentItem.Id),
string.Join(",", status.InvalidProperties.Select(x => x.Alias))
}).Trim());
break;
default:
throw new IndexOutOfRangeException();
}
}
/// <summary>
/// Performs a permissions check for the user to check if it has access to the node based on
@@ -741,15 +745,15 @@ namespace Umbraco.Web.Editors
/// <param name="contentItem">Specifies the already resolved content item to check against</param>
/// <returns></returns>
internal static bool CheckPermissions(
IDictionary<string, object> storage,
IUser user,
IUserService userService,
IContentService contentService,
int nodeId,
char[] permissionsToCheck = null,
IContent contentItem = null)
IDictionary<string, object> storage,
IUser user,
IUserService userService,
IContentService contentService,
int nodeId,
char[] permissionsToCheck = null,
IContent contentItem = null)
{
if (contentItem == null && nodeId != Constants.System.Root && nodeId != Constants.System.RecycleBinContent)
{
contentItem = contentService.GetById(nodeId);
@@ -764,16 +768,16 @@ namespace Umbraco.Web.Editors
}
var hasPathAccess = (nodeId == Constants.System.Root)
? UserExtensions.HasPathAccess(
Constants.System.Root.ToInvariantString(),
user.StartContentId,
Constants.System.RecycleBinContent)
: (nodeId == Constants.System.RecycleBinContent)
? UserExtensions.HasPathAccess(
Constants.System.RecycleBinContent.ToInvariantString(),
user.StartContentId,
Constants.System.RecycleBinContent)
: user.HasPathAccess(contentItem);
? UserExtensions.HasPathAccess(
Constants.System.Root.ToInvariantString(),
user.StartContentId,
Constants.System.RecycleBinContent)
: (nodeId == Constants.System.RecycleBinContent)
? UserExtensions.HasPathAccess(
Constants.System.RecycleBinContent.ToInvariantString(),
user.StartContentId,
Constants.System.RecycleBinContent)
: user.HasPathAccess(contentItem);
if (hasPathAccess == false)
{
+62 -59
View File
@@ -52,7 +52,7 @@ namespace Umbraco.Web.Editors
/// </summary>
public MediaController()
: this(UmbracoContext.Current)
{
{
}
/// <summary>
@@ -156,7 +156,7 @@ namespace Umbraco.Web.Editors
var folderTypes = Services.ContentTypeService.GetAllMediaTypes().ToArray().Where(x => x.Alias.EndsWith("Folder")).Select(x => x.Id);
var children = (id < 0) ? Services.MediaService.GetRootMedia() : Services.MediaService.GetById(id).Children();
return children.Where(x => folderTypes.Contains(x.ContentTypeId)).Select(Mapper.Map<IMedia, ContentItemBasic<ContentPropertyBasic, IMedia>>);
return children.Where(x => folderTypes.Contains(x.ContentTypeId)).Select(Mapper.Map<IMedia, ContentItemBasic<ContentPropertyBasic, IMedia>>);
}
/// <summary>
@@ -180,13 +180,16 @@ namespace Umbraco.Web.Editors
int pageSize = 0,
string orderBy = "SortOrder",
Direction orderDirection = Direction.Ascending,
bool orderBySystemField = true,
string filter = "")
{
int totalChildren;
IMedia[] children;
if (pageNumber > 0 && pageSize > 0)
{
children = Services.MediaService.GetPagedChildren(id, (pageNumber - 1), pageSize, out totalChildren, orderBy, orderDirection, filter).ToArray();
children = Services.MediaService
.GetPagedChildren(id, (pageNumber - 1), pageSize, out totalChildren
, orderBy, orderDirection, orderBySystemField, filter).ToArray();
}
else
{
@@ -261,7 +264,7 @@ namespace Umbraco.Web.Editors
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(toMove.Path, Encoding.UTF8, "application/json");
return response;
return response;
}
/// <summary>
@@ -307,7 +310,7 @@ namespace Umbraco.Web.Editors
//return the updated model
var display = Mapper.Map<IMedia, MediaItemDisplay>(contentItem.PersistedContent);
//lasty, if it is not valid, add the modelstate to the outgoing object and throw a 403
HandleInvalidModelState(display);
@@ -334,8 +337,8 @@ namespace Umbraco.Web.Editors
throw new HttpResponseException(Request.CreateValidationErrorResponse(display));
}
}
break;
break;
}
return display;
@@ -364,7 +367,7 @@ namespace Umbraco.Web.Editors
Services.MediaService.EmptyRecycleBin();
return Request.CreateResponse(HttpStatusCode.OK);
}
/// <summary>
/// Change the sort order for media
/// </summary>
@@ -383,7 +386,7 @@ namespace Umbraco.Web.Editors
{
return Request.CreateResponse(HttpStatusCode.OK);
}
var mediaService = base.ApplicationContext.Services.MediaService;
var sortedMedia = new List<IMedia>();
try
@@ -405,7 +408,7 @@ namespace Umbraco.Web.Editors
}
}
[EnsureUserPermissionForMedia("folder.ParentId")]
[EnsureUserPermissionForMedia("folder.ParentId")]
public MediaItemDisplay PostAddFolder(EntityBasic folder)
{
var mediaService = ApplicationContext.Services.MediaService;
@@ -436,7 +439,7 @@ namespace Umbraco.Web.Editors
var provider = new MultipartFormDataStreamProvider(root);
var result = await Request.Content.ReadAsMultipartAsync(provider);
//must have a file
if (result.FileData.Count == 0)
{
@@ -449,10 +452,10 @@ namespace Umbraco.Web.Editors
{
return Request.CreateValidationErrorResponse("The request was not formatted correctly, the currentFolder is not an integer");
}
//ensure the user has access to this folder by parent id!
if (CheckPermissions(
new Dictionary<string, object>(),
new Dictionary<string, object>(),
Security.CurrentUser,
Services.MediaService, parentId) == false)
{
@@ -463,65 +466,65 @@ namespace Umbraco.Web.Editors
Services.TextService.Localize("speechBubbles/invalidUserPermissionsText"),
SpeechBubbleIcon.Warning)));
}
var tempFiles = new PostedFiles();
var mediaService = ApplicationContext.Services.MediaService;
//in case we pass a path with a folder in it, we will create it and upload media to it.
if (result.FormData.ContainsKey("path"))
{
if (result.FormData.ContainsKey("path"))
{
var folders = result.FormData["path"].Split('/');
var folders = result.FormData["path"].Split('/');
for (int i = 0; i < folders.Length - 1; i++)
{
var folderName = folders[i];
IMedia folderMediaItem;
for (int i = 0; i < folders.Length - 1; i++)
{
var folderName = folders[i];
IMedia folderMediaItem;
//if uploading directly to media root and not a subfolder
if (parentId == -1)
{
//look for matching folder
folderMediaItem =
mediaService.GetRootMedia().FirstOrDefault(x => x.Name == folderName && x.ContentType.Alias == Constants.Conventions.MediaTypes.Folder);
if (folderMediaItem == null)
{
//if null, create a folder
folderMediaItem = mediaService.CreateMedia(folderName, -1, Constants.Conventions.MediaTypes.Folder);
mediaService.Save(folderMediaItem);
}
}
else
{
//get current parent
var mediaRoot = mediaService.GetById(parentId);
//if uploading directly to media root and not a subfolder
if (parentId == -1)
{
//look for matching folder
folderMediaItem =
mediaService.GetRootMedia().FirstOrDefault(x => x.Name == folderName && x.ContentType.Alias == Constants.Conventions.MediaTypes.Folder);
if (folderMediaItem == null)
{
//if null, create a folder
folderMediaItem = mediaService.CreateMedia(folderName, -1, Constants.Conventions.MediaTypes.Folder);
mediaService.Save(folderMediaItem);
}
}
else
{
//get current parent
var mediaRoot = mediaService.GetById(parentId);
//if the media root is null, something went wrong, we'll abort
if (mediaRoot == null)
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError,
"The folder: " + folderName + " could not be used for storing images, its ID: " + parentId +
" returned null");
//if the media root is null, something went wrong, we'll abort
if (mediaRoot == null)
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError,
"The folder: " + folderName + " could not be used for storing images, its ID: " + parentId +
" returned null");
//look for matching folder
folderMediaItem = mediaRoot.Children().FirstOrDefault(x => x.Name == folderName && x.ContentType.Alias == Constants.Conventions.MediaTypes.Folder);
if (folderMediaItem == null)
{
//if null, create a folder
folderMediaItem = mediaService.CreateMedia(folderName, mediaRoot, Constants.Conventions.MediaTypes.Folder);
mediaService.Save(folderMediaItem);
}
}
//set the media root to the folder id so uploaded files will end there.
parentId = folderMediaItem.Id;
}
}
//look for matching folder
folderMediaItem = mediaRoot.Children().FirstOrDefault(x => x.Name == folderName && x.ContentType.Alias == Constants.Conventions.MediaTypes.Folder);
if (folderMediaItem == null)
{
//if null, create a folder
folderMediaItem = mediaService.CreateMedia(folderName, mediaRoot, Constants.Conventions.MediaTypes.Folder);
mediaService.Save(folderMediaItem);
}
}
//set the media root to the folder id so uploaded files will end there.
parentId = folderMediaItem.Id;
}
}
//get the files
//get the files
foreach (var file in result.FileData)
{
var fileName = file.Headers.ContentDisposition.FileName.Trim(new[] { '\"' });
var ext = fileName.Substring(fileName.LastIndexOf('.')+1).ToLower();
var ext = fileName.Substring(fileName.LastIndexOf('.') + 1).ToLower();
if (UmbracoConfig.For.UmbracoSettings().Content.DisallowedUploadFiles.Contains(ext) == false)
{
@@ -583,7 +586,7 @@ namespace Umbraco.Web.Editors
if (origin.Value == "blueimp")
{
return Request.CreateResponse(HttpStatusCode.OK,
tempFiles,
tempFiles,
//Don't output the angular xsrf stuff, blue imp doesn't like that
new JsonMediaTypeFormatter());
}
+37 -34
View File
@@ -73,15 +73,16 @@ namespace Umbraco.Web.Editors
get { return Services.MemberService.GetMembershipScenario(); }
}
public PagedResult<MemberBasic> GetPagedResults(
public PagedResult<MemberBasic> GetPagedResults(
int pageNumber = 1,
int pageSize = 100,
string orderBy = "Name",
Direction orderDirection = Direction.Ascending,
bool orderBySystemField = true,
string filter = "",
string memberTypeAlias = null)
{
if (pageNumber <= 0 || pageSize <= 0)
{
throw new NotSupportedException("Both pageNumber and pageSize must be greater than zero");
@@ -90,7 +91,9 @@ namespace Umbraco.Web.Editors
if (MembershipScenario == MembershipScenario.NativeUmbraco)
{
long totalRecords;
var members = Services.MemberService.GetAll((pageNumber - 1), pageSize, out totalRecords, orderBy, orderDirection, memberTypeAlias, filter).ToArray();
var members = Services.MemberService
.GetAll((pageNumber - 1), pageSize, out totalRecords, orderBy, orderDirection, orderBySystemField
, memberTypeAlias, filter).ToArray();
if (totalRecords == 0)
{
return new PagedResult<MemberBasic>(0, 0, 0);
@@ -114,7 +117,7 @@ namespace Umbraco.Web.Editors
.Select(Mapper.Map<MembershipUser, MemberBasic>);
return pagedResult;
}
}
/// <summary>
@@ -162,23 +165,23 @@ namespace Umbraco.Web.Editors
return Mapper.Map<IMember, MemberDisplay>(foundMember);
case MembershipScenario.CustomProviderWithUmbracoLink:
//TODO: Support editing custom properties for members with a custom membership provider here.
//TODO: Support editing custom properties for members with a custom membership provider here.
//foundMember = Services.MemberService.GetByKey(key);
//if (foundMember == null)
//{
// HandleContentNotFound(key);
//}
//foundMembershipMember = Membership.GetUser(key, false);
//if (foundMembershipMember == null)
//{
// HandleContentNotFound(key);
//}
//foundMember = Services.MemberService.GetByKey(key);
//if (foundMember == null)
//{
// HandleContentNotFound(key);
//}
//foundMembershipMember = Membership.GetUser(key, false);
//if (foundMembershipMember == null)
//{
// HandleContentNotFound(key);
//}
//display = Mapper.Map<MembershipUser, MemberDisplay>(foundMembershipMember);
////map the name over
//display.Name = foundMember.Name;
//return display;
//display = Mapper.Map<MembershipUser, MemberDisplay>(foundMembershipMember);
////map the name over
//display.Name = foundMember.Name;
//return display;
case MembershipScenario.StandaloneCustomProvider:
default:
@@ -219,7 +222,7 @@ namespace Umbraco.Web.Editors
emptyContent.AdditionalData["NewPassword"] = Membership.GeneratePassword(Membership.MinRequiredPasswordLength, Membership.MinRequiredNonAlphanumericCharacters);
return Mapper.Map<IMember, MemberDisplay>(emptyContent);
case MembershipScenario.CustomProviderWithUmbracoLink:
//TODO: Support editing custom properties for members with a custom membership provider here.
//TODO: Support editing custom properties for members with a custom membership provider here.
case MembershipScenario.StandaloneCustomProvider:
default:
@@ -275,7 +278,7 @@ namespace Umbraco.Web.Editors
{
throw new NotSupportedException("Currently the member editor does not support providers that have RequiresQuestionAndAnswer specified");
}
//We're gonna look up the current roles now because the below code can cause
// events to be raised and developers could be manually adding roles to members in
// their handlers. If we don't look this up now there's a chance we'll just end up
@@ -324,7 +327,7 @@ namespace Umbraco.Web.Editors
//create/save the IMember
Services.MemberService.Save(contentItem.PersistedContent);
}
//Now let's do the role provider stuff - now that we've saved the content item (that is important since
// if we are changing the username, it must be persisted before looking up the member roles).
if (rolesToRemove.Any())
@@ -504,7 +507,7 @@ namespace Umbraco.Web.Editors
private void RefetchMemberData(MemberSave contentItem, LookupType lookup)
{
var currProps = contentItem.PersistedContent.Properties.ToArray();
switch (MembershipScenario)
{
case MembershipScenario.NativeUmbraco:
@@ -512,11 +515,11 @@ namespace Umbraco.Web.Editors
{
case LookupType.ByKey:
//Go and re-fetch the persisted item
contentItem.PersistedContent = Services.MemberService.GetByKey(contentItem.Key);
contentItem.PersistedContent = Services.MemberService.GetByKey(contentItem.Key);
break;
case LookupType.ByUserName:
contentItem.PersistedContent = Services.MemberService.GetByUsername(contentItem.Username.Trim());
break;
break;
}
break;
case MembershipScenario.CustomProviderWithUmbracoLink:
@@ -524,14 +527,14 @@ namespace Umbraco.Web.Editors
default:
var membershipUser = _provider.GetUser(contentItem.Key, false);
//Go and re-fetch the persisted item
contentItem.PersistedContent = Mapper.Map<MembershipUser, IMember>(membershipUser);
contentItem.PersistedContent = Mapper.Map<MembershipUser, IMember>(membershipUser);
break;
}
UpdateName(contentItem);
//re-assign the mapped values that are not part of the membership provider properties.
var builtInAliases = Constants.Conventions.Member.GetStandardPropertyTypeStubs().Select(x => x.Key).ToArray();
var builtInAliases = Constants.Conventions.Member.GetStandardPropertyTypeStubs().Select(x => x.Key).ToArray();
foreach (var p in contentItem.PersistedContent.Properties)
{
var valueMapped = currProps.SingleOrDefault(x => x.Alias == p.Alias);
@@ -542,7 +545,7 @@ namespace Umbraco.Web.Editors
p.TagSupport.Enable = valueMapped.TagSupport.Enable;
p.TagSupport.Tags = valueMapped.TagSupport.Tags;
}
}
}
}
/// <summary>
@@ -595,7 +598,7 @@ namespace Umbraco.Web.Editors
contentItem.IsApproved,
Guid.NewGuid(), //since it's the umbraco provider, the user key here doesn't make any difference
out status);
break;
case MembershipScenario.CustomProviderWithUmbracoLink:
//We are using a custom membership provider, we'll create an empty IMember first to get the unique id to use
@@ -618,7 +621,7 @@ namespace Umbraco.Web.Editors
case MembershipScenario.StandaloneCustomProvider:
// we don't have a member type to use so we will just create the basic membership user with the provider with no
// link back to the umbraco data
var newKey = Guid.NewGuid();
//TODO: We are not supporting q/a - passing in empty here
membershipUser = _provider.CreateUser(
@@ -628,9 +631,9 @@ namespace Umbraco.Web.Editors
"TEMP", //some membership provider's require something here even if q/a is disabled!
"TEMP", //some membership provider's require something here even if q/a is disabled!
contentItem.IsApproved,
newKey,
newKey,
out status);
break;
default:
throw new ArgumentOutOfRangeException();
@@ -685,12 +688,12 @@ namespace Umbraco.Web.Editors
break;
case MembershipCreateStatus.InvalidProviderUserKey:
ModelState.AddPropertyError(
//specify 'default' just so that it shows up as a notification - is not assigned to a property
//specify 'default' just so that it shows up as a notification - is not assigned to a property
new ValidationResult("Invalid provider user key"), "default");
break;
case MembershipCreateStatus.DuplicateProviderUserKey:
ModelState.AddPropertyError(
//specify 'default' just so that it shows up as a notification - is not assigned to a property
//specify 'default' just so that it shows up as a notification - is not assigned to a property
new ValidationResult("Duplicate provider user key"), "default");
break;
case MembershipCreateStatus.ProviderError:
@@ -1,50 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using Umbraco.Core;
namespace Umbraco.Web.WebApi.Filters
{
/// <summary>
/// Ensures that the request is not cached by the browser
/// </summary>
public class DisableBrowserCacheAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
//See: http://stackoverflow.com/questions/17755239/how-to-stop-chrome-from-caching-rest-response-from-webapi
base.OnActionExecuted(actionExecutedContext);
//NOTE: Until we upgraded to WebApi 2, this didn't work correctly and we had to revert to using
// HttpContext.Current responses. I've changed this back to what it should be now since it works
// and now with WebApi2, the HttpContext.Current responses dont! Anyways, all good now.
actionExecutedContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
NoCache = true,
NoStore = true,
MaxAge = new TimeSpan(0),
MustRevalidate = true
};
actionExecutedContext.Response.Headers.Pragma.Add(new NameValueHeaderValue("no-cache"));
if (actionExecutedContext.Response.Content != null)
{
actionExecutedContext.Response.Content.Headers.Expires =
//Mon, 01 Jan 1990 00:00:00 GMT
new DateTimeOffset(1990, 1, 1, 0, 0, 0, TimeSpan.Zero);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using Umbraco.Core;
namespace Umbraco.Web.WebApi.Filters
{
/// <summary>
/// Ensures that the request is not cached by the browser
/// </summary>
public class DisableBrowserCacheAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
//See: http://stackoverflow.com/questions/17755239/how-to-stop-chrome-from-caching-rest-response-from-webapi
base.OnActionExecuted(actionExecutedContext);
if (actionExecutedContext == null || actionExecutedContext.Response == null ||
actionExecutedContext.Response.Headers == null)
{
return;
}
//NOTE: Until we upgraded to WebApi 2, this didn't work correctly and we had to revert to using
// HttpContext.Current responses. I've changed this back to what it should be now since it works
// and now with WebApi2, the HttpContext.Current responses dont! Anyways, all good now.
actionExecutedContext.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
NoCache = true,
NoStore = true,
MaxAge = new TimeSpan(0),
MustRevalidate = true
};
actionExecutedContext.Response.Headers.Pragma.Add(new NameValueHeaderValue("no-cache"));
if (actionExecutedContext.Response.Content != null)
{
actionExecutedContext.Response.Content.Headers.Expires =
//Mon, 01 Jan 1990 00:00:00 GMT
new DateTimeOffset(1990, 1, 1, 0, 0, 0, TimeSpan.Zero);
}
}
}
}
+58 -57
View File
@@ -16,8 +16,8 @@ using Lucene.Net.Analysis;
namespace UmbracoExamine
{
/// <summary>
/// <summary>
/// Custom indexer for members
/// </summary>
public class UmbracoMemberIndexer : UmbracoContentIndexer
@@ -26,29 +26,29 @@ namespace UmbracoExamine
private readonly IMemberService _memberService;
private readonly IDataTypeService _dataTypeService;
/// <summary>
/// Default constructor
/// </summary>
public UmbracoMemberIndexer() : base()
{
/// <summary>
/// Default constructor
/// </summary>
public UmbracoMemberIndexer() : base()
{
_dataTypeService = ApplicationContext.Current.Services.DataTypeService;
_memberService = ApplicationContext.Current.Services.MemberService;
}
}
/// <summary>
/// Constructor to allow for creating an indexer at runtime
/// </summary>
/// <param name="indexerData"></param>
/// <param name="indexPath"></param>
/// <param name="dataService"></param>
/// <param name="analyzer"></param>
[Obsolete("Use the overload that specifies the Umbraco services")]
public UmbracoMemberIndexer(IIndexCriteria indexerData, DirectoryInfo indexPath, IDataService dataService, Analyzer analyzer, bool async)
: base(indexerData, indexPath, dataService, analyzer, async)
{
/// <summary>
/// Constructor to allow for creating an indexer at runtime
/// </summary>
/// <param name="indexerData"></param>
/// <param name="indexPath"></param>
/// <param name="dataService"></param>
/// <param name="analyzer"></param>
[Obsolete("Use the overload that specifies the Umbraco services")]
public UmbracoMemberIndexer(IIndexCriteria indexerData, DirectoryInfo indexPath, IDataService dataService, Analyzer analyzer, bool async)
: base(indexerData, indexPath, dataService, analyzer, async)
{
_dataTypeService = ApplicationContext.Current.Services.DataTypeService;
_memberService = ApplicationContext.Current.Services.MemberService;
}
}
/// <summary>
/// Constructor to allow for creating an indexer at runtime
@@ -60,19 +60,19 @@ namespace UmbracoExamine
/// <param name="memberService"></param>
/// <param name="analyzer"></param>
/// <param name="async"></param>
public UmbracoMemberIndexer(IIndexCriteria indexerData, DirectoryInfo indexPath, IDataService dataService,
IDataTypeService dataTypeService,
IMemberService memberService,
Analyzer analyzer, bool async)
: base(indexerData, indexPath, dataService, analyzer, async)
{
public UmbracoMemberIndexer(IIndexCriteria indexerData, DirectoryInfo indexPath, IDataService dataService,
IDataTypeService dataTypeService,
IMemberService memberService,
Analyzer analyzer, bool async)
: base(indexerData, indexPath, dataService, analyzer, async)
{
_dataTypeService = dataTypeService;
_memberService = memberService;
}
}
/// <summary>
/// <summary>
/// Ensures that the'_searchEmail' is added to the user fields so that it is indexed - without having to modify the config
/// </summary>
/// <param name="indexSet"></param>
@@ -87,7 +87,7 @@ namespace UmbracoExamine
if (indexerData.UserFields.Any(x => x.Name == "_searchEmail") == false)
{
var field = new IndexField {Name = "_searchEmail"};
var field = new IndexField { Name = "_searchEmail" };
var policy = IndexFieldPolicies.FirstOrDefault(x => x.Name == "_searchEmail");
if (policy != null)
{
@@ -97,7 +97,7 @@ namespace UmbracoExamine
return new IndexCriteria(
indexerData.StandardFields,
indexerData.UserFields.Concat(new[] {field}),
indexerData.UserFields.Concat(new[] { field }),
indexerData.IncludeNodeTypes,
indexerData.ExcludeNodeTypes,
indexerData.ParentNodeId
@@ -105,10 +105,10 @@ namespace UmbracoExamine
}
}
return indexerData;
return indexerData;
}
/// <summary>
/// <summary>
/// The supported types for this indexer
/// </summary>
protected override IEnumerable<string> SupportedTypes
@@ -119,39 +119,40 @@ namespace UmbracoExamine
}
}
/// <summary>
/// Reindex all members
/// </summary>
/// <param name="type"></param>
protected override void PerformIndexAll(string type)
{
/// <summary>
/// Reindex all members
/// </summary>
/// <param name="type"></param>
protected override void PerformIndexAll(string type)
{
//This only supports members
if (SupportedTypes.Contains(type) == false)
return;
const int pageSize = 1000;
var pageIndex = 0;
IMember[] members;
if (IndexerData.IncludeNodeTypes.Any())
{
{
//if there are specific node types then just index those
foreach (var nodeType in IndexerData.IncludeNodeTypes)
{
{
do
{
long total;
members = _memberService.GetAll(pageIndex, pageSize, out total, "LoginName", Direction.Ascending, nodeType).ToArray();
members = _memberService.GetAll(pageIndex, pageSize, out total, "LoginName"
, Direction.Ascending, true, nodeType).ToArray();
AddNodesToIndex(GetSerializedMembers(members), type);
pageIndex++;
} while (members.Length == pageSize);
}
}
else
{
}
}
else
{
//no node types specified, do all members
do
{
@@ -162,8 +163,8 @@ namespace UmbracoExamine
pageIndex++;
} while (members.Length == pageSize);
}
}
}
}
private IEnumerable<XElement> GetSerializedMembers(IEnumerable<IMember> members)
{
@@ -171,18 +172,18 @@ namespace UmbracoExamine
return members.Select(member => serializer.Serialize(_dataTypeService, member));
}
protected override XDocument GetXDocument(string xPath, string type)
{
throw new NotSupportedException();
}
protected override XDocument GetXDocument(string xPath, string type)
{
throw new NotSupportedException();
}
protected override Dictionary<string, string> GetSpecialFieldsToIndex(Dictionary<string, string> allValuesForIndexing)
{
var fields = base.GetSpecialFieldsToIndex(allValuesForIndexing);
//adds the special path property to the index
fields.Add("__key", allValuesForIndexing["__key"]);
return fields;
}
@@ -207,14 +208,14 @@ namespace UmbracoExamine
if (e.Fields.ContainsKey("_searchEmail") == false)
e.Fields.Add("_searchEmail", e.Node.Attribute("email").Value.Replace(".", " ").Replace("@", " "));
}
if (e.Fields.ContainsKey(IconFieldName) == false)
e.Fields.Add(IconFieldName, (string)e.Node.Attribute("icon"));
}
private static XElement GetMemberItem(int nodeId)
{
//TODO: Change this so that it is not using the LegacyLibrary, just serialize manually!
//TODO: Change this so that it is not using the LegacyLibrary, just serialize manually!
var nodes = LegacyLibrary.GetMember(nodeId);
return XElement.Parse(nodes.Current.OuterXml);
}