Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
81.82% covered (warning)
81.82%
36 / 44
50.00% covered (danger)
50.00%
3 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
EchoPresentationModelSection
83.72% covered (warning)
83.72%
36 / 43
50.00% covered (danger)
50.00%
3 / 6
13.73
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getRawSectionTitle
72.73% covered (warning)
72.73%
8 / 11
0.00% covered (danger)
0.00%
0 / 1
4.32
 getParsedSectionTitle
78.57% covered (warning)
78.57%
11 / 14
0.00% covered (danger)
0.00%
0 / 1
3.09
 exists
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getTitleWithSection
87.50% covered (warning)
87.50%
7 / 8
0.00% covered (danger)
0.00%
0 / 1
3.02
 getTruncatedSectionTitle
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace MediaWiki\Extension\Notifications\Formatters;
4
5use BadMethodCallException;
6use Language;
7use MediaWiki\Extension\Notifications\DiscussionParser;
8use MediaWiki\Extension\Notifications\Model\Event;
9use MediaWiki\Revision\RevisionRecord;
10use MediaWiki\Title\Title;
11use MediaWiki\User\User;
12use Parser;
13
14/**
15 * Component that represents a section of a page to be used from EchoEventPresentationModel subclass.
16 */
17class EchoPresentationModelSection {
18
19    /**
20     * @var string|false|null
21     */
22    private $rawSectionTitle = null;
23
24    /**
25     * @var string|false|null
26     */
27    private $parsedSectionTitle = null;
28
29    /**
30     * @var Event
31     */
32    protected $event;
33
34    /**
35     * @var User
36     */
37    protected $user;
38
39    /**
40     * @var Language
41     */
42    protected $language;
43
44    /**
45     * @param Event $event
46     * @param User $user
47     * @param Language $language
48     */
49    public function __construct( Event $event, User $user, Language $language ) {
50        $this->event = $event;
51        $this->user = $user;
52        $this->language = $language;
53    }
54
55    /**
56     * Get the raw (unparsed) section title
57     * @return string|false Section title
58     */
59    protected function getRawSectionTitle() {
60        if ( $this->rawSectionTitle !== null ) {
61            return $this->rawSectionTitle;
62        }
63        $sectionTitle = $this->event->getExtraParam( 'section-title' );
64        if ( !$sectionTitle ) {
65            $this->rawSectionTitle = false;
66            return false;
67        }
68        // Check permissions
69        if ( !$this->event->userCan( RevisionRecord::DELETED_TEXT, $this->user ) ) {
70            $this->rawSectionTitle = false;
71            return false;
72        }
73
74        $this->rawSectionTitle = $sectionTitle;
75        return $this->rawSectionTitle;
76    }
77
78    /**
79     * Get the section title parsed to plain text
80     * @return string|false Section title (plain text)
81     */
82    protected function getParsedSectionTitle() {
83        if ( $this->parsedSectionTitle !== null ) {
84            return $this->parsedSectionTitle;
85        }
86        $rawSectionTitle = $this->getRawSectionTitle();
87        if ( !$rawSectionTitle ) {
88            $this->parsedSectionTitle = false;
89            return false;
90        }
91        $this->parsedSectionTitle = DiscussionParser::getTextSnippet(
92            $rawSectionTitle,
93            $this->language,
94            DiscussionParser::DEFAULT_SNIPPET_LENGTH,
95            $this->event->getTitle(),
96            // linestart=false, because this wikitext was inside a heading like `== … ==`,
97            // so start-of-line markup like `*` should not be parsed (T299572)
98            false
99        );
100        return $this->parsedSectionTitle;
101    }
102
103    /**
104     * Check if there is a section.
105     *
106     * This also returns false if the revision is deleted,
107     * even if there is a section, because the section can't
108     * be viewed in that case.
109     * @return bool Whether there is a section
110     */
111    public function exists() {
112        return (bool)$this->getRawSectionTitle();
113    }
114
115    /**
116     * Get a Title pointing to the section, if available.
117     * @return Title
118     */
119    public function getTitleWithSection() {
120        $title = $this->event->getTitle();
121        if ( $title === null ) {
122            throw new BadMethodCallException( 'Event #' . $this->event->getId() . ' with no title' );
123        }
124        $section = $this->getParsedSectionTitle();
125        if ( $section ) {
126            $fragment = substr( Parser::guessSectionNameFromStrippedText( $section ), 1 );
127            $title = $title->createFragmentTarget( $fragment );
128        }
129        return $title;
130    }
131
132    /**
133     * Get truncated section title, according to user's language.
134     * You should only call this if EchoPresentationModelSection::exists returns true.
135     * @return string
136     */
137    public function getTruncatedSectionTitle() {
138        return $this->language->embedBidi( $this->language->truncateForVisual(
139            $this->getParsedSectionTitle(),
140            EchoEventPresentationModel::SECTION_TITLE_RECOMMENDED_LENGTH,
141            '...',
142            false
143        ) );
144    }
145}
146
147class_alias( EchoPresentationModelSection::class, 'EchoPresentationModelSection' );