1<?php
2
3/**
4 * compatibility functions
5 *
6 * This file contains a few functions that might be missing from the PHP build
7 */
8
9if (!function_exists('ctype_space')) {
10    /**
11     * Check for whitespace character(s)
12     *
13     * @param string $text
14     * @return bool
15     * @see ctype_space
16     */
17    function ctype_space($text)
18    {
19        if (!is_string($text)) return false; #FIXME original treats between -128 and 255 inclusive as ASCII chars
20        if (trim($text) === '') return true;
21        return false;
22    }
23}
24
25if (!function_exists('ctype_digit')) {
26    /**
27     * Check for numeric character(s)
28     *
29     * @param string $text
30     * @return bool
31     * @see ctype_digit
32     */
33    function ctype_digit($text)
34    {
35        if (!is_string($text)) return false; #FIXME original treats between -128 and 255 inclusive as ASCII chars
36        if (preg_match('/^\d+$/', $text)) return true;
37        return false;
38    }
39}
40
41if (!function_exists('gzopen') && function_exists('gzopen64')) {
42    /**
43     * work around for PHP compiled against certain zlib versions #865
44     *
45     * @link http://stackoverflow.com/questions/23417519/php-zlib-gzopen-not-exists
46     *
47     * @param string $filename
48     * @param string $mode
49     * @param int $use_include_path
50     * @return mixed
51     */
52    function gzopen($filename, $mode, $use_include_path = 0)
53    {
54        return gzopen64($filename, $mode, $use_include_path);
55    }
56}
57
58if (!function_exists('gzseek') && function_exists('gzseek64')) {
59    /**
60     * work around for PHP compiled against certain zlib versions #865
61     *
62     * @link http://stackoverflow.com/questions/23417519/php-zlib-gzopen-not-exists
63     *
64     * @param resource $zp
65     * @param int $offset
66     * @param int $whence
67     * @return int
68     */
69    function gzseek($zp, $offset, $whence = SEEK_SET)
70    {
71        return gzseek64($zp, $offset, $whence);
72    }
73}
74
75if (!function_exists('gztell') && function_exists('gztell64')) {
76    /**
77     * work around for PHP compiled against certain zlib versions #865
78     *
79     * @link   http://stackoverflow.com/questions/23417519/php-zlib-gzopen-not-exists
80     *
81     * @param resource $zp
82     * @return int
83     */
84    function gztell($zp)
85    {
86        return gztell64($zp);
87    }
88}
89
90/**
91 * polyfill for PHP < 8
92 * @see https://www.php.net/manual/en/function.str-starts-with
93 */
94if (!function_exists('str_starts_with')) {
95    function str_starts_with(?string $haystack, ?string $needle)
96    {
97        return 0 === strncmp($haystack, $needle, \strlen($needle));
98    }
99}
100
101/**
102 * polyfill for PHP < 8
103 * @see https://www.php.net/manual/en/function.str-contains
104 */
105if (!function_exists('str_contains')) {
106    function str_contains(?string $haystack, ?string $needle)
107    {
108        return '' === $needle || false !== strpos($haystack, (string) $needle);
109    }
110}
111
112/**
113 * polyfill for PHP < 8
114 * @see https://www.php.net/manual/en/function.str-ends-with
115 */
116if (!function_exists('str_ends_with')) {
117    function str_ends_with(?string $haystack, ?string $needle)
118    {
119        if ('' === $needle || $needle === $haystack) {
120            return true;
121        }
122
123        if ('' === $haystack) {
124            return false;
125        }
126
127        $needleLength = \strlen($needle);
128
129        return $needleLength <= \strlen($haystack) && 0 === substr_compare($haystack, $needle, -$needleLength);
130    }
131}
132
133/**
134 * polyfill for PHP < 8.1
135 * @see https://www.php.net/manual/en/function.array-is-list
136 */
137if (!function_exists('array_is_list')) {
138    function array_is_list(array $arr)
139    {
140        if ($arr === []) {
141            return true;
142        }
143        return array_keys($arr) === range(0, count($arr) - 1);
144    }
145}
146