public static function createQuery($querystring, $params, $context = SMWQueryProcessor::INLINE_QUERY, $format = '', $extraprintouts = array())
 {
     global $smwgQDefaultNamespaces, $smwgQFeatures, $smwgQConceptFeatures;
     // parse query:
     if ($context == SMWQueryProcessor::CONCEPT_DESC) {
         $queryfeatures = $smwgQConceptFeatures;
     } else {
         $queryfeatures = $smwgQFeatures;
     }
     $qp = new SMWSPARQLQueryParser($queryfeatures);
     $qp->setDefaultNamespaces($smwgQDefaultNamespaces);
     $desc = $qp->getQueryDescription($querystring);
     if ($format == '') {
         $format = SMWQueryProcessor::getResultFormat($params);
     }
     if ($format == 'count') {
         $querymode = SMWQuery::MODE_COUNT;
     } elseif ($format == 'debug') {
         $querymode = SMWQuery::MODE_DEBUG;
     } elseif (in_array($format, array('rss', 'icalendar', 'vcard', 'csv'))) {
         $querymode = SMWQuery::MODE_NONE;
     } else {
         $querymode = SMWQuery::MODE_INSTANCES;
     }
     if (array_key_exists('mainlabel', $params)) {
         $mainlabel = $params['mainlabel'] . $qp->getLabel();
     } else {
         $mainlabel = $qp->getLabel();
     }
     if ($querymode == SMWQuery::MODE_NONE || (!$desc->isSingleton() || count($desc->getPrintRequests()) + count($extraprintouts) == 0) && $mainlabel != '-') {
         $desc->prependPrintRequest(new SMWPrintRequest(SMWPrintRequest::PRINT_THIS, $mainlabel));
     }
     $mergeResults = array_key_exists('merge', $params) ? $params['merge'] == 'true' : true;
     $query = new SMWSPARQLQuery($desc, true);
     $query->params = $params;
     $query->mergeResults = $mergeResults;
     $query->fromASK = strpos($querystring, 'SELECT') === false;
     $query->mainLabelMissing = $mainlabel == '-';
     $query->setQueryString($querystring);
     $query->setExtraPrintouts($extraprintouts);
     $query->addErrors($qp->getErrors());
     // set query parameters:
     $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);
         }
     }
     // determine sortkeys and ascendings:
     if (array_key_exists('order', $params)) {
         $orders = explode(',', $params['order']);
         foreach ($orders as $key => $order) {
             // normalise
             $order = strtolower(trim($order));
             if ('descending' == $order || 'reverse' == $order || 'desc' == $order) {
                 $orders[$key] = 'DESC';
             } elseif ('random' == $order || 'rand' == $order) {
                 $orders[$key] = 'RAND()';
             } else {
                 $orders[$key] = 'ASC';
             }
         }
     } else {
         $orders = array();
     }
     reset($orders);
     if (array_key_exists('sort', $params)) {
         $query->sort = true;
         $query->sortkeys = array();
         foreach (explode(',', trim($params['sort'])) as $sort) {
             $sort = smwfNormalTitleDBKey(trim($sort));
             // slight normalisation
             $order = current($orders);
             if ($order === false) {
                 // default
                 $order = 'ASC';
             }
             if (array_key_exists($sort, $query->sortkeys)) {
                 // maybe throw an error here?
             } else {
                 $query->sortkeys[$sort] = $order;
             }
             next($orders);
         }
         if (current($orders) !== false) {
             // sort key remaining, apply to page name
             $query->sortkeys[''] = current($orders);
         }
     } elseif ($format == 'rss') {
         // unsorted RSS: use *descending* default order
         ///TODO: the default sort field should be "modification date" (now it is the title, but
         ///likely to be overwritten by printouts with label "date").
         $query->sortkeys[''] = current($orders) != false ? current($orders) : 'DESC';
     } else {
         // sort by page title (main column) by default
         $query->sortkeys[''] = current($orders) != false ? current($orders) : 'ASC';
     }
     // TODO: check and report if there are further order statements?
     return $query;
 }