summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/SemanticMediaWiki/src/Elastic/QueryEngine/DescriptionInterpreters/ClassDescriptionInterpreter.php
blob: 68c49fa9496eb6304c0dae820c3dc847c8327375 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<?php

namespace SMW\Elastic\QueryEngine\DescriptionInterpreters;

use SMW\DIProperty;
use SMW\Elastic\QueryEngine\ConditionBuilder;
use SMW\Elastic\QueryEngine\Condition;
use SMW\Query\Language\ClassDescription;

/**
 * @license GNU GPL v2+
 * @since 3.0
 *
 * @author mwjames
 */
class ClassDescriptionInterpreter {

	/**
	 * @var ConditionBuilder
	 */
	private $conditionBuilder;

	/**
	 * @since 3.0
	 *
	 * @param ConditionBuilder $conditionBuilder
	 */
	public function __construct( ConditionBuilder $conditionBuilder ) {
		$this->conditionBuilder = $conditionBuilder;
	}

	/**
	 * @since 3.0
	 *
	 * @param ClassDescription $description
	 *
	 * @return Condition
	 */
	public function interpretDescription( ClassDescription $description, $isConjunction = false ) {

		$pid = 'P:' . $this->conditionBuilder->getID( new DIProperty( '_INST' ) );
		$field = 'wpgID';

		$dataItems = $description->getCategories();
		$hierarchyDepth = $description->getHierarchyDepth();

		$should = false;
		$params = [];

		// More than one member per list means OR
		if ( count( $dataItems ) > 1 ) {
			$should = true;
		}

		$fieldMapper = $this->conditionBuilder->getFieldMapper();

		foreach ( $dataItems as $dataItem ) {
			$value = $this->conditionBuilder->getID( $dataItem );

			$p = $fieldMapper->term( "$pid.$field", $value );
			$hierarchy = [];

			$ids = $this->conditionBuilder->findHierarchyMembers( $dataItem, $hierarchyDepth );

			if ( $ids !== [] ) {
				$hierarchy[] = $fieldMapper->terms( "$pid.$field", $ids );
			}

			// Hierarchies cannot be build as part of the normal index process
			// therefore use the consecutive list to build a chain of disjunctive
			// (should === OR) queries to match members of the list
			if ( $hierarchy !== [] ) {
				$params[] = $fieldMapper->bool( Condition::TYPE_SHOULD, array_merge( [ $p ], $hierarchy ) );
			} else {
				$params[] = $p;
			}
		}

		// This feature is NOT supported by the SQLStore!!
		// Encapsulate condition for something like `[[Category:!CatTest1]] ...`
		if ( isset( $description->isNegation ) && $description->isNegation ) {
			$condition = $this->conditionBuilder->newCondition( $params );
			$condition->type( Condition::TYPE_MUST_NOT );
		} else {
			// ??!! If the description contains more than one category then it is
			// interpret as OR (same as the SQLStore) and only in the case of an AND
			// it is represented as Conjunction
			$condition = $this->conditionBuilder->newCondition( $params );
			$condition->type( ( $should ? Condition::TYPE_SHOULD : Condition::TYPE_FILTER ) );
		}

		$condition->log( [ 'ClassDescription' => $description->getQueryString() ] );

		return $condition;
	}

}