r36149 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r36148‎ | r36149 | r36150 >
Date:14:30, 10 June 2008
Author:mkroetzsch
Status:old
Tags:
Comment:
support for .-separated property chains in queries, much simpler syntax for amny queries
Modified paths:
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_QueryProcessor.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SemanticMediaWiki/includes/SMW_QueryProcessor.php
@@ -537,19 +537,22 @@
538538 */
539539 protected function getLinkDescription(&$setNS, &$label) {
540540 // This method is called when we encountered an opening '[['. The following
541 - // block could be a Category-statement, fixed object, property statements,
 541+ // block could be a Category-statement, fixed object, property statements,
542542 // or according print statements.
543 - $chunk = $this->readChunk();
544 - if ($chunk == $this->m_categoryprefix) { // category statement
 543+ $chunk = $this->readChunk('',true,false); // NOTE: untrimmed, initial " " escapes prop. chains
 544+ if (smwfNormalTitleText($chunk) == $this->m_categoryprefix) { // category statement
545545 return $this->getCategoryDescription($setNS, $label);
546546 } else { // fixed subject, namespace restriction, property query, or subquery
547547 $sep = $this->readChunk('',false); //do not consume hit, "look ahead"
548 - if ($sep == '::') { // relation statement
549 - return $this->getPropertyDescription($chunk, $setNS, $label);
550 - } elseif ($sep == ':=') { // attribute statement
551 - return $this->getPropertyDescription($chunk, $setNS, $label);
 548+ if ( ($sep == '::') || ($sep == ':=') ) {
 549+ if ($chunk{0} !=':') { // property statement
 550+ return $this->getPropertyDescription($chunk, $setNS, $label);
 551+ } else { // escaped article description, read part after :: to get full contents
 552+ $chunk .= $this->readChunk('\[\[|\]\]|\|\||\|');
 553+ return $this->getArticleDescription(trim($chunk), $setNS, $label);
 554+ }
552555 } else { // Fixed article/namespace restriction. $sep should be ]] or ||
553 - return $this->getArticleDescription($chunk, $setNS, $label);
 556+ return $this->getArticleDescription(trim($chunk), $setNS, $label);
554557 }
555558 }
556559 }
@@ -611,16 +614,31 @@
612615 protected function getPropertyDescription($propertyname, &$setNS, &$label) {
613616 global $smwgIP;
614617 include_once($smwgIP . '/includes/SMW_DataValueFactory.php');
615 - $this->readChunk(); // consume seperator ":="
616 - $property = Title::newFromText($propertyname, SMW_NS_PROPERTY);
617 - if ($property === NULL) {
618 - $this->m_errors[] .= wfMsgForContent('smw_badtitle', htmlspecialchars($propertyname));
619 - return NULL; ///TODO: read some more chunks and try to finish [[ ]]
 618+ $this->readChunk(); // consume separator ":=" or "::"
 619+ // first process property chain syntax (e.g. "property1.property2::value"):
 620+ if ($propertyname{0} == ' ') { // escape
 621+ $propertynames = array($propertyname);
 622+ } else {
 623+ $propertynames = explode('.', $propertyname);
620624 }
 625+ $properties = array();
 626+ $typeid = '_wpg';
 627+ foreach ($propertynames as $name) {
 628+ if ($typeid != '_wpg') { // non-final property in chain was no wikipage: not allowed
 629+ $this->m_errors[] .= wfMsgForContent('smw_valuesubquery', end($name));
 630+ return NULL; ///TODO: read some more chunks and try to finish [[ ]]
 631+ }
 632+ $property = Title::newFromText($name, SMW_NS_PROPERTY);
 633+ $typeid = SMWDataValueFactory::getPropertyObjectTypeID($property);
 634+ if ($property === NULL) { // illegal title
 635+ $this->m_errors[] .= wfMsgForContent('smw_badtitle', htmlspecialchars($name));
 636+ return NULL; ///TODO: read some more chunks and try to finish [[ ]]
 637+ }
 638+ $properties[] = $property;
 639+ } ///NOTE: after iteration, $property and $typeid correspond to last value
621640
622641 $innerdesc = NULL;
623642 $continue = true;
624 - $typeid = SMWDataValueFactory::getPropertyObjectTypeID($property);
625643 while ($continue) {
626644 $chunk = $this->readChunk();
627645 switch ($chunk) {
@@ -639,7 +657,7 @@
640658 $sublabel = '';
641659 $innerdesc = $this->addDescription($innerdesc, $this->getSubqueryDescription($setsubNS, $sublabel), false);
642660 } else { // no subqueries allowed for non-pages
643 - $this->m_errors[] = wfMsgForContent('smw_valuesubquery', $propertyname);
 661+ $this->m_errors[] = wfMsgForContent('smw_valuesubquery', end($propertynames));
644662 $innerdesc = $this->addDescription($innerdesc, new SMWThingDescription(), false);
645663 }
646664 $chunk = $this->readChunk();
@@ -649,6 +667,7 @@
650668 $open = 1;
651669 $value = $chunk;
652670 $continue2 = true;
 671+ // read value with inner [[, ]], ||
653672 while ( ($open > 0) && ($continue2) ) {
654673 $chunk = $this->readChunk('\[\[|\]\]|\|\||\|');
655674 switch ($chunk) {
@@ -663,14 +682,14 @@
664683 $open = 0;
665684 }
666685 break;
667 - case '': // this is not good ... TODO:report error
 686+ case '': ///TODO: report error; this is not good right now
668687 $continue2 = false;
669688 break;
670689 }
671690 if ($open != 0) {
672691 $value .= $chunk;
673692 }
674 - } // note that at this point, we normally already read one more chunk behind the value
 693+ } ///NOTE: at this point, we normally already read one more chunk behind the value
675694
676695 if ($typeid == '__nry') { // nary value
677696 $dv = SMWDataValueFactory::newPropertyObjectValue($property);
@@ -744,8 +763,11 @@
745764 }
746765 $this->m_errors[] = wfMsgForContent('smw_propvalueproblem', $property->getText());
747766 }
748 - $result = new SMWSomeProperty($property,$innerdesc);
749 -
 767+ $properties = array_reverse($properties);
 768+ foreach ($properties as $property) {
 769+ $innerdesc = new SMWSomeProperty($property,$innerdesc);
 770+ }
 771+ $result = $innerdesc;
750772 return $this->finishLinkDescription($chunk, false, $result, $setNS, $label);
751773 }
752774
@@ -795,7 +817,7 @@
796818
797819 /**
798820 * Parse an article description (the part of an inline query that
799 - * is in between "[[" and the closing "]]" if it is not specifying
 821+ * is in between "[[" and the closing "]]" assuming it is not specifying
800822 * a category or property) and create a suitable description.
801823 * The first chunk behind the "[[" has already been read and is
802824 * passed as a parameter.
@@ -829,9 +851,9 @@
830852 }
831853 }
832854
833 - $chunk = $this->readChunk();
 855+ $chunk = $this->readChunk('\[\[|\]\]|\|\||\|');
834856 if ($chunk == '||') {
835 - $chunk = $this->readChunk();
 857+ $chunk = $this->readChunk('\[\[|\]\]|\|\||\|');
836858 $continue = true;
837859 } else {
838860 $continue = false;
@@ -885,7 +907,7 @@
886908 * (such as [[, ]], <q>, ...). If the string starts with such a delimiter,
887909 * this delimiter is returned. Otherwise the first string in front of such a
888910 * delimiter is returned.
889 - * Trailing and initial spaces are always ignored and chunks
 911+ * Trailing and initial spaces are ignored if $trim is true, and chunks
890912 * consisting only of spaces are not returned.
891913 * If there is no more qurey string left to process, the empty string is
892914 * returned (and in no other case).
@@ -896,27 +918,27 @@
897919 * $consume specifies whether the returned chunk should be removed from the
898920 * query string.
899921 */
900 - protected function readChunk($stoppattern = '', $consume=true) {
 922+ protected function readChunk($stoppattern = '', $consume=true, $trim=true) {
901923 if ($stoppattern == '') {
902924 $stoppattern = '\[\[|\]\]|::|:=|<q>|<\/q>|^' . $this->m_categoryprefix . '|\|\||\|';
903925 }
904 - $chunks = preg_split('/[\s]*(' . $stoppattern . ')[\s]*/u', $this->m_curstring, 2, PREG_SPLIT_DELIM_CAPTURE);
 926+ $chunks = preg_split('/(' . $stoppattern . ')/u', $this->m_curstring, 2, PREG_SPLIT_DELIM_CAPTURE);
905927 if (count($chunks) == 1) { // no matches anymore, strip spaces and finish
906928 if ($consume) {
907929 $this->m_curstring = '';
908930 }
909 - return trim($chunks[0]);
910 - } elseif (count($chunks) == 3) { // this chould generally happen if count is not 1
 931+ return $trim?trim($chunks[0]):$chunks[0];
 932+ } elseif (count($chunks) == 3) { // this should generally happen if count is not 1
911933 if ($chunks[0] == '') { // string started with delimiter
912934 if ($consume) {
913935 $this->m_curstring = $chunks[2];
914936 }
915 - return $chunks[1]; // spaces stripped already
 937+ return $trim?trim($chunks[1]):$chunks[1];
916938 } else {
917939 if ($consume) {
918940 $this->m_curstring = $chunks[1] . $chunks[2];
919941 }
920 - return $chunks[0]; // spaces stripped already
 942+ return $trim?trim($chunks[0]):$chunks[0];
921943 }
922944 } else { return false; } //should never happen
923945 }

Status & tagging log