"text", "_num" => "number", "_dat" => "date", "_geo" => "text", "_uri" => "url" ]; protected static $exhibitRunningNumber = 0; // not sufficient since there might be multiple pages rendered within one PHP run; but good enough now // /overwrite function to allow execution of result printer even if no results are available (in case remote query yields no results in local wiki) public function getResult( $results, $params, $outputmode ) { $this->readParameters( $params, $outputmode ); $result = $this->getResultText( $results, $outputmode ); return $result; } // /function aligns the format of SMW's property names to Exhibit's format protected function encodePropertyName( $property ) { return strtolower( str_replace( " ", "_", trim( $property ) ) ); } // /Tries to determine the namespace in the event it got lost protected function determineNamespace( $res ) { $row = $res->getNext(); if ( $row != null ) { $tmp = clone $row[0]; $object = $tmp->getNextDataValue(); if ( $object instanceof SMWWikiPageValue ) { $value = $object->getPrefixedText(); if ( strpos( $value, ':' ) ) { $value = explode( ':', $value, 2 ); return $value[0] . ':'; } } } return ""; } protected function getResultText( SMWQueryResult $res, $outputmode ) { global $smwgIQRunningNumber, $wgScriptPath, $wgGoogleMapsKey, $srfgScriptPath; if ( defined( 'MW_SUPPORTS_RESOURCE_MODULES' ) ) { SMWOutputs::requireHeadItem( 'exhibit-compat', Html::linkedScript( "$wgScriptPath/common/wikibits.js" ) ); } // ////////////////////////////// // ///////REMOTE STUFF/////////// // ////////////////////////////// $remote = false; // in case the remote parameter is set, a link to the JSON export of the remote wiki is included in the header as data source for Exhibit // this section creates the link if ( array_key_exists( 'remote', $this->params ) && srfgExhibitRemote == true ) { $remote = true; // fetch interwiki link $dbr = &wfGetDB( DB_SLAVE ); $cl = $dbr->tableName( 'interwiki' ); $dbres = $dbr->select( $cl, 'iw_url', "iw_prefix='" . $this->params['remote'] . "'", __METHOD__, [] ); $row = $dbr->fetchRow( $dbres ); $extlinkpattern = $row[iw_url]; $dbr->freeResult( $dbres ); $newheader = 'getPrintRequests() as $pr ) { $colstack[] = $this->encodePropertyName( $pr->getLabel() ) . ':' . ( array_key_exists( $pr->getTypeID(), $this->m_types ) ? $this->m_types[$pr->getTypeID()] : 'text' ); } array_shift( $colstack ); array_unshift( $colstack, 'label' ); if ( SRFExhibit::$exhibitRunningNumber == 0 ) { $sourcesrc = "var ex_sources = { source" . ( $smwgIQRunningNumber - 1 ) . ": { id: 'querytable" . $smwgIQRunningNumber . "' , columns: '" . implode( ',', $colstack ) . "'.split(','), hideTable: '1', type: 'Item', label: 'Item', pluralLabel: 'Items' } };"; } else { $sourcesrc = "sources.source" . $smwgIQRunningNumber . " = { id: 'querytable" . $smwgIQRunningNumber . "' , columns: '" . implode( ',', $colstack ) . "'.split(','), hideTable: '1', type: 'Item', label: 'Item', pluralLabel: 'Items' };"; } $sourcesrc = ""; // prepare facets $facetcounter = 0; if ( array_key_exists( 'facets', $this->params ) ) { $facets = explode( ',', $this->params['facets'] ); $facetstack = []; $params = [ 'height' ]; $facparams = []; foreach ( $params as $param ) { if ( array_key_exists( $param, $this->params ) ) { $facparams[] = 'ex:' . $param . '="' . $this->encodePropertyName( $this->params[$param] ) . '" '; } } foreach ( $facets as $facet ) { $facet = trim( $facet ); if ( strtolower( $facet ) == "search" ) { // special facet (text search) $facetstack[] = ' facet' . $facetcounter++ . ': { position : "right", innerHTML: \'ex:role="facet" ex:showMissing="false" ex:facetClass="TextSearch" ex:facetLabel="' . $facet . '"\'}'; } else { // usual facet foreach ( $res->getPrintRequests() as $pr ) { if ( $this->encodePropertyName( $pr->getLabel() ) == $this->encodePropertyName( $facet ) ) { switch ( $pr->getTypeID() ) { case '_num': $facetstack[] = ' facet' . $facetcounter++ . ': { position : "right", innerHTML: \'ex:role="facet" ex:showMissing="false" ex:expression=".' . $this->encodePropertyName( $facet ) . '" ex:facetLabel="' . $facet . '" ex:facetClass="Slider"\'}'; break; default: $facetstack[] = ' facet' . $facetcounter++ . ': { position : "right", innerHTML: \'ex:role="facet" ex:showMissing="false" ' . implode( " ", $facparams ) . ' ex:expression=".' . $this->encodePropertyName( $facet ) . '" ex:facetLabel="' . $facet . '"\'}'; } } } } } $facetstring = implode( ',', $facetstack ); } else { $facetstring = ''; } $facetsrc = "var ex_facets = {" . $facetstring . " };"; // prepare views $stylesrc = ''; if ( array_key_exists( 'views', $this->params ) ) { $views = explode( ',', $this->params['views'] ); } else { $views[] = 'tiles'; } foreach ( $views as $view ) { switch ( trim( $view ) ) { case 'tabular':// table view (the columns are automatically defined by the selected properties) $thstack = []; foreach ( $res->getPrintRequests() as $pr ) { $thstack[] = "." . $this->encodePropertyName( $pr->getLabel() ); } array_shift( $thstack ); array_unshift( $thstack, '.label' ); $stylesrc = 'var myStyler = function(table, database) {table.className=\'smwtable\';};'; // assign SMWtable CSS to Exhibit tabular view $viewstack[] = 'ex:role=\'view\' ex:viewClass=\'Tabular\' ex:showSummary=\'false\' ex:sortAscending=\'true\' ex:tableStyler=\'myStyler\' ex:label=\'Table\' ex:columns=\'' . implode( ',', $thstack ) . '\' ex:sortAscending=\'false\''; break; case 'timeline':// timeline view $timeline = true; $exparams = [ 'start', 'end', 'proxy', 'colorkey' ]; // parameters expecting an Exhibit graph expression $usparams = [ 'timelineheight', 'topbandheight', 'bottombandheight', 'bottombandunit', 'topbandunit' ]; // parametes expecting a textual or numeric value $tlparams = []; foreach ( $exparams as $param ) { if ( array_key_exists( $param, $this->params ) ) { $tlparams[] = 'ex:' . $param . '=\'.' . $this->encodePropertyName( $this->params[$param] ) . '\' '; } } foreach ( $usparams as $param ) { if ( array_key_exists( $param, $this->params ) ) { $tlparams[] = 'ex:' . $param . '=\'' . $this->encodePropertyName( $this->params[$param] ) . '\' '; } } if ( !array_key_exists( 'start', $this->params ) ) {// find out if a start and/or end date is specified $dates = []; foreach ( $res->getPrintRequests() as $pr ) { if ( $pr->getTypeID() == '_dat' ) { $dates[] = $pr; if ( sizeof( $dates ) > 2 ) { break; } } } if ( sizeof( $dates ) == 1 ) { $tlparams[] = 'ex:start=\'.' . $this->encodePropertyName( $dates[0]->getLabel() ) . '\' '; } elseif ( sizeof( $dates ) == 2 ) { $tlparams[] = 'ex:start=\'.' . $this->encodePropertyName( $dates[0]->getLabel() ) . '\' '; $tlparams[] = 'ex:end=\'.' . $this->encodePropertyName( $dates[1]->getLabel() ) . '\' '; } } $viewstack[] = 'ex:role=\'view\' ex:viewClass=\'Timeline\' ex:label=\'Timeline\' ex:showSummary=\'false\' ' . implode( " ", $tlparams ); break; case 'map':// map view if ( isset( $wgGoogleMapsKey ) ) { $map = true; $exparams = [ 'latlng', 'colorkey' ]; $usparams = [ 'type', 'center', 'zoom', 'size', 'scalecontrol', 'overviewcontrol', 'mapheight' ]; $mapparams = []; foreach ( $exparams as $param ) { if ( array_key_exists( $param, $this->params ) ) { $mapparams[] = 'ex:' . $param . '=\'.' . $this->encodePropertyName( $this->params[$param] ) . '\' '; } } foreach ( $usparams as $param ) { if ( array_key_exists( $param, $this->params ) ) { $mapparams[] = 'ex:' . $param . '=\'' . $this->encodePropertyName( $this->params[$param] ) . '\' '; } } if ( !array_key_exists( 'start', $this->params ) && !array_key_exists( 'end', $this->params ) ) { // find out if a geographic coordinate is available foreach ( $res->getPrintRequests() as $pr ) { if ( $pr->getTypeID() == '_geo' ) { $mapparams[] = 'ex:latlng=\'.' . $this->encodePropertyName( $pr->getLabel() ) . '\' '; break; } } } $viewstack[] .= 'ex:role=\'view\' ex:viewClass=\'Map\' ex:showSummary=\'false\' ex:label=\'Map\' ' . implode( " ", $mapparams ); } break; default: case 'tiles':// tile view $sortstring = ''; if ( array_key_exists( 'sort', $this->params ) ) { $sortfields = explode( ",", $this->params['sort'] ); foreach ( $sortfields as $field ) { $sortkeys[] = "." . $this->encodePropertyName( trim( $field ) ); } $sortstring = 'ex:orders=\'' . implode( ",", $sortkeys ) . '\' '; if ( array_key_exists( 'order', $this->params ) ) { $sortstring .= ' ex:directions=\'' . $this->encodePropertyName( $this->params['order'] ) . '\''; } if ( array_key_exists( 'grouped', $this->params ) ) { $sortstring .= ' ex:grouped=\'' . $this->encodePropertyName( $this->params['grouped'] ) . '\''; } } $viewstack[] = 'ex:role=\'view\' ex:showSummary=\'false\' ' . $sortstring; break; } } $viewsrc = 'var ex_views = "' . implode( "/", $viewstack ) . '".split(\'/\');;'; // prepare automatic lenses global $wgParser; $lenscounter = 0; $linkcounter = 0; $imagecounter = 0; if ( array_key_exists( 'lens', $this->params ) ) {// a customized lens is specified via the lens parameter within the query $lenstitle = Title::newFromText( "Template:" . $this->params['lens'] ); $lensarticle = new Article( $lenstitle ); $lenswikitext = $lensarticle->getContent(); if ( preg_match_all( "/[\[][\[][Ii][m][a][g][e][:][{][{][{][1-9A-z\-[:space:]]*[}][}][}][\]][\]]/u", $lenswikitext, $matches ) ) { foreach ( $matches as $match ) { foreach ( $match as $value ) { $strippedvalue = trim( substr( $value, 8 ), "[[{}]]" ); $lenswikitext = str_replace( $value, '