00001 <?php
00015 class SMWQueryProcessor {
00016
00017
00018
00019
00020 const SPECIAL_PAGE = 0;
00021 const INLINE_QUERY = 1;
00022 const CONCEPT_DESC = 2;
00023
00039 public static function getProcessedParams( array $params, array $printRequests = null, $unknownInvalid = true ) {
00040 $paramDefinitions = self::getParameters();
00041
00042 $formatManipulation = new SMWParamFormat();
00043
00044 if ( !is_null( $printRequests ) ) {
00045 $formatManipulation->setPrintRequests( $printRequests );
00046 }
00047
00048 $paramDefinitions['format']->addManipulations( $formatManipulation );
00049
00050 $validator = new Validator( 'SMW query', $unknownInvalid );
00051 $validator->setParameters( $params, $paramDefinitions, false );
00052 $validator->validateParameters();
00053
00054 return $validator->getParameterValues();
00055 }
00056
00076 static public function createQuery( $querystring, array $params, $context = self::INLINE_QUERY, $format = '', array $extraprintouts = array() ) {
00077 global $smwgQDefaultNamespaces, $smwgQFeatures, $smwgQConceptFeatures;
00078
00079
00080 $queryfeatures = ( $context == self::CONCEPT_DESC ) ? $smwgQConceptFeatures : $smwgQFeatures;
00081 $qp = new SMWQueryParser( $queryfeatures );
00082 $qp->setDefaultNamespaces( $smwgQDefaultNamespaces );
00083 $desc = $qp->getQueryDescription( $querystring );
00084
00085 if ( $format === '' || is_null( $format ) ) {
00086 $format = $params['format'];
00087 }
00088
00089 if ( $format == 'count' ) {
00090 $querymode = SMWQuery::MODE_COUNT;
00091 } elseif ( $format == 'debug' ) {
00092 $querymode = SMWQuery::MODE_DEBUG;
00093 } else {
00094 $printer = self::getResultPrinter( $format, $context );
00095 $querymode = $printer->getQueryMode( $context );
00096 }
00097
00098 $query = new SMWQuery( $desc, ( $context != self::SPECIAL_PAGE ), ( $context == self::CONCEPT_DESC ) );
00099 $query->setQueryString( $querystring );
00100 $query->setExtraPrintouts( $extraprintouts );
00101 $query->setMainLabel( $params['mainlabel'] );
00102 $query->addErrors( $qp->getErrors() );
00103
00104
00105 $query->querymode = $querymode;
00106 if ( ( array_key_exists( 'offset', $params ) ) && ( is_int( $params['offset'] + 0 ) ) ) {
00107 $query->setOffset( max( 0, trim( $params['offset'] ) + 0 ) );
00108 }
00109
00110 if ( $query->querymode == SMWQuery::MODE_COUNT ) {
00111 global $smwgQMaxLimit;
00112 $query->setOffset( 0 );
00113 $query->setLimit( $smwgQMaxLimit, false );
00114 } else {
00115 if ( ( array_key_exists( 'limit', $params ) ) && ( is_int( trim( $params['limit'] ) + 0 ) ) ) {
00116 $query->setLimit( max( 0, trim( $params['limit'] ) + 0 ) );
00117 if ( ( trim( $params['limit'] ) + 0 ) < 0 ) {
00118 $query->querymode = SMWQuery::MODE_NONE;
00119 }
00120 } else {
00121 global $smwgQDefaultLimit;
00122 $query->setLimit( $smwgQDefaultLimit );
00123 }
00124 }
00125
00126 $defaultSort = $format === 'rss' ? 'DESC' : 'ASC';
00127 $sort = self::getSortKeys( $params['sort'], $params['order'], $defaultSort );
00128
00129 $query->sortkeys = $sort['keys'];
00130 $query->addErrors( $sort['errors'] );
00131 $query->sort = count( $query->sortkeys ) > 0;
00132
00133 return $query;
00134 }
00135
00147 protected static function getSortKeys( array $sortParam, array $orderParam, $defaultSort ) {
00148 $orders = array();
00149 $sortKeys = array();
00150 $sortErros = array();
00151
00152 foreach ( $orderParam as $key => $order ) {
00153 $order = strtolower( trim( $order ) );
00154 if ( ( $order == 'descending' ) || ( $order == 'reverse' ) || ( $order == 'desc' ) ) {
00155 $orders[$key] = 'DESC';
00156 } elseif ( ( $order == 'random' ) || ( $order == 'rand' ) ) {
00157 $orders[$key] = 'RANDOM';
00158 } else {
00159 $orders[$key] = 'ASC';
00160 }
00161 }
00162
00163 foreach ( $sortParam as $sort ) {
00164 $sortKey = false;
00165
00166
00167
00168 if ( trim( $sort ) === '' ) {
00169 $sortKey = '';
00170 }
00171 else {
00172 $propertyValue = SMWPropertyValue::makeUserProperty( trim( $sort ) );
00173
00174 if ( $propertyValue->isValid() ) {
00175 $sortKey = $propertyValue->getDataItem()->getKey();
00176 } else {
00177 $sortErros = array_merge( $sortErros, $propertyValue->getErrors() );
00178 }
00179 }
00180
00181 if ( $sortKey !== false ) {
00182 $order = empty( $orders ) ? $defaultSort : array_shift( $orders );
00183 $sortKeys[$sortKey] = $order;
00184 }
00185 }
00186
00187
00188
00189 if ( !array_key_exists( '', $sortKeys ) && !empty( $orders ) ) {
00190 $sortKeys[''] = array_shift( $orders );
00191 }
00192
00193 return array( 'keys' => $sortKeys, 'errors' => $sortErros );
00194 }
00195
00204 public static function addThisPrintout( array &$printRequests, array $rawParams ) {
00205 if ( !is_null( $printRequests ) ) {
00206 $hasMainlabel = array_key_exists( 'mainlabel', $rawParams );
00207
00208 if ( !$hasMainlabel || trim( $rawParams['mainlabel'] ) !== '-' ) {
00209 array_unshift( $printRequests, new SMWPrintRequest(
00210 SMWPrintRequest::PRINT_THIS,
00211 $hasMainlabel ? $rawParams['mainlabel'] : ''
00212 ) );
00213 }
00214 }
00215 }
00216
00230 static public function processFunctionParams( array $rawparams, &$querystring, &$params, &$printouts, $showmode = false ) {
00231 global $wgContLang;
00232
00233 $querystring = '';
00234 $printouts = array();
00235 $lastprintout = null;
00236 $params = array();
00237
00238 foreach ( $rawparams as $name => $param ) {
00239
00240
00241 if ( is_array( $param ) ) {
00242 $param = implode( ',', array_keys( $param ) );
00243 }
00244
00245 if ( is_string( $name ) && ( $name !== '' ) ) {
00246 $param = $name . '=' . $param;
00247 }
00248
00249 if ( $param === '' ) {
00250 } elseif ( $param { 0 } == '?' ) {
00251 $param = substr( $param, 1 );
00252 $parts = explode( '=', $param, 2 );
00253 $propparts = explode( '#', $parts[0], 2 );
00254
00255 $data = null;
00256
00257 if ( trim( $propparts[0] ) === '' ) {
00258 $printmode = SMWPrintRequest::PRINT_THIS;
00259 $label = '';
00260 $title = null;
00261 } elseif ( $wgContLang->getNsText( NS_CATEGORY ) == ucfirst( trim( $propparts[0] ) ) ) {
00262 $title = null;
00263 $printmode = SMWPrintRequest::PRINT_CATS;
00264 $label = $showmode ? '' : $wgContLang->getNSText( NS_CATEGORY );
00265 } else {
00266 $title = Title::newFromText( trim( $propparts[0] ), SMW_NS_PROPERTY );
00267 if ( is_null( $title ) ) {
00268 continue;
00269 }
00270
00271 if ( $title->getNamespace() == NS_CATEGORY ) {
00272 $printmode = SMWPrintRequest::PRINT_CCAT;
00273 $data = $title;
00274 $label = $showmode ? '' : $title->getText();
00275 } else {
00276 $printmode = SMWPrintRequest::PRINT_PROP;
00277 $property = SMWPropertyValue::makeUserProperty( trim( $propparts[0] ) );
00278 $data = $property;
00279 $label = $showmode ? '' : $property->getWikiValue();
00280 }
00281 }
00282
00283 if ( count( $propparts ) == 1 ) {
00284 $propparts[] = false;
00285 } elseif ( trim( $propparts[1] ) === '' ) {
00286 $propparts[1] = '-';
00287 }
00288
00289 if ( count( $parts ) > 1 ) {
00290 $label = trim( $parts[1] );
00291 }
00292
00293 $lastprintout = new SMWPrintRequest( $printmode, $label, $data, trim( $propparts[1] ) );
00294 $printouts[] = $lastprintout;
00295 } elseif ( $param[0] == '+' ) {
00296 if ( !is_null( $lastprintout ) ) {
00297 $param = substr( $param, 1 );
00298 $parts = explode( '=', $param, 2 );
00299 if ( count( $parts ) == 2 ) {
00300 $lastprintout->setParameter( trim( $parts[0] ), $parts[1] );
00301 }
00302 }
00303 } else {
00304 $parts = explode( '=', $param, 2 );
00305
00306 if ( count( $parts ) >= 2 ) {
00307 $params[strtolower( trim( $parts[0] ) )] = $parts[1];
00308 } else {
00309 $querystring .= $param;
00310 }
00311 }
00312 }
00313
00314 $querystring = str_replace( array( '<', '>' ), array( '<', '>' ), $querystring );
00315 if ( $showmode ) {
00316 $querystring = "[[:$querystring]]";
00317 }
00318 }
00319
00330 static public function getResultFromFunctionParams( array $rawparams, $outputmode, $context = self::INLINE_QUERY, $showmode = false ) {
00331 self::processFunctionParams( $rawparams, $querystring, $params, $printouts, $showmode );
00332
00333 if ( !$showmode ) {
00334 self::addThisPrintout( $printouts, $params, $showmode );
00335 }
00336
00337 $params = self::getProcessedParams( $params, $printouts );
00338
00339 return self::getResultFromQueryString( $querystring, $params, $printouts, SMW_OUTPUT_WIKI, $context );
00340 }
00341
00356 static public function getResultFromQueryString( $querystring, array $params, $extraprintouts, $outputmode, $context = self::INLINE_QUERY ) {
00357 wfProfileIn( 'SMWQueryProcessor::getResultFromQueryString (SMW)' );
00358
00359 $format = $params['format'];
00360 $query = self::createQuery( $querystring, $params, $context, $format, $extraprintouts );
00361 $result = self::getResultFromQuery( $query, $params, $extraprintouts, $outputmode, $context, $format );
00362
00363 wfProfileOut( 'SMWQueryProcessor::getResultFromQueryString (SMW)' );
00364
00365 return $result;
00366 }
00367
00380 static public function getResultFromQuery( SMWQuery $query, array $params, $extraprintouts, $outputmode, $context = self::INLINE_QUERY, $format = '' ) {
00381 wfProfileIn( 'SMWQueryProcessor::getResultFromQuery (SMW)' );
00382
00383
00384
00385
00386 global $smwgQuerySources;
00387
00388 if ( array_key_exists( 'source', $params ) && array_key_exists( $params['source'], $smwgQuerySources ) ) {
00389 $store = new $smwgQuerySources[$params['source']]();
00390 $query->params = $params;
00391 } else {
00392 $store = smwfGetStore();
00393 }
00394
00395 $res = $store->getQueryResult( $query );
00396
00397 if ( ( $query->querymode == SMWQuery::MODE_INSTANCES ) || ( $query->querymode == SMWQuery::MODE_NONE ) ) {
00398 wfProfileIn( 'SMWQueryProcessor::getResultFromQuery-printout (SMW)' );
00399
00400 if ( $format === '' ) {
00401 $format = self::getResultFormat( $params );
00402 }
00403
00404 $printer = self::getResultPrinter( $format, $context, $res );
00405 $result = $printer->getResult( $res, $params, $outputmode );
00406
00407 wfProfileOut( 'SMWQueryProcessor::getResultFromQuery-printout (SMW)' );
00408 wfProfileOut( 'SMWQueryProcessor::getResultFromQuery (SMW)' );
00409
00410 return $result;
00411 } else {
00412 if ( is_numeric( $res ) ) {
00413 $res = strval( $res );
00414 }
00415 if ( is_string( $res ) ) {
00416 if ( array_key_exists( 'intro', $params ) ) {
00417 $res = str_replace( '_', ' ', $params['intro'] ) . $res;
00418 }
00419 if ( array_key_exists( 'outro', $params ) ) {
00420 $res .= str_replace( '_', ' ', $params['outro'] );
00421 }
00422
00423 $result = $res . smwfEncodeMessages( $query->getErrors() );
00424 } else {
00425 $result = smwfEncodeMessages( $query->getErrors() );
00426 }
00427
00428 wfProfileOut( 'SMWQueryProcessor::getResultFromQuery (SMW)' );
00429
00430 return $result;
00431 }
00432 }
00433
00444 static public function getResultPrinter( $format, $context = self::SPECIAL_PAGE ) {
00445 global $smwgResultFormats;
00446
00447 if ( !array_key_exists( $format, $smwgResultFormats ) ) {
00448 throw new MWException( "There is no result format for '$format'." );
00449 }
00450
00451 $formatClass = $smwgResultFormats[$format];
00452
00453 return new $formatClass( $format, ( $context != self::SPECIAL_PAGE ) );
00454 }
00455
00465 static protected function getResultFormat( array $params ) {
00466 $format = 'auto';
00467
00468 if ( array_key_exists( 'format', $params ) ) {
00469 global $smwgResultFormats;
00470
00471 $format = strtolower( trim( $params['format'] ) );
00472
00473 if ( !array_key_exists( $format, $smwgResultFormats ) ) {
00474 $isAlias = SMWParamFormat::resolveFormatAliases( $format );
00475 if ( !$isAlias ) {
00476 $format = 'auto';
00477 }
00478 }
00479 }
00480
00481 return $format;
00482 }
00483
00496 public static function getParameters() {
00497 $params = array();
00498
00499 $allowedFormats = $GLOBALS['smwgResultFormats'];
00500
00501 foreach ( $GLOBALS['smwgResultAliases'] as $aliases ) {
00502 $allowedFormats += $aliases;
00503 }
00504
00505 $allowedFormats[] = 'auto';
00506
00507 $params['format'] = new Parameter( 'format' );
00508 $params['format']->setDefault( 'auto' );
00509
00510
00511 $params['limit'] = new Parameter( 'limit', Parameter::TYPE_INTEGER );
00512 $params['limit']->setMessage( 'smw_paramdesc_limit' );
00513 $params['limit']->setDefault( $GLOBALS['smwgQDefaultLimit'] );
00514
00515 $params['sort'] = new ListParameter( 'sort' );
00516 $params['sort']->setMessage( 'smw-paramdesc-sort' );
00517 $params['sort']->setDefault( array( '' ) );
00518
00519 $params['order'] = new ListParameter( 'order' );
00520 $params['order']->setMessage( 'smw-paramdesc-order' );
00521 $params['order']->setDefault( array() );
00522 $params['order']->addCriteria( new CriterionInArray( 'descending', 'desc', 'asc', 'ascending', 'rand', 'random' ) );
00523
00524 $params['offset'] = new Parameter( 'offset', Parameter::TYPE_INTEGER );
00525 $params['offset']->setMessage( 'smw_paramdesc_offset' );
00526 $params['offset']->setDefault( 0 );
00527
00528 $params['headers'] = new Parameter( 'headers' );
00529 $params['headers']->setMessage( 'smw_paramdesc_headers' );
00530 $params['headers']->addCriteria( new CriterionInArray( 'show', 'hide', 'plain' ) );
00531 $params['headers']->setDefault( 'show' );
00532
00533 $params['mainlabel'] = new Parameter( 'mainlabel' );
00534 $params['mainlabel']->setMessage( 'smw_paramdesc_mainlabel' );
00535 $params['mainlabel']->setDefault( false, false );
00536
00537 $params['link'] = new Parameter( 'link' );
00538 $params['link']->setMessage( 'smw_paramdesc_link' );
00539 $params['link']->addCriteria( new CriterionInArray( 'all', 'subject', 'none' ) );
00540 $params['link']->setDefault( 'all' );
00541
00542 $params['searchlabel'] = new Parameter( 'searchlabel' );
00543 $params['searchlabel']->setDefault( false, false );
00544 $params['searchlabel']->setMessage( 'smw-paramdesc-searchlabel' );
00545
00546 return $params;
00547 }
00548
00549 }