/** * Parse a query string given in SMW's query language to create * an SMWQuery. Parameters are given as key-value-pairs in the * given array. The parameter $context defines in what context the * query is used, which affects ceretain general settings. * An object of type SMWQuery is returned. * * The format string is used to specify the output format if already * known. Otherwise it will be determined from the parameters when * needed. This parameter is just for optimisation in a common case. * * @param string $querystring * @param array $params These need to be the result of a list fed to getProcessedParams * @param $context * @param string $format * @param array $extraprintouts * * @return SMWQuery */ static public function createQuery( $querystring, array $params, $context = self::INLINE_QUERY, $format = '', array $extraprintouts = array() ) { global $smwgQDefaultNamespaces, $smwgQFeatures, $smwgQConceptFeatures; // parse query: $queryfeatures = ( $context == self::CONCEPT_DESC ) ? $smwgQConceptFeatures : $smwgQFeatures; $qp = new SMWQueryParser( $queryfeatures ); $qp->setDefaultNamespaces( $smwgQDefaultNamespaces ); $desc = $qp->getQueryDescription( $querystring ); if ( $format === '' || is_null( $format ) ) { $format = $params['format']; } if ( $format == 'count' ) { $querymode = SMWQuery::MODE_COUNT; } elseif ( $format == 'debug' ) { $querymode = SMWQuery::MODE_DEBUG; } else { $printer = self::getResultPrinter( $format, $context ); $querymode = $printer->getQueryMode( $context ); } $query = new SMWQuery( $desc, ( $context != self::SPECIAL_PAGE ), ( $context == self::CONCEPT_DESC ) ); $query->setQueryString( $querystring ); $query->setExtraPrintouts( $extraprintouts ); $query->setMainLabel( $params['mainlabel'] ); $query->addErrors( $qp->getErrors() ); // keep parsing errors for later output // set mode, limit, and offset: $query->querymode = $querymode; if ( ( array_key_exists( 'offset', $params ) ) && ( is_int( $params['offset'] + 0 ) ) ) { $query->setOffset( max( 0, trim( $params['offset'] ) + 0 ) ); } if ( $query->querymode == SMWQuery::MODE_COUNT ) { // largest possible limit for "count", even inline global $smwgQMaxLimit; $query->setOffset( 0 ); $query->setLimit( $smwgQMaxLimit, false ); } else { if ( ( array_key_exists( 'limit', $params ) ) && ( is_int( trim( $params['limit'] ) + 0 ) ) ) { $query->setLimit( max( 0, trim( $params['limit'] ) + 0 ) ); if ( ( trim( $params['limit'] ) + 0 ) < 0 ) { // limit < 0: always show further results link only $query->querymode = SMWQuery::MODE_NONE; } } else { global $smwgQDefaultLimit; $query->setLimit( $smwgQDefaultLimit ); } } $defaultSort = $format === 'rss' ? 'DESC' : 'ASC'; $sort = self::getSortKeys( $params['sort'], $params['order'], $defaultSort ); $query->sortkeys = $sort['keys']; $query->addErrors( $sort['errors'] ); $query->sort = count( $query->sortkeys ) > 0; // TODO: Why would we do this here? return $query; }
/** * Function not called anywhere but code kept for reference before * migrating it to SMWExporter. */ private function getExportData() { if ($this->isValid()) { $qp = new SMWQueryParser(); $desc = $qp->getQueryDescription(str_replace(array('<', '>', '&'), array('<', '>', '&'), $this->m_dataitem->getConceptQuery())); $exact = true; $owldesc = $this->descriptionToExpData($desc, $exact); if (!$exact) { $result = new SMWExpData(new SMWExpResource('')); $result->addPropertyObjectValue(SMWExporter::getSpecialNsResource('rdf', 'type'), new SMWExpData(SMWExporter::getSpecialNsResource('owl', 'Class'))); $result->addPropertyObjectValue(SMWExporter::getSpecialNsResource('rdfs', 'subClassOf'), $owldesc); return $result; } else { return $owldesc; } } else { return null; } }
/** * @param string $conceptDescriptionText * * @return QuerySegment|null */ public function prepareQuerySegmentFor($conceptDescriptionText) { QuerySegment::$qnum = 0; $querySegmentListBuilder = $this->queryEngine->getQuerySegmentListBuilder(); $querySegmentListBuilder->setSortKeys(array()); $qp = new QueryParser($this->conceptFeatures); $querySegmentListBuilder->getQuerySegmentFrom($qp->getQueryDescription($conceptDescriptionText)); $qid = $querySegmentListBuilder->getLastQuerySegmentId(); $querySegmentList = $querySegmentListBuilder->getQuerySegmentList(); if ($qid < 0) { return null; } // execute query tree, resolve all dependencies $querySegmentListProcessor = $this->queryEngine->getQuerySegmentListProcessor(); $querySegmentListProcessor->setQueryMode(Query::MODE_INSTANCES); $querySegmentListProcessor->setQuerySegmentList($querySegmentList); $querySegmentListProcessor->doResolveQueryDependenciesById($qid); return $querySegmentList[$qid]; }
/** * @param string $conceptDescriptionText * * @return QuerySegment|null */ public function prepareQuerySegmentFor($conceptDescriptionText) { $querySegements = array(); QuerySegment::$qnum = 0; $queryBuilder = $this->queryEngine->getQueryBuilder(); $queryBuilder->setSortKeys(array()); $qp = new QueryParser($this->conceptFeatures); $queryBuilder->buildQuerySegmentFor($qp->getQueryDescription($conceptDescriptionText)); $qid = $queryBuilder->getLastQuerySegmentId(); $querySegements = $queryBuilder->getQuerySegments(); if ($qid < 0) { return null; } // execute query tree, resolve all dependencies $querySegmentListResolver = $this->queryEngine->getQuerySegmentListResolver(); $querySegmentListResolver->setQueryMode(Query::MODE_INSTANCES); $querySegmentListResolver->setQuerySegmentList($querySegements); $querySegmentListResolver->resolveForSegmentId($qid); return $querySegements[$qid]; }
private function createQuery($queryString, $mode, array $printouts = array()) { $description = $this->queryParser->getQueryDescription($queryString); foreach ($printouts as $printout) { $property = DIProperty::newFromUserLabel($printout); $propertyValue = new PropertyValue('__pro'); $propertyValue->setDataItem($property); $description->addPrintRequest(new PrintRequest(PrintRequest::PRINT_PROP, null, $propertyValue)); } $query = new Query($description, false, false); $query->setUnboundlimit($this->queryLimit); $query->setOffset($this->queryOffset); $query->querymode = $mode; return $query; }
/** * Compute an SMWDescription from a query string. Returns whatever descriptions could be * wrestled from the given string (the most general result being SMWThingDescription if * no meaningful condition was extracted). */ public function getQueryDescription($querystring) { if (stripos($querystring, "select") === 0) { wfProfileIn('SMWSPARQLQueryParser::getQueryDescription (SMW)'); $this->m_errors = array(); $this->m_label = ''; $this->m_curstring = $querystring; $this->m_sepstack = array(); $setNS = false; $result = new SMWSPARQLDescription(); wfProfileOut('SMWSPARQLQueryParser::getQueryDescription (SMW)'); return $result; } else { return parent::getQueryDescription($querystring); } }
/** * Create a new SMWSQLStore3Query 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 * compilePropertyValueDescription to deal with this case. * * @param SMWDescription $description * * @return integer */ protected function compileQueries(SMWDescription $description) { $query = new SMWSQLStore3Query(); if ($description instanceof SMWSomeProperty) { $this->compileSomePropertyDescription($query, $description); } elseif ($description instanceof SMWNamespaceDescription) { // TODO: One instance of the SMW IDs table on s_id always suffices (swm_id is KEY)! Doable in execution ... (PERFORMANCE) $query->jointable = SMWSql3SmwIds::tableName; $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 ? SMWSQLStore3Query::Q_CONJUNCTION : SMWSQLStore3Query::Q_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) { $query->type = SMWSQLStore3Query::Q_NOQUERY; } } elseif ($description instanceof SMWClassDescription) { $cqid = SMWSQLStore3Query::$qnum; $cquery = new SMWSQLStore3Query(); $cquery->type = SMWSQLStore3Query::Q_CLASS_HIERARCHY; $cquery->joinfield = array(); foreach ($description->getCategories() as $cat) { $cid = $this->m_store->smwIds->getSMWPageID($cat->getDBkey(), NS_CATEGORY, $cat->getInterwiki(), ''); if ($cid != 0) { $cquery->joinfield[] = $cid; } } if (count($cquery->joinfield) == 0) { // Empty result. $query->type = SMWSQLStore3Query::Q_VALUE; $query->jointable = ''; $query->joinfield = ''; } else { // Instance query with disjunction of classes (categories) $query->jointable = $this->m_dbs->tableName($this->m_store->findPropertyTableID(new SMWDIProperty('_INST'))); $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->getDataItem() instanceof SMWDIWikiPage) { if ($description->getComparator() == SMW_CMP_EQ) { $query->type = SMWSQLStore3Query::Q_VALUE; $oid = $this->m_store->smwIds->getSMWPageID($description->getDataItem()->getDBkey(), $description->getDataItem()->getNamespace(), $description->getDataItem()->getInterwiki(), $description->getDataItem()->getSubobjectName()); $query->joinfield = array($oid); } else { // Join with SMW IDs table needed for other comparators (apply to title string). $query->jointable = SMWSql3SmwIds::tableName; $query->joinfield = "{$query->alias}.smw_id"; $value = $description->getDataItem()->getSortKey(); switch ($description->getComparator()) { case SMW_CMP_LEQ: $comp = '<='; break; case SMW_CMP_GEQ: $comp = '>='; break; case SMW_CMP_LESS: $comp = '<'; break; case SMW_CMP_GRTR: $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->smwIds->getSMWPageID($description->getConcept()->getDBkey(), SMW_NS_CONCEPT, '', ''); // We bypass the storage interface here (which is legal as we control it, and safe if we are careful with changes ...) // This should be faster, but we must implement the unescaping that concepts do on getWikiValue() $row = $this->m_dbs->selectRow('smw_fpt_conc', array('concept_txt', 'concept_features', 'concept_size', 'concept_depth', 'cache_date'), array('s_id' => $cid), 'SMWSQLStore3Queries::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 = SMWSQLStore3::CONCEPT_CACHE_TABLE; $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. // Unescaping is the same as in SMW_DV_Conept's getWikiValue(). $desc = $qp->getQueryDescription(str_replace(array('<', '>', '&'), array('<', '>', '&'), $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 $this->m_errors[] = wfMessage('smw_emptysubquery')->text(); // not quite the right message, but this case is very rare; let us not make detailed messages for this } } else { $this->m_errors[] = wfMessage('smw_concept_cache_miss', $description->getConcept()->getText())->text(); } } // else: no cache, no description (this may happen); treat like empty concept } } else { // (e.g. SMWThingDescription) $query->type = SMWSQLStore3Query::Q_NOQUERY; // no condition } $this->registerQuery($query); if ($query->type != SMWSQLStore3Query::Q_NOQUERY) { return $query->queryNumber; } else { return -1; } }
static public function addNotify( $rawquery, $name, $rep_all, $show_all, $delegate ) { global $wgTitle; // Take care at least of some templates -- for better template support use #ask $parser = new Parser(); $parserOptions = new ParserOptions(); $rawquery = $parser->transformMsg( $rawquery, $parserOptions, $wgTitle ); wfProfileIn( 'SMWNotifyProcessor::createNotify (SMW)' ); $sStore = NMStorage::getDatabase(); global $wgUser; $user_id = $wgUser->getId(); if ( $user_id == 0 ) { wfProfileOut( 'SMWNotifyProcessor::createNotify (SMW)' ); return wfMsg( 'smw_nm_proc_notlogin' ); } // check notify query first, use QueryParser from SMW SMWQueryProcessor::processFunctionParams( SMWNotifyProcessor::getQueryRawParams( $rawquery ), $querystring, $params, $printouts ); $qp = new SMWQueryParser(); $qp->setDefaultNamespaces( $smwgQDefaultNamespaces ); $desc = $qp->getQueryDescription( $querystring ); if ( count( $qp->getErrors() ) > 0 ) { wfProfileOut( 'SMWNotifyProcessor::createNotify (SMW)' ); return wfMsg( 'smw_nm_proc_createfail', implode( "\n", $qp->getErrors() ) ); } $notify_id = $sStore->addNotifyQuery( $user_id, $rawquery, $name, $rep_all, $show_all, $delegate ); if ( $notify_id == 0 ) { wfProfileOut( 'SMWNotifyProcessor::createNotify (SMW)' ); return wfMsg( 'smw_nm_proc_savefail' ); } wfProfileOut( 'SMWNotifyProcessor::createNotify (SMW)' ); wfProfileIn( 'SMWNotifyProcessor::enableNotify (SMW)' ); $msg = ''; $result = SMWNotifyProcessor::enableNotify( $notify_id, $rawquery, $msg ); wfProfileOut( 'SMWNotifyProcessor::enableNotify (SMW)' ); return "1" . ( $result ? "1":"0" ) . "$notify_id,$msg"; }
static function addAutocomplete() { global $smwgNMDelegateQuery, $smwgNMDelegateUserGroup; if (!$smwgNMDelegateQuery && !$smwgNMDelegateUserGroup) { return; } global $wgOut, $smwgNMScriptPath; $nmScriptPath = $smwgNMScriptPath . '/specials/SMWNotifyMe'; $nmYUIBase = "http://yui.yahooapis.com/2.7.0/build/"; $wgOut->addLink(array('rel' => 'stylesheet', 'type' => 'text/css', 'media' => "screen, projection", 'href' => $nmScriptPath . '/skins/NM_yui_autocompletion.css')); $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'yahoo/yahoo-min.js"></script>' . "\n"); $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'dom/dom-min.js"></script>' . "\n"); $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'event/event-min.js"></script>' . "\n"); $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'get/get-min.js"></script>' . "\n"); $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'connection/connection-min.js"></script>' . "\n"); $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'json/json-min.js"></script>' . "\n"); $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'datasource/datasource-min.js"></script>' . "\n"); $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'autocomplete/autocomplete-min.js"></script>' . "\n"); $wgOut->addScript('<script type="text/javascript" src="' . $nmScriptPath . '/libs/NM_yui_autocompletion.js"></script>' . "\n"); $pages = array(); if ($smwgNMDelegateUserGroup) { if ($smwgNMDelegateUserGroup != "*" && !is_array($smwgNMDelegateUserGroup)) { $groups = split(",", $smwgNMDelegateUserGroup); for ($i = count($groups) - 1; $i >= 0; --$i) { $groups[$i] = strtolower(trim(str_replace("\\'", "\\\\'", $groups[$i]))); } } $pages = NMStorage::getDatabase()->getGroupedUsers($groups); for ($i = count($pages) - 1; $i >= 0; --$i) { $pages[$i] = "['" . str_replace("\\'", "\\\\'", $pages[$i]) . "']"; } } if ($smwgNMDelegateQuery) { global $smwgQDefaultNamespaces, $smwgQFeatures; $qp = new SMWQueryParser($smwgQFeatures); $qp->setDefaultNamespaces($smwgQDefaultNamespaces); $desc = $qp->getQueryDescription($smwgNMDelegateQuery); $desc->prependPrintRequest(new SMWPrintRequest(SMWPrintRequest::PRINT_THIS, "")); $query = new SMWQuery($desc, true); $query_result = smwfGetStore()->getQueryResult($query); while ($res = $query_result->getNext()) { $pages[] = "['" . str_replace("\\'", "\\\\'", $res[0]->getNextObject()->getWikiValue()) . "']"; } } global $smwgNMMaxAutocompleteValues; if ($smwgNMMaxAutocompleteValues <= 0) { $smwgNMMaxAutocompleteValues = 10; } $wgOut->addScript('<script type="text/javascript"> nmautocompletestrings = [' . join(',', $pages) . ']; nmMaxResultsDisplayed = ' . $smwgNMMaxAutocompleteValues . '; </script>'); }
/** * 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; }
/** * No defaultnamespaces here; If any, these are already in the concept. * Unescaping is the same as in SMW_DV_Conept's getWikiValue(). */ private function getConceptQueryDescriptionFrom($conceptQuery) { $queryParser = new QueryParser(); return $queryParser->getQueryDescription(str_replace(array('<', '>', '&'), array('<', '>', '&'), $conceptQuery)); }