MediaWiki REL1_39
ImageHistoryPseudoPager.php
Go to the documentation of this file.
1<?php
23use Wikimedia\Timestamp\TimestampException;
24
26 protected $preventClickjacking = false;
27
31 protected $mImg;
32
36 protected $mTitle;
37
43
48 public $mHist;
49
54 public $mRange;
55
57 private $linkBatchFactory;
58
63 public function __construct( $imagePage, LinkBatchFactory $linkBatchFactory = null ) {
64 parent::__construct( $imagePage->getContext() );
65 $this->mImagePage = $imagePage;
66 $this->mTitle = $imagePage->getTitle()->createFragmentTarget( 'filehistory' );
67 $this->mImg = null;
68 $this->mHist = [];
69 $this->mRange = [ 0, 0 ]; // display range
70
71 // Only display 10 revisions at once by default, otherwise the list is overwhelming
72 $this->mLimitsShown = array_merge( [ 10 ], $this->mLimitsShown );
73 $this->mDefaultLimit = 10;
74 list( $this->mLimit, /* $offset */ ) =
75 $this->mRequest->getLimitOffsetForUser(
76 $this->getUser(),
77 $this->mDefaultLimit,
78 ''
79 );
80 $this->linkBatchFactory = $linkBatchFactory ?? MediaWikiServices::getInstance()->getLinkBatchFactory();
81 }
82
86 public function getTitle() {
87 return $this->mTitle;
88 }
89
90 public function getQueryInfo() {
91 return [];
92 }
93
97 public function getIndexField() {
98 return '';
99 }
100
105 public function formatRow( $row ) {
106 return '';
107 }
108
112 public function getBody() {
113 $s = '';
114 $this->doQuery();
115 if ( count( $this->mHist ) ) {
116 if ( $this->mImg->isLocal() ) {
117 // Do a batch existence check for user pages and talkpages.
118 $linkBatch = $this->linkBatchFactory->newLinkBatch();
119 for ( $i = $this->mRange[0]; $i <= $this->mRange[1]; $i++ ) {
120 $file = $this->mHist[$i];
121 $uploader = $file->getUploader( File::FOR_THIS_USER, $this->getAuthority() );
122 if ( $uploader ) {
123 $linkBatch->add( NS_USER, $uploader->getName() );
124 $linkBatch->add( NS_USER_TALK, $uploader->getName() );
125 }
126 }
127 $linkBatch->execute();
128 }
129
130 // Batch-format comments
131 $comments = [];
132 for ( $i = $this->mRange[0]; $i <= $this->mRange[1]; $i++ ) {
133 $file = $this->mHist[$i];
134 $comments[$i] = $file->getDescription(
135 File::FOR_THIS_USER,
136 $this->getAuthority()
137 ) ?: '';
138 }
139 $formattedComments = MediaWikiServices::getInstance()
140 ->getCommentFormatter()
141 ->formatStrings( $comments, $this->getTitle() );
142
143 $list = new ImageHistoryList( $this->mImagePage );
144 # Generate prev/next links
145 $navLink = $this->getNavigationBar();
146 $s = $list->beginImageHistoryList( $navLink );
147 // Skip rows there just for paging links
148 for ( $i = $this->mRange[0]; $i <= $this->mRange[1]; $i++ ) {
149 $file = $this->mHist[$i];
150 $s .= $list->imageHistoryLine( !$file->isOld(), $file, $formattedComments[$i] );
151 }
152 $s .= $list->endImageHistoryList( $navLink );
153
154 if ( $list->getPreventClickjacking() ) {
155 $this->setPreventClickjacking( true );
156 }
157 }
158 return $s;
159 }
160
161 public function doQuery() {
162 if ( $this->mQueryDone ) {
163 return;
164 }
165 $this->mImg = $this->mImagePage->getPage()->getFile(); // ensure loading
166 if ( !$this->mImg->exists() ) {
167 return;
168 }
169 // Make sure the date (probably from user input) is valid; if not, drop it.
170 if ( $this->mOffset !== null ) {
171 try {
172 $sadlyWeCannotPassThisTimestampDownTheStack = $this->mDb->timestamp( $this->mOffset );
173 } catch ( TimestampException $e ) {
174 $this->mOffset = null;
175 }
176 }
177 $queryLimit = $this->mLimit + 1; // limit plus extra row
178 if ( $this->mIsBackwards ) {
179 // Fetch the file history
180 $this->mHist = $this->mImg->getHistory( $queryLimit, null, $this->mOffset, false );
181 // The current rev may not meet the offset/limit
182 $numRows = count( $this->mHist );
183 if ( $numRows <= $this->mLimit && $this->mImg->getTimestamp() > $this->mOffset ) {
184 $this->mHist = array_merge( [ $this->mImg ], $this->mHist );
185 }
186 } else {
187 // The current rev may not meet the offset
188 if ( !$this->mOffset || $this->mImg->getTimestamp() < $this->mOffset ) {
189 $this->mHist[] = $this->mImg;
190 }
191 // Old image versions (fetch extra row for nav links)
192 $oiLimit = count( $this->mHist ) ? $this->mLimit : $this->mLimit + 1;
193 // Fetch the file history
194 $this->mHist = array_merge( $this->mHist,
195 $this->mImg->getHistory( $oiLimit, $this->mOffset, null, false ) );
196 }
197 $numRows = count( $this->mHist ); // Total number of query results
198 if ( $numRows ) {
199 # Index value of top item in the list
200 $firstIndex = $this->mIsBackwards ?
201 [ $this->mHist[$numRows - 1]->getTimestamp() ] : [ $this->mHist[0]->getTimestamp() ];
202 # Discard the extra result row if there is one
203 if ( $numRows > $this->mLimit && $numRows > 1 ) {
204 if ( $this->mIsBackwards ) {
205 # Index value of item past the index
206 $this->mPastTheEndIndex = [ $this->mHist[0]->getTimestamp() ];
207 # Index value of bottom item in the list
208 $lastIndex = [ $this->mHist[1]->getTimestamp() ];
209 # Display range
210 $this->mRange = [ 1, $numRows - 1 ];
211 } else {
212 # Index value of item past the index
213 $this->mPastTheEndIndex = [ $this->mHist[$numRows - 1]->getTimestamp() ];
214 # Index value of bottom item in the list
215 $lastIndex = [ $this->mHist[$numRows - 2]->getTimestamp() ];
216 # Display range
217 $this->mRange = [ 0, $numRows - 2 ];
218 }
219 } else {
220 # Setting indexes to an empty array means that they will be
221 # omitted if they would otherwise appear in URLs. It just so
222 # happens that this is the right thing to do in the standard
223 # UI, in all the relevant cases.
224 $this->mPastTheEndIndex = [];
225 # Index value of bottom item in the list
226 $lastIndex = $this->mIsBackwards ?
227 [ $this->mHist[0]->getTimestamp() ] : [ $this->mHist[$numRows - 1]->getTimestamp() ];
228 # Display range
229 $this->mRange = [ 0, $numRows - 1 ];
230 }
231 } else {
232 $firstIndex = [];
233 $lastIndex = [];
234 $this->mPastTheEndIndex = [];
235 }
236 if ( $this->mIsBackwards ) {
237 $this->mIsFirst = ( $numRows < $queryLimit );
238 $this->mIsLast = ( $this->mOffset == '' );
239 $this->mLastShown = $firstIndex;
240 $this->mFirstShown = $lastIndex;
241 } else {
242 $this->mIsFirst = ( $this->mOffset == '' );
243 $this->mIsLast = ( $numRows < $queryLimit );
244 $this->mLastShown = $lastIndex;
245 $this->mFirstShown = $firstIndex;
246 }
247 $this->mQueryDone = true;
248 }
249
254 protected function preventClickjacking( $enable = true ) {
255 $this->preventClickjacking = $enable;
256 }
257
262 protected function setPreventClickjacking( bool $enable ) {
263 $this->preventClickjacking = $enable;
264 }
265
269 public function getPreventClickjacking() {
271 }
272
273}
const NS_USER
Definition Defines.php:66
const NS_USER_TALK
Definition Defines.php:67
Implements some public methods and some protected utility functions which are required by multiple ch...
Definition File.php:67
Builds the image revision log shown on image pages.
__construct( $imagePage, LinkBatchFactory $linkBatchFactory=null)
doQuery()
Do the query, using information from the object context.
getQueryInfo()
Provides all parameters needed for the main paged query.
Rendering of file description pages.
Definition ImagePage.php:31
Service locator for MediaWiki core services.
Efficient paging for SQL queries.
Represents a title within MediaWiki.
Definition Title.php:49
foreach( $mmfl['setupFiles'] as $fileName) if($queue) if(empty( $mmfl['quiet'])) $s
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition router.php:42