00001 <?php
00011 class SDBrowseData extends IncludableSpecialPage {
00012
00016 public function __construct() {
00017 parent::__construct( 'BrowseData' );
00018 }
00019
00020 function execute( $query ) {
00021 global $wgRequest, $wgOut, $wgTitle;
00022 global $sdgScriptPath, $sdgContLang, $sdgNumResultsPerPage;
00023
00024 if ( $wgTitle->getNamespace() != NS_SPECIAL ) {
00025 global $wgParser;
00026 $wgParser->disableCache();
00027 }
00028 $this->setHeaders();
00029 $wgOut->addExtensionStyle( "$sdgScriptPath/skins/SD_main.css" );
00030 $wgOut->addScript( '<!--[if IE]><link rel="stylesheet" href="' . $sdgScriptPath . '/skins/SD_IEfixes.css" media="screen" /><![endif]-->' );
00031
00032 $javascript_text = <<<END
00033 <script type="text/javascript">
00034 function toggleFilterDiv(element_id, label_element) {
00035 element = document.getElementById(element_id);
00036 if (element.style.display == "none") {
00037 element.style.display = "block";
00038 label_element.innerHTML = "<img src=\"$sdgScriptPath/skins/down-arrow.png\">";
00039 } else {
00040 element.style.display = "none";
00041 label_element.innerHTML = "<img src=\"$sdgScriptPath/skins/right-arrow.png\">";
00042 }
00043 }
00044
00045 function highlightRemoveDiv(element) {
00046 element.innerHTML = "<img src=\"$sdgScriptPath/skins/filter-x-active.png\">";
00047 }
00048 function unhighlightRemoveDiv(element) {
00049 element.innerHTML = "<img src=\"$sdgScriptPath/skins/filter-x.png\">";
00050 }
00051 </script>
00052 END;
00053 $wgOut->addScript( $javascript_text );
00054
00055
00056 if ( $sdgNumResultsPerPage == null )
00057 $sdgNumResultsPerPage = 250;
00058 list( $limit, $offset ) = wfCheckLimits( $sdgNumResultsPerPage, 'sdlimit' );
00059 $filters = array();
00060
00061
00062
00063 $category = str_replace( '_', ' ', $wgRequest->getVal( '_cat' ) );
00064
00065 if ( ! $category ) {
00066 $queryparts = explode( '/', $query, 1 );
00067 $category = isset( $queryparts[0] ) ? $queryparts[0] : '';
00068 }
00069 if ( ! $category ) {
00070 $category_title = wfMsg( 'browsedata' );
00071 } else {
00072 $titles_for_category = SDUtils::getValuesForProperty( $category, NS_CATEGORY, '_SD_DT', SD_SP_HAS_DRILLDOWN_TITLE, NS_MAIN );
00073 if ( count( $titles_for_category ) > 0 ) {
00074 $category_title = str_replace( '_', ' ', $titles_for_category[0] );
00075 } else {
00076 $category_title = wfMsg( 'browsedata' ) . html_entity_decode( wfMsg( 'colon-separator' ) ) . str_replace( '_', ' ', $category );
00077 }
00078 }
00079
00080
00081 if ( ! $category ) {
00082 $categories = SDUtils::getCategoriesForBrowsing();
00083 if ( count( $categories ) > 0 ) {
00084 $category = $categories[0];
00085 }
00086 }
00087
00088 $subcategory = $wgRequest->getVal( '_subcat' );
00089
00090 $filters = SDUtils::loadFiltersForCategory( $category );
00091
00092 $filters_used = array();
00093 foreach ( $filters as $i => $filter )
00094 $filter_used[] = false;
00095 $applied_filters = array();
00096 $remaining_filters = array();
00097 foreach ( $filters as $i => $filter ) {
00098 $filter_name = str_replace( array( ' ', "'" ) , array( '_', "\'" ), $filter->name );
00099 $search_term = $wgRequest->getVal( '_search_' . $filter_name );
00100 $lower_date = $wgRequest->getArray( '_lower_' . $filter_name );
00101 $upper_date = $wgRequest->getArray( '_upper_' . $filter_name );
00102 if ( $vals_array = $wgRequest->getArray( $filter_name ) ) {
00103 foreach ( $vals_array as $j => $val ) {
00104 $vals_array[$j] = str_replace( '_', ' ', $val );
00105 }
00106 $applied_filters[] = SDAppliedFilter::create( $filter, $vals_array );
00107 $filter_used[$i] = true;
00108 } elseif ( $search_term != null ) {
00109 $applied_filters[] = SDAppliedFilter::create( $filter, array(), $search_term );
00110 $filter_used[$i] = true;
00111 } elseif ( $lower_date != null || $upper_date != null ) {
00112 $applied_filters[] = SDAppliedFilter::create( $filter, array(), null, $lower_date, $upper_date );
00113 $filter_used[$i] = true;
00114 }
00115 }
00116
00117
00118 foreach ( $filters as $i => $filter ) {
00119 $required_filters = SDUtils::getValuesForProperty( $filter->name, SD_NS_FILTER, '_SD_RF', SD_SP_REQUIRES_FILTER, SD_NS_FILTER );
00120 $matched_all_required_filters = true;
00121 foreach ( $required_filters as $required_filter ) {
00122 $found_match = false;
00123 foreach ( $applied_filters as $af ) {
00124 if ( $af->filter->name == $required_filter ) {
00125 $found_match = true;
00126 }
00127 }
00128 if ( ! $found_match ) {
00129 $matched_all_required_filters = false;
00130 continue;
00131 }
00132 }
00133 if ( $matched_all_required_filters ) {
00134 if ( ! $filter_used[$i] )
00135 $remaining_filters[] = $filter;
00136 }
00137 }
00138
00139 $wgOut->addHTML( "\n <div class=\"drilldown-results\">\n" );
00140 $rep = new SDBrowseDataPage( $category, $subcategory, $applied_filters, $remaining_filters, $offset, $limit );
00141
00142 if ( method_exists( $rep, 'execute' ) ) {
00143 $num = $rep->execute( $query );
00144 } else {
00145 $num = $rep->doQuery( $offset, $limit );
00146 }
00147 $wgOut->addHTML( "\n </div> <!-- drilldown-results -->\n" );
00148
00149
00150
00151 $wgOut->setPageTitle( $category_title );
00152
00153 return $num;
00154 }
00155 }
00156
00157 class SDBrowseDataPage extends QueryPage {
00158 var $category = "";
00159 var $subcategory = "";
00160 var $next_level_subcategories = array();
00161 var $all_subcategories = array();
00162 var $applied_filters = array();
00163 var $remaining_filters = array();
00164 var $show_single_cat = false;
00165
00169 function __construct( $category, $subcategory, $applied_filters, $remaining_filters, $offset, $limit ) {
00170
00171 if ( $this instanceof SpecialPage ) {
00172 parent::__construct( 'BrowseData' );
00173 }
00174 $this->category = $category;
00175 $this->subcategory = $subcategory;
00176 $this->applied_filters = $applied_filters;
00177 $this->remaining_filters = $remaining_filters;
00178 $this->offset = $offset;
00179 $this->limit = $limit;
00180
00181 $dbr = wfGetDB( DB_SLAVE );
00182 $categorylinks = $dbr->tableName( 'categorylinks' );
00183 $page = $dbr->tableName( 'page' );
00184 $cat_ns = NS_CATEGORY;
00185 if ( $this->subcategory )
00186 $actual_cat = str_replace( ' ', '_', $this->subcategory );
00187 else
00188 $actual_cat = str_replace( ' ', '_', $this->category );
00189
00190
00191
00192 $this->next_level_subcategories = SDUtils::getCategoryChildren( $actual_cat, true, 1 );
00193 $this->all_subcategories = SDUtils::getCategoryChildren( $actual_cat, true, 10 );
00194 }
00195
00196 function makeBrowseURL( $category, $applied_filters = array(), $subcategory = null ) {
00197 $bd = SpecialPage::getTitleFor( 'BrowseData' );
00198 $url = $bd->getLocalURL() . '/' . $category;
00199 if ( $this->show_single_cat ) {
00200 $url .= ( strpos( $url, '?' ) ) ? '&' : '?';
00201 $url .= "_single";
00202 }
00203 if ( $subcategory ) {
00204 $url .= ( strpos( $url, '?' ) ) ? '&' : '?';
00205 $url .= "_subcat=" . $subcategory;
00206 }
00207 foreach ( $applied_filters as $i => $af ) {
00208 if ( count( $af->values ) == 0 ) {
00209
00210 } elseif ( count( $af->values ) == 1 ) {
00211 $url .= ( strpos( $url, '?' ) ) ? '&' : '?';
00212 $url .= urlencode( str_replace( ' ', '_', $af->filter->name ) ) . "=" . urlencode( str_replace( ' ', '_', $af->values[0]->text ) );
00213 } else {
00214 usort( $af->values, array( "SDFilterValue", "compare" ) );
00215 foreach ( $af->values as $j => $fv ) {
00216 $url .= ( strpos( $url, '?' ) ) ? '&' : '?';
00217 $url .= urlencode( str_replace( ' ', '_', $af->filter->name ) ) . "[$j]=" . urlencode( str_replace( ' ', '_', $fv->text ) );
00218 }
00219 }
00220 if ( $af->search_term != null ) {
00221 $url .= ( strpos( $url, '?' ) ) ? '&' : '?';
00222 $url .= '_search_' . urlencode( str_replace( ' ', '_', $af->filter->name ) ) . "=" . urlencode( str_replace( ' ', '_', $af->search_term ) );
00223 }
00224 }
00225 return $url;
00226 }
00227
00233 function createTempTable( $category, $subcategory, $subcategories, $applied_filters ) {
00234 $dbr = wfGetDB( DB_SLAVE );
00235 $sql1 = "CREATE TEMPORARY TABLE semantic_drilldown_values ( id INT NOT NULL )";
00236 $dbr->query( $sql1 );
00237 $sql2 = "CREATE INDEX id_index ON semantic_drilldown_values ( id )";
00238 $dbr->query( $sql2 );
00239 $sql3 = "INSERT INTO semantic_drilldown_values SELECT ids.smw_id AS id\n";
00240 $sql3 .= $this->getSQLFromClause( $category, $subcategory, $subcategories, $applied_filters );
00241 $dbr->query( $sql3 );
00242 }
00243
00250 function getSQLFromClauseForField( $new_filter ) {
00251 $sql = "FROM semantic_drilldown_values sdv
00252 LEFT OUTER JOIN semantic_drilldown_filter_values sdfv
00253 ON sdv.id = sdfv.id
00254 WHERE ";
00255 $sql .= $new_filter->checkSQL( "sdfv.value" );
00256 return $sql;
00257 }
00258
00264 function getSQLFromClauseForCategory( $subcategory, $child_subcategories ) {
00265 $dbr = wfGetDB( DB_SLAVE );
00266 $smw_insts = $dbr->tableName( 'smw_inst2' );
00267 $smw_ids = $dbr->tableName( 'smw_ids' );
00268 $ns_cat = NS_CATEGORY;
00269 $subcategory = str_replace( "'", "\'", $subcategory );
00270 $sql = "FROM semantic_drilldown_values sdv
00271 JOIN $smw_insts inst
00272 ON sdv.id = inst.s_id
00273 WHERE inst.o_id IN
00274 (SELECT smw_id FROM $smw_ids
00275 WHERE smw_namespace = $ns_cat AND (smw_title = '$subcategory' ";
00276 foreach ( $child_subcategories as $i => $subcat ) {
00277 $subcat = str_replace( "'", "\'", $subcat );
00278 $sql .= "OR smw_title = '$subcat' ";
00279 }
00280 $sql .= ")) ";
00281 return $sql;
00282 }
00283
00289 function getSQLFromClause( $category, $subcategory, $subcategories, $applied_filters ) {
00290 $dbr = wfGetDB( DB_SLAVE );
00291 $smw_ids = $dbr->tableName( 'smw_ids' );
00292 $smw_insts = $dbr->tableName( 'smw_inst2' );
00293 $smw_rels = $dbr->tableName( 'smw_rels2' );
00294 $smw_atts = $dbr->tableName( 'smw_atts2' );
00295 $cat_ns = NS_CATEGORY;
00296 $prop_ns = SMW_NS_PROPERTY;
00297
00298 $sql = "FROM $smw_ids ids
00299 JOIN $smw_insts insts
00300 ON ids.smw_id = insts.s_id
00301 AND ids.smw_namespace != $cat_ns ";
00302 foreach ( $applied_filters as $i => $af ) {
00303
00304
00305 $includes_none = false;
00306 foreach ( $af->values as $fv ) {
00307 if ( $fv->text === '_none' || $fv->text === ' none' ) {
00308 $includes_none = true;
00309 break;
00310 }
00311 }
00312 if ( $includes_none ) {
00313 if ( $af->filter->is_relation ) {
00314 $property_table_name = $smw_rels;
00315 $property_table_nickname = "nr$i";
00316 $property_field = 'p_id';
00317 } else {
00318 $property_table_name = $smw_atts;
00319 $property_table_nickname = "na$i";
00320 $property_field = 'p_id';
00321 }
00322 $property_value = str_replace( ' ', '_', $af->filter->property );
00323 $property_value = str_replace( "'", "\'", $property_value );
00324 $sql .= "LEFT OUTER JOIN
00325 (SELECT s_id
00326 FROM $property_table_name
00327 WHERE $property_field = (SELECT smw_id FROM $smw_ids WHERE smw_title = '$property_value' AND smw_namespace = $prop_ns)) $property_table_nickname
00328 ON ids.smw_id = $property_table_nickname.s_id ";
00329 }
00330 }
00331 foreach ( $applied_filters as $i => $af ) {
00332 $sql .= "\n ";
00333 if ( $af->filter->is_relation ) {
00334 if ( $includes_none ) {
00335 $sql .= "LEFT OUTER ";
00336 }
00337 $sql .= "JOIN $smw_rels r$i ON ids.smw_id = r$i.s_id\n ";
00338 if ( $includes_none ) {
00339 $sql .= "LEFT OUTER ";
00340 }
00341 $sql .= "JOIN $smw_ids o_ids$i ON r$i.o_id = o_ids$i.smw_id ";
00342 } else {
00343 $sql .= "JOIN $smw_atts a$i ON ids.smw_id = a$i.s_id ";
00344 }
00345 }
00346 if ( $subcategory ) {
00347 $actual_cat = str_replace( ' ', '_', $subcategory );
00348 } else {
00349 $actual_cat = str_replace( ' ', '_', $category );
00350 }
00351 $actual_cat = str_replace( "'", "\'", $actual_cat );
00352 $sql .= "WHERE insts.o_id IN
00353 (SELECT smw_id FROM $smw_ids cat_ids
00354 WHERE smw_namespace = $cat_ns AND (smw_title = '$actual_cat'";
00355 foreach ( $subcategories as $i => $subcat ) {
00356 $subcat = str_replace( "'", "\'", $subcat );
00357 $sql .= " OR smw_title = '{$subcat}'";
00358 }
00359 $sql .= ")) ";
00360 foreach ( $applied_filters as $i => $af ) {
00361 $property_value = $af->filter->escaped_property;
00362 if ( $af->filter->is_relation ) {
00363 $property_field = "r$i.p_id";
00364 $sql .= "\n AND ($property_field = (SELECT smw_id FROM $smw_ids WHERE smw_title = '$property_value' AND smw_namespace = $prop_ns)";
00365 if ( $includes_none ) {
00366 $sql .= " OR $property_field IS NULL";
00367 }
00368 $sql .= ")\n AND ";
00369 $value_field = "o_ids$i.smw_title";
00370 } else {
00371 $property_field = "a$i.p_id";
00372 $sql .= "\n AND $property_field = (SELECT smw_id FROM $smw_ids WHERE smw_title = '$property_value' AND smw_namespace = $prop_ns) AND ";
00373 $value_field = "a$i.value_xsd";
00374 }
00375 $sql .= $af->checkSQL( $value_field );
00376 }
00377 return $sql;
00378 }
00379
00384 function getNumResults( $subcategory, $subcategories, $new_filter = null ) {
00385 $dbr = wfGetDB( DB_SLAVE );
00386 $sql = "SELECT COUNT(DISTINCT sdv.id) ";
00387 if ( $new_filter )
00388 $sql .= $this->getSQLFromClauseForField( $new_filter );
00389 else
00390 $sql .= $this->getSQLFromClauseForCategory( $subcategory, $subcategories );
00391 $res = $dbr->query( $sql );
00392 $row = $dbr->fetchRow( $res );
00393 $dbr->freeResult( $res );
00394 return $row[0];
00395 }
00396
00397 function getName() {
00398 return "BrowseData";
00399 }
00400
00401 function isExpensive() { return false; }
00402
00403 function isSyndicated() { return false; }
00404
00405 function printCategoriesList( $categories ) {
00406 global $sdgShowCategoriesAsTabs;
00407
00408 $choose_category_text = wfMsg( 'sd_browsedata_choosecategory' ) . wfMsg( 'colon-separator' );
00409 if ( $sdgShowCategoriesAsTabs ) {
00410 $cats_wrapper_class = "drilldown-categories-tabs-wrapper";
00411 $cats_list_class = "drilldown-categories-tabs";
00412 } else {
00413 $cats_wrapper_class = "drilldown-categories-wrapper";
00414 $cats_list_class = "drilldown-categories";
00415 }
00416 $text = <<<END
00417
00418 <div id="$cats_wrapper_class">
00419
00420 END;
00421 if ( $sdgShowCategoriesAsTabs ) {
00422 $text .= <<<END
00423 <p id="categories-header">$choose_category_text</p>
00424 <ul id="$cats_list_class">
00425
00426 END;
00427 } else {
00428 $text .= <<<END
00429 <ul id="$cats_list_class">
00430 <li id="categories-header">$choose_category_text</li>
00431
00432 END;
00433 }
00434 foreach ( $categories as $i => $category ) {
00435 $category_children = SDUtils::getCategoryChildren( $category, false, 5 );
00436 $category_str = $category . " (" . count( array_unique( $category_children ) ) . ")";
00437 if ( str_replace( '_', ' ', $this->category ) == $category ) {
00438 $text .= ' <li class="category selected">';
00439 $text .= $category_str;
00440 } else {
00441 $text .= ' <li class="category">';
00442 $category_url = $this->makeBrowseURL( $category );
00443 $text .= "<a href=\"$category_url\" title=\"$choose_category_text\">$category_str</a>";
00444 }
00445 $text .= "</li>\n";
00446 }
00447 $text .= <<<END
00448 </li>
00449 </ul>
00450 </div>
00451
00452 END;
00453 return $text;
00454 }
00455
00456 function printFilterLabel( $filter_name ) {
00457 $labels_for_filter = SDUtils::getValuesForProperty( $filter_name, SD_NS_FILTER, '_SD_L', SD_SP_HAS_LABEL, NS_MAIN );
00458 if ( count( $labels_for_filter ) > 0 ) {
00459 $filter_label = $labels_for_filter[0];
00460 } else {
00461 $filter_label = str_replace( '_', ' ', $filter_name );
00462 }
00463 return $filter_label;
00464 }
00465
00470 function printFilterValue( $filter, $value ) {
00471 $value = str_replace( '_', ' ', $value );
00472
00473 if ( $value === ' other' )
00474 return wfMsg( 'sd_browsedata_other' );
00475 elseif ( $value === ' none' )
00476 return wfMsg( 'sd_browsedata_none' );
00477 elseif ( $filter->is_boolean )
00478 return SDUtils::booleanToString( $value );
00479 elseif ( $filter->is_date && strpos( $value, '//T' ) )
00480 return str_replace( '//T', '', $value );
00481 else
00482 return $value;
00483 }
00484
00489 function printAppliedFilterLine( $af ) {
00490 global $sdgScriptPath;
00491
00492 $results_line = "";
00493 $filter_label = $this->printFilterLabel( $af->filter->name );
00494 foreach ( $this->applied_filters as $af2 ) {
00495 if ( $af->filter->name == $af2->filter->name )
00496 $current_filter_values = $af2->values;
00497 }
00498 if ( $af->filter->allowed_values != null )
00499 $or_values = $af->filter->allowed_values;
00500 else
00501 $or_values = $af->getAllOrValues( $this->category );
00502 if ( $af->search_term != null ) {
00503
00504
00505 $filter_values = array();
00506 foreach ( $or_values as $or_value ) {
00507 $filter_values[$or_value] = '';
00508 }
00509 $results_line = "<div class=\"drilldown-filter-label\">$filter_label:</div> " . $this->printComboBoxInput( $af->filter->name, $filter_values, $af->search_term );
00510 return $results_line;
00511 } elseif ( $af->lower_date != null || $af->upper_date != null ) {
00512 $results_line = "<div class=\"drilldown-filter-label\">$filter_label:</div> " . $this->printDateRangeInput( $af->filter->name, $af->lower_date, $af->upper_date );
00513 return $results_line;
00514 }
00515
00516
00517 if ( $af->filter->time_period == null )
00518 $or_values[] = '_other';
00519 $or_values[] = '_none';
00520 foreach ( $or_values as $i => $value ) {
00521 if ( $i > 0 ) { $results_line .= " · "; }
00522 $filter_text = $this->printFilterValue( $af->filter, $value );
00523 $applied_filters = $this->applied_filters;
00524 foreach ( $applied_filters as $af2 ) {
00525 if ( $af->filter->name == $af2->filter->name ) {
00526 $or_fv = SDFilterValue::create( $value, $af->filter->time_period );
00527 $af2->values = array_merge( $current_filter_values, array( $or_fv ) );
00528 }
00529 }
00530
00531
00532 $found_match = false;
00533 foreach ( $current_filter_values as $fv ) {
00534 if ( $value == $fv->text ) {
00535 $found_match = true;
00536 break;
00537 }
00538 }
00539 if ( $found_match ) {
00540 $results_line .= "\n $filter_text";
00541 } else {
00542 $filter_url = $this->makeBrowseURL( $this->category, $applied_filters, $this->subcategory );
00543 $results_line .= "\n " . '<a href="' . $filter_url . '" title="' . wfMsg( 'sd_browsedata_filterbyvalue' ) . '">' . $filter_text . '</a>';
00544 }
00545 foreach ( $applied_filters as $af2 ) {
00546 if ( $af->filter->name == $af2->filter->name ) {
00547 $af2->values = $current_filter_values;
00548 }
00549 }
00550 }
00551 $add_another_str = wfMsg( 'sd_browsedata_addanothervalue' );
00552 $results_div_id = strtolower( str_replace( ' ', '_', $filter_label ) ) . "_values";
00553 $text = <<<END
00554 <div class="drilldown-filter-label">
00555 <a onclick="toggleFilterDiv('$results_div_id', this)" style="cursor: default;"><img src="$sdgScriptPath/skins/right-arrow.png"></a>
00556 $filter_label: <span class="drilldown-filter-notes">($add_another_str)</span>
00557 </div>
00558 <div class="drilldown-filter-values" id="$results_div_id" style="display: none;">$results_line
00559 </div>
00560
00561 END;
00562 return $text;
00563 }
00564
00565 function printUnappliedFilterValues( $cur_url, $f, $filter_values ) {
00566 global $sdgFiltersSmallestFontSize, $sdgFiltersLargestFontSize;
00567
00568 $results_line = "";
00569
00570
00571 if ( $sdgFiltersSmallestFontSize > 0 && $sdgFiltersLargestFontSize > 0 ) {
00572 $lowest_num_results = min( $filter_values );
00573 $highest_num_results = max( $filter_values );
00574 $num_results_midpoint = ( $lowest_num_results + $highest_num_results ) / 2;
00575 $font_size_midpoint = ( $sdgFiltersSmallestFontSize + $sdgFiltersLargestFontSize ) / 2;
00576 $num_results_per_font_pixel = ( $highest_num_results + 1 - $lowest_num_results ) / ( $sdgFiltersLargestFontSize + 1 - $sdgFiltersSmallestFontSize );
00577 }
00578
00579 $num_printed_values = 0;
00580 foreach ( $filter_values as $value_str => $num_results ) {
00581 if ( $num_printed_values++ > 0 ) { $results_line .= " · "; }
00582 $filter_text = $this->printFilterValue( $f, $value_str );
00583 $filter_text .= " ($num_results)";
00584 $filter_url = $cur_url . urlencode( str_replace( ' ', '_', $f->name ) ) . '=' . urlencode( str_replace( ' ', '_', $value_str ) );
00585 if ( $sdgFiltersSmallestFontSize > 0 && $sdgFiltersLargestFontSize > 0 ) {
00586 $font_size = round( $font_size_midpoint + ( ( $num_results - $num_results_midpoint ) / $num_results_per_font_pixel ) );
00587 $results_line .= "\n " . '<a href="' . $filter_url . '" title="' . wfMsg( 'sd_browsedata_filterbyvalue' ) . '" style="font-size: ' . $font_size . 'px">' . $filter_text . '</a>';
00588 } else {
00589 $results_line .= "\n " . '<a href="' . $filter_url . '" title="' . wfMsg( 'sd_browsedata_filterbyvalue' ) . '">' . $filter_text . '</a>';
00590 }
00591 }
00592 return $results_line;
00593 }
00594
00599 public static function loadJavascriptAndCSS() {
00600 global $wgOut;
00601 $wgOut->addModules( 'ext.semanticdrilldown.combobox' );
00602 }
00603
00608 function addJavascriptAndCSS() {
00609 global $smwgJQueryIncluded, $smwgJQueryUIIncluded, $sdgScriptPath, $wgOut;
00610
00611 $wgOut->addExtensionStyle( "$sdgScriptPath/skins/jquery-ui/base/jquery.ui.all.css" );
00612
00613 $scripts = array();
00614 if ( !$smwgJQueryIncluded ) {
00615 $scripts[] = "$sdgScriptPath/libs/jquery-1.4.2.min.js";
00616 $smwgJQueryIncluded = true;
00617 };
00618
00619 if ( !$smwgJQueryUIIncluded ) {
00620 $scripts[] = "$sdgScriptPath/libs/jquery-ui/jquery.ui.core.min.js";
00621 $scripts[] = "$sdgScriptPath/libs/jquery-ui/jquery.ui.widget.min.js";
00622 }
00623 $scripts[] = "$sdgScriptPath/libs/jquery-ui/jquery.ui.button.min.js";
00624 if ( !$smwgJQueryUIIncluded ) {
00625 $scripts[] = "$sdgScriptPath/libs/jquery-ui/jquery.ui.position.min.js";
00626 $scripts[] = "$sdgScriptPath/libs/jquery-ui/jquery.ui.autocomplete.min.js";
00627 $smwgJQueryUIIncluded = true;
00628 }
00629 $scripts[] = "$sdgScriptPath/libs/SemanticDrilldown.js";
00630
00631 foreach ( $scripts as $script ) {
00632 $wgOut->addScriptFile( $script );
00633 }
00634 }
00635
00636 function printComboBoxInput( $filter_name, $filter_values, $cur_value = null ) {
00637 global $wgRequest, $sdgJQueryIncluded, $wgOut;
00638
00639
00640 if ( class_exists( 'ResourceLoader' ) ) {
00641 self::loadJavascriptAndCSS();
00642 } elseif ( !$sdgJQueryIncluded ) {
00643 $sdgJQueryIncluded = true;
00644 self::addJavascriptAndCSS();
00645 }
00646
00647 $filter_name = str_replace( ' ', '_', $filter_name );
00648
00649
00650 $filter_name = urldecode( $filter_name );
00651 $input_id = "_search_$filter_name";
00652 $combobox_id = "c_search_$filter_name";
00653
00654 $combobox_js =<<<END
00655 <script type="text/javascript">
00656 jQuery(document).ready(function(){
00657 jQuery("#$combobox_id").combobox();
00658 });
00659 </script>
00660 END;
00661 $wgOut->addScript( $combobox_js );
00662
00663 $text =<<< END
00664 <form method="get">
00665 <div class="ui-widget">
00666 <select id="$combobox_id" name="$cur_value">
00667 <option value="$input_id"></option>;
00668
00669 END;
00670 foreach ( $filter_values as $value => $num_instances ) {
00671 if ( $value != '_other' && $value != '_none' ) {
00672 $display_value = str_replace( '_', ' ', $value );
00673 $text .= "\t\t" . Html::element( 'option', array( 'value' => $display_value ), $display_value ) . "\n";
00674 }
00675 }
00676
00677 $text .=<<<END
00678 </select>
00679 </div>
00680
00681 END;
00682
00683 foreach ( $wgRequest->getValues() as $key => $val ) {
00684 if ( $key != $input_id ) {
00685 $text .= Html::hidden( $key, $val ) . "\n";
00686 }
00687 }
00688 $text .= Html::input( null, wfMsg( 'searchresultshead' ), 'submit' ) . "\n";
00689 $text .= "</form>\n";
00690 return $text;
00691 }
00692
00693 function printDateInput( $input_name, $cur_value = null ) {
00694 $month_names = array(
00695 wfMsgForContent( 'january' ),
00696 wfMsgForContent( 'february' ),
00697 wfMsgForContent( 'march' ),
00698 wfMsgForContent( 'april' ),
00699
00700 wfMsgForContent( 'may_long' ),
00701 wfMsgForContent( 'june' ),
00702 wfMsgForContent( 'july' ),
00703 wfMsgForContent( 'august' ),
00704 wfMsgForContent( 'september' ),
00705 wfMsgForContent( 'october' ),
00706 wfMsgForContent( 'november' ),
00707 wfMsgForContent( 'december' )
00708 );
00709
00710 if ( is_array( $cur_value ) && array_key_exists( 'month', $cur_value ) )
00711 $selected_month = $cur_value['month'];
00712 else
00713 $selected_month = null;
00714 $text = ' <select name="' . $input_name . "[month]\">\n";
00715 global $wgAmericanDates;
00716 foreach ( $month_names as $i => $name ) {
00717
00718 $month_value = ( $wgAmericanDates == true ) ? $name : str_pad( $i + 1, 2, "0", STR_PAD_LEFT );
00719 $selected_str = ( $i + 1 == $selected_month ) ? "selected" : "";
00720 $text .= "\t<option value=\"$month_value\" $selected_str>$name</option>\n";
00721 }
00722 $text .= "\t</select>\n";
00723 $text .= '<input name="' . $input_name . '[day]" type="text" size="2" value="' . $cur_value['day'] . '" />' . "\n";
00724 $text .= '<input name="' . $input_name . '[year]" type="text" size="4" value="' . $cur_value['year'] . '" />' . "\n";
00725 return $text;
00726 }
00727
00728 function printDateRangeInput( $filter_name, $lower_date = null, $upper_date = null ) {
00729 global $wgRequest;
00730
00731 $start_label = wfMsg( 'sd_browsedata_daterangestart' );
00732 $end_label = wfMsg( 'sd_browsedata_daterangeend' );
00733 $start_month_input = $this->printDateInput( "_lower_$filter_name", $lower_date );
00734 $end_month_input = $this->printDateInput( "_upper_$filter_name", $upper_date );
00735 $text = <<<END
00736 <form method="get">
00737 <p>$start_label $start_month_input
00738 $end_label $end_month_input</p>
00739
00740 END;
00741 foreach ( $wgRequest->getValues() as $key => $val ) {
00742 $text .= Html::hidden( $key, $val ) . "\n";
00743 }
00744 $submitButton = Html::input( null, wfMsg( 'searchresultshead' ), 'submit' );
00745 $text .= Html::rawElement( 'p', null, $submitButton ) . "\n";
00746 $text .= "</form>\n";
00747 return $text;
00748 }
00749
00754 function printUnappliedFilterLine( $f, $cur_url ) {
00755 global $sdgScriptPath;
00756 global $sdgFiltersSmallestFontSize, $sdgFiltersLargestFontSize;
00757
00758 $f->createTempTable();
00759 $found_results_for_filter = false;
00760 if ( count( $f->allowed_values ) == 0 ) {
00761 $filter_values = $f->getAllValues();
00762 if ( count( $filter_values ) > 0 ) {
00763 $found_results_for_filter = true;
00764 }
00765 } else {
00766 $filter_values = array();
00767 foreach ( $f->allowed_values as $value ) {
00768 $new_filter = SDAppliedFilter::create( $f, $value );
00769 $num_results = $this->getNumResults( $this->subcategory, $this->all_subcategories, $new_filter );
00770 if ( $num_results > 0 ) {
00771 $filter_values[$value] = $num_results;
00772 }
00773 }
00774 }
00775
00776
00777
00778 if ( count( $f->allowed_values ) > 0 ) {
00779 $other_filter = SDAppliedFilter::create( $f, ' other' );
00780 $num_results = $this->getNumResults( $this->subcategory, $this->all_subcategories, $other_filter );
00781 if ( $num_results > 0 ) {
00782 $filter_values['_other'] = $num_results;
00783 }
00784 }
00785
00786
00787 if ( count( $f->allowed_values ) > 0 ) {
00788 $fv = SDFilterValue::create( $f->allowed_values[0] );
00789 if ( ! $fv->is_numeric ) {
00790 $none_filter = SDAppliedFilter::create( $f, ' none' );
00791 $num_results = $this->getNumResults( $this->subcategory, $this->all_subcategories, $none_filter );
00792 if ( $num_results > 0 ) {
00793 $filter_values['_none'] = $num_results;
00794 }
00795 }
00796 }
00797
00798 $filter_name = urlencode( str_replace( ' ', '_', $f->name ) );
00799 $normal_filter = true;
00800 if ( count( $filter_values ) == 0 ) {
00801 $results_line = '(' . wfMsg( 'sd_browsedata_novalues' ) . ')';
00802
00803
00804
00805 } elseif ( $f->input_type == wfMsgForContent( 'sd_filter_combobox' ) ||
00806 $f->input_type == wfMsgForContent( 'sd_filter_freetext' ) ) {
00807 $results_line = $this->printComboBoxInput( $filter_name, $filter_values );
00808 $normal_filter = false;
00809 } elseif ( $f->input_type == wfMsgForContent( 'sd_filter_daterange' ) ) {
00810 $results_line = $this->printDateRangeInput( $filter_name );
00811 $normal_filter = false;
00812 } else {
00813 $results_line = $this->printUnappliedFilterValues( $cur_url, $f, $filter_values );
00814 }
00815
00816 $text = "";
00817 $filter_label = $this->printFilterLabel( $f->name );
00818 $results_div_id = strtolower( str_replace( ' ', '_', $filter_label ) ) . "_values";
00819 $text .= <<<END
00820 <div class="drilldown-filter-label">
00821
00822 END;
00823
00824
00825 if ( $normal_filter ) {
00826 $text .= <<<END
00827 <a onclick="toggleFilterDiv('$results_div_id', this)" style="cursor: default;"><img src="$sdgScriptPath/skins/down-arrow.png"></a>
00828
00829 END;
00830 }
00831 $text .= <<<END
00832 $filter_label:
00833 </div>
00834 <div class="drilldown-filter-values" id="$results_div_id">$results_line
00835 </div>
00836
00837 END;
00838 $f->dropTempTable();
00839 return $text;
00840 }
00841
00842 function getPageHeader() {
00843 global $wgRequest;
00844 global $sdgContLang, $sdgScriptPath;
00845 global $sdgFiltersSmallestFontSize, $sdgFiltersLargestFontSize;
00846
00847 $categories = SDUtils::getCategoriesForBrowsing();
00848
00849 if ( count( $categories ) == 0 ) {
00850 return "";
00851 }
00852 $subcategory_text = wfMsg( 'sd_browsedata_subcategory' );
00853
00854 $header = "";
00855 $this->show_single_cat = $wgRequest->getCheck( '_single' );
00856 if ( ! $this->show_single_cat ) {
00857 $header .= $this->printCategoriesList( $categories );
00858 }
00859
00860
00861
00862 if ( ( count( $this->next_level_subcategories ) == 0 ) &&
00863 ( count( $this->applied_filters ) == 0 ) &&
00864 ( count( $this->remaining_filters ) == 0 ) ) {
00865 return $header;
00866 }
00867 $header .= ' <div id="drilldown-header">' . "\n";
00868 if ( count ( $this->applied_filters ) > 0 || $this->subcategory ) {
00869 $category_url = $this->makeBrowseURL( $this->category );
00870 $header .= '<a href="' . $category_url . '" title="' . wfMsg( 'sd_browsedata_resetfilters' ) . '">' . str_replace( '_', ' ', $this->category ) . '</a>';
00871 } else
00872 $header .= str_replace( '_', ' ', $this->category );
00873 if ( $this->subcategory ) {
00874 $header .= " > ";
00875 $header .= "$subcategory_text: ";
00876 $subcat_string = str_replace( '_', ' ', $this->subcategory );
00877 $remove_filter_url = $this->makeBrowseURL( $this->category, $this->applied_filters );
00878 $header .= "\n" . ' <span class="drilldown-header-value">' . $subcat_string . '</span> <a href="' . $remove_filter_url . '" title="' . wfMsg( 'sd_browsedata_removesubcategoryfilter' ) . '"><img src="' . $sdgScriptPath . '/skins/filter-x.png" /></a> ';
00879 }
00880 foreach ( $this->applied_filters as $i => $af ) {
00881 $header .= ( ! $this->subcategory && $i == 0 ) ? " > " : "\n <span class=\"drilldown-header-value\">&</span> ";
00882 $filter_label = $this->printFilterLabel( $af->filter->name );
00883
00884
00885 if ( count( $this->applied_filters[$i]->values ) > 1 ) {
00886 $temp_filters_array = $this->applied_filters;
00887 array_splice( $temp_filters_array, $i, 1 );
00888 $remove_filter_url = $this->makeBrowseURL( $this->category, $temp_filters_array, $this->subcategory );
00889 array_splice( $temp_filters_array, $i, 0 );
00890 $header .= $filter_label . ' <a href="' . $remove_filter_url . '" title="' . wfMsg( 'sd_browsedata_removefilter' ) . '"><img src="' . $sdgScriptPath . '/skins/filter-x.png" /></a> : ';
00891 } else {
00892 $header .= "$filter_label: ";
00893 }
00894 foreach ( $af->values as $j => $fv ) {
00895 if ( $j > 0 ) { $header .= ' <span class="drilldown-or">' . wfMsg( 'sd_browsedata_or' ) . '</span> '; }
00896 $filter_text = $this->printFilterValue( $af->filter, $fv->text );
00897 $temp_filters_array = $this->applied_filters;
00898 $removed_values = array_splice( $temp_filters_array[$i]->values, $j, 1 );
00899 $remove_filter_url = $this->makeBrowseURL( $this->category, $temp_filters_array, $this->subcategory );
00900 array_splice( $temp_filters_array[$i]->values, $j, 0, $removed_values );
00901 $header .= "\n " . ' <span class="drilldown-header-value">' . $filter_text . '</span> <a href="' . $remove_filter_url . '" title="' . wfMsg( 'sd_browsedata_removefilter' ) . '"><img src="' . $sdgScriptPath . '/skins/filter-x.png" /></a>';
00902 }
00903 if ( $af->search_term != null ) {
00904 $temp_filters_array = $this->applied_filters;
00905 $removed_search_term = $temp_filters_array[$i]->search_term;
00906 $temp_filters_array[$i]->search_term = null;
00907 $remove_filter_url = $this->makeBrowseURL( $this->category, $temp_filters_array, $this->subcategory );
00908 $temp_filters_array[$i]->search_term = $removed_search_term;
00909 $header .= "\n\t" . '<span class="drilldown-header-value">~ \'' . $af->search_term . '\'</span> <a href="' . $remove_filter_url . '" title="' . wfMsg( 'sd_browsedata_removefilter' ) . '"><img src="' . $sdgScriptPath . '/skins/filter-x.png" /> </a>';
00910 } elseif ( $af->lower_date != null || $af->upper_date != null ) {
00911 $header .= "\n\t<span class=\"drilldown-header-value\">" . $af->lower_date_string . " - " . $af->upper_date_string . "</span>";
00912 }
00913 }
00914 $header .= "</div>\n";
00915 $drilldown_description = wfMsg( 'sd_browsedata_docu' );
00916 $header .= " <p>$drilldown_description</p>\n";
00917 // display the list of subcategories on one line, and below
00918 // it every filter, each on its own line; each line will
00919 // contain the possible values, and, in parentheses, the
00920 // number of pages that match that value
00921 $header .= " <div class=\"drilldown-filters\">\n";
00922 $cur_url = $this->makeBrowseURL( $this->category, $this->applied_filters, $this->subcategory );
00923 $cur_url .= ( strpos( $cur_url, '?' ) ) ? '&' : '?';
00924 $this->createTempTable( $this->category, $this->subcategory, $this->all_subcategories, $this->applied_filters );
00925 $num_printed_values = 0;
00926 if ( count( $this->next_level_subcategories ) > 0 ) {
00927 $results_line = "";
00928 // loop through to create an array of subcategory
00929 // names and their number of values, then loop through
00930 // the array to print them - we loop through twice,
00931 // instead of once, to be able to print a tag-cloud
00932 // display if necessary
00933 $subcat_values = array();
00934 foreach ( $this->next_level_subcategories as $i => $subcat ) {
00935 $further_subcats = SDUtils::getCategoryChildren( $subcat, true, 10 );
00936 $num_results = $this->getNumResults( $subcat, $further_subcats );
00937 $subcat_values[$subcat] = $num_results;
00938 }
00939 // get necessary values for creating the tag cloud,
00940 // if appropriate
00941 if ( $sdgFiltersSmallestFontSize > 0 && $sdgFiltersLargestFontSize > 0 ) {
00942 $lowest_num_results = min( $subcat_values );
00943 $highest_num_results = max( $subcat_values );
00944 $num_results_midpoint = ( $lowest_num_results + $highest_num_results ) / 2;
00945 $font_size_midpoint = ( $sdgFiltersSmallestFontSize + $sdgFiltersLargestFontSize ) / 2;
00946 $num_results_per_font_pixel = ( $highest_num_results + 1 - $lowest_num_results ) /
00947 ( $sdgFiltersLargestFontSize + 1 - $sdgFiltersSmallestFontSize );
00948 }
00949
00950 foreach ( $subcat_values as $subcat => $num_results ) {
00951 if ( $num_results > 0 ) {
00952 if ( $num_printed_values++ > 0 ) { $results_line .= " · "; }
00953 $filter_text = str_replace( '_', ' ', $subcat ) . " ($num_results)";
00954 $filter_url = $cur_url . '_subcat=' . urlencode( $subcat );
00955 if ( $sdgFiltersSmallestFontSize > 0 && $sdgFiltersLargestFontSize > 0 ) {
00956 $font_size = round( $font_size_midpoint + ( ( $num_results - $num_results_midpoint ) / $num_results_per_font_pixel ) );
00957 $results_line .= "\n " . '<a href="' . $filter_url . '" title="' . wfMsg( 'sd_browsedata_filterbysubcategory' ) . '" style="font-size: ' . $font_size . 'px">' . $filter_text . '</a>';
00958 } else {
00959 $results_line .= "\n " . '<a href="' . $filter_url . '" title="' . wfMsg( 'sd_browsedata_filterbysubcategory' ) . '">' . $filter_text . '</a>';
00960 }
00961 }
00962 }
00963 if ( $results_line != "" ) {
00964 $header .= " <p><strong>$subcategory_text:</strong> $results_line</p>\n";
00965 }
00966 }
00967 $filters = SDUtils::loadFiltersForCategory( $this->category );
00968 foreach ( $filters as $f ) {
00969 foreach ( $this->applied_filters as $af ) {
00970 if ( $af->filter->name == $f->name )
00971 $header .= $this->printAppliedFilterLine( $af );
00972 }
00973 foreach ( $this->remaining_filters as $rf ) {
00974 if ( $rf->name == $f->name )
00975 $header .= $this->printUnappliedFilterLine( $rf, $cur_url );
00976 }
00977 }
00978 $header .= " </div> <!-- drilldown-filters -->\n";
00979 return $header;
00980 }
00981
00985 function linkParameters() {
00986 $params = array();
00987 if ( $this->show_single_cat )
00988 $params['_single'] = null;
00989 $params['_cat'] = $this->category;
00990 if ( $this->subcategory )
00991 $params['_subcat'] = $this->subcategory;
00992 foreach ( $this->applied_filters as $i => $af ) {
00993 if ( count( $af->values ) == 1 ) {
00994 $key_string = str_replace( ' ', '_', $af->filter->name );
00995 $value_string = str_replace( ' ', '_', $af->values[0]->text );
00996 $params[$key_string] = $value_string;
00997 } else {
00998 // HACK - QueryPage's pagination-URL code,
00999
01000
01001
01002
01003 foreach ( $af->values as $i => $value ) {
01004 $key_string = str_replace( ' ', '_', $af->filter->name . "[$i]" );
01005 $value_string = str_replace( ' ', '_', $value->text );
01006 $params[$key_string] = $value_string;
01007 }
01008 }
01009 }
01010 return $params;
01011 }
01012
01013 function getSQL() {
01014
01015
01016 $sql = "SELECT DISTINCT ids.smw_title AS title,
01017 ids.smw_title AS value,
01018 ids.smw_title AS t,
01019 ids.smw_namespace AS namespace,
01020 ids.smw_namespace AS ns,
01021 ids.smw_id AS id,
01022 ids.smw_iw AS iw,
01023 ids.smw_sortkey AS sortkey\n";
01024 $sql .= $this->getSQLFromClause( $this->category, $this->subcategory, $this->all_subcategories, $this->applied_filters );
01025 return $sql;
01026 }
01027
01028 function getOrder() {
01029 return ' ORDER BY sortkey ';
01030 }
01031
01032 function getOrderFields() {
01033 return array( 'sortkey' );
01034 }
01035
01036 function sortDescending() {
01037 return false;
01038 }
01039
01040 function formatResult( $skin, $result ) {
01041 $title = Title::makeTitle( $result->namespace, $result->value );
01042 return $skin->makeLinkObj( $title, htmlspecialchars( $title->getText() ) );
01043 }
01044
01056 protected function outputResults( $out, $skin, $dbr, $res, $num, $offset ) {
01057 global $wgContLang;
01058
01059 $all_display_params = SDUtils::getDisplayParamsForCategory( $this->category );
01060 $querystring = null;
01061 $printouts = $params = array();
01062
01063 if ( count( $all_display_params ) > 0 ) {
01064 $display_params = array_map( 'trim', $all_display_params[0] );
01065 SMWQueryProcessor::processFunctionParams( $display_params, $querystring, $params, $printouts );
01066 }
01067 if ( ! empty( $querystring ) ) {
01068 $query = SMWQueryProcessor::createQuery( $querystring, $params );
01069 } else {
01070 $query = new SMWQuery();
01071 }
01072 if ( !array_key_exists( 'format', $params ) ) {
01073 $params['format'] = 'category';
01074 }
01075
01076 if ( array_key_exists( 'mainlabel', $params ) ) {
01077 $mainlabel = $params['mainlabel'];
01078 } else {
01079 $mainlabel = '';
01080 }
01081
01082 $r = $this->addSemanticResultWrapper( $dbr, $res, $num, $query, $mainlabel, $printouts );
01083 $printer = SMWQueryProcessor::getResultPrinter( $params['format'], SMWQueryProcessor::SPECIAL_PAGE, $r );
01084
01085 if ( version_compare( SMW_VERSION, '1.6.1', '>' ) ) {
01086 SMWQueryProcessor::addThisPrintout( $printouts, $params );
01087 $params = SMWQueryProcessor::getProcessedParams( $params, $printouts );
01088 }
01089
01090 $prresult = $printer->getResult(
01091 $r,
01092 $params,
01093 SMW_OUTPUT_HTML
01094 );
01095
01096 $prtext = is_array( $prresult ) ? $prresult[0] : $prresult;
01097
01098 SMWOutputs::commitToOutputPage( $out );
01099
01100
01101
01102
01103
01104 global $wgParser;
01105 SMWOutputs::commitToParser( $wgParser );
01106 if ( ! is_null( $wgParser->mOutput ) ) {
01107 $headItems = $wgParser->getOutput()->getHeadItems();
01108 foreach ( $headItems as $key => $item ) {
01109 $out->addHeadItem( $key, $item );
01110 }
01111
01112 $wgParser->replaceLinkHolders( $prtext );
01113 }
01114
01115 $html = array();
01116 $html[] = $prtext;
01117
01118 if ( !$this->listoutput ) {
01119 $html[] = $this->closeList();
01120 }
01121
01122 $html = $this->listoutput
01123 ? $wgContLang->listToText( $html )
01124 : implode( '', $html );
01125
01126 $out->addHTML( $html );
01127 }
01128
01129
01130
01131
01132
01133
01134 function addSemanticResultWrapper( $dbr, $res, $num, $query, $mainlabel, $printouts ) {
01135 $qr = array();
01136 $count = 0;
01137 $store = smwfGetStore();
01138 while ( ( $count < $num ) && ( $row = $dbr->fetchObject( $res ) ) ) {
01139 $count++;
01140 if ( class_exists( 'SMWDIWikiPage' ) ) {
01141
01142 $qr[] = new SMWDIWikiPage( $row->t, $row->ns, null );
01143 } else {
01144 $qr[] = SMWWikiPageValue::makePage( $row->t, $row->ns, $row->sortkey );
01145 }
01146 if ( method_exists( $store, 'cacheSMWPageID' ) ) {
01147 if ( method_exists( 'SMWDIWikiPage', 'getSubobjectName' ) ) {
01148
01149 $store->cacheSMWPageID( $row->id, $row->t, $row->ns, $row->iw, '' );
01150 } else {
01151 $store->cacheSMWPageID( $row->id, $row->t, $row->ns, $row->iw );
01152 }
01153 }
01154 }
01155 if ( $dbr->fetchObject( $res ) ) {
01156 $count++;
01157 }
01158 $dbr->freeResult( $res );
01159
01160 $printrequest = new SMWPrintRequest( SMWPrintRequest::PRINT_THIS, $mainlabel );
01161 $main_printout = array();
01162 $main_printout[$printrequest->getHash()] = $printrequest;
01163 $printouts = array_merge( $main_printout, $printouts );
01164
01165 return new SMWQueryResult( $printouts, $query, $qr, $store, ( $count > $num ) );
01166 }
01167
01168 function openList( $offset ) {
01169 }
01170
01171 function closeList() {
01172 return "\n <br style=\"clear: both\" />\n";
01173 }
01174 }