summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/SemanticMediaWiki/src/Query/Processor/QueryCreator.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/src/Query/Processor/QueryCreator.php')
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/src/Query/Processor/QueryCreator.php252
1 files changed, 252 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/src/Query/Processor/QueryCreator.php b/www/wiki/extensions/SemanticMediaWiki/src/Query/Processor/QueryCreator.php
new file mode 100644
index 00000000..7d2ac2be
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/src/Query/Processor/QueryCreator.php
@@ -0,0 +1,252 @@
+<?php
+
+namespace SMW\Query\Processor;
+
+use SMW\DataValueFactory;
+use SMW\Localizer;
+use SMW\Query\QueryContext;
+use SMW\QueryFactory;
+use SMWPropertyValue as PropertyValue;
+
+/**
+ * @private
+ *
+ * @license GNU GPL v2+
+ * @since 2.5
+ *
+ * @author mwjames
+ */
+class QueryCreator implements QueryContext {
+
+ /**
+ * @var QueryFactory
+ */
+ private $queryFactory;
+
+ /**
+ * @var array
+ */
+ private $params = [];
+
+ /**
+ * @see smwgQDefaultNamespaces
+ * @var null|array
+ */
+ private $defaultNamespaces = null;
+
+ /**
+ * @see smwgQDefaultLimit
+ * @var integer
+ */
+ private $defaultLimit = 0;
+
+ /**
+ * @see smwgQFeatures
+ * @var integer
+ */
+ private $queryFeatures = 0;
+
+ /**
+ * @see smwgQConceptFeatures
+ * @var integer
+ */
+ private $conceptFeatures = 0;
+
+ /**
+ * @since 2.5
+ *
+ * @param QueryFactory $queryFactory
+ * @param array|null $defaultNamespaces
+ * @param integer $defaultLimit
+ */
+ public function __construct( QueryFactory $queryFactory, $defaultNamespaces = null, $defaultLimit = 50 ) {
+ $this->queryFactory = $queryFactory;
+ $this->defaultNamespaces = $defaultNamespaces;
+ $this->defaultLimit = $defaultLimit;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param integer $queryFeatures
+ */
+ public function setQFeatures( $queryFeatures ) {
+ $this->queryFeatures = $queryFeatures;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param integer $conceptFeatures
+ */
+ public function setQConceptFeatures( $conceptFeatures ) {
+ $this->conceptFeatures = $conceptFeatures;
+ }
+
+ /**
+ * Parse a query string given in SMW's query language to create an Query.
+ * Parameters are given as key-value-pairs in the given array. The parameter
+ * $context defines in what context the query is used, which affects certaim
+ * general settings.
+ *
+ * @since 2.5
+ *
+ * @param string $queryString
+ * @param array $params
+ *
+ * @return Query
+ */
+ public function create( $queryString, array $params = [] ) {
+
+ $this->params = $params;
+ $context = $this->getParam( 'context', self::INLINE_QUERY );
+
+ $queryParser = $this->queryFactory->newQueryParser(
+ $context == self::CONCEPT_DESC ? $this->conceptFeatures : $this->queryFeatures
+ );
+
+ $contextPage = $this->getParam( 'contextPage', null );
+ $queryMode = $this->getParam( 'queryMode', self::MODE_INSTANCES );
+
+ $queryParser->setContextPage( $contextPage );
+ $queryParser->setDefaultNamespaces( $this->defaultNamespaces );
+
+ $query = $this->queryFactory->newQuery(
+ $queryParser->getQueryDescription( $queryString ),
+ $context
+ );
+
+ $query->setQueryToken( $queryParser->getQueryToken() );
+ $query->setQueryString( $queryString );
+ $query->setContextPage( $contextPage );
+ $query->setQueryMode( $queryMode );
+
+ $query->setExtraPrintouts(
+ $this->getParam( 'extraPrintouts', [] )
+ );
+
+ $query->setMainLabel(
+ $this->getParam( 'mainLabel', '' )
+ );
+
+ $query->setQuerySource(
+ $this->getParam( 'source', null )
+ );
+
+ $query->setOption(
+ 'self.reference',
+ $queryParser->containsSelfReference()
+ );
+
+ // keep parsing or other errors for later output
+ $query->addErrors(
+ $queryParser->getErrors()
+ );
+
+ // set sortkeys, limit, and offset
+ $query->setOffset(
+ max( 0, trim( $this->getParam( 'offset', 0 ) ) + 0 )
+ );
+
+ $query->setLimit(
+ max( 0, trim( $this->getParam( 'limit', $this->defaultLimit ) ) + 0 ),
+ $queryMode != self::MODE_COUNT
+ );
+
+ $sortKeys = $this->getSortKeys(
+ $this->getParam( 'sort', [] ),
+ $this->getParam( 'order', [] ),
+ $this->getParam( 'defaultSort', 'ASC' )
+ );
+
+ $query->addErrors(
+ $sortKeys['errors']
+ );
+
+ $query->setSortKeys(
+ $sortKeys['keys']
+ );
+
+ return $query;
+ }
+
+ /**
+ * @since 2.5
+ *
+ * @param array $sortParameters
+ * @param array $orderParameters
+ * @param string $defaultSort
+ *
+ * @return array ( keys => array(), errors => array() )
+ */
+ private function getSortKeys( array $sortParameters, array $orderParameters, $defaultSort ) {
+
+ $sortKeys = [];
+ $sortErros = [];
+
+ $orders = $this->normalize_order( $orderParameters );
+
+ foreach ( $sortParameters as $sort ) {
+ $sortKey = false;
+
+ // An empty string indicates we mean the page, such as element 0 on the next line.
+ // sort=,Some property
+ if ( trim( $sort ) === '' ) {
+ $sortKey = '';
+ } else {
+
+ $propertyValue = DataValueFactory::getInstance()->newDataValueByType( PropertyValue::TYPE_ID );
+ $propertyValue->setOption( PropertyValue::OPT_QUERY_CONTEXT, true );
+
+ $propertyValue->setUserValue(
+ $this->normalize_sort( trim( $sort ) )
+ );
+
+ if ( $propertyValue->isValid() ) {
+ $sortKey = $propertyValue->getDataItem()->getKey();
+ } else {
+ $sortErros = array_merge( $sortErros, $propertyValue->getErrors() );
+ }
+ }
+
+ if ( $sortKey !== false ) {
+ $order = empty( $orders ) ? $defaultSort : array_shift( $orders );
+ $sortKeys[$sortKey] = $order;
+ }
+ }
+
+ // If more sort arguments are provided then properties, assume the first one is for the page.
+ // TODO: we might want to add errors if there is more then one.
+ if ( !array_key_exists( '', $sortKeys ) && !empty( $orders ) ) {
+ $sortKeys[''] = array_shift( $orders );
+ }
+
+ return [ 'keys' => $sortKeys, 'errors' => $sortErros ];
+ }
+
+ private function normalize_order( $orderParameters ) {
+ $orders = [];
+
+ foreach ( $orderParameters as $key => $order ) {
+ $order = strtolower( trim( $order ) );
+ if ( ( $order == 'descending' ) || ( $order == 'reverse' ) || ( $order == 'desc' ) ) {
+ $orders[$key] = 'DESC';
+ } elseif ( ( $order == 'random' ) || ( $order == 'rand' ) ) {
+ $orders[$key] = 'RANDOM';
+ } else {
+ $orders[$key] = 'ASC';
+ }
+ }
+
+ return $orders;
+ }
+
+ private function normalize_sort( $sort ) {
+ return Localizer::getInstance()->getNamespaceTextById( NS_CATEGORY ) == mb_convert_case( $sort, MB_CASE_TITLE ) ? '_INST' : $sort;
+ }
+
+ private function getParam( $key, $default ) {
+ return isset( $this->params[$key] ) ? $this->params[$key] : $default;
+ }
+
+}