Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.00% covered (success)
95.00%
19 / 20
87.50% covered (warning)
87.50%
7 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
Manager
95.00% covered (success)
95.00%
19 / 20
87.50% covered (warning)
87.50%
7 / 8
13
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
 getSpecMap
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSpecArgs
91.67% covered (success)
91.67%
11 / 12
0.00% covered (danger)
0.00%
0 / 1
6.02
 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 Wikimedia\Leximorph\Handler\Bidi;
11use Wikimedia\Leximorph\Handler\Formal;
12use Wikimedia\Leximorph\Handler\Gender;
13use Wikimedia\Leximorph\Handler\Grammar;
14use Wikimedia\Leximorph\Handler\Overrides\GrammarFallbackRegistry;
15use Wikimedia\Leximorph\Handler\Plural;
16use Wikimedia\Leximorph\Traits\SpecBasedFactoryTrait;
17use Wikimedia\Leximorph\Util\JsonLoader;
18
19/**
20 * Manager
21 *
22 * This class is responsible for instantiating Leximorph handler objects
23 * (Grammar, Formal, Gender, Bidi, and Plural) using Wikimedia’s ObjectFactory.
24 * The Manager holds a default language code that is injected into
25 * language-specific handlers.
26 *
27 * Note that Gender and Bidi handlers are language independent.
28 *
29 * Usage Example:
30 * <code>
31 *            $manager = new Manager( 'en', new NullLogger() );
32 *            $pluralHandler = $manager->getPlural();
33 *            echo $pluralHandler->process( 3, [ 'article', 'articles' ] );
34 * </code>
35 *
36 * @newable
37 * @since     1.45
38 * @author    Doğu Abaris (abaris@null.net)
39 * @license   https://www.gnu.org/copyleft/gpl.html GPL-2.0-or-later
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 HANDLER_SPECS = [
58        Bidi::class => [
59            'args' => [],
60            'needsProvider' => true,
61        ],
62        Formal::class => [
63            'args' => [],
64            'langDependent' => true,
65            'needsLogger' => true,
66            'needsProvider' => true,
67        ],
68        Gender::class => [
69            'args' => [],
70        ],
71        Grammar::class => [
72            'args' => [],
73            'needsLogger' => true,
74            'needsProvider' => true,
75            'needsPostProcessor' => true,
76        ],
77        Plural::class => [
78            'args' => [],
79            'langDependent' => false,
80            'needsProvider' => true,
81        ],
82    ];
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;
95    }
96
97    /**
98     * Get the handler spec map.
99     *
100     * Returns an array of handler specs indexed by class name.
101     *
102     * @since 1.45
103     * @return array<class-string, array<string, mixed>>
104     */
105    protected function getSpecMap(): array {
106        return self::HANDLER_SPECS;
107    }
108
109    /**
110     * Builds the constructor arguments.
111     *
112     * @param array<string,mixed> $spec
113     *
114     * @since 1.45
115     * @return array<int,mixed>
116     */
117    protected function getSpecArgs( array $spec, LoggerInterface $logger ): array {
118        $args = [];
119        if ( $spec['needsProvider'] ?? false ) {
120            $args[] = new Provider( $this->langCode, $logger );
121        }
122        if ( $spec['needsPostProcessor'] ?? false ) {
123            $args[] = new GrammarFallbackRegistry();
124        }
125        if ( $spec['needsLogger'] ?? false ) {
126            $args[] = $logger;
127        }
128        if ( $spec['langDependent'] ?? false ) {
129            $args[] = $this->langCode;
130        }
131        if ( $spec['needsJsonLoader'] ?? false ) {
132            $args[] = new JsonLoader( $logger );
133        }
134
135        return $args;
136    }
137
138    /**
139     * Get the Bidi handler.
140     *
141     * @since 1.45
142     * @return Bidi
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     * @return Formal
153     */
154    public function getFormal(): Formal {
155        return $this->createFromSpec( Formal::class );
156    }
157
158    /**
159     * Get the Gender handler.
160     *
161     * @since 1.45
162     * @return Gender
163     */
164    public function getGender(): Gender {
165        return $this->createFromSpec( Gender::class );
166    }
167
168    /**
169     * Get the Grammar handler.
170     *
171     * @since 1.45
172     * @return Grammar
173     */
174    public function getGrammar(): Grammar {
175        return $this->createFromSpec( Grammar::class );
176    }
177
178    /**
179     * Get the Plural handler.
180     *
181     * @since 1.45
182     * @return Plural
183     */
184    public function getPlural(): Plural {
185        return $this->createFromSpec( Plural::class );
186    }
187}