Completed
Pull Request — master (#2066)
by
unknown
03:04
created

functions-compat.php ➔ yourls_mb_substr()   C

Complexity

Conditions 8
Paths 10

Size

Total Lines 36
Code Lines 17

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 8
eloc 17
nc 10
nop 4
dl 0
loc 36
rs 5.3846
1
<?php
2
/*
3
 * YOURLS
4
 * Compatibility functions when either missing from older PHP versions or not included by default
5
 */
6
7
/**
8
 * @codeCoverageIgnore
9
 */
10
 
11
/**
12
 * json_encode for PHP, should someone run a distro without php-json -- see http://askubuntu.com/questions/361424/
13
 *
14
 */
15
if( !function_exists( 'json_encode' ) ) {
16
	function json_encode( $array ) {
17
		return yourls_array_to_json( $array );
18
	}
19
}
20
21
/**
22
 * Converts an associative array of arbitrary depth and dimension into JSON representation. Used for compatibility with older PHP builds.
23
 *
24
 * @param array $array the array to convert.
25
 * @return mixed The resulting JSON string, or false if the argument was not an array.
26
 * @author Andy Rusterholz
27
 * @link http://php.net/json_encode (see comments)
28
 */
29
function yourls_array_to_json( $array ){
30
31
	if( !is_array( $array ) ){
32
		return false;
33
	}
34
35
	$associative = count( array_diff( array_keys($array), array_keys( array_keys( $array )) ));
36
	if( $associative ){
37
38
		$construct = array();
39
		foreach( $array as $key => $value ){
40
41
			// We first copy each key/value pair into a staging array,
42
			// formatting each key and value properly as we go.
43
44
			// Format the key:
45
			if( is_numeric( $key ) ){
46
				$key = "key_$key";
47
			}
48
			$key = '"'.addslashes( $key ).'"';
49
50
			// Format the value:
51 View Code Duplication
			if( is_array( $value )){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
52
				$value = yourls_array_to_json( $value );
53
			} else if( !is_numeric( $value ) || is_string( $value ) ){
54
				$value = '"'.addslashes( $value ).'"';
55
			}
56
57
			// Add to staging array:
58
			$construct[] = "$key: $value";
59
		}
60
61
		// Then we collapse the staging array into the JSON form:
62
		$result = "{ " . implode( ", ", $construct ) . " }";
63
64
	} else { // If the array is a vector (not associative):
65
66
		$construct = array();
67
		foreach( $array as $value ){
68
69
			// Format the value:
70 View Code Duplication
			if( is_array( $value )){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
71
				$value = yourls_array_to_json( $value );
72
			} else if( !is_numeric( $value ) || is_string( $value ) ){
73
				$value = '"'.addslashes($value).'"';
74
			}
75
76
			// Add to staging array:
77
			$construct[] = $value;
78
		}
79
80
		// Then we collapse the staging array into the JSON form:
81
		$result = "[ " . implode( ", ", $construct ) . " ]";
82
	}
83
84
	return $result;
85
}
86
87
88
/**
89
 * BC Math functions (assuming if one doesn't exist, none does)
90
 *
91
 */
92
if ( !function_exists( 'bcdiv' ) ) {
93
	function bcdiv( $dividend, $divisor ) {
94
		$quotient = floor( $dividend/$divisor );
95
		return $quotient;
96
	}
97
	function bcmod( $dividend, $modulo ) {
98
		$remainder = $dividend%$modulo;
99
		return $remainder;
100
	}
101
	function bcmul( $left, $right ) {
102
		return $left * $right;
103
	}
104
	function bcadd( $left, $right ) {
105
		return $left + $right;
106
	}
107
	function bcpow( $base, $power ) {
108
		return pow( $base, $power );
109
	}
110
}
111
112
113
/**
114
 * http_build_url compatibility function
115
 *
116
 * @since 1.7.1
117
 */
118
if ( !function_exists( 'http_build_url' ) ) {
119
    include YOURLS_INC . '/http_build_url/http_build_url.php';
120
}
121
122
123
/**
124
 * mb_substr compatibility function. Stolen from WP
125
 *
126
 * Only understands UTF-8 and 8bit.  All other character sets will be treated as 8bit.
127
 * For $encoding === UTF-8, the $str input is expected to be a valid UTF-8 byte sequence.
128
 * The behavior of this function for invalid inputs is undefined.
129
 *
130
 * @since 1.7.1
131
 */
132
if ( ! function_exists( 'mb_substr' ) ) :
133
    function mb_substr( $str, $start, $length = null, $encoding = null ) {
134
        return yourls_mb_substr( $str, $start, $length, $encoding );
135
    }
136
endif;
137
function yourls_mb_substr( $str, $start, $length = null, $encoding = null ) {
138
    if ( null === $encoding ) {
139
        $encoding = 'UTF-8';
140
    }
141
    // The solution below works only for UTF-8,
142
    // so in case of a different charset just use built-in substr()
143
    if ( ! in_array( $encoding, array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ) ) {
144
        return is_null( $length ) ? substr( $str, $start ) : substr( $str, $start, $length );
145
    }
146
    if ( yourls_supports_pcre_u() ) {
147
        // Use the regex unicode support to separate the UTF-8 characters into an array
148
        preg_match_all( '/./us', $str, $match );
149
        $chars = is_null( $length ) ? array_slice( $match[0], $start ) : array_slice( $match[0], $start, $length );
150
        return implode( '', $chars );
151
    }
152
    $regex = '/(
153
          [\x00-\x7F]                  # single-byte sequences   0xxxxxxx
154
        | [\xC2-\xDF][\x80-\xBF]       # double-byte sequences   110xxxxx 10xxxxxx
155
        | \xE0[\xA0-\xBF][\x80-\xBF]   # triple-byte sequences   1110xxxx 10xxxxxx * 2
156
        | [\xE1-\xEC][\x80-\xBF]{2}
157
        | \xED[\x80-\x9F][\x80-\xBF]
158
        | [\xEE-\xEF][\x80-\xBF]{2}
159
        | \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences   11110xxx 10xxxxxx * 3
160
        | [\xF1-\xF3][\x80-\xBF]{3}
161
        | \xF4[\x80-\x8F][\x80-\xBF]{2}
162
    )/x';
163
    $chars = array( '' ); // Start with 1 element instead of 0 since the first thing we do is pop
164
    do {
165
        // We had some string left over from the last round, but we counted it in that last round.
166
        array_pop( $chars );
167
        // Split by UTF-8 character, limit to 1000 characters (last array element will contain the rest of the string)
168
        $pieces = preg_split( $regex, $str, 1000, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
169
        $chars = array_merge( $chars, $pieces );
170
    } while ( count( $pieces ) > 1 && $str = array_pop( $pieces ) ); // If there's anything left over, repeat the loop.
171
    return join( '', array_slice( $chars, $start, $length ) );
172
}
173
174
/**
175
 * mb_strlen compatibility function. Stolen from WP
176
 *
177
 * Only understands UTF-8 and 8bit.  All other character sets will be treated as 8bit.
178
 * For $encoding === UTF-8, the $str input is expected to be a valid UTF-8 byte sequence.
179
 * The behavior of this function for invalid inputs is undefined.
180
 *
181
 * @since 1.7.1
182
 */
183
if ( ! function_exists( 'mb_strlen' ) ) :
184
    function mb_strlen( $str, $encoding = null ) {
185
        return yourls_mb_strlen( $str, $encoding );
186
    }
187
endif;
188
function yourls_mb_strlen( $str, $encoding = null ) {
189
    if ( null === $encoding ) {
190
        $encoding = 'UTF-8';
191
    }
192
    // The solution below works only for UTF-8,
193
    // so in case of a different charset just use built-in strlen()
194
    if ( ! in_array( $encoding, array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ) ) {
195
        return strlen( $str );
196
    }
197
    if ( yourls_supports_pcre_u() ) {
198
        // Use the regex unicode support to separate the UTF-8 characters into an array
199
        preg_match_all( '/./us', $str, $match );
200
        return count( $match[0] );
201
    }
202
    $regex = '/(?:
203
          [\x00-\x7F]                  # single-byte sequences   0xxxxxxx
204
        | [\xC2-\xDF][\x80-\xBF]       # double-byte sequences   110xxxxx 10xxxxxx
205
        | \xE0[\xA0-\xBF][\x80-\xBF]   # triple-byte sequences   1110xxxx 10xxxxxx * 2
206
        | [\xE1-\xEC][\x80-\xBF]{2}
207
        | \xED[\x80-\x9F][\x80-\xBF]
208
        | [\xEE-\xEF][\x80-\xBF]{2}
209
        | \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences   11110xxx 10xxxxxx * 3
210
        | [\xF1-\xF3][\x80-\xBF]{3}
211
        | \xF4[\x80-\x8F][\x80-\xBF]{2}
212
    )/x';
213
    $count = 1; // Start at 1 instead of 0 since the first thing we do is decrement
214
    do {
215
        // We had some string left over from the last round, but we counted it in that last round.
216
        $count--;
217
        // Split by UTF-8 character, limit to 1000 characters (last array element will contain the rest of the string)
218
        $pieces = preg_split( $regex, $str, 1000 );
219
        // Increment
220
        $count += count( $pieces );
221
    } while ( $str = array_pop( $pieces ) ); // If there's anything left over, repeat the loop.
222
    // Fencepost: preg_split() always returns one extra item in the array
223
    return --$count;
224
}
225