]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - includes/specials/SpecialRecentchangeslinked.php
MediaWiki 1.15.0
[autoinstallsdev/mediawiki.git] / includes / specials / SpecialRecentchangeslinked.php
1 <?php
2
3 /**
4  * This is to display changes made to all articles linked in an article.
5  * @ingroup SpecialPage
6  */
7 class SpecialRecentchangeslinked extends SpecialRecentchanges {
8
9         function __construct(){
10                 SpecialPage::SpecialPage( 'Recentchangeslinked' );
11                 $this->includable( true );
12         }
13
14         public function getDefaultOptions() {
15                 $opts = parent::getDefaultOptions();
16                 $opts->add( 'target', '' );
17                 $opts->add( 'showlinkedto', false );
18                 $opts->add( 'tagfilter', '' );
19                 return $opts;
20         }
21
22         public function parseParameters( $par, FormOptions $opts ) {
23                 $opts['target'] = $par;
24         }
25
26         public function feedSetup() {
27                 global $wgRequest;
28                 $opts = parent::feedSetup();
29                 # Feed is cached on limit,hideminor,target; other params would randomly not work
30                 $opts['target'] = $wgRequest->getVal( 'target' );
31                 return $opts;
32         }
33
34         public function getFeedObject( $feedFormat ){
35                 $feed = new ChangesFeed( $feedFormat, false );
36                 $feedObj = $feed->getFeedObject(
37                         wfMsgForContent( 'recentchangeslinked-title', $this->mTargetTitle->getPrefixedText() ),
38                         wfMsgForContent( 'recentchangeslinked' )
39                 );
40                 return array( $feed, $feedObj );
41         }
42
43         public function doMainQuery( $conds, $opts ) {
44                 global $wgUser, $wgOut;
45
46                 $target = $opts['target'];
47                 $showlinkedto = $opts['showlinkedto'];
48                 $limit = $opts['limit'];
49
50                 if ( $target === '' ) {
51                         return false;
52                 }
53                 $title = Title::newFromURL( $target );
54                 if( !$title || $title->getInterwiki() != '' ){
55                         $wgOut->wrapWikiMsg( '<div class="errorbox">$1</div><br clear="both" />', 'allpagesbadtitle' );
56                         return false;
57                 }
58                 $this->mTargetTitle = $title;
59
60                 $wgOut->setPageTitle( wfMsg( 'recentchangeslinked-title', $title->getPrefixedText() ) );
61
62                 /*
63                  * Ordinary links are in the pagelinks table, while transclusions are
64                  * in the templatelinks table, categorizations in categorylinks and
65                  * image use in imagelinks.  We need to somehow combine all these.
66                  * Special:Whatlinkshere does this by firing multiple queries and
67                  * merging the results, but the code we inherit from our parent class
68                  * expects only one result set so we use UNION instead.
69                  */
70
71                 $dbr = wfGetDB( DB_SLAVE, 'recentchangeslinked' );
72                 $id = $title->getArticleId();
73                 $ns = $title->getNamespace();
74                 $dbkey = $title->getDBkey();
75
76                 $tables = array( 'recentchanges' );
77                 $select = array( $dbr->tableName( 'recentchanges' ) . '.*' );
78                 $join_conds = array();
79                 $query_options = array();
80
81                 // left join with watchlist table to highlight watched rows
82                 if( $uid = $wgUser->getId() ) {
83                         $tables[] = 'watchlist';
84                         $select[] = 'wl_user';
85                         $join_conds['watchlist'] = array( 'LEFT JOIN', "wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace" );
86                 }
87
88                 ChangeTags::modifyDisplayQuery( $tables, $select, $conds, $join_conds,
89                         $query_options, $opts['tagfilter'] );
90
91                 // XXX: parent class does this, should we too?
92                 // wfRunHooks('SpecialRecentChangesQuery', array( &$conds, &$tables, &$join_conds, $opts ) );
93
94                 if( $ns == NS_CATEGORY && !$showlinkedto ) {
95                         // special handling for categories
96                         // XXX: should try to make this less klugy
97                         $link_tables = array( 'categorylinks' );
98                         $showlinkedto = true;
99                 } else {
100                         // for now, always join on these tables; really should be configurable as in whatlinkshere
101                         $link_tables = array( 'pagelinks', 'templatelinks' );
102                         // imagelinks only contains links to pages in NS_FILE
103                         if( $ns == NS_FILE || !$showlinkedto ) $link_tables[] = 'imagelinks';
104                 }
105
106                 if( $id == 0 && !$showlinkedto )
107                         return false; // nonexistent pages can't link to any pages
108
109                 // field name prefixes for all the various tables we might want to join with
110                 $prefix = array( 'pagelinks' => 'pl', 'templatelinks' => 'tl', 'categorylinks' => 'cl', 'imagelinks' => 'il' );
111
112                 $subsql = array(); // SELECT statements to combine with UNION
113
114                 foreach( $link_tables as $link_table ) {
115                         $pfx = $prefix[$link_table];
116
117                         // imagelinks and categorylinks tables have no xx_namespace field, and have xx_to instead of xx_title
118                         if( $link_table == 'imagelinks' ) $link_ns = NS_FILE;
119                         else if( $link_table == 'categorylinks' ) $link_ns = NS_CATEGORY;
120                         else $link_ns = 0;
121
122                         if( $showlinkedto ) {
123                                 // find changes to pages linking to this page
124                                 if( $link_ns ) {
125                                         if( $ns != $link_ns ) continue; // should never happen, but check anyway
126                                         $subconds = array( "{$pfx}_to" => $dbkey );
127                                 } else {
128                                         $subconds = array( "{$pfx}_namespace" => $ns, "{$pfx}_title" => $dbkey );
129                                 }
130                                 $subjoin = "rc_cur_id = {$pfx}_from";
131                         } else {
132                                 // find changes to pages linked from this page
133                                 $subconds = array( "{$pfx}_from" => $id );
134                                 if( $link_table == 'imagelinks' || $link_table == 'categorylinks' ) {
135                                         $subconds["rc_namespace"] = $link_ns;
136                                         $subjoin = "rc_title = {$pfx}_to";
137                                 } else {
138                                         $subjoin = "rc_namespace = {$pfx}_namespace AND rc_title = {$pfx}_title";
139                                 }
140                         }
141
142                         $subsql[] = $dbr->selectSQLText( 
143                                 array_merge( $tables, array( $link_table ) ), 
144                                 $select, 
145                                 $conds + $subconds,
146                                 __METHOD__, 
147                                 array( 'ORDER BY' => 'rc_timestamp DESC', 'LIMIT' => $limit ) + $query_options,
148                                 $join_conds + array( $link_table => array( 'INNER JOIN', $subjoin ) )
149                         );
150                 }
151
152                 if( count($subsql) == 0 )
153                         return false; // should never happen
154                 if( count($subsql) == 1 )
155                         $sql = $subsql[0];
156                 else {
157                         // need to resort and relimit after union
158                         $sql = "(" . implode( ") UNION (", $subsql ) . ") ORDER BY rc_timestamp DESC LIMIT {$limit}";
159                 }
160
161                 $res = $dbr->query( $sql, __METHOD__ );
162
163                 if( $res->numRows() == 0 )
164                         $this->mResultEmpty = true;
165
166                 return $res;
167         }
168         
169         function getExtraOptions( $opts ){
170                 $opts->consumeValues( array( 'showlinkedto', 'target' ) );
171                 $extraOpts = array();
172                 $extraOpts['namespace'] = $this->namespaceFilterForm( $opts );
173                 $extraOpts['target'] = array( wfMsg( 'recentchangeslinked-page' ),
174                         Xml::input( 'target', 40, str_replace('_',' ',$opts['target']) ) .
175                         Xml::check( 'showlinkedto', $opts['showlinkedto'], array('id' => 'showlinkedto') ) . ' ' .
176                         Xml::label( wfMsg("recentchangeslinked-to"), 'showlinkedto' ) );
177                 $tagFilter = ChangeTags::buildTagFilterSelector( $opts['tagfilter'] );
178                 if ($tagFilter)
179                         $extraOpts['tagfilter'] = $tagFilter;
180                 return $extraOpts;
181         }
182
183         function setTopText( OutputPage $out, FormOptions $opts ) {
184                 global $wgUser;
185                 $skin = $wgUser->getSkin();
186                 if( isset( $this->mTargetTitle ) && is_object( $this->mTargetTitle ) )
187                         $out->setSubtitle( wfMsg( 'recentchangeslinked-backlink', $skin->link( $this->mTargetTitle,
188                                 $this->mTargetTitle->getPrefixedText(), array(), array( 'redirect' => 'no'  ) ) ) );
189         }
190
191         function setBottomText( OutputPage $out, FormOptions $opts ){
192                 if( isset( $this->mTargetTitle ) && is_object( $this->mTargetTitle ) ){
193                         global $wgUser;
194                         $out->setFeedAppendQuery( "target=" . urlencode( $this->mTargetTitle->getPrefixedDBkey() ) );
195                 }
196                 if( isset( $this->mResultEmpty ) && $this->mResultEmpty ){
197                         $out->addWikiMsg( 'recentchangeslinked-noresult' );     
198                 }
199         }
200 }