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