Passed
Push — master ( 980804...08b834 )
by Mihail
09:48
created

env()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 7

Importance

Changes 0
Metric Value
eloc 10
c 0
b 0
f 0
dl 0
loc 18
ccs 1
cts 1
cp 1
rs 8.8333
cc 7
nc 6
nop 3
crap 7
1
<?php
2
3
/*
4
 * This file is part of the Koded package.
5
 *
6
 * (c) Mihail Binev <[email protected]>
7
 *
8
 * Please view the LICENSE distributed with this source code
9
 * for the full copyright and license information.
10
*/
11
12
namespace Koded\Stdlib;
13
14
use DateTimeImmutable;
15
use FilesystemIterator;
16
use JsonException;
17
use Koded\Stdlib\Serializer\{JsonSerializer, XmlSerializer};
18
use RecursiveDirectoryIterator;
19
use RecursiveIteratorIterator;
20
21
/**
22
 * Creates a new Arguments instance
23
 * with optional arbitrary number of arguments.
24
 *
25
 * @param array ...$values
26
 *
27
 * @return Argument
28
 */
29
function arguments(...$values): Argument
30
{
31
    return new Arguments(...$values);
0 ignored issues
show
Bug introduced by
$values is expanded, but the parameter $values of Koded\Stdlib\Arguments::__construct() does not expect variable arguments. ( Ignorable by Annotation )

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

31
    return new Arguments(/** @scrutinizer ignore-type */ ...$values);
Loading history...
32 1
}
33
34
/**
35
 * Creates a new Data instance (Immutable)
36
 * with optional arbitrary number of arguments.
37
 *
38
 * @param array ...$values
39
 *
40
 * @return Data
41
 */
42
function value(...$values): Data
43
{
44
    return new Immutable(...$values);
0 ignored issues
show
Bug introduced by
$values is expanded, but the parameter $values of Koded\Stdlib\Immutable::__construct() does not expect variable arguments. ( Ignorable by Annotation )

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

44
    return new Immutable(/** @scrutinizer ignore-type */ ...$values);
Loading history...
45 1
}
46
47
/**
48
 * Gets or sets environment variables.
49
 *
50
 * @param string [optional] $name The name of the env variable
51
 * @param mixed [optional]  $default Default value if not set
52
 * @param array [optional]  $initialState To set all variables at once
53
 * @return mixed The value for the env variable,
54
 *               or all variables if $name is not provided
55
 */
56
function env(
57
    string $name = null,
58
    mixed $default = null,
59 1
    array $initialState = null): mixed
60
{
61
    static $state = [];
62
    if (null !== $initialState) {
63
        foreach ($initialState as $k => $v) {
64
            null === $v || \putenv($k . '=' . $v);
65
        }
66
        return $state = $initialState;
67
    }
68
    if (null === $name) {
69
        return $state;
70
    }
71
    return \array_key_exists($name, $state)
72
        ? $state[$name]
73
        : (\getenv($name) ?: $default);
74
}
75
76
/**
77 5
 * HTML encodes a string.
78 5
 * Useful for escaping the input values in HTML templates.
79 5
 *
80
 * @param string $input    The input string
81
 * @param string $encoding The encoding
82 5
 *
83
 * @return string
84
 */
85
function htmlencode(string $input, string $encoding = 'UTF-8'): string
86
{
87
    return \htmlentities($input, ENT_QUOTES | ENT_HTML5, $encoding);
88
}
89
90
/**
91
 * Creates a random generated string with optional prefix and/or suffix.
92
 *
93
 * NOTE: DO NOT use it for passwords or any data that requires cryptographic secureness!
94 10
 *
95 10
 * @param int    $length [optional]
96
 * @param string $prefix [optional]
97
 * @param string $suffix [optional]
98
 *
99
 * @return string
100
 * @throws \Exception if it was not possible to gather sufficient entropy
101
 * @since 1.10.0
102
 */
103
function randomstring(
104
    int $length = 16,
105
    string $prefix = '',
106
    string $suffix = ''): string
107 5
{
108 5
    $buffer = '';
109
    for ($x = 0; $x < $length; ++$x) {
110
        $buffer .= '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'[\random_int(0, 61)];
111
    }
112
    return $prefix . $buffer . $suffix;
113
}
114
115
/**
116
 * Transforms the simple snake_case string into CamelCaseName.
117
 *
118
 * @param string $string
119
 *
120
 * @return string Camel-cased string
121 3
 */
122 3
function snake_to_camel_case(string $string): string
123
{
124
    $string = \preg_replace('/[\W\_]++/', ' ', $string);
125
    return \str_replace(' ', '', \ucwords($string));
126
}
127
128
/**
129
 * Transforms simple CamelCaseName into camel_case_name (lower case underscored).
130
 *
131
 * @param string $string CamelCase string to be underscored
132
 *
133
 * @return string Transformed string (for weird strings, you get what you deserve)
134 1
 */
135
function camel_to_snake_case(string $string): string
136
{
137
    $string = snake_to_camel_case($string);
138
    return \strtolower(\preg_replace('/(?<=\\w)([A-Z])/', '_\\1', \trim($string)));
139
}
140
141
/**
142
 * Converts the string with desired delimiter character.
143
 *
144
 * @param string $string
145
 * @param int    $delimiter chr() of the delimiter character
146
 *
147
 * @return string The converted string with the provided delimiter
148 10
 */
