Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 150
0.00% covered (danger)
0.00%
0 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
DBStore
0.00% covered (danger)
0.00%
0 / 150
0.00% covered (danger)
0.00%
0 / 11
870
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
2
 getQuestionInfo
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 1
30
 callbackValidVotes
0.00% covered (danger)
0.00%
0 / 18
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 ILoadBalancer */
14    private $loadBalancer;
15
16    /** @var string|bool */
17    private $wiki;
18
19    /**
20     * DBStore constructor.
21     * @param ILoadBalancer $loadBalancer The load balancer used to get connection objects
22     * @param string|bool $wiki The wiki ID or false to use the local wiki
23     */
24    public function __construct(
25        ILoadBalancer $loadBalancer,
26        $wiki = false
27    ) {
28        $this->loadBalancer = $loadBalancer;
29        $this->wiki = $wiki;
30    }
31
32    /** @inheritDoc */
33    public function getMessages( $lang, $ids ) {
34        $db = $this->getDB( DB_REPLICA );
35        $res = $db->newSelectQueryBuilder()
36            ->select( '*' )
37            ->from( 'securepoll_msgs' )
38            ->where( [
39                'msg_entity' => $ids,
40                'msg_lang' => $lang
41            ] )
42            ->caller( __METHOD__ )
43            ->fetchResultSet();
44        $messages = [];
45        foreach ( $res as $row ) {
46            $messages[$row->msg_entity][$row->msg_key] = $row->msg_text;
47        }
48
49        return $messages;
50    }
51
52    /** @inheritDoc */
53    public function getLangList( $ids ) {
54        $db = $this->getDB( DB_REPLICA );
55        $res = $db->newSelectQueryBuilder()
56            ->select( 'msg_lang' )
57            ->distinct()
58            ->from( 'securepoll_msgs' )
59            ->where( [
60                'msg_entity' => $ids
61            ] )
62            ->caller( __METHOD__ )
63            ->fetchResultSet();
64        $langs = [];
65        foreach ( $res as $row ) {
66            $langs[] = $row->msg_lang;
67        }
68
69        return $langs;
70    }
71
72    /** @inheritDoc */
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    /** @inheritDoc */
90    public function getElectionInfo( $ids ) {
91        $ids = (array)$ids;
92        $db = $this->getDB( DB_REPLICA );
93        $res = $db->newSelectQueryBuilder()
94            ->select( '*' )
95            ->from( 'securepoll_elections' )
96            ->where( [ 'el_entity' => $ids ] )
97            ->caller( __METHOD__ )
98            ->fetchResultSet();
99        $infos = [];
100        foreach ( $res as $row ) {
101            $infos[$row->el_entity] = $this->decodeElectionRow( $row );
102        }
103
104        return $infos;
105    }
106
107    /** @inheritDoc */
108    public function getElectionInfoByTitle( $names ) {
109        $names = (array)$names;
110        $db = $this->getDB( DB_REPLICA );
111        $res = $db->newSelectQueryBuilder()
112            ->select( '*' )
113            ->from( 'securepoll_elections' )
114            ->where( [ 'el_title' => $names ] )
115            ->caller( __METHOD__ )
116            ->fetchResultSet();
117        $infos = [];
118        foreach ( $res as $row ) {
119            $infos[$row->el_title] = $this->decodeElectionRow( $row );
120        }
121
122        return $infos;
123    }
124
125    /** @inheritDoc */
126    public function decodeElectionRow( $row ) {
127        static $map = [
128            'id' => 'el_entity',
129            'title' => 'el_title',
130            'ballot' => 'el_ballot',
131            'tally' => 'el_tally',
132            'primaryLang' => 'el_primary_lang',
133            'startDate' => 'el_start_date',
134            'endDate' => 'el_end_date',
135            'auth' => 'el_auth_type',
136            'owner' => 'el_owner'
137        ];
138
139        $info = [];
140        foreach ( $map as $key => $field ) {
141            if ( $key == 'startDate' || $key == 'endDate' ) {
142                $info[$key] = wfTimestamp( TS_MW, $row->$field );
143            } elseif ( isset( $row->$field ) ) {
144                $info[$key] = $row->$field;
145            }
146        }
147
148        return $info;
149    }
150
151    /** @inheritDoc */
152    public function getDB( $index = DB_PRIMARY ) {
153        return $this->loadBalancer->getConnection(
154            $index,
155            [],
156            $this->wiki
157        );
158    }
159
160    /** @inheritDoc */
161    public function getQuestionInfo( $electionId ) {
162        $db = $this->getDB( DB_REPLICA );
163        $res = $db->newSelectQueryBuilder()
164            ->select( '*' )
165            ->from( 'securepoll_questions' )
166            ->join( 'securepoll_options', null, 'op_question=qu_entity' )
167            ->where( [
168                'qu_election' => $electionId,
169            ] )
170            ->orderBy( [ 'qu_index', 'qu_entity' ] )
171            ->caller( __METHOD__ )
172            ->fetchResultSet();
173
174        $questions = [];
175        $options = [];
176        $questionId = false;
177        $electionId = false;
178        foreach ( $res as $row ) {
179            if ( $questionId !== false && $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    /** @inheritDoc */
206    public function callbackValidVotes( $electionId, $callback, $voterId = null ) {
207        $dbr = $this->getDB( DB_REPLICA );
208        $queryBuilder = $dbr->newSelectQueryBuilder()
209            ->select( '*' )
210            ->from( 'securepoll_votes' )
211            ->where( [
212                'vote_election' => $electionId,
213                'vote_current' => 1,
214                'vote_struck' => 0
215            ] )
216            ->caller( __METHOD__ );
217        if ( $voterId !== null ) {
218            $queryBuilder->andWhere( [ 'vote_voter' => $voterId ] );
219        }
220        $res = $queryBuilder->fetchResultSet();
221
222        foreach ( $res as $row ) {
223            $status = $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    /** @inheritDoc */
233    public function getEntityType( $id ) {
234        $db = $this->getDB( DB_REPLICA );
235        $res = $db->newSelectQueryBuilder()
236            ->select( '*' )
237            ->from( 'securepoll_entity' )
238            ->where( [ 'en_id' => $id ] )
239            ->caller( __METHOD__ )
240            ->fetchRow();
241
242        return $res ? $res->en_type : false;
243    }
244}