Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 55
0.00% covered (danger)
0.00%
0 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
MemoryStore
0.00% covered (danger)
0.00%
0 / 55
0.00% covered (danger)
0.00%
0 / 12
552
0.00% covered (danger)
0.00%
0 / 1
 getAllElectionIds
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 getMessages
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getLangList
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 getProperties
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getElectionInfo
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getElectionInfoByTitle
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getQuestionInfo
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 decodeElectionRow
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 getDB
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 setForcePrimary
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 callbackValidVotes
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
30
 getEntityType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace MediaWiki\Extension\SecurePoll\Store;
4
5use LogicException;
6use MediaWiki\Logger\LoggerFactory;
7use MediaWiki\Status\Status;
8
9/**
10 * Storage class that stores all data in local memory. The memory must be
11 * initialized somehow, methods for this are not provided except in the
12 * subclass.
13 */
14class MemoryStore implements Store {
15    /** @var array|null */
16    public $messages;
17    /** @var array|null */
18    public $properties;
19    /** @var array|null */
20    public $idsByName;
21    /** @var array|null */
22    public $votes;
23    /** @var array */
24    public $entityInfo = [];
25
26    /**
27     * Get an array containing all election IDs stored in this object
28     * @return array
29     */
30    public function getAllElectionIds() {
31        $electionIds = [];
32        foreach ( $this->entityInfo as $info ) {
33            if ( $info['type'] !== 'election' ) {
34                continue;
35            }
36            $electionIds[] = $info['id'];
37        }
38
39        return $electionIds;
40    }
41
42    public function getMessages( $lang, $ids ) {
43        if ( !isset( $this->messages[$lang] ) ) {
44            return [];
45        }
46
47        return array_intersect_key( $this->messages[$lang], array_flip( $ids ) );
48    }
49
50    public function getLangList( $ids ) {
51        $langs = [];
52        foreach ( $this->messages as $lang => $langMessages ) {
53            foreach ( $ids as $id ) {
54                if ( isset( $langMessages[$id] ) ) {
55                    $langs[] = $lang;
56                    break;
57                }
58            }
59        }
60
61        return $langs;
62    }
63
64    public function getProperties( $ids ) {
65        $ids = (array)$ids;
66
67        return array_intersect_key( $this->properties, array_flip( $ids ) );
68    }
69
70    public function getElectionInfo( $ids ) {
71        $ids = (array)$ids;
72
73        return array_intersect_key( $this->entityInfo, array_flip( $ids ) );
74    }
75
76    public function getElectionInfoByTitle( $names ) {
77        $names = (array)$names;
78        $ids = array_intersect_key( $this->idsByName, array_flip( $names ) );
79
80        return array_intersect_key( $this->entityInfo, array_flip( $ids ) );
81    }
82
83    public function getQuestionInfo( $electionId ) {
84        return $this->entityInfo[$electionId]['questions'];
85    }
86
87    public function decodeElectionRow( $row ) {
88        // @phan-suppress-previous-line PhanPluginNeverReturnMethod LSP violation
89        throw new LogicException(
90            'Internal error: attempt to use decodeElectionRow() with ' .
91            'a storage class that doesn\'t support it.'
92        );
93    }
94
95    public function getDB( $index = DB_PRIMARY ) {
96        // @phan-suppress-previous-line PhanPluginNeverReturnMethod LSP violation
97        throw new LogicException(
98            'Internal error: attempt to use getDB() when the database is disabled.'
99        );
100    }
101
102    public function setForcePrimary( $forcePrimary ) {
103    }
104
105    public function callbackValidVotes( $electionId, $callback, $voterId = null ) {
106        if ( !isset( $this->votes[$electionId] ) ) {
107            return Status::newGood();
108        }
109
110        // T288366 Tallies fail on beta/prod with little visibility
111        // Add logging to gain more context into where it fails
112        LoggerFactory::getInstance( 'AdHocDebug' )->info(
113            'Adding votes to election',
114            [
115                'electionId' => $electionId,
116                'voteCount' => count( $this->votes[$electionId] ),
117            ]
118        );
119
120        foreach ( $this->votes[$electionId] as $i => $vote ) {
121            $status = call_user_func( $callback, $this, $vote );
122            if ( !$status->isOK() ) {
123                return $status;
124            }
125
126            if ( $i % 5 === 0 ) {
127                // T288366 Tallies fail on beta/prod with little visibility
128                // Add logging to gain more context into where it fails
129                LoggerFactory::getInstance( 'AdHocDebug' )->info(
130                    'Batch addRecord() currently in progress',
131                    [
132                        'electionId' => $electionId,
133                        'currentVoteIndex' => $i,
134                    ]
135                );
136            }
137        }
138
139        return Status::newGood();
140    }
141
142    public function getEntityType( $id ) {
143        return isset( $this->entityInfo[$id] ) ? $this->entityInfo[$id]['type'] : false;
144    }
145}