r23319 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r23318‎ | r23319 | r23320 >
Date:13:43, 24 June 2007
Author:mkroetzsch
Status:old
Tags:
Comment:
Cleaned up code/split into shorter functions. Support for choosing mainlabel via |-syntax on query conditions.
Modified paths:
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_QueryProcessor.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SemanticMediaWiki/includes/SMW_QueryProcessor.php
@@ -241,7 +241,7 @@
242242 $this->m_curstring = $querystring;
243243 $this->m_sepstack = array();
244244 $setNS = true;
245 - return $this->getSubqueryDescription($setNS);
 245+ return $this->getSubqueryDescription($setNS, $this->m_label);
246246 }
247247
248248 /**
@@ -267,8 +267,8 @@
268268 *
269269 * The call-by-ref parameter $setNS is a boolean. Its input specifies whether
270270 * the query should set the current default namespace if no namespace restricitons
271 - * were given. If false, the super-query is happy to set the required NS-restrictions
272 - * by itself if needed. Otherwise the subquery itslef has to impose the defaults.
 271+ * were given. If false, the calling super-query is happy to set the required
 272+ * NS-restrictions by itself if needed. Otherwise the subquery has to impose the defaults.
273273 * This is so, since outermost queries and subqueries of disjunctions will have to set
274274 * their own default restrictions.
275275 *
@@ -280,8 +280,10 @@
281281 * Note that $setNS is no means to switch on or off default namespaces in general,
282282 * but just controls query generation. For general effect, the default namespaces
283283 * should be set to NULL.
 284+ *
 285+ * The call-by-ref parameter $label is used to append any label strings found.
284286 */
285 - protected function getSubqueryDescription(&$setNS) {
 287+ protected function getSubqueryDescription(&$setNS, &$label) {
286288 $conjunction = NULL; // used for the current inner conjunction
287289 $disjuncts = array(); // (disjunctive) array of subquery conjunctions
288290 $printrequests = array(); // the printrequests found for this query level
@@ -293,7 +295,7 @@
294296 $setsubNS = false;
295297 switch ($chunk) {
296298 case '[[': // start new link block
297 - $ld = $this->getLinkDescription($setsubNS);
 299+ $ld = $this->getLinkDescription($setsubNS, $label);
298300 if ($ld === NULL) {
299301 return NULL;
300302 } elseif ($ld instanceof SMWPrintRequest) {
@@ -304,7 +306,8 @@
305307 break;
306308 case '<q>': // enter new subquery, currently irrelevant but possible
307309 $this->pushDelimiter('</q>');
308 - $conjunction = $this->addDescription($conjunction, $this->getSubqueryDescription($setsubNS));
 310+ $conjunction = $this->addDescription($conjunction, $this->getSubqueryDescription($setsubNS, $label));
 311+ /// TODO: print requests from subqueries currently are ignored, should be moved down
309312 break;
310313 case '||': case '': case '</q>': // finish disjunction and maybe subquery
311314 if ($this->m_defaultns !== NULL) { // possibly add namespace restrictions
@@ -379,233 +382,285 @@
380383 * specifies a print request, return the print request object.
381384 * Returns NULL upon error.
382385 *
383 - * The call-by-ref parameter $setNS is a boolean used to state whether
384 - * the namespace defaults must be added, and returns whether any have been
385 - * added. Similar usage as in getSubqueryDescription().
 386+ * Parameters $setNS and $label have the same use as in getSubqueryDescription().
386387 */
387 - protected function getLinkDescription(&$setNS) {
388 - $result = NULL;
 388+ protected function getLinkDescription(&$setNS, &$label) {
389389 // This method is called when we encountered an opening '[['. The following
390390 // block could be a Category-statement, fixed object, relation or attribute
391391 // statements, or according print statements.
392392 $chunk = $this->readChunk();
393 - $hasNamespaces = false;
394 -
395393 if ($chunk == $this->m_categoryprefix) { // category statement
396 - // note: no subqueries allowed here, inline disjunction allowed, wildcards allowed
397 - $continue = true;
398 - while ($continue) {
399 - $chunk = $this->readChunk();
400 - switch ($chunk) {
401 - case '*': //print statement
402 - $chunk = $this->readChunk('\]\]|\|');
403 - if ($chunk == '|') {
404 - $label = $this->readChunk('\]\]');
405 - if ($label != ']]') {
406 - $chunk = $this->readChunk('\]\]');
407 - } else {
408 - $label = '';
409 - $chunk = ']]';
410 - }
411 - } else {
412 - global $wgContLang;
413 - $label = $wgContLang->getNSText(NS_CATEGORY);
414 - }
415 - if ($chunk == ']]') {
416 - return new SMWPrintRequest(SMW_PRINT_CATS, $label);
417 - } else {
418 - $this->m_error = 'Misshaped print statement.'; //TODO: internationalise
419 - return NULL;
420 - }
421 - break;
422 - case '+': //wildcard, ignore for categories (semantically meaningless)
423 - break;
424 - default: //assume category title
425 - $cat = Title::newFromText($chunk, NS_CATEGORY);
426 - if ($cat !== NULL) {
427 - $result = $this->addDescription($result, new SMWClassDescription($cat), false);
428 - }
429 - }
430 - $chunk = $this->readChunk();
431 - if ($chunk == '||') {
432 - $continue = true;
433 - } else {
434 - $continue = false;
435 - }
436 - }
 394+ return $this->getCategoryDescription($setNS, $label);
437395 } else { // fixed subject, namespace restriction, property query, or subquery
438396 $sep = $this->readChunk('',false); //do not consume hit, "look ahead"
439397 if ($sep == '::') { // relation statement
440 - $this->readChunk(); // consume $sep
441 - $rel = Title::newFromText($chunk, SMW_NS_RELATION);
442 - $continue = true;
443 - $innerdesc = NULL;
444 - while ($continue) {
445 - $chunk = $this->readChunk();
446 - switch ($chunk) {
447 - case '*': // print statement, abort processing
448 - $chunk = $this->readChunk('\]\]|\|');
449 - if ($chunk == '|') {
450 - $label = $this->readChunk('\]\]');
451 - if ($label != ']]') {
452 - $chunk = $this->readChunk('\]\]');
453 - } else {
454 - $label = '';
455 - $chunk = ']]';
456 - }
457 - } else {
458 - $label = $rel->getText();
459 - }
460 - if ($chunk == ']]') {
461 - return new SMWPrintRequest(SMW_PRINT_RELS, $label, $rel);
462 - } else {
463 - $this->m_error = 'Misshaped print statement.'; //TODO: internationalise
464 - return NULL;
465 - }
466 - break;
467 - case '+': // wildcard
468 - /// TODO enforce default namespace!
469 - $innerdesc = $this->addDescription($innerdesc, new SMWThingDescription(), false);
470 - break;
471 - case '<q>': // subquery, set default namespaces
472 - $this->pushDelimiter('</q>');
473 - $setsubNS = true;
474 - $innerdesc = $this->addDescription($innerdesc, $this->getSubqueryDescription($setsubNS), false);
475 - break;
476 - default: //normal object value, brings its own namespace
477 - $obj = Title::newFromText($chunk);
478 - if ($obj !== NULL) {
479 - $innerdesc = $this->addDescription($innerdesc, new SMWNominalDescription($obj), false);
480 - }
481 - }
482 - $chunk = $this->readChunk();
483 - $continue = ($chunk == '||');
484 - }
485 - if ($innerdesc !== NULL) {
486 - $result = new SMWSomeRelation($rel,$innerdesc);
487 - }
 398+ return $this->getRelationDescription($chunk, $setNS, $label);
488399 } elseif ($sep == ':=') { // attribute statement
489 - $this->readChunk(); // consume $sep
490 - $att = Title::newFromText($chunk, SMW_NS_ATTRIBUTE);
491 - ///TODO: currently no support for disjunctions in data values (needs extension of query processor)
 400+ return $this->getAttributeDescription($chunk, $setNS, $label);
 401+ } else { // Fixed article/namespace restriction. $sep should be ]] or ||
 402+ return $this->getArticleDescription($chunk, $setNS, $label);
 403+ }
 404+ }
 405+ }
492406
493 - // get values, including values with internal [[...]]
494 - $open = 1;
495 - $value = '';
496 - while ( ($open > 0) && ($chunk != '') ) {
497 - $chunk = $this->readChunk('\[\[|\]\]|\|');
498 - switch ($chunk) {
499 - case '[[': // open new [[ ]]
500 - $open++;
501 - break;
502 - case ']]': // close [[ ]]
503 - $open--;
504 - break;
505 - case '|': // terminates only outermost [[ ]]
506 - if ($open == 1) {
507 - $open = 0;
508 - }
509 - break;
510 - }
511 - if ($open != 0) {
512 - $value .= $chunk;
513 - }
514 - }
515 - // note that at this point, we already read one more chunk behind the value
516 - $list = preg_split('/^\*/',$value,2);
517 - if (count($list) == 2) { //hit
518 - $value = '*';
519 - $printmodifier = $list[1];
520 - } else {
521 - $printmodifier = '';
522 - }
523 - switch ($value) {
524 - case '*': // print statement
525 - if ($chunk == '|') {
526 - $label = $this->readChunk('\]\]');
527 - if ($label != ']]') {
528 - $chunk = $this->readChunk('\]\]');
529 - } else {
530 - $label = '';
531 - $chunk = ']]';
532 - }
 407+ /**
 408+ * Parse a category description (the part of an inline query that
 409+ * is in between "[[Category:" and the closing "]]" and create a
 410+ * suitable description.
 411+ */
 412+ protected function getCategoryDescription(&$setNS, &$label) {
 413+ // note: no subqueries allowed here, inline disjunction allowed, wildcards allowed
 414+ $result = NULL;
 415+ $continue = true;
 416+ while ($continue) {
 417+ $chunk = $this->readChunk();
 418+ switch ($chunk) {
 419+ case '*': //print statement
 420+ $chunk = $this->readChunk('\]\]|\|');
 421+ if ($chunk == '|') {
 422+ $label = $this->readChunk('\]\]');
 423+ if ($label != ']]') {
 424+ $chunk = $this->readChunk('\]\]');
533425 } else {
534 - $label = $att->getText();
 426+ $label = '';
 427+ $chunk = ']]';
535428 }
536 - if ($chunk == ']]') {
537 - return new SMWPrintRequest(SMW_PRINT_ATTS, $label, $att, $printmodifier);
538 - } else {
539 - $this->m_error = 'Misshaped print statement.'; //TODO: internationalise
540 - return NULL;
541 - }
542 - break;
543 - case '+': // wildcard
544 - $vd = new SMWValueDescription(NULL, SMW_CMP_ANY);
545 - break;
546 - default: // fixed value, possibly with comparator addons
547 - // for now, treat comparators only if placed before whole value:
548 - $list = preg_split('/^(<|>)/',$value, 2, PREG_SPLIT_DELIM_CAPTURE);
549 - $comparator = SMW_CMP_EQ;
550 - if (count($list) == 3) { // initial comparator found ($list[1] should be empty)
551 - switch ($list[1]) {
552 - case '<':
553 - $comparator = SMW_CMP_LEQ;
554 - $value = $list[2];
555 - break;
556 - case '>':
557 - $comparator = SMW_CMP_GEQ;
558 - $value = $list[2];
559 - break;
560 - //default: not possible
561 - }
562 - }
563 - // TODO: needs extension for n-ary values
564 - $dv = SMWDataValueFactory::newAttributeValue($att->getText(), $value);
565 - if (!$dv->isValid()) {
566 - $this->m_error = $dv->getError();
567 - $vd = new SMWValueDescription(NULL, SMW_CMP_ANY);
568 - } else {
569 - $vd = new SMWValueDescription($dv, $comparator);
570 - }
571 - }
572 - $result = new SMWSomeAttribute($att, $vd);
573 - } else { // Fixed article/namespace restriction. $sep should be ]] or ||
574 - $continue = true;
575 - //$innerdesc = NULL;
576 - while ($continue) {
577 - $hasNamespaces = true; // enforced for all cases
578 - if ($chunk == '<q>') { // no subqueries of the form [[<q>...</q>]] (not needed)
579 - $this->m_error = 'Subqueries not allowed here.'; //TODO
 429+ } else {
 430+ global $wgContLang;
 431+ $label = $wgContLang->getNSText(NS_CATEGORY);
 432+ }
 433+ if ($chunk == ']]') {
 434+ return new SMWPrintRequest(SMW_PRINT_CATS, $label);
 435+ } else {
 436+ $this->m_error = 'Misshaped print statement.'; //TODO: internationalise
580437 return NULL;
581438 }
582 - $list = preg_split('/:/', $chunk, 3); // ":Category:Foo" "User:bar" ":baz" ":+"
583 - if ( ($list[0] == '') && (count($list)==3) ) {
584 - $list = array_slice($list, 1);
 439+ break;
 440+ case '+': //wildcard, ignore for categories (semantically meaningless)
 441+ break;
 442+ default: //assume category title
 443+ $cat = Title::newFromText($chunk, NS_CATEGORY);
 444+ if ($cat !== NULL) {
 445+ $result = $this->addDescription($result, new SMWClassDescription($cat), false);
585446 }
586 - if ( (count($list) == 2) && ($list[1] == '+') ) { // try namespace restriction
587 - global $wgContLang;
588 - $idx = $wgContLang->getNsIndex($list[0]);
589 - if ($idx !== false) {
590 - $result = $this->addDescription($result, new SMWNamespaceDescription($idx), false);
 447+ }
 448+ $chunk = $this->readChunk();
 449+ $continue = ($chunk == '||');
 450+ }
 451+
 452+ return $this->finishLinkDescription($chunk, false, $result, $setNS, $label);
 453+ }
 454+
 455+ /**
 456+ * Parse a relation description (the part of an inline query that
 457+ * is in between "[[Some Relation::" and the closing "]]" and create a
 458+ * suitable description. The "::" is the first chunk on the current
 459+ * string.
 460+ */
 461+ protected function getRelationDescription($relname, &$setNS, &$label) {
 462+ $innerdesc = NULL;
 463+ $rel = Title::newFromText($relname, SMW_NS_RELATION);
 464+
 465+ $this->readChunk(); // consume seperator "::"
 466+ $continue = true;
 467+ while ($continue) {
 468+ $chunk = $this->readChunk();
 469+ switch ($chunk) {
 470+ case '*': // print statement, abort processing
 471+ $chunk = $this->readChunk('\]\]|\|');
 472+ if ($chunk == '|') {
 473+ $label = $this->readChunk('\]\]');
 474+ if ($label != ']]') {
 475+ $chunk = $this->readChunk('\]\]');
 476+ } else {
 477+ $label = '';
 478+ $chunk = ']]';
591479 }
592480 } else {
593 - $title = Title::newFromText($chunk);
594 - if ($title !== NULL) {
595 - $result = $this->addDescription($result, new SMWNominalDescription($title), false);
596 - }
 481+ $label = $rel->getText();
597482 }
 483+ if ($chunk == ']]') {
 484+ return new SMWPrintRequest(SMW_PRINT_RELS, $label, $rel);
 485+ } else {
 486+ $this->m_error = 'Misshaped print statement.'; //TODO: internationalise
 487+ return NULL;
 488+ }
 489+ break;
 490+ case '+': // wildcard
 491+ if ($this->m_defaultns !== NULL) {
 492+ $innerdesc = $this->addDescription($innerdesc, $this->m_defaultns, false);
 493+ } else {
 494+ $innerdesc = $this->addDescription($innerdesc, new SMWThingDescription(), false);
 495+ }
 496+ break;
 497+ case '<q>': // subquery, set default namespaces
 498+ $this->pushDelimiter('</q>');
 499+ $setsubNS = true;
 500+ $sublabel = '';
 501+ $innerdesc = $this->addDescription($innerdesc, $this->getSubqueryDescription($setsubNS, $sublabel), false);
 502+ break;
 503+ default: //normal object value, brings its own namespace
 504+ $obj = Title::newFromText($chunk);
 505+ if ($obj !== NULL) {
 506+ $innerdesc = $this->addDescription($innerdesc, new SMWNominalDescription($obj), false);
 507+ }
 508+ }
 509+ $chunk = $this->readChunk();
 510+ $continue = ($chunk == '||');
 511+ }
598512
599 - $chunk = $this->readChunk();
600 - if ($chunk == '||') {
601 - $chunk = $this->readChunk();
602 - $continue = true;
 513+ if ($innerdesc !== NULL) {
 514+ $result = new SMWSomeRelation($rel,$innerdesc);
 515+ } else {
 516+ $result = NULL;
 517+ }
 518+
 519+ return $this->finishLinkDescription($chunk, false, $result, $setNS, $label);
 520+ }
 521+
 522+ /**
 523+ * Parse an attribute description (the part of an inline query that
 524+ * is in between "[[Some Attribute:=" and the closing "]]" and create a
 525+ * suitable description. The ":=" is the first chunk on the current
 526+ * string.
 527+ */
 528+ protected function getAttributeDescription($attname, &$setNS, &$label) {
 529+ $this->readChunk(); // consume seperator ":="
 530+ $att = Title::newFromText($attname, SMW_NS_ATTRIBUTE);
 531+ ///TODO: currently no support for disjunctions in data values (needs extension of query processor)
 532+
 533+ // get values, including values with internal [[...]]
 534+ $open = 1;
 535+ $value = '';
 536+ $chunk = 'NONEMPTY';
 537+ while ( ($open > 0) && ($chunk != '') ) {
 538+ $chunk = $this->readChunk('\[\[|\]\]|\|');
 539+ switch ($chunk) {
 540+ case '[[': // open new [[ ]]
 541+ $open++;
 542+ break;
 543+ case ']]': // close [[ ]]
 544+ $open--;
 545+ break;
 546+ case '|': // terminates only outermost [[ ]]
 547+ if ($open == 1) {
 548+ $open = 0;
 549+ }
 550+ break;
 551+ }
 552+ if ($open != 0) {
 553+ $value .= $chunk;
 554+ }
 555+ }
 556+ // note that at this point, we already read one more chunk behind the value
 557+ $list = preg_split('/^\*/',$value,2);
 558+ if (count($list) == 2) { //hit
 559+ $value = '*';
 560+ $printmodifier = $list[1];
 561+ } else {
 562+ $printmodifier = '';
 563+ }
 564+ switch ($value) {
 565+ case '*': // print statement
 566+ if ($chunk == '|') {
 567+ $label = $this->readChunk('\]\]');
 568+ if ($label != ']]') {
 569+ $chunk = $this->readChunk('\]\]');
603570 } else {
604 - $continue = false;
 571+ $label = '';
 572+ $chunk = ']]';
605573 }
 574+ } else {
 575+ $label = $att->getText();
606576 }
 577+ if ($chunk == ']]') {
 578+ return new SMWPrintRequest(SMW_PRINT_ATTS, $label, $att, $printmodifier);
 579+ } else {
 580+ $this->m_error = 'Misshaped print statement.'; //TODO: internationalise
 581+ return NULL;
 582+ }
 583+ break;
 584+ case '+': // wildcard
 585+ $vd = new SMWValueDescription(NULL, SMW_CMP_ANY);
 586+ break;
 587+ default: // fixed value, possibly with comparator addons
 588+ // for now, treat comparators only if placed before whole value:
 589+ $list = preg_split('/^(<|>)/',$value, 2, PREG_SPLIT_DELIM_CAPTURE);
 590+ $comparator = SMW_CMP_EQ;
 591+ if (count($list) == 3) { // initial comparator found ($list[1] should be empty)
 592+ switch ($list[1]) {
 593+ case '<':
 594+ $comparator = SMW_CMP_LEQ;
 595+ $value = $list[2];
 596+ break;
 597+ case '>':
 598+ $comparator = SMW_CMP_GEQ;
 599+ $value = $list[2];
 600+ break;
 601+ //default: not possible
 602+ }
 603+ }
 604+ // TODO: needs extension for n-ary values
 605+ $dv = SMWDataValueFactory::newAttributeValue($att->getText(), $value);
 606+ if (!$dv->isValid()) {
 607+ $this->m_error = $dv->getError();
 608+ $vd = new SMWValueDescription(NULL, SMW_CMP_ANY);
 609+ } else {
 610+ $vd = new SMWValueDescription($dv, $comparator);
 611+ }
 612+ }
 613+
 614+ return $this->finishLinkDescription($chunk, false, new SMWSomeAttribute($att, $vd), $setNS, $label);
 615+ }
 616+
 617+ /**
 618+ * Parse an article description (the part of an inline query that
 619+ * is in between "[[" and the closing "]]" if it is not specifying
 620+ * a category, relation, or attribute) and create a suitable
 621+ * description.
 622+ * The first chunk behind the "[[" has already been read and is
 623+ * passed as a parameter.
 624+ */
 625+ protected function getArticleDescription($firstchunk, &$setNS, &$label) {
 626+ $chunk = $firstchunk;
 627+ $result = NULL;
 628+ $continue = true;
 629+ //$innerdesc = NULL;
 630+ while ($continue) {
 631+ if ($chunk == '<q>') { // no subqueries of the form [[<q>...</q>]] (not needed)
 632+ $this->m_error = 'Subqueries not allowed here.'; //TODO
 633+ return NULL;
607634 }
 635+ $list = preg_split('/:/', $chunk, 3); // ":Category:Foo" "User:bar" ":baz" ":+"
 636+ if ( ($list[0] == '') && (count($list)==3) ) {
 637+ $list = array_slice($list, 1);
 638+ }
 639+ if ( (count($list) == 2) && ($list[1] == '+') ) { // try namespace restriction
 640+ global $wgContLang;
 641+ $idx = $wgContLang->getNsIndex($list[0]);
 642+ if ($idx !== false) {
 643+ $result = $this->addDescription($result, new SMWNamespaceDescription($idx), false);
 644+ }
 645+ } else {
 646+ $title = Title::newFromText($chunk);
 647+ if ($title !== NULL) {
 648+ $result = $this->addDescription($result, new SMWNominalDescription($title), false);
 649+ }
 650+ }
 651+
 652+ $chunk = $this->readChunk();
 653+ if ($chunk == '||') {
 654+ $chunk = $this->readChunk();
 655+ $continue = true;
 656+ } else {
 657+ $continue = false;
 658+ }
608659 }
609660
 661+ return $this->finishLinkDescription($chunk, true, $result, $setNS, $label);
 662+ }
 663+
 664+ protected function finishLinkDescription($chunk, $hasNamespaces, $result, &$setNS, &$label) {
610665 if ($result === NULL) { // no useful information or concrete error found
611666 $this->m_error = 'Syntax error in part of query.'; //TODO internationalise
612667 return NULL;
@@ -619,11 +674,12 @@
620675
621676 // terminate link (assuming that next chunk was read already)
622677 if ($chunk == '|') { // label, TODO
623 - $label = $this->readChunk('\]\]');
624 - if ($label != ']]') {
 678+ $chunk = $this->readChunk('\]\]');
 679+ if ($chunk != ']]') {
 680+ $label .= $chunk;
625681 $chunk = $this->readChunk('\]\]');
626682 } else {
627 - $label = '';
 683+ // empty label does not add to overall label
628684 $chunk = ']]';
629685 }
630686 }
@@ -640,8 +696,6 @@
641697 }
642698 return NULL;
643699 }
644 -
645 - return $result;
646700 }
647701
648702 /**

Status & tagging log