/home/awneajlw/www/wp-content/plugins/broken-link-checker/core/utils/class-utilities.php
<?php
/**
* Useful utilities.
*
* @link https://wordpress.org/plugins/broken-link-checker/
* @since 2.0.0
*
* @author WPMUDEV (https://wpmudev.com)
* @package WPMUDEV_BLC\Core
*
* @copyright (c) 2022, Incsub (http://incsub.com)
*/
namespace WPMUDEV_BLC\Core\Utils;
// If this file is called directly, abort.
defined( 'WPINC' ) || die;
use WPMUDEV_BLC\Core\Traits\Dashboard_API;
use DateTime;
use DateTimeZone;
use WPMUDEV_Dashboard_Api;
use function array_keys;
use function array_values;
use function call_user_func;
use function date;
use function dirname;
use function error_log; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
use function fclose;
use function file_exists;
use function fopen;
use function is_callable;
use function is_dir;
use function is_int;
use function is_multisite;
use function is_null;
use function mkdir;
use function path_join;
use function round;
use function wp_normalize_path;
/**
* Class WPMUDEV_BLC
*
* @package WPMUDEV_BLC\Core
*/
final class Utilities {
use Dashboard_API;
/**
* Array that holds variable values that can be re-used in several classes.
*
* @since 2.0.0
* @var array $value_provider
*/
public static $value_provider = array();
/**
* Checks if current request is on multisite for the network administrative interface.
*
* @since 2.0.0
* @return bool
*/
public static function is_network_admin() {
if ( ! is_multisite() ) {
return false;
}
/**
* Filter to change network admin flag.
*
* @since 2.0.0
*
* @param bool Is network.
*/
return apply_filters( 'wpmudev_blc_is_network_admin', is_network_admin() || self::is_ajax_network_admin() );
}
/**
* Check if network admin.
*
* The is_network_admin() check does not work in AJAX calls.
*
* @since 2.0.0
*
* @return bool
*/
public static function is_ajax_network_admin() {
if ( ! is_multisite() ) {
return false;
}
return defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_SERVER['HTTP_REFERER'] ) && preg_match( '#^' . network_admin_url() . '#i', wp_unslash( $_SERVER['HTTP_REFERER'] ) );
}
/**
* Checks if current request is on a subsite admin of a multisite installation. If we are on main site or on
* network admin, it returns false.
*
* @since 2.0.0
* @return bool
*/
public static function is_subsite() {
if ( ! is_multisite() ) {
return false;
}
/**
* Filter to change subsite admin flag.
*
* @since 2.0.0
*
* @param bool Is subsite.
*/
return apply_filters(
'wpmudev_blc_is_subsite',
! ( self::is_network_admin() || is_main_site() )
);
}
/**
* Gives the subsite id based on url.
*
* @return int|null
*/
public static function subsite_id_from_url( string $url = '' ) {
if ( empty( $url ) || ! is_multisite() ) {
return null;
}
$url_parts = wp_parse_url( $url );
$domain = $url_parts['host'] ?? null;
$path = null;
if ( defined( 'SUBDOMAIN_INSTALL' ) ) {
if ( SUBDOMAIN_INSTALL ) {
$path = '/';
} else {
$path = $url_parts['path'] ?? null;
}
}
if ( ! empty( $domain ) && ! empty( $path ) ) {
return get_blog_id_from_url( $domain, $path );
}
return null;
}
/**
* Checks if subsite id is valid.
*
* @param int|null $id
*
* @return false|void
*/
public static function valid_subsite_id( ?int $id = null ) {
if ( empty( $id ) || ! is_multisite() ) {
return false;
}
return in_array( $id, get_sites( array( 'fields' => 'ids' ) ) );
}
/**
* Checks if given url belongs to author and returns author WP_User object else false.
*
* @since 2.1.0
*
* @param string $url
*
* @return WP_User|bool
*/
public static function is_author_url( string $url = '' ) {
$site_url = site_url();
if ( substr( $url, 0, strlen( $site_url ) ) !== $site_url ) {
return false;
}
global $wp_rewrite;
$parsed_url = wp_parse_url( $url );
$user = null;
// Check url when it has plain permalink structure.
if ( ! empty( $parsed_url['query'] ) ) {
$parsed_query = array();
parse_str( $parsed_url['query'], $parsed_query );
if ( ! empty( $parsed_query[ $wp_rewrite->author_base ] ) ) {
$user_key = is_numeric( $parsed_query[ $wp_rewrite->author_base ] ) ? 'id' : 'login';
$user = get_user_by( $user_key, sanitize_user( $parsed_query[ $wp_rewrite->author_base ] ) );
}
} elseif ( ! empty( $parsed_url['path'] ) ) {
// Check url with pretty permalink structure.
$path = trim( $parsed_url['path'], '/\\' );
$author_base = "{$wp_rewrite->author_base}/";
$user_name = sanitize_user( str_replace( $author_base, '', $path ) );
$user = get_user_by( 'login', $user_name );
}
return $user;
}
/**
* Get collation of a table's column.
*
* @since 2.2.2
*
* @param string $table The table name
* @param string $column The table's column name
* @return null|string
*/
public static function get_table_col_collation( string $table = '', string $column = '' ) {
if ( empty( $table ) || empty( $column ) ) {
return null;
}
$table_parts = explode( '.', $table );
$table = ! empty( $table_parts[1] ) ? $table_parts[1] : $table;
$col_key = strtolower( "{$table}_{$column}" );
static $tables_collates = array();
if ( ! isset( $tables_collates[ $col_key ] ) ) {
global $wpdb;
$tables_collates[ $col_key ] = null;
$table_status = null;
// Alternatively in order to check only for wp core tables $wpdb->tables() could be used.
$tables_like_table = $wpdb->get_results( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) );
if ( ! empty( $tables_like_table ) ) {
$table_status = $wpdb->get_row(
$wpdb->prepare(
"SHOW FULL COLUMNS FROM {$table} WHERE field = '%s'",
$column
)
);
}
if ( ! empty( $table_status ) && ! empty( $table_status->Collation ) ) {
$tables_collates[ $col_key ] = $table_status->Collation;
}
}
return $tables_collates[ $col_key ];
}
/**
* Get charset of a table's column.
*
* @since 2.2.2
*
* @param string $table The table name
* @param string $column The table's column name
* @return null|string
*/
public static function get_table_col_charset( string $table = '', string $column = '' ) {
if ( empty( $table ) || empty( $column ) ) {
return null;
}
$collation = self::get_table_col_collation( $table, $column );
if ( empty( $collation ) ) {
return null;
}
list( $charset ) = explode( '_', $collation );
return $charset;
}
/**
* Generate random unique id. Useful for creating element ids in scripts
*
* @since 2.0.0
*
* @param string $prefix Optional. A prefix.
*
* @return string Generate unique id.
*/
public static function get_unique_id( $prefix = null ): string {
if ( is_null( $prefix ) ) {
$prefix = uniqid() . '_';
}
return wp_unique_id( $prefix );
}
/**
* Checks if WPMU DEV Dashboard plugin is installed.
*
* @since 2.0.0
*
* @return bool
*/
public static function dash_plugin_installed() {
return apply_filters(
'wpmudev_blc_is_dash_installed',
file_exists( WP_PLUGIN_DIR . '/wpmudev-updates/update-notifications.php' )
);
}
/**
* Checks if WPMU DEV Dashboard plugin is active.
*
* @since 2.0.0
*
* @return bool
*/
public static function dash_plugin_active() {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
$is_active = is_multisite() ?
is_plugin_active_for_network( 'wpmudev-updates/update-notifications.php' ) :
is_plugin_active( 'wpmudev-updates/update-notifications.php' );
return apply_filters( 'wpmudev_blc_is_dash_active', $is_active );
}
/**
* Returns a boolean. True if site is connected to hub or false if not.
*
* @return bool
*/
public static function is_site_connected() {
return self::site_connected();
}
/**
* Returns a boolean. True if site is connected to hub or false if not.
*
* @return bool
*/
public static function membership_expired() {
return 'expired' === self::get_membership_type();
}
/**
* Returns true if the current user has a Free membership, else false.
*
* @return bool
*/
public static function is_free_member(): bool {
return 'free' === self::get_membership_type();
}
/**
* Returns the hub's start scan url.
*
* @return string
*/
public static function hub_scan_url() {
return apply_filters( 'wpmudev_blc_hub_scan_url', self::hub_home_url() . '?start-scan=1' );
}
/**
* Returns the hub's url.
*
* @return string
*/
public static function hub_home_url() {
$site_id = self::site_id();
$url = apply_filters( 'wpmudev_blc_hub_home_url', untrailingslashit( self::wpmudev_base_url() . "hub2/site/{$site_id}/blc" ) );
return $url;
}
/**
* Returns WPMUDEV API Server URL
*
* @return string
*/
public static function wpmudev_base_url() {
$api_server_url = defined( 'WPMUDEV_CUSTOM_API_SERVER' ) && WPMUDEV_CUSTOM_API_SERVER
? trailingslashit( WPMUDEV_CUSTOM_API_SERVER )
: 'https://wpmudev.com/';
return $api_server_url;
}
/**
* Returns the hub's signup url.
*
* @return string
*/
public static function hub_signup_url() {
return apply_filters( 'wpmudev_blc_hub_signup_url', self::wpmudev_base_url() . 'register/?signup=blc&blc_url=' . site_url() );
}
/**
* Returns the hub's connect url.
*
* @return string
*/
public static function hub_connect_url() {
return apply_filters( 'wpmudev_blc_hub_connect_url', self::hub_base_url() . 'connect/choose-method/' );
}
/**
* Returns the signup url.
* If Dashboard plugin is active the signup url returned will be the Dashboard signup page. Else Hub signup page.
*
* @return string
*/
public static function signup_url() {
if ( self::get_dashboard_api() instanceof WPMUDEV_Dashboard_Api ) {
return add_query_arg(
array(
'page' => 'wpmudev',
),
is_multisite() ? network_admin_url() : get_admin_url()
);
}
return self::hub_signup_url();
}
/**
* Returns the hub's url.
*
* @return string
*/
public static function hub_base_url() {
return apply_filters( 'wpmudev_blc_hub_base_url', self::wpmudev_base_url() . 'hub2/' );
}
/**
* Returns the hub's account url.
*
* @return string
*/
public static function hub_account_url() {
return apply_filters( 'wpmudev_blc_hub_account_url', self::hub_base_url() . 'account/' );
}
/**
*
* Returns the hub's BLC page url.
*/
public static function hub_blc_page_url() {
return apply_filters( 'wpmudev_blc_hub_blc_page_url', self::hub_base_url() . 'site/' . self::site_id() . '/link-checker' );
}
/**
* Returns the hub's pricing url.
*
* @return string
*/
public static function dev_pricing_url() {
return apply_filters( 'wpmudev_blc_dev_pricing_url', self::wpmudev_base_url() . 'pricing/' );
}
/**
* Returns the hub's start scan page url.
*
* @return string|null
*/
public static function hub_api_scan_url() {
$url = add_query_arg(
array(
'domain' => untrailingslashit( self::schemaless_url() ),
'site_id' => self::site_id(),
),
self::wpmudev_base_url() . 'api/blc/v1/scan'
);
return apply_filters( 'wpmudev_blc_api_scan_url', $url );
}
/**
* Returns url without schema (^http(s)?://).
*
* @param string $url .
*
* @return mixed
*/
public static function schemaless_url( string $url = '' ) {
if ( empty( $url ) ) {
$url = site_url();
}
$parsed_url = wp_parse_url( $url );
$host = $parsed_url['host'];
$path = $parsed_url['path'] ?? '';
// Path includes port if it exists in url.
return apply_filters( 'wpmudev_blc_schemaless_url', $host . $path, $url );
}
/**
* Returns the site id from hub.
*
* @return int
*/
public static function site_id() {
return apply_filters( 'wpmudev_blc_site_id', intval( self::get_site_id() ) );
}
/**
* Returns the hub's start scan page url.
*
* @return string|null
*/
public static function hub_api_sync_url() {
$url = add_query_arg(
array(
'domain' => untrailingslashit( self::schemaless_url() ),
'site_id' => self::site_id(),
),
self::wpmudev_base_url() . 'api/blc/v1/result'
);
return apply_filters( 'result_api_sync_url', $url );
}
/**
* Returns the hub url to send edit link results when edit link queue gets completed.
*
* @return string
*/
public static function hub_edit_link_completed() {
return apply_filters( 'hub_edit_link_completed', self::wpmudev_base_url() . 'api/blc/v1/edit-link-completed' );
}
public static function make_link_relative( string $url = '' ) {
$site_url = site_url();
$site_url_parts = wp_parse_url( $site_url );
$url_parts = wp_parse_url( $url );
if ( ! empty( $url_parts['host'] ) && $site_url_parts['host'] !== $url_parts['host'] ) {
return $url;
}
// Check if missing url scheme.
// It is not unusual to have urls starting with two slashes.
// Relative urls starting with 2 slashes replace everything from the hostname onward.
if ( substr( $url, 0, 2 ) === '//' ) {
$url = wp_parse_url( $site_url, PHP_URL_SCHEME ) . ':' . $url;
}
// If string is internal (starts with same url) we need to get the relative url.
$link_substring = substr( $url, 0, strlen( $site_url ) );
if ( strcasecmp( $link_substring, $site_url ) == 0 ) {
return wp_make_link_relative( $url );
}
return $url;
}
/**
* Returns true if given screen(s) is the current admin screen.
*
* @since 2.0.0
*
* @param string|array $screen .
* @param bool $strict .
*
* @return bool
*/
public static function is_admin_screen( $screen = null, $strict = false ) {
if ( is_null( $screen ) || ! is_callable( '\get_current_screen' ) || ! isset( get_current_screen()->id ) ) {
return false;
}
if ( $strict ) {
return is_array( $screen ) ?
in_array( get_current_screen()->id, $screen, true ) :
get_current_screen()->id === $screen;
}
return is_array( $screen ) ?
! empty(
array_filter(
$screen,
function ( $page ) {
return strpos( get_current_screen()->id, $page ) !== false;
}
)
) : strpos( get_current_screen()->id, $screen ) !== false;
}
/**
* Returns site time zone string as done in WP settings ( Not like `wp_timezone_string()` )
*
* @since 2.0.0
*
* @param bool $plain .
*
* @return string
*/
public static function get_timezone_string( bool $plain = true ) {
$current_offset = get_option( 'gmt_offset' );
$tzstring = get_option( 'timezone_string' );
// Remove old Etc mappings. Fallback to gmt_offset.
if ( false !== strpos( $tzstring, 'Etc/GMT' ) ) {
$tzstring = '';
}
if ( empty( $tzstring ) ) {
// Create a UTC+- zone if no timezone string exists.
if ( $plain ) {
$tzstring = $current_offset < 0 ? $current_offset : "+{$current_offset}";
} else {
$tzstring = $current_offset < 0 ? "UTC{$current_offset}" : "UTC+{$current_offset}";
}
}
return $tzstring;
}
/**
* Returns array with formatted hour list 0...23. Taken from Snapshot4.
*
* @return array
*/
public static function get_hour_list() {
$dt = new DateTime();
$dt->setTimezone( new DateTimeZone( 'UTC' ) );
$dt->setTimestamp( 0 );
$result = array();
$time_format = self::get_time_format();
foreach ( range( 0, 23 ) as $hour ) {
$dt->setTime( $hour, 0, 0 );
$key = $dt->format( 'H:i' );
$value = $dt->format( $time_format );
$result[ $key ] = $value;
}
return $result;
}
/**
* Returns time format
*
* @return string
*/
public static function get_time_format() {
$time_format = get_option( 'time_format' );
$supported_formats = array(
'g:i a',
'g:i A',
'g:i:s a',
'g:i:s A',
'g:i,',
'H:i',
);
if ( ! in_array( $time_format, $supported_formats, true ) ) {
$time_format = 'H:i'; // Fallback to default format.
}
return $time_format;
}
/**
* Returns an array with weekdays.
*
* @since 2.0.0
* @return array
*/
public static function get_week_days() {
global $wp_locale;
$week_days = array();
for ( $day_index = 0; $day_index <= 6; $day_index++ ) {
$week_days[] = array(
'key' => $day_index,
'value' => $wp_locale->get_weekday( $day_index ),
);
}
return $week_days;
}
/**
* Returns the value of a given key from a query string.
*
* @param string $query_string .
* @param string $key .
*
* @return mixed
*/
public static function get_query_var( string $query_string = '', string $key = '' ) {
if ( '' === $query_string || '' === $key ) {
return false;
}
$query_vars = array();
wp_parse_str( wp_parse_url( $query_string, PHP_URL_QUERY ), $query_vars );
return $query_vars[ $key ] ?? false;
}
/**
* Returns user avatar by user id.
*
* @param int $id .
* @param array $args .
*
* @return array|bool|string|null
*/
public static function avatar_by_id( int $id = 0, array $args = array() ) {
return self::avatar_data( $id, 'id', $args );
}
/**
* Retruns avatar dat.
*
* @param string $input .
* @param string $input_type .
* @param array $args .
*
* @return bool|null|array|string
*/
public static function avatar_data( string $input = '', string $input_type = 'id', array $args = array() ) {
$response = null;
switch ( $input_type ) {
case 'id':
$input = intval( $input );
break;
case 'email':
$input = filter_var( $input, FILTER_VALIDATE_EMAIL );
break;
}
$args = wp_parse_args(
$args,
array(
'size' => 96,
'height' => null,
'width' => null,
'default' => get_option( 'avatar_default', 'mystery' ),
'force_default' => false,
'rating' => get_option( 'avatar_rating' ),
'scheme' => null,
'processed_args' => null, // If used, should be a reference.
'extra_attr' => '',
'return' => 'raw', // Allowed values, array raw, bool found_avatar, string url.
)
);
$avatar_data = get_avatar_data( $input, $args );
switch ( $args['return'] ) {
case 'raw':
$response = $avatar_data;
break;
case 'found_avatar':
$response = isset( $avatar_data['found_avatar'] ) && (bool) $avatar_data['found_avatar'];
break;
case 'url':
$response = isset( $avatar_data['url'] ) ? esc_html( $avatar_data['url'] ) : false;
break;
}
return $response;
}
/**
* Returns avatar by a given email address.
*
* @param string $email .
* @param array $args .
*
* @return array|bool|string|null
*/
public static function avatar_by_email( string $email = '', array $args = array() ) {
return self::avatar_data( $email, 'email', $args );
}
/**
* Returns user's role titles
*
* @param int $user_id The user's id to get roles for.
*
* @return array
*/
public static function user_role_names( int $user_id = 0 ) {
if ( ! function_exists( 'get_editable_roles' ) ) {
require_once ABSPATH . 'wp-admin/includes/user.php';
}
$editable_roles = get_editable_roles();
return array_map(
function ( $item ) use ( $editable_roles ) {
return isset( $editable_roles[ $item ] ) ? $editable_roles[ $item ]['name'] : $item;
},
get_userdata( $user_id )->roles
);
}
/**
* Returns names of user roles
*
* @param array $capabilities Optional. An array with capabilities. Fetch roles per capability.
*
* @return array
*/
public static function roles_names( array $capabilities = array() ) {
if ( ! function_exists( 'get_editable_roles' ) ) {
require_once ABSPATH . 'wp-admin/includes/user.php';
}
$roles = get_editable_roles();
if ( ! empty( $capabilities ) ) {
$roles = array_filter(
$roles,
function ( $role ) use ( $capabilities ) {
foreach ( $capabilities as $capability ) {
if ( array_key_exists( $capability, $role['capabilities'] ) ) {
return true;
}
}
return false;
}
);
}
return wp_list_pluck( $roles, 'name' );
}
/**
* Converts an int number of seconds to hours, minutes and seconds format.
*
* @param float $seconds A float holding number of seconds.
*
* @return string
*/
public static function normalize_seconds_format( float $seconds = 0 ) {
if ( 0 >= $seconds ) {
return $seconds;
}
$seconds = round( $seconds );
$hours_str = '';
if ( $seconds >= HOUR_IN_SECONDS ) {
$hours_str = sprintf(
// translators: 1. The Hours of the datetime.
_n(
'%d h ',
'%d h ',
gmdate( 'H', $seconds ),
'broken-link-checker'
),
gmdate( 'H', $seconds )
);
}
$minutes_str = sprintf(
// translators: 1. The Minutes of the datetime.
_n(
'%d min ',
'%d min ',
gmdate( 'i', $seconds ),
'broken-link-checker'
),
gmdate( 'i', $seconds )
);
$seconds_str = ( $seconds % MINUTE_IN_SECONDS ) > 0 ? sprintf(
// translators: 1. The Seconds of the datetime.
_n(
'%d s ',
'%d s ',
gmdate( 's', $seconds ),
'broken-link-checker'
),
gmdate( 's', $seconds )
) : '';
return $hours_str . $minutes_str . $seconds_str;
}
/**
* Formats a timestamp into a date and time string based on site format.
*
* @param int $timestamp The timestamp to format.
*
* @return string|null
*/
public static function timestamp_to_formatted_date( ?int $timestamp = null, bool $gmt_to_local = false ) {
$timezone = null;
if ( ! $gmt_to_local ) {
$timezone = new DateTimeZone( 'UTC' );
}
return self::format_date( $timestamp, null, $timezone );
}
/**
* Format a time/date
*
* @param integer $timestamp Timestamp.
* @param string|null $format Date/time format.
* @param DateTimeZone|null $timezone Timezone.
*
* @return string
* @todo Rename method to be datetime specific.
*/
public static function format_date( $timestamp, $format = null, $timezone = null ) {
if ( is_null( $format ) ) {
$format = self::get_format();
}
if ( is_null( $timezone ) ) {
$timezone = self::get_timezone();
}
$dt = new DateTime();
$dt->setTimestamp( $timestamp );
$dt->setTimezone( $timezone );
return $dt->format( $format );
}
/**
* Returns datetime format
*
* @return string
* @todo Rename method to be datetime specific.
*/
public static function get_format() {
$format = self::get_date_format();
$format .= _x( ' ', 'date time sep', 'broken-link-checker' );
$format .= self::get_time_format();
return $format;
}
/**
* Returns date format
*
* @return string
*/
public static function get_date_format() {
return get_option( 'date_format' );
}
/**
* Returns user's timezone
*
* @return DateTimeZone
*/
public static function get_timezone() {
return wp_timezone();
}
/**
* Converts a timestamp from UTC to site's local timezone.
*
* @param int|null $timestamp
*
* @return false|int
*/
public static function timestamp_from_UTC( ?int $timestamp = null ) {
$timestamp = is_null( $timestamp ) ? time() : $timestamp;
$timestamp = strlen( $timestamp ) === 13 ? $timestamp / 1000 : $timestamp;
$date_time = DateTime::createFromFormat( 'U', $timestamp, new DateTimeZone( 'UTC' ) );
$date_time->setTimezone( new DateTimeZone( wp_timezone_string() ) );
return strtotime( $date_time->format( 'Y-m-d H:i:s' ) );
}
/**
* Converts microtime to date.
*
* @param int|float $microtime Microtime. Int when sent from API, float from PHP.
* @param string $form Output form. Accepted values 'full_date', 'date', 'day', 'month', 'year', 'time'.
* @param bool $gmt_to_local Convert from GMT to site local timezone. By default, it's false.
*
* @return string|null
*/
public static function microtime_to_date( $microtime = 0, string $form = 'full_date', bool $gmt_to_local = false ) {
if ( ! in_array( $form, array( 'full_date', 'date', 'day', 'month', 'year', 'time' ), true ) ) {
return null;
}
$microtime = ! is_float( $microtime ) ? ( strlen( $microtime ) === 13 ? $microtime / 1000 : $microtime ) : $microtime;
$date_time = null;
if ( strlen( $microtime ) === 10 ) {
$date_time = DateTime::createFromFormat( 'U', $microtime );
} elseif ( strlen( $microtime ) === 13 ) {
$date_time = DateTime::createFromFormat( 'U.u', $microtime );
} else {
return null;
}
$date_format = get_option( 'date_format' );
$time_format = get_option( 'time_format' );
$output = null;
if ( $gmt_to_local ) {
$date_time->setTimezone( new DateTimeZone( wp_timezone_string() ) );
}
switch ( $form ) {
case 'full_date':
$output = $date_time->format( "{$date_format} {$time_format}" );
break;
case 'date':
$output = $date_time->format( $date_format );
break;
case 'day':
$output = $date_time->format( 'd' );
break;
case 'month':
$output = $date_time->format( 'm' );
break;
case 'year':
$output = $date_time->format( 'Y' );
break;
case 'time':
$output = $date_time->format( $time_format );
break;
}
return $output;
}
/**
* Calculates the diff of microtime.
*
* @param int|float|null $micro_start .
* @param int|float|null $micro_end .
* @param string $format .
*
* @return false|float|int|mixed|null
*/
public static function microtimediff( $micro_start = null, $micro_end = null, string $format = 'SEC' ) {
if ( is_null( $micro_start ) ) {
return false;
}
if ( is_null( $micro_end ) ) {
/*
* Multiplying with 1000 so php microtime matches format sent from api.
*/
$micro_end = intval( round( microtime( true ) * 1000 ) );
}
/**
* From APIs the microtime is usually a float.
* The previous condition, if reached, will give an integer, so there is no risk of multiplying by 1000 twice.
*/
$micro_start = is_float( $micro_start ) ? round( $micro_start * 1000 ) : $micro_start;
$micro_end = is_float( $micro_end ) ? round( $micro_end * 1000 ) : $micro_end;
/*
* Microtime has 13 digits as sent from api side.
*/
if ( strlen( $micro_start ) !== 13 || strlen( $micro_end ) !== 13 ) {
return false;
}
$diff = number_format( $micro_end - $micro_start, 2, '.', '' );
switch ( $format ) {
case 'MIN':
$diff = $diff / 1000 / MINUTE_IN_SECONDS;
break;
case 'SEC':
$diff = $diff / 1000;
break;
default:
case 'MICRO':
break;
}
return $diff;
}
/**
* Returns true if plain permalinks iare used.
*
* @return bool
*/
public static function plain_permalinks_mode() {
return empty( get_option( 'permalink_structure' ) );
}
/**
* Checks if site is hosted on localhost.
*
* @return bool
*/
public static function is_localhost() {
return ! wp_doing_cron() &&
isset( $_SERVER['REMOTE_ADDR'] ) &&
in_array( $_SERVER['REMOTE_ADDR'], array( '127.0.0.1', '::1' ), true ) &&
! (
( defined( 'WPMUDEV_DEVELOPMENT_MODE' ) && WPMUDEV_DEVELOPMENT_MODE ) ||
( defined( 'WP_ENVIRONMENT_TYPE' ) && 'local' === WP_ENVIRONMENT_TYPE )
);
}
/**
* Returns an array with all the callbacks for a cron's hook.
*
* @param string $hook .
*
* @return array
*/
public static function get_scheduled_event_callbacks( string $hook = '' ) {
return self::get_hook_callbacks( $hook );
}
/**
* Returns hook callbacks. Taken from WP Crontrol plugin.
*
* @param string $hook .
*
* @return array
*/
public static function get_hook_callbacks( string $hook = '' ) {
global $wp_filter;
$actions = array();
if ( isset( $wp_filter[ $hook ] ) ) {
// See http://core.trac.wordpress.org/ticket/17817.
$action = $wp_filter[ $hook ];
foreach ( $action as $priority => $callbacks ) {
foreach ( $callbacks as $callback ) {
$actions[] = array(
'priority' => $priority,
'callback' => $callback,
);
}
}
}
return $actions;
}
/**
* Returns replaced value based on array keys and callbacks/values from a given mapped array.
*
* @param string $content The string that contains the content we need to replace the mapped values.
* @param array $map An array mapping keys and values/callbacks.
* @param string $context An optional string holding a context. Used in filter to help in specificity.
* @param array $keys Optional. An array of keys to map in given mapped array. If empty all $map's array keys will be used.
*
* @return string
*/
public static function replace_mapped_values( string $content = '', array $map = array(), ?string $context = null, array $keys = array() ) {
if ( empty( $map ) ) {
return $content;
}
if ( empty( $keys ) ) {
$keys = array_keys( $map );
}
$mapped_values = array_fill_keys( $keys, null );
foreach ( $keys as $key ) {
$mapped_values[ $key ] = self::get_mapped_value( $map[ $key ], $context );
}
return str_replace( array_keys( $mapped_values ), array_values( $mapped_values ), $content );
}
/**
* Returns replaced value based on array keys and callbacks/values from a given mapped array.
*
* @param mixed $input An array mapping keys and values/callbacks.
* @param string $context An optional string holding a context. Used in filter to help in specificity.
*/
public static function get_mapped_value( $input = null, ?string $context = null ) {
if ( is_null( $input ) ) {
return null;
}
return apply_filters(
'wpmudev_blc_replace_mapped_value',
is_callable( $input ) ? call_user_func( $input ) : $input,
$input,
$context
);
}
/**
* Verifies is input code is a valid http response code.
*
* @param int $code The code to verify.
*
* @return bool
*/
public static function valid_http_response_code( int $code = 0 ) {
// HTTP Response codes should be between 100 and 599: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status.
return is_int( $code ) && $code >= 100 && $code <= 599;
}
/**
* Logs messages in either `wp-content/debug.log` by default or to a given file path. Requires `WP_DEBUG_LOG` to be set to true.
*
* @param string $message The message to be logged.
* @param string $file Optional. Log file path. If not set `wp-content/debug.log` will be used. File path has to be relative to WP_CONTENT_DIR.
*
* @return void
*/
public static function log( string $message = '', string $file_path = '' ) {
if ( ! defined( 'WPMUDEV_BLC_LOG' ) || ! WPMUDEV_BLC_LOG ) {
return;
}
$month = date( 'm' );
$year = date( 'Y' );
$default_log_file = "/blc-logs/debug-{$year}-{$month}.log";
if ( empty( $file_path ) ) {
$file_path = $default_log_file;
}
$dt_string = date( self::get_date_format() . ' ' . self::get_time_format() );
$file_path = wp_normalize_path( path_join( WP_CONTENT_DIR, ltrim( $file_path, '/' ) ) );
if ( ! is_dir( dirname( $file_path ) ) ) {
mkdir( dirname( $file_path ), 0755, true );
}
if ( ! file_exists( $file_path ) ) {
$new_file = fopen( $file_path, 'w' );
if ( ! $new_file ) {
return;
}
fclose( $new_file );
}
error_log( "[{$dt_string}] $message \n", 3, $file_path );
}
/**
* Provides a flag that determines if plugin should go through links more extensively.
*
* @param $param
*
* @return bool
*/
public static function process_extensive( $param = null ) {
return apply_filters( 'wpmudev_blc_process_extensive', false, $param );
}
}