"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, '
' . $this->encodePropertyName( strtolower( str_replace( "\n", "", $strippedvalue ) ) ) . '
', $lenswikitext ); $imagecounter++; } } } if ( preg_match_all( "/[\[][\[][{][{][{][1-9A-z\-[:space:]]*[}][}][}][\]][\]]/u", $lenswikitext, $matches ) ) { foreach ( $matches as $match ) { foreach ( $match as $value ) { $strippedvalue = trim( $value, "[[{}]]" ); $lenswikitext = str_replace( $value, '
' . $this->encodePropertyName( strtolower( str_replace( "\n", "", $strippedvalue ) ) ) . '
', $lenswikitext ); $linkcounter++; } } } if ( preg_match_all( "/[{][{][{][1-9A-z\:\|\/\=\-[:space:]]*[}][}][}]/u", $lenswikitext, $matches ) ) { foreach ( $matches as $match ) { foreach ( $match as $value ) { $strippedvalue = trim( $value, "{}" ); $lenswikitext = str_replace( $value, '
' . $this->encodePropertyName( strtolower( str_replace( "\n", "", $strippedvalue ) ) ) . '
', $lenswikitext ); $lenscounter++; } } } $lenshtml = $wgParser->internalParse( $lenswikitext );// $wgParser->parse($lenswikitext, $lenstitle, new ParserOptions(), true, true)->getText(); $lenssrc = "var ex_lens = '" . str_replace( "\n", "", $lenshtml ) . "';ex_lenscounter =" . $lenscounter . ";ex_linkcounter=" . $linkcounter . ";ex_imagecounter=" . $imagecounter . ";"; } else {// generic lens (creates links to further content (property-pages, pages about values) foreach ( $res->getPrintRequests() as $pr ) { if ( $remote ) { $wikiurl = str_replace( "$1", "", $extlinkpattern ); } else { $wikiurl = $wgScriptPath . "/index.php?title="; } if ( $pr->getTypeID() == '_wpg' ) { $prefix = ''; if ( $pr->getLabel() == 'Category' ) { $prefix = "Category:"; } $lensstack[] = '' . $pr->getText( 0, $this->mLinker ) . '
'; } else { $lensstack[] = '' . $pr->getText( 0, $this->mLinker ) . '
'; } } array_shift( $lensstack ); $lenssrc = 'var ex_lens = \'
' . implode( "", $lensstack ) . '
\'; ex_lenscounter = 0; ex_linkcounter=0; ex_imagecounter=0;'; } if ( $remote ) { $varremote = 'true'; } else { $varremote = 'false'; } // Handling special formats like date $formatssrc = 'var formats =\'\''; if ( array_key_exists( 'date', $this->params ) ) { $formatssrc = 'var formats = \'ex:formats="date { mode:' . $this->params['date'] . '; show:date }"\';'; } // create a URL pointing to the corresponding JSON feed $label = ''; $JSONlink = $res->getQueryLink( $label ); if ( $this->getSearchLabel( SMW_OUTPUT_WIKI ) != '' ) { // used as a file name $link->setParameter( $this->getSearchLabel( SMW_OUTPUT_WIKI ), 'searchlabel' ); } if ( array_key_exists( 'limit', $this->params ) ) { $JSONlink->setParameter( htmlspecialchars( $this->params['limit'] ), 'limit' ); } $JSONlink->setParameter( 'json', 'format' ); $stringtoedit = explode( "|", $JSONlink->getText( $outputmode, $this->mLinker ) ); $stringtoedit = substr( $stringtoedit[0], 3 ); $JSONlinksrc = "var JSONlink = '" . $stringtoedit . "';"; // create script header with variables containing the Exhibit markup $headervars = ""; // To run Exhibit some links to the scripts of the API need to be included in the header $ExhibitScriptSrc1 = ''; $ExhibitScriptSrc2 = ''; $CSSSrc = ''; SMWOutputs::requireHeadItem( 'CSS', $CSSSrc ); // include CSS SMWOutputs::requireHeadItem( 'EXHIBIT1', $ExhibitScriptSrc1 ); // include Exhibit API SMWOutputs::requireHeadItem( 'EXHIBIT2', $ExhibitScriptSrc2 ); // includes javascript overwriting the Exhibit start-up functions SMWOutputs::requireHeadItem( 'SOURCES' . $smwgIQRunningNumber, $sourcesrc );// include sources variable SMWOutputs::requireHeadItem( 'VIEWSFACETS', $headervars );// include views and facets variable if ( !$remote ) { // print input table // print header $result = "\n"; if ( $this->mShowHeaders ) { // building headers $result .= "\t\n"; foreach ( $res->getPrintRequests() as $pr ) { if ( $pr->getText( $outputmode, $this->getLinker( 0 ) ) == '' ) { $headerlabel = "Name"; } else { $headerlabel = $pr->getText( $outputmode, $this->getLinker( 0 ) ); } $result .= "\t\t\n"; } $result .= "\t\n"; } // print all result rows while ( $row = $res->getNext() ) { $result .= "\t\n"; foreach ( $row as $field ) { $result .= "\t\t\n"; } else { $result .= "\n"; } } $result .= "\t\n"; } $result .= "
" . $headerlabel . "
"; $textstack = []; while ( ( $object = $field->getNextDataValue() ) !== false ) { switch ( $object->getTypeID() ) { case '_wpg': $textstack[] = $object->getLongText( $outputmode, $this->getLinker( 0 ) ); break; case '_geo': $c = $object->getDBKeys(); $textstack[] = $c[0] . "," . $c[1]; break; case '_num': if ( method_exists( $object, 'getValueKey' ) ) { $textstack[] = $object->getValueKey( $outputmode, $this->getLinker( 0 ) ); } else { $textstack[] = $object->getNumericValue( $outputmode, $this->getLinker( 0 ) ); } break; case '_dat': $textstack[] = $object->getYear() . "-" . str_pad( $object->getMonth(), 2, '0', STR_PAD_LEFT ) . "-" . str_pad( $object->getDay(), 2, '0', STR_PAD_LEFT ) . " " . $object->getTimeString(); break; case '_ema': $textstack[] = $object->getShortWikiText( $this->getLinker( 0 ) ); break; case '_tel': case '_anu': case '_uri': $textstack[] = $object->getWikiValue(); break; case '__sin': $tmp = $object->getShortText( $outputmode, null ); if ( strpos( $tmp, ":" ) ) { $tmp = explode( ":", $tmp, 2 ); $tmp = $tmp[1]; } $textstack[] = $tmp; break; case '_txt': case '_cod': case '_str': $textstack[] = $object->getWikiValue(); break; default: $textstack[] = $object->getLongHTMLText( $this->getLinker( 0 ) ); } } if ( $textstack != null ) { $result .= implode( ';', $textstack ) . "
\n"; } if ( SRFExhibit::$exhibitRunningNumber == 0 ) { $result .= "
"; } // print placeholder (just print it one time) $this->isHTML = ( $outputmode == SMW_OUTPUT_HTML ); // yes, our code can be viewed as HTML if requested, no more parsing needed SRFExhibit::$exhibitRunningNumber++; return $result; } /** * @see SMWResultPrinter::getParamDefinitions * * @since 1.8 * * @param $definitions array of IParamDefinition * * @return array of IParamDefinition|array */ public function getParamDefinitions( array $definitions ) { $params = parent::getParamDefinitions( $definitions ); $params[] = [ 'name' => 'views', 'message' => 'srf_paramdesc_views', 'islist' => true, 'values' => [ 'tiles', 'tabular', 'timeline', 'maps' ] ]; $params[] = [ 'name' => 'facets', 'message' => 'srf_paramdesc_facets' ]; $params[] = [ 'name' => 'lens', 'message' => 'srf_paramdesc_lens' ]; return $params; } }