Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.24% covered (success)
95.24%
40 / 42
71.43% covered (warning)
71.43%
5 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
PageLintHandler
95.24% covered (success)
95.24%
40 / 42
71.43% covered (warning)
71.43%
5 / 7
10
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
 getParamSettings
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 needsWriteAccess
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getRedirectHelper
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 postValidationSetup
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 run
100.00% covered (success)
100.00%
28 / 28
100.00% covered (success)
100.00%
1 / 1
4
 getResponseBodySchemaFileName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Rest\Handler;
4
5use MediaWiki\Parser\Parsoid\LintErrorChecker;
6use MediaWiki\Rest\Handler\Helper\PageContentHelper;
7use MediaWiki\Rest\Handler\Helper\PageRedirectHelper;
8use MediaWiki\Rest\Handler\Helper\PageRestHelperFactory;
9use MediaWiki\Rest\LocalizedHttpException;
10use MediaWiki\Rest\Response;
11use MediaWiki\Rest\SimpleHandler;
12use Wikimedia\Assert\Assert;
13use Wikimedia\Message\MessageValue;
14use Wikimedia\Parsoid\Core\ClientError;
15use Wikimedia\Parsoid\Core\ResourceLimitExceededException;
16
17/**
18 * A handler that returns linter errors for main (text) content of pages
19 *
20 * @package MediaWiki\Rest\Handler
21 */
22class PageLintHandler extends SimpleHandler {
23
24    private PageRestHelperFactory $helperFactory;
25    private PageContentHelper $contentHelper;
26    private LintErrorChecker $lintErrorChecker;
27
28    public function __construct(
29        PageRestHelperFactory $helperFactory,
30        LintErrorChecker $lintErrorChecker
31    ) {
32        $this->helperFactory = $helperFactory;
33        $this->contentHelper = $helperFactory->newPageContentHelper();
34        $this->lintErrorChecker = $lintErrorChecker;
35    }
36
37    public function getParamSettings(): array {
38        return $this->contentHelper->getParamSettings();
39    }
40
41    public function needsWriteAccess(): bool {
42        return false;
43    }
44
45    private function getRedirectHelper(): PageRedirectHelper {
46        return $this->helperFactory->newPageRedirectHelper(
47            $this->getResponseFactory(),
48            $this->getRouter(),
49            $this->getPath(),
50            $this->getRequest()
51        );
52    }
53
54    protected function postValidationSetup() {
55        $authority = $this->getAuthority();
56        $this->contentHelper->init( $authority, $this->getValidatedParams() );
57    }
58
59    /**
60     * @return Response
61     * @throws LocalizedHttpException
62     */
63    public function run(): Response {
64        $this->contentHelper->checkAccessPermission();
65        $page = $this->contentHelper->getPageIdentity();
66
67        $followWikiRedirects = $this->contentHelper->getRedirectsAllowed();
68
69        // The page should be set if checkAccessPermission() didn't throw
70        Assert::invariant( $page !== null, 'Page should be known' );
71
72        $redirectHelper = $this->getRedirectHelper();
73        $redirectHelper->setFollowWikiRedirects( $followWikiRedirects );
74        // Respect wiki redirects and variant redirects unless ?redirect=no was provided.
75        // With ?redirect=no, non-existing pages with an existing variant will get a 404.
76        $redirectResponse = $redirectHelper->createRedirectResponseIfNeeded(
77            $page,
78            $this->contentHelper->getTitleText()
79        );
80
81        if ( $redirectResponse !== null ) {
82            return $redirectResponse;
83        }
84
85        // We could have a missing page at this point, check and return 404 if that's the case
86        $this->contentHelper->checkHasContent();
87
88        // Get the content and make sure that it is text content
89        $content = $this->contentHelper->getContent();
90
91        try {
92            $lintErrors = $this->lintErrorChecker->check( $content->getText() );
93            $response = $this->getResponseFactory()->createJson( $lintErrors );
94            $this->contentHelper->setCacheControl( $response );
95        } catch ( ClientError $e ) {
96            throw new LocalizedHttpException(
97                new MessageValue( "rest-lint-backend-error", [ $e->getMessage() ] ),
98                400
99            );
100        } catch ( ResourceLimitExceededException $e ) {
101            throw new LocalizedHttpException(
102                new MessageValue( "rest-resource-limit-exceeded", [ $e->getMessage() ] ),
103                413
104            );
105        }
106
107        return $response;
108    }
109
110    public function getResponseBodySchemaFileName( string $method ): ?string {
111        return 'includes/Rest/Handler/Schema/ContentLintErrors.json';
112    }
113}