RuleApplier::applyRule()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 16
nc 4
nop 5
dl 0
loc 26
rs 9.7333
c 1
b 0
f 0
ccs 15
cts 15
cp 1
crap 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Oliverde8\Component\RuleEngine;
6
7
use Oliverde8\Component\RuleEngine\Exceptions\RuleException;
8
use Oliverde8\Component\RuleEngine\Exceptions\UnknownRuleException;
9
use Oliverde8\Component\RuleEngine\Rules\RuleInterface;
10
use Psr\Log\LoggerInterface;
11
12
/**
13
 * Class RuleApplier
14
 *
15
 * @author    de Cramer Oliver<[email protected]>
16
 * @copyright 2018 Oliverde8
17
 * @package Oliverde8\Component\RuleEngine\RuleApplier
18
 */
19
class RuleApplier
20
{
21
    protected LoggerInterface $logger;
22
23
    /** @var RuleInterface[] */
24
    protected array $rules;
25
26
    protected bool $validate;
27
28
    protected array $currentIdentity;
29
30
    /**
31
     * RuleApplier constructor.
32
     *
33
     * @param LoggerInterface $logger   Standard logger to use to log errors or debug information.
34
     * @param RuleInterface[] $rules    List of rules defined.
35
     * @param boolean         $validate When validation is active rules are validated and clear messages are displayed
36
     *                                  when a rule is not well coded. But performance is worsened.
37
     */
38
    public function __construct(LoggerInterface $logger, array $rules, bool $validate = false)
39 28
    {
40
        $this->logger = $logger;
41 28
        $this->validate = $validate;
42 28
43
        foreach ($rules as $rule) {
44 28
            $this->registerRule($rule);
45
        }
46
    }
47 28
48
    /**
49
     * Register a rule to the rule engine.
50
     *
51
     * @param RuleInterface $rule
52
     */
53
    public function registerRule(RuleInterface $rule)
54 7
    {
55
        $this->rules[$rule->getRuleCode()] = $rule;
56 7
    }
57 7
58
59
    /**
60
     * Apply rules to data.
61
     *
62
     * @param array|string $rowData         Data that is being transformed.
63
     * @param array|string $transformedData Transformed data at the current stage
64
     * @param array|string $rules           Rules to apply, if string is given the string is returned.
65
     * @param array        $options         Options to be used by the rules.
66
     * @param array        $identifier      Identity of the line rule is applied on to log & display.
67
     *
68
     * @return null|string
69
     * @throws UnknownRuleException
70
     * @throws RuleException
71
     */
72
    public function apply($rowData, $transformedData, $rules, array $options = [], array $identifier = [])
73 11
    {
74
        // There is no rule apply.
75
        if (!is_array($rules)) {
76 11
            return $rules;
77 5
        }
78
79
        if (!empty($identifier)) {
80 6
            $this->currentIdentity = $identifier;
81 6
        }
82
83
        foreach ($rules as $ruleData) {
84 6
            // There is no rule apply.
85
            if (!is_array($ruleData)) {
86 6
                return $ruleData;
87 1
            }
88
89
            foreach ($ruleData as $rule => $ruleOptions) {
90 6
                $value = $this->applyRule($rule, $ruleOptions, $rowData, $transformedData, $options);
0 ignored issues
show
Bug introduced by
It seems like $rowData can also be of type string; however, parameter $rowData of Oliverde8\Component\Rule...uleApplier::applyRule() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

90
                $value = $this->applyRule($rule, $ruleOptions, /** @scrutinizer ignore-type */ $rowData, $transformedData, $options);
Loading history...
Bug introduced by
It seems like $transformedData can also be of type string; however, parameter $transformedData of Oliverde8\Component\Rule...uleApplier::applyRule() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

90
                $value = $this->applyRule($rule, $ruleOptions, $rowData, /** @scrutinizer ignore-type */ $transformedData, $options);
Loading history...
91 6
92
                if (!empty($value) || $value === 0 || $value === "0") {
93 4
                    return $value;
94 2
                }
95
            }
96
        }
97
98
        if (!empty($this->currentIdentity)) {
99 1
            $this->logger->warning("Rules were not resolved for line.", $this->currentIdentity);
100 1
        }
101
102
        return "";
103 1
    }
104
105
    /**
106
     * Apply a rule to a data set.
107
     *
108
     * @param string $rule            Code of the rule to apply.
109
     * @param array  $ruleOptions     Options to use when applying the rule
110
     * @param array  $rowData         Row that needs conversion.
111
     * @param array  $transformedData Current state of the transformed rule.
112
     * @param array  $options         Other options.
113
     *
114
     * @throws RuleException
115
     *
116
     * @return null|string
117
     * @throws UnknownRuleException
118
     */
119
    protected function applyRule(string $rule, array $ruleOptions, array $rowData, array $transformedData, array $options)
120 6
    {
121
        if (!isset($this->rules[$rule])) {
122 6
            throw new UnknownRuleException("Rule '$rule' was not found!");
123 1
        }
124
        $ruleObject = $this->rules[$rule];
125 5
126
        $options = array_merge($options, $ruleOptions);
127 5
128
        if ($this->validate) {
129 5
            try {
130
                $ruleObject->validate($options);
131 5
            } catch (RuleException $ruleException) {
132 1
                $this->logger->error(
133 1
                    "An exception accured when executing rules!",
134 1
                    array_merge(
135 1
                        $this->currentIdentity,
136 1
                        ['message' => $ruleException->getMessage()]
137 1
                    )
138
                );
139
                throw $ruleException;
140 1
            }
141
        }
142
143
        $ruleObject->setApplier($this);
144 4
        return $ruleObject->apply($rowData, $transformedData, $options);
145
    }
146
}