Fixed #4532 Items media in beta version are showing now (#4551)

* logs

* Issue resolved

* Logs removed

* Beta working

* Production GET call only for fetch images from depicted item

* Code convention maintained

* Code convention maintained

* Test resolved

* Java Docs added

* Quotes added
This commit is contained in:
Ayan Sarkar 2022-01-19 20:40:55 +05:30 committed by GitHub
parent 7bcaab2442
commit 0914eeea53
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 162 additions and 5 deletions

View file

@ -0,0 +1,18 @@
package fr.free.nrw.commons
/**
* Production variant related constants which is used in beta variant for some specific GET calls on
* production server where beta server does not work
*/
object BetaConstants {
/**
* Commons production URL which is used in beta for some specific GET calls on
* production server where beta server does not work
*/
const val COMMONS_URL = "https://commons.wikimedia.org/"
/**
* Commons production's depicts property which is used in beta for some specific GET calls on
* production server where beta server does not work
*/
const val DEPICTS_PROPERTY = "P180"
}

View file

@ -5,6 +5,7 @@ import androidx.annotation.NonNull;
import com.google.gson.Gson;
import dagger.Module;
import dagger.Provides;
import fr.free.nrw.commons.BetaConstants;
import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.actions.PageEditClient;
import fr.free.nrw.commons.actions.PageEditInterface;
@ -14,6 +15,7 @@ import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.media.MediaDetailInterface;
import fr.free.nrw.commons.media.MediaInterface;
import fr.free.nrw.commons.media.PageMediaInterface;
import fr.free.nrw.commons.media.WikidataMediaInterface;
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
import fr.free.nrw.commons.mwapi.UserInterface;
import fr.free.nrw.commons.review.ReviewInterface;
@ -226,6 +228,20 @@ public class NetworkingModule {
return ServiceFactory.get(commonsWikiSite, BuildConfig.COMMONS_URL, MediaInterface.class);
}
/**
* Add provider for WikidataMediaInterface
* It creates a retrofit service for the commons wiki site
* @param commonsWikiSite commonsWikiSite
* @return WikidataMediaInterface
*/
@Provides
@Singleton
public WikidataMediaInterface provideWikidataMediaInterface(
@Named(NAMED_COMMONS_WIKI_SITE) final WikiSite commonsWikiSite) {
return ServiceFactory.get(commonsWikiSite,
BetaConstants.COMMONS_URL, WikidataMediaInterface.class);
}
@Provides
@Singleton
public MediaDetailInterface providesMediaDetailInterface(@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikisite) {

View file

@ -1,17 +1,17 @@
package fr.free.nrw.commons.explore.depictions.media
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.explore.depictions.search.LoadFunction
import fr.free.nrw.commons.explore.paging.LiveDataConverter
import fr.free.nrw.commons.explore.paging.PageableBaseDataSource
import fr.free.nrw.commons.explore.depictions.search.LoadFunction
import fr.free.nrw.commons.media.MediaClient
import fr.free.nrw.commons.media.WikidataMediaClient
import javax.inject.Inject
class PageableDepictedMediaDataSource @Inject constructor(
liveDataConverter: LiveDataConverter,
private val mediaClient: MediaClient
private val wikiMediaClient: WikidataMediaClient
) : PageableBaseDataSource<Media>(liveDataConverter) {
override val loadFunction: LoadFunction<Media> = { loadSize: Int, startPosition: Int ->
mediaClient.fetchImagesForDepictedItem(query, loadSize, startPosition).blockingGet()
wikiMediaClient.fetchImagesForDepictedItem(query, loadSize, startPosition).blockingGet()
}
}

View file

@ -0,0 +1,93 @@
package fr.free.nrw.commons.media
import fr.free.nrw.commons.BetaConstants
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.category.ContinuationClient
import fr.free.nrw.commons.explore.media.MediaConverter
import io.reactivex.Single
import org.wikipedia.dataclient.mwapi.MwQueryPage
import org.wikipedia.dataclient.mwapi.MwQueryResponse
import org.wikipedia.wikidata.Entities
import javax.inject.Inject
import javax.inject.Singleton
/**
* Media Client to handle custom calls to Commons MediaWiki APIs of production server
*/
@Singleton
class WikidataMediaClient @Inject constructor(
private val wikidataMediaInterface: WikidataMediaInterface,
private val mediaDetailInterface: MediaDetailInterface,
private val mediaConverter: MediaConverter
) : ContinuationClient<MwQueryResponse, Media>() {
/**
* Fetch images for depict ID
*
* @param query depictionEntityId ex. "Q9394"
* @param srlimit the number of items to fetch
* @param sroffset number of depictions already fetched,
* this is useful in implementing pagination
* @return list of images for a particular depict ID
*/
fun fetchImagesForDepictedItem(
query: String,
srlimit: Int,
sroffset: Int
): Single<List<Media>> {
return responseMapper(
wikidataMediaInterface.fetchImagesForDepictedItem(
"haswbstatement:" + BetaConstants.DEPICTS_PROPERTY + "=" + query,
srlimit.toString(),
sroffset.toString()
)
)
}
/**
* Helps to map to the required data from the API response
*
* @param networkResult MwQueryResponse
* @param key for handling continuation request, this is null in this case
*/
override fun responseMapper(
networkResult: Single<MwQueryResponse>,
key: String?
): Single<List<Media>> {
return networkResult.map {
handleContinuationResponse(it.continuation(), key)
it.query()?.pages() ?: emptyList()
}.flatMap(::mediaFromPageAndEntity)
}
/**
* Gets list of Media from MwQueryPage
*/
private fun mediaFromPageAndEntity(pages: List<MwQueryPage>): Single<List<Media>> {
return if (pages.isEmpty())
Single.just(emptyList())
else
getEntities(pages.map { "$PAGE_ID_PREFIX${it.pageId()}" })
.map {
pages.zip(it.entities().values)
.mapNotNull { (page, entity) ->
page.imageInfo()?.let {
mediaConverter.convert(page, entity, it)
}
}
}
}
/**
* Gets Entities from IDs
*
* @param entityIds list of IDs of pages/entities ex. {"M4254154", "M11413343"}
*/
fun getEntities(entityIds: List<String>): Single<Entities> {
return if (entityIds.isEmpty())
Single.error(Exception("empty list passed for ids"))
else
mediaDetailInterface.getEntity(entityIds.joinToString("|"))
}
}

View file

@ -0,0 +1,29 @@
package fr.free.nrw.commons.media;
import static fr.free.nrw.commons.media.MediaInterface.MEDIA_PARAMS;
import io.reactivex.Single;
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
import retrofit2.http.GET;
import retrofit2.http.Query;
/**
* Interface for getting Wikidata images from production server
*/
public interface WikidataMediaInterface {
/**
* Fetches list of images from a depiction entity
* @param query depictionEntityId ex. "haswbstatement:P180=Q9394"
* @param srlimit the number of items to fetch
* @param sroffset number of depictions already fetched,
* this is useful in implementing pagination
* @return Single<MwQueryResponse>
*/
@GET("w/api.php?action=query&format=json&formatversion=2" + //Basic parameters
"&generator=search&gsrnamespace=6" + //Search parameters
MEDIA_PARAMS)
Single<MwQueryResponse> fetchImagesForDepictedItem(@Query("gsrsearch") String query,
@Query("gsrlimit")String srlimit, @Query("gsroffset") String sroffset);
}

View file

@ -3,6 +3,7 @@ package fr.free.nrw.commons.explore.depictions.media
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.whenever
import fr.free.nrw.commons.media.MediaClient
import fr.free.nrw.commons.media.WikidataMediaClient
import io.reactivex.Single
import org.junit.Assert
import org.junit.Test
@ -10,7 +11,7 @@ import org.junit.Test
class PageableDepictedMediaDataSourceTest{
@Test
fun `loadFunction loads Media`() {
val mediaClient = mock<MediaClient>()
val mediaClient = mock<WikidataMediaClient>()
whenever(mediaClient.fetchImagesForDepictedItem("test",0,1))
.thenReturn(Single.just(emptyList()))
val pageableDepictedMediaDataSource = PageableDepictedMediaDataSource(mock(), mediaClient)