Skip to content

Commit 2668466

Browse files
committed
Level 7
1 parent 4fd98bf commit 2668466

File tree

11 files changed

+59
-30
lines changed

11 files changed

+59
-30
lines changed

lib/cli/Arguments.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,11 @@ public function getHelpScreen() {
9191
* @return string
9292
*/
9393
public function asJSON() {
94-
return json_encode($this->_parsed);
94+
$json = json_encode( $this->_parsed );
95+
if ( false === $json ) {
96+
throw new \RuntimeException( 'Failed to encode arguments as JSON' );
97+
}
98+
return $json;
9599
}
96100

97101
/**

lib/cli/Colors.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,10 @@ static public function wrapPreColorized( $string, $width, $encoding = false ) {
340340
// Split the string into parts: ANSI codes and text
341341
$parts = preg_split( $ansi_pattern, $string, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
342342

343+
if ( false === $parts ) {
344+
$parts = array( $string );
345+
}
346+
343347
foreach ( $parts as $part ) {
344348
// Check if this part is an ANSI code
345349
if ( preg_match( $ansi_pattern, $part ) ) {
@@ -361,6 +365,7 @@ static public function wrapPreColorized( $string, $width, $encoding = false ) {
361365

362366
while ( $offset < $text_length ) {
363367
$char = \cli\safe_substr( $part, $offset, 1, false, $encoding );
368+
assert( is_string( $char ) );
364369
$char_width = \cli\strwidth( $char, $encoding );
365370

366371
// Check if adding this character would exceed the width

lib/cli/Memoize.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ public function __get($name) {
3636
return ($this->_memoCache[$name] = null);
3737
}
3838

39-
$method = array($this, $name);
40-
($this->_memoCache[$name] = call_user_func($method));
39+
($this->_memoCache[$name] = $this->$name());
4140
return $this->_memoCache[$name];
4241
}
4342

lib/cli/Notify.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public function speed() {
121121
$this->_speed = ($this->_current / $this->_iteration) / $span;
122122
}
123123

124-
return $this->_speed;
124+
return (int) $this->_speed;
125125
}
126126

127127
/**

lib/cli/Shell.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ static public function columns() {
5050
}
5151
} else {
5252
$size = exec( '/usr/bin/env stty size 2>/dev/null' );
53-
if ( '' !== $size && preg_match( '/[0-9]+ ([0-9]+)/', $size, $matches ) ) {
53+
if ( $size && preg_match( '/[0-9]+ ([0-9]+)/', $size, $matches ) ) {
5454
$columns = (int) $matches[1];
5555
}
5656
if ( ! $columns ) {

lib/cli/Streams.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ class Streams {
1919
* @return mixed
2020
*/
2121
static function _call( $func, $args ) {
22-
$method = __CLASS__ . '::' . $func;
22+
$method = array( __CLASS__, $func );
23+
assert( is_callable( $method ) );
2324
return call_user_func_array( $method, $args );
2425
}
2526

@@ -164,7 +165,7 @@ public static function input( $format = null, $hide = false ) {
164165
throw new \Exception( 'Caught ^D during input' );
165166
}
166167

167-
return trim( $line );
168+
return trim( (string) $line );
168169
}
169170

