Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
47 / 47
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
OATHAuthModuleRegistry
100.00% covered (success)
100.00%
47 / 47
100.00% covered (success)
100.00%
8 / 8
16
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 moduleExists
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getModuleByKey
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 getAllModules
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getModuleId
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getModuleIds
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
4
 getModuleIdsFromDatabase
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
3
 getModules
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2declare( strict_types=1 );
3/**
4 * @license GPL-2.0-or-later
5 *
6 * @file
7 */
8
9namespace MediaWiki\Extension\OATHAuth;
10
11use InvalidArgumentException;
12use MediaWiki\Extension\OATHAuth\Module\IModule;
13use Wikimedia\ObjectFactory\ObjectFactory;
14use Wikimedia\Rdbms\IConnectionProvider;
15
16class OATHAuthModuleRegistry {
17
18    private ?array $moduleIds = null;
19
20    public function __construct(
21        private readonly IConnectionProvider $dbProvider,
22        private readonly ObjectFactory $objectFactory,
23        private readonly array $modules,
24    ) {
25    }
26
27    public function moduleExists( string $moduleKey ): bool {
28        return isset( $this->getModules()[$moduleKey] );
29    }
30
31    public function getModuleByKey( string $key ): IModule {
32        if ( !isset( $this->getModules()[$key] ) ) {
33            throw new InvalidArgumentException( "No such two-factor module $key" );
34        }
35
36        $data = $this->getModules()[$key];
37        return $this->objectFactory->createObject(
38            $data,
39            [ 'assertClass' => IModule::class ]
40        );
41    }
42
43    /**
44     * Get all modules registered on the wiki
45     *
46     * @return IModule[]
47     */
48    public function getAllModules(): array {
49        $modules = [];
50        foreach ( $this->getModules() as $key => $callback ) {
51            $modules[$key] = $this->getModuleByKey( $key );
52        }
53        return $modules;
54    }
55
56    /**
57     * Returns the numerical ID for the module with the specified key.
58     */
59    public function getModuleId( string $key ): int {
60        $ids = $this->getModuleIds();
61        if ( isset( $ids[$key] ) ) {
62            return $ids[$key];
63        }
64
65        throw new InvalidArgumentException( "Module $key does not seem to exist" );
66    }
67
68    /**
69     * @return array<string,int>
70     */
71    public function getModuleIds(): array {
72        if ( $this->moduleIds === null ) {
73            $this->moduleIds = $this->getModuleIdsFromDatabase( false );
74        }
75
76        $missing = array_diff(
77            array_keys( $this->getModules() ),
78            array_keys( $this->moduleIds )
79        );
80
81        if ( $missing ) {
82            $insert = $this->dbProvider
83                ->getPrimaryDatabase( 'virtual-oathauth' )
84                ->newInsertQueryBuilder()
85                ->insertInto( 'oathauth_types' )
86                ->caller( __METHOD__ );
87
88            foreach ( $missing as $name ) {
89                $insert->row( [ 'oat_name' => $name ] );
90            }
91
92            $insert->execute();
93            $this->moduleIds = $this->getModuleIdsFromDatabase( true );
94        }
95
96        return $this->moduleIds;
97    }
98
99    /**
100     * @return array<string,int>
101     */
102    private function getModuleIdsFromDatabase( bool $fromPrimary ): array {
103        $ids = [];
104
105        if ( $fromPrimary ) {
106            $dbr = $this->dbProvider->getPrimaryDatabase( 'virtual-oathauth' );
107        } else {
108            $dbr = $this->dbProvider->getReplicaDatabase( 'virtual-oathauth' );
109        }
110
111        $rows = $dbr->newSelectQueryBuilder()
112            ->select( [ 'oat_id', 'oat_name' ] )
113            ->from( 'oathauth_types' )
114            ->caller( __METHOD__ )
115            ->fetchResultSet();
116
117        foreach ( $rows as $row ) {
118            $ids[$row->oat_name] = (int)$row->oat_id;
119        }
120
121        return $ids;
122    }
123
124    private function getModules(): array {
125        return $this->modules;
126    }
127}