Encoder   A
last analyzed

Complexity

Total Complexity 41

Size/Duplication

Total Lines 539
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 9

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 41
lcom 2
cbo 9
dl 0
loc 539
ccs 124
cts 124
cp 1
rs 9.1199
c 0
b 0
f 0

35 Methods

Rating   Name   Duplication   Size   Complexity  
A encodeRule() 0 14 1
A encodePolicy() 0 13 1
A encodePolicySet() 0 15 1
A getType() 0 6 1
A isTarget() 0 4 1
A isRule() 0 4 1
A isPolicy() 0 4 1
A isPolicySet() 0 8 2
A targetName() 0 6 1
A targetAnyOfs() 0 6 1
A ruleName() 0 6 1
A ruleTarget() 0 6 1
A ruleEffect() 0 6 1
A ruleCondition() 0 6 1
A ruleObligations() 0 6 1
A ruleAdvice() 0 6 1
A policyName() 0 6 1
A policyTarget() 0 6 1
A policyObligations() 0 6 1
A policyAdvice() 0 6 1
A policyRules() 0 6 1
A policySetName() 0 6 1
A policySetTarget() 0 6 1
A policySetObligations() 0 6 1
A policySetAdvice() 0 6 1
A policySetChildren() 0 6 1
A rulesData() 0 6 1
A policiesAndSetsData() 0 6 1
A getFulfillObligations() 0 6 2
A getAppliedAdvice() 0 6 2
A serializeMethod() 0 4 2
A encodeObligations() 0 10 2
A encodeAdvice() 0 10 2
A encodeRules() 0 7 1
A serializePoliciesAndSets() 0 9 1

How to fix   Complexity   

Complex Class

Complex classes like Encoder often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Encoder, and based on these observations, apply Extract Interface, too.

1
<?php declare(strict_types=1);
2
3
namespace Limoncello\Auth\Authorization\PolicyDecision\Algorithms;
4
5
/**
6
 * Copyright 2015-2019 [email protected]
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 * http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
21
use Limoncello\Auth\Contracts\Authorization\PolicyAdministration\AdviceInterface;
22
use Limoncello\Auth\Contracts\Authorization\PolicyAdministration\MethodInterface;
23
use Limoncello\Auth\Contracts\Authorization\PolicyAdministration\ObligationInterface;
24
use Limoncello\Auth\Contracts\Authorization\PolicyAdministration\PolicyCombiningAlgorithmInterface;
25
use Limoncello\Auth\Contracts\Authorization\PolicyAdministration\PolicyInterface;
26
use Limoncello\Auth\Contracts\Authorization\PolicyAdministration\PolicySetInterface;
27
use Limoncello\Auth\Contracts\Authorization\PolicyAdministration\RuleCombiningAlgorithmInterface;
28
use Limoncello\Auth\Contracts\Authorization\PolicyAdministration\RuleInterface;
29
use function assert;
30
use function array_key_exists;
31
32
/**
33
 * @package Limoncello\Auth
34
 *
35
 * @SuppressWarnings(PHPMD.TooManyMethods)
36
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
37
 */
