2017-12-07 16:45:25 +01:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text.RegularExpressions ;
using NPoco ;
using Umbraco.Core.Cache ;
using Umbraco.Core.Exceptions ;
using Umbraco.Core.Logging ;
using Umbraco.Core.Models ;
2019-06-28 09:19:11 +02:00
using Umbraco.Core.Models.Entities ;
2017-12-28 09:06:33 +01:00
using Umbraco.Core.Persistence.Dtos ;
2017-12-07 16:45:25 +01:00
using Umbraco.Core.Persistence.Factories ;
using Umbraco.Core.Persistence.Querying ;
2019-12-10 08:37:19 +01:00
using Umbraco.Core.PropertyEditors ;
2017-12-12 15:04:13 +01:00
using Umbraco.Core.Scoping ;
2018-09-18 11:53:33 +02:00
using Umbraco.Core.Services ;
2019-05-20 17:57:28 +02:00
using static Umbraco . Core . Persistence . SqlExtensionsStatics ;
2017-12-07 16:45:25 +01:00
namespace Umbraco.Core.Persistence.Repositories.Implement
{
/// <summary>
/// Represents a repository for doing CRUD operations for <see cref="IMedia"/>
/// </summary>
2019-12-17 16:30:26 +01:00
public class MediaRepository : ContentRepositoryBase < int , IMedia , MediaRepository > , IMediaRepository
2017-12-07 16:45:25 +01:00
{
private readonly IMediaTypeRepository _mediaTypeRepository ;
private readonly ITagRepository _tagRepository ;
2020-02-19 16:37:00 +11:00
private readonly MediaUrlGeneratorCollection _mediaUrlGenerators ;
2017-12-07 16:45:25 +01:00
private readonly MediaByGuidReadRepository _mediaByGuidReadRepository ;
2019-12-11 08:13:51 +01:00
public MediaRepository (
IScopeAccessor scopeAccessor ,
AppCaches cache ,
ILogger logger ,
IMediaTypeRepository mediaTypeRepository ,
ITagRepository tagRepository ,
ILanguageRepository languageRepository ,
IRelationRepository relationRepository ,
IRelationTypeRepository relationTypeRepository ,
Lazy < PropertyEditorCollection > propertyEditorCollection ,
2020-02-19 16:37:00 +11:00
MediaUrlGeneratorCollection mediaUrlGenerators ,
2019-12-11 08:13:51 +01:00
DataValueReferenceFactoryCollection dataValueReferenceFactories ,
IDataTypeService dataTypeService )
: base ( scopeAccessor , cache , logger , languageRepository , relationRepository , relationTypeRepository , propertyEditorCollection , dataValueReferenceFactories , dataTypeService )
2017-12-07 16:45:25 +01:00
{
_mediaTypeRepository = mediaTypeRepository ? ? throw new ArgumentNullException ( nameof ( mediaTypeRepository ) ) ;
_tagRepository = tagRepository ? ? throw new ArgumentNullException ( nameof ( tagRepository ) ) ;
2020-02-19 16:37:00 +11:00
_mediaUrlGenerators = mediaUrlGenerators ;
2017-12-14 17:04:44 +01:00
_mediaByGuidReadRepository = new MediaByGuidReadRepository ( this , scopeAccessor , cache , logger ) ;
2017-12-07 16:45:25 +01:00
}
protected override MediaRepository This = > this ;
#region Repository Base
2019-11-05 13:45:42 +01:00
protected override Guid NodeObjectTypeId = > Constants . ObjectTypes . Media ;
2017-12-07 16:45:25 +01:00
protected override IMedia PerformGet ( int id )
{
var sql = GetBaseQuery ( QueryType . Single )
. Where < NodeDto > ( x = > x . NodeId = = id )
. SelectTop ( 1 ) ;
var dto = Database . Fetch < ContentDto > ( sql ) . FirstOrDefault ( ) ;
return dto = = null
? null
: MapDtoToContent ( dto ) ;
}
protected override IEnumerable < IMedia > PerformGetAll ( params int [ ] ids )
{
var sql = GetBaseQuery ( QueryType . Many ) ;
if ( ids . Any ( ) )
sql . WhereIn < NodeDto > ( x = > x . NodeId , ids ) ;
return MapDtosToContent ( Database . Fetch < ContentDto > ( sql ) ) ;
}
protected override IEnumerable < IMedia > PerformGetByQuery ( IQuery < IMedia > query )
{
var sqlClause = GetBaseQuery ( QueryType . Many ) ;
var translator = new SqlTranslator < IMedia > ( sqlClause , query ) ;
var sql = translator . Translate ( ) ;
2019-01-21 15:39:19 +01:00
sql
2017-12-07 16:45:25 +01:00
. OrderBy < NodeDto > ( x = > x . Level )
. OrderBy < NodeDto > ( x = > x . SortOrder ) ;
return MapDtosToContent ( Database . Fetch < ContentDto > ( sql ) ) ;
}
protected override Sql < ISqlContext > GetBaseQuery ( QueryType queryType )
{
2018-03-22 11:24:12 +01:00
return GetBaseQuery ( queryType ) ;
2017-12-07 16:45:25 +01:00
}
2018-03-22 11:24:12 +01:00
protected virtual Sql < ISqlContext > GetBaseQuery ( QueryType queryType , bool current = true , bool joinMediaVersion = false )
2017-12-07 16:45:25 +01:00
{
var sql = SqlContext . Sql ( ) ;
switch ( queryType )
{
case QueryType . Count :
sql = sql . SelectCount ( ) ;
break ;
case QueryType . Ids :
sql = sql . Select < ContentDto > ( x = > x . NodeId ) ;
break ;
case QueryType . Single :
case QueryType . Many :
sql = sql . Select < ContentDto > ( r = >
r . Select ( x = > x . NodeDto )
2018-10-18 14:16:54 +02:00
. Select ( x = > x . ContentVersionDto ) )
// ContentRepositoryBase expects a variantName field to order by name
// for now, just return the plain invariant node name
. AndSelect < NodeDto > ( x = > Alias ( x . Text , "variantName" ) ) ;
2017-12-07 16:45:25 +01:00
break ;
}
sql
. From < ContentDto > ( )
. InnerJoin < NodeDto > ( ) . On < ContentDto , NodeDto > ( left = > left . NodeId , right = > right . NodeId )
. InnerJoin < ContentVersionDto > ( ) . On < ContentDto , ContentVersionDto > ( left = > left . NodeId , right = > right . NodeId ) ;
2018-03-22 11:24:12 +01:00
if ( joinMediaVersion )
sql . InnerJoin < MediaVersionDto > ( ) . On < ContentVersionDto , MediaVersionDto > ( ( left , right ) = > left . Id = = right . Id ) ;
2017-12-07 16:45:25 +01:00
sql . Where < NodeDto > ( x = > x . NodeObjectType = = NodeObjectTypeId ) ;
if ( current )
sql . Where < ContentVersionDto > ( x = > x . Current ) ; // always get the current version
return sql ;
}
protected override Sql < ISqlContext > GetBaseQuery ( bool isCount )
{
return GetBaseQuery ( isCount ? QueryType . Count : QueryType . Single ) ;
}
// ah maybe not, that what's used for eg Exists in base repo
protected override string GetBaseWhereClause ( )
{
return $"{Constants.DatabaseSchema.Tables.Node}.id = @id" ;
}
protected override IEnumerable < string > GetDeleteClauses ( )
{
var list = new List < string >
{
"DELETE FROM " + Constants . DatabaseSchema . Tables . User2NodeNotify + " WHERE nodeId = @id" ,
"DELETE FROM " + Constants . DatabaseSchema . Tables . UserGroup2NodePermission + " WHERE nodeId = @id" ,
"DELETE FROM " + Constants . DatabaseSchema . Tables . UserStartNode + " WHERE startNode = @id" ,
"UPDATE " + Constants . DatabaseSchema . Tables . UserGroup + " SET startContentId = NULL WHERE startContentId = @id" ,
"DELETE FROM " + Constants . DatabaseSchema . Tables . Relation + " WHERE parentId = @id" ,
"DELETE FROM " + Constants . DatabaseSchema . Tables . Relation + " WHERE childId = @id" ,
"DELETE FROM " + Constants . DatabaseSchema . Tables . TagRelationship + " WHERE nodeId = @id" ,
"DELETE FROM " + Constants . DatabaseSchema . Tables . Document + " WHERE nodeId = @id" ,
2018-03-22 11:24:12 +01:00
"DELETE FROM " + Constants . DatabaseSchema . Tables . MediaVersion + " WHERE id IN (SELECT id FROM " + Constants . DatabaseSchema . Tables . ContentVersion + " WHERE nodeId = @id)" ,
2017-12-07 16:45:25 +01:00
"DELETE FROM " + Constants . DatabaseSchema . Tables . PropertyData + " WHERE versionId IN (SELECT id FROM " + Constants . DatabaseSchema . Tables . ContentVersion + " WHERE nodeId = @id)" ,
"DELETE FROM " + Constants . DatabaseSchema . Tables . ContentVersion + " WHERE nodeId = @id" ,
"DELETE FROM " + Constants . DatabaseSchema . Tables . Content + " WHERE nodeId = @id" ,
"DELETE FROM " + Constants . DatabaseSchema . Tables . Node + " WHERE id = @id"
} ;
return list ;
}
#endregion
#region Versions
public override IEnumerable < IMedia > GetAllVersions ( int nodeId )
{
2018-03-22 11:24:12 +01:00
var sql = GetBaseQuery ( QueryType . Many , current : false )
2017-12-07 16:45:25 +01:00
. Where < NodeDto > ( x = > x . NodeId = = nodeId )
. OrderByDescending < ContentVersionDto > ( x = > x . Current )
. AndByDescending < ContentVersionDto > ( x = > x . VersionDate ) ;
return MapDtosToContent ( Database . Fetch < ContentDto > ( sql ) , true ) ;
}
public override IMedia GetVersion ( int versionId )
{
var sql = GetBaseQuery ( QueryType . Single )
. Where < ContentVersionDto > ( x = > x . Id = = versionId ) ;
var dto = Database . Fetch < ContentDto > ( sql ) . FirstOrDefault ( ) ;
return dto = = null ? null : MapDtoToContent ( dto ) ;
}
public IMedia GetMediaByPath ( string mediaPath )
{
var umbracoFileValue = mediaPath ;
const string pattern = ".*[_][0-9]+[x][0-9]+[.].*" ;
var isResized = Regex . IsMatch ( mediaPath , pattern ) ;
// If the image has been resized we strip the "_403x328" of the original "/media/1024/koala_403x328.jpg" url.
if ( isResized )
{
var underscoreIndex = mediaPath . LastIndexOf ( '_' ) ;
var dotIndex = mediaPath . LastIndexOf ( '.' ) ;
umbracoFileValue = string . Concat ( mediaPath . Substring ( 0 , underscoreIndex ) , mediaPath . Substring ( dotIndex ) ) ;
}
2018-03-22 11:24:12 +01:00
var sql = GetBaseQuery ( QueryType . Single , joinMediaVersion : true )
. Where < MediaVersionDto > ( x = > x . Path = = umbracoFileValue )
. SelectTop ( 1 ) ;
2017-12-07 16:45:25 +01:00
2018-03-22 11:24:12 +01:00
var dto = Database . Fetch < ContentDto > ( sql ) . FirstOrDefault ( ) ;
return dto = = null
? null
: MapDtoToContent ( dto ) ;
2017-12-07 16:45:25 +01:00
}
protected override void PerformDeleteVersion ( int id , int versionId )
{
// raise event first else potential FK issues
2017-12-12 15:04:13 +01:00
OnUowRemovingVersion ( new ScopedVersionEventArgs ( AmbientScope , id , versionId ) ) ;
2017-12-07 16:45:25 +01:00
Database . Delete < PropertyDataDto > ( "WHERE versionId = @versionId" , new { versionId } ) ;
Database . Delete < ContentVersionDto > ( "WHERE versionId = @versionId" , new { versionId } ) ;
}
#endregion
#region Persist
protected override void PersistNewItem ( IMedia entity )
{
2019-06-28 09:19:11 +02:00
entity . AddingEntity ( ) ;
2017-12-07 16:45:25 +01:00
// ensure unique name on the same level
entity . Name = EnsureUniqueNodeName ( entity . ParentId , entity . Name ) ;
// ensure that strings don't contain characters that are invalid in xml
2019-01-26 09:42:14 -05:00
// TODO: do we really want to keep doing this here?
2017-12-07 16:45:25 +01:00
entity . SanitizeEntityPropertiesForXmlStorage ( ) ;
// create the dto
2020-02-19 16:37:00 +11:00
var dto = ContentBaseFactory . BuildDto ( _mediaUrlGenerators , entity ) ;
2017-12-07 16:45:25 +01:00
// derive path and level from parent
var parent = GetParentNodeDto ( entity . ParentId ) ;
var level = parent . Level + 1 ;
// get sort order
var sortOrder = GetNewChildSortOrder ( entity . ParentId , 0 ) ;
// persist the node dto
2018-03-22 11:24:12 +01:00
var nodeDto = dto . ContentDto . NodeDto ;
2017-12-07 16:45:25 +01:00
nodeDto . Path = parent . Path ;
nodeDto . Level = Convert . ToInt16 ( level ) ;
nodeDto . SortOrder = sortOrder ;
// see if there's a reserved identifier for this unique id
// and then either update or insert the node dto
var id = GetReservedId ( nodeDto . UniqueId ) ;
if ( id > 0 )
nodeDto . NodeId = id ;
else
Database . Insert ( nodeDto ) ;
2018-03-22 11:24:12 +01:00
nodeDto . Path = string . Concat ( parent . Path , "," , nodeDto . NodeId ) ;
nodeDto . ValidatePathWithException ( ) ;
Database . Update ( nodeDto ) ;
2017-12-07 16:45:25 +01:00
// update entity
entity . Id = nodeDto . NodeId ;
entity . Path = nodeDto . Path ;
entity . SortOrder = sortOrder ;
entity . Level = level ;
// persist the content dto
2018-03-22 11:24:12 +01:00
var contentDto = dto . ContentDto ;
contentDto . NodeId = nodeDto . NodeId ;
Database . Insert ( contentDto ) ;
2017-12-07 16:45:25 +01:00
// persist the content version dto
// assumes a new version id and version date (modified date) has been set
2018-03-22 11:24:12 +01:00
var contentVersionDto = dto . MediaVersionDto . ContentVersionDto ;
2017-12-07 16:45:25 +01:00
contentVersionDto . NodeId = nodeDto . NodeId ;
contentVersionDto . Current = true ;
Database . Insert ( contentVersionDto ) ;
2020-04-16 22:04:27 +10:00
entity . VersionId = contentVersionDto . Id ;
2017-12-07 16:45:25 +01:00
2018-03-22 11:24:12 +01:00
// persist the media version dto
var mediaVersionDto = dto . MediaVersionDto ;
2020-04-16 22:04:27 +10:00
mediaVersionDto . Id = entity . VersionId ;
2018-03-22 11:24:12 +01:00
Database . Insert ( mediaVersionDto ) ;
2017-12-07 16:45:25 +01:00
// persist the property data
2020-04-16 22:04:27 +10:00
var propertyDataDtos = PropertyFactory . BuildDtos ( entity . ContentType . Variations , entity . VersionId , 0 , entity . Properties , LanguageRepository , out _ , out _ ) ;
2017-12-07 16:45:25 +01:00
foreach ( var propertyDataDto in propertyDataDtos )
Database . Insert ( propertyDataDto ) ;
// set tags
2018-02-01 14:14:45 +01:00
SetEntityTags ( entity , _tagRepository ) ;
2017-12-07 16:45:25 +01:00
2019-10-25 14:17:18 +11:00
PersistRelations ( entity ) ;
2017-12-12 15:04:13 +01:00
OnUowRefreshedEntity ( new ScopedEntityEventArgs ( AmbientScope , entity ) ) ;
2017-12-07 16:45:25 +01:00
entity . ResetDirtyProperties ( ) ;
}
protected override void PersistUpdatedItem ( IMedia entity )
{
// update
2020-04-16 22:04:27 +10:00
entity . UpdatingEntity ( ) ;
2017-12-07 16:45:25 +01:00
2020-04-07 13:29:00 +10:00
// Check if this entity is being moved as a descendant as part of a bulk moving operations.
2020-04-07 15:02:08 +10:00
// In this case we can bypass a lot of the below operations which will make this whole operation go much faster.
// When moving we don't need to create new versions, etc... because we cannot roll this operation back anyways.
var isMoving = entity . IsMoving ( ) ;
2017-12-07 16:45:25 +01:00
2020-04-07 13:29:00 +10:00
if ( ! isMoving )
2017-12-07 16:45:25 +01:00
{
2020-04-07 13:29:00 +10:00
// ensure unique name on the same level
entity . Name = EnsureUniqueNodeName ( entity . ParentId , entity . Name , entity . Id ) ;
// ensure that strings don't contain characters that are invalid in xml
// TODO: do we really want to keep doing this here?
entity . SanitizeEntityPropertiesForXmlStorage ( ) ;
// if parent has changed, get path, level and sort order
if ( entity . IsPropertyDirty ( nameof ( entity . ParentId ) ) )
{
var parent = GetParentNodeDto ( entity . ParentId ) ;
entity . Path = string . Concat ( parent . Path , "," , entity . Id ) ;
entity . Level = parent . Level + 1 ;
entity . SortOrder = GetNewChildSortOrder ( entity . ParentId , 0 ) ;
}
2017-12-07 16:45:25 +01:00
}
// create the dto
2020-02-19 16:37:00 +11:00
var dto = ContentBaseFactory . BuildDto ( _mediaUrlGenerators , entity ) ;
2017-12-07 16:45:25 +01:00
// update the node dto
2018-03-22 11:24:12 +01:00
var nodeDto = dto . ContentDto . NodeDto ;
2017-12-07 16:45:25 +01:00
nodeDto . ValidatePathWithException ( ) ;
Database . Update ( nodeDto ) ;
2020-04-07 13:29:00 +10:00
if ( ! isMoving )
{
// update the content dto
Database . Update ( dto . ContentDto ) ;
// update the content & media version dtos
var contentVersionDto = dto . MediaVersionDto . ContentVersionDto ;
var mediaVersionDto = dto . MediaVersionDto ;
contentVersionDto . Current = true ;
Database . Update ( contentVersionDto ) ;
Database . Update ( mediaVersionDto ) ;
// replace the property data
2020-04-16 22:04:27 +10:00
var deletePropertyDataSql = SqlContext . Sql ( ) . Delete < PropertyDataDto > ( ) . Where < PropertyDataDto > ( x = > x . VersionId = = entity . VersionId ) ;
2020-04-07 13:29:00 +10:00
Database . Execute ( deletePropertyDataSql ) ;
2020-04-16 22:04:27 +10:00
var propertyDataDtos = PropertyFactory . BuildDtos ( entity . ContentType . Variations , entity . VersionId , 0 , entity . Properties , LanguageRepository , out _ , out _ ) ;
2020-04-07 13:29:00 +10:00
foreach ( var propertyDataDto in propertyDataDtos )
Database . Insert ( propertyDataDto ) ;
SetEntityTags ( entity , _tagRepository ) ;
PersistRelations ( entity ) ;
}
2019-10-25 14:17:18 +11:00
2017-12-12 15:04:13 +01:00
OnUowRefreshedEntity ( new ScopedEntityEventArgs ( AmbientScope , entity ) ) ;
2017-12-07 16:45:25 +01:00
entity . ResetDirtyProperties ( ) ;
}
protected override void PersistDeletedItem ( IMedia entity )
{
// raise event first else potential FK issues
2017-12-12 15:04:13 +01:00
OnUowRemovingEntity ( new ScopedEntityEventArgs ( AmbientScope , entity ) ) ;
2017-12-07 16:45:25 +01:00
base . PersistDeletedItem ( entity ) ;
}
#endregion
#region Recycle Bin
2019-11-05 13:45:42 +01:00
public override int RecycleBinId = > Constants . System . RecycleBinMedia ;
2017-12-07 16:45:25 +01:00
#endregion
#region Read Repository implementation for Guid keys
public IMedia Get ( Guid id )
{
return _mediaByGuidReadRepository . Get ( id ) ;
}
IEnumerable < IMedia > IReadRepository < Guid , IMedia > . GetMany ( params Guid [ ] ids )
{
return _mediaByGuidReadRepository . GetMany ( ids ) ;
}
public bool Exists ( Guid id )
{
return _mediaByGuidReadRepository . Exists ( id ) ;
}
/// <summary>
/// A reading repository purely for looking up by GUID
/// </summary>
/// <remarks>
/// TODO: This is ugly and to fix we need to decouple the IRepositoryQueryable -> IRepository -> IReadRepository which should all be separate things!
/// Then we can do the same thing with repository instances and we wouldn't need to leave all these methods as not implemented because we wouldn't need to implement them
/// </remarks>
private class MediaByGuidReadRepository : NPocoRepositoryBase < Guid , IMedia >
{
private readonly MediaRepository _outerRepo ;
2019-01-17 08:34:29 +01:00
public MediaByGuidReadRepository ( MediaRepository outerRepo , IScopeAccessor scopeAccessor , AppCaches cache , ILogger logger )
2017-12-14 17:04:44 +01:00
: base ( scopeAccessor , cache , logger )
2017-12-07 16:45:25 +01:00
{
_outerRepo = outerRepo ;
}
protected override Guid NodeObjectTypeId = > _outerRepo . NodeObjectTypeId ;
protected override IMedia PerformGet ( Guid id )
{
var sql = _outerRepo . GetBaseQuery ( QueryType . Single )
. Where < NodeDto > ( x = > x . UniqueId = = id ) ;
var dto = Database . Fetch < ContentDto > ( sql . SelectTop ( 1 ) ) . FirstOrDefault ( ) ;
if ( dto = = null )
return null ;
var content = _outerRepo . MapDtoToContent ( dto ) ;
return content ;
}
protected override IEnumerable < IMedia > PerformGetAll ( params Guid [ ] ids )
{
var sql = _outerRepo . GetBaseQuery ( QueryType . Many ) ;
if ( ids . Length > 0 )
sql . WhereIn < NodeDto > ( x = > x . UniqueId , ids ) ;
return _outerRepo . MapDtosToContent ( Database . Fetch < ContentDto > ( sql ) ) ;
}
protected override IEnumerable < IMedia > PerformGetByQuery ( IQuery < IMedia > query )
{
2019-10-06 11:34:25 +02:00
throw new InvalidOperationException ( "This method won't be implemented." ) ;
2017-12-07 16:45:25 +01:00
}
protected override IEnumerable < string > GetDeleteClauses ( )
{
2019-10-06 11:34:25 +02:00
throw new InvalidOperationException ( "This method won't be implemented." ) ;
2017-12-07 16:45:25 +01:00
}
protected override void PersistNewItem ( IMedia entity )
{
2019-10-06 11:34:25 +02:00
throw new InvalidOperationException ( "This method won't be implemented." ) ;
2017-12-07 16:45:25 +01:00
}
protected override void PersistUpdatedItem ( IMedia entity )
{
2019-10-06 11:34:25 +02:00
throw new InvalidOperationException ( "This method won't be implemented." ) ;
2017-12-07 16:45:25 +01:00
}
protected override Sql < ISqlContext > GetBaseQuery ( bool isCount )
{
2019-10-06 11:34:25 +02:00
throw new InvalidOperationException ( "This method won't be implemented." ) ;
2017-12-07 16:45:25 +01:00
}
protected override string GetBaseWhereClause ( )
{
2019-10-06 11:34:25 +02:00
throw new InvalidOperationException ( "This method won't be implemented." ) ;
2017-12-07 16:45:25 +01:00
}
}
#endregion
2018-09-18 11:53:33 +02:00
/// <inheritdoc />
public override IEnumerable < IMedia > GetPage ( IQuery < IMedia > query ,
long pageIndex , int pageSize , out long totalRecords ,
IQuery < IMedia > filter , Ordering ordering )
2017-12-07 16:45:25 +01:00
{
Sql < ISqlContext > filterSql = null ;
if ( filter ! = null )
{
filterSql = Sql ( ) ;
foreach ( var clause in filter . GetWhereClauses ( ) )
filterSql = filterSql . Append ( $"AND ({clause.Item1})" , clause . Item2 ) ;
}
2017-12-12 15:04:13 +01:00
return GetPage < ContentDto > ( query , pageIndex , pageSize , out totalRecords ,
2018-09-18 11:53:33 +02:00
x = > MapDtosToContent ( x ) ,
filterSql ,
ordering ) ;
2017-12-07 16:45:25 +01:00
}
private IEnumerable < IMedia > MapDtosToContent ( List < ContentDto > dtos , bool withCache = false )
{
var temps = new List < TempContent < Models . Media > > ( ) ;
var contentTypes = new Dictionary < int , IMediaType > ( ) ;
var content = new Models . Media [ dtos . Count ] ;
for ( var i = 0 ; i < dtos . Count ; i + + )
{
var dto = dtos [ i ] ;
if ( withCache )
{
// if the cache contains the (proper version of the) item, use it
var cached = IsolatedCache . GetCacheItem < IMedia > ( RepositoryCacheKeys . GetKey < IMedia > ( dto . NodeId ) ) ;
if ( cached ! = null & & cached . VersionId = = dto . ContentVersionDto . Id )
{
2019-01-21 15:39:19 +01:00
content [ i ] = ( Models . Media ) cached ;
2017-12-07 16:45:25 +01:00
continue ;
}
}
// else, need to build it
// get the content type - the repository is full cache *but* still deep-clones
// whatever comes out of it, so use our own local index here to avoid this
var contentTypeId = dto . ContentTypeId ;
if ( contentTypes . TryGetValue ( contentTypeId , out IMediaType contentType ) = = false )
contentTypes [ contentTypeId ] = contentType = _mediaTypeRepository . Get ( contentTypeId ) ;
var c = content [ i ] = ContentBaseFactory . BuildEntity ( dto , contentType ) ;
// need properties
var versionId = dto . ContentVersionDto . Id ;
temps . Add ( new TempContent < Models . Media > ( dto . NodeId , versionId , 0 , contentType , c ) ) ;
}
// load all properties for all documents from database in 1 query - indexed by version id
var properties = GetPropertyCollections ( temps ) ;
// assign properties
foreach ( var temp in temps )
{
temp . Content . Properties = properties [ temp . VersionId ] ;
// reset dirty initial properties (U4-1946)
temp . Content . ResetDirtyProperties ( false ) ;
}
return content ;
}
private IMedia MapDtoToContent ( ContentDto dto )
{
var contentType = _mediaTypeRepository . Get ( dto . ContentTypeId ) ;
var media = ContentBaseFactory . BuildEntity ( dto , contentType ) ;
// get properties - indexed by version id
var versionId = dto . ContentVersionDto . Id ;
var temp = new TempContent < Models . Media > ( dto . NodeId , versionId , 0 , contentType ) ;
var properties = GetPropertyCollections ( new List < TempContent < Models . Media > > { temp } ) ;
media . Properties = properties [ versionId ] ;
// reset dirty initial properties (U4-1946)
media . ResetDirtyProperties ( false ) ;
return media ;
}
2019-11-05 12:54:22 +01:00
2017-12-07 16:45:25 +01:00
}
}