'k', '1000000' => 'M', '1000000000' => 'B', '1000000000000' => 'T', '1000000000000000' => 'Q', ); $current_number = $number; $current_number_as_string = (string) $number; $unit = ''; $previous_number = 0; foreach ( $unit_names as $thousands => $suffix ) { $thousands_int = (int) preg_replace( '/\D/', '', (string) $thousands ); if ( $number >= $thousands_int ) { $current_number = $number / $thousands_int; $precision = $fraction_digits; // For over 10 units, we reduce the precision to 1 fraction digit. $modulo = (int) fmod( $current_number, 1 ); if ( 0 !== $previous_number && $modulo > 1 / $previous_number ) { $precision = $current_number > 10 ? 1 : 2; } // Precision override, where we want to show 2 fraction digits. $zeroes = floatval( number_format( $current_number, 2 ) ) === floatval( number_format( $current_number, 0 ) ); $precision = $zeroes ? 0 : $precision; $current_number_as_string = number_format( $current_number, $precision, '.', '' ); $unit = $suffix; } $previous_number = $current_number; } return $current_number_as_string . $glue . $unit; } /** * Gets time in formatted form. * * Example: * - Input `1000` (seconds) and Output `16:40` which represents "16 minutes, 40 seconds” * * @since 3.7.0 * * @param float $seconds Time in seconds to be formatted. * * @return string */ public static function get_formatted_time( $seconds ): string { $seconds = round( $seconds ); $hours = floor( $seconds / 3600 ); if ( $hours >= 1 ) { $seconds = $seconds - ( $hours * 3600 ); $minutes = floor( $seconds / 60 ); $seconds = round( $seconds % 60 ); return esc_html( sprintf( /* translators: 1: Number of hours 2: Number of minutes 3: Number of seconds */ __( '%1$d:%2$02d:%3$02d', 'wp-parsely' ), $hours, $minutes, $seconds ) ); } $minutes = floor( $seconds / 60 ); $seconds = round( $seconds % 60 ); if ( $minutes >= 1 ) { return esc_html( sprintf( /* translators: 1: Number of minutes 2: Number of seconds */ __( '%1$d:%2$02d', 'wp-parsely' ), $minutes, $seconds ) ); } return esc_html( sprintf( /* translators: 1: Number of seconds */ __( '%1$d sec.', 'wp-parsely' ), round( $seconds ) ) ); } /** * Returns the passed float as a time duration in m:ss format. * * Examples: * - $time of 1.005 yields '1:00'. * - $time of 1.5 yields '1:30'. * - $time of 1.999 yields '2:00'. * * @since 3.6.0 * * @param float $time The time as a float number. * * @return string The resulting formatted time duration. */ public static function get_formatted_duration( float $time ): string { $minutes = absint( $time ); $seconds = absint( round( fmod( $time, 1 ) * 60 ) ); if ( 60 === $seconds ) { ++$minutes; $seconds = 0; } return sprintf( '%d:%02d', $minutes, $seconds ); } /** * Converts to associate array. * * @since 3.7.0 * * @param mixed $obj Input object. * * @return array|WP_Error */ public static function convert_to_associative_array( $obj ) { $encoded = wp_json_encode( $obj ); if ( false === $encoded ) { return new WP_Error( 'parsely_encoding_failed', __( 'Unable to encode API response for associative array', 'wp-parsely' ) ); } /** * Variable. * * @var array */ return json_decode( $encoded, true ); } /** * Converts a string to a positive integer, removing any non-numeric * characters. * * @param string $value The string to be converted to an integer. * @return int The integer resulting from the conversion. */ public static function convert_to_positive_integer( string $value ): int { return (int) preg_replace( '/\D/', '', $value ); } /** * Converts endpoint to filter key by replacing `/` with `_`. * * @param string $endpoint Route of the endpoint. * * @since 3.7.0 * * @return string */ public static function convert_endpoint_to_filter_key( string $endpoint ): string { return trim( str_replace( array( '-', '/' ), '_', $endpoint ), '_' ); } /** * Gets content of asset file. * * @param string $path Path of the asset file. * * @since 3.8.0 * * @return Asset_Info */ public static function get_asset_info( string $path ) { return require plugin_dir_path( PARSELY_FILE ) . $path; } /** * Checks if a string starts with a specific substring. * * This function uses the built-in PHP function `str_starts_with` if it's available (PHP 8.0 and later). * If the function is not available (PHP versions prior to 8.0), it uses the `strpos` function as a fallback. * * @since 3.13.0 * * @param string $haystack The string to search in. * @param string $needle The substring to search for at the start of $haystack. * @return bool Returns true if $haystack starts with $needle, false otherwise. */ public static function str_starts_with( string $haystack, string $needle ): bool { if ( function_exists( '\str_starts_with' ) ) { return \str_starts_with( $haystack, $needle ); } return 0 === strpos( $haystack, $needle ); } /** * Checks if HTTPS is supported for the site. * * This function checks if the WordPress function 'wp_is_using_https' exists and uses it to determine if * HTTPS is supported. * If the function does not exist, it checks if the home URL scheme is HTTPS. * If neither of the above conditions are met, it checks if the site URL option scheme is HTTPS. * * @since 3.14.1 * * @return bool Returns true if HTTPS is supported, false otherwise. */ public static function parsely_is_https_supported(): bool { if ( function_exists( 'wp_is_using_https' ) ) { return wp_is_using_https(); } if ( 'https' === wp_parse_url( home_url(), PHP_URL_SCHEME ) ) { return true; } // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound $site_url = apply_filters( 'site_url', get_option( 'siteurl' ), '', null, null ); return 'https' === wp_parse_url( $site_url, PHP_URL_SCHEME ); } /** * Returns the post ID for the passed URL. * * @since 3.16.0 * @since 3.18.0 Moved from `Models/class-smart-link.php`. * * @param string $url The URL to get the post ID for. * @return int The post ID of the URL, 0 if not found. */ public static function get_post_id_by_url( string $url ): int { $cache_key = sprintf( 'url-to-postid-%s', hash( 'sha256', $url ) ); $cache = wp_cache_get( $cache_key, PARSELY_CACHE_GROUP ); if ( false !== $cache && is_numeric( $cache ) ) { return (int) $cache; } if ( function_exists( 'wpcom_vip_url_to_postid' ) ) { $post_id = wpcom_vip_url_to_postid( $url ); } else { // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.url_to_postid_url_to_postid $post_id = url_to_postid( $url ); wp_cache_set( $cache_key, $post_id, PARSELY_CACHE_GROUP, WEEK_IN_SECONDS ); } // A post ID was found, return it. if ( 0 !== $post_id ) { return $post_id; } // No post ID was found, try to find it from the slug. $clean_url = preg_replace( '/\?.*$/', '', $url ); // Remove the query string from the URL. if ( null === $clean_url ) { $clean_url = $url; } $post_slug = basename( $clean_url ); $public_post_types = get_post_types( array( 'public' => true, 'show_in_rest' => true, ) ); $post = get_page_by_path( $post_slug, OBJECT, array_keys( $public_post_types ) ); if ( null !== $post ) { wp_cache_set( $cache_key, $post->ID, PARSELY_CACHE_GROUP, WEEK_IN_SECONDS ); return $post->ID; } return 0; } /** * Appends ITM parameters to a URL. * * @since 3.19.0 * * @param string $url The URL to append the ITM parameters to. * @param ItmParams $params The ITM parameters to append. * @return string The URL with the ITM parameters appended. */ public static function append_itm_params( string $url, $params ): string { // Convert the params array to the correct format. $mapping = array( 'campaign' => 'itm_campaign', 'source' => 'itm_source', 'medium' => 'itm_medium', 'content' => 'itm_content', 'term' => 'itm_term', ); $itm_params = array(); foreach ( $params as $key => $value ) { if ( array_key_exists( $key, $mapping ) ) { $itm_params[ $mapping[ $key ] ] = $value; } } return add_query_arg( $itm_params, $url ); } }