Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
27.91% covered (danger)
27.91%
12 / 43
25.00% covered (danger)
25.00%
1 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
Templating
27.91% covered (danger)
27.91%
12 / 43
25.00% covered (danger)
25.00%
1 / 4
139.40
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
 getUserLinks
69.23% covered (warning)
69.23%
9 / 13
0.00% covered (danger)
0.00%
0 / 1
5.73
 getContent
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
90
 getModeratedRevision
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace Flow;
4
5use Flow\Exception\FlowException;
6use Flow\Exception\InvalidParameterException;
7use Flow\Exception\PermissionException;
8use Flow\Model\AbstractRevision;
9use Flow\Model\PostRevision;
10use Flow\Parsoid\ContentFixer;
11use Flow\Repository\UserNameBatch;
12use MediaWiki\Linker\Linker;
13use MediaWiki\WikiMap\WikiMap;
14
15/**
16 * This class is slowly being deprecated. It used to house a minimalist
17 * php templating system, it is now just a few of the helpers that were
18 * reused in the new api responses and other parts of Flow.
19 */
20class Templating {
21    /**
22     * @var UserNameBatch
23     */
24    private $usernames;
25
26    /**
27     * @var RevisionActionPermissions
28     */
29    private $permissions;
30
31    /**
32     * @var ContentFixer
33     */
34    private $contentFixer;
35
36    /**
37     * @param UserNameBatch $usernames
38     * @param ContentFixer $contentFixer
39     * @param RevisionActionPermissions $permissions
40     */
41    public function __construct(
42        UserNameBatch $usernames,
43        ContentFixer $contentFixer,
44        RevisionActionPermissions $permissions
45    ) {
46        $this->usernames = $usernames;
47        $this->contentFixer = $contentFixer;
48        $this->permissions = $permissions;
49    }
50
51    /**
52     * Returns pretty-printed user links + user tool links for history and
53     * RecentChanges pages.
54     *
55     * Moderation-aware.
56     *
57     * @param AbstractRevision $revision Revision to display
58     * @return string HTML
59     * @throws PermissionException
60     */
61    public function getUserLinks( AbstractRevision $revision ) {
62        if ( !$revision->isModerated() && !$this->permissions->isAllowed( $revision, 'history' ) ) {
63            throw new PermissionException( 'Insufficient permissions to see userlinks for rev_id = ' .
64                $revision->getRevisionId()->getAlphadecimal() );
65        }
66
67        // Convert to use MapCacheLRU?
68        // if this specific revision is moderated, its usertext can always be
69        // displayed, since it will be the moderator user
70        static $cache = [];
71        $userid = $revision->getUserId();
72        $userip = $revision->getUserIp();
73        if ( isset( $cache[$userid][$userip] ) ) {
74            return $cache[$userid][$userip];
75        }
76        $username = $this->usernames->get( WikiMap::getCurrentWikiId(), $userid, $userip );
77        $cache[$userid][$userip] = $username ?
78            Linker::userLink( $userid, $username ) . Linker::userToolLinks( $userid, $username ) :
79            '';
80        return $cache[$userid][$userip];
81    }
82
83    /**
84     * Usually the revisions's content can just be displayed. In the event
85     * of moderation, however, that info should not be exposed.
86     *
87     * If a specific i18n message is available for a certain moderation level,
88     * that message will be returned (well, unless the user actually has the
89     * required permissions to view the full content). Otherwise, in normal
90     * cases, the full content will be returned.
91     *
92     * The content-type of the return value varies on the $format parameter.
93     * Further processing in the final output stage must escape all formats
94     * other than the default 'html' and 'fixed-html'.
95     *
96     * @param AbstractRevision $revision Revision to display content for
97     * @param string $format Format to output content in one of:
98     *   (fixed-html|html|wikitext|topic-title-html|topic-title-wikitext|topic-title-plaintext)
99     * @return string HTML if requested, otherwise plain text
100     * @throws InvalidParameterException
101     */
102    public function getContent( AbstractRevision $revision, $format = 'fixed-html' ) {
103        if ( !in_array( $format, [ 'fixed-html', 'html', 'wikitext', 'topic-title-html',
104                'topic-title-wikitext', 'topic-title-plaintext' ]
105            )
106        ) {
107            throw new InvalidParameterException( 'Invalid format: ' . $format );
108        }
109
110        $mainPermissionAction = ( $revision instanceof PostRevision && $revision->isTopicTitle() ) ?
111            'view-topic-title' :
112            'view';
113
114        $allowed = $this->permissions->isAllowed( $revision, $mainPermissionAction );
115        // Posts require view access to the topic title as well
116        if ( $allowed && $revision instanceof PostRevision && !$revision->isTopicTitle() ) {
117            $allowed = $this->permissions->isAllowed(
118                $revision->getRootPost(),
119                'view'
120            );
121        }
122
123        if ( !$allowed ) {
124            // failsafe - never output content if permissions aren't satisfied!
125            return '';
126        }
127
128        if ( $format === 'fixed-html' ) {
129            // Parsoid doesn't render redlinks & doesn't strip bad images
130            $content = $this->contentFixer->getContent( $revision );
131        } else {
132            $content = $revision->getContent( $format );
133        }
134
135        return $content;
136    }
137
138    public function getModeratedRevision( AbstractRevision $revision ) {
139        if ( $revision->isModerated() ) {
140            return $revision;
141        } else {
142            try {
143                return Container::get( 'collection.cache' )->getLastRevisionFor( $revision );
144            } catch ( FlowException $e ) {
145                wfDebugLog( 'Flow', "Failed loading last revision for revid " .
146                    $revision->getRevisionId()->getAlphadecimal() . " with collection id " .
147                    $revision->getCollectionId()->getAlphadecimal() );
148                throw $e;
149            }
150        }
151    }
152}