149 1
function to_delimited_string(string $string, int $delimiter): string
150 1
{
151
    $str = \preg_split('~[^\p{L}\p{N}\']+~u', \trim($string));
152
    return \join(\chr($delimiter), $str);
153 9
}
154
155
/**
156
 * Converts the string to-kebab-case
157
 *
158
 * @param string $string
159
 *
160
 * @return string
161
 */
162
function to_kebab_string(string $string): string
163
{
164
    return \strtolower(to_delimited_string($string, \ord('-')));
165 5
}
166
167 5
/**
168 2
 * Returns the JSON representation of a value.
169 2
 *
170
 * @param mixed $value   The data to be serialized
171
 * @param int   $options [optional] JSON bitmask options for JSON encoding.
172 3
 *                       Warning: uses {@JsonSerializer::OPTIONS} as defaults;
173
 *                       instead of adding, it may remove the option (if set in OPTIONS)
174
 *
175
 * @return string JSON encoded string, or EMPTY STRING if encoding failed
176
 * @see http://php.net/manual/en/function.json-encode.php
177
 */
178
function json_serialize($value, int $options = JsonSerializer::OPTIONS): string
179
{
180
    try {
181
        return \json_encode($value, $options);
182
    } catch (JsonException $e) {
183
        error_log(__FUNCTION__, $e->getMessage(), $value);
184
        return '';
185
    }
186
}
187
188
/**
189
 * Decodes a JSON string into appropriate PHP type.
190
 *
191
 * @param string $json        A JSON string
192
 * @param bool   $associative When TRUE, returned objects will be
193
 *                            converted into associative arrays
194
 *
195
 * @return mixed The decoded value, or EMPTY STRING on error
196
 */
197
function json_unserialize(string $json, bool $associative = false): mixed
198
{
199
    try {
200
        return \json_decode($json, $associative, 512,
201 1
                            JSON_OBJECT_AS_ARRAY
202
                            | JSON_BIGINT_AS_STRING
203
                            | JSON_THROW_ON_ERROR);
204
    } catch (JsonException $e) {
205
        error_log(__FUNCTION__, $e->getMessage(), $json);
206
        return '';
207
    }
208
}
209
210
/**
211
 * Serializes the data into XML document.
212
 *
213 3
 * @param string   $root The XML document root name
214 3
 * @param iterable $data The data to be encoded
215
 *
216
 * @return string XML document
217
 */
218
function xml_serialize(string $root, iterable $data): string
219
{
220
    return (new XmlSerializer($root))->serialize($data);
221
}
222
223
/**
224
 * Unserialize an XML document into PHP array.
225
 * This function does not deal with magical conversions
226
 * of complicated XML structures.
227
 *
228
 * @param string $xml The XML document to be decoded into array
229
 *
230
 * @return array Decoded version of the XML string,
231
 *               or empty array on malformed XML
232
 */
233 25
function xml_unserialize(string $xml): array
234
{
235
    return (new XmlSerializer(null))->unserialize($xml) ?: [];
236
}
237
238
/**
239
 * Send a formatted error message to PHP's system logger.
240
 *
241
 * @param string $func    The function name where error occurred
242
 * @param string $message The error message
243 1
 * @param mixed  $data    Original data passed into function
244
 */
245
function error_log(string $func, string $message, mixed $data): void
246
{
247
    \error_log(\sprintf("(%s) %s:\n%s", $func, $message, \var_export($data, true)));
248
}
249
250
/**
251
 * Checks if the array is an associative array.
252
 *
253
 * Simple rules:
254
 *
255 1
 * - If all keys are sequential starting from 0..n, it is not an associative array
256
 * - empty array is not associative
257
 *
258 1
 * Unfortunately, the internal typecast to integer on the keys makes
259 1
 * the sane programming an ugly Array Oriented Programming hackery.
260 1
 *
261
 * @param array $array
262
 *
263 1
 * @return bool
264
 */
265
function is_associative(array $array): bool
266
{
267
    return (bool)\array_diff_assoc($array, \array_values($array));
268
}
269
270
/**
271
 * Gets an instance of DateTimeImmutable in UTC.
272
 *
273
 * @return DateTimeImmutable
274
 */
275
function now(): DateTimeImmutable
276
{
277
    return \date_create_immutable('now', \timezone_open('UTC'));
278
}
279
280
/**
281
 * Removes a directory.
282
 *
283
 * @param string $dirname The folder name
284
 *
285
 * @return bool TRUE on success, FALSE otherwise
286
 */
287
function rmdir(string $dirname): bool
288
{
289
    $deleted = [];
290
291
    /** @var \SplFileInfo $path */
292
    foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dirname, FilesystemIterator::SKIP_DOTS),
293
        RecursiveIteratorIterator::CHILD_FIRST) as $path) {
294
        $deleted[] = ($path->isDir() && false === $path->isLink())
295
            ? \rmdir($path->getPathname())
296
            : \unlink($path->getPathname());
297
    }
298
    return (bool)\array_product($deleted);
299
}
300