Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 144 |
|
0.00% |
0 / 6 |
CRAP | |
0.00% |
0 / 1 |
CentralNoticePageLogPager | |
0.00% |
0 / 144 |
|
0.00% |
0 / 6 |
272 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
getIndexField | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getQueryInfo | |
0.00% |
0 / 21 |
|
0.00% |
0 / 1 |
6 | |||
formatRow | |
0.00% |
0 / 86 |
|
0.00% |
0 / 1 |
90 | |||
getStartBody | |
0.00% |
0 / 31 |
|
0.00% |
0 / 1 |
6 | |||
getEndBody | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | use MediaWiki\Html\Html; |
4 | use MediaWiki\MediaWikiServices; |
5 | |
6 | /** |
7 | * This class generates a paginated log of recent changes to banner messages (the parts that get |
8 | * translated). We use the rencentchanges table since it is lightweight, however, this means that |
9 | * the log only goes back 30 days. |
10 | */ |
11 | class CentralNoticePageLogPager extends ReverseChronologicalPager { |
12 | /** @var Title */ |
13 | public $viewPage; |
14 | /** @var SpecialPage */ |
15 | public $special; |
16 | /** @var string */ |
17 | public $logType; |
18 | |
19 | /** |
20 | * Construct instance of class. |
21 | * @param SpecialPage $special object calling object |
22 | * @param string $type type of log - 'bannercontent' or 'bannermessages' (optional) |
23 | */ |
24 | public function __construct( $special, $type = 'bannercontent' ) { |
25 | $this->special = $special; |
26 | parent::__construct(); |
27 | |
28 | $this->viewPage = SpecialPage::getTitleFor( 'NoticeTemplate', 'view' ); |
29 | $this->logType = $type; |
30 | } |
31 | |
32 | /** |
33 | * Sort the log list by timestamp |
34 | * @return string |
35 | */ |
36 | public function getIndexField() { |
37 | return 'rc_timestamp'; |
38 | } |
39 | |
40 | /** |
41 | * Pull log entries from the database |
42 | * @return array[] |
43 | */ |
44 | public function getQueryInfo() { |
45 | $conds = [ |
46 | 'rc_bot' => 1, // include bot edits (all edits made by CentralNotice are bot edits) |
47 | 'rc_namespace' => 8, // only MediaWiki pages |
48 | ]; |
49 | $db = CNDatabase::getDb(); |
50 | if ( $this->logType == 'bannercontent' ) { |
51 | // Add query contitions for banner content log |
52 | $conds += [ |
53 | // get banner content |
54 | 'rc_title' . $db->buildLike( 'Centralnotice-template-', $db->anyString() ), |
55 | ]; |
56 | } else { |
57 | // Add query contitions for banner messages log |
58 | $conds += [ |
59 | // get banner messages |
60 | 'rc_title' . $db->buildLike( 'Centralnotice-', $db->anyString() ), |
61 | // exclude normal banner content |
62 | 'rc_title NOT' . $db->buildLike( 'Centralnotice-template-', $db->anyString() ), |
63 | ]; |
64 | } |
65 | |
66 | $rcQuery = RecentChange::getQueryInfo(); |
67 | $ret = [ |
68 | 'tables' => $rcQuery['tables'], |
69 | 'fields' => $rcQuery['fields'], |
70 | 'conds' => $conds, // WHERE conditions |
71 | 'join_conds' => $rcQuery['joins'], |
72 | ]; |
73 | |
74 | return $ret; |
75 | } |
76 | |
77 | /** |
78 | * Generate the content of each table row (1 row = 1 log entry) |
79 | * @param stdClass $row |
80 | * @return string HTML |
81 | */ |
82 | public function formatRow( $row ) { |
83 | // Create a user object so we can pull the name, user page, etc. |
84 | $loggedUser = User::newFromId( $row->rc_user ); |
85 | // Create the user page link |
86 | $userLink = $this->special->getLinkRenderer()->makeKnownLink( |
87 | $loggedUser->getUserPage(), |
88 | $loggedUser->getName() |
89 | ); |
90 | $userTalkLink = $this->special->getLinkRenderer()->makeKnownLink( |
91 | $loggedUser->getTalkPage(), |
92 | $this->msg( 'centralnotice-talk-link' )->text() |
93 | ); |
94 | |
95 | $language = 'en'; // English is the default for CentralNotice messages |
96 | |
97 | if ( $this->logType == 'bannercontent' ) { |
98 | // Extract the banner name from the title |
99 | $pattern = '/Centralnotice-template-(.*)/'; |
100 | preg_match( $pattern, $row->rc_title, $matches ); |
101 | $banner = $matches[1]; |
102 | } elseif ( $this->logType == 'bannermessages' ) { |
103 | // Split the title into banner, message, and language |
104 | $titlePieces = explode( "/", $row->rc_title, 2 ); |
105 | $titleBase = $titlePieces[0]; |
106 | if ( array_key_exists( 1, $titlePieces ) ) { |
107 | $language = $titlePieces[1]; |
108 | } |
109 | $pattern = '/Centralnotice-([^-]*)-(.*)/'; |
110 | preg_match( $pattern, $titleBase, $matches ); |
111 | $banner = $matches[1]; |
112 | $message = $matches[2]; |
113 | } else { |
114 | throw new LogicException( "Unknown type {$this->logType}" ); |
115 | } |
116 | |
117 | // Create banner link |
118 | $bannerLink = $this->special->getLinkRenderer()->makeKnownLink( |
119 | $this->viewPage, |
120 | $banner, |
121 | [], |
122 | [ 'template' => $banner ] |
123 | ); |
124 | |
125 | // Create title object |
126 | $title = Title::newFromText( "MediaWiki:{$row->rc_title}" ); |
127 | |
128 | if ( $this->logType == 'bannercontent' ) { |
129 | // If the banner was just created, show a link to the banner. If the banner was |
130 | // edited, show a link to the banner and a link to the diff. |
131 | if ( $row->rc_source === RecentChange::SRC_NEW ) { |
132 | $bannerCell = $bannerLink; |
133 | } else { |
134 | $querydiff = [ |
135 | 'curid' => $row->rc_cur_id, |
136 | 'diff' => $row->rc_this_oldid, |
137 | 'oldid' => $row->rc_last_oldid |
138 | ]; |
139 | $diffUrl = htmlspecialchars( $title->getLinkUrl( $querydiff ) ); |
140 | // Should "diff" be localised? It appears not to be elsewhere in the interface. |
141 | // See ChangesList->preCacheMessages() for example. |
142 | $bannerCell = $bannerLink . " (<a href=\"$diffUrl\">diff</a>)"; |
143 | } |
144 | } elseif ( $this->logType == 'bannermessages' ) { |
145 | $bannerCell = $bannerLink; |
146 | |
147 | // Create the message link |
148 | // @phan-suppress-next-line PhanPossiblyUndeclaredVariable |
149 | $messageLink = $this->special->getLinkRenderer()->makeKnownLink( $title, $message ); |
150 | |
151 | // If the message was just created, show a link to the message. If the message was |
152 | // edited, show a link to the message and a link to the diff. |
153 | if ( $row->rc_source === RecentChange::SRC_NEW ) { |
154 | $messageCell = $messageLink; |
155 | } else { |
156 | $querydiff = [ |
157 | 'curid' => $row->rc_cur_id, |
158 | 'diff' => $row->rc_this_oldid, |
159 | 'oldid' => $row->rc_last_oldid |
160 | ]; |
161 | $diffUrl = htmlspecialchars( $title->getLinkUrl( $querydiff ) ); |
162 | // Should "diff" be localised? It appears not to be elsewhere in the interface. |
163 | // See ChangesList->preCacheMessages() for example. |
164 | $messageCell = $messageLink . " (<a href=\"$diffUrl\">diff</a>)"; |
165 | } |
166 | } else { |
167 | throw new LogicException( "Unknown type {$this->logType}" ); |
168 | } |
169 | |
170 | // Begin log entry primary row |
171 | $lang = $this->getLanguage(); |
172 | $htmlOut = Html::openElement( 'tr' ); |
173 | |
174 | $htmlOut .= Html::element( 'td', [ 'valign' => 'top' ] ); |
175 | $htmlOut .= Xml::element( 'td', [ 'valign' => 'top', 'class' => 'primary' ], |
176 | $lang->date( $row->rc_timestamp ) . ' ' . $lang->time( $row->rc_timestamp ) |
177 | ); |
178 | $htmlOut .= Html::rawElement( 'td', [ 'valign' => 'top', 'class' => 'primary' ], |
179 | $this->msg( 'centralnotice-user-links' ) |
180 | ->rawParams( $userLink, $userTalkLink ) |
181 | ->escaped() |
182 | ); |
183 | $htmlOut .= Html::rawElement( 'td', [ 'valign' => 'top', 'class' => 'primary' ], |
184 | $bannerCell |
185 | ); |
186 | if ( $this->logType == 'bannermessages' ) { |
187 | // @phan-suppress-next-next-line PhanPossiblyUndeclaredVariable,PhanTypeMismatchArgumentNullable |
188 | $htmlOut .= Html::rawElement( 'td', [ 'valign' => 'top', 'class' => 'primary' ], |
189 | $messageCell |
190 | ); |
191 | $htmlOut .= Html::rawElement( 'td', [ 'valign' => 'top', 'class' => 'primary' ], |
192 | $language |
193 | ); |
194 | } |
195 | |
196 | $htmlOut .= Html::rawElement( 'td', |
197 | [ 'valign' => 'top', 'class' => 'primary-summary' ], |
198 | htmlspecialchars( |
199 | MediaWikiServices::getInstance()->getCommentStore()->getComment( 'rc_comment', $row )->text |
200 | ) |
201 | ); |
202 | $htmlOut .= Html::rawElement( 'td', [], |
203 | ' ' |
204 | ); |
205 | |
206 | // End log entry primary row |
207 | $htmlOut .= Html::closeElement( 'tr' ); |
208 | |
209 | return $htmlOut; |
210 | } |
211 | |
212 | /** |
213 | * @return string |
214 | */ |
215 | public function getStartBody() { |
216 | $htmlOut = ''; |
217 | $htmlOut .= Html::openElement( 'table', [ 'id' => 'cn-campaign-logs', 'cellpadding' => 3 ] ); |
218 | $htmlOut .= Html::openElement( 'tr' ); |
219 | $htmlOut .= Xml::element( 'th', [ 'style' => 'width: 20px;' ] ); |
220 | $htmlOut .= Xml::element( 'th', [ 'align' => 'left', 'style' => 'width: 130px;' ], |
221 | $this->msg( 'centralnotice-timestamp' )->text() |
222 | ); |
223 | $htmlOut .= Xml::element( 'th', [ 'align' => 'left', 'style' => 'width: 160px;' ], |
224 | $this->msg( 'centralnotice-user' )->text() |
225 | ); |
226 | $htmlOut .= Xml::element( 'th', [ 'align' => 'left', 'style' => 'width: 160px;' ], |
227 | $this->msg( 'centralnotice-banner' )->text() |
228 | ); |
229 | if ( $this->logType == 'bannermessages' ) { |
230 | $htmlOut .= Xml::element( 'th', [ 'align' => 'left', 'style' => 'width: 160px;' ], |
231 | $this->msg( 'centralnotice-message' )->text() |
232 | ); |
233 | $htmlOut .= Xml::element( 'th', [ 'align' => 'left', 'style' => 'width: 100px;' ], |
234 | $this->msg( 'centralnotice-language' )->text() |
235 | ); |
236 | |
237 | $commentWidth = '120px'; |
238 | |
239 | } else { |
240 | $commentWidth = '250px'; |
241 | } |
242 | |
243 | $htmlOut .= Xml::element( 'th', |
244 | [ 'align' => 'left', 'style' => "width: {$commentWidth};" ], |
245 | $this->msg( 'centralnotice-change-summary-heading' )->text() |
246 | ); |
247 | |
248 | $htmlOut .= Html::rawElement( 'td', [], |
249 | ' ' |
250 | ); |
251 | $htmlOut .= Html::closeElement( 'tr' ); |
252 | return $htmlOut; |
253 | } |
254 | |
255 | /** |
256 | * Close table |
257 | * @return string |
258 | */ |
259 | public function getEndBody() { |
260 | return Html::closeElement( 'table' ); |
261 | } |
262 | } |