friendship ended with social-app. php is my new best friend
1<?php
2
3/**
4 * This file is part of the Nette Framework (https://nette.org)
5 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6 */
7
8declare(strict_types=1);
9
10namespace Nette\Utils;
11
12use Nette;
13use function array_unique, ini_get, levenshtein, max, min, ob_end_clean, ob_get_clean, ob_start, preg_replace, strlen;
14use const PHP_OS_FAMILY;
15
16
17class Helpers
18{
19 public const IsWindows = PHP_OS_FAMILY === 'Windows';
20
21
22 /**
23 * Executes a callback and returns the captured output as a string.
24 */
25 public static function capture(callable $func): string
26 {
27 ob_start(fn() => '');
28 try {
29 $func();
30 return ob_get_clean();
31 } catch (\Throwable $e) {
32 ob_end_clean();
33 throw $e;
34 }
35 }
36
37
38 /**
39 * Returns the last occurred PHP error or an empty string if no error occurred. Unlike error_get_last(),
40 * it is nit affected by the PHP directive html_errors and always returns text, not HTML.
41 */
42 public static function getLastError(): string
43 {
44 $message = error_get_last()['message'] ?? '';
45 $message = ini_get('html_errors') ? Html::htmlToText($message) : $message;
46 $message = preg_replace('#^\w+\(.*?\): #', '', $message);
47 return $message;
48 }
49
50
51 /**
52 * Converts false to null, does not change other values.
53 */
54 public static function falseToNull(mixed $value): mixed
55 {
56 return $value === false ? null : $value;
57 }
58
59
60 /**
61 * Returns value clamped to the inclusive range of min and max.
62 */
63 public static function clamp(int|float $value, int|float $min, int|float $max): int|float
64 {
65 if ($min > $max) {
66 throw new Nette\InvalidArgumentException("Minimum ($min) is not less than maximum ($max).");
67 }
68
69 return min(max($value, $min), $max);
70 }
71
72
73 /**
74 * Looks for a string from possibilities that is most similar to value, but not the same (for 8-bit encoding).
75 * @param string[] $possibilities
76 */
77 public static function getSuggestion(array $possibilities, string $value): ?string
78 {
79 $best = null;
80 $min = (strlen($value) / 4 + 1) * 10 + .1;
81 foreach (array_unique($possibilities) as $item) {
82 if ($item !== $value && ($len = levenshtein($item, $value, 10, 11, 10)) < $min) {
83 $min = $len;
84 $best = $item;
85 }
86 }
87
88 return $best;
89 }
90
91
92 /**
93 * Compares two values in the same way that PHP does. Recognizes operators: >, >=, <, <=, =, ==, ===, !=, !==, <>
94 */
95 public static function compare(mixed $left, string $operator, mixed $right): bool
96 {
97 return match ($operator) {
98 '>' => $left > $right,
99 '>=' => $left >= $right,
100 '<' => $left < $right,
101 '<=' => $left <= $right,
102 '=', '==' => $left == $right,
103 '===' => $left === $right,
104 '!=', '<>' => $left != $right,
105 '!==' => $left !== $right,
106 default => throw new Nette\InvalidArgumentException("Unknown operator '$operator'"),
107 };
108 }
109}