00001 <?php
00018 class SMWSpecialBrowse extends SpecialPage {
00020 static public $incomingvaluescount = 8;
00022 static public $incomingpropertiescount = 21;
00024 private $subject = null;
00026 private $articletext = "";
00028 private $showoutgoing = true;
00030 private $showincoming = false;
00032 private $offset = 0;
00033
00037 public function __construct() {
00038 global $smwgBrowseShowAll;
00039 parent::__construct( 'Browse', '', true, false, 'default', true );
00040 if ( $smwgBrowseShowAll ) {
00041 SMWSpecialBrowse::$incomingvaluescount = 21;
00042 SMWSpecialBrowse::$incomingpropertiescount = - 1;
00043 }
00044 }
00045
00051 public function execute( $query ) {
00052 global $wgRequest, $wgOut, $smwgBrowseShowAll;
00053 $this->setHeaders();
00054
00055 $this->articletext = $wgRequest->getVal( 'article' );
00056
00057 if ( is_null( $this->articletext ) ) {
00058 $params = SMWInfolink::decodeParameters( $query, false );
00059 reset( $params );
00060 $this->articletext = current( $params );
00061 }
00062
00063 $this->subject = SMWDataValueFactory::newTypeIDValue( '_wpg', $this->articletext );
00064 $offsettext = $wgRequest->getVal( 'offset' );
00065 $this->offset = ( is_null( $offsettext ) ) ? 0 : intval( $offsettext );
00066
00067 $dir = $wgRequest->getVal( 'dir' );
00068
00069 if ( $smwgBrowseShowAll ) {
00070 $this->showoutgoing = true;
00071 $this->showincoming = true;
00072 }
00073
00074 if ( $dir === 'both' || $dir === 'in' ) {
00075 $this->showincoming = true;
00076 }
00077
00078 if ( $dir === 'in' ) {
00079 $this->showoutgoing = false;
00080 }
00081
00082 if ( $dir === 'out' ) {
00083 $this->showincoming = false;
00084 }
00085
00086 $wgOut->addHTML( $this->displayBrowse() );
00087 SMWOutputs::commitToOutputPage( $wgOut );
00088 }
00089
00096 private function displayBrowse() {
00097 global $wgContLang, $wgOut;
00098 $html = "\n";
00099 $leftside = !( $wgContLang->isRTL() );
00100
00101 if ( $this->subject->isValid() ) {
00102 $wgOut->addStyle( '../extensions/SemanticMediaWiki/skins/SMW_custom.css' );
00103
00104 $html .= $this->displayHead();
00105
00106 if ( $this->showoutgoing ) {
00107 $data = smwfGetStore()->getSemanticData( $this->subject->getDataItem() );
00108 $html .= $this->displayData( $data, $leftside );
00109 $html .= $this->displayCenter();
00110 }
00111
00112 if ( $this->showincoming ) {
00113 list( $indata, $more ) = $this->getInData();
00114 global $smwgBrowseShowInverse;
00115
00116 if ( !$smwgBrowseShowInverse ) {
00117 $leftside = !$leftside;
00118 }
00119
00120 $html .= $this->displayData( $indata, $leftside, true );
00121 $html .= $this->displayBottom( $more );
00122 }
00123
00124 $this->articletext = $this->subject->getWikiValue();
00125
00126
00127 if ( !$this->including() ) {
00128 $html .= "<p>   </p>\n";
00129 }
00130 }
00131
00132 if ( !$this->including() ) {
00133 $html .= $this->queryForm();
00134 }
00135
00136 $wgOut->addHTML( $html );
00137 }
00138
00148 private function displayData( SMWSemanticData $data, $left = true, $incoming = false ) {
00149
00150
00151 $ccsPrefix = $left ? 'smwb-' : 'smwb-i';
00152
00153 $html = "<table class=\"{$ccsPrefix}factbox\" cellpadding=\"0\" cellspacing=\"0\">\n";
00154
00155 $diProperties = $data->getProperties();
00156 $noresult = true;
00157 foreach ( $diProperties as $key => $diProperty ) {
00158 $dvProperty = SMWDataValueFactory::newDataItemValue( $diProperty, null );
00159
00160 if ( $dvProperty->isVisible() ) {
00161 $dvProperty->setCaption( $this->getPropertyLabel( $dvProperty, $incoming ) );
00162 $proptext = $dvProperty->getShortHTMLText( smwfGetLinker() ) . "\n";
00163 } elseif ( $diProperty->getKey() == '_INST' ) {
00164 $proptext = smwfGetLinker()->specialLink( 'Categories' );
00165 } elseif ( $diProperty->getKey() == '_REDI' ) {
00166 $proptext = smwfGetLinker()->specialLink( 'Listredirects', 'isredirect' );
00167 } else {
00168 continue;
00169 }
00170
00171 $head = '<th>' . $proptext . "</th>\n";
00172
00173 $body = "<td>\n";
00174
00175 $values = $data->getPropertyValues( $diProperty );
00176
00177 if ( $incoming && ( count( $values ) >= SMWSpecialBrowse::$incomingvaluescount ) ) {
00178 $moreIncoming = true;
00179 array_pop( $values );
00180 } else {
00181 $moreIncoming = false;
00182 }
00183
00184 $first = true;
00185 foreach ( $values as $di ) {
00186 if ( $first ) {
00187 $first = false;
00188 } else {
00189 $body .= ', ';
00190 }
00191
00192 if ( $incoming ) {
00193 $dv = SMWDataValueFactory::newDataItemValue( $di, null );
00194 } else {
00195 $dv = SMWDataValueFactory::newDataItemValue( $di, $diProperty );
00196 }
00197
00198 $body .= "<span class=\"{$ccsPrefix}value\">" .
00199 $this->displayValue( $dvProperty, $dv, $incoming ) . "</span>\n";
00200 }
00201
00202 if ( $moreIncoming ) {
00203 $body .= Html::element(
00204 'a',
00205 array(
00206 'href' => SpecialPage::getSafeTitleFor( 'SearchByProperty' )->getLocalURL( array(
00207 'property' => $dvProperty->getWikiValue(),
00208 'value' => $this->subject->getWikiValue()
00209 ) )
00210 ),
00211 wfMsg( 'smw_browse_more' )
00212 );
00213
00214 }
00215
00216 $body .= "</td>\n";
00217
00218
00219 $html .= "<tr class=\"{$ccsPrefix}propvalue\">\n" .
00220 ( $left ? ( $head . $body ):( $body . $head ) ) . "</tr>\n";
00221 $noresult = false;
00222 }
00223
00224 if ( $noresult ) {
00225 $html .= "<tr class=\"smwb-propvalue\"><th>   </th><td><em>" .
00226 wfMsg( $incoming ? 'smw_browse_no_incoming':'smw_browse_no_outgoing' ) . "</em></td></tr>\n";
00227 }
00228 $html .= "</table>\n";
00229 return $html;
00230 }
00231
00241 private function displayValue( SMWPropertyValue $property, SMWDataValue $dataValue, $incoming ) {
00242 $linker = smwfGetLinker();
00243
00244 $html = $dataValue->getLongHTMLText( $linker );
00245
00246 if ( $dataValue->getTypeID() == '_wpg' ) {
00247 $html .= " " . SMWInfolink::newBrowsingLink( '+', $dataValue->getLongWikiText() )->getHTML( $linker );
00248 } elseif ( $incoming && $property->isVisible() ) {
00249 $html .= " " . SMWInfolink::newInversePropertySearchLink( '+', $dataValue->getTitle(), $property->getDataItem()->getLabel(), 'smwsearch' )->getHTML( $linker );
00250 } else {
00251 $html .= $dataValue->getInfolinkText( SMW_OUTPUT_HTML, $linker );
00252 }
00253
00254 return $html;
00255 }
00256
00262 private function displayHead() {
00263 global $wgOut;
00264
00265 $wgOut->setHTMLTitle( $this->subject->getTitle() );
00266 $html = "<table class=\"smwb-factbox\" cellpadding=\"0\" cellspacing=\"0\">\n" .
00267 "<tr class=\"smwb-title\"><td colspan=\"2\">\n" .
00268 $this->subject->getLongHTMLText( smwfGetLinker() ) . "\n" .
00269 "</td></tr>\n</table>\n";
00270
00271 return $html;
00272 }
00273
00279 private function displayCenter() {
00280 return "<a name=\"smw_browse_incoming\"></a>\n" .
00281 "<table class=\"smwb-factbox\" cellpadding=\"0\" cellspacing=\"0\">\n" .
00282 "<tr class=\"smwb-center\"><td colspan=\"2\">\n" .
00283 ( $this->showincoming ?
00284 $this->linkHere( wfMsg( 'smw_browse_hide_incoming' ), true, false, 0 ):
00285 $this->linkHere( wfMsg( 'smw_browse_show_incoming' ), true, true, $this->offset ) ) .
00286 " \n" . "</td></tr>\n" . "</table>\n";
00287 }
00288
00295 private function displayBottom( $more ) {
00296 $html = "<table class=\"smwb-factbox\" cellpadding=\"0\" cellspacing=\"0\">\n" .
00297 "<tr class=\"smwb-center\"><td colspan=\"2\">\n";
00298 global $smwgBrowseShowAll;
00299 if ( !$smwgBrowseShowAll ) {
00300 if ( ( $this->offset > 0 ) || $more ) {
00301 $offset = max( $this->offset - SMWSpecialBrowse::$incomingpropertiescount + 1, 0 );
00302 $html .= ( $this->offset == 0 ) ? wfMsg( 'smw_result_prev' ):
00303 $this->linkHere( wfMsg( 'smw_result_prev' ), $this->showoutgoing, true, $offset );
00304 $offset = $this->offset + SMWSpecialBrowse::$incomingpropertiescount - 1;
00305 $html .= "     <strong>" . wfMsg( 'smw_result_results' ) . " " . ( $this->offset + 1 ) .
00306 " – " . ( $offset ) . "</strong>     ";
00307 $html .= $more ? $this->linkHere( wfMsg( 'smw_result_next' ), $this->showoutgoing, true, $offset ):wfMsg( 'smw_result_next' );
00308 }
00309 }
00310 $html .= " \n" . "</td></tr>\n" . "</table>\n";
00311 return $html;
00312 }
00313
00324 private function linkHere( $text, $out, $in, $offset ) {
00325 $frag = ( $text == wfMsg( 'smw_browse_show_incoming' ) ) ? '#smw_browse_incoming' : '';
00326
00327 return Html::element(
00328 'a',
00329 array(
00330 'href' => SpecialPage::getSafeTitleFor( 'Browse' )->getLocalURL( array(
00331 'offset' => $offset,
00332 'dir' => $out ? ( $in ? 'both' : 'out' ) : 'in',
00333 'article' => $this->subject->getLongWikiText()
00334 ) ) . $frag
00335 ),
00336 $text
00337 );
00338 }
00339
00346 private function getInData() {
00347 $indata = new SMWSemanticData( $this->subject->getDataItem() );
00348 $options = new SMWRequestOptions();
00349 $options->sort = true;
00350 $options->limit = SMWSpecialBrowse::$incomingpropertiescount;
00351 if ( $this->offset > 0 ) $options->offset = $this->offset;
00352
00353 $inproperties = smwfGetStore()->getInProperties( $this->subject->getDataItem(), $options );
00354
00355 if ( count( $inproperties ) == SMWSpecialBrowse::$incomingpropertiescount ) {
00356 $more = true;
00357 array_pop( $inproperties );
00358 } else {
00359 $more = false;
00360 }
00361
00362 $valoptions = new SMWRequestOptions();
00363 $valoptions->sort = true;
00364 $valoptions->limit = SMWSpecialBrowse::$incomingvaluescount;
00365
00366 foreach ( $inproperties as $property ) {
00367 $values = smwfGetStore()->getPropertySubjects( $property, $this->subject->getDataItem(), $valoptions );
00368 foreach ( $values as $value ) {
00369 $indata->addPropertyObjectValue( $property, $value );
00370 }
00371 }
00372
00373 return array( $indata, $more );
00374 }
00375
00386 private function getPropertyLabel( SMWPropertyValue $property, $incoming = false ) {
00387 global $smwgBrowseShowInverse;
00388
00389 if ( $incoming && $smwgBrowseShowInverse ) {
00390 $oppositeprop = SMWPropertyValue::makeUserProperty( wfMsg( 'smw_inverse_label_property' ) );
00391 $labelarray = &smwfGetStore()->getPropertyValues( $property->getDataItem()->getDiWikiPage(), $oppositeprop->getDataItem() );
00392 $rv = ( count( $labelarray ) > 0 ) ? $labelarray[0]->getLongWikiText():
00393 wfMsg( 'smw_inverse_label_default', $property->getWikiValue() );
00394 } else {
00395 $rv = $property->getWikiValue();
00396 }
00397
00398 return $this->unbreak( $rv );
00399 }
00400
00406 private function queryForm() {
00407 self::addAutoComplete();
00408 $title = SpecialPage::getTitleFor( 'Browse' );
00409 return ' <form name="smwbrowse" action="' . htmlspecialchars( $title->getLocalURL() ) . '" method="get">' . "\n" .
00410 ' <input type="hidden" name="title" value="' . $title->getPrefixedText() . '"/>' .
00411 wfMsg( 'smw_browse_article' ) . "<br />\n" .
00412 ' <input type="text" name="article" id="page_input_box" value="' . htmlspecialchars( $this->articletext ) . '" />' . "\n" .
00413 ' <input type="submit" value="' . wfMsg( 'smw_browse_go' ) . "\"/>\n" .
00414 " </form>\n";
00415 }
00416
00421 private static function addAutoComplete() {
00422 SMWOutputs::requireResource( 'jquery.ui.autocomplete' );
00423
00424 $javascript_autocomplete_text = <<<END
00425 <script type="text/javascript">
00426 jQuery(document).ready(function(){
00427 jQuery("#page_input_box").autocomplete({
00428 minLength: 3,
00429 source: function(request, response) {
00430 jQuery.getJSON(wgScriptPath+'/api.php?action=opensearch&limit=10&namespace=0&format=jsonfm&search='+request.term, function(data){
00431 response(data[1]);
00432 });
00433 }
00434 });
00435 });
00436 </script>
00437
00438 END;
00439
00440 SMWOutputs::requireScript( 'smwAutocompleteSpecialBrowse', $javascript_autocomplete_text );
00441 }
00442
00449 private function unbreak( $text ) {
00450 $nonBreakingSpace = html_entity_decode( ' ', ENT_NOQUOTES, 'UTF-8' );
00451 $text = preg_replace( '/[\s]/u', $nonBreakingSpace, $text, - 1, $count );
00452 return $count > 2 ? preg_replace( '/($nonBreakingSpace)/u', ' ', $text, max( 0, $count - 2 ) ):$text;
00453 }
00454
00455 }