Completed
Push — master ( fa5d50...73dade )
by Alex
13s queued 11s
created

BitMask::isFlag()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 1
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cruxinator\BitMask;
6
7
use BadMethodCallException;
8
use MyCLabs\Enum\Enum;
9
10
abstract class BitMask extends Enum
11
{
12
    // Because 0 is the identity element when ORing a bitmask, we have to special-case it when ANDing bitmasks
13
    // (akin to ordinary division by 0, the addition identity element on integers/rationals/reals)
14
15
    protected function isFlag(int $flag): bool
16
    {
17
        return 0 === $flag ? 0 === $this->value : (($this->value & $flag) == $flag);
18
    }
19
20
    protected function setFlag(int $flag, bool $value)
21
    {
22
        if ($value) {
23
            $this->value = 0 === $flag ? 0 : $this->value | $flag;
24
        } else {
25
            $this->value = 0 === $flag  ? $this->value : $this->value & ~$flag;
26
        }
27
        return $this;
28
    }
29
30
    /**
31
     * @param $name
32
     * @param $arguments
33
     * @return bool|self
34
     */
35
    public function __call($name, $arguments)
36
    {
37
        $array     = static::toArray();
38
        $regexBase = '/(is|set)(%s)/m';
39
        $regexFull = sprintf($regexBase, implode('|', array_keys($array)));
40
        preg_match($regexFull, $name, $match);
41
        if (count($match)>0 && $match[0] === $name) {
42
            return $this->{$match[1] . 'Flag'}($array[$match[2]], $arguments[0] ?? true);
43
        }
44
        throw new BadMethodCallException(sprintf('Enum %s not found on %s', $name, get_class($this)));
45
    }
46
47
    /**
48
     * @param $value
49
     * @return bool
50
     */
51
    public static function isValid($value)
52
    {
53
        $min = min(static::toArray());
54
        $max = max(static::toArray()) * 2 - 1;
55
        return $value >= $min && $value <= $max;
56
    }
57
58
    /**
59
     * @return array
60
     */
61
    public static function toArray()
62
    {
63
        $array = parent::toArray();
64
        //TODO: check that the array is defined correctly. basically check everything in the array is a int.
65
        /*$array = array_filter($array, function ($temp) {
66
            $raw = log($temp, 2);
67
            return is_int($temp) && 0.01 > abs($raw - round($raw));
68
        }
69
        );*/
70
        return $array;
71
    }
72
73
    /**
74
     * @return array|mixed
75
     */
76
    public function getKey()
77
    {
78
        $value = $this->value;
79
        $f     = array_filter(static::toArray(), function () use (&$value) {
80
            $isSet = $value & 1;
81
            $value = $value >> 1;
82
            return $isSet;
83
        });
84
85
        return array_keys($f);
86
    }
87
88
    /**
89
     * @return string
90
     */
91
    public function __toString()
92
    {
93
        $name  = $this->getName();
94
        $array = static::toArray();
95
        $ret   = '';
96
        foreach ($array as $key => $value) {
97
            $ret .= "'" . $key . "' => " . ($this->{'is' . $key}() ? 'TRUE' : 'FALSE') . PHP_EOL;
98
        }
99
        return $name . '[' . PHP_EOL .
100
            $ret .
101
            ']' . PHP_EOL;
102
    }
103
104
    public function getName()
105
    {
106
        $path = explode('\\', __CLASS__);
107
        return array_pop($path);
108
    }
109
}
110