: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
$this->libxml_disable_entity_loader( true );
return simplexml_load_string( $data );
* Creates a path string using the provided arguments.
* et_()->path( '/this/is', 'a', 'path' );
* // Returns '/this/is/a/path'
* et_()->path( ['/this/is', 'a', 'path', 'to', 'file.php'] );
* // Returns '/this/is/a/path/to/file.php'
* @param string|string[] ...$parts
$parts = func_get_args();
if ( 1 === count( $parts ) && is_array( reset( $parts ) ) ) {
$parts = array_pop( $parts );
foreach ( $parts as $part ) {
return substr( $path, 0, -1 );
* Process an XML-RPC response string.
public function process_xmlrpc_response( $response, $skip_processing = false ) {
$response = $this->simplexml_load_string( $response );
if ( $skip_processing ) {
if ( count( $response->fault ) > 0 ) {
return $this->_parse_value( $response->fault->value );
$single = count( $response->params->param ) === 1;
foreach ( $response->params->param as $param ) {
$value = $this->_parse_value( $param->value );
* Removes empty directories recursively starting at and (possibly) including `$path`. `$path` must be
* an absolute path located under {@see WP_CONTENT_DIR}. Current user must have 'manage_options'
* capability. If the path or permissions check fails, no directories will be removed.
* @param string $path Absolute path to parent directory.
public function remove_empty_directories( $path ) {
$path = realpath( $path );
$path = $this->normalize_path( $path );
$content_dir = $this->normalize_path( WP_CONTENT_DIR );
if ( 0 !== strpos( $path, $content_dir ) || $content_dir === $path ) {
$capability = 0 === strpos( $path, "{$content_dir}/cache/et" ) ? 'edit_posts' : 'manage_options';
if ( ! wp_doing_cron() && ! et_core_security_check_passed( $capability ) ) {
$this->_remove_empty_directories( $path );
* Whether or not a value includes another value.
* @param mixed $haystack The value to look in.
* @param string $needle The value to look for.
public function includes( $haystack, $needle ) {
if ( is_string( $haystack ) ) {
return false !== strpos( $haystack, $needle );
if ( is_object( $haystack ) ) {
return property_exists( $haystack, $needle );
if ( is_array( $haystack ) ) {
return in_array( $needle, $haystack );
public function sanitize_text_fields( $fields ) {
if ( ! is_array( $fields ) ) {
return sanitize_text_field( $fields );
foreach ( $fields as $field_id => $field_value ) {
$field_id = sanitize_text_field( $field_id );
if ( is_array( $field_value ) ) {
$field_value = $this->sanitize_text_fields( $field_value );
$field_value = sanitize_text_field( $field_value );
$result[ $field_id ] = $field_value;
* Recursively traverses an array and escapes the keys and values according to passed escaping function.
* @param array $values The array to be recursively escaped.
* @param string $escaping_function The escaping function to be used on keys and values. Default 'esc_html'. Optional.
public function esc_array( $values, $escaping_function = 'esc_html' ) {
if ( ! is_array( $values ) ) {
return $escaping_function( $values );
foreach ( $values as $key => $value ) {
$key = $escaping_function( $key );
if ( is_array( $value ) ) {
$value = $this->esc_array( $value, $escaping_function );
$value = $escaping_function( $value );
$result[ $key ] = $value;
* Transforms an array of data into a new array based on the provided transformation definition.
* @since 3.10 Renamed from `transform_data_to` to `array_transform`.
* @param array $data The data to transform.
* @param array $data_map Transformation definition. See examples below.
* @param string $direction The direction in which to transform. Accepts '->', '<-'. Default '->'
* @param array $exclude_keys Keys that should be excluded from the result. Optional.
public function array_transform( $data, $data_map, $direction = '->', $exclude_keys = array() ) {
if ( ! in_array( $direction, array( '->', '<-' ) ) ) {
foreach ( $data_map as $address_1 => $address_2 ) {
$from_address = '->' === $direction ? $address_1 : $address_2;
$to_address = '->' === $direction ? $address_2 : $address_1;
$array_value_required = $negate_bool_value = false;
if ( 0 === strpos( $to_address, '@' ) || 0 === strpos( $from_address, '@' ) ) {
$array_value_required = true;
$to_address = ltrim( $to_address, '@' );
$from_address = ltrim( $from_address, '@' );
} else if ( 0 === strpos( $to_address, '!' ) || 0 === strpos( $from_address, '!' ) ) {
$negate_bool_value = true;
$to_address = ltrim( $to_address, '!' );
$from_address = ltrim( $from_address, '!' );
if ( ! empty( $exclude_keys ) && array_key_exists( $to_address, $exclude_keys ) ) {
$value = $this->array_get( $data, $from_address, null );
if ( $array_value_required && ! is_array( $value ) ) {
$value = array( $value );
} else if ( $negate_bool_value ) {
$this->array_set( $result, $to_address, $value );
* Converts xml data to array. Useful in cases where the xml doesn't adhere to XML-RPC spec.
* @param string|\SimpleXMLElement $xml_data
public function xml_to_array( $xml_data ) {
if ( is_string( $xml_data ) ) {
$xml_data = $this->simplexml_load_string( $xml_data );
$json = wp_json_encode( $xml_data );
return json_decode( $json, true );
* Make sure that in provided selector do not exist sub-selectors that targets inputs placeholders
* If they exist they should be split in an apart selector.
* @param string $selector
* @return array Return a list of selectors
public function sanitize_css_placeholders( $selector ) {
$selectors = explode( ',', $selector );
$selectors = array_map( 'trim', $selectors );
$selectors = array_filter( $selectors );
$main_selector = array();
'::-webkit-input-placeholder',
':-ms-input-placeholder',
// No need to sanitize if is a single selector or even no selectors at all
// Also if selectors do not contain placeholder meta-selector
if ( count( $selectors ) < 2 || ! preg_match( '/' . implode( '|', $placeholders ) . '/', $selector ) ) {
return array( $selector );
foreach ( $selectors as $_selector ) {
foreach ( $placeholders as $placeholder ) {
if ( strpos( $_selector, $placeholder ) !== false ) {
$exceptions[] = $_selector;
$main_selector[] = $_selector;
return array_filter( array_merge( array( implode( ', ', $main_selector ) ), $exceptions ) );
* Whether or not a string starts with a substring.
* @param string $substring
public function starts_with( $string, $substring ) {
return 0 === strpos( $string, $substring );
* Convert string to camel case format.
* @param string $string Original string data.
* @param array $no_strip Additional regex pattern exclusion.
public function camel_case( $string, $no_strip = array() ) {
$words = preg_split( '/[^a-zA-Z0-9' . implode( '', $no_strip ) . ']+/i', strtolower( $string ) );
if ( count( $words ) === 1 ) {
$camel_cased = implode( '', array_map( 'ucwords', $words ) );
$camel_cased[0] = strtolower( $camel_cased[0] );
* Returns the WP Filesystem instance.
* @return WP_Filesystem_Base {@see ET_Core_PageResource::wpfs()}
return et_core_cache_dir()->wpfs;
* Equivalent of usort but preserves relative order of equally weighted values.
* @param callable $comparison_function
public function usort( &$array, $comparison_function ) {
return $this->_user_sort( $array, 'usort', $comparison_function );
* Equivalent of uasort but preserves relative order of equally weighted values.
* @param callable $comparison_function
public function uasort( &$array, $comparison_function ) {
return $this->_user_sort( $array, 'uasort', $comparison_function );
* Equivalent of uksort but preserves relative order of equally weighted values.
* @param callable $comparison_function
public function uksort( &$array, $comparison_function ) {
return $this->_user_sort( $array, 'uksort', $comparison_function );
* Returns a string with a valid CSS property value.
* With some locales (ex: ro_RO) the decimal point can be ',' (comma) and
* we need to convert that to a '.' (period) decimal point to ensure that
* the value is a valid CSS property value.
* @param float $float Original float value.
public function to_css_decimal( $float ) {
return strtr( $float, ',', '.' );
* Sort using a custom function accounting for the common undefined order
* pitfall due to a return value of 0.
* @param array &$array Array to sort
* @param callable $sort_function "usort", "uasort" or "uksort"
* @param callable $comparison_function Custom comparison function
protected function _user_sort( &$array, $sort_function, $comparison_function ) {
$allowed_sort_functions = array( 'usort', 'uasort', 'uksort' );
if ( ! $this->includes( $allowed_sort_functions, $sort_function ) ) {
_doing_it_wrong( __FUNCTION__, esc_html__( 'Only custom sorting functions can be used.', 'et_core' ), esc_html( et_get_theme_version() ) );
// Use properties temporarily to pass values in order to preserve PHP 5.2 support.
$this->sort_arguments['array'] = $array;
$this->sort_arguments['sort'] = $sort_function;
$this->sort_arguments['comparison'] = $comparison_function;
$this->sort_arguments['array_map'] = 'uksort' === $sort_function
? array_flip( array_keys( $array ) )
: array_values( $array );
$sort_function( $array, array( $this, '_user_sort_callback' ) );
$this->sort_arguments['array'] = array();
$this->sort_arguments['array_map'] = array();
$this->sort_arguments['sort'] = '__return_false';
$this->sort_arguments['comparison'] = '__return_false';
* Sort callback only meant to acompany self::sort().
* Do not use outside of self::_user_sort().
protected function _user_sort_callback( $a, $b ) {
// @phpcs:ignore Generic.PHP.ForbiddenFunctions.Found
$result = (int) call_user_func( $this->sort_arguments['comparison'], $a, $b );
if ( 'uksort' === $this->sort_arguments['sort'] ) {
// Intentional isset() use for performance reasons.
$a_order = isset( $this->sort_arguments['array_map'][ $a ] ) ? $this->sort_arguments['array_map'][ $a ] : false;
$b_order = isset( $this->sort_arguments['array_map'][ $b ] ) ? $this->sort_arguments['array_map'][ $b ] : false;
$a_order = array_search( $a, $this->sort_arguments['array_map'] );
$b_order = array_search( $b, $this->sort_arguments['array_map'] );
if ( false === $a_order || false === $b_order ) {
// This should not be possible so we fallback to the undefined
// sorting behavior by returning 0.
return $a_order - $b_order;
* Returns RFC 4211 compliant Universally Unique Identifier (UUID) version 4
* https://tools.ietf.org/html/rfc4122
* @param array $random_sequence The initial random sequence. Mostly used for test purposes.
public static function uuid_v4( $random_sequence = null ) {
for ( $i = 0; $i < 16; $i++) {
$buffer[] = isset( $random_sequence[ $i ] ) ? $random_sequence[ $i ] : mt_rand(0, 0xff);