Completed
Push — master ( f04bbc...eab9d5 )
by Jeroen De
07:09
created

SMAreaValueDescription::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 4
dl 0
loc 12
ccs 0
cts 9
cp 0
crap 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
use DataValues\Geo\Values\LatLongValue;
4
use SMW\DataValueFactory;
5
6
/**
7
 * Description of a geographical area defined by a coordinates set and a distance to the bounds.
8
 * The bounds are a 'rectangle' (but bend due to the earths curvature), as the resulting query
9
 * would otherwise be to resource intensive.
10
 *
11
 * @since 0.6
12
 *
13
 * @licence GNU GPL v2+
14
 * @author Jeroen De Dauw < [email protected]
15
 * 
16
 * TODO: would be awesome to use Spatial Extensions to select coordinates
17
 */
18
class SMAreaValueDescription extends SMWValueDescription {
19
	
20
	/**
21
	 * Associative array containing the bounds of the area, or false when not set.
22
	 * 
23
	 * @since 0.6
24
	 * 
25
	 * @var mixed
26
	 */
27
	protected $bounds = false;
28
29
	/**
30
	 * @since 3.0
31
	 *
32
	 * @var SMWDIGeoCoord
33
	 */
34
	protected $center;
35
36
	/**
37
	 * @since 3.0
38
	 *
39
	 * @var string
40
	 */
41
	protected $radius;
42
43
	/**
44
	 * @param SMWDataItem $areaCenter
45
	 * @param string $comparator
46
	 * @param string $radius
47
	 * @param SMWDIProperty $property
48
	 *
49
	 * @throws InvalidArgumentException
50
	 */
51
	public function __construct( SMWDataItem $areaCenter, $comparator, $radius, SMWDIProperty $property = null ) {
52
		if ( !( $areaCenter instanceof SMWDIGeoCoord ) ) {
0 ignored issues
show
Bug introduced by
The class SMWDIGeoCoord does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
53
			throw new InvalidArgumentException( '$areaCenter needs to be a SMWDIGeoCoord' );
54
		}
55
56
		parent::__construct( $areaCenter, $property, $comparator );
57
58
		$this->radius = MapsDistanceParser::parseDistance( $radius );
0 ignored issues
show
Documentation Bug introduced by
It seems like \MapsDistanceParser::parseDistance($radius) of type false or double is incompatible with the declared type string of property $radius.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
59
		$this->center = $areaCenter;
60
61
		$this->bounds = $this->getBoundingBox();
62
	}
63
64
	private function getPropertyCompat() {
65
		return method_exists( $this, 'getProperty' ) ? $this->getProperty() : $this->m_property;
66
	}
67
68
	/**
69
	 * @see SMWDescription:getQueryString
70
	 * 
71
	 * @since 0.6
72
	 * 
73
	 * @param boolean $asValue
74
	 * @return string
75
	 */
76
	public function getQueryString( $asValue = false ) {
77
		if ( $this->getDataItem() !== null ) {
78
			$queryString = DataValueFactory::newDataItemValue( $this->getDataItem(), $this->getPropertyCompat() )->getWikiValue();
79
			return $asValue ? $queryString : "[[$queryString]]";
80
		} else {
81
			return $asValue ? '+' : '';
82
		}
83
	}
84
85
	/**
86
	 * @see SMWDescription:prune
87
	 * 
88
	 * @since 0.6
89
	 */
90
    public function prune( &$maxsize, &$maxdepth, &$log ) {
91
    	if ( ( $maxsize < $this->getSize() ) || ( $maxdepth < $this->getDepth() ) ) {
92
			$log[] = $this->getQueryString();
93
			
94
			$result = new SMWThingDescription();
95
			$result->setPrintRequests( $this->getPrintRequests() );
96
			
97
			return $result;
98
		} else {
99
			$maxsize = $maxsize - $this->getSize();
100
			$maxdepth = $maxdepth - $this->getDepth();
101
			return $this;
102
		}
103
    }
104
    
105
    /**
106
     * Returns the bounds of the area.
107
     * 
108
     * @since 0.6
109
     * 
110
     * @return array
111
     */
112
    public function getBounds() {
113
    	return $this->bounds;
114
    }    
115
	
116
	/**
117
	 * @see SMWDescription::getSQLCondition
118
	 *
119
	 * FIXME: store specific code should be in the store component
120
	 *
121
	 * @since 0.6
122
	 * 
123
	 * @param string $tableName
124
	 * @param array $fieldNames
125
	 * @param DatabaseBase $dbs
126
	 * 
127
	 * @return string or false
128
	 */
129
	public function getSQLCondition( $tableName, array $fieldNames, DatabaseBase $dbs ) {
130
		// Only execute the query when the description's type is geographical coordinates,
131
		// the description is valid, and the near comparator is used.
132
		if ( $this->getDataItem()->getDIType() != SMWDataItem::TYPE_GEO
133
			|| ( $this->getComparator() != SMW_CMP_EQ && $this->getComparator() != SMW_CMP_NEQ )
134
			) {
135
			return false;
136
		}
137
		
138
		$north = $dbs->addQuotes( $this->bounds['north'] );
139
		$east = $dbs->addQuotes( $this->bounds['east'] );
140
		$south = $dbs->addQuotes( $this->bounds['south'] );
141
		$west = $dbs->addQuotes( $this->bounds['west'] );
142
143
		$isEq = $this->getComparator() == SMW_CMP_EQ;
144
		
145
        $conditions = [];
146
147
        $smallerThen = $isEq ? '<' : '>=';
148
        $biggerThen = $isEq ? '>' : '<=';
149
        $joinCond = $isEq ? 'AND' : 'OR';
150
151
        $conditions[] = "{$tableName}.$fieldNames[1] $smallerThen $north";
152
        $conditions[] = "{$tableName}.$fieldNames[1] $biggerThen $south";
153
        $conditions[] = "{$tableName}.$fieldNames[2] $smallerThen $east";
154
        $conditions[] = "{$tableName}.$fieldNames[2] $biggerThen $west";
155
156
        $sql = implode( " $joinCond ", $conditions );
157
158
		return $sql;
159
	}
160
161
	/**
162
	 * @return float[] An associative array containing the limits with keys north, east, south and west.
163
	 */
164
	protected function getBoundingBox() {
165
		$center = new LatLongValue(
166
			$this->center->getLatitude(),
167
			$this->center->getLongitude()
168
		);
169
170
		$north = MapsGeoFunctions::findDestination( $center, 0, $this->radius );
171
		$east = MapsGeoFunctions::findDestination( $center, 90, $this->radius );
172
		$south = MapsGeoFunctions::findDestination( $center, 180, $this->radius );
173
		$west = MapsGeoFunctions::findDestination( $center, 270, $this->radius );
174
175
		return [
176
			'north' => $north['lat'],
177
			'east' => $east['lon'],
178
			'south' => $south['lat'],
179
			'west' => $west['lon'],
180
		];
181
	}
182
	
183
	/**
184
	 * Returns a boolean indicating if MapsGeoFunctions is available. 
185
	 * 
186
	 * @since 0.6
187
	 * 
188
	 * @return boolean
189
	 */
190
	protected function geoFunctionsAreAvailable() {
191
		return class_exists( 'MapsGeoFunctions' );
192
	}	
193
	
194
}