Completed
Push — master ( 62f537...55f32a )
by Alberto
02:16
created

Parser::normalize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
/**
3
 * This file is part of Chirp package
4
 *
5
 * Copyright (c) 2015 Alberto Pagliarini
6
 *
7
 * Licensed under the MIT license
8
 * https://github.com/batopa/chirp/blob/master/LICENSE
9
 */
10
namespace Bato\Chirp\Utility;
11
12
class Parser
13
{
14
    /**
15
     * Normalize a string trimming trailing '/'
16
     * and replacing remained '/' with '-'
17
     *
18
     * Example:
19
     * - ///first//second///// => first-second
20
     *
21
     * @param string $name the string to normalize
22
     * @return string
23
     */
24
    public static function normalize($name)
25
    {
26
        $name = trim($name, '/');
27
        return preg_replace('/\/+/', '-', $name);
28
    }
29
30
    /**
31
     * Match $data returning false if $conditions are not sotisfied.
32
     * Return true if all conditions are met
33
     *
34
     * @param array $data an array of data
35
     * @param array $conditions an array if filter vars
36
     * @return bool
37
     */
38
    public static function match(array $data, array $conditions = array())
39
    {
40
        $default = [
41
            'require' => [],
42
            'grep' => []
43
        ];
44
        $conditions = array_intersect_key($conditions, $default) + $default;
45
46
        foreach ($conditions as $key => $value) {
47
            $method = 'match' . ucfirst($key);
48
            if (!self::{$method}($data, $conditions[$key])) {
49
                return false;
50
            }
51
        }
52
53
        return true;
54
    }
55
56
    /**
57
     * Match require
58
     * Check if $data contains all required keys with not empty values.
59
     * It returns false if some reuired keys is missing
60
     *
61
     * @param array $data an array of data
62
     * @param array $require an array if required keys
63
     * @return bool
64
     */
65
    protected static function matchRequire(array $data, array $require = array())
66
    {
67
        foreach ($require as $name) {
68
            if (!self::hasKey($data, $name)) {
69
                return false;
70
            }
71
        }
72
        return true;
73
    }
74
75
    /**
76
     * Check if a key is present in array and it's value is not empty or match $matchValue value
77
     * $key can be a point separated string to traversing the array
78
     *
79
     * Examples:
80
     *
81
     * ```
82
     * $data = [
83
     *     'name1' => [
84
     *          'name2' => 'value',
85
     *          'name3' => null
86
     *     ]
87
     * ];
88
     *
89
     * Parser::hasKey($data, 'name1'); // return true
90
     * Parser::hasKey($data, 'name1.name2'); // return true
91
     * Parser::hasKey($data, 'name2'); // return false
92
     * Parser::hasKey($data, 'name1.name3'); // return false
93
     * Parser::hasKey($data', name1.name4'); // return false
94
     * Parser::hasKey($data, 'name1.name2', '/alu/'); // return true
95
     * Parser::hasKey($data, 'name1.name2', '/^alu/'); // return false
96
     * ```
97
     * @param array $data an array to check
98
     * @param string $key the key name
99
     * @param string $matchPattern a regexp used to match value
0 ignored issues
show
Documentation introduced by
Should the type for parameter $matchPattern not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
100
     * @return bool
101
     */
102
    public static function hasKey(array $data, $key, $matchPattern = null)
103
    {
104
        $keys = array_filter(explode('.', $key));
105
        foreach ($keys as $k => $n) {
106
            if (empty($data[$n])) {
107
                return false;
108
            }
109
            if (array_key_exists($k + 1, $keys)) {
110
                $data = $data[$n];
111
            } elseif (is_string($matchPattern) && !preg_match($matchPattern, $data[$n])) {
112
                return false;
113
            }
114
        }
115
        return true;
116
    }
117
118
    /**
119
     * Match grep
120
     * Check if $grep keys exist in $data and their value match $grep values
121
     * $grep is an array as
122
     *
123
     * ```
124
     * [
125
     *     'grep_key' => 'grep_value',
126
     *     'grep_key2.grep_key3' => 'grep_value2'
127
     * ]
128
     * ```
129
     *
130
     * @param array $data an array of data
131
     * @param array $grep
132
     * @return bool
133
     */
134
    protected static function matchGrep(array $data, array $grep = array())
135
    {
136
        if (empty($grep)) {
137
            return true;
138
        }
139
140
        foreach ($grep as $key => $value) {
141
            $matchPattern = self::grepPattern($value);
142
            if (!self::hasKey($data, $key, $matchPattern)) {
143
                return false;
144
            }
145
        }
146
        return true;
147
    }
148
149
    /**
150
     * Given a string or an array of string
151
     * it builds the regexp pattern to use in self::matchGrep()
152
     *
153
     * Example:
154
     * ```
155
     * $data = ['one', 'two', 'three'];
156
     * ```
157
     * will produce the pattern `/((^|\s|\W)one\b)|((^|\s|\W)two\b)|((^|\s|\W)three\b)/i`
158
     *
159
     * @param array|string $data
160
     * @return string
161
     */
162
    private static function grepPattern($data)
163
    {
164
        $stringPattern = '((^|\s|\W)%s\b)';
165
        $multipleStringPattern = '%s|%s';
166
        $globalPattern = '/%s/i';
167
        if (!is_array($data)) {
168
            $data = sprintf($stringPattern, $data);
169
            return sprintf($globalPattern, $data);
170
        }
171
172
        $result = '';
173
        foreach ($data as $string) {
174
            $string = sprintf($stringPattern, $string);
175
            if (empty($result)) {
176
                $result = $string;
177
            } else {
178
                $result = sprintf($multipleStringPattern, $result, $string);
179
            }
180
        }
181
        return sprintf($globalPattern, $result);
182
    }
183
}
184