r26049 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r26048‎ | r26049 | r26050 >
Date:01:02, 24 September 2007
Author:kim
Status:old
Tags:
Comment:
* Added SpecialCopy as a file (doesn'd do any work, but doesn't break
anything either)
* Converted util/Copy.php to an actual library, will need some further
modifications to work inside the wikidata framework
* removed old files that are no longer used.
Modified paths:
  • /trunk/extensions/Wikidata/App.php (modified) (history)
  • /trunk/extensions/Wikidata/OmegaWiki/Copy.php (added) (history)
  • /trunk/extensions/Wikidata/OmegaWiki/CopyDM.php (deleted) (history)
  • /trunk/extensions/Wikidata/OmegaWiki/GetDM.php (deleted) (history)
  • /trunk/extensions/Wikidata/OmegaWiki/SaveDM.php (deleted) (history)
  • /trunk/extensions/Wikidata/OmegaWiki/SpecialCopy.php (added) (history)

Diff [purge]

Index: trunk/extensions/Wikidata/App.php
@@ -50,6 +50,7 @@
5151 require_once("{$IP}/extensions/Wikidata/OmegaWiki/SpecialImportLangNames.php");
5252 require_once("{$IP}/extensions/Wikidata/OmegaWiki/SpecialAddCollection.php");
5353 require_once("{$IP}/extensions/Wikidata/OmegaWiki/SpecialConceptMapping.php");
 54+require_once("{$IP}/extensions/Wikidata/OmegaWiki/SpecialCopy.php");
