Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
68.09% covered (warning)
68.09%
32 / 47
50.00% covered (danger)
50.00%
6 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
RevisionSourceHandler
68.09% covered (warning)
68.09%
32 / 47
50.00% covered (danger)
50.00%
6 / 12
35.34
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 postValidationSetup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 constructHtmlUrl
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
2.01
 run
85.71% covered (warning)
85.71%
18 / 21
0.00% covered (danger)
0.00%
0 / 1
5.07
 getTargetFormat
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getResponseBodySchemaFileName
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 getETag
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLastModified
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getOutputMode
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
 needsWriteAccess
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getParamSettings
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasRepresentation
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace MediaWiki\Rest\Handler;
4
5use LogicException;
6use MediaWiki\Rest\Handler\Helper\PageRestHelperFactory;
7use MediaWiki\Rest\Handler\Helper\RevisionContentHelper;
8use MediaWiki\Rest\LocalizedHttpException;
9use MediaWiki\Rest\Response;
10use MediaWiki\Rest\SimpleHandler;
11use MediaWiki\Revision\RevisionRecord;
12use Wikimedia\Message\MessageValue;
13
14/**
15 * A handler that returns page source and metadata for the following routes:
16 * - /revision/{revision}
17 * - /revision/{revision}/bare
18 */
19class RevisionSourceHandler extends SimpleHandler {
20
21    private RevisionContentHelper $contentHelper;
22
23    public function __construct( PageRestHelperFactory $helperFactory ) {
24        $this->contentHelper = $helperFactory->newRevisionContentHelper();
25    }
26
27    protected function postValidationSetup() {
28        $this->contentHelper->init( $this->getAuthority(), $this->getValidatedParams() );
29    }
30
31    /**
32     * @param RevisionRecord $rev
33     * @return string
34     */
35    private function constructHtmlUrl( RevisionRecord $rev ): string {
36        // TODO: once legacy "v1" routes are removed, just use the path prefix from the module.
37        $pathPrefix = $this->getModule()->getPathPrefix();
38        if ( strlen( $pathPrefix ) == 0 ) {
39            $pathPrefix = 'v1';
40        }
41
42        return $this->getRouter()->getRouteUrl(
43            '/' . $pathPrefix . '/revision/{id}/html',
44            [ 'id' => $rev->getId() ]
45        );
46    }
47
48    /**
49     * @return Response
50     * @throws LocalizedHttpException
51     */
52    public function run() {
53        $this->contentHelper->checkAccess();
54
55        $outputMode = $this->getOutputMode();
56        switch ( $outputMode ) {
57            case 'restbase': // compatibility for restbase migration
58                $body = [ 'items' => [ $this->contentHelper->constructRestbaseCompatibleMetadata() ] ];
59                break;
60            case 'bare':
61                $revisionRecord = $this->contentHelper->getTargetRevision();
62                $body = $this->contentHelper->constructMetadata();
63                // @phan-suppress-next-line PhanTypeMismatchArgumentNullable revisionRecord is set when used
64                $body['html_url'] = $this->constructHtmlUrl( $revisionRecord );
65                $response = $this->getResponseFactory()->createJson( $body );
66                $this->contentHelper->setCacheControl( $response );
67                break;
68            case 'source':
69                $content = $this->contentHelper->getContent();
70                $body = $this->contentHelper->constructMetadata();
71                $body['source'] = $content->getText();
72                break;
73            default:
74                throw new LogicException( "Unknown output mode $outputMode" );
75        }
76
77        $response = $this->getResponseFactory()->createJson( $body );
78        $this->contentHelper->setCacheControl( $response );
79
80        return $response;
81    }
82
83    private function getTargetFormat(): string {
84        return $this->getConfig()['format'];
85    }
86
87    protected function getResponseBodySchemaFileName( string $method ): ?string {
88        switch ( $this->getTargetFormat() ) {
89            case 'bare':
90                return 'includes/Rest/Handler/Schema/RevisionMetaDataBare.json';
91
92            case 'source':
93                return 'includes/Rest/Handler/Schema/RevisionMetaDataWithSource.json';
94
95            default:
96                throw new LocalizedHttpException(
97                    new MessageValue( "rest-unsupported-target-format" ), 500
98                );
99        }
100    }
101
102    /**
103     * @return string|null
104     */
105    protected function getETag(): ?string {
106        return $this->contentHelper->getETag();
107    }
108
109    /**
110     * @return string|null
111     */
112    protected function getLastModified(): ?string {
113        return $this->contentHelper->getLastModified();
114    }
115
116    private function getOutputMode(): string {
117        if ( $this->getRouter()->isRestbaseCompatEnabled( $this->getRequest() ) ) {
118            return 'restbase';
119        }
120        return $this->getConfig()['format'];
121    }
122
123    public function needsWriteAccess(): bool {
124        return false;
125    }
126
127    public function getParamSettings(): array {
128        return $this->contentHelper->getParamSettings();
129    }
130
131    /**
132     * @return bool
133     */
134    protected function hasRepresentation() {
135        return $this->contentHelper->hasContent();
136    }
137}