WikidataBuilder has uploaded a new change for review. (
https://gerrit.wikimedia.org/r/369007 )
Change subject: New Wikidata Build - 2017-08-01T10:00:01+0000
......................................................................
New Wikidata Build - 2017-08-01T10:00:01+0000
Change-Id: I84c485d33ae10259ae3c8d5040fba6f914c111c6
---
M composer.lock
M extensions/ArticlePlaceholder/package.json
M extensions/Constraints/extension.json
M extensions/Constraints/i18n/de.json
M extensions/Constraints/i18n/en.json
M extensions/Constraints/i18n/fr.json
M extensions/Constraints/i18n/pl.json
M extensions/Constraints/i18n/pt.json
M extensions/Constraints/i18n/qqq.json
M extensions/Constraints/i18n/sl.json
M extensions/Constraints/includes/ConstraintCheck/Checker/ValueTypeChecker.php
M
extensions/Constraints/includes/ConstraintCheck/DelegatingConstraintChecker.php
A extensions/Constraints/includes/ConstraintCheck/Helper/LoggingHelper.php
M extensions/Constraints/includes/ConstraintReportFactory.php
M extensions/Constraints/modules/ui/ConstraintReportPanel.js
M extensions/Constraints/package.json
M extensions/Constraints/tests/phpunit/Api/CheckConstraintsTest.php
M
extensions/Constraints/tests/phpunit/Checker/TypeChecker/ValueTypeCheckerTest.php
A extensions/Constraints/tests/phpunit/Helper/LoggingHelperTest.php
M extensions/MediaInfo/package.json
M extensions/Wikibase/README.md
M extensions/Wikibase/client/i18n/ha.json
A extensions/Wikibase/client/i18n/kab.json
M extensions/Wikibase/client/i18n/li.json
M extensions/Wikibase/client/i18n/tay.json
M extensions/Wikibase/client/includes/Usage/Sql/EntityUsageTable.php
M
extensions/Wikibase/client/tests/phpunit/includes/Usage/Sql/EntityUsageTableTest.php
A extensions/Wikibase/lib/i18n/cop.json
M extensions/Wikibase/package.json
A extensions/Wikibase/repo/i18n/kab.json
M extensions/Wikibase/repo/i18n/sr-ec.json
M extensions/Wikibase/repo/i18n/sv.json
M extensions/Wikibase/repo/includes/ChangeOp/ChangeOps.php
M extensions/Wikibase/repo/includes/Specials/SpecialModifyTerm.php
M extensions/Wikibase/repo/includes/Store/Sql/TermSqlIndexBuilder.php
M extensions/Wikibase/repo/maintenance/rebuildTermSqlIndex.php
M extensions/Wikibase/repo/tests/phpunit/includes/ChangeOp/ChangeOpsTest.php
M
extensions/Wikibase/repo/tests/phpunit/includes/Specials/SpecialModifyTermTestCase.php
M
extensions/Wikibase/repo/tests/phpunit/includes/Specials/SpecialSetLabelDescriptionAliasesTest.php
M
extensions/Wikibase/repo/tests/phpunit/includes/Store/Sql/TermSqlIndexBuilderTest.php
M extensions/Wikidata.org/package.json
A extensions/WikimediaBadges/i18n/sr-ec.json
M extensions/WikimediaBadges/package.json
M vendor/composer/autoload_classmap.php
M vendor/composer/autoload_static.php
M vendor/composer/installed.json
46 files changed, 651 insertions(+), 100 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikidata
refs/changes/07/369007/1
diff --git a/composer.lock b/composer.lock
index 9bb2720..259e513 100644
--- a/composer.lock
+++ b/composer.lock
@@ -756,12 +756,12 @@
"source": {
"type": "git",
"url":
"https://github.com/wikimedia/mediawiki-extensions-ArticlePlaceholder.git",
- "reference": "38de1ad276d73a0f1ff4e19b19212dd0270a5a2e"
+ "reference": "f1e8a1a35716239f9a78eebca09f1135935c4f17"
},
"dist": {
"type": "zip",
- "url":
"https://api.github.com/repos/wikimedia/mediawiki-extensions-ArticlePlaceholder/zipball/38de1ad276d73a0f1ff4e19b19212dd0270a5a2e",
- "reference": "38de1ad276d73a0f1ff4e19b19212dd0270a5a2e",
+ "url":
"https://api.github.com/repos/wikimedia/mediawiki-extensions-ArticlePlaceholder/zipball/f1e8a1a35716239f9a78eebca09f1135935c4f17",
+ "reference": "f1e8a1a35716239f9a78eebca09f1135935c4f17",
"shasum": ""
},
"require": {
@@ -790,7 +790,7 @@
],
"description": "Provides a special page with Wikibase information
about a certain topic, with invitation to create an article for the topic",
"homepage":
"https://www.mediawiki.org/wiki/Extension:ArticlePlaceholder",
- "time": "2017-07-27 20:23:52"
+ "time": "2017-07-31 10:42:11"
},
{
"name": "propertysuggester/property-suggester",
@@ -913,7 +913,7 @@
"source": {
"type": "git",
"url":
"https://gerrit.wikimedia.org/r/mediawiki/extensions/Wikidata.org",
- "reference": "7bf342b2689f281c02a420216036f0f16f78af02"
+ "reference": "a1572228a8ed86de29e5198baa9ff52cd0ab2075"
},
"require": {
"php": ">=5.5.9"
@@ -958,7 +958,7 @@
"support": {
"irc": "irc://irc.freenode.net/wikidata"
},
- "time": "2017-07-25 20:48:54"
+ "time": "2017-07-31 11:44:29"
},
{
"name": "wikibase/constraints",
@@ -966,7 +966,7 @@
"source": {
"type": "git",
"url":
"https://gerrit.wikimedia.org/r/mediawiki/extensions/WikibaseQualityConstraints",
- "reference": "1a936ad2688d6984ac936ea2a46c4a8cc807ff78"
+ "reference": "8614148918fc44218c82182610aff43fdd07f081"
},
"require": {
"php": ">=5.5.9",
@@ -1027,7 +1027,7 @@
"support": {
"issues":
"https://phabricator.wikimedia.org/project/profile/1202/"
},
- "time": "2017-07-29 13:58:43"
+ "time": "2017-07-31 21:06:39"
},
{
"name": "wikibase/data-model",
@@ -1377,7 +1377,7 @@
"source": {
"type": "git",
"url":
"https://gerrit.wikimedia.org/r/mediawiki/extensions/WikibaseMediaInfo",
- "reference": "a841cd855cd01ee9d9bd6f3f7f9f40bfd4d7b0b5"
+ "reference": "7fe01856186fb92b8edcbd810a27603902f29a20"
},
"require": {
"php": ">=5.5.9",
@@ -1424,7 +1424,7 @@
"issues": "https://phabricator.wikimedia.org/",
"irc": "irc://irc.freenode.net/wikidata"
},
- "time": "2017-07-25 20:48:22"
+ "time": "2017-07-31 11:44:06"
},
{
"name": "wikibase/quality",
@@ -1540,12 +1540,12 @@
"source": {
"type": "git",
"url":
"https://github.com/wikimedia/mediawiki-extensions-Wikibase.git",
- "reference": "90bcc0a38f901e0acddb09ebd3b70bbd251fcb0a"
+ "reference": "aa7c10c4531cca80af5f81b817fd5b578e94942e"
},
"dist": {
"type": "zip",
- "url":
"https://api.github.com/repos/wikimedia/mediawiki-extensions-Wikibase/zipball/90bcc0a38f901e0acddb09ebd3b70bbd251fcb0a",
- "reference": "90bcc0a38f901e0acddb09ebd3b70bbd251fcb0a",
+ "url":
"https://api.github.com/repos/wikimedia/mediawiki-extensions-Wikibase/zipball/aa7c10c4531cca80af5f81b817fd5b578e94942e",
+ "reference": "aa7c10c4531cca80af5f81b817fd5b578e94942e",
"shasum": ""
},
"require": {
@@ -1621,7 +1621,7 @@
"wikibaserepo",
"wikidata"
],
- "time": "2017-07-31 09:25:57"
+ "time": "2017-08-01 08:03:31"
},
{
"name": "wikibase/wikimedia-badges",
@@ -1629,7 +1629,7 @@
"source": {
"type": "git",
"url":
"https://gerrit.wikimedia.org/r/mediawiki/extensions/WikimediaBadges",
- "reference": "5b2e9cd6fd4804f0e73cdf8b4e7e181c3ef7ed41"
+ "reference": "368087a658472291f13652580acc30552b816e61"
},
"require": {
"php": ">=5.5.9"
@@ -1674,7 +1674,7 @@
"support": {
"irc": "irc://irc.freenode.net/wikidata"
},
- "time": "2017-07-27 19:54:06"
+ "time": "2017-07-31 21:07:41"
},
{
"name": "wikimedia/assert",
diff --git a/extensions/ArticlePlaceholder/package.json
b/extensions/ArticlePlaceholder/package.json
index d7d1c16..faf5b41 100644
--- a/extensions/ArticlePlaceholder/package.json
+++ b/extensions/ArticlePlaceholder/package.json
@@ -24,6 +24,7 @@
"oojs-ui": "^0.18.1",
"qunitjs": "^2.0.1",
"sinon": "^1.17.6",
+ "stylelint": "7.8.0",
"stylelint-config-wikimedia": "0.4.1"
}
}
diff --git a/extensions/Constraints/extension.json
b/extensions/Constraints/extension.json
index f4ba546..40229ec 100644
--- a/extensions/Constraints/extension.json
+++ b/extensions/Constraints/extension.json
@@ -63,7 +63,8 @@
"wbqc-parameterissues-short",
"wbqc-parameterissues-long",
"wbqc-problems-short",
- "wbqc-problems-long"
+ "wbqc-problems-long",
+ "wbqc-constrainttypehelp-long"
],
"scripts": [
"modules/ui/module.js",
@@ -98,6 +99,16 @@
"description": "The maximum number of entities that are
accessed when checking type or subtype relations.",
"public": true
},
+ "WBQualityConstraintsCheckDurationInfoSeconds": {
+ "value": 1.0,
+ "description": "The maximum time that a constraint
check should usually take, in seconds. Any constraint check that takes longer
than this time is logged at ‘info’ level. Specifying `null` disables this
logging.",
+ "public": true
+ },
+ "WBQualityConstraintsCheckDurationWarningSeconds": {
+ "value": 10.0,
+ "description": "The maximum time that a constraint
check should ever take, in seconds. Any constraint check that takes longer than
this time is logged at ‘warning’ level. Specifying `null` disables this
logging.",
+ "public": true
+ },
"WBQualityConstraintsEnableConstraintsImportFromStatements": {
"value": false,
"description": "Whether to import property constraint
statements into the constraint database or not.",
diff --git a/extensions/Constraints/i18n/de.json
b/extensions/Constraints/i18n/de.json
index aa671ee..ad21137 100644
--- a/extensions/Constraints/i18n/de.json
+++ b/extensions/Constraints/i18n/de.json
@@ -38,6 +38,7 @@
"wbqc-parameterissues-long": "Dies sind Probleme mit der
Beschränkungsdefinition zu der Eigenschaft, nicht mit dieser Aussage.",
"wbqc-problems-short": "Probleme",
"wbqc-problems-long": "Diese Aussage hat einige Probleme.",
+ "wbqc-constrainttypehelp-long": "Hilfeseite für diesen
Beschränkungstyp",
"apihelp-wbcheckconstraints-description": "Führt Beschränkungsprüfungen
zu jedem gewünschten Objekt aus und gibt das Ergebnis zurück.",
"apihelp-wbcheckconstraints-param-id": "Kennung der Objektliste, von
der die Daten abgerufen werden sollen. Mehrere Werte mit „|“ oder Ähnlichem
trennen.",
"apihelp-wbcheckconstraints-param-claimid": "GUID-Liste, die eine
Behauptung erkennt, um einen Beschränkungsbericht zu prüfen. Mehrere Werte mit
„|“ trennen.",
@@ -105,5 +106,6 @@
"wbqc-violation-message-valueType-instance": "Werte der Aussagen $1
sollten Instanzen von {{PLURAL:$3|1=$5|2=$5 oder $6|einer der folgenden
Klassen}} sein (oder von {{PLURAL:$3|1=einer ihrer Unterklasse|2=einer ihrer
Unterklasse|einer ihrer Unterklassen}}), aber $2 hat sie derzeit
{{PLURAL:$3|1=nicht.|2=nicht.|nicht: $4.}}",
"wbqc-violation-message-valueType-subclass": "Werte der Aussagen $1
sollten Unterklassen von {{PLURAL:$3|1=$5|2=$5 oder $6|einer der folgenden
Klassen}} sein (oder von {{PLURAL:$3|1=einer ihrer Unterklassen|2=einer ihrer
Unterklasse|einer ihrer Unterklassen}}), aber $2 hat sie derzeit
{{PLURAL:$3|1=nicht.|2=nicht.|nicht: $4.}}",
"wbqc-violation-message-target-required-claim": "$1 sollte
{{PLURAL:$3|0=eine Aussage $2 haben.|1=eine Aussage $2 $5 haben.|eine Aussage
für $2 mit einem der folgenden Werte haben: $4}}",
- "wbqc-violation-message-unique-value": "Der Wert dieser Eigenschaft
darf nicht in einem anderen Objekt vorhanden sein, er ist aber auch auf
{{PLURAL:$1|1=$3 vorhanden.|2=$3 und $4 vorhanden.|den folgenden Objekten
vorhanden: $2.}}"
+ "wbqc-violation-message-unique-value": "Der Wert dieser Eigenschaft
darf nicht in einem anderen Objekt vorhanden sein, er ist aber auch auf
{{PLURAL:$1|1=$3 vorhanden.|2=$3 und $4 vorhanden.|den folgenden Objekten
vorhanden: $2.}}",
+ "wbqc-exception-message": "Dieses Objekt ist eine bekannte Ausnahme für
diese Beschränkung und wurde als solche markiert."
}
diff --git a/extensions/Constraints/i18n/en.json
b/extensions/Constraints/i18n/en.json
index c7c288e..bce0d22 100644
--- a/extensions/Constraints/i18n/en.json
+++ b/extensions/Constraints/i18n/en.json
@@ -39,6 +39,7 @@
"wbqc-parameterissues-long": "These issues are problems with the
constraint definition on the property, not with this statement.",
"wbqc-problems-short": "Problems",
"wbqc-problems-long": "This statement has some problems.",
+ "wbqc-constrainttypehelp-long": "Help page for this constraint type",
"apihelp-wbcheckconstraints-description": "Performs constraint checks
on any entity you want and returns the result.",
"apihelp-wbcheckconstraints-summary": "Performs constraint checks on
any entity you want and returns the result.",
@@ -119,5 +120,7 @@
"wbqc-violation-message-valueType-instance": "Values of $1 statements
should be instances of {{PLURAL:$3|1=$5|2=$5 or $6|one of the following
classes}} (or of {{PLURAL:$3|1=a subclass of it|2=a subclass of them|one of
their subclasses}}), but $2 currently {{PLURAL:$3|1=isn't.|2=isn't.|isn't:
$4}}",
"wbqc-violation-message-valueType-subclass": "Values of $1 statements
should be subclasses of {{PLURAL:$3|1=$5|2=$5 or $6|one of the following
classes}} (or of {{PLURAL:$3|1=a subclass of it|2=a subclass of them|one of
their subclasses}}), but $2 currently {{PLURAL:$3|1=isn't.|2=isn't.|isn't:
$4}}",
"wbqc-violation-message-target-required-claim": "$1 should have
{{PLURAL:$3|0=a statement $2.|1=a statement $2 $5.|a statement for $2 with one
of the following values:$4}}",
- "wbqc-violation-message-unique-value": "This property's value must not
be present on any other item, but is also present on {{PLURAL:$1|1=$3.|2=$3 and
$4.|the following items: $2}}"
+ "wbqc-violation-message-unique-value": "This property's value must not
be present on any other item, but is also present on {{PLURAL:$1|1=$3.|2=$3 and
$4.|the following items: $2}}",
+
+ "wbqc-exception-message": "This entity is a known exception for this
constraint and has been marked as such."
}
diff --git a/extensions/Constraints/i18n/fr.json
b/extensions/Constraints/i18n/fr.json
index 553ff76..ef5f727 100644
--- a/extensions/Constraints/i18n/fr.json
+++ b/extensions/Constraints/i18n/fr.json
@@ -43,6 +43,7 @@
"wbqc-parameterissues-long": "Ces problèmes sont relatifs à la
définition de la contrainte sur la propriété, et non à cette déclaration.",
"wbqc-problems-short": "Problèmes",
"wbqc-problems-long": "Cette déclaration a quelques problèmes.",
+ "wbqc-constrainttypehelp-long": "Page d'aide pour ce type de
contrainte",
"apihelp-wbcheckconstraints-description": "Réalise les contrôles de
contraintes sur n'importe quelle entité que vous désirez et retourne les
résultats.",
"apihelp-wbcheckconstraints-summary": "Réalise les contrôles de
contraintes sur toute entité que vous désirez et retourne le résultat.",
"apihelp-wbcheckconstraints-param-id": "Liste d'ID des entités pour
lesquelles ont veux les informations. Séparez les valeurs avec '|' ou
similaire.",
@@ -117,5 +118,6 @@
"wbqc-violation-message-valueType-instance": "Les valeurs des
déclarations $1 devraient être des instances de {{PLURAL:$3|1=$5|2=$5 ou $6|une
des classes suivantes}} (ou {{PLURAL:$3|1=d’une de ses sous-classes|2=d’une de
leurs sous-classes|d’une de leurs sous-classes}}), mais $2 {{PLURAL:$3|1=ne
l’est pas actuellement.|2=ne l’est pas actuellement.|ne l’est pas : $4}}",
"wbqc-violation-message-valueType-subclass": "Les valeurs des
déclarations $1 doivent être des sous-classes de {{PLURAL:$3|1=$5|2=$5 ou
$6|une des classes suivantes}} (ou {{PLURAL:$3|1=d’une de ses
sous-classes|2=d’une de leurs sous-classes|d’une de leurs sous-classes}}), mais
$2 {{PLURAL:$3|1=ne l’est pas actuellement.|2=ne l’est pas actuellement.|ne
l’est pas : $4}}",
"wbqc-violation-message-target-required-claim": "$1 doit avoir
{{PLURAL:$3|0=une déclaration $2.|1=une déclaration $2 $5.|une déclaration pour
$2 avec une des valeurs suivantes : $4}}",
- "wbqc-violation-message-unique-value": "Cette valeur de propriété ne
doit être associée à aucun autre élément, et figure également sur
{{PLURAL:$1|1=$3.|2=$3 et $4.|les éléments suivants : $2}}"
+ "wbqc-violation-message-unique-value": "Cette valeur de propriété ne
doit être associée à aucun autre élément, et figure également sur
{{PLURAL:$1|1=$3.|2=$3 et $4.|les éléments suivants : $2}}",
+ "wbqc-exception-message": "Cette entrée est une exception connue pour
cette contrainte et a été marquée comme telle."
}
diff --git a/extensions/Constraints/i18n/pl.json
b/extensions/Constraints/i18n/pl.json
index 1c92765..bcc5abb 100644
--- a/extensions/Constraints/i18n/pl.json
+++ b/extensions/Constraints/i18n/pl.json
@@ -11,8 +11,10 @@
"wbqc-constraintreport-status-exception": "Wyjątek",
"wbqc-constraintreport-status-todo": "Do zrobienia",
"wbqc-constraintreport-status-bad-parameters": "Złe parametry",
+ "wbqc-constraintreport-status-warning": "Ostrzeżenie",
"wbqc-constraintreport-result-table-header-status": "Status",
"wbqc-constraintreport-no-parameter": "brak",
+ "wbqc-badparameters-short": "Złe parametry",
"wbqc-violation-header-parameters": "Parametry:",
"wbqc-violation-message-parameter-regex": "$1 nie jest prawidłowym
wyrażeniem regularnym.",
"wbqc-violation-message-diff-within-range-property-must-exist":
"Właściwość określona w parametrach musi istnieć.",
diff --git a/extensions/Constraints/i18n/pt.json
b/extensions/Constraints/i18n/pt.json
index e2f4d6a..f54986f 100644
--- a/extensions/Constraints/i18n/pt.json
+++ b/extensions/Constraints/i18n/pt.json
@@ -38,6 +38,7 @@
"wbqc-parameterissues-long": "Estes problemas estão relacionados com a
definição da restrição sobre a propriedade, não com esta declaração.",
"wbqc-problems-short": "Problemas",
"wbqc-problems-long": "Esta declaração tem alguns problemas.",
+ "wbqc-constrainttypehelp-long": "Página de ajuda para este tipo de
restrição",
"apihelp-wbcheckconstraints-description": "Realiza a verificação das
restrições de qualquer entidade que queira e devolve o resultado.",
"apihelp-wbcheckconstraints-summary": "Realiza a verificação das
restrições de qualquer entidade que queira e devolve o resultado.",
"apihelp-wbcheckconstraints-param-id": "Lista de identificadores das
entidades de que serão obtidos os dados. Separar os valores com '|' ou
alternativa.",
@@ -112,5 +113,6 @@
"wbqc-violation-message-valueType-instance": "Os valores de declarações
$1 deveriam ser instâncias de {{PLURAL:$3|1=$5|2=$5 ou $6|uma das seguintes
classes}} (ou de {{PLURAL:$3|1=uma subclasse dela|2=uma subclasse delas|uma das
subclasses delas}}), mas neste momento $2 {{PLURAL:$3|1=não é.|2=não é.|não é:
$4}}",
"wbqc-violation-message-valueType-subclass": "Os valores de declarações
$1 deveriam ser subclasses de {{PLURAL:$3|1=$5|2=$5 ou $6|uma das seguintes
classes}} (ou de {{PLURAL:$3|1=uma subclasse dela|2=uma subclasse delas|uma das
subclasses delas}}), mas neste momento $2 {{PLURAL:$3|1=não é.|2=não é.|não é:
$4}}",
"wbqc-violation-message-target-required-claim": "$1 deveria ter
{{PLURAL:$3|0=uma declaração $2.|1=uma declaração $2 $5.|uma declaração para $2
com um dos seguintes valores:$4}}",
- "wbqc-violation-message-unique-value": "O valor da propriedade não pode
estar presente em nenhum outro objeto, mas também está presente
{{PLURAL:$1|1=em $3.|2=em $3 e $4.|nos seguintes objetos: $2}}"
+ "wbqc-violation-message-unique-value": "O valor da propriedade não pode
estar presente em nenhum outro objeto, mas também está presente
{{PLURAL:$1|1=em $3.|2=em $3 e $4.|nos seguintes objetos: $2}}",
+ "wbqc-exception-message": "Esta entidade é uma exceção conhecida para
esta restrição e foi marcada como tal."
}
diff --git a/extensions/Constraints/i18n/qqq.json
b/extensions/Constraints/i18n/qqq.json
index c23f595..06b593b 100644
--- a/extensions/Constraints/i18n/qqq.json
+++ b/extensions/Constraints/i18n/qqq.json
@@ -41,6 +41,7 @@
"wbqc-parameterissues-long": "Longer explanation of the section of the
constraint parameter report popup that contains problems about the constraint
parameters.\n{{Related|wbqc-parameterissues-short}}",
"wbqc-problems-short": "Headline of the constraint report popup section
for violations of mandatory constraints.{{Related|wbqc-potentialissues-short}}",
"wbqc-problems-long": "Title for the icon shown on statements with
mandatory constraint violations, usually displayed by the browser when the user
hovers over the icon with the mouse
cursor.\n{{Related|wbqc-problems-short}}\n{{Related|wbqc-potentialissues-long}}",
+ "wbqc-constrainttypehelp-long": "Title for the help icon shown next to
the constraint type in a constraint violation report. Clicking the icon leads
to a help page on Wikidata about the constraint type.",
"apihelp-wbcheckconstraints-description":
"{{doc-apihelp-description|wbcheckconstraints}}",
"apihelp-wbcheckconstraints-summary":
"{{doc-apihelp-summary|wbcheckconstraints}}",
"apihelp-wbcheckconstraints-param-id":
"{{doc-apihelp-param|wbcheckconstraints|id}}",
@@ -115,5 +116,6 @@
"wbqc-violation-message-valueType-instance": "Message for a violation
of the “Value type” constraint, when the value of a statement should have be an
instance of a certain type but isn't. $1 is the property of the statement, $2
is the value of the statement, $3 is the number of classes, $4 is an HTML list
of all classes, and $5, $6 etc. are the individual
classes.\n{{Related|wbqc-violation-message-valueType-subclass}}",
"wbqc-violation-message-valueType-subclass": "Message for a violation
of the “Value type” constraint, when the value of a statement should have be a
subclass of a certain type but isn't. $1 is the property of the statement, $2
is the value of the statement, $3 is the number of classes, $4 is an HTML list
of all classes, and $5, $6 etc. are the individual
classes.\n{{Related|wbqc-violation-message-valueType-instance}}",
"wbqc-violation-message-target-required-claim": "Message for a
violation of the “Target required claim” constraint, when the target entity of
a statement is missing an expected statement. Parameters:\n* $1 is the subject
entity of the missing statement, i. e. the target entity of the statement that
has the constraint.\n* $2 is the property of the missing statement.\n* $3 is
the number of values permitted for the missing statement (or 0, in which case
the constraint only specifies that there should be a statement but not the
values it should have).\n* $4 is an HTML list of all values permitted for the
missing statement.\n* $5, $6 etc. are the individual values permitted for the
missing statement.\n{{Related|wbqc-violation-message-item}}",
- "wbqc-violation-message-unique-value": "Message for violation of the
Unique Value constraint, when other items are found. Parameters:\n* $1 is the
number of other items with the same value.\n* $2 is an HTML list of all other
items found with the same value.\n* $3, $4 etc. are the individual other items
with the same value."
+ "wbqc-violation-message-unique-value": "Message for violation of the
Unique Value constraint, when other items are found. Parameters:\n* $1 is the
number of other items with the same value.\n* $2 is an HTML list of all other
items found with the same value.\n* $3, $4 etc. are the individual other items
with the same value.",
+ "wbqc-exception-message": "Message for a constraint check result on an
entity that has been marked as an exception to the constraint. This message
only appears on [[Special:ConstraintReport]]; the gadget does not show
exception reports."
}
diff --git a/extensions/Constraints/i18n/sl.json
b/extensions/Constraints/i18n/sl.json
index 948b697..efe4b02 100644
--- a/extensions/Constraints/i18n/sl.json
+++ b/extensions/Constraints/i18n/sl.json
@@ -4,5 +4,6 @@
"HairyFotr"
]
},
- "wbqc-constraintreport-status-warning": "Opozorilo"
+ "wbqc-constraintreport-status-warning": "Opozorilo",
+ "wbqc-violation-message-parameter-regex": "$1 ni veljaven regularni
izraz."
}
diff --git
a/extensions/Constraints/includes/ConstraintCheck/Checker/ValueTypeChecker.php
b/extensions/Constraints/includes/ConstraintCheck/Checker/ValueTypeChecker.php
index 95799f7..cc2ae5d 100644
---
a/extensions/Constraints/includes/ConstraintCheck/Checker/ValueTypeChecker.php
+++
b/extensions/Constraints/includes/ConstraintCheck/Checker/ValueTypeChecker.php
@@ -16,6 +16,8 @@
use WikibaseQuality\ConstraintReport\ConstraintCheck\Result\CheckResult;
use
WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\SparqlHelperException;
use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\TypeCheckerHelper;
+use WikibaseQuality\ConstraintReport\ConstraintParameterRenderer;
+use WikibaseQuality\ConstraintReport\Role;
use Wikibase\DataModel\Statement\Statement;
/**
@@ -29,6 +31,11 @@
* @var ConstraintParameterParser
*/
private $constraintParameterParser;
+
+ /**
+ * @var ConstraintParameterRenderer
+ */
+ private $constraintParameterRenderer;
/**
* @var EntityLookup
@@ -48,17 +55,20 @@
/**
* @param EntityLookup $lookup
* @param ConstraintParameterParser $constraintParameterParser
+ * @param ConstraintParameterRenderer $constraintParameterRenderer
* @param TypeCheckerHelper $typeCheckerHelper
* @param Config $config
*/
public function __construct(
EntityLookup $lookup,
ConstraintParameterParser $constraintParameterParser,
+ ConstraintParameterRenderer $constraintParameterRenderer,
TypeCheckerHelper $typeCheckerHelper,
Config $config
) {
$this->entityLookup = $lookup;
$this->constraintParameterParser = $constraintParameterParser;
+ $this->constraintParameterRenderer =
$constraintParameterRenderer;
$this->typeCheckerHelper = $typeCheckerHelper;
$this->config = $config;
}
@@ -105,7 +115,9 @@
* $mainSnak must be PropertyValueSnak, neither
PropertySomeValueSnak nor PropertyNoValueSnak is allowed
*/
if ( !$mainSnak instanceof PropertyValueSnak ) {
- $message = wfMessage(
"wbqc-violation-message-value-needed" )->params(
$constraint->getConstraintTypeItemId() )->escaped();
+ $message = wfMessage(
"wbqc-violation-message-value-needed" )
+ ->rawParams(
$this->constraintParameterRenderer->formatItemId(
$constraint->getConstraintTypeItemId(), Role::CONSTRAINT_TYPE_ITEM ) )
+ ->escaped();
return new CheckResult( $entity->getId(), $statement,
$constraint, $parameters, CheckResult::STATUS_VIOLATION, $message );
}
@@ -116,7 +128,12 @@
* type of $dataValue for properties with 'Value type'
constraint has to be 'wikibase-entityid'
*/
if ( $dataValue->getType() !== 'wikibase-entityid' ) {
- $message = wfMessage(
"wbqc-violation-message-value-needed-of-type" )->params(
$constraint->getConstraintTypeItemId(), 'wikibase-entityid' )->escaped();
+ $message = wfMessage(
"wbqc-violation-message-value-needed-of-type" )
+ ->rawParams(
+
$this->constraintParameterRenderer->formatItemId(
$constraint->getConstraintTypeItemId(), Role::CONSTRAINT_TYPE_ITEM ),
+ 'wikibase-entityid' // TODO is there a
message for this type so we can localize it?
+ )
+ ->escaped();
return new CheckResult( $entity->getId(), $statement,
$constraint, $parameters, CheckResult::STATUS_VIOLATION, $message );
}
/** @var EntityIdValue $dataValue */
diff --git
a/extensions/Constraints/includes/ConstraintCheck/DelegatingConstraintChecker.php
b/extensions/Constraints/includes/ConstraintCheck/DelegatingConstraintChecker.php
index 1870c8f..9a4f7ad 100644
---
a/extensions/Constraints/includes/ConstraintCheck/DelegatingConstraintChecker.php
+++
b/extensions/Constraints/includes/ConstraintCheck/DelegatingConstraintChecker.php
@@ -4,7 +4,6 @@
use InvalidArgumentException;
use LogicException;
-use MediaWiki\MediaWikiServices;
use Wikibase\DataModel\Entity\EntityDocument;
use Wikibase\DataModel\Entity\PropertyId;
use Wikibase\DataModel\Services\Lookup\EntityLookup;
@@ -14,6 +13,7 @@
use Wikibase\DataModel\Statement\StatementListProvider;
use
WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConstraintParameterException;
use
WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConstraintParameterParser;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\LoggingHelper;
use
WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\SparqlHelperException;
use WikibaseQuality\ConstraintReport\ConstraintCheck\Result\CheckResult;
use WikibaseQuality\ConstraintReport\ConstraintLookup;
@@ -59,24 +59,32 @@
private $statementGuidParser;
/**
+ * @var LoggingHelper
+ */
+ private $loggingHelper;
+
+ /**
* @param EntityLookup $lookup
* @param ConstraintChecker[] $checkerMap
* @param ConstraintLookup $constraintRepository
* @param ConstraintParameterParser $constraintParameterParser
* @param StatementGuidParser $statementGuidParser
+ * @param LoggingHelper $loggingHelper
*/
public function __construct(
EntityLookup $lookup,
array $checkerMap,
ConstraintLookup $constraintRepository,
ConstraintParameterParser $constraintParameterParser,
- StatementGuidParser $statementGuidParser
+ StatementGuidParser $statementGuidParser,
+ LoggingHelper $loggingHelper
) {
$this->entityLookup = $lookup;
$this->checkerMap = $checkerMap;
$this->constraintLookup = $constraintRepository;
$this->constraintParameterParser = $constraintParameterParser;
$this->statementGuidParser = $statementGuidParser;
+ $this->loggingHelper = $loggingHelper;
}
/**
@@ -305,6 +313,7 @@
}
if ( in_array( $entityId, $exceptions ) ) {
+ $message = wfMessage( 'wbqc-exception-message'
)->escaped();
$result[] = new CheckResult(
$entityId,
$statement,
@@ -312,7 +321,7 @@
// TODO: Display parameters anyway.
[],
CheckResult::STATUS_EXCEPTION,
- 'This entity is a known exception for
this constraint and has been marked as such.'
+ $message
);
continue;
}
@@ -334,7 +343,6 @@
private function getCheckResultFor( Statement $statement, Constraint
$constraint, EntityDocument $entity ) {
if ( array_key_exists( $constraint->getConstraintTypeItemId(),
$this->checkerMap ) ) {
$checker =
$this->checkerMap[$constraint->getConstraintTypeItemId()];
- $statsd =
MediaWikiServices::getInstance()->getStatsdDataFactory();
$startTime = microtime( true );
try {
@@ -358,10 +366,7 @@
wfMessage(
'wbqc-violation-message-sparql-error' )->escaped()
);
}
- $statsd->timing(
- 'wikibase.quality.constraints.check.timing.' .
$constraint->getConstraintTypeItemId(),
- ( microtime( true ) - $startTime ) * 1000
- );
+ $endTime = microtime( true );
try {
$constraintStatus =
$this->constraintParameterParser
@@ -392,6 +397,16 @@
$result->getParameters['constraint_status'] =
$constraintStatus;
}
+ $this->loggingHelper->logConstraintCheck(
+ $statement,
+ $constraint,
+ $entity,
+ $result,
+ get_class( $checker ),
+ $endTime - $startTime,
+ __METHOD__
+ );
+
return $result;
} else {
return new CheckResult( $entity->getId(), $statement,
$constraint, [], CheckResult::STATUS_TODO, null );
diff --git
a/extensions/Constraints/includes/ConstraintCheck/Helper/LoggingHelper.php
b/extensions/Constraints/includes/ConstraintCheck/Helper/LoggingHelper.php
new file mode 100644
index 0000000..cd48ce0
--- /dev/null
+++ b/extensions/Constraints/includes/ConstraintCheck/Helper/LoggingHelper.php
@@ -0,0 +1,131 @@
+<?php
+
+namespace WikibaseQuality\ConstraintReport\ConstraintCheck\Helper;
+
+use Config;
+use IBufferingStatsdDataFactory;
+use Psr\Log\LoggerInterface;
+use Wikibase\DataModel\Entity\EntityDocument;
+use Wikibase\DataModel\Statement\Statement;
+use WikibaseQuality\ConstraintReport\Constraint;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Result\CheckResult;
+
+/**
+ * Helper class for tracking and logging messages.
+ *
+ * @package WikibaseQuality\ConstraintReport\ConstraintCheck\Helper
+ * @author Lucas Werkmeister
+ * @license GNU GPL v2+
+ */
+class LoggingHelper {
+
+ /**
+ * @var IBufferingStatsdDataFactory
+ */
+ private $dataFactory;
+
+ /**
+ * @type LoggerInterface
+ */
+ private $logger;
+
+ /**
+ * @type float[]
+ */
+ private $constraintCheckDurationLimits;
+
+ /**
+ * @param IBufferingStatsdDataFactory $dataFactory,
+ * @param LoggerInterface $logger
+ * @param Config $config
+ */
+ public function __construct(
+ IBufferingStatsdDataFactory $dataFactory,
+ LoggerInterface $logger,
+ Config $config
+ ) {
+ $this->dataFactory = $dataFactory;
+ $this->logger = $logger;
+ $this->constraintCheckDurationLimits = [
+ 'info' => $config->get(
'WBQualityConstraintsCheckDurationInfoSeconds' ),
+ 'warning' => $config->get(
'WBQualityConstraintsCheckDurationWarningSeconds' ),
+ ];
+ }
+
+ /**
+ * Log a constraint check.
+ * The constraint check is tracked on the statsd data factory,
+ * and also logged with the logger interface if it took longer than a
certain time.
+ * Multiple limits corresponding to different log levels can be
specified in the configuration;
+ * checks that exceed a higher limit are logged at a more severe level.
+ *
+ * @param Statement $statement
+ * @param Constraint $constraint
+ * @param EntityDocument $entity
+ * @param CheckResult $result
+ * @param string $constraintCheckerClass
+ * @param float $durationSeconds
+ * @param string $method Use __METHOD__.
+ */
+ public function logConstraintCheck(
+ Statement $statement,
+ Constraint $constraint,
+ EntityDocument $entity,
+ CheckResult $result,
+ $constraintCheckerClass,
+ $durationSeconds,
+ $method
+ ) {
+ $constraintCheckerClassShortName = substr( strrchr(
$constraintCheckerClass, '\\' ), 1 );
+ $constraintTypeItemId = $constraint->getConstraintTypeItemId();
+
+ $this->dataFactory->timing(
+ 'wikibase.quality.constraints.check.timing.' .
+ $constraintTypeItemId . '-' .
+ $constraintCheckerClassShortName,
+ $durationSeconds * 1000
+ );
+
+ // find the longest limit (and associated log level) that the
duration exceeds
+ foreach ( $this->constraintCheckDurationLimits as $level =>
$limit ) {
+ if (
+ // duration exceeds this limit
+ isset( $limit ) && $durationSeconds > $limit &&
+ // this limit is longer than previous longest
limit
+ ( !isset( $limitSeconds ) || $limit >
$limitSeconds )
+ ) {
+ $limitSeconds = $limit;
+ $logLevel = $level;
+ }
+ }
+
+ if ( !isset( $limitSeconds ) ) {
+ return;
+ }
+
+ $this->logger->log(
+ $logLevel,
+ 'Constraint check with
{constraintCheckerClassShortName} ' .
+ 'took longer than {limitSeconds} second(s) ' .
+ '(duration: {durationSeconds} seconds).',
+ [
+ 'method' => $method,
+ 'loggingMethod' => __METHOD__,
+ 'durationSeconds' => $durationSeconds,
+ 'limitSeconds' => $limitSeconds,
+ 'constraintId' =>
$constraint->getConstraintId(),
+ 'constraintPropertyId' =>
$constraint->getPropertyId()->getSerialization(),
+ 'constraintTypeItemId' => $constraintTypeItemId,
+ 'constraintParameters' =>
$constraint->getConstraintParameters(),
+ 'constraintCheckerClass' =>
$constraintCheckerClass,
+ 'constraintCheckerClassShortName' =>
$constraintCheckerClassShortName,
+ 'entityId' =>
$entity->getId()->getSerialization(),
+ 'statementGuid' => $statement->getGuid(),
+ 'resultStatus' => $result->getStatus(),
+ 'resultParameters' => $result->getParameters(),
+ 'resultMessage' => $result->getMessage(),
+ ]
+ );
+ }
+
+}
diff --git a/extensions/Constraints/includes/ConstraintReportFactory.php
b/extensions/Constraints/includes/ConstraintReportFactory.php
index be61867..63a9b58 100644
--- a/extensions/Constraints/includes/ConstraintReportFactory.php
+++ b/extensions/Constraints/includes/ConstraintReportFactory.php
@@ -3,6 +3,7 @@
namespace WikibaseQuality\ConstraintReport;
use Config;
+use MediaWiki\Logger\LoggerFactory;
use MediaWiki\MediaWikiServices;
use TitleParser;
use ValueFormatters\FormatterOptions;
@@ -34,6 +35,7 @@
use
WikibaseQuality\ConstraintReport\ConstraintCheck\Checker\UniqueValueChecker;
use WikibaseQuality\ConstraintReport\ConstraintCheck\ConstraintChecker;
use
WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConnectionCheckerHelper;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\LoggingHelper;
use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\RangeCheckerHelper;
use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\SparqlHelper;
use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\TypeCheckerHelper;
@@ -183,7 +185,12 @@
$this->getConstraintCheckerMap(),
new CachingConstraintLookup(
$this->getConstraintRepository() ),
$this->constraintParameterParser,
- $this->statementGuidParser
+ $this->statementGuidParser,
+ new LoggingHelper(
+
MediaWikiServices::getInstance()->getStatsdDataFactory(),
+ LoggerFactory::getInstance(
'WikibaseQualityConstraints' ),
+ $this->config
+ )
);
}
@@ -227,7 +234,8 @@
'Range' => new RangeChecker(
$this->propertyDataTypeLookup, $this->constraintParameterParser,
$rangeCheckerHelper, $this->constraintParameterRenderer ),
'Diff within range' => new
DiffWithinRangeChecker( $this->constraintParameterParser, $rangeCheckerHelper,
$this->constraintParameterRenderer ),
'Type' => new TypeChecker( $this->lookup,
$this->constraintParameterParser, $typeCheckerHelper, $this->config ),
- 'Value type' => new ValueTypeChecker(
$this->lookup, $this->constraintParameterParser, $typeCheckerHelper,
$this->config ),
+ 'Value type' => new ValueTypeChecker(
+ $this->lookup,
$this->constraintParameterParser, $this->constraintParameterRenderer,
$typeCheckerHelper, $this->config ),
'Single value' => new SingleValueChecker(),
'Multi value' => new MultiValueChecker(),
'Unique value' => new UniqueValueChecker(
$this->constraintParameterRenderer, $sparqlHelper ),
diff --git a/extensions/Constraints/modules/ui/ConstraintReportPanel.js
b/extensions/Constraints/modules/ui/ConstraintReportPanel.js
index f00ac2d..b5eaaff 100644
--- a/extensions/Constraints/modules/ui/ConstraintReportPanel.js
+++ b/extensions/Constraints/modules/ui/ConstraintReportPanel.js
@@ -1,4 +1,4 @@
-( function( wb ) {
+( function( mw, wb ) {
'use strict';
/**
@@ -54,6 +54,7 @@
);
this.helpButton = config.helpButton || new OO.ui.ButtonWidget( {
icon: 'help',
+ title: mw.message( 'wbqc-constrainttypehelp-long'
).text(),
framed: false,
classes: [ 'wbqc-constraint-type-help' ],
href:
'https://www.wikidata.org/wiki/Help:Property_constraints_portal/' +
this.constraint.type,
@@ -82,4 +83,4 @@
// (none)
-}( wikibase ) );
+}( mediaWiki, wikibase ) );
diff --git a/extensions/Constraints/package.json
b/extensions/Constraints/package.json
index fe2116f..b85a888 100644
--- a/extensions/Constraints/package.json
+++ b/extensions/Constraints/package.json
@@ -14,9 +14,10 @@
"eslint-config-wikimedia": "0.4.0",
"grunt": "1.0.1",
"grunt-banana-checker": "0.3.0",
- "grunt-jsonlint": "1.1.0",
"grunt-eslint": "19.0.0",
+ "grunt-jsonlint": "1.1.0",
"grunt-stylelint": "0.6.0",
+ "stylelint": "7.8.0",
"stylelint-config-wikimedia": "0.4.1"
}
}
diff --git a/extensions/Constraints/tests/phpunit/Api/CheckConstraintsTest.php
b/extensions/Constraints/tests/phpunit/Api/CheckConstraintsTest.php
index 5d1e399..be77be6 100644
--- a/extensions/Constraints/tests/phpunit/Api/CheckConstraintsTest.php
+++ b/extensions/Constraints/tests/phpunit/Api/CheckConstraintsTest.php
@@ -5,6 +5,8 @@
use ApiTestCase;
use DataValues\UnknownValue;
use HashConfig;
+use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\MediaWikiServices;
use RequestContext;
use Wikibase\DataModel\Entity\Item;
use Wikibase\DataModel\Entity\ItemId;
@@ -23,6 +25,7 @@
use WikibaseQuality\ConstraintReport\ConstraintCheck\ConstraintChecker;
use
WikibaseQuality\ConstraintReport\ConstraintCheck\DelegatingConstraintChecker;
use
WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\ConstraintParameterParser;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\LoggingHelper;
use WikibaseQuality\ConstraintReport\ConstraintCheck\Result\CheckResult;
use WikibaseQuality\ConstraintReport\Tests\Fake\FakeChecker;
use WikibaseQuality\ConstraintReport\Tests\Fake\InMemoryConstraintLookup;
@@ -103,6 +106,8 @@
'WBQualityConstraintsPropertyConstraintId' =>
'P1',
'WBQualityConstraintsExceptionToConstraintId'
=> 'P2',
'WBQualityConstraintsConstraintStatusId' =>
'P3',
+ 'WBQualityConstraintsCheckDurationInfoSeconds'
=> 1.0,
+
'WBQualityConstraintsCheckDurationWarningSeconds' => 10.0,
] );
$entityIdParser = new ItemIdParser();
$constraintParameterRenderer = new
ConstraintParameterRenderer( $entityIdFormatter, $valueFormatter );
@@ -116,7 +121,12 @@
self::$checkerMap,
new InMemoryConstraintLookup(
self::$constraintLookupContents ),
$constraintParameterParser,
- $repo->getStatementGuidParser()
+ $repo->getStatementGuidParser(),
+ new LoggingHelper(
+
MediaWikiServices::getInstance()->getStatsdDataFactory(),
+ LoggerFactory::getInstance(
'WikibaseQualityConstraints' ),
+ $config
+ )
);
return new CheckConstraints(
diff --git
a/extensions/Constraints/tests/phpunit/Checker/TypeChecker/ValueTypeCheckerTest.php
b/extensions/Constraints/tests/phpunit/Checker/TypeChecker/ValueTypeCheckerTest.php
index af2b7be..b6ae9e8 100644
---
a/extensions/Constraints/tests/phpunit/Checker/TypeChecker/ValueTypeCheckerTest.php
+++
b/extensions/Constraints/tests/phpunit/Checker/TypeChecker/ValueTypeCheckerTest.php
@@ -58,6 +58,7 @@
$this->checker = new ValueTypeChecker(
$this->lookup,
$this->getConstraintParameterParser(),
+ $this->getConstraintParameterRenderer(),
new TypeCheckerHelper(
$this->lookup,
$this->getDefaultConfig(),
diff --git a/extensions/Constraints/tests/phpunit/Helper/LoggingHelperTest.php
b/extensions/Constraints/tests/phpunit/Helper/LoggingHelperTest.php
new file mode 100644
index 0000000..c0d7b77
--- /dev/null
+++ b/extensions/Constraints/tests/phpunit/Helper/LoggingHelperTest.php
@@ -0,0 +1,138 @@
+<?php
+
+namespace WikibaseQuality\ConstraintReport\Test\ConstraintChecker;
+
+use HashConfig;
+use IBufferingStatsdDataFactory;
+use Psr\Log\LoggerInterface;
+use Wikibase\DataModel\Entity\PropertyId;
+use Wikibase\Repo\Tests\NewItem;
+use Wikibase\Repo\Tests\NewStatement;
+use WikibaseQuality\ConstraintReport\Constraint;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\LoggingHelper;
+use WikibaseQuality\ConstraintReport\ConstraintCheck\Result\CheckResult;
+
+/**
+ * @covers
\WikibaseQuality\ConstraintReport\ConstraintCheck\Helper\LoggingHelper
+ *
+ * @group WikibaseQualityConstraints
+ *
+ * @author Lucas Werkmeister
+ * @license GNU GPL v2+
+ */
+class LoggingHelperTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @dataProvider logLongConstraintProvider
+ */
+ public function testLogConstraintCheck( $durationSeconds,
$expectedLevel, $expectedLimit ) {
+ $statement = NewStatement::noValueFor( 'P1' )->build();
+ $constraint = new Constraint( 'test constraint id', new
PropertyId( 'P1' ), 'Q100', [] );
+ $entity = NewItem::withId( 'Q1' )->build();
+ $checkResult = new CheckResult(
+ $entity->getId(),
+ $statement,
+ $constraint,
+ [ 'test' => 'params' ],
+ CheckResult::STATUS_VIOLATION,
+ 'test message'
+ );
+
+ $dataFactory = $this->getMock(
IBufferingStatsdDataFactory::class );
+ $dataFactory->expects( $this->once() )
+ ->method( 'timing' )
+ ->with(
+ $this->identicalTo(
'wikibase.quality.constraints.check.timing.Q100-TestChecker' ),
+ $this->identicalTo( $durationSeconds * 1000 )
+ );
+
+ $logger = $this->getMock( LoggerInterface::class );
+ $logger->expects( $expectedLevel !== null ? $this->once() :
$this->never() )
+ ->method( 'log' )
+ ->with(
+ $this->identicalTo( $expectedLevel ),
+ $this->identicalTo(
+ 'Constraint check with
{constraintCheckerClassShortName} ' .
+ 'took longer than {limitSeconds}
second(s) ' .
+ '(duration: {durationSeconds} seconds).'
+ ),
+ $this->equalTo(
+ [
+ 'method' => __METHOD__,
+ 'loggingMethod' =>
LoggingHelper::class . '::logConstraintCheck',
+ 'durationSeconds' =>
$durationSeconds,
+ 'limitSeconds' =>
$expectedLimit,
+ 'constraintId' => 'test
constraint id',
+ 'constraintPropertyId' => 'P1',
+ 'constraintTypeItemId' =>
'Q100',
+ 'constraintParameters' => [],
+ 'constraintCheckerClass' =>
'\Test\Namespace\TestChecker',
+
'constraintCheckerClassShortName' => 'TestChecker',
+ 'entityId' => 'Q1',
+ 'statementGuid' =>
$statement->getGuid(),
+ 'resultStatus' =>
CheckResult::STATUS_VIOLATION,
+ 'resultParameters' => [ 'test'
=> 'params' ],
+ 'resultMessage' => 'test
message',
+ ]
+ )
+ );
+
+ $loggingHelper = new LoggingHelper( $dataFactory, $logger, new
HashConfig( [
+ 'WBQualityConstraintsCheckDurationInfoSeconds' => 1.0,
+ 'WBQualityConstraintsCheckDurationWarningSeconds' =>
10.0,
+ ] ) );
+
+ $loggingHelper->logConstraintCheck(
+ $statement, $constraint, $entity,
+ $checkResult,
+ '\Test\Namespace\TestChecker', $durationSeconds,
+ __METHOD__
+ );
+ }
+
+ public function logLongConstraintProvider() {
+ return [
+ 'short constraint check, nothing to log' => [ 0.5,
null, null ],
+ 'long but not extremely long constraint check, log as
info' => [ 5.0, 'info', 1.0 ],
+ 'extremely long constraint check, log as warning' => [
50.0, 'warning', 10.0 ],
+ ];
+ }
+
+ public function testLogConstraintCheckDisabled() {
+ $statement = NewStatement::noValueFor( 'P1' )->build();
+ $constraint = new Constraint( 'test constraint id', new
PropertyId( 'P1' ), 'Q100', [] );
+ $entity = NewItem::withId( 'Q1' )->build();
+ $checkResult = new CheckResult(
+ $entity->getId(),
+ $statement,
+ $constraint,
+ [ 'test' => 'params' ],
+ CheckResult::STATUS_VIOLATION,
+ 'test message'
+ );
+
+ $dataFactory = $this->getMock(
IBufferingStatsdDataFactory::class );
+ $dataFactory->expects( $this->once() )
+ ->method( 'timing' )
+ ->with(
+ $this->identicalTo(
'wikibase.quality.constraints.check.timing.Q100-TestChecker' ),
+ $this->identicalTo( 5000.0 )
+ );
+
+ $logger = $this->getMock( LoggerInterface::class );
+ $logger->expects( $this->never() )->method( 'log' );
+
+ $loggingHelper = new LoggingHelper( $dataFactory, $logger, new
HashConfig( [
+ 'WBQualityConstraintsCheckDurationInfoSeconds' => null,
+ 'WBQualityConstraintsCheckDurationWarningSeconds' =>
null,
+ ] ) );
+
+ $loggingHelper->logConstraintCheck(
+ $statement, $constraint, $entity,
+ $checkResult,
+ '\Test\Namespace\TestChecker', 5.0,
+ __METHOD__
+ );
+ }
+
+}
diff --git a/extensions/MediaInfo/package.json
b/extensions/MediaInfo/package.json
index 02ca4e3..f099762 100644
--- a/extensions/MediaInfo/package.json
+++ b/extensions/MediaInfo/package.json
@@ -10,6 +10,7 @@
"grunt-eslint": "19.0.0",
"grunt-jsonlint": "1.0.7",
"grunt-stylelint": "0.6.0",
+ "stylelint": "7.8.0",
"stylelint-config-wikimedia": "0.4.1"
}
}
diff --git a/extensions/Wikibase/README.md b/extensions/Wikibase/README.md
index d1da9a7..c7077ce 100644
--- a/extensions/Wikibase/README.md
+++ b/extensions/Wikibase/README.md
@@ -2,10 +2,8 @@
Introduction to Wikibase
====================
-[Travis Build
Status](http://travis-ci.org/wikimedia/mediawiki-extensions-Wikibase/):
-
-[Scrutinizer Code
Quality](https://scrutinizer-ci.com/g/wikimedia/mediawiki-extensions-Wikibase/):
-
+[](http://travis-ci.org/wikimedia/mediawiki-extensions-Wikibase/)
+[](https://scrutinizer-ci.com/g/wikimedia/mediawiki-extensions-Wikibase/)
The Wikibase.git package is part of the [Wikibase software](http://wikiba.se/)
and consists of
three interconnected extensions:
diff --git a/extensions/Wikibase/client/i18n/ha.json
b/extensions/Wikibase/client/i18n/ha.json
index 184aa8b..8040ef2 100644
--- a/extensions/Wikibase/client/i18n/ha.json
+++ b/extensions/Wikibase/client/i18n/ha.json
@@ -4,5 +4,7 @@
"DonCamillo"
]
},
+ "wikibase-editlinks": "Gyara mahaɗa",
+ "wikibase-rc-hide-wikidata-hide": "Ɓoye",
"wikibase-rc-hide-wikidata-show": "Nuna"
}
diff --git a/extensions/Wikibase/client/i18n/kab.json
b/extensions/Wikibase/client/i18n/kab.json
new file mode 100644
index 0000000..231f754
--- /dev/null
+++ b/extensions/Wikibase/client/i18n/kab.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Belkacem77"
+ ]
+ },
+ "tooltip-t-wikibase": "Aseɣwen ɣer uferdis n temsisɣelt n isefka
yeqqnen",
+ "wikibase-comment-update": "Aferdis {{WBREPONAME}} ibeddel",
+ "wikibase-dataitem": "Aferdis {{WBREPONAME}}",
+ "wikibase-editlinks": "Ẓreg iseɣwan",
+ "wikibase-editlinkstitle": "Ẓreg iseɣwan n gar tutlayin",
+ "wikibase-rc-hide-wikidata-show": "Sken",
+ "wikibase-rc-wikibase-edit-letter": "D",
+ "wikibase-rc-wikibase-edit-title": "Taẓrigt n {{WBREPONAME}}"
+}
diff --git a/extensions/Wikibase/client/i18n/li.json
b/extensions/Wikibase/client/i18n/li.json
index 11f4ca7..03b1fc4 100644
--- a/extensions/Wikibase/client/i18n/li.json
+++ b/extensions/Wikibase/client/i18n/li.json
@@ -11,7 +11,7 @@
"wikibase-dataitem": "{{WBREPONAME}}-item",
"wikibase-editlinks": "Bewirk links",
"wikibase-editlinkstitle": "Bewirk interwiki's",
- "wikibase-rc-hide-wikidata": "{{WBREPONAME}} $1",
+ "wikibase-rc-hide-wikidata": "$1 {{WBREPONAME}}",
"wikibase-rc-hide-wikidata-hide": "Versjtaek",
"wikibase-rc-hide-wikidata-show": "Toean",
"wikibase-rc-wikibase-edit-letter": "D",
diff --git a/extensions/Wikibase/client/i18n/tay.json
b/extensions/Wikibase/client/i18n/tay.json
index d10355d..93b4511 100644
--- a/extensions/Wikibase/client/i18n/tay.json
+++ b/extensions/Wikibase/client/i18n/tay.json
@@ -6,11 +6,13 @@
]
},
"tooltip-t-wikibase": "P’buzyun squw biru’ na pin’buzyan nquw wal sr’
tun lmlamu’ na blnkgan",
+ "wikibase-comment-update": "binkgan lamu’ na sinbahan {{WBREPONAME}}",
"wikibase-dataitem": "{{WBREPONAME}} binkgan lmlamu’",
"wikibase-editlinks": "Smr’zyut miru’ sa ’ubuy",
"wikibase-editlinkstitle": "’Ubuy sa smr’zyut ini’ ptnaq na kay’",
"wikibase-rc-hide-wikidata": "$1 {{WBREPONAME}}",
"wikibase-rc-hide-wikidata-hide": "smbbaq",
"wikibase-rc-hide-wikidata-show": "Show",
+ "wikibase-rc-wikibase-edit-letter": "b",
"wikibase-rc-wikibase-edit-title": "{{WBREPONAME}} Smr’zyut miru’"
}
diff --git a/extensions/Wikibase/client/includes/Usage/Sql/EntityUsageTable.php
b/extensions/Wikibase/client/includes/Usage/Sql/EntityUsageTable.php
index 913fe21..40d9be4 100644
--- a/extensions/Wikibase/client/includes/Usage/Sql/EntityUsageTable.php
+++ b/extensions/Wikibase/client/includes/Usage/Sql/EntityUsageTable.php
@@ -378,16 +378,10 @@
// Note: We need to use one (sub)query per entity here, per
T116404
$subQueries = $this->getUsedEntityIdStringsQueries( $idStrings
);
- $values = [];
if ( $this->readConnection->getType() === 'mysql' ) {
- // On MySQL we can UNION all queries and run them at
once
- $sql = $this->readConnection->unionQueries(
$subQueries, true );
-
- $res = $this->readConnection->query( $sql, __METHOD__ );
- foreach ( $res as $row ) {
- $values[] = $row->eu_entity_id;
- }
+ return $this->getUsedEntityIdStringsMySql( $subQueries
);
} else {
+ $values = [];
foreach ( $subQueries as $sql ) {
$res = $this->readConnection->query( $sql,
__METHOD__ );
if ( $res->numRows() ) {
@@ -439,4 +433,24 @@
return array_map( 'intval', $rowIds ?: [] );
}
+ /**
+ * @param string[] $subQueries
+ * @return string[]
+ */
+ private function getUsedEntityIdStringsMySql( array $subQueries ) {
+ $values = [];
+
+ // On MySQL we can UNION up queries and run them at once
+ foreach ( array_chunk( $subQueries, $this->batchSize ) as
$queryChunks ) {
+ $sql = $this->readConnection->unionQueries(
$queryChunks, true );
+
+ $res = $this->readConnection->query( $sql, __METHOD__ );
+ foreach ( $res as $row ) {
+ $values[] = $row->eu_entity_id;
+ }
+ }
+
+ return $values;
+ }
+
}
diff --git
a/extensions/Wikibase/client/tests/phpunit/includes/Usage/Sql/EntityUsageTableTest.php
b/extensions/Wikibase/client/tests/phpunit/includes/Usage/Sql/EntityUsageTableTest.php
index ff8d310..7c0402a 100644
---
a/extensions/Wikibase/client/tests/phpunit/includes/Usage/Sql/EntityUsageTableTest.php
+++
b/extensions/Wikibase/client/tests/phpunit/includes/Usage/Sql/EntityUsageTableTest.php
@@ -222,7 +222,7 @@
$u4l = new EntityUsage( $q4, EntityUsage::LABEL_USAGE );
$u4t = new EntityUsage( $q4, EntityUsage::TITLE_USAGE );
- $usageTable = $this->getEntityUsageTable( 3 );
+ $usageTable = $this->getEntityUsageTable( 2 );
$usageTable->addUsages( 23, [ $u3s, $u3l, $u4l ] );
$usageTable->addUsages( 42, [ $u4l, $u4t ] );
@@ -294,6 +294,7 @@
public function testGetUnusedEntities() {
$q3 = new ItemId( 'Q3' );
$q4 = new ItemId( 'Q4' );
+ $q5 = new ItemId( 'Q5' );
$q6 = new ItemId( 'Q6' );
$u3i = new EntityUsage( $q3, EntityUsage::SITELINK_USAGE );
@@ -302,22 +303,23 @@
$usages = [ $u3i, $u3l, $u4l ];
- $usageTable = $this->getEntityUsageTable( 3 );
+ $usageTable = $this->getEntityUsageTable( 2 );
$usageTable->addUsages( 23, $usages );
$this->assertEmpty( $usageTable->getUnusedEntities( [ $q4 ] ),
'Q4 should not be unused' );
- $entityIds = [ $q4, $q6 ];
if ( wfGetDB( DB_REPLICA )->getType() === 'mysql' ) {
// On MySQL we use UNIONs on the table… as the table is
temporary that
// doesn't work in unit tests.
//
https://dev.mysql.com/doc/refman/5.7/en/temporary-table-problems.html
$entityIds = [ $q6 ];
+ $unused = $usageTable->getUnusedEntities( $entityIds );
+ $this->assertEquals( [ $q6 ], array_values( $unused ),
'Q6 should be unused' );
+ } else {
+ $entityIds = [ $q4, $q5, $q6 ];
+ $unused = $usageTable->getUnusedEntities( $entityIds );
+ $this->assertEquals( [ $q5, $q6 ], array_values(
$unused ), 'Q5 and Q6 should be unused' );
}
-
- $unused = $usageTable->getUnusedEntities( $entityIds );
- $this->assertCount( 1, $unused );
- $this->assertEquals( $q6, reset( $unused ), 'Q6 should be
unused' );
}
/**
diff --git a/extensions/Wikibase/lib/i18n/cop.json
b/extensions/Wikibase/lib/i18n/cop.json
new file mode 100644
index 0000000..78447f1
--- /dev/null
+++ b/extensions/Wikibase/lib/i18n/cop.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "ⲁϩⲙⲉⲧ"
+ ]
+ },
+ "wikibase-sitelinks-wikipedia": "ⲃⲓⲕⲓⲡⲁⲓⲇⲉⲓⲁ"
+}
diff --git a/extensions/Wikibase/package.json b/extensions/Wikibase/package.json
index aa0c945..ed151e3 100644
--- a/extensions/Wikibase/package.json
+++ b/extensions/Wikibase/package.json
@@ -17,6 +17,7 @@
"grunt-eslint": "19.0.0",
"grunt-jsonlint": "1.0.7",
"grunt-stylelint": "0.6.0",
+ "stylelint": "7.8.0",
"stylelint-config-wikimedia": "0.4.1"
}
}
diff --git a/extensions/Wikibase/repo/i18n/kab.json
b/extensions/Wikibase/repo/i18n/kab.json
new file mode 100644
index 0000000..52de01b
--- /dev/null
+++ b/extensions/Wikibase/repo/i18n/kab.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Belkacem77"
+ ]
+ },
+ "wikibase-edit": "ẓreg",
+ "wikibase-add": "rnu"
+}
diff --git a/extensions/Wikibase/repo/i18n/sr-ec.json
b/extensions/Wikibase/repo/i18n/sr-ec.json
index 19032eb..a9496c2 100644
--- a/extensions/Wikibase/repo/i18n/sr-ec.json
+++ b/extensions/Wikibase/repo/i18n/sr-ec.json
@@ -78,6 +78,7 @@
"wb-special-newitem-new-item-notification": "Нова ставка $1 је
направљена и преусмерена на ову страницу. Повратак на $2.",
"wikibase-aliases-input-help-message": "Да би олакшали проналажење
ентитета можете унети алтернативне називе.",
"wikibase-propertypage-datatype": "Тип податка",
+ "wikibase-propertypage-bad-datatype": "Непозната врста података: $1",
"wikibase-claimview-snak-new-tooltip": "После навођења својства можете
унети одговарајућу вредност. Ако својство нема одређену вредност или тачна
вредност није позната, уместо навођења прилагођене вредности можете изабрати
алтернативну врсту вредности кликом на икону пре поља за унос вредности.",
"wikibase-statementview-rank-preferred": "Пожељни ранг",
"wikibase-statementview-rank-tooltip-preferred": "Валидна и ажурна
вредност",
@@ -99,12 +100,15 @@
"wikibase-shortcopyrightwarning": "Кликом на „$1“, прихватате
[[$2|услове коришћења]], и неопозиво прихватате да ваше измене буду лиценциране
под $3.",
"wikibase-copyrighttooltip-acknowledge": "Прихватам ове услове за све
моје будуће измене. Не приказуј више ову поруку.",
"wikibase-entityselector-more": "још",
+ "wikibase-entityselector-notfound": "Нема подударања",
"wikibase-anonymouseditwarning": "Напомена: Нисте пријављени.\nВаша ИП
адреса ће бити забележена у историји измена овог ентитета.",
"wikibase-validator-sitelink-conflict": "Веза $1 је већ прикачена за
ставку $2. Можете је уклонити из $2 ако ту не припада или спојити ставке ако су
о баш истој теми.",
"wikibase-validator-label-conflict": "Својство $3 већ има назив „$1“
повезан са језичким кодом $2.",
"wikibase-validator-label-with-description-conflict": "Ставка $3 већ
има назив „$1“ повезан са језичким кодом $2, са истим описом",
"wikibase-validator-illegal-geo-shape-title": "Вредност мора да почиње
са <code>Data:</code> и завршава са <code>.map</code>. Додатно, наслов не треба
да садржи карактере као што је двотачка, тараба или усправна црта.",
"wikibase-validator-illegal-tabular-data-title": "Вредност мора да
почиње са <code>Data:</code> и завршава са <code>.tab</code>. Такође, наслов не
би требало да садржи карактере као што је двотачка, тараба или усправна црта.",
+ "wikibase-validator-page-not-exists": "Страница „$1“ не постоји.",
+ "wikibase-validator-not-a-language": "„$1“ није познат језички код.",
"wikibase-item-reference-edit-placeholder": "Унесите идентификатор
ставке, нпр. Q10",
"wikibase-wikibaserepopage-invalid-langcode": "Језички код „$1“ је
непознат. Молимо користите језичке кодове познате систему, као што је „sr“.",
"wikibase-wikibaserepopage-invalid-id": "ID „$1” је непознат систему.
Користите валидан ID ентитета.",
@@ -117,6 +121,7 @@
"wikibase-itembytitle-lookup-page": "Страна:",
"wikibase-itembytitle-submit": "Претражи",
"wikibase-itembytitle-create": "Можете такође и [$1 направити ставку].",
+ "special-gotolinkedpage": "Иди на повезану страницу",
"wikibase-gotolinkedpage-lookup-site": "Сајт:",
"wikibase-gotolinkedpage-lookup-item": "Ознака ставке:",
"wikibase-gotolinkedpage-submit": "Иди",
@@ -201,6 +206,7 @@
"wikibase-listproperties-datatype": "Врста податка:",
"wikibase-listproperties-all": "Све врсте података",
"wikibase-listproperties-submit": "Пронађи",
+ "special-entitieswithoutdescription": "Ентитети без описа",
"special-entitieswithoutlabel": "Субјекти без назива",
"wikibase-entitieswithoutlabel-legend": "Добави списак субјеката без
назива",
"wikibase-entitieswithoutlabel-label-language": "Код језика:",
@@ -216,7 +222,9 @@
"wikibase-entitydata-unsupported-format": "Формат података $1 не
подржава овај интерфејс.",
"wikibase-entitydata-title": "Подаци за унос",
"wikibase-entitydata-text": "Ова страница садржи интерфејс повезаних
података до вредности ентитета. Молимо да повежете ID ентитета у URL, користећи
синтаксу подстранице.\n* Преговарање око садржаја се примењује на основу
клијентовог заглавља Прихвати. Ово значи да ће подаци за ентитете да буду дати
у формату који је одабрао Ваш клијент. За веб-прегледаче, ово ће да буде HTML,
због чега ће Ваш прегледач да преусмери до обичне странице ентитета.\n* Можете
експлицитно захтевати одређени формат података додавањем припадајуће екстензије
датотеке на ID ентитета: Q23.json ће вратити податке у JSON формату, Q23.ttl ће
вратити RDF/Turtle итд. Подржани формати су: $1.",
+ "wikibase-entitypage-title": "Страница ентитета",
"wikibase-entitypage-bad-id": "Неисправан идентификатор: $1.",
+ "special-redirectentity": "Преусмери ентитет",
"wikibase-redirectentity-success": "$1 је успешно преусмерено на $2.",
"wikibase-redirectentity-submit": "Преусмерење",
"wikibase-mylanguagefallbackchain-converted-item": "$1 - $2, претворено
из $3 - $4",
@@ -251,8 +259,13 @@
"action-item-merge": "спајање ставки",
"action-property-create": "правите својства",
"wikibase-pageinfo-subscription-none": "Нема",
+ "wikibase-search-bad-entity-type": "Погрешна врста ентитета: $1",
"apihelp-wbeditentity-example-12": "Уклања назив",
+ "apihelp-wbgetentities-example-1": "Прикажи ентитете са идентификатором
<samp>Q42</samp> са свим доступним атрибутима на свим доступним језицима",
+ "apihelp-wbgetentities-example-4": "Прикажи ентитете са идентификатором
<samp>Q42</samp> са свим доступним атрибутима на енглеском језику",
"apihelp-wbmergeitems-description": "Спаја више ставки.",
+ "apihelp-wbmergeitems-summary": "Спаја више ставки.",
+ "apihelp-wbmergeitems-param-fromid": "Идентификатор за спајање од",
"apihelp-wbmergeitems-param-toid": "Идентификатор за спајање са",
"apihelp-wbsearchentities-param-search": "Претрага за овај текст.",
"apihelp-wbsearchentities-param-language": "Претрага на овом језику.",
diff --git a/extensions/Wikibase/repo/i18n/sv.json
b/extensions/Wikibase/repo/i18n/sv.json
index e9710ec..3b86a3a 100644
--- a/extensions/Wikibase/repo/i18n/sv.json
+++ b/extensions/Wikibase/repo/i18n/sv.json
@@ -317,6 +317,7 @@
"wikibase-api-unresolved-redirect": "Angiven entitets-ID hänvisar till
en omdirigering, som inte stöds i detta sammanhang.",
"wikibase-api-illegal-entity-remove": "Entiteter med toppnivånyckeln
<var>remove</var> kan inte raderas.",
"wikibase-api-illegal-entity-selector": "Du måste ange antingen en
<var>id</var>-entitet eller en kombination av <var>site</var> och
<var>page</var>, men inte båda.",
+ "wikibase-api-no-such-entity": "Kunde inte hitta en entitet med ID
\"$1\".",
"wikibase-api-no-such-sitelink": "Kunde inte hitta en webbplatslänk
till \"$1\" när du försökte redigera emblem.",
"wikibase-api-not-recognized-datatype": "En datatyp förväntades, men
saknades eller kändes inte igen.",
"wikibase-api-target-not-empty": "Omdirigeringen kan enbart skapas
ovanpå en tom eller raderad entitet.",
diff --git a/extensions/Wikibase/repo/includes/ChangeOp/ChangeOps.php
b/extensions/Wikibase/repo/includes/ChangeOp/ChangeOps.php
index 120d34a..2c4618e 100644
--- a/extensions/Wikibase/repo/includes/ChangeOp/ChangeOps.php
+++ b/extensions/Wikibase/repo/includes/ChangeOp/ChangeOps.php
@@ -71,8 +71,17 @@
* @throws ChangeOpException
*/
public function apply( EntityDocument $entity, Summary $summary = null
) {
- foreach ( $this->changeOps as $changeOp ) {
- $changeOp->apply( $entity, $summary );
+ if ( count( $this->changeOps ) === 1 ) {
+ reset( $this->changeOps )->apply( $entity, $summary );
+ } elseif ( count( $this->changeOps ) === 0 ) {
+ return;
+ } else {
+ foreach ( $this->changeOps as $changeOp ) {
+ $changeOp->apply( $entity, null );
+ }
+ if ( $summary ) {
+ $summary->setAction( 'update' );
+ }
}
}
diff --git a/extensions/Wikibase/repo/includes/Specials/SpecialModifyTerm.php
b/extensions/Wikibase/repo/includes/Specials/SpecialModifyTerm.php
index 3aa5c57..989cd33 100644
--- a/extensions/Wikibase/repo/includes/Specials/SpecialModifyTerm.php
+++ b/extensions/Wikibase/repo/includes/Specials/SpecialModifyTerm.php
@@ -4,9 +4,8 @@
use HTMLForm;
use Html;
-use InvalidArgumentException;
use Language;
-use PermissionsError;
+use Status;
use Wikibase\Repo\ChangeOp\ChangeOpException;
use Wikibase\Repo\ChangeOp\FingerprintChangeOpFactory;
use Wikibase\DataModel\Entity\EntityDocument;
@@ -148,9 +147,8 @@
return false;
}
- try {
- $this->checkTermChangePermissions(
$this->entityRevision->getEntity() );
- } catch ( PermissionsError $e ) {
+ $status = $this->checkTermChangePermissions(
$this->entityRevision->getEntity() );
+ if ( !$status->isOK() ) {
$this->showErrorHTML( $this->msg( 'permissionserrors' )
);
return false;
}
@@ -187,18 +185,14 @@
/**
* @param EntityDocument $entity
*
- * @throws PermissionsError
+ * @return Status
*/
private function checkTermChangePermissions( EntityDocument $entity ) {
- $status =
$this->permissionChecker->getPermissionStatusForEntity(
+ return $this->permissionChecker->getPermissionStatusForEntity(
$this->getUser(),
EntityPermissionChecker::ACTION_EDIT_TERMS,
$entity
);
-
- if ( !$status->isOK() ) {
- throw new PermissionsError( null, $status->getErrors()
);
- }
}
/**
diff --git
a/extensions/Wikibase/repo/includes/Store/Sql/TermSqlIndexBuilder.php
b/extensions/Wikibase/repo/includes/Store/Sql/TermSqlIndexBuilder.php
index 1de3c4a..fcd7fb3 100644
--- a/extensions/Wikibase/repo/includes/Store/Sql/TermSqlIndexBuilder.php
+++ b/extensions/Wikibase/repo/includes/Store/Sql/TermSqlIndexBuilder.php
@@ -130,12 +130,11 @@
$this->batchSize = $size;
}
- public function setReadFullEntityIdColumn() {
- $this->readFullEntityIdColumn = true;
- }
-
- public function setDoNotReadFullEntityIdColumn() {
- $this->readFullEntityIdColumn = false;
+ /**
+ * @param bool $readFullEntityIdColumn
+ */
+ public function setReadFullEntityIdColumn( $readFullEntityIdColumn ) {
+ $this->readFullEntityIdColumn = $readFullEntityIdColumn;
}
public function rebuild() {
diff --git a/extensions/Wikibase/repo/maintenance/rebuildTermSqlIndex.php
b/extensions/Wikibase/repo/maintenance/rebuildTermSqlIndex.php
index 72b7fd0..b99e8de 100644
--- a/extensions/Wikibase/repo/maintenance/rebuildTermSqlIndex.php
+++ b/extensions/Wikibase/repo/maintenance/rebuildTermSqlIndex.php
@@ -93,11 +93,7 @@
$builder->setProgressReporter( $this->getReporter() );
$builder->setErrorReporter( $this->getErrorReporter() );
$builder->setBatchSize( $batchSize );
- if ( $repoSettings->getSetting( 'readFullEntityIdColumn' ) ) {
- $builder->setReadFullEntityIdColumn();
- } else {
- $builder->setDoNotReadFullEntityIdColumn();
- }
+ $builder->setReadFullEntityIdColumn( $repoSettings->getSetting(
'readFullEntityIdColumn' ) );
if ( $fromId !== null ) {
$builder->setFromId( (int)$fromId );
diff --git
a/extensions/Wikibase/repo/tests/phpunit/includes/ChangeOp/ChangeOpsTest.php
b/extensions/Wikibase/repo/tests/phpunit/includes/ChangeOp/ChangeOpsTest.php
index 9996693..ec26946 100644
--- a/extensions/Wikibase/repo/tests/phpunit/includes/ChangeOp/ChangeOpsTest.php
+++ b/extensions/Wikibase/repo/tests/phpunit/includes/ChangeOp/ChangeOpsTest.php
@@ -4,8 +4,10 @@
use DataValues\StringValue;
use InvalidArgumentException;
+use Prophecy\Argument;
use ValueValidators\Error;
use ValueValidators\Result;
+use Wikibase\DataModel\Entity\EntityDocument;
use Wikibase\Repo\ChangeOp\ChangeOp;
use Wikibase\Repo\ChangeOp\ChangeOpDescription;
use Wikibase\Repo\ChangeOp\ChangeOpLabel;
@@ -16,7 +18,9 @@
use Wikibase\DataModel\Services\Statement\GuidGenerator;
use Wikibase\DataModel\Snak\PropertyValueSnak;
use Wikibase\Repo\Store\EntityPermissionChecker;
+use Wikibase\Repo\Tests\NewItem;
use Wikibase\Repo\Validators\SnakValidator;
+use Wikibase\Summary;
/**
* @covers Wikibase\Repo\ChangeOp\ChangeOps
@@ -198,4 +202,58 @@
$this->assertContains( EntityPermissionChecker::ACTION_EDIT,
$actions );
}
+ public function testApply_HasTwoChangeOps_DoesNotPassSummaryObject() {
+ $changeOp1 = $this->prophesize( ChangeOp::class );
+ $changeOp2 = $this->prophesize( ChangeOp::class );
+
+ $changeOps = new ChangeOps( [ $changeOp1->reveal(),
$changeOp2->reveal() ] );
+ $changeOps->apply(
+ $this->prophesize( EntityDocument::class )->reveal(),
+ $this->prophesize( Summary::class )->reveal()
+ );
+
+ $changeOp1->apply( Argument::any(), null
)->shouldHaveBeenCalled();
+ $changeOp2->apply( Argument::any(), null
)->shouldHaveBeenCalled();
+ }
+
+ public function testApply_HasOneChangeOp_PassesSummaryObject() {
+ $changeOp = $this->prophesize( ChangeOp::class );
+
+ $changeOps = new ChangeOps( [ $changeOp->reveal() ] );
+ $changeOps->apply(
+ $this->prophesize( EntityDocument::class )->reveal(),
+ $this->prophesize( Summary::class )->reveal()
+ );
+
+ $changeOp->apply( Argument::any(), Argument::type(
Summary::class ) )
+ ->shouldHaveBeenCalled();
+ }
+
+ public function testApply_HasTwoChangeOps_SetsGenericSummaryMessage() {
+ $changeOps = new ChangeOps( [
+ $this->prophesize( ChangeOp::class )->reveal(),
+ $this->prophesize( ChangeOp::class )->reveal()
+ ] );
+
+ $summary = $this->prophesize( Summary::class );
+ $changeOps->apply(
+ $this->prophesize( EntityDocument::class )->reveal(),
+ $summary->reveal()
+ );
+
+ $summary->setAction( 'update' )->shouldHaveBeenCalled();
+ }
+
+ public function testApply_HasZeroChangeOps_DoesNotUpdateSummaryAction()
{
+ $changeOps = new ChangeOps( [] );
+
+ $summary = $this->prophesize( Summary::class );
+ $changeOps->apply(
+ $this->prophesize( EntityDocument::class )->reveal(),
+ $summary->reveal()
+ );
+
+ $summary->setAction( Argument::any()
)->shouldNotHaveBeenCalled();
+ }
+
}
diff --git
a/extensions/Wikibase/repo/tests/phpunit/includes/Specials/SpecialModifyTermTestCase.php
b/extensions/Wikibase/repo/tests/phpunit/includes/Specials/SpecialModifyTermTestCase.php
index 2967b30..fe2b279 100644
---
a/extensions/Wikibase/repo/tests/phpunit/includes/Specials/SpecialModifyTermTestCase.php
+++
b/extensions/Wikibase/repo/tests/phpunit/includes/Specials/SpecialModifyTermTestCase.php
@@ -3,6 +3,8 @@
namespace Wikibase\Repo\Tests\Specials;
use FauxRequest;
+use Language;
+use Message;
use SpecialPageTestBase;
use Wikibase\DataModel\Entity\Item;
use Wikibase\EntityContent;
@@ -123,4 +125,19 @@
) ) ) );
}
+ public function testGivenUserHasInsufficientPermissions_errorIsShown() {
+ $this->setMwGlobals( 'wgGroupPermissions', [ '*' => [ 'read' =>
true, 'edit' => true, 'item-term' => false ] ] );
+
+ $id = $this->createNewItemWithTerms( $language = 'de',
$termValue = 'foo' );
+
+ $request = new FauxRequest( [ 'id' => $id, 'language' =>
$language, 'value' => '' ], true );
+
+ list( $output, ) = $this->executeSpecialPage( '', $request,
self::USER_LANGUAGE );
+
+ assertThat( $output, is( htmlPiece( havingChild(
+ both( tagMatchingOutline( "<p class='error'/>" ) )
+ ->andAlso( havingTextContents( new Message(
'permissionserrors', [], new Language( self::USER_LANGUAGE ) ) ) )
+ ) ) ) );
+ }
+
}
diff --git
a/extensions/Wikibase/repo/tests/phpunit/includes/Specials/SpecialSetLabelDescriptionAliasesTest.php
b/extensions/Wikibase/repo/tests/phpunit/includes/Specials/SpecialSetLabelDescriptionAliasesTest.php
index c1f5aa8..258a4a6 100644
---
a/extensions/Wikibase/repo/tests/phpunit/includes/Specials/SpecialSetLabelDescriptionAliasesTest.php
+++
b/extensions/Wikibase/repo/tests/phpunit/includes/Specials/SpecialSetLabelDescriptionAliasesTest.php
@@ -4,6 +4,9 @@
use FauxRequest;
use FauxResponse;
+use Language;
+use Message;
+use SpecialPageExecutor;
use Status;
use ValueValidators\Result;
use WebRequest;
@@ -21,6 +24,7 @@
use Wikibase\Repo\Hooks\EditFilterHookRunner;
use Wikibase\Repo\Specials\SpecialPageCopyrightView;
use Wikibase\Repo\Specials\SpecialSetLabelDescriptionAliases;
+use Wikibase\Repo\Store\EntityPermissionChecker;
use Wikibase\Repo\Validators\TermValidatorFactory;
use Wikibase\Repo\Validators\UniquenessViolation;
@@ -356,4 +360,51 @@
$this->assertTrue( $expected->equals( $actual ), 'Fingerprint
mismatches' );
}
+ public function testGivenUserHasInsufficientPermissions_errorIsShown() {
+ $inputEntity = new Item( null, $this->makeFingerprint( [ 'en'
=> 'a label' ] ) );
+
+ $this->mockRepository->putEntity( $inputEntity );
+ $id = $inputEntity->getId();
+
+ $specialPage =
$this->newSpecialPageWithForbiddingPermissionChecker();
+
+ $request = new FauxRequest( [ 'language' => 'en', 'label' =>
'new label' ], true );
+
+ list( $output, ) = ( new SpecialPageExecutor()
)->executeSpecialPage( $specialPage, $id->getSerialization(), $request );
+
+ assertThat( $output, is( htmlPiece( havingChild(
+ both( tagMatchingOutline( "<p class='error'/>" ) )
+ ->andAlso( havingTextContents( new Message(
'permissionserrors', [], new Language( self::USER_LANGUAGE ) ) ) )
+ ) ) ) );
+ }
+
+ private function newSpecialPageWithForbiddingPermissionChecker() {
+ $copyrightView = new SpecialPageCopyrightView( new
CopyrightMessageBuilder(), '', '' );
+
+ $error = Status::newFatal( 'permission error' );
+
+ $permissionChecker = $this->getMock(
EntityPermissionChecker::class );
+ $permissionChecker->method( $this->anything() )
+ ->willReturn( $error );
+
+ return new SpecialSetLabelDescriptionAliases(
+ $copyrightView,
+ $this->getSummaryFormatter(),
+ $this->getEntityRevisionLookup(),
+ $this->getEntityTitleLookup(),
+ new EditEntityFactory(
+ $this->getEntityTitleLookup(),
+ $this->getEntityRevisionLookup(),
+ $this->getEntityStore(),
+ $this->getEntityPermissionChecker(),
+ new EntityDiffer(),
+ new EntityPatcher(),
+ $this->getMockEditFitlerHookRunner()
+ ),
+ $this->getFingerprintChangeOpsFactory(),
+ new StaticContentLanguages( self::$languageCodes ),
+ $permissionChecker
+ );
+ }
+
}
diff --git
a/extensions/Wikibase/repo/tests/phpunit/includes/Store/Sql/TermSqlIndexBuilderTest.php
b/extensions/Wikibase/repo/tests/phpunit/includes/Store/Sql/TermSqlIndexBuilderTest.php
index c56ca37..0d2ca11 100644
---
a/extensions/Wikibase/repo/tests/phpunit/includes/Store/Sql/TermSqlIndexBuilderTest.php
+++
b/extensions/Wikibase/repo/tests/phpunit/includes/Store/Sql/TermSqlIndexBuilderTest.php
@@ -194,7 +194,7 @@
);
$builder->setBatchSize( 2 );
- $builder->setDoNotReadFullEntityIdColumn();
+ $builder->setReadFullEntityIdColumn( false );
return $builder;
}
diff --git a/extensions/Wikidata.org/package.json
b/extensions/Wikidata.org/package.json
index 02ca4e3..f099762 100644
--- a/extensions/Wikidata.org/package.json
+++ b/extensions/Wikidata.org/package.json
@@ -10,6 +10,7 @@
"grunt-eslint": "19.0.0",
"grunt-jsonlint": "1.0.7",
"grunt-stylelint": "0.6.0",
+ "stylelint": "7.8.0",
"stylelint-config-wikimedia": "0.4.1"
}
}
diff --git a/extensions/WikimediaBadges/i18n/sr-ec.json
b/extensions/WikimediaBadges/i18n/sr-ec.json
new file mode 100644
index 0000000..ffdf7b9
--- /dev/null
+++ b/extensions/WikimediaBadges/i18n/sr-ec.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Милан Јелисавчић"
+ ]
+ },
+ "wikimediabadges-desc": "Подразумеване теме за приказивање значки на
Викимедијним пројектима"
+}
diff --git a/extensions/WikimediaBadges/package.json
b/extensions/WikimediaBadges/package.json
index 8feb7c8..ea043bd 100644
--- a/extensions/WikimediaBadges/package.json
+++ b/extensions/WikimediaBadges/package.json
@@ -1,4 +1,5 @@
{
+ "private": true,
"devDependencies": {
"eslint-config-wikimedia": "0.4.0",
"grunt": "1.0.1",
@@ -6,6 +7,7 @@
"grunt-eslint": "19.0.0",
"grunt-jsonlint": "1.1.0",
"grunt-stylelint": "0.6.0",
+ "stylelint": "7.8.0",
"stylelint-config-wikimedia": "0.4.1"
},
"scripts": {
diff --git a/vendor/composer/autoload_classmap.php
b/vendor/composer/autoload_classmap.php
index 74274aa..3874a7d 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -272,6 +272,7 @@
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Helper\\ConnectionCheckerHelper'
=> $baseDir .
'/extensions/Constraints/includes/ConstraintCheck/Helper/ConnectionCheckerHelper.php',
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Helper\\ConstraintParameterException'
=> $baseDir .
'/extensions/Constraints/includes/ConstraintCheck/Helper/ConstraintParameterException.php',
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Helper\\ConstraintParameterParser'
=> $baseDir .
'/extensions/Constraints/includes/ConstraintCheck/Helper/ConstraintParameterParser.php',
+
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Helper\\LoggingHelper' =>
$baseDir .
'/extensions/Constraints/includes/ConstraintCheck/Helper/LoggingHelper.php',
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Helper\\RangeCheckerHelper'
=> $baseDir .
'/extensions/Constraints/includes/ConstraintCheck/Helper/RangeCheckerHelper.php',
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Helper\\SparqlHelper'
=> $baseDir .
'/extensions/Constraints/includes/ConstraintCheck/Helper/SparqlHelper.php',
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Helper\\SparqlHelperException'
=> $baseDir .
'/extensions/Constraints/includes/ConstraintCheck/Helper/SparqlHelperException.php',
diff --git a/vendor/composer/autoload_static.php
b/vendor/composer/autoload_static.php
index d4f9d38..c4bde36 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -578,6 +578,7 @@
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Helper\\ConnectionCheckerHelper'
=> __DIR__ . '/../..' .
'/extensions/Constraints/includes/ConstraintCheck/Helper/ConnectionCheckerHelper.php',
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Helper\\ConstraintParameterException'
=> __DIR__ . '/../..' .
'/extensions/Constraints/includes/ConstraintCheck/Helper/ConstraintParameterException.php',
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Helper\\ConstraintParameterParser'
=> __DIR__ . '/../..' .
'/extensions/Constraints/includes/ConstraintCheck/Helper/ConstraintParameterParser.php',
+
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Helper\\LoggingHelper' =>
__DIR__ . '/../..' .
'/extensions/Constraints/includes/ConstraintCheck/Helper/LoggingHelper.php',
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Helper\\RangeCheckerHelper'
=> __DIR__ . '/../..' .
'/extensions/Constraints/includes/ConstraintCheck/Helper/RangeCheckerHelper.php',
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Helper\\SparqlHelper' =>
__DIR__ . '/../..' .
'/extensions/Constraints/includes/ConstraintCheck/Helper/SparqlHelper.php',
'WikibaseQuality\\ConstraintReport\\ConstraintCheck\\Helper\\SparqlHelperException'
=> __DIR__ . '/../..' .
'/extensions/Constraints/includes/ConstraintCheck/Helper/SparqlHelperException.php',
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index e140f6d..8dbd8a9 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -122,12 +122,12 @@
"source": {
"type": "git",
"url":
"https://github.com/wikimedia/mediawiki-extensions-ArticlePlaceholder.git",
- "reference": "38de1ad276d73a0f1ff4e19b19212dd0270a5a2e"
+ "reference": "f1e8a1a35716239f9a78eebca09f1135935c4f17"
},
"dist": {
"type": "zip",
- "url":
"https://api.github.com/repos/wikimedia/mediawiki-extensions-ArticlePlaceholder/zipball/38de1ad276d73a0f1ff4e19b19212dd0270a5a2e",
- "reference": "38de1ad276d73a0f1ff4e19b19212dd0270a5a2e",
+ "url":
"https://api.github.com/repos/wikimedia/mediawiki-extensions-ArticlePlaceholder/zipball/f1e8a1a35716239f9a78eebca09f1135935c4f17",
+ "reference": "f1e8a1a35716239f9a78eebca09f1135935c4f17",
"shasum": ""
},
"require": {
@@ -138,7 +138,7 @@
"jakub-onderka/php-parallel-lint": "0.9.2",
"wikibase/wikibase-codesniffer": "^0.1.0"
},
- "time": "2017-07-27 20:23:52",
+ "time": "2017-07-31 10:42:11",
"type": "mediawiki-extension",
"installation-source": "dist",
"autoload": {
@@ -1380,12 +1380,12 @@
"source": {
"type": "git",
"url":
"https://github.com/wikimedia/mediawiki-extensions-Wikibase.git",
- "reference": "90bcc0a38f901e0acddb09ebd3b70bbd251fcb0a"
+ "reference": "aa7c10c4531cca80af5f81b817fd5b578e94942e"
},
"dist": {
"type": "zip",
- "url":
"https://api.github.com/repos/wikimedia/mediawiki-extensions-Wikibase/zipball/90bcc0a38f901e0acddb09ebd3b70bbd251fcb0a",
- "reference": "90bcc0a38f901e0acddb09ebd3b70bbd251fcb0a",
+ "url":
"https://api.github.com/repos/wikimedia/mediawiki-extensions-Wikibase/zipball/aa7c10c4531cca80af5f81b817fd5b578e94942e",
+ "reference": "aa7c10c4531cca80af5f81b817fd5b578e94942e",
"shasum": ""
},
"require": {
@@ -1418,7 +1418,7 @@
"jakub-onderka/php-parallel-lint": ">=0.3 <0.10",
"wikibase/wikibase-codesniffer": "^0.1.0"
},
- "time": "2017-07-31 09:25:57",
+ "time": "2017-08-01 08:03:31",
"type": "mediawiki-extension",
"installation-source": "dist",
"autoload": {
@@ -1471,7 +1471,7 @@
"source": {
"type": "git",
"url":
"https://gerrit.wikimedia.org/r/mediawiki/extensions/WikimediaBadges",
- "reference": "5b2e9cd6fd4804f0e73cdf8b4e7e181c3ef7ed41"
+ "reference": "368087a658472291f13652580acc30552b816e61"
},
"require": {
"php": ">=5.5.9"
@@ -1481,7 +1481,7 @@
"jakub-onderka/php-parallel-lint": "0.9.2",
"wikibase/wikibase-codesniffer": "^0.1.0"
},
- "time": "2017-07-27 19:54:06",
+ "time": "2017-07-31 21:07:41",
"type": "mediawiki-extension",
"installation-source": "source",
"autoload": {
@@ -1526,7 +1526,7 @@
"source": {
"type": "git",
"url":
"https://gerrit.wikimedia.org/r/mediawiki/extensions/Wikidata.org",
- "reference": "7bf342b2689f281c02a420216036f0f16f78af02"
+ "reference": "a1572228a8ed86de29e5198baa9ff52cd0ab2075"
},
"require": {
"php": ">=5.5.9"
@@ -1536,7 +1536,7 @@
"jakub-onderka/php-parallel-lint": "0.9.2",
"wikibase/wikibase-codesniffer": "^0.1.0"
},
- "time": "2017-07-25 20:48:54",
+ "time": "2017-07-31 11:44:29",
"type": "mediawiki-extension",
"installation-source": "source",
"autoload": {
@@ -1581,7 +1581,7 @@
"source": {
"type": "git",
"url":
"https://gerrit.wikimedia.org/r/mediawiki/extensions/WikibaseMediaInfo",
- "reference": "a841cd855cd01ee9d9bd6f3f7f9f40bfd4d7b0b5"
+ "reference": "7fe01856186fb92b8edcbd810a27603902f29a20"
},
"require": {
"php": ">=5.5.9",
@@ -1596,7 +1596,7 @@
"phpunit/phpunit": "~4.8",
"wikibase/wikibase-codesniffer": "^0.1.0"
},
- "time": "2017-07-25 20:48:22",
+ "time": "2017-07-31 11:44:06",
"type": "mediawiki-extension",
"installation-source": "source",
"autoload": {
@@ -1768,7 +1768,7 @@
"source": {
"type": "git",
"url":
"https://gerrit.wikimedia.org/r/mediawiki/extensions/WikibaseQualityConstraints",
- "reference": "1a936ad2688d6984ac936ea2a46c4a8cc807ff78"
+ "reference": "8614148918fc44218c82182610aff43fdd07f081"
},
"require": {
"php": ">=5.5.9",
@@ -1784,7 +1784,7 @@
"satooshi/php-coveralls": "master-dev",
"wikibase/wikibase-codesniffer": "^0.1.0"
},
- "time": "2017-07-29 13:45:32",
+ "time": "2017-07-31 21:06:39",
"type": "mediawiki-extension",
"installation-source": "source",
"autoload": {
--
To view, visit https://gerrit.wikimedia.org/r/369007
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I84c485d33ae10259ae3c8d5040fba6f914c111c6
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikidata
Gerrit-Branch: master
Gerrit-Owner: WikidataBuilder <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits