Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
87.37% covered (warning)
87.37%
83 / 95
60.00% covered (warning)
60.00%
3 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiWikispeechSegment
87.37% covered (warning)
87.37%
83 / 95
60.00% covered (warning)
60.00%
3 / 5
21.89
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 execute
90.91% covered (success)
90.91%
40 / 44
0.00% covered (danger)
0.00%
0 / 1
9.06
 isValidRemoveTags
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
9
 getAllowedParams
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
1 / 1
1
 getExamplesMessages
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Wikispeech\Api;
4
5/**
6 * @file
7 * @ingroup API
8 * @ingroup Extensions
9 * @license GPL-2.0-or-later
10 */
11
12use ApiBase;
13use ApiMain;
14use ConfigFactory;
15use FormatJson;
16use MediaWiki\Http\HttpRequestFactory;
17use MediaWiki\Revision\RevisionStore;
18use MediaWiki\Wikispeech\Segment\SegmentPageFactory;
19use Title;
20use WANObjectCache;
21use Wikimedia\ParamValidator\ParamValidator;
22
23/**
24 * API module to segment a page.
25 *
26 * @since 0.0.1
27 */
28class ApiWikispeechSegment extends ApiBase {
29
30    /** @var WANObjectCache */
31    private $cache;
32
33    /** @var HttpRequestFactory */
34    private $requestFactory;
35
36    /** @var RevisionStore */
37    private $revisionStore;
38
39    /** @var ConfigFactory */
40    private $configFactory;
41
42    /**
43     * @since 0.1.7
44     * @param ApiMain $mainModule
45     * @param string $moduleName
46     * @param WANObjectCache $cache
47     * @param HttpRequestFactory $requestFactory
48     * @param RevisionStore $revisionStore
49     * @param ConfigFactory $configFactory
50     * @param string $modulePrefix
51     */
52    public function __construct(
53        ApiMain $mainModule,
54        string $moduleName,
55        WANObjectCache $cache,
56        HttpRequestFactory $requestFactory,
57        RevisionStore $revisionStore,
58        ConfigFactory $configFactory,
59        string $modulePrefix = ''
60    ) {
61        parent::__construct( $mainModule, $moduleName, $modulePrefix );
62        $this->cache = $cache;
63        $this->requestFactory = $requestFactory;
64        $this->revisionStore = $revisionStore;
65        $this->configFactory = $configFactory;
66    }
67
68    /**
69     * Execute an API request.
70     *
71     * @since 0.0.1
72     */
73    public function execute() {
74        $parameters = $this->extractRequestParams();
75        if (
76            isset( $parameters['consumer-url'] ) &&
77            !$this->getConfig()->get( 'WikispeechProducerMode' ) ) {
78            $this->dieWithError( 'apierror-wikispeech-consumer-not-allowed' );
79        }
80        $title = Title::newFromText( $parameters['page'] );
81        if ( !$title || $title->isExternal() ) {
82            $this->dieWithError( [
83                'apierror-invalidtitle',
84                wfEscapeWikiText( $parameters['page'] )
85            ] );
86        }
87        if ( !isset( $parameters['consumer-url'] ) && !$title->exists() ) {
88            $this->dieWithError( 'apierror-missingtitle' );
89        }
90        $result = FormatJson::parse(
91            $parameters['removetags'],
92            FormatJson::FORCE_ASSOC
93        );
94        if ( !$result->isGood() ) {
95            $this->dieWithError( 'apierror-wikispeech-segment-removetagsinvalidjson' );
96        }
97        $removeTags = $result->getValue();
98        if ( !self::isValidRemoveTags( $removeTags ) ) {
99            $this->dieWithError( 'apierror-wikispeech-segment-removetagsinvalid' );
100        }
101        $segmentPageFactory = new SegmentPageFactory(
102            $this->cache,
103            $this->configFactory
104        );
105        $segmentPageResponse = $segmentPageFactory
106            ->setSegmentBreakingTags( $parameters['segmentbreakingtags'] )
107            ->setRemoveTags( $removeTags )
108            ->setUseRevisionPropertiesCache( true )
109            ->setRequirePageRevisionProperties( false )
110            ->setUseSegmentsCache( true )
111            ->setContextSource( $this->getContext() )
112            ->setRevisionStore( $this->revisionStore )
113            ->setHttpRequestFactory( $this->requestFactory )
114            ->setConsumerUrl( $parameters['consumer-url'] )
115            ->segmentPage(
116                $title,
117                null
118            );
119
120        $this->getResult()->addValue(
121            null,
122            $this->getModuleName(),
123            [ 'segments' => $segmentPageResponse->getSegments()->toArray() ]
124        );
125    }
126
127    /**
128     * Tests if a variable is valid as "remove tags".
129     *
130     * The variable should be an associative array. Keys should be
131     * strings and values should be booleans, strings or sequential
132     * arrays containing strings.
133     *
134     * @since 0.0.1
135     * @param mixed $removeTags The variable to test.
136     * @return bool true if $removeTags is valid, else false.
137     */
138    public static function isValidRemoveTags( $removeTags ) {
139        if ( !is_array( $removeTags ) ) {
140            return false;
141        }
142        foreach ( $removeTags as $tagName => $rule ) {
143            if ( !is_string( $tagName ) ) {
144                // A key isn't a string.
145                return false;
146            }
147            if ( is_array( $rule ) ) {
148                // Rule is a list of class names.
149                foreach ( $rule as $className ) {
150                    if ( !is_string( $className ) ) {
151                        // Only strings are valid if the rule is
152                        // an array.
153                        return false;
154                    }
155                }
156            } elseif ( !is_bool( $rule ) && !is_string( $rule ) ) {
157                // Rule is not array, string or boolean.
158                return false;
159            }
160        }
161        return true;
162    }
163
164    /**
165     * Specify what parameters the API accepts.
166     *
167     * @since 0.0.1
168     * @return array
169     */
170    public function getAllowedParams() {
171        return array_merge(
172            parent::getAllowedParams(),
173            [
174                'page' => [
175                    ParamValidator::PARAM_TYPE => 'string',
176                    ParamValidator::PARAM_REQUIRED => true
177                ],
178                'removetags' => [
179                    ParamValidator::PARAM_TYPE => 'string',
180                    ParamValidator::PARAM_DEFAULT => json_encode(
181                        $this->getConfig()->get( 'WikispeechRemoveTags' )
182                    )
183                ],
184                'segmentbreakingtags' => [
185                    ParamValidator::PARAM_TYPE => 'string',
186                    ParamValidator::PARAM_ISMULTI => true,
187                    ParamValidator::PARAM_DEFAULT => implode(
188                        '|',
189                        $this->getConfig()->get( 'WikispeechSegmentBreakingTags' )
190                    )
191                ],
192                'consumer-url' => [
193                    ParamValidator::PARAM_TYPE => 'string'
194                ]
195            ]
196        );
197    }
198
199    /**
200     * Give examples of usage.
201     *
202     * @since 0.0.1
203     * @return array
204     */
205    public function getExamplesMessages() {
206        return [
207            'action=wikispeech-segment&format=json&page=Main_Page'
208            => 'apihelp-wikispeech-segment-example-1',
209            // phpcs:ignore Generic.Files.LineLength
210            'action=wikispeech-segment&format=json&page=Main_Page&removetags={"sup": true, "div": "toc"}&segmentbreakingtags=h1|h2'
211            => 'apihelp-wikispeech-segment-example-2',
212            'action=wikispeech-segment&format=json&page=Main_Page&consumer-url=https://consumer.url/w'
213            => 'apihelp-wikispeech-segment-example-3',
214        ];
215    }
216}