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\Client\Api; |
||
4 | |||
5 | use ApiBase; |
||
6 | use ApiQuery; |
||
7 | use ApiQueryBase; |
||
8 | use ApiResult; |
||
9 | use Wikibase\Client\RepoLinker; |
||
10 | use Wikibase\Client\Usage\EntityUsage; |
||
11 | use Wikibase\Client\WikibaseClient; |
||
12 | use Wikimedia\Rdbms\IResultWrapper; |
||
13 | |||
14 | /** |
||
15 | * API module to get the usage of entities. |
||
16 | * |
||
17 | * @license GPL-2.0-or-later |
||
18 | * @author Amir Sarabadani < [email protected] > |
||
19 | */ |
||
20 | class ApiPropsEntityUsage extends ApiQueryBase { |
||
21 | |||
22 | /** |
||
23 | * @var RepoLinker |
||
24 | */ |
||
25 | private $repoLinker = null; |
||
26 | |||
27 | /** |
||
28 | * @param ApiQuery $query |
||
29 | * @param string $moduleName |
||
30 | * @param RepoLinker $repoLinker |
||
31 | */ |
||
32 | public function __construct( ApiQuery $query, $moduleName, RepoLinker $repoLinker ) { |
||
33 | parent::__construct( $query, $moduleName, 'wbeu' ); |
||
34 | |||
35 | $this->repoLinker = $repoLinker; |
||
36 | } |
||
37 | |||
38 | public static function factory( ApiQuery $apiQuery, string $moduleName ): self { |
||
39 | return new self( |
||
40 | $apiQuery, |
||
41 | $moduleName, |
||
42 | WikibaseClient::getDefaultInstance()->newRepoLinker() |
||
43 | ); |
||
44 | } |
||
45 | |||
46 | public function execute() { |
||
47 | $params = $this->extractRequestParams(); |
||
48 | $res = $this->doQuery( $params ); |
||
49 | if ( !$res ) { |
||
50 | return; |
||
51 | } |
||
52 | |||
53 | $prop = array_flip( (array)$params['prop'] ); |
||
54 | $this->formatResult( $res, $params['limit'], $prop ); |
||
55 | } |
||
56 | |||
57 | /** |
||
58 | * @param IResultWrapper $res |
||
59 | * @param int $limit |
||
60 | * @param array $prop |
||
61 | */ |
||
62 | private function formatResult( IResultWrapper $res, $limit, array $prop ) { |
||
63 | $currentPageId = null; |
||
64 | $entry = []; |
||
65 | $count = 0; |
||
66 | |||
67 | foreach ( $res as $row ) { |
||
68 | if ( ++$count > $limit ) { |
||
69 | // We've reached the one extra which shows that |
||
70 | // there are additional pages to be had. Stop here... |
||
71 | $this->setContinueFromRow( $row ); |
||
72 | break; |
||
73 | } |
||
74 | |||
75 | if ( isset( $currentPageId ) && $row->eu_page_id !== $currentPageId ) { |
||
76 | // Flush out everything we built |
||
77 | $fit = $this->addPageSubItems( $currentPageId, $entry ); |
||
78 | if ( !$fit ) { |
||
79 | $this->setContinueFromRow( $row ); |
||
80 | break; |
||
81 | } |
||
82 | $entry = []; |
||
83 | } |
||
84 | $currentPageId = $row->eu_page_id; |
||
85 | if ( array_key_exists( $row->eu_entity_id, $entry ) ) { |
||
86 | $entry[$row->eu_entity_id]['aspects'][] = $row->eu_aspect; |
||
87 | } else { |
||
88 | $entry[$row->eu_entity_id] = [ 'aspects' => [ $row->eu_aspect ] ]; |
||
89 | if ( isset( $prop['url'] ) ) { |
||
90 | $entry[$row->eu_entity_id]['url'] = $this->repoLinker->getPageUrl( |
||
91 | 'Special:EntityPage/' . $row->eu_entity_id ); |
||
92 | } |
||
93 | ApiResult::setIndexedTagName( |
||
94 | $entry[$row->eu_entity_id]['aspects'], 'aspect' |
||
95 | ); |
||
96 | ApiResult::setArrayType( $entry, 'kvp', 'id' ); |
||
97 | } |
||
98 | |||
99 | } |
||
100 | |||
101 | if ( $entry ) { // Sanity |
||
0 ignored issues
–
show
|
|||
102 | // Flush out remaining ones |
||
103 | $this->addPageSubItems( $currentPageId, $entry ); |
||
104 | } |
||
105 | } |
||
106 | |||
107 | /** |
||
108 | * @param object $row |
||
109 | */ |
||
110 | private function setContinueFromRow( $row ) { |
||
111 | $this->setContinueEnumParameter( |
||
112 | 'continue', |
||
113 | "{$row->eu_page_id}|{$row->eu_entity_id}|{$row->eu_aspect}" |
||
114 | ); |
||
115 | } |
||
116 | |||
117 | /** |
||
118 | * @see ApiQueryBase::getCacheMode |
||
119 | * |
||
120 | * @param array $params |
||
121 | * |
||
122 | * @return string |
||
123 | */ |
||
124 | public function getCacheMode( $params ) { |
||
125 | return 'public'; |
||
126 | } |
||
127 | |||
128 | /** |
||
129 | * @param array $params |
||
130 | * |
||
131 | * @return IResultWrapper|null |
||
132 | */ |
||
133 | public function doQuery( array $params ) { |
||
134 | $pages = $this->getPageSet()->getGoodTitles(); |
||
135 | if ( !$pages ) { |
||
136 | return null; |
||
137 | } |
||
138 | |||
139 | $this->addFields( [ |
||
140 | 'eu_page_id', |
||
141 | 'eu_entity_id', |
||
142 | 'eu_aspect' |
||
143 | ] ); |
||
144 | |||
145 | $this->addTables( 'wbc_entity_usage' ); |
||
146 | $this->addWhereFld( 'eu_page_id', array_keys( $pages ) ); |
||
147 | |||
148 | if ( isset( $params['entities'] ) ) { |
||
149 | $this->addWhereFld( 'eu_entity_id', $params['entities'] ); |
||
150 | } |
||
151 | |||
152 | if ( $params['continue'] !== null ) { |
||
153 | $db = $this->getDB(); |
||
154 | list( $pageContinueSql, $entityContinueSql, $aspectContinueSql ) = explode( '|', $params['continue'], 3 ); |
||
155 | $pageContinue = (int)$pageContinueSql; |
||
156 | $entityContinue = $db->addQuotes( $entityContinueSql ); |
||
157 | $aspectContinue = $db->addQuotes( $aspectContinueSql ); |
||
158 | // Filtering out results that have been shown already and |
||
159 | // starting the query from where it ended. |
||
160 | $this->addWhere( |
||
161 | "eu_page_id > $pageContinue OR " . |
||
162 | "(eu_page_id = $pageContinue AND " . |
||
163 | "(eu_entity_id > $entityContinue OR " . |
||
164 | "(eu_entity_id = $entityContinue AND " . |
||
165 | "eu_aspect >= $aspectContinue)))" |
||
166 | ); |
||
167 | } |
||
168 | |||
169 | $orderBy = [ 'eu_page_id' , 'eu_entity_id' ]; |
||
170 | if ( isset( $params['aspect'] ) ) { |
||
171 | $this->addWhereFld( 'eu_aspect', $params['aspect'] ); |
||
172 | } else { |
||
173 | $orderBy[] = 'eu_aspect'; |
||
174 | } |
||
175 | $this->addOption( 'ORDER BY', $orderBy ); |
||
176 | |||
177 | $this->addOption( 'LIMIT', $params['limit'] + 1 ); |
||
178 | $res = $this->select( __METHOD__ ); |
||
179 | return $res; |
||
180 | } |
||
181 | |||
182 | public function getAllowedParams() { |
||
183 | return [ |
||
184 | 'prop' => [ |
||
185 | ApiBase::PARAM_ISMULTI => true, |
||
186 | ApiBase::PARAM_TYPE => [ |
||
187 | 'url', |
||
188 | ], |
||
189 | ApiBase::PARAM_HELP_MSG_PER_VALUE => [], |
||
190 | ], |
||
191 | 'aspect' => [ |
||
192 | ApiBase::PARAM_ISMULTI => true, |
||
193 | ApiBase::PARAM_TYPE => [ |
||
194 | EntityUsage::SITELINK_USAGE, |
||
195 | EntityUsage::LABEL_USAGE, |
||
196 | EntityUsage::DESCRIPTION_USAGE, |
||
197 | EntityUsage::TITLE_USAGE, |
||
198 | EntityUsage::STATEMENT_USAGE, |
||
199 | EntityUsage::ALL_USAGE, |
||
200 | EntityUsage::OTHER_USAGE, |
||
201 | ] |
||
202 | ], |
||
203 | 'entities' => [ |
||
204 | ApiBase::PARAM_ISMULTI => true, |
||
205 | ], |
||
206 | 'limit' => [ |
||
207 | ApiBase::PARAM_DFLT => 10, |
||
208 | ApiBase::PARAM_TYPE => 'limit', |
||
209 | ApiBase::PARAM_MIN => 1, |
||
210 | ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1, |
||
211 | ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2 |
||
212 | ], |
||
213 | 'continue' => [ |
||
214 | ApiBase::PARAM_HELP_MSG => 'api-help-param-continue', |
||
215 | ], |
||
216 | ]; |
||
217 | } |
||
218 | |||
219 | protected function getExamplesMessages() { |
||
220 | return [ |
||
221 | 'action=query&prop=wbentityusage&titles=Main%20Page' |
||
222 | => 'apihelp-query+wbentityusage-example-simple', |
||
223 | ]; |
||
224 | } |
||
225 | |||
226 | public function getHelpUrls() { |
||
227 | return 'https://www.mediawiki.org/wiki/Special:MyLanguage/Wikibase/API#wbentityusage'; |
||
228 | } |
||
229 | |||
230 | } |
||
231 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.