The list of chunks. Empty if there is no content. */ public static function chunk( string $content, int $max_length ): array { $content = trim( $content ); if ( '' === $content || $max_length < 1 ) { return array(); } if ( mb_strlen( $content ) <= $max_length ) { return array( $content ); } $sentences = preg_split( '/(?<=[.!?])\s+/u', $content ); if ( false === $sentences ) { $sentences = array( $content ); } $chunks = array(); $current = ''; foreach ( $sentences as $sentence ) { // A single sentence longer than the limit gets hard-split. if ( mb_strlen( $sentence ) > $max_length ) { if ( '' !== $current ) { $chunks[] = $current; $current = ''; } $offset = 0; $length = mb_strlen( $sentence ); while ( $offset < $length ) { $chunks[] = mb_substr( $sentence, $offset, $max_length ); $offset += $max_length; } continue; } $candidate = '' === $current ? $sentence : $current . ' ' . $sentence; if ( mb_strlen( $candidate ) > $max_length ) { $chunks[] = $current; $current = $sentence; } else { $current = $candidate; } } if ( '' !== $current ) { $chunks[] = $current; } return array_values( array_filter( array_map( 'trim', $chunks ), static function ( string $chunk ): bool { return '' !== $chunk; } ) ); } }