Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 183
0.00% covered (danger)
0.00%
0 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
CentralNoticeBannerLogPager
0.00% covered (danger)
0.00%
0 / 183
0.00% covered (danger)
0.00%
0 / 10
870
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getIndexField
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getQueryInfo
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 formatRow
0.00% covered (danger)
0.00%
0 / 69
0.00% covered (danger)
0.00%
0 / 1
56
 getStartBody
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
2
 getEndBody
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 showInitialSettings
0.00% covered (danger)
0.00%
0 / 33
0.00% covered (danger)
0.00%
0 / 1
30
 showChanges
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
12
 testBooleanBannerChange
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
30
 testTextBannerChange
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2
3use MediaWiki\Html\Html;
4
5class CentralNoticeBannerLogPager extends CentralNoticeCampaignLogPager {
6    /** @var SpecialCentralNoticeLogs */
7    public $special;
8
9    public function __construct( SpecialCentralNoticeLogs $special ) {
10        $this->special = $special;
11        parent::__construct( $special );
12    }
13
14    /**
15     * Sort the log list by timestamp
16     * @return string
17     */
18    public function getIndexField() {
19        return 'tmplog_timestamp';
20    }
21
22    /**
23     * Pull log entries from the database
24     * @return array
25     */
26    public function getQueryInfo() {
27        return [
28            'tables' => [ 'template_log' => 'cn_template_log' ],
29            'fields' => '*',
30        ];
31    }
32
33    /**
34     * Generate the content of each table row (1 row = 1 log entry)
35     * @param stdClass $row
36     * @return string HTML
37     */
38    public function formatRow( $row ) {
39        global $wgExtensionAssetsPath;
40        $lang = $this->getLanguage();
41
42        // Create a user object so we can pull the name, user page, etc.
43        $loggedUser = User::newFromId( $row->tmplog_user_id );
44        // Create the user page link
45        $userLink = $this->special->getLinkRenderer()->makeKnownLink(
46            $loggedUser->getUserPage(),
47            $loggedUser->getName()
48        );
49        $userTalkLink = $this->special->getLinkRenderer()->makeKnownLink(
50            $loggedUser->getTalkPage(),
51            $this->msg( 'centralnotice-talk-link' )->text()
52        );
53
54        // Create the banner link
55        $bannerLink = $this->special->getLinkRenderer()->makeKnownLink(
56            SpecialPage::getTitleFor( 'CentralNoticeBanners', "edit/{$row->tmplog_template_name}" ),
57            $row->tmplog_template_name
58        );
59
60        // Begin log entry primary row
61        $htmlOut = Html::openElement( 'tr' );
62
63        $htmlOut .= Html::openElement( 'td', [ 'valign' => 'top' ] );
64        if ( $row->tmplog_action !== 'removed' ) {
65            $collapsedImg = $this->getLanguage()->isRtl() ?
66                'collapsed-rtl.png' :
67                'collapsed-ltr.png';
68
69            $tmplogId = (int)$row->tmplog_id;
70            $htmlOut .= '<a href="javascript:toggleLogDisplay(\'' . $tmplogId . '\')">' .
71                '<img src="' . $wgExtensionAssetsPath . '/CentralNotice/resources/images/' . $collapsedImg . '" ' .
72                'id="cn-collapsed-' . $tmplogId . '" ' .
73                'style="display:block;vertical-align:baseline;"/>' .
74                '<img src="' . $wgExtensionAssetsPath . '/CentralNotice/resources/images/uncollapsed.png" ' .
75                'id="cn-uncollapsed-' . $tmplogId . '" ' .
76                'style="display:none;vertical-align:baseline;"/>' .
77                '</a>';
78        }
79        $htmlOut .= Html::closeElement( 'td' );
80        $htmlOut .= Xml::element( 'td', [ 'valign' => 'top', 'class' => 'primary' ],
81            $lang->date( $row->tmplog_timestamp ) . ' ' . $lang->time( $row->tmplog_timestamp )
82        );
83        $htmlOut .= Html::rawElement( 'td', [ 'valign' => 'top', 'class' => 'primary' ],
84            $this->msg( 'centralnotice-user-links' )
85                ->rawParams( $userLink, $userTalkLink )
86                ->escaped()
87        );
88        // Give grep a chance to find the usages:
89        // centralnotice-action-created, centralnotice-action-modified,
90        // centralnotice-action-removed
91        $htmlOut .= Xml::element( 'td', [ 'valign' => 'top', 'class' => 'primary' ],
92            $this->msg( 'centralnotice-action-' . $row->tmplog_action )->text()
93        );
94        $htmlOut .= Html::rawElement( 'td', [ 'valign' => 'top', 'class' => 'primary' ],
95            $bannerLink
96        );
97
98        // TODO temporary code for soft dependency on schema change
99        $summary = property_exists( $row, 'tmplog_comment' ) ?
100            htmlspecialchars( $row->tmplog_comment ) : '&nbsp;';
101
102        $htmlOut .= Html::rawElement( 'td',
103            [ 'valign' => 'top', 'class' => 'primary-summary' ],
104            $summary
105        );
106
107        $htmlOut .= Html::rawElement( 'td', [],
108            '&nbsp;'
109        );
110
111        // End log entry primary row
112        $htmlOut .= Html::closeElement( 'tr' );
113
114        if ( $row->tmplog_action !== 'removed' ) {
115            // Begin log entry secondary row
116            $htmlOut .= Html::openElement( 'tr',
117                [ 'id' => 'cn-log-details-' . $tmplogId, 'style' => 'display:none;' ] );
118            // @phan-suppress-previous-line PhanPossiblyUndeclaredVariable
119
120            $htmlOut .= Html::rawElement( 'td', [ 'valign' => 'top' ],
121                '&nbsp;' // force a table cell in older browsers
122            );
123            $htmlOut .= Html::openElement( 'td', [ 'valign' => 'top', 'colspan' => '5' ] );
124            if ( $row->tmplog_action == 'created' ) {
125                $htmlOut .= $this->showInitialSettings( $row );
126            } elseif ( $row->tmplog_action == 'modified' ) {
127                $htmlOut .= $this->showChanges( $row );
128            }
129            $htmlOut .= Html::closeElement( 'td' );
130
131            // End log entry primary row
132            $htmlOut .= Html::closeElement( 'tr' );
133        }
134
135        return $htmlOut;
136    }
137
138    public function getStartBody() {
139        $htmlOut = '';
140        $htmlOut .= Html::openElement( 'table', [ 'id' => 'cn-campaign-logs', 'cellpadding' => 3 ] );
141        $htmlOut .= Html::openElement( 'tr' );
142        $htmlOut .= Xml::element( 'th', [ 'style' => 'width: 20px;' ] );
143        $htmlOut .= Xml::element( 'th', [ 'align' => 'left', 'style' => 'width: 130px;' ],
144            $this->msg( 'centralnotice-timestamp' )->text()
145        );
146        $htmlOut .= Xml::element( 'th', [ 'align' => 'left', 'style' => 'width: 160px;' ],
147            $this->msg( 'centralnotice-user' )->text()
148        );
149        $htmlOut .= Xml::element( 'th', [ 'align' => 'left', 'style' => 'width: 100px;' ],
150            $this->msg( 'centralnotice-action' )->text()
151        );
152        $htmlOut .= Xml::element( 'th', [ 'align' => 'left', 'style' => 'width: 160px;' ],
153            $this->msg( 'centralnotice-banner' )->text()
154        );
155        $htmlOut .= Xml::element( 'th', [ 'align' => 'left', 'style' => 'width: 250px;' ],
156            $this->msg( 'centralnotice-change-summary-heading' )->text()
157        );
158        $htmlOut .= Html::rawElement( 'td', [],
159            '&nbsp;'
160        );
161        $htmlOut .= Html::closeElement( 'tr' );
162        return $htmlOut;
163    }
164
165    /**
166     * Close table
167     * @return string
168     */
169    public function getEndBody() {
170        return Html::closeElement( 'table' );
171    }
172
173    public function showInitialSettings( $row ) {
174        $details = '';
175        $details .= $this->msg(
176            'centralnotice-log-label',
177            $this->msg( 'centralnotice-anon' )->text(),
178            ( $row->tmplog_end_anon ? 'on' : 'off' )
179        )->parse() . "<br/>";
180        $details .= $this->msg(
181            'centralnotice-log-label',
182            $this->msg( 'centralnotice-account' )->text(),
183            ( $row->tmplog_end_account ? 'on' : 'off' )
184        )->parse() . "<br/>";
185        $details .= $this->msg(
186            'centralnotice-log-label',
187            $this->msg( 'centralnotice-category' )->text(),
188            wfEscapeWikiText( $row->tmplog_end_category )
189        )->parse() . "<br/>";
190
191        // Autolink/landing pages feature has been removed, but we might as
192        // well show any info about it in the logs.
193        $details .= $this->msg(
194            'centralnotice-log-label',
195            $this->msg( 'centralnotice-autolink' )->text(),
196            ( $row->tmplog_end_autolink ? 'on' : 'off' )
197        )->parse() . "<br/>";
198        if ( $row->tmplog_end_landingpages ) {
199            $details .= $this->msg(
200                'centralnotice-log-label',
201                $this->msg( 'centralnotice-landingpages' )->text(),
202                wfEscapeWikiText( $row->tmplog_end_landingpages )
203            )->parse() . "<br/>";
204        }
205        $details .= $this->msg(
206            'centralnotice-log-label',
207            $this->msg( 'centralnotice-devices' )->text(),
208            wfEscapeWikiText( $row->tmplog_end_devices )
209        )->parse() . "<br/>";
210        return $details;
211    }
212
213    public function showChanges( $newrow ) {
214        $oldrow = false;
215        if ( $newrow->tmplog_action === 'modified' ) {
216            $db = CNDatabase::getDb();
217            $tmplogId = (int)$newrow->tmplog_id;
218            $oldrow = $db->selectRow(
219                [ 'cn_template_log' => 'cn_template_log' ],
220                '*',
221                [ 'tmplog_template_id' => $newrow->tmplog_template_id,
222                    "tmplog_id < {$tmplogId}" ],
223                __METHOD__,
224                [ 'ORDER BY' => 'tmplog_id DESC', 'LIMIT' => 1 ]
225            );
226        }
227
228        $details = $this->testBooleanBannerChange( 'anon', $newrow, $oldrow );
229        $details .= $this->testBooleanBannerChange( 'account', $newrow, $oldrow );
230        $details .= $this->testTextBannerChange( 'category', $newrow, $oldrow );
231        $details .= $this->testBooleanBannerChange( 'autolink', $newrow, $oldrow );
232        $details .= $this->testTextBannerChange( 'landingpages', $newrow, $oldrow );
233        $details .= $this->testTextBannerChange( 'controller_mixin', $newrow, $oldrow );
234        $details .= $this->testTextBannerChange( 'prioritylangs', $newrow, $oldrow );
235        $details .= $this->testTextBannerChange( 'devices', $newrow, $oldrow );
236        if ( $newrow->tmplog_content_change ) {
237            // Show changes to banner content
238            $details .= $this->msg(
239                'centralnotice-log-label',
240                $this->msg( 'centralnotice-banner-content' )->text(),
241                $this->msg( 'centralnotice-banner-content-changed' )->text()
242            )->parse() . "<br/>";
243        }
244        return $details;
245    }
246
247    private function testBooleanBannerChange( $param, $newrow, $oldrow ) {
248        $result = '';
249        $endField = 'tmplog_end_' . $param;
250
251        $oldval = ( $oldrow ) ? $oldrow->$endField : 0;
252        if ( $oldval !== $newrow->$endField ) {
253            // The following messages are generated here:
254            // * centralnotice-anon
255            // * centralnotice-account
256            // * centralnotice-autolink
257            $result .= $this->msg(
258                'centralnotice-log-label',
259                $this->msg( 'centralnotice-' . $param )->text(),
260                $this->msg(
261                    'centralnotice-changed',
262                    ( $oldval
263                        ? $this->msg( 'centralnotice-on' )->text()
264                        : $this->msg( 'centralnotice-off' )->text() ),
265                    ( $newrow->$endField
266                        ? $this->msg( 'centralnotice-on' )->text()
267                        : $this->msg( 'centralnotice-off' )->text() )
268                )->text()
269            )->parse() . "<br/>";
270        }
271        return $result;
272    }
273
274    private function testTextBannerChange( $param, $newrow, $oldrow ) {
275        $endField = 'tmplog_end_' . $param;
276
277        $oldval = ( ( $oldrow ) ? $oldrow->$endField : '' ) ?: '';
278        $newval = ( $newrow->$endField ) ?: '';
279
280        return $this->testTextChange( $param, $newval, $oldval );
281    }
282}