Index: trunk/extensions/SemanticMediaWiki/includes/SMW_QueryProcessor.php |
— | — | @@ -241,7 +241,7 @@ |
242 | 242 | $this->m_curstring = $querystring; |
243 | 243 | $this->m_sepstack = array(); |
244 | 244 | $setNS = true; |
245 | | - return $this->getSubqueryDescription($setNS); |
| 245 | + return $this->getSubqueryDescription($setNS, $this->m_label); |
246 | 246 | } |
247 | 247 | |
248 | 248 | /** |
— | — | @@ -267,8 +267,8 @@ |
268 | 268 | * |
269 | 269 | * The call-by-ref parameter $setNS is a boolean. Its input specifies whether |
270 | 270 | * 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. |
273 | 273 | * This is so, since outermost queries and subqueries of disjunctions will have to set |
274 | 274 | * their own default restrictions. |
275 | 275 | * |
— | — | @@ -280,8 +280,10 @@ |
281 | 281 | * Note that $setNS is no means to switch on or off default namespaces in general, |
282 | 282 | * but just controls query generation. For general effect, the default namespaces |
283 | 283 | * should be set to NULL. |
| 284 | + * |
| 285 | + * The call-by-ref parameter $label is used to append any label strings found. |
284 | 286 | */ |
285 | | - protected function getSubqueryDescription(&$setNS) { |
| 287 | + protected function getSubqueryDescription(&$setNS, &$label) { |
286 | 288 | $conjunction = NULL; // used for the current inner conjunction |
287 | 289 | $disjuncts = array(); // (disjunctive) array of subquery conjunctions |
288 | 290 | $printrequests = array(); // the printrequests found for this query level |
— | — | @@ -293,7 +295,7 @@ |
294 | 296 | $setsubNS = false; |
295 | 297 | switch ($chunk) { |
296 | 298 | case '[[': // start new link block |
297 | | - $ld = $this->getLinkDescription($setsubNS); |
| 299 | + $ld = $this->getLinkDescription($setsubNS, $label); |
298 | 300 | if ($ld === NULL) { |
299 | 301 | return NULL; |
300 | 302 | } elseif ($ld instanceof SMWPrintRequest) { |
— | — | @@ -304,7 +306,8 @@ |
305 | 307 | break; |
306 | 308 | case '<q>': // enter new subquery, currently irrelevant but possible |
307 | 309 | $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 |
309 | 312 | break; |
310 | 313 | case '||': case '': case '</q>': // finish disjunction and maybe subquery |
311 | 314 | if ($this->m_defaultns !== NULL) { // possibly add namespace restrictions |
— | — | @@ -379,233 +382,285 @@ |
380 | 383 | * specifies a print request, return the print request object. |
381 | 384 | * Returns NULL upon error. |
382 | 385 | * |
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(). |
386 | 387 | */ |
387 | | - protected function getLinkDescription(&$setNS) { |
388 | | - $result = NULL; |
| 388 | + protected function getLinkDescription(&$setNS, &$label) { |
389 | 389 | // This method is called when we encountered an opening '[['. The following |
390 | 390 | // block could be a Category-statement, fixed object, relation or attribute |
391 | 391 | // statements, or according print statements. |
392 | 392 | $chunk = $this->readChunk(); |
393 | | - $hasNamespaces = false; |
394 | | - |
395 | 393 | 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); |
437 | 395 | } else { // fixed subject, namespace restriction, property query, or subquery |
438 | 396 | $sep = $this->readChunk('',false); //do not consume hit, "look ahead" |
439 | 397 | 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); |
488 | 399 | } 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 | + } |
492 | 406 | |
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('\]\]'); |
533 | 425 | } else { |
534 | | - $label = $att->getText(); |
| 426 | + $label = ''; |
| 427 | + $chunk = ']]'; |
535 | 428 | } |
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 |
580 | 437 | return NULL; |
581 | 438 | } |
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); |
585 | 446 | } |
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 = ']]'; |
591 | 479 | } |
592 | 480 | } else { |
593 | | - $title = Title::newFromText($chunk); |
594 | | - if ($title !== NULL) { |
595 | | - $result = $this->addDescription($result, new SMWNominalDescription($title), false); |
596 | | - } |
| 481 | + $label = $rel->getText(); |
597 | 482 | } |
| 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 | + } |
598 | 512 | |
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('\]\]'); |
603 | 570 | } else { |
604 | | - $continue = false; |
| 571 | + $label = ''; |
| 572 | + $chunk = ']]'; |
605 | 573 | } |
| 574 | + } else { |
| 575 | + $label = $att->getText(); |
606 | 576 | } |
| 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; |
607 | 634 | } |
| 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 | + } |
608 | 659 | } |
609 | 660 | |
| 661 | + return $this->finishLinkDescription($chunk, true, $result, $setNS, $label); |
| 662 | + } |
| 663 | + |
| 664 | + protected function finishLinkDescription($chunk, $hasNamespaces, $result, &$setNS, &$label) { |
610 | 665 | if ($result === NULL) { // no useful information or concrete error found |
611 | 666 | $this->m_error = 'Syntax error in part of query.'; //TODO internationalise |
612 | 667 | return NULL; |
— | — | @@ -619,11 +674,12 @@ |
620 | 675 | |
621 | 676 | // terminate link (assuming that next chunk was read already) |
622 | 677 | if ($chunk == '|') { // label, TODO |
623 | | - $label = $this->readChunk('\]\]'); |
624 | | - if ($label != ']]') { |
| 678 | + $chunk = $this->readChunk('\]\]'); |
| 679 | + if ($chunk != ']]') { |
| 680 | + $label .= $chunk; |
625 | 681 | $chunk = $this->readChunk('\]\]'); |
626 | 682 | } else { |
627 | | - $label = ''; |
| 683 | + // empty label does not add to overall label |
628 | 684 | $chunk = ']]'; |
629 | 685 | } |
630 | 686 | } |
— | — | @@ -640,8 +696,6 @@ |
641 | 697 | } |
642 | 698 | return NULL; |
643 | 699 | } |
644 | | - |
645 | | - return $result; |
646 | 700 | } |
647 | 701 | |
648 | 702 | /** |