From 757d238cf6d306f9daf8276f620415cf09f4afe6 Mon Sep 17 00:00:00 2001 From: Magnus Manske Date: Fri, 11 Jun 2021 14:49:43 +0000 Subject: [PATCH 01/17] display fix --- public_html/vue_components/batch_access_mixin.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public_html/vue_components/batch_access_mixin.html b/public_html/vue_components/batch_access_mixin.html index 09e7b7c..031f83c 100644 --- a/public_html/vue_components/batch_access_mixin.html +++ b/public_html/vue_components/batch_access_mixin.html @@ -13,7 +13,7 @@ if ( typeof j.json != 'undefined' ) j = j.json ; if ( typeof j.item != 'undefined' ) to_cache[j.item] = 1 ; if ( typeof j.property != 'undefined' ) to_cache[j.property] = 1 ; - if ( typeof j.datavalue != 'undefined' && j.datavalue.type == 'wikibase-entityid' ) to_cache[j.datavalue.value.id] = 1 ; + if ( typeof j.datavalue != 'undefined' && j.datavalue!=null && j.datavalue.type == 'wikibase-entityid' ) to_cache[j.datavalue.value.id] = 1 ; } ) ; wd.getItemBatch ( Object.keys(to_cache) , resolve ) } ) ; From 89c490a59fe6735bc4c0105e888feee405527cea Mon Sep 17 00:00:00 2001 From: Magnus Manske Date: Thu, 9 Dec 2021 15:41:21 +0000 Subject: [PATCH 02/17] read groups --- public_html/quickstatements.php | 35 +++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/public_html/quickstatements.php b/public_html/quickstatements.php index 2843e7f..490a6e9 100644 --- a/public_html/quickstatements.php +++ b/public_html/quickstatements.php @@ -650,25 +650,32 @@ public function compressCommands ( $commands ) { ) { if ( $commands[$pos2]['what'] == 'sources' ) { - if ( !isset($claim['references']) ) $claim['references'] = array( ) ; - - $refs = array('snaks'=>array()) ; + if ( !isset($claim['references']) ) $claim['references'] = [] ; + + $refs = ['snaks'=>[]] ; foreach ( $commands[$pos2]['sources'] AS $s ) { - $source = array ( + if ( $s['new_source_group'] ) { + # Create new reference group + if ( count($refs['snaks'])>0 ) { + $claim['references'][] = $refs ; + $refs = ['snaks'=>[]] ; + } + } + $source = [ 'snaktype' => 'value' , 'property' => $s['prop'] , 'datavalue' => $s['value'] - ) ; + ] ; $refs['snaks'][$s['prop']][] = $source ; } $claim['references'][] = $refs ; } else if ( $commands[$pos2]['what'] == 'qualifier' ) { - $qual = array ( + $qual = [ 'property' => $commands[$pos2]['qualifier']['prop'] , 'snaktype' => 'value' , 'datavalue' => $commands[$pos2]['qualifier']['value'] - ) ; + ] ; $claim['qualifiers'][] = $qual ; } @@ -1236,8 +1243,9 @@ protected function importDataFromV1 ( $data , &$ret ) { $key = array_shift ( $cols ) ; $key = strtoupper ( trim ( $key ) ) ; $value = array_shift ( $cols ) ; - if ( preg_match ( '/^([SP])(\d+)$/i' , $key , $m ) ) { - $what = $m[1] == 'S' ? 'sources' : 'qualifier' ; + if ( preg_match ( '/^(S|P|!S)(\d+)$/i' , $key , $m ) ) { + $is_new_source_group = $m[1]=='!S' ; + $what = in_array($m[1], ['S','!S']) ? 'sources' : 'qualifier' ; $num = $m[2] ; // Store previous one, and reset @@ -1245,11 +1253,12 @@ protected function importDataFromV1 ( $data , &$ret ) { $skip_add_command = false ; $last_command = $ret['data']['commands'][count($ret['data']['commands'])-1] ; - $cmd = array ( 'action'=>$action , 'item'=>$first , 'property'=>$prop , 'what'=>$what , 'datavalue'=>$last_command['datavalue'] ) ; - $dummy = array() ; + $cmd = [ 'action'=>$action , 'item'=>$first , 'property'=>$prop , 'what'=>$what , 'datavalue'=>$last_command['datavalue'] ] ; + $dummy = [] ; $this->parseValueV1 ( $value , $dummy ) ; // TODO transfer error message - $dv = array ( 'prop' => 'P'.$num , 'value' => $dummy['datavalue'] ) ; - if ( $what == 'sources' ) $cmd[$what] = array($dv) ; + $dv = [ 'prop' => 'P'.$num , 'value' => $dummy['datavalue'] ] ; + if ( $is_new_source_group ) $dv['new_source_group'] = 1 ; + if ( $what == 'sources' ) $cmd[$what] = [$dv] ; else $cmd[$what] = $dv ; //$ret['debug'][] = array ( $what , $last_command['what'] ) ; if ( $what == 'sources' and $last_command['what'] == $what ) { From 9b0827d8c49f3369fc4fb920481ac1e1a9a8001b Mon Sep 17 00:00:00 2001 From: David Fichtmueller Date: Mon, 14 Mar 2022 15:58:50 +0100 Subject: [PATCH 03/17] removed strtolower() and trim() on site name check within run_single_command, the site name is checked against the currently available sites. This was done, using the functions strtolower() and trim() to clean up the file name. The only problem is that at no other point in the app are the site names adjusted this way, causing issues, when the site name uses upper case letters or spaces in the beginning and end. In wmde/wikibase-release-pipeline#293 I suggested using the same variable to full the site name, as the label, go show to the user which wikibase instance the user is going to write to with the current quickstatement page. For this branding however, users might be inclined to use a name that contains capital letters causing Quickstatements to fail when writing to the API. --- public_html/api.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public_html/api.php b/public_html/api.php index 553369e..20b6909 100644 --- a/public_html/api.php +++ b/public_html/api.php @@ -217,7 +217,7 @@ function validate_origin() { } else if ( $action == 'run_single_command' ) { validate_origin(); - $site = strtolower ( trim ( get_request ( 'site' , '' ) ) ) ; + $site = get_request ( 'site' , '' ) ; if ( !$qs->setSite ( $site ) ) { $out['status'] = "Error while setting site '{$site}': " . $qs->last_error_message ; } else { From 8d516dea588e0b0ada237504ba927860f23ae440 Mon Sep 17 00:00:00 2001 From: jmformenti Date: Thu, 27 Oct 2022 21:38:10 +0200 Subject: [PATCH 04/17] Resolves #34 --- public_html/quickstatements.php | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/public_html/quickstatements.php b/public_html/quickstatements.php index 490a6e9..ad32eb9 100644 --- a/public_html/quickstatements.php +++ b/public_html/quickstatements.php @@ -548,27 +548,30 @@ protected function isProperty ( $p ) { protected function getStatementID ( $command ) { if ( !$this->isProperty ( $command->property ) ) return ; if ( !isset($command->datavalue) ) return ; + if ( isset($command->new_statement) and $command->new_statement ) return ; $q = $command->item ; $this->wd->loadItem ( $q ) ; if ( !$this->wd->hasItem($q) ) return ; $i = $this->wd->getItem ( $q ) ; $claims = $i->getClaims ( $command->property ) ; + $last_claim_id = null ; foreach ( $claims AS $c ) { // when snaktype is somevalue/novalue, $c->mainsnak->datavalue doesn't exist (since the value is unknown or not existing) if ( $c->mainsnak->snaktype === "somevalue" || $c->mainsnak->snaktype === "novalue" ) { $lackingValueType = $c->mainsnak->snaktype ; - if ( $lackingValueType === $command->datavalue->type ) return $c->id ; + if ( $lackingValueType === $command->datavalue->type ) $last_claim_id = $c->id ; // return $c->id ; } else { if ( !isset($c->mainsnak) or !isset($c->mainsnak->datavalue) ) continue ; if ( !isset($command->datavalue) ) continue ; - if ( $this->compareDatavalue ( $c->mainsnak->datavalue , $command->datavalue ) ) return $c->id ; + if ( $this->compareDatavalue ( $c->mainsnak->datavalue , $command->datavalue ) ) $last_claim_id = $c->id ; // return $c->id ; } } + return $last_claim_id ; } // Return true if both datavalues are the same (for any given value of same...), or false otherwise @@ -632,7 +635,8 @@ public function compressCommands ( $commands ) { 'mainsnak' => array ( 'snaktype' => 'value' , 'property' => $commands[$pos]['property'] , - 'datavalue' => $commands[$pos]['datavalue'] + 'datavalue' => $commands[$pos]['datavalue'], + 'new_statement' => $commands[$pos]['new_statement'] ) , 'type' => 'statement' , 'rank' => 'normal' @@ -1227,9 +1231,14 @@ protected function importDataFromV1 ( $data , &$ret ) { $cols[0] = $m[1] ; } $first = strtoupper(trim($cols[0])) ; - if ( count ( $cols ) >= 3 and ( $this->isValidItemIdentifier($first) or $first == 'LAST' ) and $this->isValidItemIdentifier($cols[1]) ) { - $prop = strtoupper(trim($cols[1])) ; - $cmd = array ( 'action'=>$action , 'item'=>$first , 'property'=>$prop , 'what'=>'statement' ) ; + if ( count ( $cols ) >= 3 and ( $this->isValidItemIdentifier($first) or $first == 'LAST' ) and ( $this->isValidItemIdentifier($cols[1]) or preg_match ( '/^(!P)(\d+)$/i' , $cols[1] ) ) ) { + $prop = strtoupper(trim($cols[1])) ; + $is_new_statement = 0 ; + if ( $prop[0] == '!') { + $is_new_statement = 1 ; + $prop = substr($prop, 1) ; + } + $cmd = array ( 'action'=>$action , 'item'=>$first , 'property'=>$prop , 'what'=>'statement', 'new_statement'=>$is_new_statement ) ; if ( $comment != '' ) $cmd['summary'] = $comment ; $this->parseValueV1 ( $cols[2] , $cmd ) ; From d8bae918621f1b30bf220169f8fcd3db6b50e8b1 Mon Sep 17 00:00:00 2001 From: Magnus Manske Date: Thu, 3 Nov 2022 08:44:59 +0000 Subject: [PATCH 05/17] misc --- public_html/quickstatements.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/public_html/quickstatements.php b/public_html/quickstatements.php index 490a6e9..d5748c3 100644 --- a/public_html/quickstatements.php +++ b/public_html/quickstatements.php @@ -59,14 +59,15 @@ class QuickStatements { public $auth_db = '' ; public $debugging = false ; public $maxlag = 5 ; + public $verbose = false ; + public $logging = true ; protected $actions_v1 = array ( 'L'=>'label' , 'D'=>'description' , 'A'=>'alias' , 'S'=>'sitelink' ) ; protected $is_batch_run = false ; protected $user_name = '' ; protected $user_id = 0 ; - protected $user_groups = array() ; + protected $user_groups = [] ; protected $db ; - protected $logging = true ; public function __construct () { global $wikidata_api_url ; @@ -654,7 +655,7 @@ public function compressCommands ( $commands ) { $refs = ['snaks'=>[]] ; foreach ( $commands[$pos2]['sources'] AS $s ) { - if ( $s['new_source_group'] ) { + if ( isset($s['new_source_group']) ) { # Create new reference group if ( count($refs['snaks'])>0 ) { $claim['references'][] = $refs ; @@ -910,9 +911,11 @@ protected function commandAddStatement ( $command , $i , $statement_id ) { 'snaktype' => $this->getSnakType ( $command->datavalue ) , 'property' => $command->property , 'value' => json_encode ( $command->datavalue->value ) , - 'summary' => '' , - 'baserevid' => $i->j->lastrevid + 'summary' => '' ) ; + if ( isset($i->j) and isset($i->j->lastrevid) ) { + $action['baserevid'] = $i->j->lastrevid ; + } if ( $action['snaktype'] != 'value' ) unset( $action['value'] ); $this->runAction ( $action , $command ) ; if ( !$this->isBatchRun() ) $this->wd->updateItem ( $command->item ) ; @@ -1102,7 +1105,7 @@ public function runCommandArray ( $commands ) { foreach ( $commands AS $command_original ) { $command = $this->array2object ( $command_original ) ; $command = $this->runSingleCommand ( $command ) ; - if ( $command->status != 'done' ) { + if ( $command->status != 'done' and $this->verbose ) { print "
" ; print_r ( $command ) ; print "
" ; } // TODO proper error handling From 5175807fcf7468cc9387f60035ac5411d7221837 Mon Sep 17 00:00:00 2001 From: jmformenti Date: Sat, 12 Nov 2022 08:49:37 +0100 Subject: [PATCH 06/17] Import Julian dates --- public_html/quickstatements.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/public_html/quickstatements.php b/public_html/quickstatements.php index ad32eb9..4514765 100644 --- a/public_html/quickstatements.php +++ b/public_html/quickstatements.php @@ -1523,16 +1523,21 @@ protected function parseValueV1 ( $v , &$cmd ) { return true ; } - if ( preg_match ( '/^([+-]{0,1})(\d+)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z\/{0,1}(\d*)$/i' , $v , $m ) ) { // TIME + if ( preg_match ( '/^([+-]{0,1})(\d+)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z\/{0,1}(\d*)(\/J){0,1}$/i' , $v , $m ) ) { // TIME $prec = 9 ; if ( $m[8] != '' ) $prec = $m[8]*1 ; + $is_julian = false ; + if ( count($m) == 10 ) { + $is_julian = true ; + $v = preg_replace ( '/\/J$/', '', $v ) ; + } $cmd['datavalue'] = array ( "type"=>"time" , "value"=>array( 'time' => preg_replace ( '/\/\d+$/' , '' , $v ) , 'timezone' => 0 , 'before' => 0 , 'after' => 0 , 'precision' => $prec , - 'calendarmodel' => 'http://www.wikidata.org/entity/Q1985727' + 'calendarmodel' => $is_julian ? 'http://www.wikidata.org/entity/Q1985786' : 'http://www.wikidata.org/entity/Q1985727' ) ) ; return true ; } From 9911e1cbcc964c2a55af8e138b35057e918654eb Mon Sep 17 00:00:00 2001 From: Daniel Mietchen Date: Sun, 22 Jan 2023 21:52:07 +0100 Subject: [PATCH 07/17] documentation of ```format``` use via curl --- public_html/vue_components/user-page.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public_html/vue_components/user-page.html b/public_html/vue_components/user-page.html index cc4b0cf..3cb04ab 100644 --- a/public_html/vue_components/user-page.html +++ b/public_html/vue_components/user-page.html @@ -57,12 +57,13 @@
Here, you can generate a token to use when submitting bat For this to work, you need to have run a batch (server side) before manually, so your OAuth details can be filled in.

-
From the shell, use curl (assuming your QS commands are in a file test.qs; batchname is optional):
+
From the shell, use curl (assuming your QS commands are in a file test.qs; format can be "v1" or "csv"; batchname is optional):
 	curl https://quickstatements.toolforge.org/api.php \
 	-d action=import \
 	-d submit=1 \
+	-d format=FORMAT \
 	-d username={{encodeURIComponent(user.getUserName().replace(/ /g,'_'))}} \
 	-d "batchname=THE NAME OF THE BATCH" \
 	--data-raw 'token={{token}}' \

From b0163e741c80d711b9da6bdb974d7f3922282b5a Mon Sep 17 00:00:00 2001
From: addshore 
Date: Fri, 17 Feb 2023 15:57:15 +0000
Subject: [PATCH 08/17] api.php, ignore E_DEPRECATED errors

These break the API when using later verisons of PHP8 as deprecation warnings are printed.
https://github.com/wmde/wikibase-release-pipeline/pull/398#issuecomment-1434823727

As this is hardcoded and can't be overwritten by the php.ini file it's probably worth having
a default that is less broken
---
 public_html/api.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/public_html/api.php b/public_html/api.php
index 20b6909..2e0a59b 100644
--- a/public_html/api.php
+++ b/public_html/api.php
@@ -1,6 +1,6 @@
 
Date: Mon, 27 Feb 2023 20:45:23 +0100
Subject: [PATCH 09/17] Fix statement creation in CSV mode
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This was broken by 8d516dea58. The new $statement field 'new_statement'
is checked via isset() in getStatementID(), but unconditionally assumed
to exist in compressCommands(). However, only importDataFromV1() was
taught to create this field, while importDataFromCSV() wasn’t. This
meant that parsing CSV statements would produce a PHP warning, which is
included in the web response and thus breaks the JSON output.

Fixes #38.

An alternative would be to guard the access in compressCommands(); the
easiest option would be the `??` operator, but that was only added in
PHP 7.0 and I don’t really want to risk breaking sites that use
QuickStatements on older PHP (even though PHP 7.0 has been out for a
while already).
---
 public_html/quickstatements.php | 1 +
 1 file changed, 1 insertion(+)

diff --git a/public_html/quickstatements.php b/public_html/quickstatements.php
index d137d23..2f47abc 100644
--- a/public_html/quickstatements.php
+++ b/public_html/quickstatements.php
@@ -1382,6 +1382,7 @@ protected function importDataFromCSV ( $data, &$ret ) {
                 if ( $instruction[0] === 'P' ) {
                     $command += [
                         'what' => 'statement',
+                        'new_statement' => 0,
                         'property' => $instruction
                     ];
                     $this->parseValueV1( $value, $command );

From 2af6eeb30a4284039773b1115bbc4563ed6d3ed4 Mon Sep 17 00:00:00 2001
From: Lucas Werkmeister 
Date: Mon, 27 Feb 2023 21:05:58 +0100
Subject: [PATCH 10/17] =?UTF-8?q?Don=E2=80=99t=20try=20to=20send=20incompl?=
 =?UTF-8?q?ete=20values=20to=20the=20API?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

If parseValueV1() can’t parse the value, the $cmd it returns will still
have a 'datavalue', but there won’t be a 'value' inside it (but rather a
'text', along with 'type'=>'unknown'). This is apparently not checked at
any intervening point (neither in the V1 nor CSV formats), and
eventually the commandAdd*() methods would try to send the incomplete
data to the API, after producing several PHP warnings due to the missing
value (several of them inside getSnakType()), which would also break the
JSON response as usual.

Work around this by checking if we have a value just before sending the
API request. This means that the bad values will still be shown in the
batch view in a weird format (raw JSON), but I don’t know how that
should be fixed instead. This at least fixes the server-side warnings
and makes the batch not stuck indefinitely.
---
 public_html/quickstatements.php | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/public_html/quickstatements.php b/public_html/quickstatements.php
index d137d23..8a97fef 100644
--- a/public_html/quickstatements.php
+++ b/public_html/quickstatements.php
@@ -907,6 +907,7 @@ protected function getPrefixedID ( $q ) {
 	protected function commandAddStatement ( $command , $i , $statement_id ) {
 		// Paranoia
 		if ( isset($statement_id) ) return $this->commandDone ( $command , "Statement already exists as $statement_id" ) ;
+		if ( !isset($command->datavalue->value) ) return $this->commandError ( $command, "Incomplete command parameters" ) ;
 
 		// Execute!
 		$action = array (
@@ -931,6 +932,7 @@ protected function commandAddQualifier ( $command , $i , $statement_id ) {
 		if ( !isset($command->qualifier) ) return $this->commandError ( $command , "Incomplete command parameters" ) ;
 		if ( !isset($command->qualifier->prop) ) return $this->commandError ( $command , "Incomplete command parameters" ) ;
 		if ( !preg_match ( '/^P\d+$/' , $command->qualifier->prop ) ) return $this->commandError ( $command , "Invalid qualifier property {$command->qualifier->prop}" ) ;
+		if ( !isset($command->qualifier->value->value) ) return $this->commandError ( $command, "Incomplete command parameters" ) ;
 
 		// Execute!
 		$action = array (
@@ -957,6 +959,7 @@ protected function commandAddSources ( $command , $i , $statement_id ) {
 		// Prep
 		$snaks = array() ;
 		foreach ( $command->sources AS $source ) {
+			if ( !isset($source->value->value) ) return $this->commandError ( $command, "Incomplete command parameters" ) ;
 			$s = array(
 				'snaktype' => $this->getSnakType ( $source->value ) ,
 				'property' => $source->prop ,

From 8fb6cf24c181bfcd45bde3d5263f4edee125ca74 Mon Sep 17 00:00:00 2001
From: Magnus Manske 
Date: Tue, 11 Apr 2023 12:12:02 +0000
Subject: [PATCH 11/17] weird message default text

---
 public_html/quickstatements.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/public_html/quickstatements.php b/public_html/quickstatements.php
index 4ff9e0f..7e26252 100644
--- a/public_html/quickstatements.php
+++ b/public_html/quickstatements.php
@@ -165,7 +165,7 @@ public function addBatch ( $commands , $user_id , $name = '' , $site = '' ) {
 		if ( $this->use_command_compression ) $commands = $this->compressCommands ( $commands ) ;
 		$db = $this->getDB() ;
 		$ts = $this->getCurrentTimestamp() ;
-		$sql = "INSERT INTO batch (name,user,site,ts_created,ts_last_change,status) VALUES ('".$db->real_escape_string($name)."',$user_id,'".$db->real_escape_string($site)."','$ts','$ts','LOADING')" ;
+		$sql = "INSERT INTO batch (name,user,site,ts_created,ts_last_change,status,message) VALUES ('".$db->real_escape_string($name)."',$user_id,'".$db->real_escape_string($site)."','$ts','$ts','LOADING','')" ;
 		if(!$result = $db->query($sql)) return $this->setErrorMessage ( 'There was an error running the query [' . $db->error . ']'."\n$sql" ) ;
 		$batch_id = $db->insert_id ;
 		$serialized = serialize($this->getOA()) ;
@@ -181,7 +181,7 @@ public function addBatch ( $commands , $user_id , $name = '' , $site = '' ) {
 			if ( trim($cs) == '' ) continue ; // Paranoia
 			$status = 'INIT' ;
 			if ( isset($c->status) and trim($c->status) != '' ) $status = strtoupper(trim($c->status)) ;
-			$sql = "INSERT INTO command (batch_id,num,json,status,ts_change) VALUES ($batch_id,$k,'".$db->real_escape_string($cs)."','".$db->real_escape_string($status)."','$ts')" ;
+			$sql = "INSERT INTO command (batch_id,num,json,status,ts_change,message) VALUES ($batch_id,$k,'".$db->real_escape_string($cs)."','".$db->real_escape_string($status)."','$ts','')" ;
 			if(!$result = $db->query($sql)) return $this->setErrorMessage ( 'There was an error running the query [' . $db->error . ']'."\n$sql" ) ;
 		}
 		$sql = "UPDATE batch SET status='INIT' WHERE id=$batch_id" ;

From d7c084d9bec73510a244cb3c60ec14d44283969c Mon Sep 17 00:00:00 2001
From: Lucas Werkmeister 
Date: Wed, 21 Jun 2023 20:13:09 +0200
Subject: [PATCH 12/17] Fix setting sitelinks

Basically the same as commit 4622f78d55, just for another API action.
No Wikibase API needs entity IDs with namespaces ("Item:Q24").
---
 public_html/quickstatements.php | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/public_html/quickstatements.php b/public_html/quickstatements.php
index 7e26252..7705eca 100644
--- a/public_html/quickstatements.php
+++ b/public_html/quickstatements.php
@@ -894,16 +894,6 @@ protected function getSnakType ( $datavalue ) {
 		return 'value' ;
 	}
 	
-	protected function getPrefixedID ( $q ) {
-		$q = trim ( strtoupper ( $q ) ) ;
-		
-		foreach ( $this->getSite()->types AS $char => $data ) {
-			if ( !isset($data->ns_prefix) or $data->ns_prefix == '' ) continue ;
-			if ( preg_match ( '/^'.$char.'\d+$/' , $q ) ) return $data->ns_prefix.$q ;
-		}
-		return $q ;
-	}
-	
 	protected function commandAddStatement ( $command , $i , $statement_id ) {
 		// Paranoia
 		if ( isset($statement_id) ) return $this->commandDone ( $command , "Statement already exists as $statement_id" ) ;
@@ -1055,7 +1045,7 @@ protected function commandSetSitelink ( $command , $i ) {
 		// Execute!
 		$this->runAction ( array (
 			'action' => 'wbsetsitelink' ,
-			'id' => $this->getPrefixedID ( $command->item ) ,
+			'id' => $command->item ,
 			'linksite' => $command->site ,
 			'linktitle' => $command->value ,
 			'summary' => '' ,

From 8ed0601d447e26c45bee27056c221b9761c790a1 Mon Sep 17 00:00:00 2001
From: Magnus Manske 
Date: Wed, 21 Jun 2023 19:37:04 +0000
Subject: [PATCH 13/17] misc

---
 public_html/quickstatements.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/public_html/quickstatements.php b/public_html/quickstatements.php
index 7e26252..7e06318 100644
--- a/public_html/quickstatements.php
+++ b/public_html/quickstatements.php
@@ -746,7 +746,7 @@ protected function getBotAPI ( $force_login = false ) {
 		
 	}
 	
-	public function runBotAction ( $params_orig , $attempts_left = 1000 , $lag = 0 ) {
+	public function runBotAction ( $params_orig , $attempts_left = 10 , $lag = 0 ) {
 		if ( $attempts_left <= 0 ) return false ;
 		if ( $lag == 0 ) $lag = $this->maxlag ;
 		$params = array() ;

From 549be5e961b95d6b2aa59c99f2eb9ec41d1b8c1d Mon Sep 17 00:00:00 2001
From: Magnus Manske 
Date: Mon, 8 Jul 2024 11:02:38 +0100
Subject: [PATCH 14/17] reset bugfix

---
 public_html/vue_components/batch.html | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/public_html/vue_components/batch.html b/public_html/vue_components/batch.html
index 7222b87..e82440c 100644
--- a/public_html/vue_components/batch.html
+++ b/public_html/vue_components/batch.html
@@ -287,11 +287,12 @@
         	var me = this ;
         	if ( me.meta.batch.id == 0 ) { // In browser
         		$.each ( me.meta.batch.data.commands , function ( k , cmd ) {
-        			if ( typeof cmd.meta == 'undefined' || typeof cmd.meta.status == 'undefined' || cmd.meta.status != 'ERROR' ) return ;
+        			if ( typeof cmd.meta == 'undefined' || typeof cmd.meta.status == 'undefined' || (cmd.meta.status != 'ERROR' && cmd.meta.status != 'RUN') ) return ;
         			if ( cmd.action == 'CREATE' && typeof cmd.data == 'undefined' ) return ;
         			if ( typeof cmd.item != 'undefined' && cmd.item == 'LAST' ) return ;
+        			let old_status = cmd.meta.status;
         			cmd.meta.status = 'INIT' ;
-        			Vue.set ( me.meta.commands , 'ERROR' , (me.meta.commands.ERROR||0)-1 ) ;
+        			Vue.set ( me.meta.commands , old_status , (me.meta.commands.ERROR||0)-1 ) ;
         			Vue.set ( me.meta.commands , 'INIT' , (me.meta.commands.INIT||0)+1 ) ;
         		} ) ;
         	} else {

From 994f57c195a388452d42044e86ba3b33088cbe71 Mon Sep 17 00:00:00 2001
From: Magnus Manske 
Date: Mon, 8 Jul 2024 17:20:51 +0000
Subject: [PATCH 15/17] bugfix

---
 public_html/vue_components/batch.html | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/public_html/vue_components/batch.html b/public_html/vue_components/batch.html
index e82440c..ce57810 100644
--- a/public_html/vue_components/batch.html
+++ b/public_html/vue_components/batch.html
@@ -351,6 +351,10 @@
 			else j.summary = me.run.temp_id + "; " + j.summary ;
 
 			$('#working').show() ;
+			me.actuallyRunCommand(j,original_summary,cmdnum,5);
+		},
+		actuallyRunCommand: function ( j , original_summary , cmdnum , attempts_left ) {
+			let me = this;
 			$.post ( me.api , {
 				action:'run_single_command',
 				command : JSON.stringify(j) ,
@@ -374,7 +378,14 @@
 				setTimeout ( function () { me.runNextCommand() } , me.direct_command_delay_ms ) ;
 				me.run.last_ts = me.getTimestampNow() ;
 			} , 'json' )
-			. fail ( function () {
+			. fail ( function(xhr, status, error) {
+				if ( attempts_left > 0 ) {
+					// Try again after two seconds
+					setTimeout ( function() {
+						me.actuallyRunCommand( j , original_summary , cmdnum , attempts_left-1 );
+					} , 2000 );
+					return;
+				}
 				$('#working').hide() ;
 				if ( typeof d.command.message != 'undefined' ) d.command.meta.message = d.command.message ;
 //				d.command.summary = original_summary ; // To remove the temporary_batch

From 83b9fe3534a606662fd6dceb152041796bd9fbc4 Mon Sep 17 00:00:00 2001
From: dena 
Date: Fri, 31 Jan 2025 12:03:11 +0100
Subject: [PATCH 16/17] avoid float to int conversion

---
 public_html/quickstatements.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/public_html/quickstatements.php b/public_html/quickstatements.php
index 8ea6add..1849b59 100644
--- a/public_html/quickstatements.php
+++ b/public_html/quickstatements.php
@@ -1116,7 +1116,7 @@ public function getTemporaryBatchSummary () {
 	}
 	
 	public function runSingleCommand ( $command ) {
-		if ( $this->sleep != 0 ) sleep ( $this->sleep ) ;
+		if ( $this->sleep != 0 ) sleep ( $this->usleep * 1000 ) ;
 		if ( !isset($command) ) return $this->commandError ( $command , "Empty command" ) ;
 		$command->status = 'working' ;
 		if ( isset($command->error) ) unset ( $command->error ) ;

From d8ab836bbd1386f9bcbf9993314894fbd112d7a5 Mon Sep 17 00:00:00 2001
From: dena 
Date: Tue, 11 Feb 2025 14:26:10 +0100
Subject: [PATCH 17/17] add pending upstream fix

https://github.com/magnusmanske/quickstatements/pull/60
---
 public_html/quickstatements.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/public_html/quickstatements.php b/public_html/quickstatements.php
index 34cfe51..fca7bbf 100644
--- a/public_html/quickstatements.php
+++ b/public_html/quickstatements.php
@@ -1141,7 +1141,7 @@ public function getTemporaryBatchSummary () {
 	}
 
 	public function runSingleCommand ( $command ) {
-		if ( $this->sleep != 0 ) sleep ( $this->usleep * 1000 ) ;
+		if ( $this->sleep != 0 ) usleep ( $this->sleep * 1000 ) ;
 		if ( !isset($command) ) return $this->commandError ( $command , "Empty command" ) ;
 		$command->status = 'working' ;
 		if ( isset($command->error) ) unset ( $command->error ) ;