Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
90.48% covered (success)
90.48%
19 / 21
87.50% covered (warning)
87.50%
7 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
Manager
90.48% covered (success)
90.48%
19 / 21
87.50% covered (warning)
87.50%
7 / 8
13.15
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
 getSpecMap
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSpecArgs
83.33% covered (warning)
83.33%
10 / 12
0.00% covered (danger)
0.00%
0 / 1
6.17
 getBidi
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFormal
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getGender
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getGrammar
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPlural
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 Psr\Log\LoggerInterface;
10use Psr\Log\NullLogger;
11use Wikimedia\Leximorph\Handler\Bidi;
12use Wikimedia\Leximorph\Handler\Formal;
13use Wikimedia\Leximorph\Handler\Gender;
14use Wikimedia\Leximorph\Handler\Grammar;
15use Wikimedia\Leximorph\Handler\Overrides\GrammarFallbackRegistry;
16use Wikimedia\Leximorph\Handler\Plural;
17use Wikimedia\Leximorph\Traits\SpecBasedFactoryTrait;
18use Wikimedia\Leximorph\Util\JsonLoader;
19
20/**
21 * Manager
22 *
23 * This class is responsible for instantiating Leximorph handler objects
24 * (Grammar, Formal, Gender, Bidi, and Plural) using Wikimedia’s ObjectFactory.
25 * The Manager holds a default language code that is injected into
26 * language-specific handlers.
27 *
28 * Note that Gender and Bidi handlers are language independent.
29 *
30 * Usage Example:
31 * @code
32 *            $manager = new Manager( 'en', new NullLogger() );
33 *            $pluralHandler = $manager->getPlural();
34 *            echo $pluralHandler->process( 3, [ 'article', 'articles' ] );
35 * @endcode
36 *
37 * @newable
38 * @since     1.45
39 * @author    Doğu Abaris (abaris@null.net)
40 */
41final class Manager {
42
43    use SpecBasedFactoryTrait;
44
45    /**
46     * Handler specifications.
47     *
48     * Each entry defines:
49     * - args: Default constructor arguments.
50     * - langDependent: Prepend the language code.
51     * - needsLogger: Pass a logger.
52     * - needsProvider: Use a provider instance.
53     * - needsPostProcessor: Pass a GrammarFallbackRegistry instance.
54     *
55     * @var array<class-string, array<string, mixed>>
56     */
57    private const array HANDLER_SPECS = [
58        Bidi::class => [
59            'args' => [],
60            'needsProvider' => true,
61        ],
62        Formal::class => [
63            'args' => [],
64            'needsProvider' => true,
65        ],
66        Gender::class => [
67            'args' => [],
68        ],
69        Grammar::class => [
70            'args' => [],
71            'needsLogger' => true,
72            'needsProvider' => true,
73            'needsPostProcessor' => true,
74        ],
75        Plural::class => [
76            'args' => [],
77            'langDependent' => false,
78            'needsProvider' => true,
79        ],
80    ];
81
82    private Provider $provider;
83
84    /**
85     * Initializes a new Manager instance with a default language code.
86     *
87     * @param string $langCode The default language code.
88     * @param ?LoggerInterface $logger Optional logger; defaults to NullLogger.
89     *
90     * @since 1.45
91     */
92    public function __construct( string $langCode, ?LoggerInterface $logger = null ) {
93        $this->langCode = $langCode;
94        $this->logger = $logger ?? new NullLogger();
95        $this->provider = new Provider( $this->langCode, $this->logger );
96    }
97
98    /**
99     * Get the handler spec map.
100     *
101     * Returns an array of handler specs indexed by class name.
102     *
103     * @since 1.45
104     * @return array<class-string, array<string, mixed>>
105     */
106    protected function getSpecMap(): array {
107        return self::HANDLER_SPECS;
108    }
109
110    /**
111     * Builds the constructor arguments.
112     *
113     * @param array<string,mixed> $spec
114     *
115     * @since 1.45
116     * @return array<int,mixed>
117     */
118    protected function getSpecArgs( array $spec, LoggerInterface $logger ): array {
119        $args = [];
120        if ( $spec['needsProvider'] ?? false ) {
121            $args[] = $this->provider;
122        }
123        if ( $spec['needsPostProcessor'] ?? false ) {
124            $args[] = new GrammarFallbackRegistry();
125        }
126        if ( $spec['needsLogger'] ?? false ) {
127            $args[] = $logger;
128        }
129        if ( $spec['langDependent'] ?? false ) {
130            $args[] = $this->langCode;
131        }
132        if ( $spec['needsJsonLoader'] ?? false ) {
133            $args[] = new JsonLoader( $logger );
134        }
135
136        return $args;
137    }
138
139    /**
140     * Get the Bidi handler.
141     *
142     * @since 1.45
143     */
144    public function getBidi(): Bidi {
145        return $this->createFromSpec( Bidi::class );
146    }
147
148    /**
149     * Get the Formal handler.
150     *
151     * @since 1.45
152     */
153    public function getFormal(): Formal {
154        return $this->createFromSpec( Formal::class );
155    }
156
157    /**
158     * Get the Gender handler.
159     *
160     * @since 1.45
161     */
162    public function getGender(): Gender {
163        return $this->createFromSpec( Gender::class );
164    }
165
166    /**
167     * Get the Grammar handler.
168     *
169     * @since 1.45
170     */
171    public function getGrammar(): Grammar {
172        return $this->createFromSpec( Grammar::class );
173    }
174
175    /**
176     * Get the Plural handler.
177     *
178     * @since 1.45
179     */
180    public function getPlural(): Plural {
181        return $this->createFromSpec( Plural::class );
182    }
183}