3 * A helper class to query the globalimagelinks table
6 class GlobalUsageQuery
{
9 private $hasMore = false;
10 private $filterLocal = false;
13 private $reversed = false;
14 private $target = null;
17 * @param $target mixed Title or db key, or array of db keys of target(s)
19 public function __construct( $target ) {
20 global $wgGlobalDatabase;
21 $this->db
= wfGetDB( DB_SLAVE
, array(), $wgGlobalDatabase );
22 if ( $target instanceof Title
&& $target->getNamespace( ) == NS_FILE
) {
23 $this->target
= $target->getDBKey();
25 $this->target
= $target;
27 $this->offset
= array();
31 * Set the offset parameter
33 * @param $offset string offset
34 * @param $reversed bool True if this is the upper offset
36 public function setOffset( $offset, $reversed = null ) {
37 if ( !is_null( $reversed ) ) {
38 $this->reversed
= $reversed;
41 if ( !is_array( $offset ) ) {
42 $offset = explode( '|', $offset );
45 if ( count( $offset ) == 3 ) {
46 $this->offset
= $offset;
53 * Return the offset set by the user
55 * @return array offset
57 public function getOffsetString() {
58 return implode( '|', $this->offset
);
61 * Is the result reversed
65 public function isReversed() {
66 return $this->reversed
;
70 * Returns the string used for continuation in a file search
75 public function getContinueFileString() {
76 if ( $this->hasMore() ) {
77 return "{$this->lastRow->gil_to}|{$this->lastRow->gil_wiki}|{$this->lastRow->gil_page}";
84 * Returns the string used for continuation in a template search
89 public function getContinueTemplateString() {
90 if ( $this->hasMore() ) {
91 return "{$this->lastRow->gtl_to_title}|{$this->lastRow->gtl_from_wiki}|{$this->lastRow->gtl_from_page}";
98 * Set the maximum amount of items to return. Capped at 500.
100 * @param $limit int The limit
102 public function setLimit( $limit ) {
103 $this->limit
= min( $limit, 500 );
106 * Returns the user set limit
108 public function getLimit() {
113 * Set whether to filter out the local usage
115 public function filterLocal( $value = true ) {
116 $this->filterLocal
= $value;
120 * Executes the query for a file search
122 public function searchTemplate() {
123 global $wgLocalInterwiki;
125 /* Construct a where clause */
126 // Add target template(s)
127 $where = array( 'gtl_to_prefix' => $wgLocalInterwiki,
128 'gtl_to_namespace' => $this->target
->getNamespace( ),
129 'gtl_to_title' => $this->target
->getDBkey( )
132 // Set the continuation condition
134 if ( $this->offset
) {
135 $qTo = $this->db
->addQuotes( $this->offset
[0] );
136 $qWiki = $this->db
->addQuotes( $this->offset
[1] );
137 $qPage = intval( $this->offset
[2] );
139 // Check which limit we got in order to determine which way to traverse rows
140 if ( $this->reversed
) {
141 // Reversed traversal; do not include offset row
146 // Normal traversal; include offset row
152 $where[] = "(gtl_to_title $op1 $qTo) OR " .
153 "(gtl_to_title = $qTo AND gtl_from_wiki $op1 $qWiki) OR " .
154 "(gtl_to_title = $qTo AND gtl_from_wiki = $qWiki AND gtl_from_page $op2 $qPage)";
157 /* Perform select (Duh.) */
158 $res = $this->db
->select(
160 'globaltemplatelinks',
167 'gtl_from_namespace',
173 'ORDER BY' => "gtl_to_title $order, gtl_from_wiki $order, gtl_from_page $order",
174 // Select an extra row to check whether we have more rows available
175 'LIMIT' => $this->limit +
1,
178 'gtl_from_namespace = gn_namespace'
183 // Always return the result in the same order; regardless whether reversed was specified
184 // reversed is really only used to determine from which direction the offset is
186 foreach ( $res as $row ) {
189 if ( $this->reversed
) {
190 $rows = array_reverse( $rows );
193 // Build the result array
195 $this->hasMore
= false;
196 $this->result
= array();
197 foreach ( $rows as $row ) {
199 if ( $count > $this->limit
) {
200 // We've reached the extra row that indicates that there are more rows
201 $this->hasMore
= true;
202 $this->lastRow
= $row;
206 if ( !isset( $this->result
[$row->gtl_to_title
] ) ) {
207 $this->result
[$row->gtl_to_title
] = array();
209 if ( !isset( $this->result
[$row->gtl_to_title
][$row->gtl_from_wiki
] ) ) {
210 $this->result
[$row->gtl_to_title
][$row->gtl_from_wiki
] = array();
213 $this->result
[$row->gtl_to_title
][$row->gtl_from_wiki
][] = array(
214 'template' => $row->gtl_to_title
,
215 'id' => $row->gtl_from_page
,
216 'namespace' => $row->gn_namespacetext
,
217 'title' => $row->gtl_from_title
,
218 'wiki' => $row->gtl_from_wiki
,
224 * Executes the query for a template search
226 public function searchFile() {
227 /* Construct a where clause */
228 // Add target image(s)
229 $where = array( 'gil_to' => $this->target
);
231 if ( $this->filterLocal
) {
232 // Don't show local file usage
233 $where[] = 'gil_wiki != ' . $this->db
->addQuotes( wfWikiId() );
236 // Set the continuation condition
238 if ( $this->offset
) {
239 $qTo = $this->db
->addQuotes( $this->offset
[0] );
240 $qWiki = $this->db
->addQuotes( $this->offset
[1] );
241 $qPage = intval( $this->offset
[2] );
243 // Check which limit we got in order to determine which way to traverse rows
244 if ( $this->reversed
) {
245 // Reversed traversal; do not include offset row
250 // Normal traversal; include offset row
256 $where[] = "(gil_to $op1 $qTo) OR " .
257 "(gil_to = $qTo AND gil_wiki $op1 $qWiki) OR " .
258 "(gil_to = $qTo AND gil_wiki = $qWiki AND gil_page $op2 $qPage)";
261 /* Perform select (Duh.) */
262 $res = $this->db
->select( 'globalimagelinks',
267 'gil_page_namespace',
273 'ORDER BY' => "gil_to $order, gil_wiki $order, gil_page $order",
274 // Select an extra row to check whether we have more rows available
275 'LIMIT' => $this->limit +
1,
280 // Always return the result in the same order; regardless whether reversed was specified
281 // reversed is really only used to determine from which direction the offset is
283 foreach ( $res as $row ) {
286 if ( $this->reversed
) {
287 $rows = array_reverse( $rows );
290 // Build the result array
292 $this->hasMore
= false;
293 $this->result
= array();
294 foreach ( $rows as $row ) {
296 if ( $count > $this->limit
) {
297 // We've reached the extra row that indicates that there are more rows
298 $this->hasMore
= true;
299 $this->lastRow
= $row;
303 if ( !isset( $this->result
[$row->gil_to
] ) ) {
304 $this->result
[$row->gil_to
] = array();
306 if ( !isset( $this->result
[$row->gil_to
][$row->gil_wiki
] ) ) {
307 $this->result
[$row->gil_to
][$row->gil_wiki
] = array();
310 $this->result
[$row->gil_to
][$row->gil_wiki
][] = array(
311 'image' => $row->gil_to
,
312 'id' => $row->gil_page
,
313 'namespace' => $row->gil_page_namespace
,
314 'title' => $row->gil_page_title
,
315 'wiki' => $row->gil_wiki
,
321 * Returns the result set. The result is a 4 dimensional array
322 * (file, wiki, page), whose items are arrays with keys:
323 * - image or template: File name or template name
325 * - namespace: Page namespace text
326 * - title: Unprefixed page title
329 * @return array Result set
331 public function getResult() {
332 return $this->result
;
335 * Returns a 3 dimensional array with the result of the first file. Useful
336 * if only one resource was queried.
338 * For further information see documentation of getResult()
340 * @return array Result set
342 public function getSingleResult() {
343 if ( $this->result
) {
344 return current( $this->result
);
351 * Returns whether there are more results
355 public function hasMore() {
356 return $this->hasMore
;
360 * Returns the result length
364 public function count() {
365 return count( $this->result
);