Index: trunk/extensions/SemanticMediaWiki/includes/SMW_QueryPrinters.php |
— | — | @@ -20,7 +20,6 @@ |
21 | 21 | protected $mLinkOthers; // should article names of other columns (besides the first) be linked? |
22 | 22 | protected $mDefault = ''; // default return value for empty queries |
23 | 23 | protected $mShowHeaders = true; // should the headers (property names) be printed? |
24 | | - protected $mMainLabel = NULL; // label used for displaying the subject, or NULL if none was given |
25 | 24 | protected $mInline; // is this query result "inline" in some page (only then a link to unshown results is created, error handling may also be affected) |
26 | 25 | protected $mLinker; // Linker object as needed for making result links. Might come from some skin at some time. |
27 | 26 | |
— | — | @@ -87,9 +86,6 @@ |
88 | 87 | $this->mShowHeaders = true; |
89 | 88 | } |
90 | 89 | } |
91 | | - if (array_key_exists('mainlabel', $params)) { |
92 | | - $this->mMainLabel = htmlspecialchars($params['mainlabel']); |
93 | | - } |
94 | 90 | } |
95 | 91 | |
96 | 92 | /** |
— | — | @@ -185,7 +181,7 @@ |
186 | 182 | SMWResultPrinter::readParameters($params); |
187 | 183 | |
188 | 184 | if (array_key_exists('sep', $params)) { |
189 | | - $this->mSep = htmlspecialchars($params['sep']); |
| 185 | + $this->mSep = htmlspecialchars(str_replace('_',' ',$params['sep'])); |
190 | 186 | } |
191 | 187 | if (array_key_exists('template', $params)) { |
192 | 188 | $this->mSep = $params['template']; |
— | — | @@ -306,9 +302,388 @@ |
307 | 303 | } |
308 | 304 | |
309 | 305 | |
| 306 | +/** |
| 307 | + * New implementation of SMW's printer for timeline data. |
| 308 | + */ |
| 309 | +class SMWTimelineResultPrinter extends SMWResultPrinter { |
310 | 310 | |
| 311 | + protected $m_tlstart = ''; // name of the start-date property if any |
| 312 | + protected $m_tlend = ''; // name of the end-date property if any |
| 313 | + protected $m_tlsize = ''; // CSS-compatible size (such as 400px) |
| 314 | + protected $m_tlbands = ''; // array of band IDs (MONTH, YEAR, ...) |
| 315 | + protected $m_tlpos = ''; // position identifier (start, end, today, middle) |
311 | 316 | |
| 317 | + protected function readParameters($params) { |
| 318 | + SMWResultPrinter::readParameters($params); |
312 | 319 | |
| 320 | + if (array_key_exists('timelinestart', $params)) { |
| 321 | + $this->m_tlstart = smwfNormalTitleDBKey($params['timelinestart']); |
| 322 | + } |
| 323 | + if (array_key_exists('timelineend', $params)) { |
| 324 | + $this->m_tlstart = smwfNormalTitleDBKey($params['timelineend']); |
| 325 | + } |
| 326 | + if (array_key_exists('timelinesize', $params)) { |
| 327 | + $this->m_tlsize = htmlspecialchars(str_replace(';', ' ', strtolower($params['timelinesize']))); |
| 328 | + // str_replace makes sure this is only one value, not mutliple CSS fields (prevent CSS attacks) |
| 329 | + } else { |
| 330 | + $this->m_tlsize = '300px'; |
| 331 | + } |
| 332 | + if (array_key_exists('timelinebands', $params)) { |
| 333 | + //check for band parameter, should look like "DAY,MONTH,YEAR" |
| 334 | + $this->m_tlbands = preg_split('/[,][\s]*/',$params['timelinebands']); |
| 335 | + } else { |
| 336 | + $this->m_tlbands = array('MONTH','YEAR'); // TODO: check what default the JavaScript uses |
| 337 | + } |
| 338 | + if (array_key_exists('timelineposition', $params)) { |
| 339 | + $this->m_tlpos = strtolower($params['timelineposition']); |
| 340 | + } else { |
| 341 | + $this->m_tlpos = 'middle'; |
| 342 | + } |
| 343 | + } |
| 344 | + |
| 345 | + public function getHTML($res) { |
| 346 | + global $smwgIQRunningNumber; |
| 347 | + |
| 348 | + $eventline = ('eventline' == $this->mFormat); |
| 349 | + |
| 350 | + if ( !$eventline && ($this->m_tlstart == '') ) { // seek defaults |
| 351 | + foreach ($res->getPrintRequests() as $pr) { |
| 352 | + if ( ($pr->getMode() == SMW_PRINT_ATTS) && ($pr->getDatavalue()->getTypeID() == 'datetime') ) { |
| 353 | + if ( ($this->m_tlend == '') && ($this->m_tlstart != '') && |
| 354 | + ($this->m_tlstart != $pr->getTitle()->getText()) ) { |
| 355 | + $this->m_tlend = $pr->getTitle()->getText(); |
| 356 | + } elseif ( ($this->m_tlstart == '') && ($this->m_tlend != $pr->getTitle()->getText()) ) { |
| 357 | + $this->m_tlstart = $pr->getTitle()->getText(); |
| 358 | + } |
| 359 | + } |
| 360 | + } |
| 361 | + } |
| 362 | + |
| 363 | + // print header |
| 364 | + $result = "<div class=\"smwtimeline\" id=\"smwtimeline$smwgIQRunningNumber\" style=\"height: $this->m_tlsize\">"; |
| 365 | + $result .= '<span class="smwtlcomment">' . wfMsgForContent('smw_iq_nojs',$res->getQueryURL()) . '</span>'; // note for people without JavaScript |
| 366 | + |
| 367 | + foreach ($this->m_tlbands as $band) { |
| 368 | + $result .= '<span class="smwtlband">' . htmlspecialchars($band) . '</span>'; |
| 369 | + //just print any "band" given, the JavaScript will figure out what to make of it |
| 370 | + } |
| 371 | + |
| 372 | + // print all result rows |
| 373 | + $positions = array(); // possible positions, collected to select one for centering |
| 374 | + $curcolor = 0; // color cycling is used for eventline |
| 375 | + if ( ($this->m_tlstart != '') || $eventline ) { |
| 376 | + $output = false; // true if output for the popup was given on current line |
| 377 | + if ($eventline) $events = array(); // array of events that are to be printed |
| 378 | + while ( $row = $res->getNext() ) { |
| 379 | + $hastime = false; // true as soon as some startdate value was found |
| 380 | + $hastitle = false; // true as soon as some label for the event was found |
| 381 | + $curdata = ''; // current *inner* print data (within some event span) |
| 382 | + $curmeta = ''; // current event meta data |
| 383 | + $curarticle = ''; // label of current article, if it was found; needed only for eventline labeling |
| 384 | + $first_col = true; |
| 385 | + foreach ($row as $field) { |
| 386 | + $first_value = true; |
| 387 | + $pr = $field->getPrintRequest(); |
| 388 | + while ( ($object = $field->getNextObject()) !== false ) { |
| 389 | + // Obtain string value ... |
| 390 | + // TODO: this would be simpler with uniform Datavalue usage |
| 391 | + $urlobject = false; // is our current object having a URL representation string? |
| 392 | + if ($object instanceof SMWDataValue) { //print data values |
| 393 | + $objectlabel = $object->getShortHTMLText(NULL); // TODO: support linked datavalues once |
| 394 | + } elseif ($object instanceof Title) { // print Title objects |
| 395 | + if ($this->getLinker($first_col) === NULL) { |
| 396 | + $objectlabel = htmlspecialchars($object->getPrefixedText()); |
| 397 | + } else { |
| 398 | + $urlobject = true; |
| 399 | + if ($pr->getMode() == SMW_PRINT_THIS) { // "this" results must exist |
| 400 | + $objectlabel = $this->getLinker($first_col)->makeKnownLinkObj($object); |
| 401 | + } else { |
| 402 | + $objectlabel = $this->getLinker($first_col)->makeLinkObj($object); |
| 403 | + } |
| 404 | + } |
| 405 | + } // ... done. |
| 406 | + $header = ''; |
| 407 | + if ($first_value) { |
| 408 | + // find header for current value: |
| 409 | + if ( $this->mShowHeaders && ('' != $pr->getLabel()) ) { |
| 410 | + $header = $pr->getHTMLText($this->mLinker) . ' '; |
| 411 | + } |
| 412 | + // is this a start date? |
| 413 | + if ( ($pr->getMode() == SMW_PRINT_ATTS) && |
| 414 | + ($pr->getTitle()->getText() == $this->m_tlstart) ) { |
| 415 | + //FIXME: Timeline scripts should support XSD format explicitly. They |
| 416 | + //currently seem to implement iso8601 which deviates from XSD in cases. |
| 417 | + //NOTE: We can assume $object to be an SMWDataValue in this case. |
| 418 | + $curmeta .= '<span class="smwtlstart">' . $object->getXSDValue() . '</span>'; |
| 419 | + $positions[$object->getNumericValue()] = $object->getXSDValue(); |
| 420 | + $hastime = true; |
| 421 | + } |
| 422 | + // is this the end date? |
| 423 | + if ( ($pr->getMode() == SMW_PRINT_ATTS) && |
| 424 | + ($pr->getTitle()->getText() == $this->m_tlend) ) { |
| 425 | + //NOTE: We can assume $object to be an SMWDataValue in this case. |
| 426 | + $curmeta .= '<span class="smwtlend">' . $object->getXSDValue() . '</span>'; |
| 427 | + } |
| 428 | + // find title for displaying event |
| 429 | + if ( !$hastitle ) { |
| 430 | + if ($urlobject) { |
| 431 | + $curmeta .= '<span class="smwtlurl">' . $objectlabel . '</span>'; |
| 432 | + } else { |
| 433 | + $curmeta .= '<span class="smwtltitle">' . $objectlabel . '</span>'; |
| 434 | + } |
| 435 | + if ( ($pr->getMode() == SMW_PRINT_THIS) ) { |
| 436 | + // NOTE: type Title of $object implied |
| 437 | + $curarticle = $object->getText(); |
| 438 | + } |
| 439 | + $hastitle = true; |
| 440 | + } |
| 441 | + } elseif ($output) $curdata .= ', '; //it *can* happen that output is false here, if the subject was not printed (fixed subject query) and mutliple items appear in the first row |
| 442 | + if (!$first_col || !$first_value || $eventline) { |
| 443 | + $curdata .= $header . $objectlabel; |
| 444 | + $output = true; |
| 445 | + } |
| 446 | + if ($eventline && ($pr->getMode() == SMW_PRINT_ATTS) && ($pr->getDatavalue()->getTypeID() == 'datetime') && ('' != $pr->getLabel()) && ($pr->getTitle()->getText() != $this->m_tlstart) && ($pr->getTitle()->getText() != $this->m_tlend) ) { |
| 447 | + $events[] = array($object->getXSDValue(), $pr->getLabel(), $object->getNumericValue()); |
| 448 | + } |
| 449 | + $first_value = false; |
| 450 | + } |
| 451 | + if ($output) $curdata .= "<br />"; |
| 452 | + $output = false; |
| 453 | + $first_col = false; |
| 454 | + } |
| 455 | + |
| 456 | + if ( $hastime ) { |
| 457 | + $result .= '<span class="smwtlevent">' . $curmeta . '<span class="smwtlcoloricon">' . $curcolor . '</span>' . $curdata . '</span>'; |
| 458 | + } |
| 459 | + if ( $eventline ) { |
| 460 | + foreach ($events as $event) { |
| 461 | + $result .= '<span class="smwtlevent"><span class="smwtlstart">' . $event[0] . '</span><span class="smwtlurl">' . $event[1] . '</span><span class="smwtlcoloricon">' . $curcolor . '</span>'; |
| 462 | + if ( $curarticle != '' ) $result .= '<span class="smwtlprefix">' . $curarticle . ' </span>'; |
| 463 | + $result .= $curdata . '</span>'; |
| 464 | + $positions[$event[2]] = $event[0]; |
| 465 | + } |
| 466 | + $events = array(); |
| 467 | + $curcolor = ($curcolor + 1) % 10; |
| 468 | + } |
| 469 | + } |
| 470 | + ksort($positions); |
| 471 | + $positions = array_values($positions); |
| 472 | + switch ($this->m_tlpos) { |
| 473 | + case 'start': |
| 474 | + $result .= '<span class="smwtlposition">' . $positions[0] . '</span>'; |
| 475 | + break; |
| 476 | + case 'end': |
| 477 | + $result .= '<span class="smwtlposition">' . $positions[count($positions)-1] . '</span>'; |
| 478 | + break; |
| 479 | + case 'today': break; // default |
| 480 | + case 'middle': default: |
| 481 | + $result .= '<span class="smwtlposition">' . $positions[ceil(count($positions)/2)-1] . '</span>'; |
| 482 | + break; |
| 483 | + } |
| 484 | + } |
| 485 | + //no further results displayed ... |
| 486 | + |
| 487 | + // print footer |
| 488 | + $result .= "</div>"; |
| 489 | + return $result; |
| 490 | + } |
| 491 | +} |
| 492 | + |
| 493 | + |
| 494 | +/** |
| 495 | + * Printer for template data. Passes a result row as anonymous parameters to |
| 496 | + * a given template (which might ignore them or not) and prints the result. |
| 497 | + */ |
| 498 | +class SMWTemplateResultPrinter extends SMWResultPrinter { |
| 499 | + |
| 500 | + protected $m_template; |
| 501 | + |
| 502 | + protected function readParameters($params) { |
| 503 | + SMWResultPrinter::readParameters($params); |
| 504 | + |
| 505 | + if (array_key_exists('template', $params)) { |
| 506 | + $this->m_template = $params['template']; |
| 507 | + } else { |
| 508 | + $this->m_template = false; |
| 509 | + } |
| 510 | + } |
| 511 | + |
| 512 | + public function getHTML($res) { |
| 513 | + // handle factbox |
| 514 | + global $smwgStoreActive, $wgTitle; |
| 515 | + |
| 516 | + // print all result rows |
| 517 | + if ($this->m_template == false) { |
| 518 | + return 'Please provide parameter "template" for query to work.'; // TODO: internationalise, beautify |
| 519 | + } |
| 520 | + |
| 521 | + $old_smwgStoreActive = $smwgStoreActive; |
| 522 | + $smwgStoreActive = false; // no annotations stored, no factbox printed |
| 523 | + |
| 524 | + $parserinput = $this->mIntro; |
| 525 | + |
| 526 | + $parser_options = new ParserOptions(); |
| 527 | + $parser_options->setEditSection(false); // embedded sections should not have edit links |
| 528 | + $parser = new Parser(); |
| 529 | + while ( $row = $res->getNext() ) { |
| 530 | + $wikitext = ''; |
| 531 | + $firstcol = true; |
| 532 | + foreach ($row as $field) { |
| 533 | + $wikitext .= "|"; |
| 534 | + $first = true; |
| 535 | + while ( ($text = $field->getNextWikiText($this->getLinker($firstcol))) !== false ) { |
| 536 | + if ($first) { |
| 537 | + $first = false; |
| 538 | + } else { |
| 539 | + $wikitext .= ', '; |
| 540 | + } |
| 541 | + $wikitext .= $text; |
| 542 | + } |
| 543 | + $firstcol = false; |
| 544 | + } |
| 545 | + $parserinput .= '{{' . $this->m_template . str_replace('=','|', $wikitext) . '}}'; // encode '=' for use in templates (templates fail otherwise) |
| 546 | + } |
| 547 | + $parserOutput = $parser->parse($parserinput, $wgTitle, $parser_options); |
| 548 | + $result = $parserOutput->getText(); |
| 549 | + // show link to more results |
| 550 | + if ($this->mInline && $res->hasFurtherResults()) { |
| 551 | + $label = $this->mSearchlabel; |
| 552 | + if ($label === NULL) { //apply defaults |
| 553 | + $label = wfMsgForContent('smw_iq_moreresults'); |
| 554 | + } |
| 555 | + if ($label != '') { |
| 556 | + $result .= '<a href="' . $res->getQueryURL() . '">' . $label . '</a>'; |
| 557 | + } |
| 558 | + } |
| 559 | + |
| 560 | + $smwgStoreActive = $old_smwgStoreActive; |
| 561 | + return $result; |
| 562 | + } |
| 563 | +} |
| 564 | + |
| 565 | + |
| 566 | +/** |
| 567 | + * Printer for embedded data. |
| 568 | + * Embeds in the page output the contents of the pages in the query result set. |
| 569 | + * Only the first column of the query is considered. If it is a page reference then that page's contents is embedded. |
| 570 | + * The optional "titlestyle" formatting parameter can be used to apply a format to the headings for the page titles. |
| 571 | + * If "titlestyle" is not specified, a <h1> tag is used. |
| 572 | + * @author Fernando Correia |
| 573 | + * @author Markus Kr�tzsch |
| 574 | + */ |
| 575 | +class SMWEmbeddedResultPrinter extends SMWResultPrinter { |
| 576 | + |
| 577 | + protected $m_showhead; |
| 578 | + protected $m_embedformat; |
| 579 | + |
| 580 | + protected function readParameters($params) { |
| 581 | + SMWResultPrinter::readParameters($params); |
| 582 | + |
| 583 | + if (array_key_exists('embedonly', $params)) { |
| 584 | + $this->m_showhead = false; |
| 585 | + } else { |
| 586 | + $this->m_showhead = true; |
| 587 | + } |
| 588 | + if (array_key_exists('embedformat', $params)) { |
| 589 | + $this->m_embedformat = $params['embedformat']; |
| 590 | + } else { |
| 591 | + $this->m_embedformat = 'h1'; |
| 592 | + } |
| 593 | + } |
| 594 | + |
| 595 | + public function getHTML($res) { |
| 596 | + // handle factbox |
| 597 | + global $smwgStoreActive; |
| 598 | + $old_smwgStoreActive = $smwgStoreActive; |
| 599 | + $smwgStoreActive = false; // no annotations stored, no factbox printed |
| 600 | + |
| 601 | + // print header |
| 602 | + $result = $this->mIntro; |
| 603 | + |
| 604 | + switch ($this->m_embedformat) { |
| 605 | + case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': |
| 606 | + $footer = ''; |
| 607 | + $embstart = ''; |
| 608 | + $headstart = '<' . $this->m_embedformat . '>'; |
| 609 | + $headend = '</' . $this->m_embedformat . ">\n"; |
| 610 | + $embend = ''; |
| 611 | + break; |
| 612 | + case 'ul': case 'ol': |
| 613 | + $result .= '<' . $this->m_embedformat . '>'; |
| 614 | + $footer = '</' . $this->m_embedformat . '>'; |
| 615 | + $embstart = '<li>'; |
| 616 | + $headstart = ''; |
| 617 | + $headend = "<br />\n"; |
| 618 | + $embend = "</li>\n"; |
| 619 | + break; |
| 620 | + } |
| 621 | + |
| 622 | + // print all result rows |
| 623 | + $parser_options = new ParserOptions(); |
| 624 | + $parser_options->setEditSection(false); // embedded sections should not have edit links |
| 625 | + $parser = new Parser(); |
| 626 | + |
| 627 | + while ( $row = $res->getNext() ) { |
| 628 | + $first_col = true; |
| 629 | + foreach ($row as $field) { |
| 630 | + if ( ($field->getPrintRequest()->getMode() == SMW_PRINT_RELS) || |
| 631 | + ($field->getPrintRequest()->getMode() == SMW_PRINT_THIS) ) { // ensure that we deal with titles |
| 632 | + while ( ($object = $field->getNextObject()) !== false ) { |
| 633 | + $result .= $embstart; |
| 634 | + // create text version (this will improve with the unified datavalue framework) ... |
| 635 | + if ($this->getLinker(true) === NULL) { |
| 636 | + $text = htmlspecialchars($object->getPrefixedText()); |
| 637 | + } else { |
| 638 | + if ($field->getPrintRequest()->getMode() == SMW_PRINT_THIS) { // "this" results must exist |
| 639 | + $text = $this->getLinker(true)->makeKnownLinkObj($object); |
| 640 | + } else { |
| 641 | + $text = $this->getLinker(true)->makeLinkObj($object); |
| 642 | + } |
| 643 | + } // ... done |
| 644 | + if ($this->m_showhead) { |
| 645 | + $result .= $headstart . $text . $headend; |
| 646 | + } |
| 647 | + if ($object->getNamespace() == NS_MAIN) { |
| 648 | + $articlename = ':' . $object->getText(); |
| 649 | + } else { |
| 650 | + $articlename = $object->getPrefixedText(); |
| 651 | + } |
| 652 | + $parserOutput = $parser->parse('{{' . $articlename . '}}', $object, $parser_options); |
| 653 | + $result .= $parserOutput->getText(); |
| 654 | + $result .= $embend; |
| 655 | + } |
| 656 | + } |
| 657 | + break; // only use first column for now |
| 658 | + } |
| 659 | + } |
| 660 | + |
| 661 | + // show link to more results |
| 662 | + if ($this->mInline && $res->hasFurtherResults()) { |
| 663 | + $label = $this->mSearchlabel; |
| 664 | + if ($label === NULL) { //apply defaults |
| 665 | + $label = wfMsgForContent('smw_iq_moreresults'); |
| 666 | + } |
| 667 | + if ($label != '') { |
| 668 | + $result .= $embstart . '<a href="' . $res->getQueryURL() . '">' . $label . '</a>' . $embend ; |
| 669 | + } |
| 670 | + } |
| 671 | + $result .= $footer; |
| 672 | + |
| 673 | + $smwgStoreActive = $old_smwgStoreActive; |
| 674 | + return $result; |
| 675 | + } |
| 676 | +} |
| 677 | + |
| 678 | + |
| 679 | + |
| 680 | + |
| 681 | + |
| 682 | + |
| 683 | + |
| 684 | + |
| 685 | + |
| 686 | + |
| 687 | + |
313 | 688 | /////////////////////////////////////////////////////////////////////////////// |
314 | 689 | /////////////////////////////////////////////////////////////////////////////// |
315 | 690 | /////////////////////////////////////////////////////////////////////////////// |