diff --git a/lib/cli/cli.php b/lib/cli/cli.php index 5fe2604..f449727 100755 --- a/lib/cli/cli.php +++ b/lib/cli/cli.php @@ -153,13 +153,45 @@ function menu( $items, $default = null, $title = 'Choose an item' ) { } /** - * An encoding-safe way of getting string length. + * Attempts an encoding-safe way of getting string length. If mb_string extensions aren't + * installed, falls back to basic strlen if no encoding is present * * @param string The string to check * @return int Numeric value that represents the string's length */ function safe_strlen( $str ) { - return mb_strlen( $str, mb_detect_encoding( $str ) ); + if ( function_exists( 'mb_strlen' ) ) { + $length = mb_strlen( $str, mb_detect_encoding( $str ) ); + } else { + // iconv will return PHP notice if non-ascii characters are present in input string + $str = iconv( 'ASCII' , 'ASCII', $str ); + + $length = strlen( $str ); + } + + return $length; +} + +/** + * Attempts an encoding-safe way of getting a substring. If mb_string extensions aren't + * installed, falls back to ascii substring if no encoding is present + * + * @param string $str The input string + * @param int $start The starting position of the substring + * @param boolean $length Maximum length of the substring + * @return string Substring of string specified by start and length parameters + */ +function safe_substr( $str, $start, $length = false ) { + if ( function_exists( 'mb_substr' ) ) { + $substr = mb_substr( $str, $start, $length, mb_detect_encoding( $str ) ); + } else { + // iconv will return PHP notice if non-ascii characters are present in input string + $str = iconv( 'ASCII' , 'ASCII', $str ); + + $substr = substr( $str, $start, $length ); + } + + return $substr; } /** diff --git a/lib/cli/table/Ascii.php b/lib/cli/table/Ascii.php index 2270a5d..faf2278 100644 --- a/lib/cli/table/Ascii.php +++ b/lib/cli/table/Ascii.php @@ -132,15 +132,15 @@ public function row( array $row ) { $col_width = $this->_widths[ $col ]; $original_val_width = Colors::length( $value ); if ( $original_val_width > $col_width ) { - $row[ $col ] = mb_substr( $value, 0, $col_width, mb_detect_encoding( $value ) ); - $value = mb_substr( $value, $col_width, $original_val_width, mb_detect_encoding( $value ) ); + $row[ $col ] = \cli\safe_substr( $value, 0, $col_width ); + $value = \cli\safe_substr( $value, $col_width, $original_val_width ); $i = 0; do { - $extra_value = mb_substr( $value, 0, $col_width, mb_detect_encoding( $value ) ); - $val_width = mb_strlen( $extra_value, mb_detect_encoding( $extra_value ) ); + $extra_value = \cli\safe_substr( $value, 0, $col_width ); + $val_width = \cli\safe_strlen( $extra_value ); if ( $val_width ) { $extra_rows[ $col ][] = $extra_value; - $value = mb_substr( $value, $col_width, $original_val_width, mb_detect_encoding( $value ) ); + $value = \cli\safe_substr( $value, $col_width, $original_val_width ); $i++; if ( $i > $extra_row_count ) { $extra_row_count = $i; diff --git a/tests/test-cli.php b/tests/test-cli.php index 36b823f..06540f3 100644 --- a/tests/test-cli.php +++ b/tests/test-cli.php @@ -24,6 +24,13 @@ function test_encoded_string_length() { } + function test_encoded_substr() { + + $this->assertEquals( \cli\safe_substr( \cli\Colors::pad( 'hello', 6), 0, 2 ), 'he' ); + $this->assertEquals( \cli\safe_substr( \cli\Colors::pad( 'óra', 6), 0, 2 ), 'ór' ); + + } + function test_colorized_string_length() { $this->assertEquals( \cli\Colors::length( \cli\Colors::colorize( '%Gx%n', true ) ), 1 ); }