Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.65% covered (success)
95.65%
22 / 23
88.89% covered (warning)
88.89%
8 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
Provider
95.65% covered (success)
95.65%
22 / 23
88.89% covered (warning)
88.89%
8 / 9
15
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getLanguageCode
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSpecMap
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSpecArgs
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
7
 getBidiProvider
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFormalityIndexProvider
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getGrammarTransformationsProvider
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLanguageFallbacksProvider
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPluralProvider
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * @license GPL-2.0-or-later
4 * @file
5 */
6
7namespace Wikimedia\Leximorph;
8
9use CLDRPluralRuleParser\Evaluator;
10use Psr\Log\LoggerInterface;
11use Wikimedia\Leximorph\Provider\FormalityIndex;
12use Wikimedia\Leximorph\Provider\GrammarTransformations;
13use Wikimedia\Leximorph\Provider\LanguageFallbacks;
14use Wikimedia\Leximorph\Provider\PluralRules;
15use Wikimedia\Leximorph\Provider\TextDirection;
16use Wikimedia\Leximorph\Traits\SpecBasedFactoryTrait;
17use Wikimedia\Leximorph\Util\JsonLoader;
18use Wikimedia\Leximorph\Util\XmlLoader;
19
20/**
21 * Provider
22 *
23 * This class is responsible for instantiating Leximorph provider objects
24 * (Index, GrammarTransformations, LanguageFallbacks, and PluralRules)
25 * using Wikimedia’s ObjectFactory. The Provider holds a default language code
26 * that is injected into language-specific providers.
27 *
28 * Usage Example:
29 * <code>
30 *            $provider = new Provider( 'en', $logger );
31 *            $plural = $provider->getPluralProvider();
32 * </code>
33 *
34 * @newable
35 * @since     1.45
36 * @author    Doğu Abaris (abaris@null.net)
37 * @license   https://www.gnu.org/copyleft/gpl.html GPL-2.0-or-later
38 */
39final class Provider {
40
41    use SpecBasedFactoryTrait;
42
43    /**
44     * Provider specifications.
45     *
46     * Each entry defines:
47     * - args: Default constructor arguments.
48     * - langDependent: Prepend the language code.
49     * - needsEvaluator: Inject a CLDR Evaluator instance.
50     * - needsLogger: Pass a logger instance.
51     * - needsJsonLoader: Inject a JsonLoader instance.
52     * - needsXmlLoader: Inject an XmlLoader instance.
53     * - needsSelf: Inject this Provider instance.
54     *
55     * @var array<class-string, array<string, mixed>>
56     */
57    private const PROVIDER_SPECS = [
58        TextDirection::class => [
59            'args' => [],
60        ],
61        FormalityIndex::class => [
62            'args' => [],
63            'langDependent' => true,
64            'needsLogger' => true,
65            'needsJsonLoader' => true,
66        ],
67        GrammarTransformations::class => [
68            'args' => [],
69            'langDependent' => true,
70            'needsJsonLoader' => true,
71        ],
72        LanguageFallbacks::class => [
73            'args' => [],
74            'langDependent' => true,
75            'needsLogger' => true,
76            'needsJsonLoader' => true,
77        ],
78        PluralRules::class => [
79            'args' => [],
80            'langDependent' => true,
81            'needsEvaluator' => true,
82            'needsSelf' => true,
83            'needsLogger' => true,
84            'needsXmlLoader' => true,
85        ],
86    ];
87
88    /**
89     * Initializes a new Provider instance with a default language code and a logger.
90     *
91     * @param string $langCode The default language code to use.
92     * @param ?LoggerInterface $logger Optional logger; defaults to a NullLogger.
93     *
94     * @since 1.45
95     */
96    public function __construct( string $langCode, ?LoggerInterface $logger = null ) {
97        $this->langCode = $langCode;
98        $this->logger = $logger;
99    }
100
101    /**
102     * Get the current language code.
103     *
104     * @return string
105     * @since 1.45
106     */
107    public function getLanguageCode(): string {
108        return $this->langCode;
109    }
110
111    /**
112     * Get the handler spec map.
113     *
114     * Returns an array of handler specs indexed by class name.
115     *
116     * @since 1.45
117     * @return array<class-string, array<string,mixed>>
118     */
119    protected function getSpecMap(): array {
120        return self::PROVIDER_SPECS;
121    }
122
123    /**
124     * Builds the constructor arguments.
125     *
126     * @param array<string,mixed> $spec
127     *
128     * @since 1.45
129     * @return array<int,mixed>
130     */
131    protected function getSpecArgs( array $spec, LoggerInterface $logger ): array {
132        $args = [];
133        if ( $spec['langDependent'] ?? false ) {
134            $args[] = $this->langCode;
135        }
136        if ( $spec['needsEvaluator'] ?? false ) {
137            $args[] = new Evaluator();
138        }
139        if ( $spec['needsSelf'] ?? false ) {
140            $args[] = $this;
141        }
142        if ( $spec['needsLogger'] ?? false ) {
143            $args[] = $logger;
144        }
145        if ( $spec['needsJsonLoader'] ?? false ) {
146            $args[] = new JsonLoader( $logger );
147        }
148        if ( $spec['needsXmlLoader'] ?? false ) {
149            $args[] = new XmlLoader( $logger );
150        }
151
152        return $args;
153    }
154
155    /**
156     * Get the TextDirection provider.
157     *
158     * @since 1.45
159     */
160    public function getBidiProvider(): TextDirection {
161        return $this->createFromSpec( TextDirection::class );
162    }
163
164    /**
165     * Get the Index provider.
166     *
167     * @since 1.45
168     */
169    public function getFormalityIndexProvider(): FormalityIndex {
170        return $this->createFromSpec( FormalityIndex::class );
171    }
172
173    /**
174     * Get the GrammarTransformations provider.
175     *
176     * @since 1.45
177     * @return GrammarTransformations
178     */
179    public function getGrammarTransformationsProvider(): GrammarTransformations {
180        return $this->createFromSpec( GrammarTransformations::class );
181    }
182
183    /**
184     * Get the LanguageFallbacks provider.
185     *
186     * @since 1.45
187     * @return LanguageFallbacks
188     */
189    public function getLanguageFallbacksProvider(): LanguageFallbacks {
190        return $this->createFromSpec( LanguageFallbacks::class );
191    }
192
193    /**
194     * Get the PluralRules provider.
195     *
196     * @since 1.45
197     * @return PluralRules
198     */
199    public function getPluralProvider(): PluralRules {
200        return $this->createFromSpec( PluralRules::class );
201    }
202}