Completed
Pull Request — master (#3)
by Clayton
01:09
created

Sanitizer::parseRulesArray()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.7333
c 0
b 0
f 0
cc 4
nc 4
nop 1
1
<?php
2
/**
3
 * File copied from Waavi/Sanitizer https://github.com/waavi/sanitizer
4
 * Sanitization functionality to be customized within this project before a 1.0 release.
5
 */
6
7
namespace PerfectOblivion\Valid\Sanitizer;
8
9
use Closure;
10
use Illuminate\Support\Arr;
11
use InvalidArgumentException;
12
use PerfectOblivion\Valid\Sanitizer\Filters;
13
use Illuminate\Validation\ValidationRuleParser;
14
15
class Sanitizer
16
{
17
    /** @var array */
18
    protected $data;
19
20
    /** @var array */
21
    protected $rules;
22
23
    /** @var array */
24
    protected $filters = [
25
        'capitalize'  => Filters\Capitalize::class,
26
        'cast'        => Filters\Cast::class,
27
        'escape'      => Filters\EscapeHTML::class,
28
        'format_date' => Filters\FormatDate::class,
29
        'lowercase'   => Filters\Lowercase::class,
30
        'uppercase'   => Filters\Uppercase::class,
31
        'trim'        => Filters\Trim::class,
32
        'strip_tags'  => Filters\StripTags::class,
33
        'digit'       => Filters\Digit::class,
34
    ];
35
36
    /**
37
     * Create a new sanitizer instance.
38
     *
39
     * @param  array  $data
40
     * @param  array  $rules      Rules to be applied to each data attribute
41
     * @param  array  $filters    Available filters for this sanitizer
0 ignored issues
show
Documentation introduced by
There is no parameter named $filters. Did you maybe mean $customFilters?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
42
     */
43
    public function __construct(array $data, array $rules, array $customFilters = [])
44
    {
45
        $this->data    = $data;
46
        $this->rules   = $this->parseRulesArray($rules);
47
        $this->filters = array_merge($this->filters, $customFilters);
48
    }
49
50
    /**
51
     * Parse a rules array.
52
     *
53
     * @param  array $rules
54
     *
55
     * @return array
56
     */
57
    protected function parseRulesArray(array $rules)
58
    {
59
        $parsedRules = [];
60
        $rawRules = (new ValidationRuleParser($this->data))->explode($rules);
61
62
        foreach ($rawRules->rules as $attribute => $attributeRules) {
63
            foreach ($attributeRules as $attributeRule) {
64
                $parsedRule = $this->parseRuleString($attributeRule);
65
                if ($parsedRule) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parsedRule of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
66
                    $parsedRules[$attribute][] = $parsedRule;
67
                }
68
            }
69
        }
70
71
        return $parsedRules;
72
    }
73
74
    /**
75
     * Parse a rule string formatted as filterName:option1, option2 into an array formatted as [name => filterName, options => [option1, option2]]
76
     *
77
     * @param  string  $rule    Formatted as 'filterName:option1, option2' or just 'filterName'
78
     *
79
     * @return array
80
     */
81
    protected function parseRuleString($rule)
82
    {
83
        if (strpos($rule, ':') !== false) {
84
            list($name, $options) = explode(':', $rule, 2);
85
            $options              = array_map('trim', explode(',', $options));
86
        } else {
87
            $name    = $rule;
88
            $options = [];
89
        }
90
91
        if (! $name) {
92
            return [];
93
        }
94
95
        return compact('name', 'options');
96
    }
97
98
    /**
99
     * Apply the given filter by its name
100
     *
101
     * @param  mixed  $name
102
     *
103
     * @return Filter
104
     */
105
    protected function applyFilter($name, $value, $options = [])
106
    {
107
        // If the filter does not exist, throw an Exception:
108
        if (! isset($this->filters[$name])) {
109
            throw new InvalidArgumentException("No filter found by the name of $name");
110
        }
111
112
        $filter = $this->filters[$name];
113
114
        if ($filter instanceof Closure) {
115
            return call_user_func_array($filter, [$value, $options]);
116
        } else {
117
            $filter = new $filter;
118
119
            return $filter->apply($value, $options);
120
        }
121
    }
122
123
    /**
124
     * Sanitize the given data
125
     *
126
     * @return array
127
     */
128
    public function sanitize()
129
    {
130
        $sanitized = $this->data;
131
132
        foreach ($this->rules as $attr => $rules) {
133
            if (Arr::has($this->data, $attr)) {
134
                $value = Arr::get($this->data, $attr);
135
                foreach ($rules as $rule) {
136
                    $value = $this->applyFilter($rule['name'], $value, $rule['options']);
137
                }
138
                Arr::set($sanitized, $attr, $value);
139
            }
140
        }
141
142
        return $sanitized;
143
    }
144
145
    /**
146
     * Sanitize the given attribute
147
     *
148
     * @param  string  $attribute  Attribute name
149
     * @param  mixed  $value      Attribute value
150
     *
151
     * @return mixed   Sanitized value
152
     */
153
    protected function sanitizeAttribute($attribute, $value)
154
    {
155
        if (isset($this->rules[$attribute])) {
156
            foreach ($this->rules[$attribute] as $rule) {
157
                $value = $this->applyFilter($rule['name'], $value, $rule['options']);
158
            }
159
        }
160
161
        return $value;
162
    }
163
}
164