Index: trunk/extensions/SemanticMediaWiki/specials/AskSpecial/SMW_SpecialAsk.php |
— | — | @@ -23,11 +23,12 @@ |
24 | 24 | class SMW_AskPage { |
25 | 25 | |
26 | 26 | static function execute() { |
27 | | - global $wgRequest, $wgOut, $smwgIQEnabled, $smwgIQMaxLimit, $wgUser, $smwgIQSortingEnabled; |
| 27 | + global $wgRequest, $wgOut, $smwgQEnabled, $smwgQMaxLimit, $wgUser, $smwgIQSortingEnabled; |
| 28 | + |
28 | 29 | $skin = $wgUser->getSkin(); |
29 | 30 | |
30 | 31 | $query = $wgRequest->getVal( 'query' ); |
31 | | - $sort = $wgRequest->getVal( 'sort' ); |
| 32 | + $sort = $wgRequest->getVal( 'sort' ); |
32 | 33 | $order = $wgRequest->getVal( 'order' ); |
33 | 34 | $limit = $wgRequest->getVal( 'limit' ); |
34 | 35 | if ('' == $limit) $limit = 20; //$smwgIQDefaultLimit; |
— | — | @@ -54,7 +55,7 @@ |
55 | 56 | $html .= '<br /><input type="submit" value="' . wfMsg('smw_ask_submit') . "\"/>\n</form>"; |
56 | 57 | |
57 | 58 | // print results if any |
58 | | - if ($smwgIQEnabled && ('' != $query) ) { |
| 59 | + if ($smwgQEnabled && ('' != $query) ) { |
59 | 60 | $params = array('offset' => $offset, 'limit' => $limit, 'format' => 'broadtable', 'mainlabel' => ' ', 'link' => 'all', 'default' => wfMsg('smw_result_noresults'), 'sort' => $sort, 'order' => $order); |
60 | 61 | $queryobj = SMWQueryProcessor::createQuery($query, $params, false); |
61 | 62 | $res = smwfGetStore()->getQueryResult($queryobj); |
— | — | @@ -79,8 +80,8 @@ |
80 | 81 | $navigation .= ' ('; |
81 | 82 | $first = false; |
82 | 83 | } else $navigation .= ' | '; |
83 | | - if ($l > $smwgIQMaxLimit) { |
84 | | - $l = $smwgIQMaxLimit; |
| 84 | + if ($l > $smwgQMaxLimit) { |
| 85 | + $l = $smwgQMaxLimit; |
85 | 86 | $max = true; |
86 | 87 | } |
87 | 88 | if ( $limit != $l ) { |
— | — | @@ -94,7 +95,7 @@ |
95 | 96 | $html .= '<br /><div style="text-align: center;">' . $navigation; |
96 | 97 | $html .= '<br />' . $result; |
97 | 98 | $html .= '<br />' . $navigation . '</div>'; |
98 | | - } elseif (!$smwgIQEnabled) { |
| 99 | + } elseif (!$smwgQEnabled) { |
99 | 100 | $html .= '<br />' . wfMsgForContent('smw_iq_disabled'); |
100 | 101 | } |
101 | 102 | $wgOut->addHTML($html); |
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_QueryProcessor.php |
— | — | @@ -26,11 +26,11 @@ |
27 | 27 | * The <ask> parser hook processing part. |
28 | 28 | */ |
29 | 29 | function smwfProcessInlineQuery($text, $param) { |
30 | | - global $smwgIQEnabled; |
31 | | - if ($smwgIQEnabled) { |
| 30 | + global $smwgQEnabled; |
| 31 | + if ($smwgQEnabled) { |
32 | 32 | return SMWQueryProcessor::getResultHTML($text,$param); |
33 | 33 | } else { |
34 | | - return wfMsgForContent('smw_iq_disabled'); |
| 34 | + return smwfEncodeMessages(array(wfMsgForContent('smw_iq_disabled'))); |
35 | 35 | } |
36 | 36 | } |
37 | 37 | |
— | — | @@ -62,7 +62,7 @@ |
63 | 63 | */ |
64 | 64 | static public function createQuery($querystring, $params, $inline = true, $format = '') { |
65 | 65 | // This should be the proper way of substituting templates in a safe and comprehensive way: |
66 | | - global $wgTitle, $smwgIQSearchNamespaces; |
| 66 | + global $wgTitle, $smwgQDefaultNamespaces; |
67 | 67 | $parser = new Parser(); |
68 | 68 | $parserOptions = new ParserOptions(); |
69 | 69 | $parser->startExternalParse( $wgTitle, $parserOptions, OT_HTML ); |
— | — | @@ -70,7 +70,7 @@ |
71 | 71 | |
72 | 72 | // parse query: |
73 | 73 | $qp = new SMWQueryParser(); |
74 | | - $qp->setDefaultNamespaces($smwgIQSearchNamespaces); |
| 74 | + $qp->setDefaultNamespaces($smwgQDefaultNamespaces); |
75 | 75 | $desc = $qp->getQueryDescription($querystring); |
76 | 76 | if ($desc === NULL) { //abort with failure |
77 | 77 | return $qp->getErrorString(); |
— | — | @@ -82,46 +82,36 @@ |
83 | 83 | $mainlabel = $qp->getLabel(); |
84 | 84 | } |
85 | 85 | if ( !$desc->isSingleton() || (count($desc->getPrintRequests()) == 0) ) { |
86 | | - $desc->prependPrintRequest(new SMWPrintRequest(SMW_PRINT_THIS, $mainlabel)); |
| 86 | + $desc->prependPrintRequest(new SMWPrintRequest(SMW_PRINT_THIS, $mainlabel)); |
87 | 87 | } |
88 | 88 | |
89 | | - $query = new SMWQuery($desc); |
| 89 | + $query = new SMWQuery($desc, $inline); |
90 | 90 | $query->setQueryString($querystring); |
91 | 91 | $query->addErrors($qp->getErrors()); // keep parsing errors for later output |
| 92 | + |
| 93 | + // set query parameters: |
92 | 94 | if ($format == '') { |
93 | 95 | $format = SMWQueryProcessor::getResultFormat($params); |
94 | 96 | } |
95 | | - switch ($format) { |
96 | | - case 'count': |
97 | | - $query->querymode = SMWQuery::MODE_COUNT; |
98 | | - break; |
99 | | - case 'debug': |
100 | | - $query->querymode = SMWQuery::MODE_DEBUG; |
101 | | - break; |
102 | | - default: break; |
| 97 | + if ($format == 'count') { |
| 98 | + $query->querymode = SMWQuery::MODE_COUNT; |
| 99 | + } elseif ($format == 'debug') { |
| 100 | + $query->querymode = SMWQuery::MODE_DEBUG; |
103 | 101 | } |
104 | | - |
105 | | - //print '### Query:' . htmlspecialchars($desc->getQueryString()) . ' ###'; // DEBUG |
106 | | - |
107 | | - // set query parameters: |
108 | | - global $smwgIQMaxLimit, $smwgIQMaxInlineLimit; |
109 | | - if ($inline) |
110 | | - $maxlimit = $smwgIQMaxInlineLimit; |
111 | | - else $maxlimit = $smwgIQMaxLimit; |
112 | | - |
113 | | - if ( !$inline && (array_key_exists('offset',$params)) && (is_int($params['offset'] + 0)) ) { |
114 | | - $query->offset = min($maxlimit - 1, max(0,$params['offset'] + 0)); //select integer between 0 and maximal limit -1 |
| 102 | + if ( (array_key_exists('offset',$params)) && (is_int($params['offset'] + 0)) ) { |
| 103 | + $query->setOffset(max(0,$params['offset'] + 0)); |
115 | 104 | } |
116 | 105 | if ($query->querymode != SMWQuery::MODE_COUNT) { |
117 | | - // set limit small enough to stay in range with chosen offset |
118 | | - // it makes sense to have limit=0 in order to only show the link to the search special |
119 | 106 | if ( (array_key_exists('limit',$params)) && (is_int($params['limit'] + 0)) ) { |
120 | | - $query->limit = min($maxlimit - $query->offset, max(0,$params['limit'] + 0)); |
| 107 | + $query->setLimit(max(0,$params['limit'] + 0)); |
121 | 108 | } else { |
122 | | - $query->limit = $maxlimit; |
| 109 | + global $smwgQDefaultLimit; |
| 110 | + $query->setLimit($smwgQDefaultLimit); |
123 | 111 | } |
124 | | - } else { // largest possible limit for "count" |
125 | | - $query->limit = $smwgIQMaxLimit; |
| 112 | + } else { // largest possible limit for "count", even inline |
| 113 | + global $smwgQMaxLimit; |
| 114 | + $query->setOffset(0); |
| 115 | + $query->setLimit($smwgQMaxLimit, false); |
126 | 116 | } |
127 | 117 | if (array_key_exists('sort', $params)) { |
128 | 118 | $query->sort = true; |
— | — | @@ -347,6 +337,8 @@ |
348 | 338 | $continue = false; |
349 | 339 | } |
350 | 340 | break; |
| 341 | + case '+': // "... AND true" (ignore) |
| 342 | + break; |
351 | 343 | default: // error: unexpected $chunk |
352 | 344 | $this->m_errors[] = 'The part \'' . $chunk . '\' in the query was not understood. Results might not be as expected.'; // TODO: internationalise |
353 | 345 | return NULL; |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_Description.php |
— | — | @@ -133,6 +133,13 @@ |
134 | 134 | return $this->m_printreqs; |
135 | 135 | } |
136 | 136 | |
| 137 | + /** |
| 138 | + * Set the array of print requests completely. |
| 139 | + */ |
| 140 | + public function setPrintRequests($printrequests) { |
| 141 | + $this->m_printreqs = $printrequests; |
| 142 | + } |
| 143 | + |
137 | 144 | public function addPrintRequest(SMWPrintRequest $printrequest) { |
138 | 145 | $this->m_printreqs[$printrequest->getHash()] = $printrequest; |
139 | 146 | } |
— | — | @@ -156,6 +163,42 @@ |
157 | 164 | */ |
158 | 165 | abstract public function isSingleton(); |
159 | 166 | |
| 167 | + /** |
| 168 | + * Compute the size of the decription. Default is 1. |
| 169 | + */ |
| 170 | + public function getSize() { |
| 171 | + return 1; |
| 172 | + } |
| 173 | + |
| 174 | + /** |
| 175 | + * Compute the depth of the decription. Default is 0. |
| 176 | + */ |
| 177 | + public function getDepth() { |
| 178 | + return 0; |
| 179 | + } |
| 180 | + |
| 181 | + /** |
| 182 | + * Recursively restrict query to a maximal size and depth as given. |
| 183 | + * Returns a possibly changed description that should be used as a replacement. |
| 184 | + * Reduce values of parameters to account for the returned descriptions size. |
| 185 | + * Default implementation for non-nested descriptions of size 1. |
| 186 | + * The parameter $log contains a list of all pruned conditions, updated when some |
| 187 | + * description was reduced. |
| 188 | + * NOTE: objects must not do changes on $this during pruning, since $this can be |
| 189 | + * reused in multiple places of one or many queries. Make new objects to reflect |
| 190 | + * changes. |
| 191 | + */ |
| 192 | + public function prune(&$maxsize, &$maxdepth, &$log) { |
| 193 | + if ( ($maxsize < $this->getSize()) || ($maxdepth < $this->getDepth()) ) { |
| 194 | + $log[] = $this->getQueryString(); |
| 195 | + return new SMWThingDescription(); |
| 196 | + } else { |
| 197 | + $maxsize = $maxsize - $this->getSize(); |
| 198 | + $maxdepth = $maxdepth - $this->getDepth(); |
| 199 | + return $this; |
| 200 | + } |
| 201 | + } |
| 202 | + |
160 | 203 | } |
161 | 204 | |
162 | 205 | /** |
— | — | @@ -173,6 +216,14 @@ |
174 | 217 | public function isSingleton() { |
175 | 218 | return false; |
176 | 219 | } |
| 220 | + |
| 221 | + public function getSize() { |
| 222 | + return 0; // no real condition, no size or depth |
| 223 | + } |
| 224 | + |
| 225 | + public function prune(&$maxsize, &$maxdepth, &$log) { |
| 226 | + return $this; |
| 227 | + } |
177 | 228 | } |
178 | 229 | |
179 | 230 | /** |
— | — | @@ -201,6 +252,7 @@ |
202 | 253 | public function isSingleton() { |
203 | 254 | return false; |
204 | 255 | } |
| 256 | + |
205 | 257 | } |
206 | 258 | |
207 | 259 | /** |
— | — | @@ -229,6 +281,7 @@ |
230 | 282 | public function isSingleton() { |
231 | 283 | return false; |
232 | 284 | } |
| 285 | + |
233 | 286 | } |
234 | 287 | |
235 | 288 | /** |
— | — | @@ -317,6 +370,15 @@ |
318 | 371 | public function isSingleton() { |
319 | 372 | return false; |
320 | 373 | } |
| 374 | + |
| 375 | + public function getSize() { |
| 376 | + if ($this->m_comparator == SMW_CMP_ANY) { |
| 377 | + return 0; |
| 378 | + } else { |
| 379 | + return 1; |
| 380 | + } |
| 381 | + } |
| 382 | + |
321 | 383 | } |
322 | 384 | |
323 | 385 | /** |
— | — | @@ -337,7 +399,9 @@ |
338 | 400 | } |
339 | 401 | |
340 | 402 | public function addDescription(SMWDescription $description) { |
341 | | - $this->m_descriptions[] = $description; |
| 403 | + if (! ($description instanceof SMWThingDescription) ) { |
| 404 | + $this->m_descriptions[] = $description; |
| 405 | + } |
342 | 406 | } |
343 | 407 | |
344 | 408 | public function getQueryString() { |
— | — | @@ -345,7 +409,11 @@ |
346 | 410 | foreach ($this->m_descriptions as $desc) { |
347 | 411 | $result .= $desc->getQueryString() . ' '; |
348 | 412 | } |
349 | | - return $result; |
| 413 | + if ($result == '') { |
| 414 | + return '+'; |
| 415 | + } else { |
| 416 | + return ' <q>' . $result . '</q>'; |
| 417 | + } |
350 | 418 | } |
351 | 419 | |
352 | 420 | public function isSingleton() { |
— | — | @@ -356,6 +424,46 @@ |
357 | 425 | } |
358 | 426 | return false; |
359 | 427 | } |
| 428 | + |
| 429 | + public function getSize() { |
| 430 | + $size = 0; |
| 431 | + foreach ($this->m_descriptions as $desc) { |
| 432 | + $size += $desc->getSize(); |
| 433 | + } |
| 434 | + return $size; |
| 435 | + } |
| 436 | + |
| 437 | + public function getDepth() { |
| 438 | + $depth = 0; |
| 439 | + foreach ($this->m_descriptions as $desc) { |
| 440 | + $depth = max($depth, $desc->getDepth()); |
| 441 | + } |
| 442 | + return $depth; |
| 443 | + } |
| 444 | + |
| 445 | + public function prune(&$maxsize, &$maxdepth, &$log) { |
| 446 | + if ($maxsize <= 0) { |
| 447 | + $log[] = $this->getQueryString(); |
| 448 | + return new SMWThingDescription(); |
| 449 | + } |
| 450 | + $prunelog = array(); |
| 451 | + $newdepth = $maxdepth; |
| 452 | + $result = new SMWConjunction(); |
| 453 | + $result->setPrintRequests($this->getPrintRequests()); |
| 454 | + foreach ($this->m_descriptions as $desc) { |
| 455 | + $restdepth = $maxdepth; |
| 456 | + $result->addDescription($desc->prune($maxsize, $restdepth, $prunelog)); |
| 457 | + $newdepth = min($newdepth, $restdepth); |
| 458 | + } |
| 459 | + if (count($result->getDescriptions()) > 0) { |
| 460 | + $log = array_merge($log, $prunelog); |
| 461 | + $maxdepth = $newdepth; |
| 462 | + return $result; |
| 463 | + } else { |
| 464 | + $log[] = $this->getQueryString(); |
| 465 | + return new SMWThingDescription(); |
| 466 | + } |
| 467 | + } |
360 | 468 | } |
361 | 469 | |
362 | 470 | /** |
— | — | @@ -366,9 +474,12 @@ |
367 | 475 | */ |
368 | 476 | class SMWDisjunction extends SMWDescription { |
369 | 477 | protected $m_descriptions; |
| 478 | + protected $m_true = false; // used if disjunction is trivially true already |
370 | 479 | |
371 | 480 | public function SMWDisjunction($descriptions = array()) { |
372 | | - $this->m_descriptions = $descriptions; |
| 481 | + foreach ($descriptions as $desc) { |
| 482 | + $this->addDescription($desc); |
| 483 | + } |
373 | 484 | } |
374 | 485 | |
375 | 486 | public function getDescriptions() { |
— | — | @@ -376,10 +487,19 @@ |
377 | 488 | } |
378 | 489 | |
379 | 490 | public function addDescription(SMWDescription $description) { |
380 | | - $this->m_descriptions[] = $description; |
| 491 | + if ($description instanceof SMWThingDescription) { |
| 492 | + $this->m_true = true; |
| 493 | + $this->m_descriptions = array(); // no conditions any more |
| 494 | + } |
| 495 | + if (!$this->m_true) { |
| 496 | + $this->m_descriptions[] = $description; |
| 497 | + } |
381 | 498 | } |
382 | 499 | |
383 | 500 | public function getQueryString() { |
| 501 | + if ($this->m_true) { |
| 502 | + return '+'; |
| 503 | + } |
384 | 504 | $result = ''; |
385 | 505 | // TODO: many disjunctions have more suitable || abbreviations |
386 | 506 | $first = true; |
— | — | @@ -391,7 +511,7 @@ |
392 | 512 | } |
393 | 513 | $result .= $desc->getQueryString(); |
394 | 514 | } |
395 | | - return '<q>' . $result . '</q>'; |
| 515 | + return ' <q>' . $result . '</q>'; |
396 | 516 | } |
397 | 517 | |
398 | 518 | public function isSingleton() { |
— | — | @@ -403,6 +523,46 @@ |
404 | 524 | return $this->m_descriptions[0]->isSingleton(); |
405 | 525 | } |
406 | 526 | } |
| 527 | + |
| 528 | + public function getSize() { |
| 529 | + $size = 0; |
| 530 | + foreach ($this->m_descriptions as $desc) { |
| 531 | + $size += $desc->getSize(); |
| 532 | + } |
| 533 | + return $size; |
| 534 | + } |
| 535 | + |
| 536 | + public function getDepth() { |
| 537 | + $depth = 0; |
| 538 | + foreach ($this->m_descriptions as $desc) { |
| 539 | + $depth = max($depth, $desc->getDepth()); |
| 540 | + } |
| 541 | + return $depth; |
| 542 | + } |
| 543 | + |
| 544 | + public function prune(&$maxsize, &$maxdepth, &$log) { |
| 545 | + if ($maxsize <= 0) { |
| 546 | + $log[] = $this->getQueryString(); |
| 547 | + return new SMWThingDescription(); |
| 548 | + } |
| 549 | + $prunelog = array(); |
| 550 | + $newdepth = $maxdepth; |
| 551 | + $result = new SMWDisjunction(); |
| 552 | + $result->setPrintRequests($this->getPrintRequests()); |
| 553 | + foreach ($this->m_descriptions as $desc) { |
| 554 | + $restdepth = $maxdepth; |
| 555 | + $result->addDescription($desc->prune($maxsize, $restdepth, $prunelog)); |
| 556 | + $newdepth = min($newdepth, $restdepth); |
| 557 | + } |
| 558 | + if (count($result->getDescriptions()) > 0) { |
| 559 | + $log = array_merge($log, $prunelog); |
| 560 | + $maxdepth = $newdepth; |
| 561 | + return $result; |
| 562 | + } else { |
| 563 | + $log[] = $this->getQueryString(); |
| 564 | + return new SMWThingDescription(); |
| 565 | + } |
| 566 | + } |
407 | 567 | } |
408 | 568 | |
409 | 569 | /** |
— | — | @@ -431,12 +591,36 @@ |
432 | 592 | } |
433 | 593 | |
434 | 594 | public function getQueryString() { |
435 | | - return '[[' . $this->m_relation->getText() . '::<q>' . $this->m_description->getQueryString() . '</q>]]'; |
| 595 | + if ($this->m_description instanceof SMWThingDescription) { |
| 596 | + return '[[' . $this->m_relation->getText() . '::+]]'; |
| 597 | + } else { |
| 598 | + return '[[' . $this->m_relation->getText() . ':: <q>' . $this->m_description->getQueryString() . '</q>]]'; |
| 599 | + } |
436 | 600 | } |
437 | 601 | |
438 | 602 | public function isSingleton() { |
439 | 603 | return false; |
440 | 604 | } |
| 605 | + |
| 606 | + public function getSize() { |
| 607 | + return 1+$this->getDescription()->getSize(); |
| 608 | + } |
| 609 | + |
| 610 | + public function getDepth() { |
| 611 | + return 1+$this->getDescription()->getDepth(); |
| 612 | + } |
| 613 | + |
| 614 | + public function prune(&$maxsize, &$maxdepth, &$log) { |
| 615 | + if (($maxsize <= 0)||($maxdepth <= 0)) { |
| 616 | + $log[] = $this->getQueryString(); |
| 617 | + return new SMWThingDescription(); |
| 618 | + } |
| 619 | + $maxsize--; |
| 620 | + $maxdepth--; |
| 621 | + $result = new SMWSomeRelation($this->getRelation(), $this->m_description->prune($maxsize,$maxdepth,$log)); |
| 622 | + $result->setPrintRequests($this->getPrintRequests()); |
| 623 | + return $result; |
| 624 | + } |
441 | 625 | } |
442 | 626 | |
443 | 627 | /** |
— | — | @@ -471,6 +655,26 @@ |
472 | 656 | public function isSingleton() { |
473 | 657 | return false; |
474 | 658 | } |
| 659 | + |
| 660 | + public function getSize() { |
| 661 | + return 1+$this->getDescription()->getSize(); |
| 662 | + } |
| 663 | + |
| 664 | + public function getDepth() { |
| 665 | + return 1+$this->getDescription()->getDepth(); |
| 666 | + } |
| 667 | + |
| 668 | + public function prune(&$maxsize, &$maxdepth, &$log) { |
| 669 | + if (($maxsize <= 0)||($maxdepth <= 0)) { |
| 670 | + $log[] = $this->getQueryString(); |
| 671 | + return new SMWThingDescription(); |
| 672 | + } |
| 673 | + $maxsize--; |
| 674 | + $maxdepth--; |
| 675 | + $result = new SMWSomeAttribute($this->getAttribute(), $this->m_description->prune($maxsize,$maxdepth,$log)); |
| 676 | + $result->setPrintRequests($this->getPrintRequests()); |
| 677 | + return $result; |
| 678 | + } |
475 | 679 | } |
476 | 680 | |
477 | 681 | |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_Query.php |
— | — | @@ -24,24 +24,33 @@ |
25 | 25 | const MODE_COUNT = 2; |
26 | 26 | const MODE_DEBUG = 3; |
27 | 27 | |
28 | | - public $limit = -1; |
29 | | - public $offset = 0; |
30 | 28 | public $sort = false; |
31 | 29 | public $ascending = true; |
32 | 30 | public $sortkey = false; |
33 | 31 | public $querymode = SMWQuery::MODE_INSTANCES; |
34 | 32 | |
| 33 | + protected $m_limit; |
| 34 | + protected $m_offset = 0; |
35 | 35 | protected $m_description; |
36 | | - protected $m_errors; // keep any errors that occurred so far |
| 36 | + protected $m_errors = array(); // keep any errors that occurred so far |
37 | 37 | protected $m_querystring = false; // string (inline query) version (if fixed and known) |
| 38 | + protected $m_inline; // query used inline? (required for finding right default parameters) |
38 | 39 | |
39 | | - public function SMWQuery($description = NULL) { |
| 40 | + public function SMWQuery($description = NULL, $inline = false) { |
| 41 | + global $smwgQMaxLimit, $smwgQMaxInlineLimit; |
| 42 | + if ($inline) { |
| 43 | + $this->limit = $smwgQMaxInlineLimit; |
| 44 | + } else { |
| 45 | + $this->limit = $smwgQMaxLimit; |
| 46 | + } |
| 47 | + $this->m_inline = $inline; |
40 | 48 | $this->m_description = $description; |
41 | | - $this->m_errors = array(); |
| 49 | + $this->applyRestrictions(); |
42 | 50 | } |
43 | 51 | |
44 | 52 | public function setDescription(SMWDescription $description) { |
45 | 53 | $this->m_description = $description; |
| 54 | + $this->applyRestrictions(); |
46 | 55 | } |
47 | 56 | |
48 | 57 | public function getDescription() { |
— | — | @@ -70,5 +79,59 @@ |
71 | 80 | } |
72 | 81 | } |
73 | 82 | |
| 83 | + public function getOffset() { |
| 84 | + return $this->m_offset; |
| 85 | + } |
| 86 | + |
| 87 | + /** |
| 88 | + * Set an offset for the returned query results. The current limit is taken into |
| 89 | + * account such that the offset cannot be so large that no results are can ever |
| 90 | + * be returned at all. |
| 91 | + * The function returns the chosen offset. |
| 92 | + */ |
| 93 | + public function setOffset($offset) { |
| 94 | + $this->m_offset = min($this->m_limit - 1, $offset); //select integer between 0 and current limit -1; |
| 95 | + return $this->m_offset; |
| 96 | + } |
| 97 | + |
| 98 | + public function getLimit() { |
| 99 | + return $this->m_limit; |
| 100 | + } |
| 101 | + |
| 102 | + /** |
| 103 | + * Set a limit for number of query results. The set limit might be restricted by the |
| 104 | + * current offset so as to ensure that the number of the last considered result does not |
| 105 | + * exceed the maximum amount of supported results. |
| 106 | + * The function returns the chosen limit. |
| 107 | + * NOTE: it makes sense to have limit==0 e.g. to only show a link to the search special |
| 108 | + */ |
| 109 | + public function setLimit($limit, $restrictinline = true) { |
| 110 | + global $smwgQMaxLimit, $smwgQMaxInlineLimit; |
| 111 | + if ($this->m_inline && $restrictinline) { |
| 112 | + $maxlimit = $smwgQMaxInlineLimit; |
| 113 | + } else { |
| 114 | + $maxlimit = $smwgQMaxLimit; |
| 115 | + } |
| 116 | + $this->m_limit = min($maxlimit - $this->m_offset, $limit); |
| 117 | + return $this->m_limit; |
| 118 | + } |
| 119 | + |
| 120 | + /** |
| 121 | + * Apply structural restrictions to the current description. |
| 122 | + */ |
| 123 | + public function applyRestrictions() { |
| 124 | + global $smwgQMaxSize, $smwgQMaxDepth; |
| 125 | + if ($this->m_description !== NULL) { |
| 126 | + $maxsize = $smwgQMaxSize; |
| 127 | + $maxdepth = $smwgQMaxDepth; |
| 128 | + $log = array(); |
| 129 | + $this->m_description = $this->m_description->prune($maxsize, $maxdepth, $log); |
| 130 | + if (count($log) > 0) { |
| 131 | + $this->m_errors[] = 'The following query conditions could not be considered due to restrictions in query size or depth: ' . implode(', ' , $log) . '.'; |
| 132 | + } |
| 133 | + } |
| 134 | + } |
| 135 | + |
| 136 | + |
74 | 137 | } |
75 | 138 | |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore.php |
— | — | @@ -638,10 +638,8 @@ |
639 | 639 | |
640 | 640 | // Prepare SQL options |
641 | 641 | $sql_options = array(); |
642 | | - if ($query->limit >= 0) { |
643 | | - $sql_options['LIMIT'] = $query->limit + 1; |
644 | | - } |
645 | | - $sql_options['OFFSET'] = $query->offset; |
| 642 | + $sql_options['LIMIT'] = $query->getLimit() + 1; |
| 643 | + $sql_options['OFFSET'] = $query->getOffset(); |
646 | 644 | if ( $smwgIQSortingEnabled ) { |
647 | 645 | $order = $query->ascending ? 'ASC' : 'DESC'; |
648 | 646 | if ( ($this->m_sortfield == false) && ($this->m_sortkey == false) ) { |
— | — | @@ -665,7 +663,9 @@ |
666 | 664 | list( $startOpts, $useIndex, $tailOpts ) = $db->makeSelectOptions( $sql_options ); |
667 | 665 | $result = '<div style="border: 1px dotted black; background: #A1FB00; padding: 20px; ">' . |
668 | 666 | '<b>Generated Wiki-Query</b><br />' . |
669 | | - htmlspecialchars($query->getDescription()->getQueryString()) . '<br />' . |
| 667 | + $query->getDescription()->getQueryString() . '<br />' . |
| 668 | + '<b>Query-Size: </b>' . $query->getDescription()->getSize() . '<br />' . |
| 669 | + '<b>Query-Depth: </b>' . $query->getDescription()->getDepth() . '<br />' . |
670 | 670 | '<b>SQL-Query</b><br />' . |
671 | 671 | "SELECT DISTINCT $pagetable.page_title as title, $pagetable.page_namespace as namespace" . |
672 | 672 | ' FROM ' . $from . ' WHERE ' . $where . $tailOpts . '<br />' . |
— | — | @@ -699,7 +699,7 @@ |
700 | 700 | |
701 | 701 | $qr = array(); |
702 | 702 | $count = 0; |
703 | | - while ( ( ($count<$query->limit) || ($query->limit < 0) ) && ($row = $db->fetchObject($res)) ) { |
| 703 | + while ( ($count<$query->getLimit()) && ($row = $db->fetchObject($res)) ) { |
704 | 704 | $count++; |
705 | 705 | $qr[] = Title::newFromText($row->title, $row->namespace); |
706 | 706 | } |
— | — | @@ -710,7 +710,7 @@ |
711 | 711 | |
712 | 712 | // Create result by executing print statements for everything that was fetched |
713 | 713 | ///TODO: use limit (and offset?) values for printouts? |
714 | | - $result = new SMWQueryResult($prs, $query, ( ($count > $query->limit) && ($query->limit >= 0) ) ); |
| 714 | + $result = new SMWQueryResult($prs, $query, ($count > $query->getLimit()) ); |
715 | 715 | foreach ($qr as $qt) { |
716 | 716 | $row = array(); |
717 | 717 | foreach ($prs as $pr) { |
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_GlobalFunctions.php |
— | — | @@ -378,7 +378,7 @@ |
379 | 379 | */ |
380 | 380 | function smwfEncodeMessages($msgarray) { |
381 | 381 | if (count($msgarray) > 0) { |
382 | | - $msgs = implode(', ', $msgarray); |
| 382 | + $msgs = implode(' ', $msgarray); |
383 | 383 | return '<span class="smwttpersist"><span class="smwtticon">warning.png</span><span class="smwttcontent">' . $msgs . '</span></span>'; |
384 | 384 | } else { |
385 | 385 | return ''; |
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_Settings.php |
— | — | @@ -55,23 +55,31 @@ |
56 | 56 | # Settings for inline queries (<ask>) and for semantic queries in general. |
57 | 57 | # Especially meant to prevent overly high server-load by complex queries. |
58 | 58 | ## |
59 | | -$smwgQSubcategoryDepth = 10; // Restrict level of sub-category inclusion (steps within category hierarchy) |
60 | | -$smwgQSubpropertyDepth = 10; // Restrict level of sub-property inclusion (steps within category hierarchy) |
61 | | -// (Use 0 to disable hierarchy-inferencing in queries) |
| 59 | +$smwgQEnabled = true; // (De)activates all query related features and interfaces |
| 60 | +$smwgQMaxSize = 12; // Maximal number of conditions in queries, use format="debug" for example sizes |
| 61 | +$smwgQMaxDepth = 4; // Maximal property depth of queries, e.g. [[rel::<q>[[rel2::Test]]</q>]] has depth 2 |
| 62 | +$smwgQSubcategoryDepth = 10; // Restrict level of sub-category inclusion (steps within category hierarchy) |
| 63 | +$smwgQSubpropertyDepth = 10; // Restrict level of sub-property inclusion (steps within property hierarchy) |
| 64 | + // (Use 0 to disable hierarchy-inferencing in queries) |
62 | 65 | $smwgQEqualitySupport = true; // Should #redirects be evaluated as equality between page names? |
| 66 | +$smwgQDefaultNamespaces = array(NS_MAIN, NS_IMAGE); // Which namespaces should be searched by default? |
| 67 | + // (value NULL switches off default restrictions on searching -- this is faster) |
| 68 | +$smwgQMaxLimit = 10000; // Max number of results ever retrieved, even when using special query pages. |
63 | 69 | |
| 70 | + |
| 71 | +### Settings about printout of (especially inline) queries: |
| 72 | +$smwgQDefaultLimit = 50; // Default number of rows returned in a query. Can be increased with <ask limit="num">... |
| 73 | +$smwgQMaxInlineLimit = 500; // Max number of rows ever printed in a single inline query on a single page. |
| 74 | + |
| 75 | +$smwgIQMaxPrintout = 10; // Max number of supported printouts (added columns in result table, * statements) |
| 76 | + |
| 77 | +### Formatting settings |
| 78 | +$smwgIQDefaultLinking = 'subject'; // Default linking behaviour. Can be one of "none", "subject", "all" |
| 79 | + |
64 | 80 | ## older query parameters below, some of those might be ignored |
65 | | -$smwgIQEnabled = true; // (De)activates all query related features |
66 | | -$smwgIQDefaultLinking = 'subject'; // Default linking behaviour. Can be one of "none", "subject", "all" |
67 | | -$smwgIQSearchNamespaces = array(NS_MAIN, NS_IMAGE); // Which namespaces should be searched by default? |
68 | | - // Value NULL switches off default restrictions on searching (faster) |
69 | | -$smwgIQMaxConditions = 50; // Max number of "conditions" (e.g. value or category conditions in a query) |
70 | | -$smwgIQMaxTables = 10; // Max number of "joins" in a query. Restricts nesting depth of queries. |
71 | | -$smwgIQMaxPrintout = 10; // Max number of supported printouts (added columns in result table, * statements) |
72 | | -$smwgIQSubQueriesEnabled = true; //(De)activates subqueries (<q>-Syntax), use $smwgIQMaxTables for limiting them |
73 | | -$smwgIQMaxLimit = 10000; // Max number of results ever retrieved, even when using special query pages. |
74 | | -$smwgIQMaxInlineLimit = 500; // Max number of rows printed in an inline query on a single page. |
75 | | -$smwgIQDefaultLimit = 50; // Default number of rows returned in a query. Can be increased with <ask limit="num">... |
| 81 | +//$smwgIQMaxConditions = 50; // Max number of "conditions" (e.g. value or category conditions in a query) |
| 82 | +//$smwgIQMaxTables = 10; // Max number of "joins" in a query. Restricts nesting depth of queries. |
| 83 | +//$smwgIQSubQueriesEnabled = true; //(De)activates subqueries (<q>-Syntax), use $smwgIQMaxTables for limiting them |
76 | 84 | $smwgIQDisjunctiveQueriesEnabled = true; // Support disjunctions in queries (||)? |
77 | 85 | //$smwgIQRedirectNormalization = true; // Should redirects be interpreted as equivalence between page names? |
78 | 86 | $smwgIQSortingEnabled = true; // (De)activate sorting of results. |