Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
CollationFactory
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 5
90
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 getCategoryCollation
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDefaultCollationName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 makeCollation
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
30
 instantiateCollation
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 * http://www.gnu.org/copyleft/gpl.html
18 *
19 * @file
20 */
21
22namespace MediaWiki\Collation;
23
24use Collation;
25use InvalidArgumentException;
26use MediaWiki\Config\ServiceOptions;
27use MediaWiki\HookContainer\HookContainer;
28use MediaWiki\HookContainer\HookRunner;
29use MediaWiki\MainConfigNames;
30use Wikimedia\ObjectFactory\ObjectFactory;
31
32/**
33 * Common factory to construct collation classes.
34 *
35 * @since 1.37
36 */
37class CollationFactory {
38    /**
39     * @internal For use by ServiceWiring
40     */
41    public const CONSTRUCTOR_OPTIONS = [
42        MainConfigNames::CategoryCollation,
43    ];
44
45    private const CORE_COLLATIONS = [
46        'uppercase' => [
47            'class' => \UppercaseCollation::class,
48            'services' => [
49                'LanguageFactory',
50            ]
51        ],
52        'numeric' => [
53            'class' => \NumericUppercaseCollation::class,
54            'services' => [
55                'LanguageFactory',
56                'ContentLanguage',
57            ]
58        ],
59        'identity' => [
60            'class' => \IdentityCollation::class,
61            'services' => [
62                'ContentLanguage',
63            ]
64        ],
65        'uca-default' => [
66            'class' => \IcuCollation::class,
67            'services' => [
68                'LanguageFactory',
69            ],
70            'args' => [
71                'root',
72            ]
73        ],
74        'uca-default-u-kn' => [
75            'class' => \IcuCollation::class,
76            'services' => [
77                'LanguageFactory',
78            ],
79            'args' => [
80                'root-u-kn',
81            ]
82        ],
83        'xx-uca-ckb' => [
84            'class' => \CollationCkb::class,
85            'services' => [
86                'LanguageFactory',
87            ]
88        ],
89        'uppercase-ab' => [
90            'class' => \AbkhazUppercaseCollation::class,
91            'services' => [
92                'LanguageFactory',
93            ]
94        ],
95        'uppercase-ba' => [
96            'class' => \BashkirUppercaseCollation::class,
97            'services' => [
98                'LanguageFactory',
99            ]
100        ],
101        'uppercase-smn' => [
102            'class' => \InariSaamiUppercaseCollation::class,
103            'services' => [
104                'LanguageFactory',
105            ]
106        ],
107        'uppercase-ckb' => [
108            'class' => \CentralKurdishUppercaseCollation::class,
109            'services' => [
110                'LanguageFactory',
111            ]
112        ],
113    ];
114
115    /** @var ServiceOptions */
116    private $options;
117
118    /** @var ObjectFactory */
119    private $objectFactory;
120
121    /** @var HookRunner */
122    private $hookRunner;
123
124    /**
125     * @param ServiceOptions $options
126     * @param ObjectFactory $objectFactory
127     * @param HookContainer $hookContainer
128     */
129    public function __construct(
130        ServiceOptions $options,
131        ObjectFactory $objectFactory,
132        HookContainer $hookContainer
133    ) {
134        $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
135        $this->options = $options;
136        $this->objectFactory = $objectFactory;
137        $this->hookRunner = new HookRunner( $hookContainer );
138    }
139
140    public function getCategoryCollation(): Collation {
141        return $this->makeCollation( $this->getDefaultCollationName() );
142    }
143
144    public function getDefaultCollationName(): string {
145        return $this->options->get( MainConfigNames::CategoryCollation );
146    }
147
148    public function makeCollation( string $collationName ): Collation {
149        if ( isset( self::CORE_COLLATIONS[$collationName] ) ) {
150            return $this->instantiateCollation( self::CORE_COLLATIONS[$collationName] );
151        }
152
153        if ( preg_match( '/^uca-([A-Za-z@=-]+)$/', $collationName, $match ) ) {
154            return $this->instantiateCollation( [
155                'class' => \IcuCollation::class,
156                'services' => [
157                    'LanguageFactory',
158                ],
159                'args' => [
160                    $match[1],
161                ]
162            ] );
163        } elseif ( preg_match( '/^remote-uca-([A-Za-z@=-]+)$/', $collationName, $match ) ) {
164            return $this->instantiateCollation( [
165                'class' => \RemoteIcuCollation::class,
166                'services' => [
167                    'ShellboxClientFactory'
168                ],
169                'args' => [
170                    $match[1]
171                ]
172            ] );
173        }
174
175        // Provide a mechanism for extensions to hook in.
176        $collationObject = null;
177        $this->hookRunner->onCollation__factory( $collationName, $collationObject );
178
179        if ( !$collationObject instanceof Collation ) {
180            throw new InvalidArgumentException( __METHOD__ . ": unknown collation type \"$collationName\"" );
181        }
182
183        return $collationObject;
184    }
185
186    /**
187     * @param array $spec
188     * @return Collation
189     */
190    private function instantiateCollation( $spec ): Collation {
191        return $this->objectFactory->createObject(
192            $spec,
193            [
194                'assertClass' => Collation::class
195            ]
196        );
197    }
198
199}