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 ) ) { |
|
|
|
|
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 ); |
|
|
|
|
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
|
|
|
} |
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 thecomposer.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
orrequire-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 you have not tested against this specific condition, such errors might go unnoticed.