Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
90.57% covered (success)
90.57%
48 / 53
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
VoiceHandler
90.57% covered (success)
90.57%
48 / 53
50.00% covered (danger)
50.00%
1 / 2
10.08
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getDefaultVoice
89.80% covered (warning)
89.80%
44 / 49
0.00% covered (danger)
0.00%
0 / 1
9.09
1<?php
2
3namespace MediaWiki\Wikispeech;
4
5/**
6 * @file
7 * @ingroup Extensions
8 * @license GPL-2.0-or-later
9 */
10
11use Config;
12use Psr\Log\LoggerInterface;
13use WANObjectCache;
14
15/**
16 * Handles voice information.
17 *
18 * @since 0.1.7
19 */
20class VoiceHandler {
21
22    /** @var LoggerInterface */
23    private $logger;
24
25    /** @var Config */
26    private $config;
27
28    /** @var SpeechoidConnector */
29    private $speechoidConnector;
30
31    /** @var WANObjectCache */
32    private $cache;
33
34    /**
35     * @since 0.1.7
36     * @param LoggerInterface $logger
37     * @param Config $config
38     * @param SpeechoidConnector $speechoidConnector
39     * @param WANObjectCache $cache
40     */
41    public function __construct( $logger, $config, $speechoidConnector, $cache ) {
42        $this->logger = $logger;
43        $this->config = $config;
44        $this->speechoidConnector = $speechoidConnector;
45        $this->cache = $cache;
46    }
47
48    /**
49     * Picks up the configured default voice for a language, or
50     * fallback on the first registered voice for that language.
51     *
52     * Default voice per language response from Speechoid is cached
53     * for one hour.
54     *
55     * @since 0.1.7
56     * @param string $language
57     * @return string|null Default language or null if language or no
58     *  voices are registered.
59     */
60    public function getDefaultVoice( $language ) {
61        $cacheKey = $this->cache->makeKey(
62            'Wikispeech.voiceHandler.defaultVoicePerLanguage',
63            $language
64        );
65        $defaultVoicePerLanguage = $this->cache->get( $cacheKey );
66        if (
67            // not set
68            $defaultVoicePerLanguage === null ||
69            // cache error
70            $defaultVoicePerLanguage === false
71        ) {
72            $defaultVoicePerLanguage = $this->speechoidConnector->listDefaultVoicePerLanguage();
73            // One hour TTL.  I.e. it will take one hour for a new
74            // default language in Speechoid to be selected.
75            $this->cache->set(
76                $cacheKey,
77                $defaultVoicePerLanguage,
78                $this->cache::TTL_HOUR
79            );
80        }
81        $registeredVoicesPerLanguage = $this->config->get( 'WikispeechVoices' );
82        $defaultVoice = null;
83        if ( array_key_exists( $language, $defaultVoicePerLanguage ) ) {
84            // is defined as a language in list of default languages
85            $defaultVoice = $defaultVoicePerLanguage[$language];
86        }
87        if ( !$defaultVoice ) {
88            // unable to find a default voice for the language
89            if ( !array_key_exists( $language, $registeredVoicesPerLanguage ) ) {
90                // not a registered language
91                $this->logger->error( __METHOD__ . ': ' .
92                    'Not a registered language: {language}',
93                    [ 'language' => $language ]
94                );
95                return null;
96            }
97            $languageVoices = $registeredVoicesPerLanguage[$language];
98            if ( !$languageVoices ) {
99                // no voices registered to the language
100                $this->logger->error( __METHOD__ . ': ' .
101                    'No voices registered to language: {language}',
102                    [ 'language' => $language ]
103                );
104                return null;
105            }
106            // falling back on first registered voice as default
107            return $languageVoices[0];
108        }
109        // make sure defaultVoice is a registered voice
110        if ( !array_key_exists( $language, $registeredVoicesPerLanguage ) ) {
111            // language registered with default voice but not a as
112            // language with voices.
113            $this->logger->error( __METHOD__ . ': ' .
114                'Default voice found but language not registered in config: {language}',
115                [ 'language' => $language ]
116            );
117            return null;
118        }
119        $languageVoices = $registeredVoicesPerLanguage[$language];
120        if ( !in_array( $defaultVoice, $languageVoices ) ) {
121            $this->logger->error( __METHOD__ . ': ' .
122                'Default voice not registered to language: {voice} {language}',
123                [
124                    'voice' => $defaultVoice,
125                    'language' => $language
126                ]
127            );
128            return null;
129        }
130        return $defaultVoice;
131    }
132}