Completed
Push — master ( 58bad8...42921a )
by Boudry
03:06
created

Condorcet::addMethod()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4.0466

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 6
cts 7
cp 0.8571
rs 9.2
c 0
b 0
f 0
cc 4
eloc 9
nc 3
nop 1
crap 4.0466
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 33 and the first side effect is on line 17.

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
namespace Condorcet;
11
12
use Condorcet\CondorcetException;
13
use Condorcet\Election;
14
use Condorcet\Result;
15
16
// Registering native Condorcet Methods implementation
17 7
Condorcet::addMethod(__NAMESPACE__.'\\Algo\\Methods\\Copeland');
18 7
Condorcet::addMethod(__NAMESPACE__.'\\Algo\\Methods\\DodgsonQuick');
19 7
Condorcet::addMethod(__NAMESPACE__.'\\Algo\\Methods\\DodgsonTidemanApproximation');
20 7
Condorcet::addMethod(__NAMESPACE__.'\\Algo\\Methods\\KemenyYoung');
21 7
Condorcet::addMethod(__NAMESPACE__.'\\Algo\\Methods\\MinimaxWinning');
22 7
Condorcet::addMethod(__NAMESPACE__.'\\Algo\\Methods\\MinimaxMargin');
23 7
Condorcet::addMethod(__NAMESPACE__.'\\Algo\\Methods\\MinimaxOpposition');
24 7
Condorcet::addMethod(__NAMESPACE__.'\\Algo\\Methods\\RankedPairsMargin');
25 7
Condorcet::addMethod(__NAMESPACE__.'\\Algo\\Methods\\RankedPairsWinning');
26 7
Condorcet::addMethod(__NAMESPACE__.'\\Algo\\Methods\\SchulzeWinning');
27 7
Condorcet::addMethod(__NAMESPACE__.'\\Algo\\Methods\\SchulzeMargin');
28 7
Condorcet::addMethod(__NAMESPACE__.'\\Algo\\Methods\\SchulzeRatio');
29
30
// Set the default Condorcet Class algorithm
31 7
Condorcet::setDefaultMethod('Schulze');
32
33
abstract class Condorcet
34
{
35
36
/////////// CONSTANTS ///////////
37
    public const VERSION = '1.5.0';
38
39
    public const CONDORCET_BASIC_CLASS = __NAMESPACE__.'\\Algo\\Methods\\CondorcetBasic';
40
41
    protected static $_defaultMethod = null;
42
    protected static $_authMethods = [ self::CONDORCET_BASIC_CLASS => (__NAMESPACE__.'\\Algo\\Methods\\CondorcetBasic')::METHOD_NAME ];
43
44
45
/////////// STATICS METHODS ///////////
46
47
    // Return library version numer
48 2
    public static function getVersion (string $options = 'FULL') : string
49
    {
50 2
        switch ($options) :
51
            case 'MAJOR':
52
                $version = explode('.', self::VERSION);
53
                return $version[0].'.'.$version[1];
54
55
            default:
56 2
                return self::VERSION;
57
        endswitch;
58
    }
59
60
    // Return an array with auth methods
61 1
    public static function getAuthMethods (bool $basic = false) : array
62
    {
63 1
        $auth = self::$_authMethods;
64
65
        // Don't show Natural Condorcet
66 1
        if (!$basic) :
67 1
            unset($auth[self::CONDORCET_BASIC_CLASS]);
68
        endif;
69
70 1
        return array_column($auth,0);
71
    }
72
73
74
    // Return the Class default method
75 7
    public static function getDefaultMethod () {
76 7
        return self::$_defaultMethod;
77
    }
78
79
80
    // Check if the method is supported
81 7
    public static function isAuthMethod (string $method)
82
    {
83 7
        $auth = self::$_authMethods;
84
85 7
        if (empty($method)) :
86
            throw new CondorcetException (8);
87
        endif;
88
89 7
        if ( isset($auth[$method]) ) :
90 7
            return $method;
91
        else : // Alias
92 7
            foreach ($auth as $class => &$alias) :
93 7
                foreach ($alias as &$entry) :
94 7
                    if ( strcasecmp($method,$entry) === 0 ) :
95 7
                        return $class;
96
                    endif;
97
                endforeach;
98
            endforeach;
99
        endif;
100
101 7
        return false;
102
    }
103
104
105
    // Add algos
106 7
    public static function addMethod (string $algos) : bool
107
    {
108
        // Check algos
109 7
        if ( self::isAuthMethod($algos) || !self::testMethod($algos) ) :
110
            return false;
111
        endif;
112
113
        // Adding algo
114 7
        self::$_authMethods[$algos] = $algos::METHOD_NAME;
115
116 7
        if (self::getDefaultMethod() === null) :
117 7
            self::setDefaultMethod($algos);
118
        endif;
119
120 7
        return true;
121
    }
122
123
124
        // Check if the class Algo. exist and ready to be used
125 7
        protected static function testMethod (string $method) : bool
126
        {
127 7
            if ( !class_exists($method) ) :             
128
                throw new CondorcetException(9);
129
            endif;
130
131 7
            if ( !is_subclass_of($method, __NAMESPACE__.'\\Algo\\MethodInterface') || !is_subclass_of($method,__NAMESPACE__.'\\Algo\\Method') ) :
2 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if __NAMESPACE__ . '\\Algo\\MethodInterface' can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if __NAMESPACE__ . '\\Algo\\Method' can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
132 1
                throw new CondorcetException(10);
133
            endif;
134
135 7
            foreach ($method::METHOD_NAME as $alias) :
136 7
                if (self::isAuthMethod($alias)) :
137 7
                    throw new CondorcetException(25);
138
                endif;
139
            endforeach;
140
141 7
            return true;
142
        }
143
144
145
    // Change default method for this class.
146 7
    public static function setDefaultMethod (string $method) : bool
147
    {       
148 7
        if ( ($method = self::isAuthMethod($method)) && $method !== self::CONDORCET_BASIC_CLASS ) :
149 7
            self::$_defaultMethod = $method;
150 7
            return true;
151
        else :
152
            return false;
153
        endif;
154
    }
155
156
    // Simplify Condorcet Var_Dump. Transform object to String.
157 4
    public static function format ($input, bool $convertObject = true)
158
    {
159 4
        if (is_object($input)) :
160
            
161 4
            $r = $input;
162
163 4
            if ($convertObject) :
164 2
                if ($input instanceof Candidate) :
165
                    $r = (string) $input;
166 2
                elseif ($input instanceof Vote) :
167
                    $r = $input->getRanking();
168 2
                elseif ($input instanceof Result) :
169 4
                    $r = $input->getResultAsArray(true);
170
                endif;
171
            endif;
172
173 4
        elseif (!is_array($input)) :
174 2
            $r = $input;
175
        else :
176 4
            foreach ($input as $key => $line) :
177 4
                $input[$key] = self::format($line,false,$convertObject);
0 ignored issues
show
Unused Code introduced by
The call to Condorcet::format() has too many arguments starting with $convertObject.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
178
            endforeach;
179
180 4
            if (count($input) === 1 && is_int(key($input)) && (!is_array(reset($input)) || count(reset($input)) === 1)):
181 2
                $r = reset($input);
182
            else:
183 2
                $r = $input;
184
            endif;
185
        endif;
186
        
187 4
        return $r;
188
    }
189
}