User:Nikki/ItemUsage.js
Jump to navigation
Jump to search
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
/* This script runs on the delete page and on the page information page.
It checks whether an item is in use in a variety of places
to help you avoid deleting items which are actually being used somewhere.
Note: This script makes requests to overpass-api.de to look for usage in OSM.
To use it, add the following to your common.js:
mw.loader.load("//www.wikidata.org/w/index.php?title=User:Nikki/ItemUsage.js&action=raw&ctype=text/javascript");
Known issues:
* Doesn't work properly for Structured Data on Commons - often finds false
positives, probably fails sometimes
* Can't detect usage in lemma/form language codes on lexemes
* Colours should probably be configurable
* So many messages... it would be possible to simplify it a bit
*/
(function (mw, wb, $) {
var messages = (function () {
var translations = {
en: {
"heading-usage-check": "Usage check",
"checking-sitelinks": "Checking sitelinks...",
"checking-items": "Checking items...",
"checking-properties": "Checking properties...",
"checking-lexemes": "Checking lexemes...",
"checking-sdoc": "Checking structured data on Commons...",
"checking-wikidata-other": "Checking other Wikidata pages...",
"checking-wikimedia-other": "Checking other Wikimedia projects...",
"checking-notability-exemptions": "Checking for notability policy exemptions...",
"checking-osm": "Checking OSM...",
"checking-usage": "Checking usage:",
"check-usage": "check usage",
"item-sitelinks": "Item has sitelinks",
"item-no-sitelinks": "Item has no sitelinks",
"item-wikidata": "Item is used by Wikidata pages",
"item-no-wikidata": "Item is not used by any other Wikidata pages",
"item-wikimedia-other": "Item is used by other Wikimedia projects",
"item-no-wikimedia-other": "Item is not used by any other Wikimedia projects",
"item-osm": "Item is linked from objects in OSM",
"item-no-osm": "Item is not used by OSM",
"item-items": "Item is used by {{PLURAL:$1|an item|$1 items}}",
"item-items-more": "Item is used by $1+ items",
"item-no-items": "Item is not used by any items",
"item-properties": "Item is used by {{PLURAL:$1|a property|$1 properties}}",
"item-properties-more": "Item is used by $1+ properties",
"item-no-properties": "Item is not used by any properties",
"item-lexemes": "Item is used by {{PLURAL:$1|a lexeme|$1 lexemes}}",
"item-lexemes-more": "Item is used by $1+ lexemes",
"item-no-lexemes": "Item is not used by any lexemes",
"item-sdoc": "Item is used in structured data by {{PLURAL:$1|a file|$1 files}} on Commons",
"item-no-sdoc": "Item is not used in structured data on Commons",
"item-notability-exemptions": "Item is a notability policy exemption",
"item-no-notability-exemptions": "Item is not a notability policy exemption",
"what-links-here": "check what links here",
"osm-view-results": "view query results",
"not-actually-used": " - not actually used (see T206857)",
"more": "and more..."
},
de: {
"heading-usage-check": "Überprüfung der Objektverwendung",
"checking-sitelinks": "Nach Interwikilinks suchen ...",
"checking-items": "Nach Links von anderen Datenobjekten suchen ...",
"checking-properties": "Nach Links von Eigenschaften suchen ...",
"checking-lexemes": "Nach Links von Lexemen suchen ...",
"checking-wikidata-other": "Nach Benutzung auf anderen Wikidata-Seiten suchen ...",
"checking-wikimedia-other": "Nach Benutzung durch andere Wikimedia-Projekte suchen ...",
"checking-notability-exemptions": "Nach Ausnahmen der Relevanzkriterien suchen ...",
"checking-osm": "Nach Links von OSM suchen ...",
"checking-usage": "Überprüfung der Objektverwendung:",
"check-usage": "Objektverwendung ansehen",
"item-sitelinks": "Datenobjekt hat Interwikilinks",
"item-no-sitelinks": "Datenobjekt hat keine Interwikilinks",
"item-wikidata": "Datenobjekt wird von anderen Wikidata-Seiten verwendet",
"item-no-wikidata": "Datenobjekt wird nicht von anderen Wikidata-Seiten verwendet",
"item-wikimedia-other": "Datenobjekt wird durch andere Wikimedia-Projekte verwendet",
"item-no-wikimedia-other": "Datenobjekt wird nicht durch andere Wikimedia-Projekte verwendet",
"item-osm": "Datenobjekt wird von Objekten in OSM verlinkt",
"item-no-osm": "Datenobjekt wird nicht von Objekten in OSM verlinkt",
"item-items": "Datenobjekt wird von {{PLURAL:$1|einem anderen Datenobjekt|$1 anderen Datenobjekten}} verlinkt",
"item-items-more": "Datenobjekt wird von mindestens $1 anderen Datenobjekten verlinkt",
"item-no-items": "Datenobjekt wird nicht von anderen Datenobjekten verlinkt",
"item-properties": "Datenobjekt wird von {{PLURAL:$1|einer Eigenschaft|$1 Eigenschaften}} verlinkt",
"item-properties-more": "Datenobjekt wird von mindestens $1 Eigenschaften verlinkt",
"item-no-properties": "Datenobjekt wird nicht von Eigenschaften verlinkt",
"item-lexemes": "Datenobjekt wird von {{PLURAL:$1|einem Lexem|$1 Lexemen}} verlinkt",
"item-lexemes-more": "Datenobjekt wird von mindestens $1 Lexemen verlinkt",
"item-no-lexemes": "Datenobjekt wird nicht von Lexemen verlinkt",
"item-notability-exemptions": "Datenobjekt ist eine Ausnahme der Relevanzkriterien",
"item-no-notability-exemptions": "Datenobjekt ist keine Ausnahme der Relevanzkriterien",
"what-links-here": "Links auf diese Seite ansehen",
"osm-view-results": "Suchergebnisse ansehen",
"not-actually-used": " - wird eigentlich nicht verwendet (siehe T206857)",
"more": "und noch mehr ..."
}
},
chain = mw.language.getFallbackLanguageChain(),
len = chain.length,
ret = {},
i = len - 1;
while (i >= 0) {
if (translations.hasOwnProperty(chain[i])) {
$.extend(ret, translations[chain[i]]);
}
i = i - 1;
}
return ret;
}());
mw.messages.set(messages);
var text_colour_good = "green";
var text_colour_bad = "#c00";
var icon_good = "//upload.wikimedia.org/wikipedia/commons/thumb/4/41/Symbol_confirmed.svg/23px-Symbol_confirmed.svg.png";
var icon_bad = "//upload.wikimedia.org/wikipedia/commons/thumb/8/85/Symbol_unrelated.svg/23px-Symbol_unrelated.svg.png";
var osm_api_url = "https://overpass-api.de/api/interpreter";
var osm_keys = ["wikidata", "operator:wikidata", "brand:wikidata", "architect:wikidata", "artist:wikidata", "subject:wikidata", "name:etymology:wikidata"];
var h2 = "<h2>" + messages["heading-usage-check"] + "</h2>";
var html = "<div style=\"clear:both; padding:5px\" id=\"usage-check\">\
<ul>\
<li id=\"usage-sitelinks\">" + messages["checking-sitelinks"] + "</li>\
<li id=\"usage-items\">" + messages["checking-items"] + "</li>\
<li id=\"usage-properties\">" + messages["checking-properties"] + "</li>\
<li id=\"usage-lexemes\">" + messages["checking-lexemes"] + "</li>\
<li id=\"usage-sdoc\">" + messages["checking-sdoc"] + "</li>\
<li id=\"usage-wikidataother\">" + messages["checking-wikidata-other"] + "</li>\
<li id=\"usage-otherwikimedia\">" + messages["checking-wikimedia-other"] + "</li>\
<li id=\"usage-exception\">" + messages["checking-notability-exemptions"] + "</li>\
<li id=\"usage-osm\">" + messages["checking-osm"] + "</li>\
</ul>\
</div>";
if (document.location.href.match(/\/w\/index.php\?title=Q[0-9]+&action=info/)) {
$(".mw-page-info").last().after(h2 + html);
} else if (document.location.href.match(/\/w\/index.php\?title=Q[0-9]+&action=delete/) && $("#deleteconfirm").length > 0) {
$("#mw-content-text").prepend(html);
$("#usage-check").css("border", "1px solid lightgrey");
$("#usage-check").prepend(messages["checking-usage"]);
$(".mw-warning").css("display", "none");
}
function update_status(id, message, is_good) {
if (is_good) {
image = "<img src=\"" + icon_good + "\" width=\"15\" height=\"15\" />";
text_colour = text_colour_good;
} else {
image = "<img src=\"" + icon_bad + "\" width=\"15\" height=\"15\" />";
text_colour = text_colour_bad;
}
$(id).html(image + " " + message);
$(id).css("color", text_colour);
}
function update_backlink_info (ns) {
$.getJSON("https://www.wikidata.org/w/api.php?format=json&action=query&list=backlinks&bltitle=" + qid + "&bllimit=" + limit + "&blnamespace=" + ns.id + "&blfilterredir=nonredirects").done(function (data) {
if (data.query.backlinks.length > 0) {
var results = data.query.backlinks.length;
var message = (results == limit) ? mw.msg("item-"+ns.key+"-more", results) : mw.msg("item-"+ns.key, results);
update_status("#usage-"+ns.key, message +
"<ul><li><a href=\"/wiki/Special:WhatLinksHere/" + qid + "?namespace=" + ns.id + "\">" + mw.msg("what-links-here") + "</a></li></ul>", false);
} else {
update_status("#usage-"+ns.key, mw.msg("item-no-"+ns.key), true);
}
});
}
function verify_wikimedia_entity_usage (qid, site, api_hostname) {
api_hostname = api_hostname.replace(/(https:\/\/[^\/]+)\/.*/, "$1");
$.getJSON(api_hostname + "/w/api.php?format=json&origin=https://www.wikidata.org&action=query&list=wblistentityusage&wbeuentities=" + qid + "&wbeuprop=url").done(function (data) {
if (!(data.hasOwnProperty("query") && data.query.hasOwnProperty("pages")))
$("#usage-"+site).append(mw.msg("not-actually-used"));
});
}
function verify_wikidata_entity_usage (qid) {
var pages_to_ignore = [
"User:Pasleim/Items for deletion/Page deleted",
"User:Pasleim/notability",
"Wikidata:Database reports",
"Wikidata:Requests for deletions"
];
$.getJSON("https://www.wikidata.org/w/api.php?format=json&action=query&list=wblistentityusage&wbeuentities=" + qid + "&wbeuprop=url").done(function (data) {
var skipped = 0;
if (data.query) {
for (var page_id in data.query.pages) {
for (var page of pages_to_ignore) {
if (data.query.pages[page_id].title.startsWith(page))
skipped = skipped + 1;
}
}
}
if (data.query && Object.keys(data.query.pages).length !== skipped) {
update_status("#usage-wikidataother", messages["item-wikidata"] + "<ul><li><a href=\"/wiki/Special:EntityUsage/" + qid + "\">" + messages["check-usage"] + "</a></li></ul>", false);
} else {
update_status("#usage-wikidataother", messages["item-no-wikidata"], true);
}
});
}
if (document.location.href.match(/\/w\/index.php\?title=Q[0-9]+&action=info/)
|| document.location.href.match(/\/w\/index.php\?title=Q[0-9]+&action=delete/) && $("#deleteconfirm").length > 0) {
var qid = mw.config.get("wgPageName");
if (qid && mw.config.get("wgNamespaceNumber") === 0) {
/* Sitelinks */
$.getJSON("https://www.wikidata.org/wiki/Special:EntityData/" + qid + ".json").done(function (data) {
if (Object.keys(data.entities[qid].sitelinks).length > 0) {
update_status("#usage-sitelinks", messages["item-sitelinks"], false);
} else {
update_status("#usage-sitelinks", messages["item-no-sitelinks"], true);
}
});
/* Structured data on Commons */
$.getJSON("https://commons.wikimedia.org/w/api.php?action=query&list=search&format=json&callback=?&srnamespace=6&srsearch=" + qid).done(function (data) {
if (data.query.searchinfo.totalhits > 0) {
update_status("#usage-sdoc", mw.msg("item-sdoc", data.query.searchinfo.totalhits), false);
} else {
update_status("#usage-sdoc", messages["item-no-sdoc"], true);
}
});
/* Data usage */
$.getJSON("https://www.wikidata.org/w/api.php?format=json&action=query&list=wbsubscribers&wblsentities=" + qid + "&wblslimit=500&wblsprop=url").done(function (data) {
var subscribers = [];
if (data.query.subscribers)
subscribers = data.query.subscribers[qid].subscribers;
var inwikidata = false;
var wikis = $.map(subscribers, function (v) {
if (v.site == "wikidatawiki")
inwikidata = true;
else
return v;
});
if (inwikidata) {
verify_wikidata_entity_usage(qid);
} else {
update_status("#usage-wikidataother", messages["item-no-wikidata"], true);
}
if (wikis.length > 0) {
var count = 0;
update_status("#usage-otherwikimedia", messages["item-wikimedia-other"] + "<ul></ul>", false);
$.each(wikis, function (i, v) {
if (count >= 10)
return;
count = count + 1;
$("#usage-otherwikimedia ul").append("<li id=\"usage-" + v.site + "\"><a href=\"" + v.url + "\">" + v.site + "</a></li>");
verify_wikimedia_entity_usage(qid, v.site, v.url);
});
if (count >= 10 || data.hasOwnProperty("continue"))
$("#usage-otherwikimedia ul").append("<li>" + mw.msg("more") + "</li>");
} else {
update_status("#usage-otherwikimedia", messages["item-no-wikimedia-other"], true);
}
});
/* OSM */
var rows = [];
rows.push("[out:json][timeout:25]; (");
for (var i = 0; i < osm_keys.length; i++) {
rows.push("nwr[\"" + osm_keys[i] + "\"=\"" + qid + "\"]; ");
}
rows.push("); out body; out skel qt;");
var query = rows.join("\n");
$.ajax({
method: "POST",
url: osm_api_url,
data: query
}).done(function (data) {
if (data.elements.length > 0) {
$("#usage-osm").html("<img src=\"" + icon_bad + "\" width=\"15\" height=\"15\" /> " + messages["item-osm"] +
"<ul><li><a href=\"https://overpass-turbo.eu/?R&Q=" + encodeURIComponent(query.replace(/out body;/, "out body; (._;>;);")) + "\">" + messages["osm-view-results"] + "</a></li></ul>");
$("#usage-osm").css("color", "#c00");
} else {
update_status("#usage-osm", messages["item-no-osm"], true);
}
});
/* Backlinks from items, properties and lexemes */
var limit = 50;
var namespaces = [
{ id: 0, key: "items" },
{ id: 120, key: "properties" },
{ id: 146, key: "lexemes" }
];
for (var ns of namespaces) {
update_backlink_info(ns);
}
/* Notability policy exemptions */
$.getJSON("/w/api.php?format=json&action=query&prop=categories&titles=Talk:" + qid + "&clcategories=Category:Notability%20policy%20exemptions").done(function (data) {
$.each(data.query.pages, function (i, v) {
if (v.categories && v.categories.length > 0) {
update_status("#usage-exception", messages["item-notability-exemptions"] + "<ul><li><a href=\"/wiki/Talk:" + qid + "\">Talk:" + qid + "</a>", false);
} else {
update_status("#usage-exception", messages["item-no-notability-exemptions"], true);
}
});
});
}
}
}(mediaWiki, wikibase, jQuery));