This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Wikibase\Repo\ParserOutput; |
||
4 | |||
5 | use DataValues\Geo\Values\GlobeCoordinateValue; |
||
6 | use ExtensionRegistry; |
||
7 | use GeoData\Coord; |
||
8 | use GeoData\CoordinatesOutput; |
||
9 | use ParserOutput; |
||
10 | use RuntimeException; |
||
11 | use Wikibase\DataModel\Services\Entity\PropertyDataTypeMatcher; |
||
12 | use Wikibase\DataModel\Snak\PropertyValueSnak; |
||
13 | use Wikibase\DataModel\Statement\Statement; |
||
14 | |||
15 | /** |
||
16 | * Extracts and stashes coordinates from Statement main snaks and |
||
17 | * adds to ParserOutput for use by the GeoData extension. |
||
18 | * |
||
19 | * GeoData populates the geo_tags table, and if using |
||
20 | * the 'elastic' backend, also adds coordinates to CirrusSearch. |
||
21 | * GeoData then provides API modules to get coordinates for pages, |
||
22 | * and to find nearby pages to a requested location. |
||
23 | * |
||
24 | * This class uses the Coord and CoordinatesOutput classes from the |
||
25 | * GeoData extension. |
||
26 | * |
||
27 | * @license GPL-2.0-or-later |
||
28 | * @author Katie Filbert < [email protected] > |
||
29 | */ |
||
30 | class GeoDataDataUpdater implements StatementDataUpdater { |
||
31 | |||
32 | /** |
||
33 | * @var PropertyDataTypeMatcher |
||
34 | */ |
||
35 | private $propertyDataTypeMatcher; |
||
36 | |||
37 | /** |
||
38 | * @var string[] |
||
39 | */ |
||
40 | private $preferredPropertiesIds; |
||
41 | |||
42 | /** |
||
43 | * @var string[] |
||
44 | */ |
||
45 | private $globeUris; |
||
46 | |||
47 | /** |
||
48 | * @var array[] |
||
49 | */ |
||
50 | private $coordinates = []; |
||
51 | |||
52 | /** |
||
53 | * @param PropertyDataTypeMatcher $propertyDataTypeMatcher |
||
54 | * @param string[] $preferredPropertiesIds |
||
55 | * @param string[] $globeUris |
||
56 | * |
||
57 | * @throws RuntimeException |
||
58 | */ |
||
59 | public function __construct( |
||
60 | PropertyDataTypeMatcher $propertyDataTypeMatcher, |
||
61 | array $preferredPropertiesIds, |
||
62 | array $globeUris |
||
63 | ) { |
||
64 | if ( !ExtensionRegistry::getInstance()->isLoaded( 'GeoData' ) ) { |
||
65 | throw new RuntimeException( 'GeoDataDataUpdater requires the GeoData extension ' |
||
66 | . 'to be enabled' ); |
||
67 | } |
||
68 | |||
69 | $this->propertyDataTypeMatcher = $propertyDataTypeMatcher; |
||
70 | $this->preferredPropertiesIds = $preferredPropertiesIds; |
||
71 | $this->globeUris = $globeUris; |
||
72 | } |
||
73 | |||
74 | /** |
||
75 | * Extract globe-coordinate DataValues for storing in ParserOutput for GeoData. |
||
76 | * |
||
77 | * @param Statement $statement |
||
78 | */ |
||
79 | public function processStatement( Statement $statement ) { |
||
80 | $propertyId = $statement->getPropertyId(); |
||
81 | |||
82 | if ( $this->propertyDataTypeMatcher->isMatchingDataType( |
||
83 | $propertyId, |
||
84 | 'globe-coordinate' |
||
85 | ) ) { |
||
86 | $rank = $statement->getRank(); |
||
87 | |||
88 | if ( $rank !== Statement::RANK_DEPRECATED ) { |
||
89 | $coordinate = $this->extractMainSnakCoord( $statement ); |
||
90 | |||
91 | if ( $coordinate instanceof Coord ) { |
||
0 ignored issues
–
show
|
|||
92 | $key = $this->makeCoordinateKey( $propertyId->getSerialization(), $rank ); |
||
93 | $this->coordinates[$key][] = $coordinate; |
||
94 | } |
||
95 | } |
||
96 | } |
||
97 | } |
||
98 | |||
99 | public function updateParserOutput( ParserOutput $parserOutput ) { |
||
100 | $coordinatesOutput = CoordinatesOutput::getOrBuildFromParserOutput( $parserOutput ); |
||
101 | $primaryCoordKey = $this->findPrimaryCoordinateKey(); |
||
102 | |||
103 | if ( !$coordinatesOutput->hasPrimary() && $primaryCoordKey !== null ) { |
||
104 | $this->addPrimaryCoordinate( $coordinatesOutput, $primaryCoordKey ); |
||
105 | } |
||
106 | |||
107 | $this->addSecondaryCoordinates( $coordinatesOutput, $primaryCoordKey ); |
||
108 | $coordinatesOutput->setToParserOutput( $parserOutput ); |
||
109 | } |
||
110 | |||
111 | /** |
||
112 | * @return string|null Array key for Coord selected as primary. |
||
113 | */ |
||
114 | private function findPrimaryCoordinateKey() { |
||
115 | foreach ( $this->preferredPropertiesIds as $id ) { |
||
116 | $key = $this->makeCoordinateKey( $id, Statement::RANK_PREFERRED ); |
||
117 | $preferredCount = $this->getCoordinatesGroupCount( $key ); |
||
118 | |||
119 | if ( $preferredCount === 1 ) { |
||
120 | return $key; |
||
121 | } elseif ( $preferredCount === 0 ) { |
||
122 | $key = $this->makeCoordinateKey( $id, Statement::RANK_NORMAL ); |
||
123 | $normalCount = $this->getCoordinatesGroupCount( $key ); |
||
124 | |||
125 | if ( $normalCount === 1 ) { |
||
126 | return $key; |
||
127 | } elseif ( $normalCount > 1 ) { |
||
128 | // multiple normal coordinates |
||
129 | return null; |
||
130 | } |
||
131 | } else { |
||
132 | // multiple preferred coordinates |
||
133 | return null; |
||
134 | } |
||
135 | } |
||
136 | |||
137 | return null; |
||
138 | } |
||
139 | |||
140 | /** |
||
141 | * @param string $key |
||
142 | * |
||
143 | * @return int |
||
144 | */ |
||
145 | private function getCoordinatesGroupCount( $key ) { |
||
146 | if ( isset( $this->coordinates[$key] ) ) { |
||
147 | return count( $this->coordinates[$key] ); |
||
148 | } |
||
149 | |||
150 | return 0; |
||
151 | } |
||
152 | |||
153 | /** |
||
154 | * @param CoordinatesOutput $coordinatesOutput |
||
155 | * @param string $primaryCoordKey |
||
156 | */ |
||
157 | private function addPrimaryCoordinate( |
||
158 | CoordinatesOutput $coordinatesOutput, |
||
159 | $primaryCoordKey |
||
160 | ) { |
||
161 | $primaryCoordinate = $this->coordinates[$primaryCoordKey][0]; |
||
162 | $primaryCoordinate->primary = true; |
||
163 | |||
164 | $coordinatesOutput->addPrimary( $primaryCoordinate ); |
||
165 | } |
||
166 | |||
167 | /** |
||
168 | * @param CoordinatesOutput $coordinatesOutput |
||
169 | * @param string|null $primaryCoordKey |
||
170 | */ |
||
171 | private function addSecondaryCoordinates( |
||
172 | CoordinatesOutput $coordinatesOutput, |
||
173 | $primaryCoordKey |
||
174 | ) { |
||
175 | foreach ( $this->coordinates as $key => $coords ) { |
||
176 | if ( $key !== $primaryCoordKey ) { |
||
177 | foreach ( $coords as $coord ) { |
||
178 | $coordinatesOutput->addSecondary( $coord ); |
||
179 | } |
||
180 | } |
||
181 | } |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * @param string $propertyIdString |
||
186 | * @param int $rank |
||
187 | * |
||
188 | * @return string |
||
189 | */ |
||
190 | private function makeCoordinateKey( $propertyIdString, $rank ) { |
||
191 | return $propertyIdString . '|' . $rank; |
||
192 | } |
||
193 | |||
194 | /** |
||
195 | * @param Statement $statement |
||
196 | * |
||
197 | * @return Coord|null |
||
198 | */ |
||
199 | private function extractMainSnakCoord( Statement $statement ) { |
||
200 | $snak = $statement->getMainSnak(); |
||
201 | |||
202 | if ( !( $snak instanceof PropertyValueSnak ) ) { |
||
203 | return null; |
||
204 | } |
||
205 | |||
206 | $dataValue = $snak->getDataValue(); |
||
207 | |||
208 | if ( !( $dataValue instanceof GlobeCoordinateValue ) ) { |
||
209 | // Property data type - value mismatch |
||
210 | return null; |
||
211 | } |
||
212 | |||
213 | $globeUri = $dataValue->getGlobe(); |
||
214 | |||
215 | if ( !isset( $this->globeUris[$globeUri] ) ) { |
||
216 | // Unknown globe |
||
217 | return null; |
||
218 | } |
||
219 | |||
220 | return new Coord( |
||
221 | $dataValue->getLatitude(), |
||
222 | $dataValue->getLongitude(), |
||
223 | $this->globeUris[$globeUri] |
||
224 | ); |
||
225 | } |
||
226 | |||
227 | } |
||
228 |
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.