Skip to content

Commit a9ae072

Browse files
committed
Merge remote-tracking branch 'refs/remotes/commons-app/master' into upload-overhaul-fork
# Conflicts: # app/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java
2 parents 3ccfcac + 32d45b2 commit a9ae072

28 files changed

+415
-35
lines changed

PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ Tested on {API level & name of device/emulator}, with {build variant, e.g. ProdD
1616

1717
{Only for user interface changes, otherwise remove this section. See [how to take a screenshot](https://android.stackexchange.com/questions/1759/how-to-take-a-screenshot-with-an-android-device)}
1818

19-
_Note: Please ensure that you have read CONTRIBUTING.md if this is your first pull request._
19+
_Note: Please ensure that you have read CONTRIBUTING.md if this is your first pull request._

app/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ android {
135135
productFlavors {
136136
prod {
137137
buildConfigField "String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.org/w/api.php\""
138+
buildConfigField "String", "WIKIDATA_API_HOST", "\"https://www.wikidata.org/w/api.php\""
138139
buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\""
139140
buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.wikimedia.org/wikipedia/commons\""
140141
buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.org/wiki/\""
@@ -151,6 +152,7 @@ android {
151152
beta {
152153
// What values do we need to hit the BETA versions of the site / api ?
153154
buildConfigField "String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.beta.wmflabs.org/w/api.php\""
155+
buildConfigField "String", "WIKIDATA_API_HOST", "\"https://www.wikidata.org/w/api.php\""
154156
buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\""
155157
buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.beta.wmflabs.org/wikipedia/commons\""
156158
buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.beta.wmflabs.org/wiki/\""

app/src/main/java/fr/free/nrw/commons/CommonsApplication.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import javax.inject.Inject;
2121
import javax.inject.Named;
2222

23+
import fr.free.nrw.commons.BuildConfig;
2324
import fr.free.nrw.commons.auth.SessionManager;
2425
import fr.free.nrw.commons.category.CategoryDao;
2526
import fr.free.nrw.commons.contributions.ContributionDao;

app/src/main/java/fr/free/nrw/commons/Utils.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ public static void rateApp(Context context) {
178178
}
179179

180180
public static void handleWebUrl(Context context, Uri url) {
181+
Timber.d("Launching web url %s", url.toString());
181182
Intent browserIntent = new Intent(Intent.ACTION_VIEW, url);
182183
if (browserIntent.resolveActivity(context.getPackageManager()) == null) {
183184
Toast toast = Toast.makeText(context, context.getString(R.string.no_web_browser), LENGTH_SHORT);

app/src/main/java/fr/free/nrw/commons/category/CategoryImagesListFragment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ public ListAdapter getAdapter() {
228228
/**
229229
* This method will be called on back pressed of CategoryImagesActivity.
230230
* It initializes the grid view by setting adapter.
231-
\ */
231+
*/
232232
@Override
233233
public void onResume() {
234234
gridView.setAdapter(gridAdapter);

app/src/main/java/fr/free/nrw/commons/contributions/Contribution.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public Contribution[] newArray(int i) {
4545
private long transferred;
4646
private String decimalCoords;
4747
private boolean isMultiple;
48+
private String wikiDataEntityId;
4849

4950
public Contribution(Uri contentUri, String filename, Uri localUri, String imageUrl, Date timestamp,
5051
int state, long dataLength, Date dateUploaded, long transferred,
@@ -222,4 +223,17 @@ private String licenseTemplateFor(String license) {
222223

223224
throw new RuntimeException("Unrecognized license value: " + license);
224225
}
226+
227+
public String getWikiDataEntityId() {
228+
return wikiDataEntityId;
229+
}
230+
231+
/**
232+
* When the corresponding wikidata entity is known as in case of nearby uploads, it can be set
233+
* using the setter method
234+
* @param wikiDataEntityId
235+
*/
236+
public void setWikiDataEntityId(String wikiDataEntityId) {
237+
this.wikiDataEntityId = wikiDataEntityId;
238+
}
225239
}

app/src/main/java/fr/free/nrw/commons/contributions/ContributionController.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public void startGalleryPick() {
9090
fragment.startActivityForResult(pickImageIntent, SELECT_FROM_GALLERY);
9191
}
9292

93-
public void handleImagePicked(int requestCode, Intent data, boolean isDirectUpload) {
93+
public void handleImagePicked(int requestCode, Intent data, boolean isDirectUpload, String wikiDataEntityId) {
9494
FragmentActivity activity = fragment.getActivity();
9595
Timber.d("handleImagePicked() called with onActivityResult()");
9696
Intent shareIntent = new Intent(activity, ShareActivity.class);
@@ -102,9 +102,6 @@ public void handleImagePicked(int requestCode, Intent data, boolean isDirectUplo
102102
shareIntent.setType(activity.getContentResolver().getType(imageData));
103103
shareIntent.putExtra(EXTRA_STREAM, imageData);
104104
shareIntent.putExtra(EXTRA_SOURCE, SOURCE_GALLERY);
105-
if (isDirectUpload) {
106-
shareIntent.putExtra("isDirectUpload", true);
107-
}
108105
break;
109106
case SELECT_FROM_CAMERA:
110107
//FIXME: Find out appropriate mime type
@@ -113,16 +110,17 @@ public void handleImagePicked(int requestCode, Intent data, boolean isDirectUplo
113110
shareIntent.setType("image/jpeg");
114111
shareIntent.putExtra(EXTRA_STREAM, lastGeneratedCaptureUri);
115112
shareIntent.putExtra(EXTRA_SOURCE, SOURCE_CAMERA);
116-
if (isDirectUpload) {
117-
shareIntent.putExtra("isDirectUpload", true);
118-
}
119113

120114
break;
121115
default:
122116
break;
123117
}
124118
Timber.i("Image selected");
125119
try {
120+
shareIntent.putExtra("isDirectUpload", isDirectUpload);
121+
if (wikiDataEntityId != null && !wikiDataEntityId.equals("")) {
122+
shareIntent.putExtra("wikiDataEntityId", wikiDataEntityId);
123+
}
126124
activity.startActivity(shareIntent);
127125
} catch (SecurityException e) {
128126
Timber.e(e, "Security Exception");

app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
117117
if (resultCode == RESULT_OK) {
118118
Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
119119
requestCode, resultCode, data);
120-
controller.handleImagePicked(requestCode, data, false);
120+
controller.handleImagePicked(requestCode, data, false, null);
121121
} else {
122122
Timber.e("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
123123
requestCode, resultCode, data);

app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,25 @@
66
import android.preference.PreferenceManager;
77
import android.support.v4.util.LruCache;
88

9+
import com.google.gson.Gson;
10+
911
import javax.inject.Named;
1012
import javax.inject.Singleton;
1113

1214
import dagger.Module;
1315
import dagger.Provides;
16+
17+
import fr.free.nrw.commons.BuildConfig;
1418
import fr.free.nrw.commons.auth.AccountUtil;
1519
import fr.free.nrw.commons.auth.SessionManager;
1620
import fr.free.nrw.commons.data.DBOpenHelper;
1721
import fr.free.nrw.commons.location.LocationServiceManager;
22+
import fr.free.nrw.commons.mwapi.ApacheHttpClientMediaWikiApi;
1823
import fr.free.nrw.commons.mwapi.MediaWikiApi;
1924
import fr.free.nrw.commons.nearby.NearbyPlaces;
2025
import fr.free.nrw.commons.upload.UploadController;
26+
import fr.free.nrw.commons.wikidata.WikidataEditListener;
27+
import fr.free.nrw.commons.wikidata.WikidataEditListenerImpl;
2128

2229
import static android.content.Context.MODE_PRIVATE;
2330
import static fr.free.nrw.commons.contributions.ContributionsContentProvider.CONTRIBUTION_AUTHORITY;
@@ -133,4 +140,10 @@ public NearbyPlaces provideNearbyPlaces() {
133140
public LruCache<String, String> provideLruCache() {
134141
return new LruCache<>(1024);
135142
}
143+
144+
@Provides
145+
@Singleton
146+
public WikidataEditListener provideWikidataEditListener() {
147+
return new WikidataEditListenerImpl();
148+
}
136149
}

app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public MediaWikiApi provideMediaWikiApi(Context context,
3535
@Named("default_preferences") SharedPreferences defaultPreferences,
3636
@Named("category_prefs") SharedPreferences categoryPrefs,
3737
Gson gson) {
38-
return new ApacheHttpClientMediaWikiApi(context, BuildConfig.WIKIMEDIA_API_HOST, defaultPreferences, categoryPrefs, gson);
38+
return new ApacheHttpClientMediaWikiApi(context, BuildConfig.WIKIMEDIA_API_HOST, BuildConfig.WIKIDATA_API_HOST, defaultPreferences, categoryPrefs, gson);
3939
}
4040

4141
@Provides

app/src/main/java/fr/free/nrw/commons/location/LocationServiceManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ public enum LocationChangeType{
284284
LOCATION_SIGNIFICANTLY_CHANGED, //Went out of borders of nearby markers
285285
LOCATION_SLIGHTLY_CHANGED, //User might be walking or driving
286286
LOCATION_NOT_CHANGED,
287-
PERMISSION_JUST_GRANTED
287+
PERMISSION_JUST_GRANTED,
288+
MAP_UPDATED
288289
}
289290
}

app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
import android.widget.TextView;
2424
import android.widget.Toast;
2525

26+
import butterknife.BindView;
27+
import butterknife.ButterKnife;
28+
import butterknife.OnClick;
2629
import java.io.IOException;
2730
import java.text.SimpleDateFormat;
2831
import java.util.ArrayList;

app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import org.apache.http.util.EntityUtils;
2626
import org.mediawiki.api.ApiResult;
2727
import org.mediawiki.api.MWApi;
28+
import org.w3c.dom.Element;
29+
import org.w3c.dom.Node;
2830
import org.w3c.dom.NodeList;
2931

3032
import java.io.IOException;
@@ -62,13 +64,15 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
6264
private static final String THUMB_SIZE = "640";
6365
private AbstractHttpClient httpClient;
6466
private MWApi api;
67+
private MWApi wikidataApi;
6568
private Context context;
6669
private SharedPreferences defaultPreferences;
6770
private SharedPreferences categoryPreferences;
6871
private Gson gson;
6972

7073
public ApacheHttpClientMediaWikiApi(Context context,
7174
String apiURL,
75+
String wikidatApiURL,
7276
SharedPreferences defaultPreferences,
7377
SharedPreferences categoryPreferences,
7478
Gson gson) {
@@ -82,6 +86,7 @@ public ApacheHttpClientMediaWikiApi(Context context,
8286
params.setParameter(CoreProtocolPNames.USER_AGENT, getUserAgent());
8387
httpClient = new DefaultHttpClient(cm, params);
8488
api = new MWApi(apiURL, httpClient);
89+
wikidataApi = new MWApi(wikidatApiURL, httpClient);
8590
this.defaultPreferences = defaultPreferences;
8691
this.categoryPreferences = categoryPreferences;
8792
this.gson = gson;
@@ -206,6 +211,15 @@ public String getEditToken() throws IOException {
206211
return api.getEditToken();
207212
}
208213

214+
@Override
215+
public String getCentralAuthToken() throws IOException {
216+
String centralAuthToken = api.action("centralauthtoken")
217+
.get()
218+
.getString("/api/centralauthtoken/@centralauthtoken");
219+
Timber.d("MediaWiki Central auth token is %s", centralAuthToken);
220+
return centralAuthToken;
221+
}
222+
209223
@Override
210224
public boolean fileExistsWithName(String fileName) throws IOException {
211225
return api.action("query")
@@ -351,6 +365,98 @@ public Observable<String> allCategories(String filterValue, int searchCatsLimit)
351365
}).flatMapObservable(Observable::fromIterable);
352366
}
353367

368+
/**
369+
* Get the edit token for making wiki data edits
370+
* https://www.mediawiki.org/wiki/API:Tokens
371+
* @return
372+
* @throws IOException
373+
*/
374+
private String getWikidataEditToken() throws IOException {
375+
return wikidataApi.getEditToken();
376+
}
377+
378+
@Override
379+
public String getWikidataCsrfToken() throws IOException {
380+
String wikidataCsrfToken = wikidataApi.action("query")
381+
.param("action", "query")
382+
.param("centralauthtoken", getCentralAuthToken())
383+
.param("meta", "tokens")
384+
.post()
385+
.getString("/api/query/tokens/@csrftoken");
386+
Timber.d("Wikidata csrf token is %s", wikidataCsrfToken);
387+
return wikidataCsrfToken;
388+
}
389+
390+
/**
391+
* Creates a new claim using the wikidata API
392+
* https://www.mediawiki.org/wiki/Wikibase/API
393+
* @param entityId the wikidata entity to be edited
394+
* @param property the property to be edited, for eg P18 for images
395+
* @param snaktype the type of value stored for that property
396+
* @param value the actual value to be stored for the property, for eg filename in case of P18
397+
* @return returns revisionId if the claim is successfully created else returns null
398+
* @throws IOException
399+
*/
400+
@Nullable
401+
@Override
402+
public String wikidatCreateClaim(String entityId, String property, String snaktype, String value) throws IOException {
403+
Timber.d("Filename is %s", value);
404+
ApiResult result = wikidataApi.action("wbcreateclaim")
405+
.param("entity", entityId)
406+
.param("centralauthtoken", getCentralAuthToken())
407+
.param("token", getWikidataCsrfToken())
408+
.param("snaktype", snaktype)
409+
.param("property", property)
410+
.param("value", value)
411+
.post();
412+
413+
if (result == null || result.getNode("api") == null) {
414+
return null;
415+
}
416+
417+
Node node = result.getNode("api").getDocument();
418+
Element element = (Element) node;
419+
420+
if (element != null && element.getAttribute("success").equals("1")) {
421+
return result.getString("api/pageinfo/@lastrevid");
422+
} else {
423+
Timber.e(result.getString("api/error/@code") + " " + result.getString("api/error/@info"));
424+
}
425+
return null;
426+
}
427+
428+
/**
429+
* Adds the wikimedia-commons-app tag to the edits made on wikidata
430+
* @param revisionId
431+
* @return
432+
* @throws IOException
433+
*/
434+
@Nullable
435+
@Override
436+
public boolean addWikidataEditTag(String revisionId) throws IOException {
437+
ApiResult result = wikidataApi.action("tag")
438+
.param("revid", revisionId)
439+
.param("centralauthtoken", getCentralAuthToken())
440+
.param("token", getWikidataCsrfToken())
441+
.param("add", "wikimedia-commons-app")
442+
.param("reason", "Add tag for edits made using Android Commons app")
443+
.post();
444+
445+
if (result == null || result.getNode("api") == null) {
446+
return false;
447+
}
448+
449+
Node node = result.getNode("api").getDocument();
450+
Element element = (Element) node;
451+
452+
if (element != null && element.getAttribute("status").equals("success")) {
453+
return true;
454+
} else {
455+
Timber.e(result.getString("api/error/@code") + " " + result.getString("api/error/@info"));
456+
}
457+
return false;
458+
}
459+
354460
@Override
355461
@NonNull
356462
public Observable<String> searchTitles(String title, int searchCatsLimit) {
@@ -586,6 +692,7 @@ public UploadResult uploadFile(String filename,
586692
String resultStatus = result.getString("/api/upload/@result");
587693
if (!resultStatus.equals("Success")) {
588694
String errorCode = result.getString("/api/error/@code");
695+
Timber.e(errorCode);
589696
return new UploadResult(resultStatus, errorCode);
590697
} else {
591698
Date dateUploaded = parseMWDate(result.getString("/api/upload/imageinfo/@timestamp"));

app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ public interface MediaWikiApi {
2727

2828
String getEditToken() throws IOException;
2929

30+
String getWikidataCsrfToken() throws IOException;
31+
32+
String getCentralAuthToken() throws IOException;
33+
3034
boolean fileExistsWithName(String fileName) throws IOException;
3135

3236
boolean pageExists(String pageName) throws IOException;
@@ -49,6 +53,12 @@ public interface MediaWikiApi {
4953
@Nullable
5054
String appendEdit(String editToken, String processedPageContent, String filename, String summary) throws IOException;
5155

56+
@Nullable
57+
String wikidatCreateClaim(String entityId, String property, String snaktype, String value) throws IOException;
58+
59+
@Nullable
60+
boolean addWikidataEditTag(String revisionId) throws IOException;
61+
5262
@NonNull
5363
MediaResult fetchMediaByFilename(String filename) throws IOException;
5464

0 commit comments

Comments
 (0)