Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 94
0.00% covered (danger)
0.00%
0 / 17
CRAP
0.00% covered (danger)
0.00%
0 / 1
FlowPresentationModel
0.00% covered (danger)
0.00%
0 / 94
0.00% covered (danger)
0.00%
0 / 17
702
0.00% covered (danger)
0.00%
0 / 1
 hasTitle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 hasValidTopicWorkflowId
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 hasValidPostId
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 getSecondaryLinks
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPostLinkUrl
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
2
 getTopicLinkUrl
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTopicTitleObj
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 getBoardLinkByNewestTopic
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 getBoardByNewestTopicUrl
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getViewTopicLink
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 getBoardByNewestLink
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getBoardLink
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getContentSnippet
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTopicTitle
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 truncateTopicTitle
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 isUserTalkPage
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getFlowUnwatchDynamicActionLink
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 1
42
1<?php
2
3namespace Flow\Notifications;
4
5use EchoEventPresentationModel;
6use Flow\Container;
7use Flow\Model\UUID;
8use Flow\UrlGenerator;
9use MediaWiki\MediaWikiServices;
10use MediaWiki\Title\Title;
11
12abstract class FlowPresentationModel extends EchoEventPresentationModel {
13
14    protected function hasTitle() {
15        return (bool)$this->event->getTitle();
16    }
17
18    protected function hasValidTopicWorkflowId() {
19        $topicWorkflowId = $this->event->getExtraParam( 'topic-workflow' );
20        return $topicWorkflowId && $topicWorkflowId instanceof UUID;
21    }
22
23    protected function hasValidPostId() {
24        $postId = $this->event->getExtraParam( 'post-id' );
25        return $postId && $postId instanceof UUID;
26    }
27
28    public function getSecondaryLinks() {
29        return [ $this->getAgentLink() ];
30    }
31
32    /**
33     * Return a full url of following format:
34     *   https://<site>/wiki/Topic:<topicId>?topic_showPostId=<$firstChronologicallyPostId>&fromnotif=1#flow-post-<$anchorPostID>
35     * @param UUID|null $firstChronologicallyPostId First unread post ID
36     * @param UUID|null $anchorPostId Post ID for anchor (i.e. to scroll to)
37     * @return string
38     */
39    protected function getPostLinkUrl( $firstChronologicallyPostId = null, $anchorPostId = null ) {
40        /** @var UUID $firstChronologicallyPostId */
41        $firstChronologicallyPostId ??= $this->event->getExtraParam( 'post-id' );
42        '@phan-var UUID $firstChronologicallyPostId';
43
44        $anchorPostId ??= $firstChronologicallyPostId;
45        $title = $this->getTopicTitleObj(
46            'flow-post-' . $anchorPostId->getAlphadecimal()
47        );
48
49        $url = $title->getFullURL(
50            [
51                'topic_showPostId' => $firstChronologicallyPostId->getAlphadecimal(),
52                'fromnotif' => 1,
53            ]
54        );
55
56        return $url;
57    }
58
59    /**
60     * Return a full url of following format:
61     *   https://<site>/wiki/Topic:<topicId>&fromnotif=1
62     * @return string
63     */
64    protected function getTopicLinkUrl() {
65        return $this->getTopicTitleObj()->getFullURL( [ 'fromnotif' => 1 ] );
66    }
67
68    /**
69     * Get the topic title Title
70     *
71     * @param string $fragment
72     * @return Title
73     */
74    protected function getTopicTitleObj( $fragment = '' ) {
75        /** @var UUID $workflowId */
76        $workflowId = $this->event->getExtraParam( 'topic-workflow' );
77        '@phan-var UUID $workflowId';
78
79        return Title::makeTitleSafe(
80            NS_TOPIC,
81            $workflowId->getAlphadecimal(),
82            $fragment
83        );
84    }
85
86    /**
87     * Return a full url to a board sorted by newest topic
88     *   ?topiclist_sortby=newest
89     * @return array
90     */
91    protected function getBoardLinkByNewestTopic() {
92        return [
93            'url' => $this->getBoardByNewestTopicUrl(),
94            'label' => $this->msg( 'flow-notification-link-text-view-topics' )->text()
95        ];
96    }
97
98    protected function getBoardByNewestTopicUrl() {
99        /** @var UrlGenerator $urlGenerator */
100        $urlGenerator = Container::get( 'url_generator' );
101        return $urlGenerator->boardLink( $this->event->getTitle(), 'newest' )->getFullURL();
102    }
103
104    protected function getViewTopicLink() {
105        /** @var UUID $workflow */
106        $workflow = $this->event->getExtraParam( 'topic-workflow' );
107        '@phan-var UUID $workflow';
108
109        $title = Title::newFromText( $workflow->getAlphadecimal(), NS_TOPIC );
110        return [
111            'url' => $title->getFullURL(),
112            'label' => $this->msg( 'flow-notification-link-text-view-topic' )->text(),
113        ];
114    }
115
116    protected function getBoardByNewestLink() {
117        return $this->getBoardLink( 'newest' );
118    }
119
120    protected function getBoardLink( $sortBy = null ) {
121        $query = $sortBy ? [ 'topiclist_sortby' => $sortBy ] : [];
122        return $this->getPageLink(
123            $this->event->getTitle(), '', true, $query
124        );
125    }
126
127    protected function getContentSnippet() {
128        return $this->event->getExtraParam( 'content' );
129    }
130
131    protected function getTopicTitle( $extraParamName = 'topic-title' ) {
132        $topicTitle = $this->event->getExtraParam( $extraParamName );
133        return $this->truncateTopicTitle( $topicTitle );
134    }
135
136    protected function truncateTopicTitle( $topicTitle ) {
137        return $this->language->embedBidi(
138            $this->language->truncateForVisual(
139                $topicTitle,
140                self::SECTION_TITLE_RECOMMENDED_LENGTH,
141                '...',
142                false
143            )
144        );
145    }
146
147    protected function isUserTalkPage() {
148        // Would like to do $this->event->getTitle()->equals( $this->user->getTalkPage() )
149        // but $this->user is private in the parent class
150        $username = $this->getViewingUserForGender();
151        return $this->event->getTitle()->getNamespace() === NS_USER_TALK &&
152            $this->event->getTitle()->getText() === $username;
153    }
154
155    /**
156     * Get a flow-specific watch/unwatch dynamic action link
157     *
158     * @param bool $isTopic Unwatching a topic. If set to false, the
159     *  action is unwatching a board
160     * @return array|null Array representing the dynamic action secondary link.
161     *  Returns null if either
162     *   * The notification came from the user's talk page, as that
163     *     page cannot be unwatched.
164     *   * The page is not currently watched.
165     */
166    protected function getFlowUnwatchDynamicActionLink( $isTopic = false ) {
167        $title = $isTopic ? $this->getTopicTitleObj() : $this->event->getTitle();
168        $query = [ 'action' => 'unwatch' ];
169        $link = $this->getWatchActionLink( $title );
170        $type = $isTopic ? 'topic' : 'board';
171        $stringPageTitle = $isTopic ? $this->getTopicTitle() : $this->getTruncatedTitleText( $title );
172
173        if ( $this->isUserTalkPage() ||
174             !MediaWikiServices::getInstance()->getWatchlistManager()->isWatched( $this->getUser(), $title )
175            ) {
176            return null;
177        }
178
179        $messageKeys = [
180            'confirmation' => [
181                // notification-dynamic-actions-flow-board-unwatch-confirmation
182                // notification-dynamic-actions-flow-topic-unwatch-confirmation
183                'title' => $this
184                    ->msg( 'notification-dynamic-actions-flow-' . $type . '-unwatch-confirmation' )
185                    ->params(
186                        $stringPageTitle,
187                        $title->getFullURL(),
188                        $this->getUser()->getName()
189                    )
190                    ->parse(),
191                // notification-dynamic-actions-flow-board-unwatch-confirmation-description
192                // notification-dynamic-actions-flow-topic-unwatch-confirmation-description
193                'description' => $this
194                    ->msg( 'notification-dynamic-actions-flow-' . $type . '-unwatch-confirmation-description' )
195                    ->params(
196                        $stringPageTitle,
197                        $title->getFullURL(),
198                        $this->getUser()->getName()
199                    )
200                    ->parse(),
201            ],
202        ];
203
204        // Override messages with flow-specific messages
205        $link[ 'data' ][ 'messages' ] = array_replace( $link[ 'data' ][ 'messages' ], $messageKeys );
206
207        // notification-dynamic-actions-flow-board-unwatch
208        // notification-dynamic-actions-flow-topic-unwatch
209        $link['label'] = $this
210            ->msg( 'notification-dynamic-actions-flow-' . $type . '-unwatch' )
211            ->params(
212                $stringPageTitle,
213                $title->getFullURL( $query ),
214                $this->getUser()->getName()
215            )
216            ->text();
217
218        return $link;
219    }
220}