Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 153
0.00% covered (danger)
0.00%
0 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
DBStore
0.00% covered (danger)
0.00%
0 / 153
0.00% covered (danger)
0.00%
0 / 12
992
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getMessages
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
6
 getLangList
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
6
 getProperties
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
 getElectionInfo
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
6
 getElectionInfoByTitle
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
6
 decodeElectionRow
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 1
30
 getDB
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 setForcePrimary
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getQuestionInfo
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 1
30
 callbackValidVotes
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
30
 getEntityType
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace MediaWiki\Extension\SecurePoll\Store;
4
5use MediaWiki\Status\Status;
6use Wikimedia\Rdbms\ILoadBalancer;
7
8/**
9 * Storage class for a DB backend. This is the one that's most often used.
10 */
11class DBStore implements Store {
12
13    /** @var bool */
14    private $forcePrimary = false;
15
16    /** @var ILoadBalancer */
17    private $loadBalancer;
18
19    /** @var string|bool */
20    private $wiki;
21
22    /**
23     * DBStore constructor.
24     * @param ILoadBalancer $loadBalancer The load balancer used to get connection objects
25     * @param string|bool $wiki The wiki ID or false to use the local wiki
26     */
27    public function __construct(
28        ILoadBalancer $loadBalancer,
29        $wiki = false
30    ) {
31        $this->loadBalancer = $loadBalancer;
32        $this->wiki = $wiki;
33    }
34
35    public function getMessages( $lang, $ids ) {
36        $db = $this->getDB( DB_REPLICA );
37        $res = $db->newSelectQueryBuilder()
38            ->select( '*' )
39            ->from( 'securepoll_msgs' )
40            ->where( [
41                'msg_entity' => $ids,
42                'msg_lang' => $lang
43            ] )
44            ->caller( __METHOD__ )
45            ->fetchResultSet();
46        $messages = [];
47        foreach ( $res as $row ) {
48            $messages[$row->msg_entity][$row->msg_key] = $row->msg_text;
49        }
50
51        return $messages;
52    }
53
54    public function getLangList( $ids ) {
55        $db = $this->getDB( DB_REPLICA );
56        $res = $db->newSelectQueryBuilder()
57            ->select( 'msg_lang' )
58            ->distinct()
59            ->from( 'securepoll_msgs' )
60            ->where( [
61                'msg_entity' => $ids
62            ] )
63            ->caller( __METHOD__ )
64            ->fetchResultSet();
65        $langs = [];
66        foreach ( $res as $row ) {
67            $langs[] = $row->msg_lang;
68        }
69
70        return $langs;
71    }
72
73    public function getProperties( $ids ) {
74        $db = $this->getDB( DB_REPLICA );
75        $res = $db->newSelectQueryBuilder()
76            ->select( '*' )
77            ->from( 'securepoll_properties' )
78            ->where( [ 'pr_entity' => $ids ] )
79            ->caller( __METHOD__ )
80            ->fetchResultSet();
81        $properties = [];
82        foreach ( $res as $row ) {
83            $properties[$row->pr_entity][$row->pr_key] = $row->pr_value;
84        }
85
86        return $properties;
87    }
88
89    public function getElectionInfo( $ids ) {
90        $ids = (array)$ids;
91        $db = $this->getDB( DB_REPLICA );
92        $res = $db->newSelectQueryBuilder()
93            ->select( '*' )
94            ->from( 'securepoll_elections' )
95            ->where( [ 'el_entity' => $ids ] )
96            ->caller( __METHOD__ )
97            ->fetchResultSet();
98        $infos = [];
99        foreach ( $res as $row ) {
100            $infos[$row->el_entity] = $this->decodeElectionRow( $row );
101        }
102
103        return $infos;
104    }
105
106    public function getElectionInfoByTitle( $names ) {
107        $names = (array)$names;
108        $db = $this->getDB( DB_REPLICA );
109        $res = $db->newSelectQueryBuilder()
110            ->select( '*' )
111            ->from( 'securepoll_elections' )
112            ->where( [ 'el_title' => $names ] )
113            ->caller( __METHOD__ )
114            ->fetchResultSet();
115        $infos = [];
116        foreach ( $res as $row ) {
117            $infos[$row->el_title] = $this->decodeElectionRow( $row );
118        }
119
120        return $infos;
121    }
122
123    public function decodeElectionRow( $row ) {
124        static $map = [
125            'id' => 'el_entity',
126            'title' => 'el_title',
127            'ballot' => 'el_ballot',
128            'tally' => 'el_tally',
129            'primaryLang' => 'el_primary_lang',
130            'startDate' => 'el_start_date',
131            'endDate' => 'el_end_date',
132            'auth' => 'el_auth_type',
133            'owner' => 'el_owner'
134        ];
135
136        $info = [];
137        foreach ( $map as $key => $field ) {
138            if ( $key == 'startDate' || $key == 'endDate' ) {
139                $info[$key] = wfTimestamp( TS_MW, $row->$field );
140            } elseif ( isset( $row->$field ) ) {
141                $info[$key] = $row->$field;
142            }
143        }
144
145        return $info;
146    }
147
148    public function getDB( $index = DB_PRIMARY ) {
149        return $this->loadBalancer->getConnection(
150            $this->forcePrimary ? DB_PRIMARY : $index,
151            [],
152            $this->wiki
153        );
154    }
155
156    public function setForcePrimary( $forcePrimary ) {
157        $this->forcePrimary = $forcePrimary;
158    }
159
160    public function getQuestionInfo( $electionId ) {
161        $db = $this->getDB( DB_REPLICA );
162        $res = $db->newSelectQueryBuilder()
163            ->select( '*' )
164            ->from( 'securepoll_questions' )
165            ->join( 'securepoll_options', null, 'op_question=qu_entity' )
166            ->where( [
167                'qu_election' => $electionId,
168            ] )
169            ->orderBy( [ 'qu_index', 'qu_entity' ] )
170            ->caller( __METHOD__ )
171            ->fetchResultSet();
172
173        $questions = [];
174        $options = [];
175        $questionId = false;
176        $electionId = false;
177        foreach ( $res as $row ) {
178            if ( $questionId === false ) {
179            } elseif ( $questionId !== $row->qu_entity ) {
180                $questions[] = [
181                    'id' => $questionId,
182                    'election' => $electionId,
183                    'options' => $options
184                ];
185                $options = [];
186            }
187            $options[] = [
188                'id' => $row->op_entity,
189                'election' => $row->op_election,
190            ];
191            $questionId = $row->qu_entity;
192            $electionId = $row->qu_election;
193        }
194        if ( $questionId !== false ) {
195            $questions[] = [
196                'id' => $questionId,
197                'election' => $electionId,
198                'options' => $options
199            ];
200        }
201
202        return $questions;
203    }
204
205    public function callbackValidVotes( $electionId, $callback, $voterId = null ) {
206        $dbr = $this->getDB( DB_REPLICA );
207        $where = [
208            'vote_election' => $electionId,
209            'vote_current' => 1,
210            'vote_struck' => 0
211        ];
212        if ( $voterId !== null ) {
213            $where['vote_voter'] = $voterId;
214        }
215        $res = $dbr->newSelectQueryBuilder()
216            ->select( '*' )
217            ->from( 'securepoll_votes' )
218            ->where( $where )
219            ->caller( __METHOD__ )
220            ->fetchResultSet();
221
222        foreach ( $res as $row ) {
223            $status = call_user_func( $callback, $this, $row->vote_record );
224            if ( $status instanceof Status && !$status->isOK() ) {
225                return $status;
226            }
227        }
228
229        return Status::newGood();
230    }
231
232    public function getEntityType( $id ) {
233        $db = $this->getDB( DB_REPLICA );
234        $res = $db->newSelectQueryBuilder()
235            ->select( '*' )
236            ->from( 'securepoll_entity' )
237            ->where( [ 'en_id' => $id ] )
238            ->caller( __METHOD__ )
239            ->fetchRow();
240
241        return $res ? $res->en_type : false;
242    }
243}