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    /** @inheritDoc */
43    public function getMessages( $lang, $ids ) {
44        if ( !isset( $this->messages[$lang] ) ) {
45            return [];
46        }
47
48        return array_intersect_key( $this->messages[$lang], array_flip( $ids ) );
49    }
50
51    /** @inheritDoc */
52    public function getLangList( $ids ) {
53        $langs = [];
54        foreach ( $this->messages as $lang => $langMessages ) {
55            foreach ( $ids as $id ) {
56                if ( isset( $langMessages[$id] ) ) {
57                    $langs[] = $lang;
58                    break;
59                }
60            }
61        }
62
63        return $langs;
64    }
65
66    /** @inheritDoc */
67    public function getProperties( $ids ) {
68        $ids = (array)$ids;
69
70        return array_intersect_key( $this->properties, array_flip( $ids ) );
71    }
72
73    /** @inheritDoc */
74    public function getElectionInfo( $ids ) {
75        $ids = (array)$ids;
76
77        return array_intersect_key( $this->entityInfo, array_flip( $ids ) );
78    }
79
80    /** @inheritDoc */
81    public function getElectionInfoByTitle( $names ) {
82        $names = (array)$names;
83        $ids = array_intersect_key( $this->idsByName, array_flip( $names ) );
84
85        return array_intersect_key( $this->entityInfo, array_flip( $ids ) );
86    }
87
88    /** @inheritDoc */
89    public function getQuestionInfo( $electionId ) {
90        return $this->entityInfo[$electionId]['questions'];
91    }
92
93    /** @inheritDoc */
94    public function decodeElectionRow( $row ) {
95        // @phan-suppress-previous-line PhanPluginNeverReturnMethod LSP violation
96        throw new LogicException(
97            'Internal error: attempt to use decodeElectionRow() with ' .
98            'a storage class that doesn\'t support it.'
99        );
100    }
101
102    /** @inheritDoc */
103    public function getDB( $index = DB_PRIMARY ) {
104        // @phan-suppress-previous-line PhanPluginNeverReturnMethod LSP violation
105        throw new LogicException(
106            'Internal error: attempt to use getDB() when the database is disabled.'
107        );
108    }
109
110    /** @inheritDoc */
111    public function setForcePrimary( $forcePrimary ) {
112    }
113
114    /** @inheritDoc */
115    public function callbackValidVotes( $electionId, $callback, $voterId = null ) {
116        if ( !isset( $this->votes[$electionId] ) ) {
117            return Status::newGood();
118        }
119
120        // T288366 Tallies fail on beta/prod with little visibility
121        // Add logging to gain more context into where it fails
122        LoggerFactory::getInstance( 'AdHocDebug' )->info(
123            'Adding votes to election',
124            [
125                'electionId' => $electionId,
126                'voteCount' => count( $this->votes[$electionId] ),
127            ]
128        );
129
130        foreach ( $this->votes[$electionId] as $i => $vote ) {
131            $status = call_user_func( $callback, $this, $vote );
132            if ( !$status->isOK() ) {
133                return $status;
134            }
135
136            if ( $i % 5 === 0 ) {
137                // T288366 Tallies fail on beta/prod with little visibility
138                // Add logging to gain more context into where it fails
139                LoggerFactory::getInstance( 'AdHocDebug' )->info(
140                    'Batch addRecord() currently in progress',
141                    [
142                        'electionId' => $electionId,
143                        'currentVoteIndex' => $i,
144                    ]
145                );
146            }
147        }
148
149        return Status::newGood();
150    }
151
152    /** @inheritDoc */
153    public function getEntityType( $id ) {
154        return isset( $this->entityInfo[$id] ) ? $this->entityInfo[$id]['type'] : false;
155    }
156}