public function getQueryLink($caption = false) { $params = array(trim($this->mQuery->getQueryString())); foreach ($this->mQuery->getExtraPrintouts() as $printout) { //$params[] = '?result.'.$printout->getData().'='.$printout->getLabel(); $params[] = '?result.' . $printout->getData() . '=' . $printout->getLabel(); } if ($caption == false) { smwfLoadExtensionMessages('SemanticMediaWiki'); $caption = ' ' . wfMsgForContent('smw_iq_moreresults'); // The space is right here, not in the QPs! } //unset limit and offset parameter since this is explicitly added by special:ask if (array_key_exists('limit', $this->mQuery->params)) { unset($this->mQuery->params['limit']); } if (array_key_exists('offset', $this->mQuery->params)) { unset($this->mQuery->params['offset']); } //add other query params like source and webservice to the link $params = array_merge($params, $this->mQuery->params); // Note: the initial : prevents SMW from reparsing :: in the query string. $result = SMWInfolink::newInternalLink($caption, ':Special:Ask', false, $params); return $result; }
/** * Constructor */ public function __construct() { global $smwgBrowseShowAll; parent::__construct( 'BrowseWiki', '', true, false, 'default', true ); smwfLoadExtensionMessages( 'SemanticMediaWiki' ); if ( $smwgBrowseShowAll ) { SWBSpecialBrowseWiki::$incomingvaluescount = 21; SWBSpecialBrowseWiki::$incomingpropertiescount = - 1; } }
/** * Create a new SMWSQLStore2Query object that can be used to obtain results * for the given description. The result is stored in $this->m_queries * using a numeric key that is returned as a result of the function. * Returns -1 if no query was created. * @todo The case of nominal classes (top-level SMWValueDescription) still * makes some assumptions about the table structure, especially about the * name of the joinfield (o_id). Better extend compileAttributeWhere to * deal with this case. * * @param SMWDescription $description * * @return integer */ protected function compileQueries(SMWDescription $description) { $qid = SMWSQLStore2Query::$qnum; $query = new SMWSQLStore2Query(); if ($description instanceof SMWSomeProperty) { $this->compilePropertyCondition($query, $description->getProperty(), $description->getDescription()); // Compilation has set type to NOQUERY: drop condition. if ($query->type == SMW_SQL2_NOQUERY) { $qid = -1; } } elseif ($description instanceof SMWNamespaceDescription) { // TODO: One instance of smw_ids on s_id always suffices (swm_id is KEY)! Doable in execution ... (PERFORMANCE) $query->jointable = 'smw_ids'; $query->joinfield = "{$query->alias}.smw_id"; $query->where = "{$query->alias}.smw_namespace=" . $this->m_dbs->addQuotes($description->getNamespace()); } elseif ($description instanceof SMWConjunction || $description instanceof SMWDisjunction) { $query->type = $description instanceof SMWConjunction ? SMW_SQL2_CONJUNCTION : SMW_SQL2_DISJUNCTION; foreach ($description->getDescriptions() as $subdesc) { $sub = $this->compileQueries($subdesc); if ($sub >= 0) { $query->components[$sub] = true; } } // All subconditions failed, drop this as well. if (count($query->components) == 0) { $qid = -1; } } elseif ($description instanceof SMWClassDescription) { $cqid = SMWSQLStore2Query::$qnum; $cquery = new SMWSQLStore2Query(); $cquery->type = SMW_SQL2_CLASS_HIERARCHY; $cquery->joinfield = array(); foreach ($description->getCategories() as $cat) { $cid = $this->m_store->getSMWPageID($cat->getDBkey(), NS_CATEGORY, $cat->getInterwiki()); if ($cid != 0) { $cquery->joinfield[] = $cid; } } if (count($cquery->joinfield) == 0) { // Empty result. $query->type = SMW_SQL2_VALUE; $query->jointable = ''; $query->joinfield = ''; } else { // Instance query with dicjunction of classes (categories) $query->jointable = 'smw_inst2'; $query->joinfield = "{$query->alias}.s_id"; $query->components[$cqid] = "{$query->alias}.o_id"; $this->m_queries[$cqid] = $cquery; } } elseif ($description instanceof SMWValueDescription) { // Only type '_wpg' objects can appear on query level (essentially as nominal classes). if ($description->getDatavalue()->getTypeID() == '_wpg') { if ($description->getComparator() == SMW_CMP_EQ) { $query->type = SMW_SQL2_VALUE; $oid = $this->m_store->getSMWPageID($description->getDatavalue()->getDBkey(), $description->getDatavalue()->getNamespace(), $description->getDatavalue()->getInterwiki()); $query->joinfield = array($oid); } else { // Join with smw_ids needed for other comparators (apply to title string). $query->jointable = 'smw_ids'; $query->joinfield = "{$query->alias}.smw_id"; $value = $description->getDatavalue()->getSortkey(); switch ($description->getComparator()) { case SMW_CMP_LEQ: $comp = '<='; break; case SMW_CMP_GEQ: $comp = '>='; break; case SMW_CMP_NEQ: $comp = '!='; break; case SMW_CMP_LIKE: case SMW_CMP_NLKE: $comp = ' LIKE '; if ($description->getComparator() == SMW_CMP_NLKE) { $comp = " NOT{$comp}"; } $value = str_replace(array('%', '_', '*', '?'), array('\\%', '\\_', '%', '_'), $value); break; } $query->where = "{$query->alias}.smw_sortkey{$comp}" . $this->m_dbs->addQuotes($value); } } } elseif ($description instanceof SMWConceptDescription) { // fetch concept definition and insert it here $cid = $this->m_store->getSMWPageID($description->getConcept()->getDBkey(), SMW_NS_CONCEPT, ''); $row = $this->m_dbs->selectRow('smw_conc2', array('concept_txt', 'concept_features', 'concept_size', 'concept_depth', 'cache_date'), array('s_id' => $cid), 'SMWSQLStore2Queries::compileQueries'); if ($row === false) { // No description found, concept does not exist. // keep the above query object, it yields an empty result // TODO: announce an error here? (maybe not, since the query processor can check for // non-existing concept pages which is probably the main reason for finding nothing here) } else { global $smwgQConceptCaching, $smwgQMaxSize, $smwgQMaxDepth, $smwgQFeatures, $smwgQConceptCacheLifetime; $may_be_computed = $smwgQConceptCaching == CONCEPT_CACHE_NONE || $smwgQConceptCaching == CONCEPT_CACHE_HARD && ~(~($row->concept_features + 0) | $smwgQFeatures) == 0 && $smwgQMaxSize >= $row->concept_size && $smwgQMaxDepth >= $row->concept_depth; if ($row->cache_date && ($row->cache_date > strtotime("now") - $smwgQConceptCacheLifetime * 60 || !$may_be_computed)) { // Cached concept, use cache unless it is dead and can be revived. $query->jointable = 'smw_conccache'; $query->joinfield = "{$query->alias}.s_id"; $query->where = "{$query->alias}.o_id=" . $this->m_dbs->addQuotes($cid); } elseif ($row->concept_txt) { // Parse description and process it recursively. if ($may_be_computed) { $qp = new SMWQueryParser(); // No defaultnamespaces here; If any, these are already in the concept. $desc = $qp->getQueryDescription($row->concept_txt); $qid = $this->compileQueries($desc); if ($qid != -1) { $query = $this->m_queries[$qid]; } else { // somehow the concept query is no longer valid; maybe some syntax changed (upgrade) or global settings were modified since storing it smwfLoadExtensionMessages('SemanticMediaWiki'); $this->m_errors[] = wfMsg('smw_emptysubquery'); // not quite the right message, but this case is very rare; let us not make detailed messages for this } } else { smwfLoadExtensionMessages('SemanticMediaWiki'); $this->m_errors[] = wfMsg('smw_concept_cache_miss', $description->getConcept()->getText()); } } // else: no cache, no description (this may happen); treat like empty concept } } else { // (e.g. SMWThingDescription) $qid = -1; // no condition } if ($qid >= 0) { // Success, keep query object, propagate sortkeys from subqueries. $this->m_queries[$qid] = $query; if ($query->type != SMW_SQL2_DISJUNCTION) { // Sortkeys are killed by disjunctions (not all parts may have them), // NOTE: preprocessing might try to push disjunctions downwards to safe sortkey, but this seems to be minor foreach ($query->components as $cid => $field) { $query->sortfields = array_merge($this->m_queries[$cid]->sortfields, $query->sortfields); } } } return $qid; }
protected function parseUserValue($value) { // echo "parseUserValue"; smwfLoadExtensionMessages('SemanticMediaWiki'); $value = trim($value); $this->m_wikitext = $value; if ($this->m_caption === false) { $this->m_caption = $this->m_wikitext; } $scheme = $hierpart = $query = $fragment = ''; if ($value == '') { // do not accept empty strings $this->addError(wfMsgForContent('smw_emptystring')); $this->m_dataitem = new SMWDIUri('http', '//example.com', '', '', $this->m_typeid); // define data item to have some value return; } $parts = explode(':', $value, 2); // try to split "schema:rest" if (count($parts) == 1) { // possibly add "http" as default $value = 'http://' . $value; $parts[1] = $parts[0]; $parts[0] = 'http'; } // check against blacklist $uri_blacklist = explode("\n", wfMsgForContent('smw_uri_blacklist')); foreach ($uri_blacklist as $uri) { $uri = trim($uri); if ($uri == mb_substr($value, 0, mb_strlen($uri))) { // disallowed URI! $this->addError(wfMsgForContent('smw_baduri', $value)); $this->m_dataitem = new SMWDIUri('http', '//example.com', '', '', $this->m_typeid); // define data item to have some value return; } } // decompose general URI components $scheme = $parts[0]; $parts = explode('?', $parts[1], 2); // try to split "hier-part?queryfrag" if (count($parts) == 2) { $hierpart = $parts[0]; $parts = explode('#', $parts[1], 2); // try to split "query#frag" $query = $parts[0]; $fragment = count($parts) == 2 ? $parts[1] : ''; } else { $query = ''; $parts = explode('#', $parts[0], 2); // try to split "hier-part#frag" $hierpart = $parts[0]; $fragment = count($parts) == 2 ? $parts[1] : ''; } // We do not validate the URI characters (the data item will do this) but we do some escaping: // encode most characters, but leave special symbols as given by user: $hierpart = str_replace(array('%3A', '%2F', '%23', '%40', '%3F', '%3D', '%26', '%25'), array(':', '/', '#', '@', '?', '=', '&', '%'), rawurlencode($hierpart)); $query = str_replace(array('%3A', '%2F', '%23', '%40', '%3F', '%3D', '%26', '%25'), array(':', '/', '#', '@', '?', '=', '&', '%'), rawurlencode($query)); $fragment = str_replace(array('%3A', '%2F', '%23', '%40', '%3F', '%3D', '%26', '%25'), array(':', '/', '#', '@', '?', '=', '&', '%'), rawurlencode($fragment)); /// NOTE: we do not support raw [ (%5D) and ] (%5E), although they are needed for ldap:// (but rarely in a wiki) /// NOTE: "+" gets encoded, as it is interpreted as space by most browsers when part of a URL; /// this prevents tel: from working directly, but we have a datatype for this anyway. // Now create the URI data item: try { SWBSpecialBrowseWiki::debug($this->m_typeid, "typeid"); $this->m_dataitem = new SMWDIUri($scheme, $hierpart, $query, $fragment, $this->m_typeid); } catch (SMWDataItemException $e) { $this->addError(wfMsgForContent('smw_baduri', $this->m_wikitext)); $this->m_dataitem = new SMWDIUri('http', '//example.com', '', '', $this->m_typeid); // define data item to have some value } }