mirror of
				https://github.com/commons-app/apps-android-commons.git
				synced 2025-10-30 22:34:02 +01:00 
			
		
		
		
	If depicted Wikidata item has no associated Commons category property, then suggest categories from its P18 (#6130)
* Fix NPE with UploadMediaDetails.captionText * Store P18 instead of processed image url in DepictedItem * Add routes for fetching category info from titles * Consider depict's P18 when suggesting categories * Add tests * Corrected DepictedItem constructor arguments * Add test for DepictedItem::primaryImage
This commit is contained in:
		
							parent
							
								
									1f33926ed5
								
							
						
					
					
						commit
						1e64acdf1d
					
				
					 7 changed files with 212 additions and 28 deletions
				
			
		|  | @ -127,30 +127,64 @@ class CategoriesModel | |||
|         /** | ||||
|          * Fetches details of every category associated with selected depictions, converts them into | ||||
|          * CategoryItem and returns them in a list. | ||||
|          * If a selected depiction has no categories, the categories in which its P18 belongs are | ||||
|          * returned in the list. | ||||
|          * | ||||
|          * @param selectedDepictions selected DepictItems | ||||
|          * @return List of CategoryItem associated with selected depictions | ||||
|          */ | ||||
|         private fun categoriesFromDepiction(selectedDepictions: List<DepictedItem>): Observable<MutableList<CategoryItem>>? = | ||||
|             Observable | ||||
|                 .fromIterable( | ||||
|                     selectedDepictions.map { it.commonsCategories }.flatten(), | ||||
|                 ).map { categoryItem -> | ||||
|                     categoryClient | ||||
|                         .getCategoriesByName( | ||||
|                             categoryItem.name, | ||||
|                             categoryItem.name, | ||||
|                             SEARCH_CATS_LIMIT, | ||||
|                         ).map { | ||||
|                             CategoryItem( | ||||
|                                 it[0].name, | ||||
|                                 it[0].description, | ||||
|                                 it[0].thumbnail, | ||||
|                                 it[0].isSelected, | ||||
|                             ) | ||||
|                         }.blockingGet() | ||||
|                 }.toList() | ||||
|                 .toObservable() | ||||
|         private fun categoriesFromDepiction(selectedDepictions: List<DepictedItem>): Observable<MutableList<CategoryItem>>? { | ||||
|             val observables =  selectedDepictions.map { depictedItem -> | ||||
|                 if (depictedItem.commonsCategories.isEmpty()) { | ||||
|                     if (depictedItem.primaryImage == null) { | ||||
|                         return@map Observable.just(emptyList<CategoryItem>()) | ||||
|                     } | ||||
|                     Observable.just( | ||||
|                             depictedItem.primaryImage | ||||
|                         ).map { image -> | ||||
|                             categoryClient | ||||
|                                 .getCategoriesOfImage( | ||||
|                                     image, | ||||
|                                     SEARCH_CATS_LIMIT, | ||||
|                                 ).map { | ||||
|                                     it.map { category -> | ||||
|                                         CategoryItem( | ||||
|                                             category.name, | ||||
|                                             category.description, | ||||
|                                             category.thumbnail, | ||||
|                                             category.isSelected, | ||||
|                                         ) | ||||
|                                     } | ||||
|                                 }.blockingGet() | ||||
|                         }.flatMapIterable { it }.toList() | ||||
|                         .toObservable() | ||||
|                 } else { | ||||
|                     Observable | ||||
|                         .fromIterable( | ||||
|                             depictedItem.commonsCategories, | ||||
|                         ).map { categoryItem -> | ||||
|                             categoryClient | ||||
|                                 .getCategoriesByName( | ||||
|                                     categoryItem.name, | ||||
|                                     categoryItem.name, | ||||
|                                     SEARCH_CATS_LIMIT, | ||||
|                                 ).map { | ||||
|                                     CategoryItem( | ||||
|                                         it[0].name, | ||||
|                                         it[0].description, | ||||
|                                         it[0].thumbnail, | ||||
|                                         it[0].isSelected, | ||||
|                                     ) | ||||
|                                 }.blockingGet() | ||||
|                         }.toList() | ||||
|                         .toObservable() | ||||
|                 } | ||||
|             } | ||||
|             return Observable.concat(observables) | ||||
|                 .scan(mutableListOf<CategoryItem>()) { accumulator, currentList -> | ||||
|                     accumulator.apply { addAll(currentList) } | ||||
|                 } | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * Fetches details of every category by their name, converts them into | ||||
|  |  | |||
|  | @ -78,6 +78,24 @@ class CategoryClient | |||
|                 ), | ||||
|             ) | ||||
| 
 | ||||
|         /** | ||||
|          * Fetches categories belonging to an image (P18 of some wikidata entity). | ||||
|          * | ||||
|          * @param image P18 of some wikidata entity | ||||
|          * @param itemLimit How many categories to return | ||||
|          * @return Single Observable emitting the list of categories | ||||
|          */ | ||||
|         fun getCategoriesOfImage( | ||||
|             image: String, | ||||
|             itemLimit: Int, | ||||
|         ): Single<List<CategoryItem>> = | ||||
|             responseMapper( | ||||
|                 categoryInterface.getCategoriesByTitles( | ||||
|                     "File:${image}", | ||||
|                     itemLimit, | ||||
|                 ), | ||||
|             ) | ||||
| 
 | ||||
|         /** | ||||
|          * The method takes categoryName as input and returns a List of Subcategories | ||||
|          * It uses the generator query API to get the subcategories in a category, 500 at a time. | ||||
|  |  | |||
|  | @ -61,6 +61,21 @@ interface CategoryInterface { | |||
|         @Query("gacoffset") offset: Int, | ||||
|     ): Single<MwQueryResponse> | ||||
| 
 | ||||
|     /** | ||||
|      * Fetches non-hidden categories by titles. | ||||
|      * | ||||
|      * @param titles titles to fetch categories for (e.g. File:<P18 of a wikidata entity>) | ||||
|      * @param itemLimit How many categories to return | ||||
|      * @return MwQueryResponse | ||||
|      */ | ||||
|     @GET( | ||||
|         "w/api.php?action=query&format=json&formatversion=2&generator=categories&prop=categoryinfo|description|pageimages&piprop=thumbnail&pithumbsize=70&gclshow=!hidden", | ||||
|     ) | ||||
|     fun getCategoriesByTitles( | ||||
|         @Query("titles") titles: String?, | ||||
|         @Query("gcllimit") itemLimit: Int, | ||||
|     ): Single<MwQueryResponse> | ||||
| 
 | ||||
|     @GET("w/api.php?action=query&format=json&formatversion=2&generator=categorymembers&gcmtype=subcat&prop=info&gcmlimit=50") | ||||
|     fun getSubCategoryList( | ||||
|         @Query("gcmtitle") categoryName: String, | ||||
|  |  | |||
|  | @ -68,6 +68,9 @@ data class DepictedItem constructor( | |||
|         entity.id(), | ||||
|     ) | ||||
| 
 | ||||
|     val primaryImage: String? | ||||
|         get() = imageUrl?.split('-')?.lastOrNull() | ||||
| 
 | ||||
|     override fun equals(other: Any?) = | ||||
|         when { | ||||
|             this === other -> true | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tanmay Gupta
						Tanmay Gupta