Split files and classes in different packages for phpdocumentor. I probably changed...
[lhc/web/wiklou.git] / includes / SpecialLog.php
1 <?php
2 # Copyright (C) 2004 Brion Vibber <brion@pobox.com>
3 # http://www.mediawiki.org/
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 # http://www.gnu.org/copyleft/gpl.html
19
20 /**
21 *
22 * @package MediaWiki
23 * @subpackage SpecialPage
24 */
25
26 /**
27 * constructor
28 */
29 function wfSpecialLog( $par = '' ) {
30 global $wgRequest;
31 $logReader =& new LogReader( $wgRequest );
32 if( '' == $wgRequest->getVal( 'type' ) && !empty( $par ) ) {
33 $logReader->limitType( $par );
34 }
35 $logViewer =& new LogViewer( $logReader );
36 $logViewer->show();
37 }
38
39 /**
40 *
41 * @package MediaWiki
42 * @subpackage SpecialPage
43 */
44 class LogReader {
45 var $db, $joinClauses, $whereClauses;
46 var $type = '', $user = '', $title = null;
47
48 function LogReader( $request ) {
49 $this->db =& wfGetDB( DB_SLAVE );
50 $this->setupQuery( $request );
51 }
52
53 function setupQuery( $request ) {
54 $cur = $this->db->tableName( 'cur' );
55 $user = $this->db->tableName( 'user' );
56 $this->joinClauses = array( "LEFT OUTER JOIN $cur ON log_namespace=cur_namespace AND log_title=cur_title" );
57 $this->whereClauses = array( 'user_id=log_user' );
58
59 $this->limitType( $request->getVal( 'type' ) );
60 $this->limitUser( $request->getText( 'user' ) );
61 $this->limitTitle( $request->getText( 'page' ) );
62 $this->limitTime( $request->getVal( 'from' ), '>=' );
63 $this->limitTime( $request->getVal( 'until' ), '<=' );
64
65 list( $this->limit, $this->offset ) = $request->getLimitOffset();
66 }
67
68 function limitType( $type ) {
69 if( empty( $type ) ) {
70 return false;
71 }
72 $this->type = $type;
73 $safetype = $this->db->strencode( $type );
74 $this->whereClauses[] = "log_type='$safetype'";
75 }
76
77 function limitUser( $name ) {
78 $title = Title::makeTitleSafe( NS_USER, $name );
79 if( empty( $name ) || is_null( $title ) ) {
80 return false;
81 }
82 $this->user = str_replace( '_', ' ', $title->getDBkey() );
83 $safename = $this->db->strencode( $this->user );
84 $user = $this->db->tableName( 'user' );
85 $this->whereClauses[] = "user_name='$safename'";
86 }
87
88 function limitTitle( $page ) {
89 $title = Title::newFromText( $page );
90 if( empty( $page ) || is_null( $title ) ) {
91 return false;
92 }
93 $this->title =& $title;
94 $safetitle = $this->db->strencode( $title->getDBkey() );
95 $ns = $title->getNamespace();
96 $this->whereClauses[] = "log_namespace=$ns AND log_title='$safetitle'";
97 }
98
99 function limitTime( $time, $direction ) {
100 # Direction should be a comparison operator
101 if( empty( $time ) ) {
102 return false;
103 }
104 $safetime = $this->db->strencode( wfTimestamp( TS_MW, $time ) );
105 $this->whereClauses[] = "log_timestamp $direction '$safetime'";
106 }
107
108 function getQuery() {
109 $logging = $this->db->tableName( "logging" );
110 $user = $this->db->tableName( 'user' );
111 $sql = "SELECT log_type, log_action, log_timestamp,
112 log_user, user_name,
113 log_namespace, log_title, cur_id,
114 log_comment FROM $logging, $user ";
115 if( !empty( $this->joinClauses ) ) {
116 $sql .= implode( ',', $this->joinClauses );
117 }
118 if( !empty( $this->whereClauses ) ) {
119 $sql .= " WHERE " . implode( ' AND ', $this->whereClauses );
120 }
121 $sql .= " ORDER BY log_timestamp DESC ";
122 $sql .= $this->db->limitResult( $this->limit, $this->offset );
123 return $sql;
124 }
125
126 function getRows() {
127 return $this->db->resultObject( $this->db->query( $this->getQuery() ) );
128 }
129
130 function queryType() {
131 return $this->type;
132 }
133
134 function queryUser() {
135 return $this->user;
136 }
137
138 function queryTitle() {
139 if( is_null( $this->title ) ) {
140 return '';
141 } else {
142 return $this->title->getPrefixedText();
143 }
144 }
145 }
146
147 /**
148 *
149 * @package MediaWiki
150 * @subpackage SpecialPage
151 */
152 class LogViewer {
153 var $reader, $skin;
154
155 function LogViewer( &$reader ) {
156 global $wgUser;
157 $this->skin =& $wgUser->getSkin();
158 $this->reader =& $reader;
159 }
160
161 function show() {
162 global $wgOut;
163 $this->showHeader( $wgOut );
164 $this->showOptions( $wgOut );
165 $this->showPrevNext( $wgOut );
166 $this->showList( $wgOut );
167 $this->showPrevNext( $wgOut );
168 }
169
170 function showList( &$out ) {
171 $html = "";
172 $result = $this->reader->getRows();
173 while( $s = $result->fetchObject() ) {
174 $html .= $this->logLine( $s );
175 }
176 $result->free();
177 $out->addHTML( $html );
178 }
179
180 # wfMsg( unprotectedarticle, $text )
181 # wfMsg( 'protectedarticle', $text )
182 # wfMsg( 'deletedarticle', $text )
183 # wfMsg( 'uploadedimage', $text )
184 # wfMsg( "blocklogentry", $this->BlockAddress, $this->BlockExpiry );
185 # wfMsg( "bureaucratlogentry", $this->mUser, implode( " ", $rightsNotation ) );
186 # wfMsg( "undeletedarticle", $this->mTarget ),
187 function logLine( $s ) {
188 global $wgLang;
189 $title = Title::makeTitle( $s->log_namespace, $s->log_title );
190 $user = Title::makeTitleSafe( NS_USER, $s->user_name );
191 $time = $wgLang->timeanddate( $s->log_timestamp );
192 if( $s->cur_id ) {
193 $titleLink = $this->skin->makeKnownLinkObj( $title );
194 } else {
195 $titleLink = $this->skin->makeBrokenLinkObj( $title );
196 }
197 $userLink = $this->skin->makeLinkObj( $user, htmlspecialchars( $s->user_name ) );
198 if( '' === $s->log_comment ) {
199 $comment = '';
200 } else {
201 $comment = '(<em>' . $this->skin->formatComment( $s->log_comment ) . '</em>)';
202 }
203
204 $action = LogPage::actionText( $s->log_type, $s->log_action, $titleLink );
205 $out = "<li>$time $userLink $action $comment</li>\n";
206 return $out;
207 }
208
209 function showHeader( &$out ) {
210 $type = $this->reader->queryType();
211 if( LogPage::isLogType( $type ) ) {
212 $out->setPageTitle( LogPage::logName( $type ) );
213 $out->addWikiText( LogPage::logHeader( $type ) );
214 }
215 }
216
217 function showOptions( &$out ) {
218 global $wgScript;
219 $action = htmlspecialchars( $wgScript );
220 $title = Title::makeTitle( NS_SPECIAL, 'Log' );
221 $special = htmlspecialchars( $title->getPrefixedDBkey() );
222 $out->addHTML( "<form action=\"$action\" method=\"get\">\n" .
223 "<input type='hidden' name='title' value=\"$special\" />\n" .
224 $this->getTypeMenu() .
225 $this->getUserInput() .
226 $this->getTitleInput() .
227 "<input type='submit' />" .
228 "</form>" );
229 }
230
231 function getTypeMenu() {
232 $out = "<select name='type'>\n";
233 foreach( LogPage::validTypes() as $type ) {
234 $text = htmlspecialchars( LogPage::logName( $type ) );
235 $selected = ($type == $this->reader->queryType()) ? ' selected="selected"' : '';
236 $out .= "<option value=\"$type\"$selected>$text</option>\n";
237 }
238 $out .= "</select>\n";
239 return $out;
240 }
241
242 function getUserInput() {
243 $user = htmlspecialchars( $this->reader->queryUser() );
244 return "User: <input type='text' name='user' size='12' value=\"$user\" />\n";
245 }
246
247 function getTitleInput() {
248 $title = htmlspecialchars( $this->reader->queryTitle() );
249 return "Title: <input type='text' name='page' size='20' value=\"$title\" />\n";
250 }
251
252 function showPrevNext( &$out ) {
253 global $wgLang;
254 $pieces = array();
255 $pieces[] = 'type=' . htmlspecialchars( $this->reader->queryType() );
256 $pieces[] = 'user=' . htmlspecialchars( $this->reader->queryUser() );
257 $pieces[] = 'page=' . htmlspecialchars( $this->reader->queryTitle() );
258 $bits = implode( '&', $pieces );
259 $offset = 0; $limit = 50;
260
261 # TODO: use timestamps instead of offsets to make it more natural
262 # to go huge distances in time
263 $html = wfViewPrevNext( $offset, $limit,
264 $wgLang->specialpage( 'Log' ),
265 $bits,
266 false);
267 $out->addHTML( '<p>' . $html . '</p>' );
268 }
269 }
270
271
272 ?>