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();
32 * Set the offset parameter
34 * @param $offset string offset
35 * @param $reversed bool True if this is the upper offset
37 public function setOffset( $offset, $reversed = null ) {
38 if ( !is_null( $reversed ) ) {
39 $this->reversed
= $reversed;
42 if ( !is_array( $offset ) ) {
43 $offset = explode( '|', $offset );
46 if ( count( $offset ) == 3 ) {
47 $this->offset
= $offset;
54 * Return the offset set by the user
56 * @return array offset
58 public function getOffsetString() {
59 return implode( '|', $this->offset
);
62 * Is the result reversed
66 public function isReversed() {
67 return $this->reversed
;
71 * Returns the string used for continuation in a file search
76 public function getContinueFileString() {
77 if ( $this->hasMore() ) {
78 return "{$this->lastRow->gil_to}|{$this->lastRow->gil_wiki}|{$this->lastRow->gil_page}";
85 * Returns the string used for continuation in a template search
90 public function getContinueTemplateString() {
91 if ( $this->hasMore() ) {
92 return "{$this->lastRow->gtl_to_title}|{$this->lastRow->gtl_from_wiki}|{$this->lastRow->gtl_from_page}";
99 * Set the maximum amount of items to return. Capped at 500.
101 * @param $limit int The limit
103 public function setLimit( $limit ) {
104 $this->limit
= min( $limit, 500 );
107 * Returns the user set limit
109 public function getLimit() {
114 * Set whether to filter out the local usage
116 public function filterLocal( $value = true ) {
117 $this->filterLocal
= $value;
121 * Executes the query for a file search
123 public function searchTemplate() {
124 global $wgLocalInterwiki;
126 /* Construct a where clause */
127 // Add target template(s)
128 $where = array( 'gtl_to_prefix' => $wgLocalInterwiki,
129 'gtl_to_namespace' => $this->target
->getNamespace( ),
130 'gtl_to_title' => $this->target
->getDBkey( )
133 // Set the continuation condition
135 if ( $this->offset
) {
136 $qTo = $this->db
->addQuotes( $this->offset
[0] );
137 $qWiki = $this->db
->addQuotes( $this->offset
[1] );
138 $qPage = intval( $this->offset
[2] );
140 // Check which limit we got in order to determine which way to traverse rows
141 if ( $this->reversed
) {
142 // Reversed traversal; do not include offset row
147 // Normal traversal; include offset row
153 $where[] = "(gtl_to_title $op1 $qTo) OR " .
154 "(gtl_to_title = $qTo AND gtl_from_wiki $op1 $qWiki) OR " .
155 "(gtl_to_title = $qTo AND gtl_from_wiki = $qWiki AND gtl_from_page $op2 $qPage)";
158 /* Perform select (Duh.) */
159 $res = $this->db
->select(
161 'globaltemplatelinks',
168 'gtl_from_namespace',
174 'ORDER BY' => "gtl_to_title $order, gtl_from_wiki $order, gtl_from_page $order",
175 // Select an extra row to check whether we have more rows available
176 'LIMIT' => $this->limit +
1,
179 'gtl_from_namespace = gn_namespace'
184 // Always return the result in the same order; regardless whether reversed was specified
185 // reversed is really only used to determine from which direction the offset is
187 foreach ( $res as $row ) {
190 if ( $this->reversed
) {
191 $rows = array_reverse( $rows );
194 // Build the result array
196 $this->hasMore
= false;
197 $this->result
= array();
198 foreach ( $rows as $row ) {
200 if ( $count > $this->limit
) {
201 // We've reached the extra row that indicates that there are more rows
202 $this->hasMore
= true;
203 $this->lastRow
= $row;
207 if ( !isset( $this->result
[$row->gtl_to_title
] ) ) {
208 $this->result
[$row->gtl_to_title
] = array();
210 if ( !isset( $this->result
[$row->gtl_to_title
][$row->gtl_from_wiki
] ) ) {
211 $this->result
[$row->gtl_to_title
][$row->gtl_from_wiki
] = array();
214 $this->result
[$row->gtl_to_title
][$row->gtl_from_wiki
][] = array(
215 'template' => $row->gtl_to_title
,
216 'id' => $row->gtl_from_page
,
217 'namespace' => $row->gn_namespacetext
,
218 'title' => $row->gtl_from_title
,
219 'wiki' => $row->gtl_from_wiki
,
225 * Executes the query for a template search
227 public function searchFile() {
228 /* Construct a where clause */
229 // Add target image(s)
230 $where = array( 'gil_to' => $this->target
);
232 if ( $this->filterLocal
) {
233 // Don't show local file usage
234 $where[] = 'gil_wiki != ' . $this->db
->addQuotes( wfWikiId() );
237 // Set the continuation condition
239 if ( $this->offset
) {
240 $qTo = $this->db
->addQuotes( $this->offset
[0] );
241 $qWiki = $this->db
->addQuotes( $this->offset
[1] );
242 $qPage = intval( $this->offset
[2] );
244 // Check which limit we got in order to determine which way to traverse rows
245 if ( $this->reversed
) {
246 // Reversed traversal; do not include offset row
251 // Normal traversal; include offset row
257 $where[] = "(gil_to $op1 $qTo) OR " .
258 "(gil_to = $qTo AND gil_wiki $op1 $qWiki) OR " .
259 "(gil_to = $qTo AND gil_wiki = $qWiki AND gil_page $op2 $qPage)";
262 /* Perform select (Duh.) */
263 $res = $this->db
->select( 'globalimagelinks',
268 'gil_page_namespace',
274 'ORDER BY' => "gil_to $order, gil_wiki $order, gil_page $order",
275 // Select an extra row to check whether we have more rows available
276 'LIMIT' => $this->limit +
1,
281 // Always return the result in the same order; regardless whether reversed was specified
282 // reversed is really only used to determine from which direction the offset is
284 foreach ( $res as $row ) {
287 if ( $this->reversed
) {
288 $rows = array_reverse( $rows );
291 // Build the result array
293 $this->hasMore
= false;
294 $this->result
= array();
295 foreach ( $rows as $row ) {
297 if ( $count > $this->limit
) {
298 // We've reached the extra row that indicates that there are more rows
299 $this->hasMore
= true;
300 $this->lastRow
= $row;
304 if ( !isset( $this->result
[$row->gil_to
] ) ) {
305 $this->result
[$row->gil_to
] = array();
307 if ( !isset( $this->result
[$row->gil_to
][$row->gil_wiki
] ) ) {
308 $this->result
[$row->gil_to
][$row->gil_wiki
] = array();
311 $this->result
[$row->gil_to
][$row->gil_wiki
][] = array(
312 'image' => $row->gil_to
,
313 'id' => $row->gil_page
,
314 'namespace' => $row->gil_page_namespace
,
315 'title' => $row->gil_page_title
,
316 'wiki' => $row->gil_wiki
,
322 * Returns the result set. The result is a 4 dimensional array
323 * (file, wiki, page), whose items are arrays with keys:
324 * - image or template: File name or template name
326 * - namespace: Page namespace text
327 * - title: Unprefixed page title
330 * @return array Result set
332 public function getResult() {
333 return $this->result
;
336 * Returns a 3 dimensional array with the result of the first file. Useful
337 * if only one resource was queried.
339 * For further information see documentation of getResult()
341 * @return array Result set
343 public function getSingleResult() {
344 if ( $this->result
) {
345 return current( $this->result
);
352 * Returns whether there are more results
356 public function hasMore() {
357 return $this->hasMore
;
361 * Returns the result length
365 public function count() {
366 return count( $this->result
);