Passed
Push — TEST/ScrutinizerPHPAnalysisEng... ( c9e065...573acf )
by Boudry
09:25
created

VotesProcess::getVoteKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 2
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
crap 1
eloc 1
nc 1
nop 1
1
<?php
2
/*
3
    Condorcet PHP - Election manager and results calculator.
4
    Designed for the Condorcet method. Integrating a large number of algorithms extending Condorcet. Expandable for all types of voting systems.
5
6
    By Julien Boudry and contributors - MIT LICENSE (Please read LICENSE.txt)
7
    https://github.com/julien-boudry/Condorcet
8
*/
9
declare(strict_types=1);
10
11
namespace Condorcet\ElectionProcess;
12
13
use Condorcet\CondorcetException;
14
use Condorcet\CondorcetUtil;
15
use Condorcet\Vote;
16
use Condorcet\DataManager\VotesManager;
17
18
// Manage Results for Election class
19
trait VotesProcess
20
{
21
22
/////////// CONSTRUCTOR ///////////
23
24
    // Data and global options
25
    protected $_Votes; // Votes list
26
    protected $_ignoreStaticMaxVote = false;
27
28
29 1
    public function ignoreMaxVote (bool $state = true) : bool
30
    {
31 1
        return $this->_ignoreStaticMaxVote = $state;
32
    }
33
34
35
/////////// VOTES LIST ///////////
36
37
    // How many votes are registered ?
38 10
    public function countVotes ($tag = null, bool $with = true) : int
39
    {
40 10
        return $this->_Votes->countVotes(VoteUtil::tagsConvert($tag),$with);
41
    }
42
43
    // Get the votes registered list
44 10
    public function getVotesList ($tag = null, bool $with = true) : array
45
    {
46 10
        return $this->_Votes->getVotesList(VoteUtil::tagsConvert($tag), $with);
47
    }
48
49 5
    public function getVotesListAsString () : string
50
    {
51 5
        return $this->_Votes->getVotesListAsString();
52
    }
53
54 86
    public function getVotesManager () : VotesManager {
55 86
        return $this->_Votes;
56
    }
57
58 5
    public function getVoteKey (Vote $vote) {
59 5
        return $this->_Votes->getVoteKey($vote);
60
    }
61
62
63
/////////// ADD & REMOVE VOTE ///////////
64
65
    // Add a single vote. Array key is the rank, each candidate in a rank are separate by ',' It is not necessary to register the last rank.
66 99
    public function addVote ($vote, $tag = null) : Vote
67
    {
68 99
        $this->prepareVoteInput($vote, $tag);
69
70
        // Check Max Vote Count
71 99
        if ( self::$_maxVoteNumber !== null && !$this->_ignoreStaticMaxVote && $this->countVotes() >= self::$_maxVoteNumber ) :
0 ignored issues
show
Bug Best Practice introduced by
The property _maxVoteNumber does not exist on Condorcet\ElectionProcess\VotesProcess. Did you maybe forget to declare it?
Loading history...
72 1
            throw new CondorcetException(16, self::$_maxVoteNumber);
73
        endif;
74
75
76
        // Register vote
77 99
        return $this->registerVote($vote, $tag); // Return the vote object
78
    }
79
80
    // return True or throw an Exception
81 6
    public function prepareModifyVote (Vote $existVote) : void
82
    {
83
        try {
84 6
            $this->prepareVoteInput($existVote);
85 6
            $this->setStateToVote();
0 ignored issues
show
Bug introduced by
It seems like setStateToVote() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

85
            $this->/** @scrutinizer ignore-call */ 
86
                   setStateToVote();
Loading history...
86
87 6
            if ($this->_Votes->isUsingHandler()) : 
88 6
                $this->_Votes[$this->getVoteKey($existVote)] = $existVote;
89
            endif;
90
        }
91
        catch (\Exception $e) {
92
            throw $e;
93
        }
94 6
    }
95
96 99
    public function checkVoteCandidate (Vote $vote) : bool
97
    {
98 99
        $linkCount = $vote->countLinks();
99 99
        $links = $vote->getLinks();
100
101 99
        $mirror = $vote->getRanking();
102 99
        $change = false;
103 99
        foreach ($vote as $rank => $choice) :
104 99
            foreach ($choice as $choiceKey => $candidate) :
105 99
                if ( !$this->existCandidateId($candidate, true) ) :
0 ignored issues
show
Bug introduced by
It seems like existCandidateId() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

105
                if ( !$this->/** @scrutinizer ignore-call */ existCandidateId($candidate, true) ) :
Loading history...
106 92
                    if ($candidate->getProvisionalState() && $this->existCandidateId($candidate, false)) :
107 91
                        if ( $linkCount === 0 || ($linkCount === 1 && reset($links) === $this) ) :
108 91
                            $mirror[$rank][$choiceKey] = $this->_Candidates[$this->getCandidateKey((string) $candidate)];
0 ignored issues
show
Bug introduced by
It seems like getCandidateKey() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

108
                            $mirror[$rank][$choiceKey] = $this->_Candidates[$this->/** @scrutinizer ignore-call */ getCandidateKey((string) $candidate)];
Loading history...
Bug Best Practice introduced by
The property _Candidates does not exist on Condorcet\ElectionProcess\VotesProcess. Did you maybe forget to declare it?
Loading history...
109 91
                            $change = true;
110
                        else :
111 99
                            return false;
112
                        endif;
113
                    endif;
114
                endif;
115
            endforeach;
116
        endforeach;
117
118 99
        if ($change) :
119 91
            $vote->setRanking(  $mirror,
120 91
                                ( abs($vote->getTimestamp() - microtime(true)) > 0.5 ) ? ($vote->getTimestamp() + 0.001) : null
121
            );
122
        endif;
123
124 99
        return true;
125
    }
126
127
    // Write a new vote
128 99
    protected function registerVote (Vote $vote, $tag = null) : Vote
129
    {
130
        // Vote identifiant
131 99
        $vote->addTags($tag);
132
        
133
        // Register
134
        try {
135 99
            $vote->registerLink($this);
136 99
            $this->_Votes[] = $vote;
0 ignored issues
show
Bug introduced by
The property _Votes is declared protected in Condorcet\Election and cannot be accessed from this context.
Loading history...
137
        } catch (CondorcetException $e) {
138
            // Security : Check if vote object not already register
139
            throw new CondorcetException(6,'Vote object already registred');
140
        }
141
142 99
        return $vote;
143
    }
144
145 5
    public function removeVote ($in, bool $with = true) : array
146
    {    
147 5
        $rem = [];
148
149 5
        if ($in instanceof Vote) :
150 4
            $key = $this->getVoteKey($in);
151 4
            if ($key !== false) :
152 4
                $this->_Votes[$key]->destroyLink($this);
153
154 4
                $rem[] = $this->_Votes[$key];
155
156 4
                unset($this->_Votes[$key]);
157
            endif;
158
        else :
159
            // Prepare Tags
160 3
            $tag = VoteUtil::tagsConvert($in);
161
162
            // Deleting
163 3
            foreach ($this->getVotesList($tag, $with) as $key => $value) :
164 3
                $this->_Votes[$key]->destroyLink($this);
165
166 3
                $rem[] = $this->_Votes[$key];
167
168 3
                unset($this->_Votes[$key]);
169
            endforeach;
170
171
        endif;
172
173 5
        return $rem;
174
    }
175
176
177
/////////// PARSE VOTE ///////////
178
179
    // Return the well formated vote to use.
180 99
    protected function prepareVoteInput (&$vote, $tag = null) : void
181
    {
182 99
        if (!($vote instanceof Vote)) :
183 83
            $vote = new Vote ($vote, $tag);
184
        endif;
185
186
        // Check array format && Make checkVoteCandidate
187 99
        if ( !$this->checkVoteCandidate($vote) ) :
188
            throw new CondorcetException(5);
189
        endif;
190 99
    }
191
192 2
    public function jsonVotes (string $input)
193
    {
194 2
        $input = CondorcetUtil::prepareJson($input);
195 1
        if ($input === false) :
196
            return $input;
197
        endif;
198
199
            //////
200
201 1
        $adding = [];
202
203 1
        foreach ($input as $record) :
204 1
            if (empty($record['vote'])) :
205 1
                continue;
206
            endif;
207
208 1
            $tags = (!isset($record['tag'])) ? null : $record['tag'];
209 1
            $multi = (!isset($record['multi'])) ? 1 : $record['multi'];
210
211 1
            for ($i = 0; $i < $multi; $i++) :
212 1
                if (self::$_maxParseIteration !== null && $this->countVotes() >= self::$_maxParseIteration) :
0 ignored issues
show
Bug Best Practice introduced by
The property _maxParseIteration does not exist on Condorcet\ElectionProcess\VotesProcess. Did you maybe forget to declare it?
Loading history...
213
                    throw new CondorcetException(12, self::$_maxParseIteration);
214
                endif;
215
216
                try {
217 1
                    $adding[] = $this->addVote($record['vote'], $tags);
218
                } catch (\Exception $e) {
219
                    // Ignore invalid vote
220
                }
221
            endfor;
222
        endforeach;
223
224 1
        return $adding;
225
    }
226
227 71
    public function parseVotes (string $input, bool $allowFile = true)
228
    {
229 71
        $input = CondorcetUtil::prepareParse($input, $allowFile);
230 71
        if ($input === false) :
231
            return $input;
232
        endif;
233
234
        // Check each lines
235 71
        $adding = [];
236 71
        foreach ($input as $line) :
237
            // Empty Line
238 71
            if (empty($line)) :
239 63
                continue;
240
            endif;
241
242
            // Multiples
243 71
            $is_multiple = mb_strpos($line, '*');
244 71
            if ($is_multiple !== false) :
245 64
                $multiple = trim( substr($line, $is_multiple + 1) );
246
247
                // Errors
248 64
                if ( !is_numeric($multiple) ) :
249
                    throw new CondorcetException(13, null);
250
                endif;
251
252 64
                $multiple = intval($multiple);
253
254
                // Reformat line
255 64
                $line = substr($line, 0, $is_multiple);
256
            else :
257 9
                $multiple = 1;
258
            endif;
259
260
            // Vote Weight
261 71
            $is_voteWeight = mb_strpos($line, '^');
262 71
            if ($is_voteWeight !== false) :
263 2
                $weight = trim( substr($line, $is_voteWeight + 1) );
264
265
                // Errors
266 2
                if ( !is_numeric($weight) ) :
267
                    throw new CondorcetException(13, null);
268
                endif;
269
270 2
                $weight = intval($weight);
271
272
                // Reformat line
273 2
                $line = substr($line, 0, $is_voteWeight);
274
            else :
275 70
                $weight = 1;
276
            endif;
277
278
            // Tags + vote
279 71
            if (mb_strpos($line, '||') !== false) :
280 4
                $data = explode('||', $line);
281
282 4
                $vote = $data[1];
283 4
                $tags = $data[0];
284
            // Vote without tags
285
            else :
286 70
                $vote = $line;
287 70
                $tags = null;
288
            endif;
289
290
            // addVote
291 71
            for ($i = 0; $i < $multiple; $i++) :
292 71
                if (self::$_maxParseIteration !== null && count($adding) >= self::$_maxParseIteration) :
0 ignored issues
show
Bug Best Practice introduced by
The property _maxParseIteration does not exist on Condorcet\ElectionProcess\VotesProcess. Did you maybe forget to declare it?
Loading history...
293 1
                    throw new CondorcetException(12, self::$_maxParseIteration);
294
                endif;
295
296
                try {
297 71
                    $adding[] = ($newVote = $this->addVote($vote, $tags));
298 71
                    $newVote->setWeight($weight);
299 1
                } catch (CondorcetException $e) {}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
300
            endfor;
301
        endforeach;
302
303 71
        return $adding;
304
    }
305
306
}
307