38
class Encoder
39
{
40
    use DefaultTargetSerializeTrait;
41
42
    /** Type index */
43
    const TYPE = 0;
44
45
    /** Encoded type */
46
    const TYPE_TARGET = 0;
47
48
    /** Encoded type */
49
    const TYPE_RULE = self::TYPE_TARGET + 1;
50
51
    /** Encoded type */
52
    const TYPE_POLICY = self::TYPE_RULE + 1;
53
54
    /** Encoded type */
55
    const TYPE_POLICY_SET = self::TYPE_POLICY + 1;
56
57
    /** Encoded type */
58
    const TYPE_RULES = self::TYPE_POLICY_SET + 1;
59
60
    /** Encoded type */
61
    const TYPE_POLICIES_AND_SETS = self::TYPE_RULES + 1;
62
63
    /** Rule index */
64
    const TARGET_NAME = self::TYPE + 1;
65
66
    /** Rule index */
67
    const TARGET_ANY_OFS = self::TARGET_NAME + 1;
68
69
    /** Rule index */
70
    const RULE_NAME = self::TYPE + 1;
71
72
    /** Rule index */
73
    const RULE_TARGET = self::RULE_NAME + 1;
74
75
    /** Rule index */
76
    const RULE_CONDITION = self::RULE_TARGET + 1;
77
78
    /** Rule index */
79
    const RULE_EFFECT = self::RULE_CONDITION + 1;
80
81
    /** Rule index */
82
    const RULE_OBLIGATIONS = self::RULE_EFFECT + 1;
83
84
    /** Rule index */
85
    const RULE_ADVICE = self::RULE_OBLIGATIONS + 1;
86
87
    /** Policy index */
88
    const POLICY_NAME = self::TYPE + 1;
89
90
    /** Policy index */
91
    const POLICY_TARGET = self::POLICY_NAME + 1;
92
93
    /** Policy index */
94
    const POLICY_OBLIGATIONS = self::POLICY_TARGET + 1;
95
96
    /** Policy index */
97
    const POLICY_ADVICE = self::POLICY_OBLIGATIONS + 1;
98
99
    /** Policy index */
100
    const POLICY_RULES = self::POLICY_ADVICE + 1;
101
102
    /** Policy index */
103
    const POLICY_SET_NAME = self::TYPE + 1;
104
105
    /** Policy index */
106
    const POLICY_SET_TARGET = self::POLICY_SET_NAME + 1;
107
108
    /** Policy index */
109
    const POLICY_SET_OBLIGATIONS = self::POLICY_SET_TARGET + 1;
110
111
    /** Policy index */
112
    const POLICY_SET_ADVICE = self::POLICY_SET_OBLIGATIONS + 1;
113
114
    /** Policy index */
115
    const POLICY_SET_CHILDREN = self::POLICY_SET_ADVICE + 1;
116
117
    /** Rules index */
118
    const RULES_DATA = self::TYPE + 1;
119
120
    /** Rules index */
121
    const POLICIES_AND_SETS_DATA = self::TYPE + 1;
122
123
    /**
124 36
     * @param RuleInterface $rule
125
     *
126
     * @return array
127 36
     */
128 36
    public static function encodeRule(RuleInterface $rule): array
129 36
    {
130 36
        $result = [
131 36
            static::TYPE             => static::TYPE_RULE,
132 36
            static::RULE_NAME        => $rule->getName(),
133 36
            static::RULE_TARGET      => static::encodeTarget($rule->getTarget()),
134
            static::RULE_CONDITION   => static::serializeMethod($rule->getCondition()),
0 ignored issues
show
Bug introduced by
Since serializeMethod() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of serializeMethod() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
135
            static::RULE_EFFECT      => static::serializeMethod($rule->effect()),
0 ignored issues
show
Bug introduced by
Since serializeMethod() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of serializeMethod() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
136 36
            static::RULE_OBLIGATIONS => static::encodeObligations($rule->getObligations()),
0 ignored issues
show
Bug introduced by
Since encodeObligations() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of encodeObligations() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
137
            static::RULE_ADVICE      => static::encodeAdvice($rule->getAdvice()),
0 ignored issues
show
Bug introduced by
Since encodeAdvice() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of encodeAdvice() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
138
        ];
139
140
        return $result;
141
    }
142
143
    /**
144 24
     * @param PolicyInterface $policy
145
     *
146
     * @return array
147 24
     */
148 24
    public static function encodePolicy(PolicyInterface $policy): array
149 24
    {
150 24
        $result = [
151 24
            static::TYPE               => static::TYPE_POLICY,
152 24
            static::POLICY_NAME        => $policy->getName(),
153
            static::POLICY_TARGET      => static::encodeTarget($policy->getTarget()),
154
            static::POLICY_OBLIGATIONS => static::encodeObligations($policy->getObligations()),
0 ignored issues
show
Bug introduced by
Since encodeObligations() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of encodeObligations() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
Documentation introduced by
$policy->getObligations() is of type array<integer,object<Lim...ation\MethodInterface>>, but the function expects a array<integer,object<Lim...n\ObligationInterface>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
155 24
            static::POLICY_ADVICE      => static::encodeAdvice($policy->getAdvice()),
0 ignored issues
show
Bug introduced by
Since encodeAdvice() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of encodeAdvice() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
Documentation introduced by
$policy->getAdvice() is of type array<integer,object<Lim...ation\MethodInterface>>, but the function expects a array<integer,object<Lim...ation\AdviceInterface>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
156
            static::POLICY_RULES       => static::encodeRules($policy->getCombiningAlgorithm(), $policy->getRules()),
0 ignored issues
show
Bug introduced by
Since encodeRules() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of encodeRules() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
157
        ];
158
159
        return $result;
160
    }
161
162
    /**
163 13
     * @param PolicySetInterface $set
164
     *
165 13
     * @return array
166 13
     */
167
    public static function encodePolicySet(PolicySetInterface $set): array
168 13
    {
169 13
        $algorithm       = $set->getCombiningAlgorithm();
170 13
        $policiesAndSets = $set->getPoliciesAndSets();
171 13
        $result          = [
172 13
            static::TYPE                   => static::TYPE_POLICY_SET,
173 13
            static::POLICY_SET_NAME        => $set->getName(),
174
            static::POLICY_SET_TARGET      => static::encodeTarget($set->getTarget()),
175
            static::POLICY_SET_OBLIGATIONS => static::encodeObligations($set->getObligations()),
0 ignored issues
show
Bug introduced by
Since encodeObligations() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of encodeObligations() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
Documentation introduced by
$set->getObligations() is of type array<integer,object<Lim...ation\MethodInterface>>, but the function expects a array<integer,object<Lim...n\ObligationInterface>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
176 13
            static::POLICY_SET_ADVICE      => static::encodeAdvice($set->getAdvice()),
0 ignored issues
show
Bug introduced by
Since encodeAdvice() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of encodeAdvice() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
Documentation introduced by
$set->getAdvice() is of type array<integer,object<Lim...ation\MethodInterface>>, but the function expects a array<integer,object<Lim...ation\AdviceInterface>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
177
            static::POLICY_SET_CHILDREN    => static::serializePoliciesAndSets($algorithm, $policiesAndSets),
0 ignored issues
show
Bug introduced by
Since serializePoliciesAndSets() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of serializePoliciesAndSets() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
178
        ];
179
180
        return $result;
181
    }
182
183
    /**
184 34
     * @param array $encoded
185
     *
186 34
     * @return int
187
     */
188 34
    public static function getType(array $encoded): int
189
    {
190
        assert(array_key_exists(static::TYPE, $encoded) === true);
191
192
        return $encoded[static::TYPE];
193
    }
194
195
    /**
196 26
     * @param array $encoded
197
     *
198 26
     * @return bool
199
     */
200
    public static function isTarget(array $encoded): bool
201
    {
202
        return static::getType($encoded) === static::TYPE_TARGET;
203
    }
204
205
    /**
206 25
     * @param array $encoded
207
     *
208 25
     * @return bool
209
     */
210
    public static function isRule(array $encoded): bool
211
    {
212
        return static::getType($encoded) === static::TYPE_RULE;
213
    }
214
215
    /**
216 22
     * @param array $encoded
217
     *
218 22
     * @return bool
219
     */
220
    public static function isPolicy(array $encoded): bool
221
    {
222
        return static::getType($encoded) === static::TYPE_POLICY;
223
    }
224
225
    /**
226 16
     * @param array $encoded
227
     *
228 16
     * @return bool
229
     */
230 16
    public static function isPolicySet(array $encoded): bool
231
    {
232 16
        $type = static::getType($encoded);
233
234
        assert($type === static::TYPE_POLICY || $type === static::TYPE_POLICY_SET);
235
236
        return $type === static::TYPE_POLICY_SET;
237
    }
238
239
    /**
240 8
     * @param array $encodedTarget
241
     *
242 8
     * @return string|null
243
     */
244 8
    public static function targetName(array $encodedTarget): ?string
245
    {
246
        assert(static::isTarget($encodedTarget));
247
248
        return $encodedTarget[self::TARGET_NAME];
249
    }
250
251
    /**
252 26
     * @param array $encodedTarget
253
     *
254 26
     * @return array|null
255
     */
256 26
    public static function targetAnyOfs(array $encodedTarget): ?array
257
    {
258
        assert(static::isTarget($encodedTarget));
259
260
        return $encodedTarget[self::TARGET_ANY_OFS];
261
    }
262
263
    /**
264 7
     * @param array $encodedRule
265
     *
266 7
     * @return string
267
     */
268 7
    public static function ruleName(array $encodedRule): string
269
    {
270
        assert(static::isRule($encodedRule));
271
272
        return $encodedRule[static::RULE_NAME];
273
    }
274
275
    /**
276 1
     * @param array $encodedRule
277
     *
278 1
     * @return array
279
     */
280 1
    public static function ruleTarget(array $encodedRule): array
281
    {
282
        assert(static::isRule($encodedRule));
283
284
        return $encodedRule[static::RULE_TARGET];
285
    }
286
287
    /**
288 21
     * @param array $encodedRule
289
     *
290 21
     * @return array|null
291
     */
292 21
    public static function ruleEffect(array $encodedRule): ?array
293
    {
294
        assert(static::isRule($encodedRule));
295
296
        return $encodedRule[static::RULE_EFFECT];
297
    }
298
299
    /**
300 20
     * @param array $encodedRule
301
     *
302 20
     * @return callable|null
303
     */
304 20
    public static function ruleCondition(array $encodedRule): ?callable
305
    {
306
        assert(static::isRule($encodedRule));
307
308
        return $encodedRule[static::RULE_CONDITION];
309
    }
310
311
    /**
312 24
     * @param array $encodedRule
313
     *
314 24
     * @return callable[]
315
     */
316 24
    public static function ruleObligations(array $encodedRule): array
317
    {
318
        assert(static::isRule($encodedRule));
319
320
        return $encodedRule[static::RULE_OBLIGATIONS];
321
    }
322
323
    /**
324 24
     * @param array $encodedRule
325
     *
326 24
     * @return callable[]
327
     */
328 24
    public static function ruleAdvice(array $encodedRule): array
329
    {
330
        assert(static::isRule($encodedRule));
331
332
        return $encodedRule[static::RULE_ADVICE];
333
    }
334
335
    /**
336 14
     * @param array $encodedPolicy
337
     *
338 14
     * @return string|null
339
     */
340 14
    public static function policyName(array $encodedPolicy): ?string
341
    {
342
        assert(static::isPolicy($encodedPolicy));
343
344
        return $encodedPolicy[static::POLICY_NAME];
345
    }
346
347
    /**
348 1
     * @param array $encodedPolicy
349
     *
350 1
     * @return array
351
     */
352 1
    public static function policyTarget(array $encodedPolicy): array
353
    {
354
        assert(static::isPolicy($encodedPolicy));
355
356
        return $encodedPolicy[static::POLICY_TARGET];
357
    }
358
359
    /**
360 13
     * @param array $encodedPolicy
361
     *
362 13
     * @return callable[]
363
     */
364 13
    public static function policyObligations(array $encodedPolicy): array
365
    {
366
        assert(static::isPolicy($encodedPolicy));
367
368
        return $encodedPolicy[static::POLICY_OBLIGATIONS];
369
    }
370
371
    /**
372 13
     * @param array $encodedPolicy
373
     *
374 13
     * @return callable[]
375
     */
376 13
    public static function policyAdvice(array $encodedPolicy): array
377
    {
378
        assert(static::isPolicy($encodedPolicy));
379
380
        return $encodedPolicy[static::POLICY_ADVICE];
381
    }
382
383
    /**
384 19
     * @param array $encodedPolicy
385
     *
386 19
     * @return array
387
     */
388 19
    public static function policyRules(array $encodedPolicy): array
389
    {
390
        assert(static::isPolicy($encodedPolicy));
391
392
        return $encodedPolicy[static::POLICY_RULES];
393
    }
394
395
    /**
396 8
     * @param array $encodedPolicySet
397
     *
398 8
     * @return string
399
     */
400 8
    public static function policySetName(array $encodedPolicySet): string
401
    {
402
        assert(static::isPolicySet($encodedPolicySet));
403
404
        return $encodedPolicySet[static::POLICY_SET_NAME];
405
    }
406
407
    /**
408 8
     * @param array $encodedPolicySet
409
     *
410 8
     * @return array
411
     */
412 8
    public static function policySetTarget(array $encodedPolicySet): array
413
    {
414
        assert(static::isPolicySet($encodedPolicySet));
415
416
        return $encodedPolicySet[static::POLICY_SET_TARGET];
417
    }
418
419
    /**
420 10
     * @param array $encodedPolicySet
421
     *
422 10
     * @return callable[]
423
     */
424 10
    public static function policySetObligations(array $encodedPolicySet): array
425
    {
426
        assert(static::isPolicySet($encodedPolicySet));
427
428
        return $encodedPolicySet[static::POLICY_SET_OBLIGATIONS];
429
    }
430
431
    /**
432 10
     * @param array $encodedPolicySet
433
     *
434 10
     * @return callable[]
435
     */
436 10
    public static function policySetAdvice(array $encodedPolicySet): array
437
    {
438
        assert(static::isPolicySet($encodedPolicySet));
439
440
        return $encodedPolicySet[static::POLICY_SET_ADVICE];
441
    }
442
443
    /**
444 11
     * @param array $encodedPolicySet
445
     *
446 11
     * @return array
447
     */
448 11
    public static function policySetChildren(array $encodedPolicySet): array
449
    {
450
        assert(static::isPolicySet($encodedPolicySet));
451
452
        return $encodedPolicySet[static::POLICY_SET_CHILDREN];
453
    }
454
455
    /**
456 19
     * @param array $rules
457
     *
458 19
     * @return array
459
     */
460 19
    public static function rulesData(array $rules): array
461
    {
462
        assert(static::getType($rules) === static::TYPE_RULES);
463
464
        return $rules[static::RULES_DATA];
465
    }
466
467
    /**
468 11
     * @param array $policesAndSets
469
     *
470 11
     * @return array
471
     */
472 11
    public static function policiesAndSetsData(array $policesAndSets): array
473
    {
474
        assert(static::getType($policesAndSets) === static::TYPE_POLICIES_AND_SETS);
475
476
        return $policesAndSets[static::POLICIES_AND_SETS_DATA];
477
    }
478
479
    /**
480
     * @param int   $evaluation
481 26
     * @param array $obligations
482
     *
483 26
     * @return array
484
     */
485 26
    public static function getFulfillObligations(int $evaluation, array $obligations): array
486
    {
487
        $result = array_key_exists($evaluation, $obligations) === true ? $obligations[$evaluation] : [];
488
489
        return $result;
490
    }
491
492
    /**
493
     * @param int   $evaluation
494 26
     * @param array $advice
495
     *
496 26
     * @return array
497
     */
498 26
    public static function getAppliedAdvice(int $evaluation, array $advice): array
499
    {
500
        $result = array_key_exists($evaluation, $advice) === true ? $advice[$evaluation] : [];
501
502
        return $result;
503
    }
504
505
    /**
506 36
     * @param MethodInterface|null $method
507
     *
508 36
     * @return callable|null
509
     */
510
    private static function serializeMethod(MethodInterface $method = null): ?callable
511
    {
512
        return $method === null ? null : $method->getCallable();
513
    }
514
515
    /**
516 36
     * @param ObligationInterface[] $obligations
517
     *
518 36
     * @return array
519 36
     */
520
    private static function encodeObligations(array $obligations): array
521 18
    {
522
        $result = [];
523
        foreach ($obligations as $item) {
524 36
            /** @var ObligationInterface $item*/
525
            $result[$item->getFulfillOn()][] = $item->getCallable();
526
        }
527
528
        return $result;
529
    }
530
531
    /**
532 36
     * @param AdviceInterface[] $advice
533
     *
534 36
     * @return array
535 36
     */
536
    private static function encodeAdvice(array $advice): array
537 20
    {
538
        $result = [];
539
        foreach ($advice as $item) {
540 36
            /** @var AdviceInterface $item*/
541
            $result[$item->getAppliesTo()][] = $item->getCallable();
542
        }
543
544
        return $result;
545
    }
546
547
    /**
548
     * @param RuleCombiningAlgorithmInterface $algorithm
549 24
     * @param array                           $rules
550
     *
551
     * @return array
552 24
     */
553 24
    private static function encodeRules(RuleCombiningAlgorithmInterface $algorithm, array $rules): array
554
    {
555
        return [
556
            static::TYPE       => static::TYPE_RULES,
557
            static::RULES_DATA => $algorithm->optimize($rules)
558
        ];
559
    }
560
561
    /**
562
     * @param PolicyCombiningAlgorithmInterface $algorithm
563 13
     * @param array                             $policiesAndSets
564
     *
565
     * @return array
566
     */
567
    private static function serializePoliciesAndSets(
568 13
        PolicyCombiningAlgorithmInterface $algorithm,
569 13
        array $policiesAndSets
570
    ): array {
571
        return [
572
            static::TYPE                   => static::TYPE_POLICIES_AND_SETS,
573
            static::POLICIES_AND_SETS_DATA => $algorithm->optimize($policiesAndSets)
574
        ];
575
    }
576
}
577