Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 71
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiDiscussionToolsPreview
0.00% covered (danger)
0.00%
0 / 71
0.00% covered (danger)
0.00%
0 / 4
56
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 1
20
 getAllowedParams
0.00% covered (danger)
0.00%
0 / 29
0.00% covered (danger)
0.00%
0 / 1
2
 isInternal
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Extension\DiscussionTools;
4
5use ApiBase;
6use ApiMain;
7use ApiUsageException;
8use MediaWiki\Extension\VisualEditor\ApiParsoidTrait;
9use MediaWiki\Extension\VisualEditor\VisualEditorParsoidClientFactory;
10use MediaWiki\Title\Title;
11use MediaWiki\User\TempUser\TempUserCreator;
12use MediaWiki\User\UserFactory;
13use SkinFactory;
14use Wikimedia\ParamValidator\ParamValidator;
15use Wikimedia\Parsoid\Utils\DOMCompat;
16use Wikimedia\Parsoid\Utils\DOMUtils;
17
18class ApiDiscussionToolsPreview extends ApiBase {
19    use ApiDiscussionToolsTrait;
20    use ApiParsoidTrait;
21
22    private CommentParser $commentParser;
23    private VisualEditorParsoidClientFactory $parsoidClientFactory;
24    private TempUserCreator $tempUserCreator;
25    private UserFactory $userFactory;
26    private SkinFactory $skinFactory;
27
28    public function __construct(
29        ApiMain $main,
30        string $name,
31        VisualEditorParsoidClientFactory $parsoidClientFactory,
32        CommentParser $commentParser,
33        TempUserCreator $tempUserCreator,
34        UserFactory $userFactory,
35        SkinFactory $skinFactory
36    ) {
37        parent::__construct( $main, $name );
38        $this->parsoidClientFactory = $parsoidClientFactory;
39        $this->commentParser = $commentParser;
40        $this->tempUserCreator = $tempUserCreator;
41        $this->userFactory = $userFactory;
42        $this->skinFactory = $skinFactory;
43    }
44
45    /**
46     * @inheritDoc
47     * @throws ApiUsageException
48     */
49    public function execute() {
50        $params = $this->extractRequestParams();
51        $title = Title::newFromText( $params['page'] );
52
53        if ( !$title ) {
54            $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['page'] ) ] );
55        }
56        if ( $params['type'] === 'topic' ) {
57            $this->requireAtLeastOneParameter( $params, 'sectiontitle' );
58        }
59
60        // Try without adding a signature
61        $result = $this->previewMessage(
62            $params['type'],
63            $title,
64            [
65                'wikitext' => $params['wikitext'],
66                'sectiontitle' => $params['sectiontitle']
67            ],
68            $params
69        );
70        $resultHtml = $result->getResultData( [ 'parse', 'text' ] );
71
72        // Check if there was a signature in a proper place
73        $container = DOMCompat::getBody( DOMUtils::parseHTML( $resultHtml ) );
74        $threadItemSet = $this->commentParser->parse( $container, $title->getTitleValue() );
75        if ( !CommentUtils::isSingleCommentSignedBy(
76            $threadItemSet, $this->getUserForPreview()->getName(), $container
77        ) ) {
78            // If not, add the signature and re-render
79            $signature = $this->msg( 'discussiontools-signature-prefix' )->inContentLanguage()->text() . '~~~~';
80            // Drop opacity of signature in preview to make message body preview clearer.
81            // Extract any leading spaces outside the <span> markup to ensure accurate previews.
82            $signature = preg_replace( '/([^ ].*)/', '<span style="opacity: 0.6;">$1</span>',
83                $signature );
84
85            $result = $this->previewMessage(
86                $params['type'],
87                $title,
88                [
89                    'wikitext' => $params['wikitext'],
90                    'sectiontitle' => $params['sectiontitle'],
91                    'signature' => $signature
92                ],
93                $params
94            );
95        }
96
97        $this->getResult()->addValue( null, $this->getModuleName(), $result->serializeForApiResult() );
98    }
99
100    /**
101     * @inheritDoc
102     */
103    public function getAllowedParams() {
104        return [
105            'type' => [
106                ParamValidator::PARAM_REQUIRED => true,
107                ParamValidator::PARAM_TYPE => [
108                    'reply',
109                    'topic',
110                ],
111                ApiBase::PARAM_HELP_MSG_PER_VALUE => [
112                    'reply' => 'apihelp-discussiontoolsedit-paramvalue-paction-addcomment',
113                    'topic' => 'apihelp-discussiontoolsedit-paramvalue-paction-addtopic',
114                ],
115            ],
116            'page' => [
117                ParamValidator::PARAM_REQUIRED => true,
118                ApiBase::PARAM_HELP_MSG => 'apihelp-visualeditoredit-param-page',
119            ],
120            'wikitext' => [
121                ParamValidator::PARAM_REQUIRED => true,
122                ParamValidator::PARAM_TYPE => 'text',
123            ],
124            'sectiontitle' => [
125                ParamValidator::PARAM_TYPE => 'string',
126                ApiBase::PARAM_HELP_MSG => 'apihelp-edit-param-sectiontitle',
127            ],
128            'useskin' => [
129                ParamValidator::PARAM_TYPE => array_keys( $this->skinFactory->getInstalledSkins() ),
130                ApiBase::PARAM_HELP_MSG => 'apihelp-parse-param-useskin',
131            ],
132        ];
133    }
134
135    /**
136     * @inheritDoc
137     */
138    public function isInternal() {
139        return true;
140    }
141}