]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - includes/RevisionList.php
MediaWiki 1.30.2-scripts2
[autoinstallsdev/mediawiki.git] / includes / RevisionList.php
1 <?php
2 /**
3  * Holders of revision list for a single page
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  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  * http://www.gnu.org/copyleft/gpl.html
19  *
20  * @file
21  */
22
23 use MediaWiki\MediaWikiServices;
24 use Wikimedia\Rdbms\ResultWrapper;
25 use Wikimedia\Rdbms\IDatabase;
26
27 /**
28  * List for revision table items for a single page
29  */
30 abstract class RevisionListBase extends ContextSource implements Iterator {
31         /** @var Title */
32         public $title;
33
34         /** @var array */
35         protected $ids;
36
37         /** @var ResultWrapper|bool */
38         protected $res;
39
40         /** @var bool|Revision */
41         protected $current;
42
43         /**
44          * Construct a revision list for a given title
45          * @param IContextSource $context
46          * @param Title $title
47          */
48         function __construct( IContextSource $context, Title $title ) {
49                 $this->setContext( $context );
50                 $this->title = $title;
51         }
52
53         /**
54          * Select items only where the ID is any of the specified values
55          * @param array $ids
56          */
57         function filterByIds( array $ids ) {
58                 $this->ids = $ids;
59         }
60
61         /**
62          * Get the internal type name of this list. Equal to the table name.
63          * Override this function.
64          * @return null
65          */
66         public function getType() {
67                 return null;
68         }
69
70         /**
71          * Initialise the current iteration pointer
72          */
73         protected function initCurrent() {
74                 $row = $this->res->current();
75                 if ( $row ) {
76                         $this->current = $this->newItem( $row );
77                 } else {
78                         $this->current = false;
79                 }
80         }
81
82         /**
83          * Start iteration. This must be called before current() or next().
84          * @return Revision First list item
85          */
86         public function reset() {
87                 if ( !$this->res ) {
88                         $this->res = $this->doQuery( wfGetDB( DB_REPLICA ) );
89                 } else {
90                         $this->res->rewind();
91                 }
92                 $this->initCurrent();
93                 return $this->current;
94         }
95
96         public function rewind() {
97                 $this->reset();
98         }
99
100         /**
101          * Get the current list item, or false if we are at the end
102          * @return Revision
103          */
104         public function current() {
105                 return $this->current;
106         }
107
108         /**
109          * Move the iteration pointer to the next list item, and return it.
110          * @return Revision
111          */
112         public function next() {
113                 $this->res->next();
114                 $this->initCurrent();
115                 return $this->current;
116         }
117
118         public function key() {
119                 return $this->res ? $this->res->key() : 0;
120         }
121
122         public function valid() {
123                 return $this->res ? $this->res->valid() : false;
124         }
125
126         /**
127          * Get the number of items in the list.
128          * @return int
129          */
130         public function length() {
131                 if ( !$this->res ) {
132                         return 0;
133                 } else {
134                         return $this->res->numRows();
135                 }
136         }
137
138         /**
139          * Do the DB query to iterate through the objects.
140          * @param IDatabase $db DB object to use for the query
141          */
142         abstract public function doQuery( $db );
143
144         /**
145          * Create an item object from a DB result row
146          * @param object $row
147          */
148         abstract public function newItem( $row );
149 }
150
151 /**
152  * Abstract base class for revision items
153  */
154 abstract class RevisionItemBase {
155         /** @var RevisionListBase The parent */
156         protected $list;
157
158         /** The database result row */
159         protected $row;
160
161         /**
162          * @param RevisionListBase $list
163          * @param object $row DB result row
164          */
165         public function __construct( $list, $row ) {
166                 $this->list = $list;
167                 $this->row = $row;
168         }
169
170         /**
171          * Get the DB field name associated with the ID list.
172          * Override this function.
173          * @return null
174          */
175         public function getIdField() {
176                 return null;
177         }
178
179         /**
180          * Get the DB field name storing timestamps.
181          * Override this function.
182          * @return bool
183          */
184         public function getTimestampField() {
185                 return false;
186         }
187
188         /**
189          * Get the DB field name storing user ids.
190          * Override this function.
191          * @return bool
192          */
193         public function getAuthorIdField() {
194                 return false;
195         }
196
197         /**
198          * Get the DB field name storing user names.
199          * Override this function.
200          * @return bool
201          */
202         public function getAuthorNameField() {
203                 return false;
204         }
205
206         /**
207          * Get the ID, as it would appear in the ids URL parameter
208          * @return int
209          */
210         public function getId() {
211                 $field = $this->getIdField();
212                 return $this->row->$field;
213         }
214
215         /**
216          * Get the date, formatted in user's language
217          * @return string
218          */
219         public function formatDate() {
220                 return $this->list->getLanguage()->userDate( $this->getTimestamp(),
221                         $this->list->getUser() );
222         }
223
224         /**
225          * Get the time, formatted in user's language
226          * @return string
227          */
228         public function formatTime() {
229                 return $this->list->getLanguage()->userTime( $this->getTimestamp(),
230                         $this->list->getUser() );
231         }
232
233         /**
234          * Get the timestamp in MW 14-char form
235          * @return mixed
236          */
237         public function getTimestamp() {
238                 $field = $this->getTimestampField();
239                 return wfTimestamp( TS_MW, $this->row->$field );
240         }
241
242         /**
243          * Get the author user ID
244          * @return int
245          */
246         public function getAuthorId() {
247                 $field = $this->getAuthorIdField();
248                 return intval( $this->row->$field );
249         }
250
251         /**
252          * Get the author user name
253          * @return string
254          */
255         public function getAuthorName() {
256                 $field = $this->getAuthorNameField();
257                 return strval( $this->row->$field );
258         }
259
260         /**
261          * Returns true if the current user can view the item
262          */
263         abstract public function canView();
264
265         /**
266          * Returns true if the current user can view the item text/file
267          */
268         abstract public function canViewContent();
269
270         /**
271          * Get the HTML of the list item. Should be include "<li></li>" tags.
272          * This is used to show the list in HTML form, by the special page.
273          */
274         abstract public function getHTML();
275
276         /**
277          * Returns an instance of LinkRenderer
278          * @return \MediaWiki\Linker\LinkRenderer
279          */
280         protected function getLinkRenderer() {
281                 return MediaWikiServices::getInstance()->getLinkRenderer();
282         }
283 }
284
285 class RevisionList extends RevisionListBase {
286         public function getType() {
287                 return 'revision';
288         }
289
290         /**
291          * @param IDatabase $db
292          * @return mixed
293          */
294         public function doQuery( $db ) {
295                 $conds = [ 'rev_page' => $this->title->getArticleID() ];
296                 if ( $this->ids !== null ) {
297                         $conds['rev_id'] = array_map( 'intval', $this->ids );
298                 }
299                 return $db->select(
300                         [ 'revision', 'page', 'user' ],
301                         array_merge( Revision::selectFields(), Revision::selectUserFields() ),
302                         $conds,
303                         __METHOD__,
304                         [ 'ORDER BY' => 'rev_id DESC' ],
305                         [
306                                 'page' => Revision::pageJoinCond(),
307                                 'user' => Revision::userJoinCond() ]
308                 );
309         }
310
311         public function newItem( $row ) {
312                 return new RevisionItem( $this, $row );
313         }
314 }
315
316 /**
317  * Item class for a live revision table row
318  */
319 class RevisionItem extends RevisionItemBase {
320         /** @var Revision */
321         protected $revision;
322
323         /** @var RequestContext */
324         protected $context;
325
326         public function __construct( $list, $row ) {
327                 parent::__construct( $list, $row );
328                 $this->revision = new Revision( $row );
329                 $this->context = $list->getContext();
330         }
331
332         public function getIdField() {
333                 return 'rev_id';
334         }
335
336         public function getTimestampField() {
337                 return 'rev_timestamp';
338         }
339
340         public function getAuthorIdField() {
341                 return 'rev_user';
342         }
343
344         public function getAuthorNameField() {
345                 return 'rev_user_text';
346         }
347
348         public function canView() {
349                 return $this->revision->userCan( Revision::DELETED_RESTRICTED, $this->context->getUser() );
350         }
351
352         public function canViewContent() {
353                 return $this->revision->userCan( Revision::DELETED_TEXT, $this->context->getUser() );
354         }
355
356         public function isDeleted() {
357                 return $this->revision->isDeleted( Revision::DELETED_TEXT );
358         }
359
360         /**
361          * Get the HTML link to the revision text.
362          * @todo Essentially a copy of RevDelRevisionItem::getRevisionLink. That class
363          * should inherit from this one, and implement an appropriate interface instead
364          * of extending RevDelItem
365          * @return string
366          */
367         protected function getRevisionLink() {
368                 $date = $this->list->getLanguage()->userTimeAndDate(
369                         $this->revision->getTimestamp(), $this->list->getUser() );
370
371                 if ( $this->isDeleted() && !$this->canViewContent() ) {
372                         return htmlspecialchars( $date );
373                 }
374                 $linkRenderer = $this->getLinkRenderer();
375                 return $linkRenderer->makeKnownLink(
376                         $this->list->title,
377                         $date,
378                         [],
379                         [
380                                 'oldid' => $this->revision->getId(),
381                                 'unhide' => 1
382                         ]
383                 );
384         }
385
386         /**
387          * Get the HTML link to the diff.
388          * @todo Essentially a copy of RevDelRevisionItem::getDiffLink. That class
389          * should inherit from this one, and implement an appropriate interface instead
390          * of extending RevDelItem
391          * @return string
392          */
393         protected function getDiffLink() {
394                 if ( $this->isDeleted() && !$this->canViewContent() ) {
395                         return $this->context->msg( 'diff' )->escaped();
396                 } else {
397                         $linkRenderer = $this->getLinkRenderer();
398                         return $linkRenderer->makeKnownLink(
399                                         $this->list->title,
400                                         $this->list->msg( 'diff' )->text(),
401                                         [],
402                                         [
403                                                 'diff' => $this->revision->getId(),
404                                                 'oldid' => 'prev',
405                                                 'unhide' => 1
406                                         ]
407                                 );
408                 }
409         }
410
411         /**
412          * @todo Essentially a copy of RevDelRevisionItem::getHTML. That class
413          * should inherit from this one, and implement an appropriate interface instead
414          * of extending RevDelItem
415          * @return string
416          */
417         public function getHTML() {
418                 $difflink = $this->context->msg( 'parentheses' )
419                         ->rawParams( $this->getDiffLink() )->escaped();
420                 $revlink = $this->getRevisionLink();
421                 $userlink = Linker::revUserLink( $this->revision );
422                 $comment = Linker::revComment( $this->revision );
423                 if ( $this->isDeleted() ) {
424                         $revlink = "<span class=\"history-deleted\">$revlink</span>";
425                 }
426                 return "<li>$difflink $revlink $userlink $comment</li>";
427         }
428 }