Passed
Branch master (73ca69)
by Boudry
03:33
created

VotesManager::countVotes()   D

Complexity

Conditions 9
Paths 10

Size

Total Lines 28
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 9

Importance

Changes 0
Metric Value
dl 0
loc 28
ccs 15
cts 15
cp 1
rs 4.909
c 0
b 0
f 0
cc 9
eloc 23
nc 10
nop 2
crap 9
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 19 and the first side effect is on line 28.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/*
3
    Condorcet PHP Class, with Schulze Methods and others !
4
5
    By Julien Boudry - MIT LICENSE (Please read LICENSE.txt)
6
    https://github.com/julien-boudry/Condorcet
7
*/
8
declare(strict_types=1);
9
10
11
namespace Condorcet\DataManager;
12
13
use Condorcet\DataManager\ArrayManager;
14
use Condorcet\DataManager\DataContextInterface;
15
use Condorcet\CondorcetException;
16
use Condorcet\Election;
17
use Condorcet\Vote;
18
19
class VotesManager extends ArrayManager
20
{
21
22
/////////// Magic ///////////
23
24 4
    public function __construct (?Election $election = null)
25
    {
26 4
        if ($election !== null) :
27 4
            $this->_link[] = $election;
28
        endif;
29
30 4
        parent::__construct();
31 4
    }
32
33
/////////// Data CallBack for external drivers ///////////
34
35
    public function getDataContextObject ()
36
    {
37
        $context = new Class implements DataContextInterface {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
38
            public $election;
39
40
            public function dataCallBack ($data) : Vote
41
            {
42
                $vote = new Vote ($data);
43
                $this->election->checkVoteCandidate($vote);
44
                $vote->registerLink($this->election);
45
46
                return $vote;
47
            }
48
49
            public function dataPrepareStoringAndFormat ($data) : string
50
            {
51
                $data->destroyLink($this->election);
52
53
                return (string) $data;
54
            }
55
        };
56
57
        $context->election = $this->_link[0] ?? null;
58
59
        return $context;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $context; (Condorcet\DataManager\an...ager/VotesManager.php$0) is incompatible with the return type of the parent method Condorcet\DataManager\Ar...r::getDataContextObject of type Condorcet\DataManager\an...ager/ArrayManager.php$0.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
60
    }
61
62
/////////// Array Access - Specials improvements ///////////
63
64 4
    public function offsetSet($offset, $value) : void
65
    {
66 4
        if ($value instanceof Vote) :
67 4
            parent::offsetSet($offset,$value);
68 4
            $this->setStateToVote();
69
        else :
70
            throw new CondorcetException (0,'Value must be an instanceof Condorcet\\Vote');
71
        endif;
72 4
    }
73
74 3
    public function offsetUnset($offset) : bool
75
    {
76 3
        if (parent::offsetUnset($offset)) :
77 3
            $this->setStateToVote();
78 3
            return true;
79
        endif;
80
        return false;
81
    }
82
83
/////////// Internal Election related methods ///////////
84
85 4
    protected function setStateToVote () : void
86
    {
87 4
        foreach ($this->_link as &$element) :
88 4
            $element->setStateToVote();
89
        endforeach;
90 4
    }
91
92
/////////// Public specific methods ///////////
93
94 2
    public function getVoteKey (Vote $vote) {
95
        // Return False if using with Bdd storing. Futur: Throw a PHP7 Error.
96 2
        return array_search($vote, $this->_Container, true);
97
    }
98
99
    // Get the votes registered list
100 4
    public function getVotesList (?array $tag = null, bool $with = true) : array
101
    {
102 4
        if (($tag = Vote::tagsConvert($tag)) === null) :
103 4
            return $this->getFullDataSet();
104
        else :
105 3
            $search = [];
106
107 3
            foreach ($this as $key => $value) :
108 3
                $noOne = true;
109 3
                foreach ($tag as $oneTag) :
110 3
                    if ( ( $oneTag === $key ) || in_array($oneTag, $value->getTags(),true) ) :
111 3
                        if ($with) :
112 3
                            $search[$key] = $value;
113 3
                            break;
114
                        else :
115 3
                            $noOne = false;
116
                        endif;
117
                    endif;
118
                endforeach;
119
120 3
                if (!$with && $noOne) :
121 3
                    $search[$key] = $value;
122
                endif;
123
            endforeach;
124
125 3
            return $search;
126
        endif;
127
    }
128
129
    public function getVotesListAsString () : string
130
    {
131
        $simpleList = '';
132
133
        $weight = [];
134
        $nb = [];
135
136
        foreach($this->getVotesList() as $oneVote) :
137
            $oneVoteString = $oneVote->getSimpleRanking($this->_link[0]);
138
139
            if(!array_key_exists($oneVoteString, $weight)) :
140
                $weight[$oneVoteString] = 0;
141
            endif;
142
            if(!array_key_exists($oneVoteString, $nb)) :
143
                $nb[$oneVoteString] = 0;
144
            endif;
145
146
            if ($this->_link[0]->isVoteWeightIsAllowed()) :
147
                $weight[$oneVoteString] += $oneVote->getWeight();
148
            else :
149
                $weight[$oneVoteString]++;
150
            endif;
151
152
            $nb[$oneVoteString]++;
153
        endforeach;
154
155
        ksort($weight);
156
        arsort($weight);
157
158
        $isFirst = true;
159
        foreach ($weight as $key => $value) :
160
            if (!$isFirst) : $simpleList .= "\n"; endif;
161
            $simpleList .= $key.' * '.$nb[$key];
162
            $isFirst = false;
163
        endforeach;
164
165
        return $simpleList;
166
    }
167
168 4
    public function countVotes (?array $tag, bool $with) : int
169
    {
170 4
        if ($tag === null) :
171 4
            return count($this);
172
        else :
173 2
            $count = 0;
174
175 2
            foreach ($this as $key => $value) :
176 2
                $noOne = true;
177 2
                foreach ($tag as $oneTag) :
178 2
                    if ( ( $oneTag === $key ) || in_array($oneTag, $value->getTags(),true) ) :
179 2
                        if ($with) :
180 2
                            $count++;
181 2
                            break;
182
                        else :
183 2
                            $noOne = false;
184
                        endif;
185
                    endif;
186
                endforeach;
187
188 2
                if (!$with && $noOne) :
189 2
                    $count++;
190
                endif;
191
            endforeach;
192
193 2
            return $count;
194
        endif;
195
    }
196
}
197