Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 81
0.00% covered (danger)
0.00%
0 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
EchoCoreThanksPresentationModel
0.00% covered (danger)
0.00%
0 / 81
0.00% covered (danger)
0.00%
0 / 11
992
0.00% covered (danger)
0.00%
0 / 1
 canRender
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 getIconType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getHeaderMessage
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
12
 getCompactHeaderMessage
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getBodyMessage
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 getRevisionEditSummary
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 getRevOrLogComment
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
42
 getPrimaryLink
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
6
 getSecondaryLinks
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getLogEntry
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 getThankType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace MediaWiki\Extension\Thanks;
4
5use MediaWiki\Context\DerivativeContext;
6use MediaWiki\Extension\Notifications\Formatters\EchoEventPresentationModel;
7use MediaWiki\Language\RawMessage;
8use MediaWiki\Logging\DatabaseLogEntry;
9use MediaWiki\Logging\LogEntry;
10use MediaWiki\Logging\LogPage;
11use MediaWiki\MediaWikiServices;
12use MediaWiki\Parser\Sanitizer;
13use MediaWiki\Revision\RevisionRecord;
14use MediaWiki\SpecialPage\SpecialPage;
15
16class EchoCoreThanksPresentationModel extends EchoEventPresentationModel {
17    /** @var LogEntry|bool|null */
18    private $logEntry;
19
20    /** @inheritDoc */
21    public function canRender() {
22        $hasTitle = (bool)$this->event->getTitle();
23        if ( $hasTitle && $this->getThankType() === 'log' ) {
24            $logEntry = $this->getLogEntry();
25            return $logEntry && !(
26                // the notification renders the message on Special:Log without the comment,
27                // so check $logEntry is not deleted, or only its comment is deleted
28                $logEntry->getDeleted() & ~LogPage::DELETED_COMMENT
29            );
30        }
31        return $hasTitle;
32    }
33
34    /** @inheritDoc */
35    public function getIconType() {
36        return 'thanks';
37    }
38
39    /** @inheritDoc */
40    public function getHeaderMessage() {
41        $type = $this->getThankType();
42        if ( $this->isBundled() ) {
43            // Message is either notification-bundle-header-rev-thank
44            // or notification-bundle-header-log-thank.
45            $msg = $this->msg( "notification-bundle-header-$type-thank" );
46            $msg->params( $this->getBundleCount() );
47            $msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) );
48            $msg->params( $this->getViewingUserForGender() );
49            return $msg;
50        } else {
51            if ( $this->event->getExtraParam( 'revcreation', null ) ) {
52                // This is a thank on a page creation revision.
53                $msg = $this->getMessageWithAgent( "notification-header-creation-thank" );
54            } else {
55                // Message is either notification-header-rev-thank or notification-header-log-thank.
56                $msg = $this->getMessageWithAgent( "notification-header-$type-thank" );
57            }
58            $msg->params( $this->getTruncatedTitleText( $this->event->getTitle(), true ) );
59            $msg->params( $this->getViewingUserForGender() );
60            return $msg;
61        }
62    }
63
64    /** @inheritDoc */
65    public function getCompactHeaderMessage() {
66        // The following message is used here:
67        // * notification-compact-header-edit-thank
68        $msg = parent::getCompactHeaderMessage();
69        $msg->params( $this->getViewingUserForGender() );
70        return $msg;
71    }
72
73    /** @inheritDoc */
74    public function getBodyMessage() {
75        $comment = $this->getRevOrLogComment();
76        if ( $comment !== '' ) {
77            $msg = new RawMessage( '$1' );
78            $msg->plaintextParams( $comment );
79            return $msg;
80        }
81        return false;
82    }
83
84    /**
85     * @return string|bool The comment or false if it could not be retrieved.
86     */
87    private function getRevisionEditSummary() {
88        if ( !$this->userCan( RevisionRecord::DELETED_COMMENT ) ) {
89            return false;
90        }
91
92        $revision = $this->event->getRevision();
93        if ( !$revision ) {
94            return false;
95        }
96
97        $summary = $revision->getComment( RevisionRecord::RAW );
98        return $summary ? $summary->text : false;
99    }
100
101    /**
102     * Get the comment/summary/excerpt of the log entry or revision,
103     * for use in the notification body.
104     * @return string
105     */
106    protected function getRevOrLogComment(): string {
107        if ( $this->event->getExtraParam( 'logid' ) ) {
108            $logEntry = $this->getLogEntry();
109            if ( !$logEntry ) {
110                return '';
111            }
112            $services = MediaWikiServices::getInstance();
113            $formatter = $services->getLogFormatterFactory()->newFromEntry( $logEntry );
114
115            // Override the language of the log entry excerpt (T410339) - there is no easier way to do this
116            $context = new DerivativeContext( $formatter->context );
117            $context->setLanguage( $this->language );
118            $formatter->context = $context;
119
120            $excerpt = $formatter->getPlainActionText();
121            // Turn wikitext into plaintext
122            $excerpt = $services->getCommentFormatter()->format( $excerpt );
123            return Sanitizer::stripAllTags( $excerpt );
124        } else {
125            // Try to get edit summary.
126            $summary = $this->getRevisionEditSummary();
127            if ( $summary !== false && $summary !== '' ) {
128                return $summary;
129            }
130            // Fallback on edit excerpt.
131            if ( $this->userCan( RevisionRecord::DELETED_TEXT ) ) {
132                return $this->event->getExtraParam( 'excerpt', '' );
133            }
134            return '';
135        }
136    }
137
138    /** @inheritDoc */
139    public function getPrimaryLink() {
140        $logId = $this->event->getExtraParam( 'logid' );
141        if ( $logId ) {
142            $url = SpecialPage::getTitleFor( 'Log' )->getLocalURL( [ 'logid' => $logId ] );
143            $label = 'notification-link-text-view-logentry';
144        } else {
145            $url = $this->event->getTitle()->getLocalURL( [
146                'oldid' => 'prev',
147                'diff' => $this->event->getExtraParam( 'revid' ),
148            ] );
149            $label = 'notification-link-text-view-edit';
150        }
151        return [
152            'url' => $url,
153            // Label is only used for non-JS clients.
154            'label' => $this->msg( $label )->text(),
155        ];
156    }
157
158    /** @inheritDoc */
159    public function getSecondaryLinks() {
160        $pageLink = $this->getPageLink( $this->event->getTitle(), '', true );
161        if ( $this->isBundled() ) {
162            return [ $pageLink ];
163        } else {
164            return [ $this->getAgentLink(), $pageLink ];
165        }
166    }
167
168    /**
169     * @return LogEntry|false
170     */
171    private function getLogEntry() {
172        if ( $this->logEntry !== null ) {
173            return $this->logEntry;
174        }
175        $logId = $this->event->getExtraParam( 'logid' );
176        if ( !$logId ) {
177            $this->logEntry = false;
178        } else {
179            $dbr = MediaWikiServices::getInstance()->getConnectionProvider()->getReplicaDatabase();
180            $this->logEntry = DatabaseLogEntry::newFromId( $logId, $dbr ) ?: false;
181        }
182        return $this->logEntry;
183    }
184
185    /**
186     * Returns thank type
187     *
188     * @return string 'log' or 'rev'
189     */
190    private function getThankType() {
191        return $this->event->getExtraParam( 'logid' ) ? 'log' : 'rev';
192    }
193}