2013-04-13 18:02:30 +00:00
using MediaBrowser.Controller.Dto ;
2013-04-13 00:42:51 +00:00
using MediaBrowser.Controller.Entities ;
2013-02-21 01:33:05 +00:00
using MediaBrowser.Controller.Library ;
2013-04-13 18:02:30 +00:00
using MediaBrowser.Controller.Persistence ;
2013-02-21 17:50:46 +00:00
using MediaBrowser.Model.Dto ;
2014-10-06 23:58:46 +00:00
using MediaBrowser.Model.Entities ;
2013-03-10 05:36:39 +00:00
using MediaBrowser.Model.Querying ;
2013-12-07 15:52:38 +00:00
using ServiceStack ;
2013-02-21 01:33:05 +00:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
namespace MediaBrowser.Api.UserLibrary
{
/// <summary>
/// Class BaseItemsByNameService
/// </summary>
/// <typeparam name="TItemType">The type of the T item type.</typeparam>
2013-03-16 05:52:33 +00:00
public abstract class BaseItemsByNameService < TItemType > : BaseApiService
2013-09-10 18:56:00 +00:00
where TItemType : BaseItem , IItemByName
2013-02-21 01:33:05 +00:00
{
2013-02-27 20:25:45 +00:00
/// <summary>
/// The _user manager
/// </summary>
protected readonly IUserManager UserManager ;
2013-03-11 05:06:55 +00:00
/// <summary>
/// The library manager
/// </summary>
2013-02-28 19:32:41 +00:00
protected readonly ILibraryManager LibraryManager ;
2013-10-02 16:08:58 +00:00
protected readonly IUserDataManager UserDataRepository ;
2013-06-18 19:16:27 +00:00
protected readonly IItemRepository ItemRepository ;
2013-09-04 17:02:19 +00:00
protected IDtoService DtoService { get ; private set ; }
2013-02-27 20:25:45 +00:00
/// <summary>
/// Initializes a new instance of the <see cref="BaseItemsByNameService{TItemType}" /> class.
/// </summary>
/// <param name="userManager">The user manager.</param>
2013-03-11 05:06:55 +00:00
/// <param name="libraryManager">The library manager.</param>
2013-04-13 18:02:30 +00:00
/// <param name="userDataRepository">The user data repository.</param>
2013-09-10 18:56:00 +00:00
/// <param name="itemRepository">The item repository.</param>
/// <param name="dtoService">The dto service.</param>
2013-10-02 16:08:58 +00:00
protected BaseItemsByNameService ( IUserManager userManager , ILibraryManager libraryManager , IUserDataManager userDataRepository , IItemRepository itemRepository , IDtoService dtoService )
2013-02-27 20:25:45 +00:00
{
UserManager = userManager ;
2013-02-28 19:32:41 +00:00
LibraryManager = libraryManager ;
2013-04-13 18:02:30 +00:00
UserDataRepository = userDataRepository ;
2013-06-18 19:16:27 +00:00
ItemRepository = itemRepository ;
2013-09-04 17:02:19 +00:00
DtoService = dtoService ;
2013-02-27 20:25:45 +00:00
}
2013-02-21 01:33:05 +00:00
/// <summary>
/// Gets the specified request.
/// </summary>
/// <param name="request">The request.</param>
/// <returns>Task{ItemsResult}.</returns>
2013-09-27 12:24:28 +00:00
protected ItemsResult GetResult ( GetItemsByName request )
2013-02-21 01:33:05 +00:00
{
2015-03-26 04:44:24 +00:00
var dtoOptions = GetDtoOptions ( request ) ;
2013-04-22 04:38:03 +00:00
User user = null ;
2015-01-25 06:34:50 +00:00
BaseItem parentItem ;
2015-03-26 04:44:24 +00:00
List < BaseItem > libraryItems = null ;
2013-02-21 01:33:05 +00:00
2013-04-22 04:38:03 +00:00
if ( request . UserId . HasValue )
{
user = UserManager . GetUserById ( request . UserId . Value ) ;
2015-01-25 06:34:50 +00:00
parentItem = string . IsNullOrEmpty ( request . ParentId ) ? user . RootFolder : LibraryManager . GetItemById ( request . ParentId ) ;
2014-03-09 22:14:44 +00:00
2015-03-26 04:44:24 +00:00
if ( RequiresLibraryItems ( request , dtoOptions ) )
{
libraryItems = user . RootFolder . GetRecursiveChildren ( user ) . ToList ( ) ;
}
2013-04-22 04:38:03 +00:00
}
else
{
2015-01-25 06:34:50 +00:00
parentItem = string . IsNullOrEmpty ( request . ParentId ) ? LibraryManager . RootFolder : LibraryManager . GetItemById ( request . ParentId ) ;
2015-03-26 04:44:24 +00:00
if ( RequiresLibraryItems ( request , dtoOptions ) )
{
libraryItems = LibraryManager . RootFolder . GetRecursiveChildren ( ) . ToList ( ) ;
}
2013-04-22 04:38:03 +00:00
}
2013-02-21 01:33:05 +00:00
IEnumerable < BaseItem > items ;
2015-01-25 06:34:50 +00:00
var excludeItemTypes = request . GetExcludeItemTypes ( ) ;
var includeItemTypes = request . GetIncludeItemTypes ( ) ;
var mediaTypes = request . GetMediaTypes ( ) ;
Func < BaseItem , bool > filter = i = > FilterItem ( request , i , excludeItemTypes , includeItemTypes , mediaTypes ) ;
if ( parentItem . IsFolder )
2013-02-21 01:33:05 +00:00
{
2015-01-25 06:34:50 +00:00
var folder = ( Folder ) parentItem ;
2013-02-21 01:33:05 +00:00
2013-04-22 04:38:03 +00:00
if ( request . UserId . HasValue )
{
2015-01-25 06:34:50 +00:00
items = request . Recursive ?
folder . GetRecursiveChildren ( user , filter ) :
folder . GetChildren ( user , true ) . Where ( filter ) ;
2013-04-22 04:38:03 +00:00
}
else
{
2015-01-25 06:34:50 +00:00
items = request . Recursive ?
folder . GetRecursiveChildren ( filter ) :
folder . Children . Where ( filter ) ;
2013-04-22 04:38:03 +00:00
}
2013-02-21 01:33:05 +00:00
}
else
{
2015-01-25 06:34:50 +00:00
items = new [ ] { parentItem } . Where ( filter ) ;
2013-02-21 01:33:05 +00:00
}
2013-09-17 02:08:18 +00:00
var extractedItems = GetAllItems ( request , items ) ;
2013-04-13 21:49:16 +00:00
2013-09-10 19:57:38 +00:00
var filteredItems = FilterItems ( request , extractedItems , user ) ;
2013-04-13 21:49:16 +00:00
2014-03-09 22:14:44 +00:00
filteredItems = FilterByLibraryItems ( request , filteredItems , user , libraryItems ) ;
2014-01-14 20:03:35 +00:00
2014-10-06 23:58:46 +00:00
filteredItems = LibraryManager . Sort ( filteredItems , user , request . GetOrderBy ( ) , request . SortOrder ? ? SortOrder . Ascending ) . Cast < TItemType > ( ) ;
2013-04-13 21:49:16 +00:00
2013-09-20 00:53:18 +00:00
var ibnItemsArray = filteredItems . ToList ( ) ;
2013-09-10 19:57:38 +00:00
IEnumerable < TItemType > ibnItems = ibnItemsArray ;
2013-02-21 01:33:05 +00:00
var result = new ItemsResult
{
2013-09-20 00:53:18 +00:00
TotalRecordCount = ibnItemsArray . Count
2013-02-21 01:33:05 +00:00
} ;
2013-03-08 21:56:07 +00:00
if ( request . StartIndex . HasValue | | request . Limit . HasValue )
2013-02-21 01:33:05 +00:00
{
if ( request . StartIndex . HasValue )
{
ibnItems = ibnItems . Skip ( request . StartIndex . Value ) ;
}
2013-03-08 21:56:07 +00:00
if ( request . Limit . HasValue )
2013-02-21 01:33:05 +00:00
{
2013-03-08 21:56:07 +00:00
ibnItems = ibnItems . Take ( request . Limit . Value ) ;
2013-02-21 01:33:05 +00:00
}
}
2015-03-26 04:44:24 +00:00
IEnumerable < Tuple < TItemType , List < BaseItem > > > tuples ;
if ( dtoOptions . Fields . Contains ( ItemFields . ItemCounts ) | | true )
{
tuples = ibnItems . Select ( i = > new Tuple < TItemType , List < BaseItem > > ( i , i . GetTaggedItems ( libraryItems ) . ToList ( ) ) ) ;
}
else
{
tuples = ibnItems . Select ( i = > new Tuple < TItemType , List < BaseItem > > ( i , new List < BaseItem > ( ) ) ) ;
}
2014-11-30 19:01:33 +00:00
2015-03-26 04:44:24 +00:00
var dtos = tuples . Select ( i = > DtoService . GetItemByNameDto ( i . Item1 , dtoOptions , i . Item2 , user ) ) ;
2013-02-21 01:33:05 +00:00
2013-09-17 02:44:06 +00:00
result . Items = dtos . Where ( i = > i ! = null ) . ToArray ( ) ;
2013-02-21 01:33:05 +00:00
return result ;
}
2015-03-26 04:44:24 +00:00
private bool RequiresLibraryItems ( GetItemsByName request , DtoOptions options )
{
var filters = request . GetFilters ( ) . ToList ( ) ;
if ( filters . Contains ( ItemFilter . IsPlayed ) )
{
return true ;
}
if ( filters . Contains ( ItemFilter . IsUnplayed ) )
{
return true ;
}
if ( request . IsPlayed . HasValue )
{
return true ;
}
return true ;
return options . Fields . Contains ( ItemFields . ItemCounts ) ;
}
2014-03-09 22:14:44 +00:00
private IEnumerable < TItemType > FilterByLibraryItems ( GetItemsByName request , IEnumerable < TItemType > items , User user , IEnumerable < BaseItem > libraryItems )
2014-01-14 20:03:35 +00:00
{
var filters = request . GetFilters ( ) . ToList ( ) ;
if ( filters . Contains ( ItemFilter . IsPlayed ) )
{
2014-03-09 22:14:44 +00:00
items = items . Where ( i = > i . GetTaggedItems ( libraryItems ) . All ( l = > l . IsPlayed ( user ) ) ) ;
2014-01-14 20:03:35 +00:00
}
if ( filters . Contains ( ItemFilter . IsUnplayed ) )
{
2014-03-09 22:14:44 +00:00
items = items . Where ( i = > i . GetTaggedItems ( libraryItems ) . All ( l = > l . IsUnplayed ( user ) ) ) ;
2014-01-14 20:03:35 +00:00
}
2014-01-19 19:25:29 +00:00
if ( request . IsPlayed . HasValue )
{
var val = request . IsPlayed . Value ;
2014-03-09 22:14:44 +00:00
items = items . Where ( i = > i . GetTaggedItems ( libraryItems ) . All ( l = > l . IsPlayed ( user ) ) = = val ) ;
2014-01-19 19:25:29 +00:00
}
2014-01-14 20:03:35 +00:00
return items ;
}
2013-04-13 21:49:16 +00:00
/// <summary>
/// Filters the items.
/// </summary>
/// <param name="request">The request.</param>
/// <param name="items">The items.</param>
/// <param name="user">The user.</param>
2013-09-10 19:57:38 +00:00
/// <returns>IEnumerable{`0}.</returns>
private IEnumerable < TItemType > FilterItems ( GetItemsByName request , IEnumerable < TItemType > items , User user )
2013-04-13 21:49:16 +00:00
{
2013-05-17 03:24:41 +00:00
if ( ! string . IsNullOrEmpty ( request . NameStartsWithOrGreater ) )
2013-05-16 20:46:18 +00:00
{
2013-10-04 15:22:03 +00:00
items = items . Where ( i = > string . Compare ( request . NameStartsWithOrGreater , i . SortName , StringComparison . CurrentCultureIgnoreCase ) < 1 ) ;
}
2014-03-05 21:46:32 +00:00
if ( ! string . IsNullOrEmpty ( request . NameStartsWith ) )
2014-03-06 02:59:48 +00:00
{
2014-03-09 22:14:44 +00:00
items = items . Where ( i = > string . Compare ( request . NameStartsWith , i . SortName . Substring ( 0 , 1 ) , StringComparison . CurrentCultureIgnoreCase ) = = 0 ) ;
2014-03-06 02:59:48 +00:00
}
2013-10-04 15:22:03 +00:00
if ( ! string . IsNullOrEmpty ( request . NameLessThan ) )
{
items = items . Where ( i = > string . Compare ( request . NameLessThan , i . SortName , StringComparison . CurrentCultureIgnoreCase ) = = 1 ) ;
2013-05-16 20:46:18 +00:00
}
2013-09-20 00:53:18 +00:00
var imageTypes = request . GetImageTypes ( ) . ToList ( ) ;
if ( imageTypes . Count > 0 )
2013-09-06 05:13:43 +00:00
{
2014-10-08 01:37:45 +00:00
items = items . Where ( item = > imageTypes . Any ( item . HasImage ) ) ;
2013-09-06 05:13:43 +00:00
}
2013-09-10 19:30:56 +00:00
2013-04-13 21:49:16 +00:00
var filters = request . GetFilters ( ) . ToList ( ) ;
if ( filters . Contains ( ItemFilter . Dislikes ) )
{
items = items . Where ( i = >
2013-09-10 19:30:56 +00:00
{
2013-09-10 19:57:38 +00:00
var userdata = UserDataRepository . GetUserData ( user . Id , i . GetUserDataKey ( ) ) ;
2013-04-13 21:49:16 +00:00
2013-09-10 19:30:56 +00:00
return userdata ! = null & & userdata . Likes . HasValue & & ! userdata . Likes . Value ;
} ) ;
2013-04-13 21:49:16 +00:00
}
if ( filters . Contains ( ItemFilter . Likes ) )
{
items = items . Where ( i = >
{
2013-09-10 19:57:38 +00:00
var userdata = UserDataRepository . GetUserData ( user . Id , i . GetUserDataKey ( ) ) ;
2013-04-13 21:49:16 +00:00
return userdata ! = null & & userdata . Likes . HasValue & & userdata . Likes . Value ;
} ) ;
}
2013-07-30 20:31:25 +00:00
if ( filters . Contains ( ItemFilter . IsFavoriteOrLikes ) )
{
items = items . Where ( i = >
{
2013-09-10 19:57:38 +00:00
var userdata = UserDataRepository . GetUserData ( user . Id , i . GetUserDataKey ( ) ) ;
2013-07-30 20:31:25 +00:00
var likes = userdata . Likes ? ? false ;
var favorite = userdata . IsFavorite ;
return likes | | favorite ;
} ) ;
}
2013-09-10 19:30:56 +00:00
2013-04-13 21:49:16 +00:00
if ( filters . Contains ( ItemFilter . IsFavorite ) )
{
items = items . Where ( i = >
{
2013-09-10 19:57:38 +00:00
var userdata = UserDataRepository . GetUserData ( user . Id , i . GetUserDataKey ( ) ) ;
2013-04-13 21:49:16 +00:00
2013-10-21 03:01:22 +00:00
return userdata ! = null & & userdata . IsFavorite ;
2013-04-13 21:49:16 +00:00
} ) ;
}
2013-09-10 19:30:56 +00:00
2014-11-10 04:20:11 +00:00
// Avoid implicitly captured closure
var currentRequest = request ;
return items . Where ( i = > ApplyAdditionalFilters ( currentRequest , i , user , false ) ) ;
}
private bool ApplyAdditionalFilters ( BaseItemsRequest request , BaseItem i , User user , bool isPreFiltered )
{
if ( ! isPreFiltered )
{
// Apply tag filter
var tags = request . GetTags ( ) ;
if ( tags . Length > 0 )
{
var hasTags = i as IHasTags ;
if ( hasTags = = null )
{
return false ;
}
if ( ! ( tags . Any ( v = > hasTags . Tags . Contains ( v , StringComparer . OrdinalIgnoreCase ) ) ) )
{
return false ;
}
}
// Apply official rating filter
var officialRatings = request . GetOfficialRatings ( ) ;
if ( officialRatings . Length > 0 & & ! officialRatings . Contains ( i . OfficialRating ? ? string . Empty ) )
{
return false ;
}
// Apply genre filter
var genres = request . GetGenres ( ) ;
if ( genres . Length > 0 & & ! ( genres . Any ( v = > i . Genres . Contains ( v , StringComparer . OrdinalIgnoreCase ) ) ) )
{
return false ;
}
// Apply year filter
var years = request . GetYears ( ) ;
if ( years . Length > 0 & & ! ( i . ProductionYear . HasValue & & years . Contains ( i . ProductionYear . Value ) ) )
{
return false ;
}
}
return true ;
2013-04-13 21:49:16 +00:00
}
2013-09-10 19:30:56 +00:00
2014-11-10 04:20:11 +00:00
2013-03-02 07:16:52 +00:00
/// <summary>
2013-04-11 19:36:50 +00:00
/// Filters the items.
2013-03-02 07:16:52 +00:00
/// </summary>
/// <param name="request">The request.</param>
2015-01-25 06:34:50 +00:00
/// <param name="f">The f.</param>
/// <param name="excludeItemTypes">The exclude item types.</param>
/// <param name="includeItemTypes">The include item types.</param>
/// <param name="mediaTypes">The media types.</param>
2013-04-11 19:36:50 +00:00
/// <returns>IEnumerable{BaseItem}.</returns>
2015-01-25 06:34:50 +00:00
protected bool FilterItem ( GetItemsByName request , BaseItem f , string [ ] excludeItemTypes , string [ ] includeItemTypes , string [ ] mediaTypes )
2013-03-02 07:16:52 +00:00
{
2013-04-13 18:02:30 +00:00
// Exclude item types
2015-01-25 06:34:50 +00:00
if ( excludeItemTypes . Length > 0 )
2013-03-02 07:16:52 +00:00
{
2015-01-25 06:34:50 +00:00
if ( excludeItemTypes . Contains ( f . GetType ( ) . Name , StringComparer . OrdinalIgnoreCase ) )
{
return false ;
}
2013-03-02 07:16:52 +00:00
}
2013-04-13 18:02:30 +00:00
// Include item types
2015-01-25 06:34:50 +00:00
if ( includeItemTypes . Length > 0 )
2013-04-13 18:02:30 +00:00
{
2015-01-25 06:34:50 +00:00
if ( ! includeItemTypes . Contains ( f . GetType ( ) . Name , StringComparer . OrdinalIgnoreCase ) )
{
return false ;
}
2013-04-13 18:02:30 +00:00
}
2013-04-11 19:36:50 +00:00
2013-04-24 20:28:42 +00:00
// Include MediaTypes
2015-01-25 06:34:50 +00:00
if ( mediaTypes . Length > 0 )
2013-04-24 20:28:42 +00:00
{
2015-01-25 06:34:50 +00:00
if ( ! mediaTypes . Contains ( f . MediaType ? ? string . Empty , StringComparer . OrdinalIgnoreCase ) )
{
return false ;
}
2013-04-24 20:28:42 +00:00
}
2013-09-10 19:30:56 +00:00
2015-01-25 06:34:50 +00:00
return true ;
2013-03-02 07:16:52 +00:00
}
2013-02-21 01:33:05 +00:00
/// <summary>
/// Gets all items.
/// </summary>
/// <param name="request">The request.</param>
/// <param name="items">The items.</param>
2013-09-10 19:57:38 +00:00
/// <returns>IEnumerable{Task{`0}}.</returns>
2013-09-17 02:08:18 +00:00
protected abstract IEnumerable < TItemType > GetAllItems ( GetItemsByName request , IEnumerable < BaseItem > items ) ;
2013-02-21 01:33:05 +00:00
}
/// <summary>
/// Class GetItemsByName
/// </summary>
2013-03-11 05:06:55 +00:00
public class GetItemsByName : BaseItemsRequest , IReturn < ItemsResult >
2013-02-21 01:33:05 +00:00
{
2013-04-22 04:38:03 +00:00
/// <summary>
/// Gets or sets the user id.
/// </summary>
/// <value>The user id.</value>
[ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public Guid ? UserId { get ; set ; }
2013-05-17 03:24:41 +00:00
[ApiMember(Name = "NameStartsWithOrGreater", Description = "Optional filter by items whose name is sorted equally or greater than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string NameStartsWithOrGreater { get ; set ; }
2014-03-06 02:59:48 +00:00
2014-03-05 21:46:32 +00:00
[ApiMember(Name = "NameStartsWith", Description = "Optional filter by items whose name is sorted equally than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string NameStartsWith { get ; set ; }
2013-09-10 19:30:56 +00:00
2013-10-04 15:22:03 +00:00
[ApiMember(Name = "NameLessThan", Description = "Optional filter by items whose name is sorted less than a given input string.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string NameLessThan { get ; set ; }
2014-03-09 22:14:44 +00:00
2013-04-22 04:38:03 +00:00
public GetItemsByName ( )
{
Recursive = true ;
}
2013-02-21 01:33:05 +00:00
}
}