Skip to content

Commit 4815e93

Browse files
Vivek Maskaramisaochan
authored andcommitted
Make P18 edits to corresponding wikidata entity on uploading from Nearby (#1495)
* Localisation updates from https://translatewiki.net. * Integrate API for displaying featured images (#1456) * Integrate API for displaying featured images * Add pagination and refactor code so that it can be reused for category images * Add license info to the images * Fix author view * Remove unused values * Fix minor issues with featured images * Fix null license url issue * Remove some log lines * Fix back navigation issue * fix tests * fix test inits * Gracefully handling various error situations * Added java docs * Update pull_request_template.md (#1476) * Update pull_request_template.md * Remove Javadocs mention * Added required/optional notes * resolves #1464 : MediaDataExtractor is making inefficient (redundant) server calls (#1496) * Open map of place where picture was taken (#1360) * Intent to map added * Merge conflicts resolved * Added the functionality to hide FAB incase of null coordinate * Merge Conflict resolved * Improve pr quality * Improve Quality * Added nested FAB animations * Nested FAB implemented * Improve Quality * Added up arrow * Javadocs Added * Add nearby tutorial (#1467) * Add dependency for MaterialShowcase * Add actionview class to get a reference to material showcase * Create a NearbyMaterialShowcaseSequence class * Apply sequence steps * Add first three steps of nearby showcase * Add sequence id constants to make sure they will be displayed only once * Add last step of sequence to explain plus fab * Create an object to prevent customize all sequences every time * Fix typo * Code cleanup * Add strings to strings.xml * Code cleanup * Revert irrelevant change * Revert irrelevant change * Remove showcaseview for recenter button * Use single showcaseView instead of sequence * Add single showcase view insted of sequence to be able to edit text style * Make sure it will be displayed only once * Cleanup * Update strings * Change dismiss text style * CONTRIBUTING: fix formatting of the gist of the guidelines (#1453) * CONTRIBUTING: fix formatting of the gist of the guidelines First level headings for a gist seems to be overkill. So, replace first level headings with an ordered-list which sounds more meaningful. * CONTRIBUTING: specify clearly that 'blame' is a feature of "Git" The contributing file specifies about the ability to know who wrote something without the need of @author javadoc tags but incorrectly attributes the feature to GitHub. Correctly attribute the feature to where it belongs, Git, and specify the name of the feature to help users easily take advantage of it. * Feature/switch to butterknife (#1494) * Implemented butterknife in MediaDetailFragment [issue #1491] * Implemented butterknife in MediaDetailPagerFragment [[issue #1491]] * post merge upstream master wip [[issue #1491]] * Localisation updates from https://translatewiki.net. * Bug fix #1504 (#1506) * Bug fix #1504 * Filtered messages with ConnectException [issue #1504] * A generalised message for exceptions in Nearby Activity [issue #1504] * Localisation updates from https://translatewiki.net. * Fix security exception crash while accessing network location provider (#1498) * Fix security exception crash while accessing network location provider * Added java docs * Localisation updates from https://translatewiki.net. * Log P18 edits to wikidata corresponding wikidata entity on uploading a nearby image * Added java docs * Fix test build * Refresh nearby * Refresh nearby list on successful edit * Java docs * Make authenticated wikidata edits * Updated toast message to show entity name that was edited
1 parent 677f85a commit 4815e93

21 files changed

+276
-38
lines changed

app/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ android {
130130
productFlavors {
131131
prod {
132132
buildConfigField "String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.org/w/api.php\""
133+
buildConfigField "String", "WIKIDATA_API_HOST", "\"https://www.wikidata.org/w/api.php\""
133134
buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\""
134135
buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.wikimedia.org/wikipedia/commons\""
135136
buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.org/wiki/\""
@@ -146,6 +147,7 @@ android {
146147
beta {
147148
// What values do we need to hit the BETA versions of the site / api ?
148149
buildConfigField "String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.beta.wmflabs.org/w/api.php\""
150+
buildConfigField "String", "WIKIDATA_API_HOST", "\"https://www.wikidata.org/w/api.php\""
149151
buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\""
150152
buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.beta.wmflabs.org/wikipedia/commons\""
151153
buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.beta.wmflabs.org/wiki/\""

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/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: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import fr.free.nrw.commons.mwapi.MediaWikiApi;
2525
import fr.free.nrw.commons.nearby.NearbyPlaces;
2626
import fr.free.nrw.commons.upload.UploadController;
27+
import fr.free.nrw.commons.wikidata.WikidataEditListener;
28+
import fr.free.nrw.commons.wikidata.WikidataEditListenerImpl;
2729

2830
import static android.content.Context.MODE_PRIVATE;
2931
import static fr.free.nrw.commons.contributions.ContributionsContentProvider.CONTRIBUTION_AUTHORITY;
@@ -123,7 +125,7 @@ public MediaWikiApi provideMediaWikiApi(Context context,
123125
@Named("default_preferences") SharedPreferences defaultPreferences,
124126
@Named("category_prefs") SharedPreferences categoryPrefs,
125127
Gson gson) {
126-
return new ApacheHttpClientMediaWikiApi(context, BuildConfig.WIKIMEDIA_API_HOST, defaultPreferences, categoryPrefs, gson);
128+
return new ApacheHttpClientMediaWikiApi(context, BuildConfig.WIKIMEDIA_API_HOST, BuildConfig.WIKIDATA_API_HOST, defaultPreferences, categoryPrefs, gson);
127129
}
128130

129131
@Provides
@@ -165,4 +167,10 @@ public NearbyPlaces provideNearbyPlaces() {
165167
public LruCache<String, String> provideLruCache() {
166168
return new LruCache<>(1024);
167169
}
170+
171+
@Provides
172+
@Singleton
173+
public WikidataEditListener provideWikidataEditListener() {
174+
return new WikidataEditListenerImpl();
175+
}
168176
}

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/mwapi/ApacheHttpClientMediaWikiApi.java

Lines changed: 74 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,65 @@ 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 true if the claim is successfully created
398+
* @throws IOException
399+
*/
400+
@Nullable
401+
@Override
402+
public boolean wikidatCreateClaim(String entityId, String property, String snaktype, String value) throws IOException {
403+
ApiResult result = wikidataApi.action("wbcreateclaim")
404+
.param("entity", entityId)
405+
.param("centralauthtoken", getCentralAuthToken())
406+
.param("token", getWikidataCsrfToken())
407+
.param("snaktype", snaktype)
408+
.param("property", property)
409+
.param("value", value)
410+
.post();
411+
412+
if (result == null || result.getNode("api") == null) {
413+
return false;
414+
}
415+
416+
Node node = result.getNode("api").getDocument();
417+
Element element = (Element) node;
418+
419+
if (element != null && element.getAttribute("success").equals("1")) {
420+
return true;
421+
} else {
422+
Timber.e(result.getString("api/error/@code") + " " + result.getString("api/error/@info"));
423+
}
424+
return false;
425+
}
426+
354427
@Override
355428
@NonNull
356429
public Observable<String> searchTitles(String title, int searchCatsLimit) {
@@ -586,6 +659,7 @@ public UploadResult uploadFile(String filename,
586659
String resultStatus = result.getString("/api/upload/@result");
587660
if (!resultStatus.equals("Success")) {
588661
String errorCode = result.getString("/api/error/@code");
662+
Timber.e(errorCode);
589663
return new UploadResult(resultStatus, errorCode);
590664
} else {
591665
Date dateUploaded = parseMWDate(result.getString("/api/upload/imageinfo/@timestamp"));

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

Lines changed: 7 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,9 @@ public interface MediaWikiApi {
4953
@Nullable
5054
String appendEdit(String editToken, String processedPageContent, String filename, String summary) throws IOException;
5155

56+
@Nullable
57+
boolean wikidatCreateClaim(String entityId, String property, String snaktype, String value) throws IOException;
58+
5259
@NonNull
5360
MediaResult fetchMediaByFilename(String filename) throws IOException;
5461

0 commit comments

Comments
 (0)