diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index f612d8c59c..1433ca98f8 100644 --- a/src/wp-includes/functions.php +++ b/src/wp-includes/functions.php @@ -322,6 +322,62 @@ function size_format( $bytes, $decimals = 0 ) { return false; } +/** + * Convert a filelength to human readable format. + * + * @since 5.0 + * + * @param string $filelength Duration will be in string format (HH:ii:ss) OR (ii:ss). + * @return boolean|string A human readable filelength string, false on failure. + */ +function human_readable_duration( $filelength = '' ) { + // Return false if filelength is empty or not in format. + if ( ( empty( $filelength ) || ! is_string( $filelength ) ) ) { + return false; + } + + // Validate filelength format. + if ( ! ( (bool) preg_match( '/^(([0-3]?[0-9])|([2][0-3])):([0-5]?[0-9])(:([0-5]?[0-9]))?$/', $filelength ) ) ) { + return false; + } + + $human_readable_duration = array(); + + // Extract duration. + $durations = array_reverse( explode( ':', $filelength ) ); + $duration_count = count( $durations ); + + if ( 3 === $duration_count ) { + // Three parts: hours, minutes & seconds. + list( $second, $minute, $hour ) = $durations; + } elseif ( 2 === $duration_count ) { + // Two parts: minutes & seconds. + list( $second, $minute ) = $durations; + } else { + return false; + } + + // Add the hour part to the string. + if ( ! empty( $hour ) && is_numeric( $hour ) ) { + /* translators: Time duration in hour or hours. */ + $human_readable_duration[] = sprintf( _n( '%s hour', '%s hours', $hour ), (int) $hour ); + } + + // Add the minute part to the string. + if ( ! empty( $minute ) && is_numeric( $minute ) ) { + /* translators: Time duration in minute or minutes. */ + $human_readable_duration[] = sprintf( _n( '%s minute', '%s minutes', $minute ), (int) $minute ); + } + + // Add the second part to the string. + if ( ! empty( $second ) && is_numeric( $second ) ) { + /* translators: Time duration in second or seconds. */ + $human_readable_duration[] = sprintf( _n( '%s second', '%s seconds', $second ), (int) $second ); + } + + return implode( ', ', $human_readable_duration ); +} + /** * Get the week start and end from the datetime or date string from MySQL. * diff --git a/src/wp-includes/media-template.php b/src/wp-includes/media-template.php index c5f272cc1a..fb44261cf1 100644 --- a/src/wp-includes/media-template.php +++ b/src/wp-includes/media-template.php @@ -371,12 +371,20 @@ function wp_print_media_templates() {
{{ data.filesizeHumanReadable }}
<# if ( 'image' === data.type && ! data.uploading ) { #> <# if ( data.width && data.height ) { #> -
{{ data.width }} × {{ data.height }}
+
+ +
<# } #> <# } #> - <# if ( data.fileLength ) { #> -
{{ data.fileLength }}
+ <# if ( data.fileLength && data.fileLengthHumanReadable ) { #> +
+ + {{ data.fileLengthHumanReadable }} +
<# } #> <# if ( 'audio' === data.type && data.meta.bitrate ) { #> @@ -547,7 +555,12 @@ function wp_print_media_templates() {
{{ data.filesizeHumanReadable }}
<# if ( 'image' === data.type && ! data.uploading ) { #> <# if ( data.width && data.height ) { #> -
{{ data.width }} × {{ data.height }}
+
+ +
<# } #> <# if ( data.can.save && data.sizes ) { #> @@ -555,8 +568,11 @@ function wp_print_media_templates() { <# } #> <# } #> - <# if ( data.fileLength ) { #> -
{{ data.fileLength }}
+ <# if ( data.fileLength && data.fileLengthHumanReadable ) { #> +
+ + {{ data.fileLengthHumanReadable }} +
<# } #> <# if ( ! data.uploading && data.can.remove ) { #> diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index f9dc9c4ebd..ec50703b33 100644 --- a/src/wp-includes/media.php +++ b/src/wp-includes/media.php @@ -3378,7 +3378,8 @@ function wp_prepare_attachment_for_js( $attachment ) { if ( $meta && ( 'audio' === $type || 'video' === $type ) ) { if ( isset( $meta['length_formatted'] ) ) { - $response['fileLength'] = $meta['length_formatted']; + $response['fileLength'] = $meta['length_formatted']; + $response['fileLengthHumanReadable'] = human_readable_duration( $meta['length_formatted'] ); } $response['meta'] = array(); diff --git a/tests/phpunit/tests/functions.php b/tests/phpunit/tests/functions.php index a6c52256d2..d6d5d066e0 100644 --- a/tests/phpunit/tests/functions.php +++ b/tests/phpunit/tests/functions.php @@ -1518,4 +1518,43 @@ class Tests_Functions extends WP_UnitTestCase { array( '/leading/relative/path', false ), ); } + + /** + * Test the human_readable_duration function. + * + * @ticket 39667 + * @dataProvider _datahuman_readable_duration() + * + * @param $input + * @param $expected + */ + public function test_duration_format( $input, $expected ) { + $this->assertSame( $expected, human_readable_duration( $input ) ); + } + + public function _datahuman_readable_duration() { + return array( + array( array(), false ), + array( '30:00', '30 minutes, 0 seconds' ), + array( 'Batman Begins !', false ), + array( '', false ), + array( '-1', false ), + array( -1, false ), + array( 0, false ), + array( 1, false ), + array( '00', false ), + array( '00:00', '0 minutes, 0 seconds' ), + array( '00:00:00', '0 hours, 0 minutes, 0 seconds' ), + array( '10:30:34', '10 hours, 30 minutes, 34 seconds' ), + array( '00:30:34', '0 hours, 30 minutes, 34 seconds' ), + array( 'MM:30:00', false ), + array( '30:MM', false ), + array( 'MM:00', false ), + array( 'MM:MM', false ), + array( '01:01', '1 minute, 1 second' ), + array( '01:01:01', '1 hour, 1 minute, 1 second' ), + array( '0:05', '5 seconds' ), + array( '1:02:00', '1 hour, 2 minutes, 0 seconds' ), + ); + } }