170171
/**
@@ -188,10 +189,12 @@ public static function prompt( $question, $default = false, $marker = ': ', $hid
188189
self::out( $question . $marker );
189190
$line = self::input( null, $hide );
190191

191-
if ( trim( $line ) !== '' )
192+
if ( trim( $line ) !== '' ) {
192193
return $line;
193-
if( $default !== false )
194-
return $default;
194+
}
195+
if( $default !== false ) {
196+
return (string) $default;
197+
}
195198
}
196199
}
197200

@@ -213,7 +216,7 @@ public static function choose( $question, $choice = 'yn', $default = 'n' ) {
213216
// Make every choice character lowercase except the default
214217
$choice = str_ireplace( $default, strtoupper( $default ), strtolower( $choice ) );
215218
// Separate each choice with a forward-slash
216-
$choices = trim( join( '/', preg_split( '//', $choice ) ), '/' );
219+
$choices = trim( join( '/', str_split( $choice ) ), '/' );
217220

218221
while( true ) {
219222
$line = self::prompt( sprintf( '%s? [%s]', $question, $choices ), $default, '' );
@@ -259,7 +262,7 @@ public static function menu( $items, $default = null, $title = 'Choose an item'
259262
if( is_numeric( $line ) ) {
260263
$line--;
261264
if( isset( $map[$line] ) ) {
262-
return array_search( $map[$line], $items );
265+
return (string) array_search( $map[$line], $items );
263266
}
264267

265268
if( $line < 0 || $line >= count( $map ) ) {

lib/cli/arguments/HelpScreen.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,7 @@ private function _renderScreen($options, $max) {
116116
foreach ($options as $option => $settings) {
117117
$formatted = ' ' . str_pad($option, $max);
118118

119-
$dlen = 80 - 4 - $max;
120-
119+
$dlen = max( 1, 80 - 4 - $max );
121120
$description = str_split($settings['description'], $dlen);
122121
$formatted.= ' ' . array_shift($description);
123122

lib/cli/cli.php

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ function safe_strlen( $str, $encoding = false ) {
166166
// Allow for selective testings - "1" bit set tests grapheme_strlen(), "2" preg_match_all( '/\X/u' ), "4" mb_strlen(), "other" strlen().
167167
$test_safe_strlen = (int) getenv( 'PHP_CLI_TOOLS_TEST_SAFE_STRLEN' );
168168

169-
// Assume UTF-8 if no encoding given - `grapheme_strlen()` will return null if given non-UTF-8 string.
170-
if ( ( ! $encoding || 'UTF-8' === $encoding ) && can_use_icu() && null !== ( $length = grapheme_strlen( $str ) ) ) {
169+
// Assume UTF-8 if no encoding given - `grapheme_strlen()` will return false on failure.
170+
if ( ( ! $encoding || 'UTF-8' === $encoding ) && can_use_icu() && is_int( $length = grapheme_strlen( $str ) ) ) {
171171
if ( ! $test_safe_strlen || ( $test_safe_strlen & 1 ) ) {
172172
return $length;
173173
}
@@ -183,10 +183,12 @@ function safe_strlen( $str, $encoding = false ) {
183183
if ( ! $encoding ) {
184184
$encoding = mb_detect_encoding( $str, null, true /*strict*/ );
185185
}
186-
$length = $encoding ? mb_strlen( $str, $encoding ) : mb_strlen( $str ); // mbstring funcs can fail if given `$encoding` arg that evals to false.
186+
$length = is_string( $encoding ) ? mb_strlen( $str, $encoding ) : mb_strlen( $str ); // mbstring funcs can fail if given `$encoding` arg that evals to false.
187187
if ( 'UTF-8' === $encoding ) {
188188
// Subtract combining characters.
189-
$length -= preg_match_all( get_unicode_regexs( 'm' ), $str, $dummy /*needed for PHP 5.3*/ );
189+
$m_regex = get_unicode_regexs( 'm' );
190+
assert( is_string( $m_regex ) );
191+
$length -= preg_match_all( $m_regex, $str, $dummy /*needed for PHP 5.3*/ );
190192
}
191193
if ( ! $test_safe_strlen || ( $test_safe_strlen & 4 ) ) {
192194
return $length;
@@ -217,6 +219,8 @@ function safe_substr( $str, $start, $length = false, $is_width = false, $encodin
217219
// Normalize `$length` when not specified - PHP 5.3 substr takes false as full length, PHP > 5.3 takes null.
218220
if ( null === $length || false === $length ) {
219221
$length = $safe_strlen;
222+
} else {
223+
$length = (int) $length;
220224
}
221225
// Normalize `$start` - various methods treat this differently.
222226
if ( $start > $safe_strlen ) {
@@ -250,7 +254,7 @@ function safe_substr( $str, $start, $length = false, $is_width = false, $encodin
250254
$encoding = mb_detect_encoding( $str, null, true /*strict*/ );
251255
}
252256
// Bug: not adjusting for combining chars.
253-
$try = $encoding ? mb_substr( $str, $start, $length, $encoding ) : mb_substr( $str, $start, $length ); // mbstring funcs can fail if given `$encoding` arg that evals to false.
257+
$try = is_string( $encoding ) ? mb_substr( $str, $start, $length, $encoding ) : mb_substr( $str, $start, $length ); // mbstring funcs can fail if given `$encoding` arg that evals to false.
254258
if ( 'UTF-8' === $encoding && $is_width ) {
255259
$try = _safe_substr_eaw( $try, $length );
256260
}
@@ -271,6 +275,7 @@ function safe_substr( $str, $start, $length = false, $is_width = false, $encodin
271275
function _safe_substr_eaw( $str, $length ) {
272276
// Set the East Asian Width regex.
273277
$eaw_regex = get_unicode_regexs( 'eaw' );
278+
assert( is_string( $eaw_regex ) );
274279

275280
// If there's any East Asian double-width chars...
276281
if ( preg_match( $eaw_regex, $str ) ) {
@@ -283,6 +288,9 @@ function _safe_substr_eaw( $str, $length ) {
283288
} else {
284289
// Explode string into an array of UTF-8 chars. Based on core `_mb_substr()` in "wp-includes/compat.php".
285290
$chars = preg_split( '/([\x00-\x7f\xc2-\xf4][^\x00-\x7f\xc2-\xf4]*)/', $str, $length + 1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
291+
if ( false === $chars ) {
292+
$chars = array( $str );
293+
}
286294
$cnt = min( count( $chars ), $length );
287295
$width = $length;
288296

@@ -326,7 +334,9 @@ function strwidth( $string, $encoding = false ) {
326334
$string = (string) $string;
327335

328336
// Set the East Asian Width and Mark regexs.
329-
list( $eaw_regex, $m_regex ) = get_unicode_regexs();
337+
$regexs = get_unicode_regexs();
338+
assert( is_array( $regexs ) );
339+
list( $eaw_regex, $m_regex ) = $regexs;
330340

331341
// Allow for selective testings - "1" bit set tests grapheme_strlen(), "2" preg_match_all( '/\X/u' ), "4" mb_strwidth(), "other" safe_strlen().
332342
$test_strwidth = (int) getenv( 'PHP_CLI_TOOLS_TEST_STRWIDTH' );
@@ -348,7 +358,7 @@ function strwidth( $string, $encoding = false ) {
348358
if ( ! $encoding ) {
349359
$encoding = mb_detect_encoding( $string, null, true /*strict*/ );
350360
}
351-
$width = $encoding ? mb_strwidth( $string, $encoding ) : mb_strwidth( $string ); // mbstring funcs can fail if given `$encoding` arg that evals to false.
361+
$width = is_string( $encoding ) ? mb_strwidth( $string, $encoding ) : mb_strwidth( $string ); // mbstring funcs can fail if given `$encoding` arg that evals to false.
352362
if ( 'UTF-8' === $encoding ) {
353363
// Subtract combining characters.
354364
$width -= preg_match_all( $m_regex, $string, $dummy /*needed for PHP 5.3*/ );

lib/cli/table/Ascii.php

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public function setWidths(array $widths, $fallback = false) {
9090

9191
if ( $widths && $max_width && array_sum( $widths ) > $max_width ) {
9292

93-
$avg = floor( $max_width / count( $widths ) );
93+
$avg = (int) floor( $max_width / count( $widths ) );
9494
$resize_widths = array();
9595
$extra_width = 0;
9696
foreach( $widths as $width ) {
@@ -102,7 +102,7 @@ public function setWidths(array $widths, $fallback = false) {
102102
}
103103

104104
if ( ! empty( $resize_widths ) && $extra_width ) {
105-
$avg_extra_width = floor( $extra_width / count( $resize_widths ) );
105+
$avg_extra_width = (int) floor( $extra_width / count( $resize_widths ) );
106106
foreach( $widths as &$width ) {
107107
if ( in_array( $width, $resize_widths ) ) {
108108
$width = $avg + $avg_extra_width;
@@ -198,6 +198,9 @@ public function row( array $row ) {
198198
$original_val_width = Colors::width( $value, self::isPreColorized( $col ), $encoding );
199199
if ( $col_width && ( $original_val_width > $col_width || strpos( $value, "\n" ) !== false ) ) {
200200
$split_lines = preg_split( '/\r\n|\n/', $value );
201+
if ( false === $split_lines ) {
202+
$split_lines = array( $value );
203+
}
201204

202205
$wrapped_lines = [];
203206
foreach ( $split_lines as $line ) {
@@ -308,11 +311,11 @@ protected function wrapText( $text, $width, $encoding, $is_precolorized ) {
308311
if ( 'truncate' === $this->_wrapping_mode ) {
309312
if ( $width <= self::ELLIPSIS_WIDTH ) {
310313
// Not enough space for ellipsis, just truncate
311-
return array( \cli\safe_substr( $text, 0, $width, true /*is_width*/, $encoding ) );
314+
return array( (string) \cli\safe_substr( $text, 0, $width, true /*is_width*/, $encoding ) );
312315
}
313316

314317
// Truncate and add ellipsis
315-
$truncated = \cli\safe_substr( $text, 0, $width - self::ELLIPSIS_WIDTH, true /*is_width*/, $encoding );
318+
$truncated = (string) \cli\safe_substr( $text, 0, $width - self::ELLIPSIS_WIDTH, true /*is_width*/, $encoding );
316319
return array( $truncated . self::ELLIPSIS );
317320
}
318321

@@ -331,11 +334,11 @@ protected function wrapText( $text, $width, $encoding, $is_precolorized ) {
331334
} else {
332335
// For non-colorized content, use character-boundary wrapping
333336
do {
334-
$wrapped_value = \cli\safe_substr( $line, 0, $width, true /*is_width*/, $encoding );
337+
$wrapped_value = (string) \cli\safe_substr( $line, 0, $width, true /*is_width*/, $encoding );
335338
$val_width = Colors::width( $wrapped_value, $is_precolorized, $encoding );
336339
if ( $val_width ) {
337340
$wrapped_lines[] = $wrapped_value;
338-
$line = \cli\safe_substr( $line, \cli\safe_strlen( $wrapped_value, $encoding ), null /*length*/, false /*is_width*/, $encoding );
341+
$line = (string) \cli\safe_substr( $line, \cli\safe_strlen( $wrapped_value, $encoding ), null /*length*/, false /*is_width*/, $encoding );
339342
}
340343
} while ( $line );
341344
}
@@ -359,6 +362,9 @@ protected function wordWrap( $text, $width, $encoding, $is_precolorized ) {
359362

360363
// Split by spaces and hyphens while keeping the delimiters
361364
$words = preg_split( '/(\s+|-)/u', $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
365+
if ( false === $words ) {
366+
$words = array( $text );
367+
}
362368

363369
foreach ( $words as $word ) {
364370
$word_width = Colors::width( $word, $is_precolorized, $encoding );
@@ -375,9 +381,9 @@ protected function wordWrap( $text, $width, $encoding, $is_precolorized ) {
375381
// Split the long word at character boundaries
376382
$remaining_word = $word;
377383
while ( $remaining_word ) {
378-
$chunk = \cli\safe_substr( $remaining_word, 0, $width, true /*is_width*/, $encoding );
384+
$chunk = (string) \cli\safe_substr( $remaining_word, 0, $width, true /*is_width*/, $encoding );
379385
$wrapped_lines[] = $chunk;
380-
$remaining_word = \cli\safe_substr( $remaining_word, \cli\safe_strlen( $chunk, $encoding ), null /*length*/, false /*is_width*/, $encoding );
386+
$remaining_word = (string) \cli\safe_substr( $remaining_word, \cli\safe_strlen( $chunk, $encoding ), null /*length*/, false /*is_width*/, $encoding );
381387
}
382388
continue;
383389
}

lib/cli/table/Tabular.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ public function row( array $row ) {
3333
$value = isset( $value ) ? (string) $value : '';
3434
$value = str_replace( "\t", ' ', $value );
3535
$split_lines = preg_split( '/\r\n|\n/', $value );
36+
if ( false === $split_lines ) {
37+
$split_lines = array( $value );
38+
}
3639
// Keep anything before the first line break on the original line
3740
$row[ $col ] = array_shift( $split_lines );
3841
}

0 commit comments

Comments
 (0)