GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Utils   A
last analyzed

Complexity

Total Complexity 35

Size/Duplication

Total Lines 148
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 148
rs 9
wmc 35
lcom 2
cbo 1

5 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 7 1
B createLambda() 0 15 7
C createComparer() 0 29 12
B lambdaToSortFlagsAndOrder() 0 11 8
C createLambdaFromString() 0 28 7
1
<?php
2
3
/**
4
 * Utils class.
5
 * @author Alexander Prokhorov
6
 * @license Simplified BSD
7
 * @link https://github.com/Athari/YaLinqo YaLinqo on GitHub
8
 */
9
10
namespace YaLinqo;
11
12
/**
13
 * Functions for creating lambdas.
14
 * @internal
15
 * @package YaLinqo
16
 */
17
class Utils
18
{
19
    const ERROR_CLOSURE_NULL = 'closure must not be null.';
20
    const ERROR_CLOSURE_NOT_CALLABLE = 'closure must be callable';
21
    const ERROR_CANNOT_PARSE_LAMBDA = 'Failed to parse closure as lambda.';
22
23
    /** Cache for createLambdaFromString function. Functions indexed by function code and function arguments as strings. @var array */
24
    private static $lambdaCache;
25
    /** Map from comparison functions names to sort flags. Used in lambdaToSortFlagsAndOrder.  @var array */
26
    private static $compareFunctionToSortFlags = [
27
        null => SORT_REGULAR,
28
        'strcmp' => SORT_STRING,
29
        'strcasecmp' => 10 /*SORT_STRING | SORT_FLAG_CASE*/,
30
        'strcoll' => SORT_LOCALE_STRING,
31
        'strnatcmp' => SORT_NATURAL,
32
        'strnatcasecmp' => 14 /*SORT_NATURAL | SORT_FLAG_CASE*/,
33
    ];
34
35
    /**
36
     * @codeCoverageIgnore
37
     * @internal
38
     */
39
    public static function init()
40
    {
41
        self::$lambdaCache = [
42
            '$v' => [ 'v,k' => Functions::$value ],
43
            '$k' => [ 'v,k' => Functions::$key ],
44
        ];
45
    }
46
47
    /**
48
     * Convert string lambda to callable function. If callable is passed, return as is.
49
     * @param callable|null $closure
50
     * @param string $closureArgs
51
     * @param \Closure|callable|null $default
52
     * @throws \InvalidArgumentException Both closure and default are null.
53
     * @throws \InvalidArgumentException Incorrect lambda syntax.
54
     * @return callable|null
55
     */
56
    public static function createLambda($closure, string $closureArgs, $default = null)
57
    {
58
        if ($closure === null) {
59
            if ($default === null)
60
                throw new \InvalidArgumentException(self::ERROR_CLOSURE_NULL);
61
            return $default;
62
        }
63
        if ($closure instanceof \Closure)
64
            return $closure;
65
        if (is_string($closure) && ($function = self::createLambdaFromString($closure, $closureArgs)))
66
            return $function;
67
        if (is_callable($closure))
68
            return $closure;
69
        throw new \InvalidArgumentException(self::ERROR_CLOSURE_NOT_CALLABLE);
70
    }
71
72
    /**
73
     * Convert string lambda or SORT_ flags to callable function. Sets isReversed to false if descending is reversed.
74
     * @param callable|int|null $closure
75
     * @param int $sortOrder
76
     * @param bool $isReversed
77
     * @return callable|string|null
78
     * @throws \InvalidArgumentException Incorrect lambda syntax.
79
     * @throws \InvalidArgumentException Incorrect SORT_ flags.
80
     */
81
    public static function createComparer($closure, $sortOrder, &$isReversed)
82
    {
83
        if ($closure === null) {
84
            $isReversed = false;
85
            return $sortOrder === SORT_DESC ? Functions::$compareStrictReversed : Functions::$compareStrict;
86
        }
87
        elseif (is_int($closure)) {
88
            switch ($closure) {
89
                case SORT_REGULAR:
90
                    return Functions::$compareStrict;
91
                case SORT_NUMERIC:
92
                    $isReversed = false;
93
                    return $sortOrder === SORT_DESC ? Functions::$compareIntReversed : Functions::$compareInt;
94
                case SORT_STRING:
95
                    return 'strcmp';
96
                case SORT_STRING | SORT_FLAG_CASE:
97
                    return 'strcasecmp';
98
                case SORT_LOCALE_STRING:
99
                    return 'strcoll';
100
                case SORT_NATURAL:
101
                    return 'strnatcmp';
102
                case SORT_NATURAL | SORT_FLAG_CASE:
103
                    return 'strnatcasecmp';
104
                default:
105
                    throw new \InvalidArgumentException("Unexpected sort flag: {$closure}.");
106
            }
107
        }
108
        return self::createLambda($closure, 'a,b');
109
    }
110
111
    /**
112
     * Convert string lambda to SORT_ flags. Convert sortOrder from bool to SORT_ order.
113
     * @param callable|string|int|null $closure
114
     * @param int|bool $sortOrder
115
     * @return callable|string|int|null
116
     */
117
    public static function lambdaToSortFlagsAndOrder($closure, &$sortOrder)
118
    {
119
        if ($sortOrder !== SORT_ASC && $sortOrder !== SORT_DESC)
120
            $sortOrder = $sortOrder ? SORT_DESC : SORT_ASC;
121
        if (is_int($closure))
122
            return $closure;
123
        elseif (($closure === null || is_string($closure)) && isset(self::$compareFunctionToSortFlags[$closure]))
124
            return self::$compareFunctionToSortFlags[$closure];
125
        else
126
            return null;
127
    }
128
129
    /**
130
     * Convert string lambda to callable function.
131
     * @param string $closure
132
     * @param string $closureArgs
133
     * @throws \InvalidArgumentException Incorrect lambda syntax.
134
     * @return string|null
135
     */
136
    private static function createLambdaFromString(string $closure, string $closureArgs)
137
    {
138
        $posDollar = strpos($closure, '$');
139
        if ($posDollar !== false) {
140
            if (isset(self::$lambdaCache[$closure][$closureArgs]))
141
                return self::$lambdaCache[$closure][$closureArgs];
142
            $posArrow = strpos($closure, '==>', $posDollar);
143
            if ($posArrow !== false) {
144
                $args = trim(substr($closure, 0, $posArrow), "() \r\n\t");
145
                $code = substr($closure, $posArrow + 3);
146
            }
147
            else {
148
                $args = '$' . str_replace(',', '=null,$', $closureArgs) . '=null';
149
                $code = $closure;
150
            }
151
            $code = trim($code, " \r\n\t");
152
            if (strlen($code) > 0 && $code[0] != '{')
153
                $code = "return {$code};";
154
            $fun = @create_function($args, $code);
155
            // @codeCoverageIgnoreStart
156
            if (!$fun)
157
                throw new \InvalidArgumentException(self::ERROR_CANNOT_PARSE_LAMBDA);
158
            // @codeCoverageIgnoreEnd
159
            self::$lambdaCache[$closure][$closureArgs] = $fun;
160
            return $fun;
161
        }
162
        return null;
163
    }
164
}
165