summaryrefslogtreecommitdiffstats
path: root/library/Icingadb/Model/Behavior/Bitmask.php
blob: f8d91f627c8ce242b1fa62d8fb68b65de6961e98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<?php

/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */

namespace Icinga\Module\Icingadb\Model\Behavior;

use ipl\Orm\Contract\PropertyBehavior;
use ipl\Orm\Contract\RewriteFilterBehavior;
use ipl\Stdlib\Filter\Condition;

/**
 * Class Bitmask
 *
 * @method void __construct(array $properties) Pass property names as keys and their bitmap ([value => bit]) as value
 */
class Bitmask extends PropertyBehavior implements RewriteFilterBehavior
{
    public function fromDb($bits, $key, $context)
    {
        $values = [];
        foreach ($context as $value => $bit) {
            if ($bits & $bit) {
                $values[] = $value;
            }
        }

        return $values;
    }

    public function toDb($value, $key, $context)
    {
        if (! is_array($value)) {
            if (is_int($value) || ctype_digit($value)) {
                return $value;
            }

            return isset($context[$value]) ? $context[$value] : -1;
        }

        $bits = [];
        $allBits = 0;
        foreach ($value as $v) {
            if (isset($context[$v])) {
                $bits[] = $context[$v];
                $allBits |= $context[$v];
            } elseif (is_int($v) || ctype_digit($v)) {
                $bits[] = $v;
                $allBits |= $v;
            }
        }

        $bits[] = $allBits;
        return $bits;
    }

    public function rewriteCondition(Condition $condition, $relation = null)
    {
        $column = $condition->metaData()->get('columnName');
        if (! isset($this->properties[$column])) {
            return;
        }

        $values = $condition->getValue();
        if (! is_array($values)) {
            if (is_int($values) || ctype_digit($values)) {
                return;
            }

            $values = [$values];
        }

        $bits = 0;
        foreach ($values as $value) {
            if (isset($this->properties[$column][$value])) {
                $bits |= $this->properties[$column][$value];
            } elseif (is_int($value) || ctype_digit($value)) {
                $bits |= $value;
            }
        }

        $condition->setColumn(sprintf('%s & %s', $condition->getColumn(), $bits));
    }
}