5455
5556 function addWikidataHeader() {
5657 global $wgOut,$wgScriptPath;
Index: trunk/extensions/Wikidata/OmegaWiki/CopyDM.php
@@ -1,46 +0,0 @@
2 -<?php
3 -
4 -# testing what we learned in SaveDM
5 -# (possibly files like this should go in a subdir
6 -# and/or be replaced by proper unit testing)
7 -
8 -define('MEDIAWIKI', true );
9 -
10 -# do we seriously need ALL of these?
11 -require_once("../../../StartProfiler.php");
12 -require_once("../../../LocalSettings.php");
13 -require_once("../php-tools/ProgressBar.php");
14 -#require_once("DatabaseUtilities.php");
15 -require_once("Setup.php");
16 -require_once("DefinedMeaningModel.php");
17 -require_once("Transaction.php");
18 -
19 -/** Just get a defined meaning */
20 -function getDM($definedMeaningId,$dc="uw") {
21 - global
22 - $wdCurrentContext;
23 - $wdCurrentContext=$dc;
24 - $model=new DefinedMeaningModel($definedMeaningId);
25 - return $model;
26 -}
27 -
28 -global
29 -$beginTime, $wgCommandLineMode, $dc;
30 -
31 -$beginTime = time();
32 -$wgCommandLineMode = true;
33 -# $dc = "uw"; < can't modify from here
34 -
35 -/* insert code here */
36 -
37 -$model=getDM(663678,"tt");
38 -
39 -$record=$model->getRecord();
40 -echo $record;
41 -
42 -$model->copyTo("uw");
43 -
44 -$endTime = time();
45 -echo("\n\nTime elapsed: " . durationToString($endTime - $beginTime));
46 -
47 -
Index: trunk/extensions/Wikidata/OmegaWiki/GetDM.php
@@ -1,68 +0,0 @@
2 -<?php
3 -
4 -# let's see...
5 -# start out with a test skeleton, get a record from one dataset
6 -# and print it out
7 -# This is just saveDM with the actual save call removed :-P
8 -# (it's simply too handy not to do ;-))
9 -
10 -define('MEDIAWIKI', true );
11 -
12 -# do we seriously need ALL of these?
13 -require_once("../../../StartProfiler.php");
14 -require_once("../../../LocalSettings.php");
15 -require_once("../php-tools/ProgressBar.php");
16 -#require_once("DatabaseUtilities.php");
17 -require_once("Setup.php");
18 -require_once("DefinedMeaningModel.php");
19 -require_once("Transaction.php");
20 -
21 -/** Just get a defined meaning */
22 -function getDM($definedMeaningId,$dc="uw") {
23 - global
24 - $wdCurrentContext;
25 - $wdCurrentContext=$dc;
26 - #$viewInformation = new ViewInformation();
27 - #$viewInformation->queryTransactionInformation= new QueryLatestTransactionInformation();
28 - $model=new DefinedMeaningModel($definedMeaningId);
29 - $record=$model->getRecord();
30 - #$record->finish("DefinedMeaning");
31 - return $model;
32 -}
33 -
34 -function saveDM($model,$dc="uw") {
35 - global
36 - $wdCurrentContext;
37 - $wdCurrentContext=$dc;
38 - #echo $model->getRecord();
39 - $model->saveWithinTransaction();
40 -}
41 -
42 -global
43 -$beginTime, $wgCommandLineMode, $dc;
44 -
45 -$beginTime = time();
46 -$wgCommandLineMode = true;
47 -# $dc = "uw"; < can't modify from here
48 -
49 -/* insert code here */
50 -
51 -$model=getDM(663674,"tt");
52 -
53 -$record=$model->getRecord();
54 -echo $record;
55 -$defexp=$record->getValue("defined-meaning-complete-defining-expression");
56 -echo $defexp."\n";
57 -#$expid=$record->getAttributeValue(new Attribute("expression-id"));
58 -$id=$defexp->getValue("expression-id");
59 -$spelling=$defexp->getValue("defined-meaning-defining-expression");
60 -$language=$defexp->getValue("language");
61 -
62 -echo "id: $id, spelling:$spelling, language:$language";
63 -
64 -#saveDM($model,"uw");
65 -
66 -$endTime = time();
67 -echo("\n\nTime elapsed: " . durationToString($endTime - $beginTime));
68 -
69 -
Index: trunk/extensions/Wikidata/OmegaWiki/SaveDM.php
@@ -1,67 +0,0 @@
2 -<?php
3 -
4 -# let's see...
5 -# start out with a test skeleton, get a record from one dataset
6 -# then save it to the other. Once this works, we can wrap it up nicely, and
7 -# apply it to our actual code.
8 -
9 -define('MEDIAWIKI', true );
10 -
11 -# do we seriously need ALL of these?
12 -require_once("../../../StartProfiler.php");
13 -require_once("../../../LocalSettings.php");
14 -require_once("../php-tools/ProgressBar.php");
15 -#require_once("DatabaseUtilities.php");
16 -require_once("Setup.php");
17 -require_once("DefinedMeaningModel.php");
18 -require_once("Transaction.php");
19 -
20 -/** Just get a defined meaning */
21 -function getDM($definedMeaningId,$dc="uw") {
22 - global
23 - $wdCurrentContext;
24 - $wdCurrentContext=$dc;
25 - #$viewInformation = new ViewInformation();
26 - #$viewInformation->queryTransactionInformation= new QueryLatestTransactionInformation();
27 - $model=new DefinedMeaningModel($definedMeaningId);
28 - $record=$model->getRecord();
29 - #$record->finish("DefinedMeaning");
30 - return $model;
31 -}
32 -
33 -function saveDM($model,$dc="uw") {
34 - global
35 - $wdCurrentContext;
36 - $wdCurrentContext=$dc;
37 - #echo $model->getRecord();
38 - $model->saveWithinTransaction();
39 -}
40 -
41 -global
42 -$beginTime, $wgCommandLineMode, $dc;
43 -
44 -$beginTime = time();
45 -$wgCommandLineMode = true;
46 -# $dc = "uw"; < can't modify from here
47 -
48 -/* insert code here */
49 -
50 -$model=getDM(663674,"tt");
51 -
52 -$record=$model->getRecord();
53 -echo $record;
54 -$defexp=$record->getValue("defined-meaning-complete-defining-expression");
55 -echo $defexp."\n";
56 -#$expid=$record->getAttributeValue(new Attribute("expression-id"));
57 -$id=$defexp->getValue("expression-id");
58 -$spelling=$defexp->getValue("defined-meaning-defining-expression");
59 -$language=$defexp->getValue("language");
60 -
61 -echo "id: $id, spelling:$spelling, language:$language";
62 -
63 -saveDM($model,"uw");
64 -
65 -$endTime = time();
66 -echo("\n\nTime elapsed: " . durationToString($endTime - $beginTime));
67 -
68 -
Index: trunk/extensions/Wikidata/OmegaWiki/Copy.php
@@ -0,0 +1,727 @@
 2+<?php
 3+
 4+# (C) 2007 Alan Smithee (licensed under the GPL v. 2, GPL v. 3 or any later version, though you're not likely to care)
 5+# Copy library to copy defined meanings between tables.
 6+# Based on the util/copy.php throwaway.
 7+#
 8+# Not the greatest code ever written, but will have to live with it for now
 9+#
 10+# common abbreviations used in varnames and comments:
 11+# dm = defined meaning.
 12+# dmid = defined meaning id: unique identifier for each dm.
 13+# dc = dataset context. datasets are implemented by having
 14+# tables with different prefixes
 15+# dc1 = dataset (context) 1 (we are copying FROM dc1 (so we READ) )
 16+# dc2 = dataset (context) 2 (we are copying TO dc2 (so we WRITE) )
 17+#
 18+# naming conventions:
 19+# Normal: Java Style
 20+# * ClassName->methodName($variableName); /* comment */
 21+# * CopyTools::getRow(...); # comment
 22+# Wrappers around PHP functions or extensions to PHP function set: Same style as the wrapped function
 23+# * mysql_insert_assoc(...); # comment
 24+#
 25+# TODO:
 26+# * Change to library
 27+# * some read/write/dup functions are still main namespace, should get their own
 28+# * classes (!!)
 29+
 30+#require_once("../../../StartProfiler.php");
 31+#include_once("../../../includes/Defines.php");
 32+#include_once("../../../LocalSettings.php");
 33+#require_once("Setup.php");
 34+require_once("WikiDataAPI.php");
 35+require_once("Transaction.php");
 36+
 37+/** copies items in the objects table.
 38+ * As a "side-effect"
 39+ * also conveniently reports to see if something was already_there
 40+ * (we don't want to accidentally duplicate things umpteen times, so the
 41+ * side-effect is almost as important)
 42+ */
 43+class ObjectCopier {
 44+
 45+ protected $id;
 46+ protected $dc1;
 47+ protected $dc2;
 48+ protected $object;
 49+ protected $already_there=null;
 50+
 51+ function __construct($id, $dc1, $dc2) {
 52+ $this->id=$id;
 53+ $this->dc1=$dc1;
 54+ $this->dc2=$dc2;
 55+ }
 56+
 57+ function getObject() {
 58+ return $this->object;
 59+ }
 60+
 61+ function setObject($object) {
 62+ $this->object=$object;
 63+ }
 64+
 65+ /** return true if the object was already present in the other dataset*/
 66+ public function already_there(){
 67+ return $this->already_there;
 68+ }
 69+
 70+ protected function read() {
 71+ $dc1=$this->dc1;
 72+ $id=$this->id;
 73+ $this->object=CopyTools::getRow($dc1, "objects", "WHERE object_id=$id");
 74+ }
 75+
 76+ /* tries to retrieve the identical UUID from the destination
 77+ * (dc2) dataset, if it exists.
 78+ * @returns the associative array representing this object,
 79+ * if successful. Else returns an empty array.
 80+ */
 81+ protected function identical() {
 82+ var_dump($this->object);
 83+ $uuid=mysql_escape_string($this->object["UUID"]);
 84+ $dc2=$this->dc2;
 85+ return CopyTools::getRow($dc2, "objects", "WHERE `UUID`='$uuid'");
 86+ }
 87+
 88+ /** Write copy of object into the objects table,taking into account
 89+ * necessary changes.
 90+ * possible TODO: Currently induces the target table from the original
 91+ * destination table name.
 92+ * Perhaps would be wiser to get the target table as an (override) parameter.
 93+ */
 94+ function write() {
 95+ $dc2 = $this->dc2;
 96+ $object = $this->object;
 97+ unset($object["object_id"]);
 98+
 99+ $tableName_exploded = explode("_", $object["table"]);
 100+ $tableName_exploded[0] = $dc2;
 101+ $tableName = implode("_", $tableName_exploded);
 102+ $object["table"]=$tableName;
 103+
 104+ CopyTools::dc_insert_assoc($dc2,"objects",$object);
 105+ return mysql_insert_id();
 106+ }
 107+
 108+ function dup() {
 109+ $this->read();
 110+ $object2=$this->identical();
 111+ if (CopyTools::sane_key_exists("object_id",$object2)) {
 112+ $this->already_there=true;
 113+ $newid=$object2["object_id"];
 114+ } else {
 115+ $this->already_there=false;
 116+ $newid=$this->write();
 117+ }
 118+ return $newid;
 119+ }
 120+}
 121+
 122+
 123+/** obtain an expression definition from the database
 124+ * @param $expression_id the id of the expression
 125+ * @param $dc1 dataset to READ expression FROM
 126+ */
 127+function expression($expression_id, $dc1) {
 128+ return CopyTools::getRow($dc1, "expression", "WHERE expression_id=$expression_id");
 129+}
 130+
 131+
 132+function getOldSyntrans($dc1, $dmid, $expid) {
 133+ return CopyTools::getRow($dc1, "syntrans", "where defined_meaning_id=$dmid and expression_id=$expid");
 134+}
 135+
 136+function writeSyntrans($syntrans, $newdmid, $newexpid, $dc2) {
 137+ $syntrans["defined_meaning_id"]=$newdmid;
 138+ $syntrans["expression_id"]=$newexpid;
 139+ CopyTools::dc_insert_assoc($dc2,"syntrans",$syntrans);
 140+}
 141+
 142+function dupSyntrans($dc1, $dc2, $olddmid, $oldexpid, $newdmid, $newexpid) {
 143+ $syntrans=getOldSyntrans($dc1, $olddmid, $oldexpid);
 144+ $copier=new ObjectCopier($syntrans["syntrans_sid"], $dc1, $dc2);
 145+ $newid=$copier->dup();
 146+ if ($copier->already_there()) {
 147+ return;
 148+ }
 149+ $syntrans["syntrans_sid"]=$newid;
 150+ writeSyntrans($syntrans, $newdmid, $newexpid, $dc2);
 151+}
 152+
 153+function get_syntranses($dmid, $dc1) {
 154+ return CopyTools::getRows($dc1, "syntrans", "where defined_meaning_id=$dmid");
 155+}
 156+
 157+
 158+/* some coy&paste happening here, might want to tidy even before we
 159+* toss this throwaway code*/
 160+function write_expression($expression, $src_dmid, $dst_dmid, $dc1, $dc2) {
 161+
 162+ $copier=new ObjectCopier($expression["expression_id"], $dc1, $dc2);
 163+ $target_expid1=$copier->dup();
 164+ $save_expression=$expression;
 165+ $save_expression["expression_id"]=$target_expid1;
 166+ if (!($copier->already_there())) {
 167+ CopyTools::dc_insert_assoc($dc,"expression",$save_expression);
 168+ }
 169+ dupsyntrans(
 170+ $dc1,
 171+ $dc2,
 172+ $src_dmid,
 173+ $expression["expression_id"],
 174+ $dst_dmid,
 175+ $save_expression["expression_id"]
 176+ );
 177+
 178+}
 179+
 180+function write_syntranses($syntranses, $src_dmid, $dst_dmid, $dc1, $dc2) {
 181+ var_dump($syntranses);
 182+ print "<br>\nExpressions:";
 183+ foreach ($syntranses as $syntrans) {
 184+ $expression=expression($syntrans["expression_id"],$dc1);
 185+ print $expression["spelling"].";";
 186+ write_expression($expression, $src_dmid, $dst_dmid, $dc1, $dc2);
 187+ # ^- which incidentally also dups the syntrans
 188+ }
 189+}
 190+
 191+function dup_syntranses($src_dmid, $dst_dmid, $dc1, $dc2) {
 192+ $syntranses=get_syntranses($src_dmid, $dc1);
 193+ write_syntranses($syntranses, $src_dmid, $dst_dmid, $dc1, $dc2);
 194+}
 195+
 196+function read_translated_content($dc1,$tcid) {
 197+ return CopyTools::getRows($dc1,"translated_content","where translated_content_id=$tcid");
 198+}
 199+
 200+function write_translated_content($dc1, $dc2, $tcid, $content) {
 201+ $content["translated_content_id"]=$tcid;
 202+ $content["text_id"]=dup_text($dc1, $dc2, $content["text_id"]);
 203+ var_dump($content);
 204+ CopyTools::dc_insert_assoc($dc2, "translated_content", $content);
 205+}
 206+
 207+
 208+function dup_translated_content($dc1, $dc2, $tcid) {
 209+ $translated_content=read_translated_content($dc1, $tcid);
 210+ $copier=new ObjectCopier($tcid, $dc1, $dc2);
 211+ $new_tcid=$copier->dup();
 212+ # note the issue where translated content is added later:
 213+ # since all translated content for a single dm
 214+ # shares one UUID, we can't check for that eventuality.
 215+ if ($copier->already_there()) {
 216+ return;
 217+ }
 218+ foreach ($translated_content as $item) {
 219+ write_translated_content($dc1, $dc2, $new_tcid, $item);
 220+ }
 221+ return $new_tcid;
 222+}
 223+
 224+function read_text($dc1,$text_id) {
 225+ return CopyTools::getRow($dc1,"text","where text_id=$text_id");
 226+}
 227+
 228+function write_text($dc2,$text) {
 229+ unset($text["text_id"]);
 230+ # inconsistent, insert_assoc should accept dc, table
 231+ $target_table=mysql_real_escape_string("${dc2}_text");
 232+ CopyTools::dc_insert_assoc($dc2, "text", $text);
 233+ return mysql_insert_id();
 234+}
 235+
 236+function dup_text($dc1, $dc2, $text_id) {
 237+ $text=read_text($dc1, $text_id);
 238+ $id=write_text($dc2, $text);
 239+ return $id;
 240+}
 241+
 242+class RelationsCopier {
 243+
 244+ protected $old_dmid;
 245+ protected $new_dmid;
 246+ protected $dc1;
 247+ protected $dc2;
 248+
 249+ function __construct($dc1, $dc2, $old_dmid, $new_dmid) {
 250+ $this->old_dmid=$old_dmid;
 251+ $this->new_dmid=$new_dmid;
 252+ $this->dc1=$dc1;
 253+ $this->dc2=$dc2;
 254+ }
 255+
 256+ function read() {
 257+ $dc1=$this->dc1;
 258+ $dmid=$this->old_dmid;
 259+ return CopyTools::getRows($dc1,"meaning_relations","where meaning1_mid=$dmid");
 260+ }
 261+
 262+ function write_single($relation) {
 263+ var_dump($relation);
 264+ $dc1=$this->dc1;
 265+ $dc2=$this->dc2;
 266+ $new_dmid=$this->new_dmid;
 267+
 268+ $copier=new ObjectCopier($relation["relation_id"], $dc1, $dc2);
 269+ $relation["relation_id"]=$copier->dup();
 270+ if ($copier->already_there()) {
 271+ return;
 272+ }
 273+ $relation["meaning1_mid"]=$new_dmid;
 274+ $dmcopier=new DefinedMeaningCopier($relation["meaning2_mid"],$dc1, $dc2);
 275+ $relation["meaning2_mid"]=$dmcopier->dup_stub();
 276+ # Typically checks same values each time. Accelerated by query_cache:
 277+ $rtcopier=new DefinedMeaningCopier($relation["relationtype_mid"],$dc1, $dc2);
 278+ $relation["relationtype_mid"]=$rtcopier->dup_stub();
 279+ var_dump($relation);
 280+ $copier=new ObjectCopier($relation["relation_id"], $dc1, $dc2);
 281+ $relation["relation_id"]=$copier->dup();
 282+ if ($copier->already_there()) {
 283+ return;
 284+ }
 285+ CopyTools::dc_insert_assoc($dc2,"meaning_relations",$relation);
 286+
 287+ }
 288+
 289+ function dup() {
 290+ $rows=$this->read();
 291+ echo "copying relations";
 292+ foreach ($rows as $row) {
 293+ $this->write_single($row);
 294+ }
 295+ }
 296+}
 297+
 298+class CollectionCopier {
 299+ protected $dmid;
 300+ protected $save_dmid;
 301+ protected $dc1;
 302+ protected $dc2;
 303+ protected $already_there=false;
 304+
 305+ public function already_there() {
 306+ return $this->already_there;
 307+ }
 308+
 309+ public function __construct ($dc1, $dc2, $dmid, $save_dmid) {
 310+ $this->dmid=$dmid;
 311+ $this->save_dmid=$save_dmid;
 312+ $this->dc1=$dc1;
 313+ $this->dc2=$dc2;
 314+ }
 315+
 316+ public function read($dc=Null){
 317+ if (is_null($dc)) {
 318+ $dc=$this->dc1;
 319+ }
 320+ $dmid=$this->dmid;
 321+ return CopyTools::getRows($dc, "collection_contents", "WHERE member_mid=$dmid");
 322+ }
 323+
 324+
 325+ public function read_definition($collection_id) {
 326+ $dc1=$this->dc1;
 327+ return CopyTools::getRow($dc1,"collection","WHERE collection_id=$collection_id");
 328+ }
 329+
 330+ /** write collection definition (and associated dm) to dc2
 331+ * if it doesn't already exist.
 332+ * If it already exists, will only look up the id.
 333+ * returns the id for dc2 either way.
 334+ */
 335+ public function write_definition($definition){
 336+ $dc1=$this->dc1;
 337+ $dc2=$this->dc2;
 338+
 339+ print "<br>\nCopying collection</br>";
 340+ var_dump($definition);
 341+ print $definition["collection_id"];
 342+ $objcopier=new ObjectCopier($definition["collection_id"], $dc1, $dc2);
 343+ $definition["collection_id"]=$objcopier->dup();
 344+ if (!$objcopier->already_there()) {
 345+ $dmid= $definition["collection_mid"];
 346+ $dmcopier=new DefinedMeaningCopier($dmid,$dc1,$dc2);
 347+ $definition["collection_mid"]=$dmcopier->dup_stub();
 348+
 349+ CopyTools::dc_insert_assoc($dc2, "collection", $definition);
 350+
 351+ }
 352+ return $definition["collection_id"];
 353+
 354+ }
 355+
 356+ /** look up the collection definition in %_collection,
 357+ * and copy if doesn't already exist in dc2
 358+ */
 359+ public function dup_definition($collection_id) {
 360+ $definition=$this->read_definition($collection_id);
 361+ return $this->write_definition($definition);
 362+ }
 363+
 364+
 365+ # we create a mapping and THEN do collections, now we need to prevent ourselves dupping
 366+ # existing mappings
 367+ public function existing_mapping($member_id) {
 368+ $dc2=$this->dc2;
 369+ $query="SELECT ${dc2}_collection_contents.* FROM ${dc2}_collection_contents, ${dc2}_collection
 370+ WHERE ${dc2}_collection_contents.collection_id = ${dc2}_collection.collection_id
 371+ AND collection_type=\"MAPP\"
 372+ AND internal_member_id=\"${member_id}\"";
 373+ $mapping_here=CopyTools::doQuery($query);
 374+
 375+ if ($mapping_here==false)
 376+ return false;
 377+ else
 378+ return true; # if anything is actually returned, we know the score.
 379+ }
 380+
 381+
 382+ /** write a single collection_contents row,
 383+ * (if the collection doesn't exist yet), also dup the definition
 384+ */
 385+ public function write_single($row){
 386+ $dc2=$this->dc2;
 387+ $save_dmid=$this->save_dmid;
 388+ $row["collection_id"]=$this->dup_definition($row["collection_id"]);
 389+
 390+ if ( $this->existing_mapping($row["internal_member_id"]) )
 391+ return;
 392+
 393+ $row["member_mid"]=$save_dmid;
 394+ CopyTools::dc_insert_assoc($dc2, "collection_contents", $row);
 395+ }
 396+
 397+ public function write($rows){
 398+ foreach ($rows as $row) {
 399+ $this->write_single($row);
 400+ }
 401+ }
 402+
 403+ /** writes a duplicate. does *NOT* return ids on return, as there
 404+ * are multiple ids
 405+ */
 406+ public function dup() {
 407+ # Is there something already there? If so, do not dup.
 408+ $checkrows=$this->read($this->dc2);
 409+ foreach ($checkrows as $row) {
 410+ if ($row["member_mid"]==$this->save_dmid){
 411+ $this->already_there=true;
 412+ return;
 413+ }
 414+ }
 415+
 416+ #seems ok, let's dup.
 417+ $rows=$this->read($this->dc1);
 418+ $this->write($rows);
 419+ }
 420+}
 421+
 422+
 423+class DefinedMeaningCopier {
 424+
 425+ protected $defined_meaning;
 426+ protected $save_meaning;
 427+ protected $dmid;
 428+ protected $dc1;
 429+ protected $dc2;
 430+ protected $already_there=false;
 431+
 432+ public function __construct ($dmid, $dc1, $dc2) {
 433+ $this->dmid=$dmid;
 434+ $this->dc1=$dc1;
 435+ $this->dc2=$dc2;
 436+ }
 437+
 438+ protected function read() {
 439+ $dmid=$this->dmid;
 440+ print "<".$dmid."-".$this->dc1.">";
 441+ $this->defined_meaning=CopyTools::getRow($this->dc1,"defined_meaning","where defined_meaning_id=$dmid");
 442+ return $this->defined_meaning; # for convenience
 443+ }
 444+
 445+
 446+ public function getDM() {
 447+ $dm=$this->defined_meaning;
 448+ if (is_null($dm)) {
 449+ $dm=$this->read();
 450+ }
 451+ return $this->defined_meaning;
 452+ }
 453+
 454+ public function already_there() {
 455+ return $this->already_there;
 456+ }
 457+
 458+ public function dup() {
 459+ $this->dup_stub();
 460+ $this->dup_rest();
 461+ return $this->save_meaning["defined_meaning_id"];
 462+ }
 463+
 464+ private function dup_stub (){
 465+ $dmid=$this->dmid;
 466+ $dc1=$this->dc1;
 467+ $dc2=$this->dc2;
 468+
 469+ echo "<br><h3>copying dm $dmid</h3><br>\n";
 470+ $this->read();
 471+
 472+ # bit of exp here too (defnitely need to tidy)
 473+ $defining_expression=expression($this->defined_meaning["expression_id"], $dc1);
 474+ $dm_target_table=mysql_real_escape_string("${dc2}_defined_meaning");
 475+ $copier=new ObjectCopier($this->defined_meaning["defined_meaning_id"], $dc1, $dc2);
 476+ $target_dmid=$copier->dup();
 477+ var_dump($target_dmid);
 478+ $this->save_meaning=$this->defined_meaning;
 479+ $this->save_meaning["defined_meaning_id"]=$target_dmid;
 480+
 481+ $this->already_there=$copier->already_there();
 482+ if (!($copier->already_there())) {
 483+ # exp
 484+ $target_table=mysql_real_escape_string("${dc2}_expression");
 485+ $exp_copier=new ObjectCopier($defining_expression["expression_id"], $dc1, $dc2);
 486+ $target_expid1=$exp_copier->dup();
 487+ var_dump($target_expid1);
 488+ $save_expression=$defining_expression;
 489+ $save_expression["expression_id"]=$target_expid1;
 490+ CopyTools::dc_insert_assoc($dc2, "expression", $save_expression);
 491+ # and insert that info into the dm
 492+ $this->save_meaning["expression_id"]=$target_expid1;
 493+ }
 494+ $this->save_meaning["meaning_text_tcid"]=dup_translated_content($dc1, $dc2, $this->defined_meaning["meaning_text_tcid"]);
 495+
 496+ if (!($copier->already_there())) {
 497+ CopyTools::dc_insert_assoc($dc2, "defined_meaning", $this->save_meaning);
 498+
 499+ $title_name=$defining_expression["spelling"];
 500+ $title_number=$target_dmid;
 501+ $title=str_replace(" ","_",$title_name)."_(".$title_number.")";
 502+ CopyTools::createPage($title);
 503+
 504+ $concepts=array(
 505+ $dc1 => $this->defined_meaning["defined_meaning_id"],
 506+ $dc2 => $this->save_meaning["defined_meaning_id"]);
 507+ createConceptMapping($concepts);
 508+ }
 509+
 510+ return $this->save_meaning["defined_meaning_id"];
 511+ }
 512+
 513+ function dup_rest() {
 514+ $dmid=$this->dmid;
 515+ $dc1=$this->dc1;
 516+ $dc2=$this->dc2;
 517+ dup_syntranses(
 518+ $this->defined_meaning["defined_meaning_id"],
 519+ $this->save_meaning["defined_meaning_id"],
 520+ $dc1,
 521+ $dc2
 522+ );
 523+
 524+ $relationsCopier=new RelationsCopier(
 525+ $dc1,
 526+ $dc2,
 527+ $this->defined_meaning["defined_meaning_id"],
 528+ $this->save_meaning["defined_meaning_id"]);
 529+ $relationsCopier->dup();
 530+
 531+ # can't merge collections, since they're not entirely covered by
 532+ # the objects table. So we don't copy them more than once.
 533+ if (!$this->already_there()) {
 534+ $collectionCopier=new CollectionCopier(
 535+ $dc1,
 536+ $dc2,
 537+ $this->defined_meaning["defined_meaning_id"],
 538+ $this->save_meaning["defined_meaning_id"]);
 539+ $collectionCopier->dup();
 540+ }
 541+
 542+ }
 543+}
 544+
 545+/** provide a namespace for copying tools (so we don't clutter up the main namespace with
 546+ * all our utility and tool functions) All functions here are public+static.
 547+ */
 548+class CopyTools {
 549+ /** create a relevant entry in the `page` table. */
 550+ public static function createPage($title) {
 551+ # page is not a Wikidata table, so it needs to be treated differently (yet again :-/)
 552+ $escTitle=mysql_real_escape_string($title);
 553+ $existing_page_data=CopyTools::doQuery("SELECT * FROM page WHERE page_namespace=24 AND page_title=\"$escTitle\"");
 554+ print "<br>PAGE COUNT: ".count($existing_page_data)."<br>\n";
 555+ if ($existing_page_data==false) {
 556+ $pagedata=array("page_namespace"=>24, "page_title"=>$title);
 557+ CopyTools::mysql_insert_assoc("page",$pagedata);
 558+ }
 559+ }
 560+
 561+ /** Times our execution time, nifty! */
 562+ public static function stopwatch(){
 563+ list($usec, $sec) = explode(" ", microtime());
 564+ return ((float)$usec + (float)$sec);
 565+ }
 566+
 567+ /** start a new copy transaction
 568+ * Gets a virtual user id from the wikidata_sets table, if available
 569+ * (else uses user 0)
 570+ * There's still some issues with transactions especially wrt with user assignment
 571+ * where we intersect with the (old) "WikiDataAPI".
 572+ */
 573+ public static function newCopyTransaction($dc1, $dc2) {
 574+
 575+ $datasets=CopyTools::getRow_noDC("wikidata_sets", "WHERE set_prefix=\"$dc2\"");
 576+ if ( $datasets == false ) {
 577+ throw new Exception("Dataset info for $dc2 not found.");
 578+ }
 579+
 580+ if ( array_key_exists("virtual_user_id", $datasets) ) {
 581+ $virtual_user_id=$datasets["virtual_user_id"];
 582+ } else {
 583+ $virtual_user_id=0;
 584+ }
 585+
 586+ print " VUID: $virtual_user_id";
 587+ startNewTransaction(
 588+ $virtual_user_id,
 589+ "0.0.0.0",
 590+ "copying from $dc1 to $dc2",
 591+ $dc2 );
 592+ print " UTID: ".getUpdateTransactionId();
 593+ }
 594+
 595+ /** retrieve a single row from the database as an associative array
 596+ * @param $dc the dataset prefix we need
 597+ * @param $table the name of the table (minus dataset prefix)
 598+ * @peram $where the actual WHERE clause we need to uniquely find our row
 599+ * @returns an associative array, representing our row. \
 600+ * keys=column headers, values = row contents
 601+ */
 602+ public static function getRow($dc, $table, $where) {
 603+ $target_table=mysql_real_escape_string("${dc}_${table}");
 604+ $query="SELECT * FROM $target_table ".$where;
 605+ return CopyTools::doQuery($query);
 606+ }
 607+
 608+ public static function getRow_noDC($table, $where) {
 609+ $target_table=mysql_real_escape_string("${table}");
 610+ $query="SELECT * FROM $target_table ".$where;
 611+ return CopyTools::doQuery($query);
 612+ }
 613+
 614+ /** retrieve multiple rows from the database, as an array of associative arrays.
 615+ * @param $dc the dataset prefix we need
 616+ * @param $table the name of the table (minus dataset prefix)
 617+ * @peram $where the actual WHERE clause we need to uniquely find our row
 618+ * @returns an array of associative arrays, representing our rows. \
 619+ * each associative array is structured with: \
 620+ * keys=column headers, values = row contents
 621+ */
 622+ public static function getRows($dc, $table, $where) {
 623+ $target_table=mysql_real_escape_string("${dc}_${table}");
 624+ $query="SELECT * FROM $target_table ".$where;
 625+ return CopyTools::doMultirowQuery($query);
 626+ }
 627+
 628+
 629+ /** Performs an arbitrary SQL query and returns an associative array
 630+ * Assumes that only 1 row can be returned!
 631+ * @param $query a valid SQL query
 632+ * @returns an associative array, representing our row. \
 633+ * keys=column headers, values = row contents
 634+ *
 635+ */
 636+ public static function doQuery($query) {
 637+ echo $query;
 638+ $result = mysql_query($query)or die ("error ".mysql_error());
 639+ $data= mysql_fetch_assoc($result);
 640+ return $data;
 641+ }
 642+ /** Perform an arbitrary SQL query
 643+ *
 644+ * @param $query a valid SQL query
 645+ * @returns an array of associative arrays, representing our rows. \
 646+ * each associative array is structured with: \
 647+ * keys=column headers, values = row contents
 648+ */
 649+
 650+ public static function doMultirowQuery($query) {
 651+ $result = mysql_query($query)or die ("error ".mysql_error());
 652+ $items=array();
 653+ while ($nextexp=mysql_fetch_assoc($result)) {
 654+ $items[]=$nextexp;
 655+ }
 656+ return $items;
 657+ }
 658+
 659+ /** identical to the php function array_key_exists(), but eats dirtier input
 660+ * returns false (rather than an error) on somewhat invalid input
 661+ */
 662+ public static function sane_key_exists($key, $array) {
 663+ if (is_null($key) or $key==false){
 664+ return false;
 665+ }
 666+ if (is_null($array) or $array==false) {
 667+ return false;
 668+ }
 669+ var_dump($array);
 670+ return array_key_exists($key, $array);
 671+ }
 672+
 673+ /**
 674+ * inverse of mysql_fetch_assoc
 675+ * takes an associative array as parameter, and inserts data
 676+ * into table as a single row (keys=column names, values = data to be inserted)
 677+ /* see: http://www.php.net/mysql_fetch_assoc (Comment by R. Bradly, 14-Sep-2006)
 678+ */
 679+ public static function mysql_insert_assoc ($my_table, $my_array) {
 680+
 681+ // Find all the keys (column names) from the array $my_array
 682+
 683+ // We compose the query
 684+ $sql = "insert into `$my_table` set";
 685+ // implode the column names, inserting "\", \"" between each (but not after the last one)
 686+ // we add the enclosing quotes at the same time
 687+ $sql_comma=$sql;
 688+ foreach($my_array as $key=>$value) {
 689+ $sql=$sql_comma;
 690+ if (is_null($value)) {
 691+ $value="DEFAULT";
 692+ } else {
 693+ $value="\"$value\"";
 694+ }
 695+ $sql.=" `$key`=$value";
 696+ $sql_comma=$sql.",";
 697+ }
 698+ // Same with the values
 699+ echo $sql."; <br>\n";
 700+ $result = mysql_query($sql);
 701+
 702+ if ($result)
 703+ {
 704+ echo "The row was added sucessfully";
 705+ return true;
 706+ }
 707+ else
 708+ {
 709+ echo ("The row was not added<br>The error was" . mysql_error());
 710+ return false;
 711+ }
 712+ }
 713+
 714+ /**convenience wrapper around mysql_insert_assoc
 715+ * like mysql_insert_assoc, but allows you to specify dc prefix+table name separately
 716+ * Also transparently handles the internal transaction (WHICH MUST ALREADY BE OPEN!)
 717+ */
 718+ public static function dc_insert_assoc($dc, $table_name, $array) {
 719+ $target_table=mysql_real_escape_string("${dc}_${table_name}");
 720+ if (CopyTools::sane_key_exists("add_transaction_id", $array)) {
 721+ $array["add_transaction_id"]=getUpdateTransactionId();
 722+ }
 723+ return CopyTools::mysql_insert_assoc($target_table, $array);
 724+ }
 725+
 726+
 727+}
 728+?>
Index: trunk/extensions/Wikidata/OmegaWiki/SpecialCopy.php
@@ -0,0 +1,239 @@
 2+<?php
 3+if (!defined('MEDIAWIKI')) die();
 4+/**
 5+ * A Special Page extension to copy defined meanings between datasets.
 6+ *
 7+ * Copied over from SpecialConceptMapping.
 8+ * User Interface temporarily retained (but currently flawed)
 9+ * Web API will be implemented
 10+ * Minimal documentation is available by calling with &action=help, as a parameter
 11+ * @addtogroup Extensions
 12+ *
 13+ * @author Erik Moeller <Eloquence@gmail.com> (Possibly some remaining code)
 14+ * @author Kim Bruning <kim@bruning.xs4all.nl>
 15+ # @author Alan Smithee <Alan.Smithee@brown.paper.bag> (if code quality improves, may yet claim)
 16+ * @license GPLv2 or later.
 17+ */
 18+
 19+
 20+$wgExtensionFunctions[] = 'wfSpecialCopy';
 21+$wgExtensionCredits['specialpage'][] = array(
 22+ 'name' => 'SpecialCopy',
 23+ 'author' => 'Alan Smithee',
 24+);
 25+
 26+function wfSpecialCopy() {
 27+ # Add messages
 28+ #require_once "$IP/includes/SpecialPage.php";
 29+
 30+ global $wgMessageCache;
 31+ $wgMessageCache->addMessages(array('Copy'=>'Wikidata: Copy'),'en');
 32+
 33+ require_once("Wikidata.php");
 34+ require_once("WikiDataAPI.php");
 35+ require_once("Utilities.php");
 36+ require_once("DefinedMeaningModel.php");
 37+ require_once("Copy.php");
 38+ class SpecialCopy extends SpecialPage {
 39+
 40+ function SpecialCopy() {
 41+ SpecialPage::SpecialPage( 'Copy' );
 42+ }
 43+
 44+ function execute( $par ) {
 45+ global $wgOut, $wgRequest, $wgTitle, $wgUser, $wdTermDBDataSet;
 46+ $wgOut->setPageTitle("Special:Copy");
 47+
 48+ if(!$wgUser->isAllowed('wikidata-copy')) {
 49+ $wgOut->addHTML("Permission denied.");
 50+ return false;
 51+ }
 52+
 53+ $action=$wgRequest->getText('action');
 54+ if(!$action) {
 55+ $this->ui();
 56+ } elseif ($action=="copy") {
 57+ $this->copy();
 58+ } elseif ($action=="list") {
 59+ $this->list_sets();
 60+ } elseif ($action=="help"){
 61+ $this->help();
 62+ } else {
 63+ $wgOut->addWikiText(wfMsgSc("copy_no_action_specified",$action));
 64+ $wgOut->addWikiText(wfMsgSc("copy_help"));
 65+ }
 66+ }
 67+
 68+ protected function ui() {
 69+
 70+ global $wgOut, $wgRequest, $wgUser;
 71+ $lang=$wgUser->getOption("language");
 72+ require_once("forms.php");
 73+ $wgOut->addHTML(wfMsgSc("conceptmapping_uitext"));
 74+ $sets=wdGetDataSets();
 75+ $options = array();
 76+ $html="";
 77+ $mappings=array();
 78+ $rq=array();
 79+
 80+ foreach ($sets as $key=>$setObject) {
 81+ $set=$setObject->getPrefix();
 82+ $rq[$set]=$wgRequest->getText("set_".$set);
 83+ $rq[$set]=trim($rq[$set]);
 84+ $rq[$set]=(int)$rq[$set];
 85+ if($rq[$set]) {
 86+ $dmModel=new DefinedMeaningModel($rq[$set],null,$setObject);
 87+ $defaultSel=$dmModel->getSyntransByLanguageCode($lang);
 88+ $options[$setObject->fetchName()]=getSuggest("set_$set", 'defined-meaning',array(), $rq[$set], $defaultSel, array(0), $setObject);
 89+ } else {
 90+ $options[$setObject->fetchName()]=getSuggest("set_$set", 'defined-meaning', array(), null, null, array(0), $setObject);
 91+ }
 92+
 93+ }
 94+ $wgOut->addHTML(getOptionPanel($options));
 95+ $noerror=$wgRequest->getText("suppressWarnings");
 96+
 97+ foreach ($sets as $key=>$setObject) {
 98+ $set=$setObject->getPrefix();
 99+ if(!$rq[$set]) {
 100+ $wgOut->addHTML(' <span style="color:yellow">['.wfMsgSc("dm_not_present").']</span>');
 101+ } else {
 102+ $dmModel=new DefinedMeaningModel($rq[$set],null,$setObject);
 103+ $dmModel->checkExistence();
 104+ if ($dmModel->exists()) {
 105+ $id=$dmModel->getId();
 106+ $title=$dmModel->getTitleText();
 107+ } else {
 108+ $id=null;
 109+ $title=null;
 110+ }
 111+ if(!$noerror) {
 112+ $wgOut->addHTML("$key: ".$rq[$set]." ($title)");
 113+ }
 114+ if ($id!=null) {
 115+ $mappings[$key]=$id;
 116+ if(!$noerror) {
 117+ $wgOut->addHTML(' <span style="color:green">['.wfMsgSc("dm_OK").']</span>');
 118+ }
 119+ } else {
 120+ if(!$noerror) {
 121+ $wgOut->addHTML(' <span style="color:red">['.wfMsgSc("dm_not_found").']</span>');
 122+ }
 123+ }
 124+ }
 125+ $wgOut->addHTML("<br>\n");
 126+ }
 127+ if (sizeOf($mappings)>1) {
 128+ createConceptMapping($mappings);
 129+ $wgOut->addHTML(wfMsgSc("mapping_successful"));
 130+ } else {
 131+ $wgOut->addHTML(wfMsgSc("mapping_unsuccessful"));
 132+ }
 133+
 134+ }
 135+
 136+ protected function help() {
 137+ global $wgOut;
 138+ $wgOut->addWikiText("<h2>Help</h2>");
 139+ $wgOut->addWikiText(wfMsgSc("copy_help"));
 140+ }
 141+
 142+ protected function insert() {
 143+ global
 144+ $wgRequest, $wgOut;
 145+
 146+ # $wgRequest->getText( 'page' );
 147+ $sets=wdGetDataSets();
 148+ #$requests=$wgRequest->getValues();
 149+ $wgOut->addWikiText("<h2>".wfMsgSc("will_insert")."</h2>");
 150+ $map=array();
 151+ foreach ($sets as $key => $set) {
 152+ $dc=$set->getPrefix();
 153+ $dm_id=$wgRequest->getText($dc);
 154+ $name=$set->fetchName();
 155+
 156+ $dm_id_ui=$dm_id; # Only for teh purdy
 157+ if ($dm_id_ui==null)
 158+ $dm_id_ui="unset";
 159+ $wgOut->addWikiText("$name ->$dm_id_ui");
 160+ $map[$dc]=$dm_id;
 161+ #$dbr=&wfGetDB(DB_MASTER);
 162+ }
 163+ createConceptMapping($map);
 164+ }
 165+
 166+ # TODO, this should actually copy :-P
 167+ protected function copy() {
 168+ global
 169+ $wgRequest, $wgOut;
 170+
 171+ $dmid=$wgRequest("dmid");
 172+ $dc1=$wgRequest("dc1");
 173+ $dc2=$wgRequest("dc2");
 174+ $abort=false;
 175+
 176+ if (is_null($dmid)) {
 177+ $wgOut->addWikiText(wfMsgSc("please_provide_dmid"));
 178+ $abort=true;
 179+ }
 180+ if (is_null($dc1)) {
 181+ $wgOut->addWikiText(wfMsgSc("please_provide_dc1"));
 182+ $abort=true;
 183+ }
 184+ if (is_null($dc2)) {
 185+ $wgOut->addWikiText(wfMsgSc("please_provide_dc2"));
 186+ $abort=true;
 187+ }
 188+
 189+ if ($abort)
 190+ return;
 191+
 192+ # $wgRequest->getText( 'page' );
 193+ $sets=wdGetDataSets();
 194+ #$requests=$wgRequest->getValues();
 195+ $wgOut->addWikiText("<h2>".wfMsgSc("will_insert")."</h2>");
 196+ $map=array();
 197+ foreach ($sets as $key => $set) {
 198+ $dc=$set->getPrefix();
 199+ $dm_id=$wgRequest->getText($dc);
 200+ $name=$set->fetchName();
 201+
 202+ $dm_id_ui=$dm_id; # Only for teh purdy
 203+ if ($dm_id_ui==null)
 204+ $dm_id_ui="unset";
 205+ $wgOut->addWikiText("$name ->$dm_id_ui");
 206+ $map[$dc]=$dm_id;
 207+ #$dbr=&wfGetDB(DB_MASTER);
 208+ }
 209+ createConceptMapping($map);
 210+ }
 211+
 212+
 213+ protected function get() {
 214+ global
 215+ $wgOut, $wgRequest;
 216+ $concept_id=$wgRequest->getText("concept");
 217+ $wgOut->addWikiText("<h2>".wfMsgSc("contents_of_mapping")."</h2>");
 218+ $map=readConceptMapping($concept_id);
 219+ #$sets=wdGetDataSets();
 220+
 221+ foreach ($map as $dc => $dm_id) {
 222+ $wgOut->addWikiText("$dc -> $dm_id");
 223+ }
 224+ }
 225+
 226+ protected function list_sets() {
 227+ global $wgOut;
 228+ $wgOut->addWikiText("<h2>".wfMsgSc("available contexts")."</h2>");
 229+ $sets=wdGetDataSets();
 230+ foreach ($sets as $key => $set) {
 231+ $name=$set->fetchName();
 232+ $wgOut->addWikiText("$key => $name");
 233+ }
 234+ }
 235+ }
 236+
 237+ SpecialPage::addPage( new SpecialCopy );
 238+
 239+}
 240+

Status & tagging log