: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* SitePress Template functions
use function WPML\Container\make;
* Returns true if the site uses ICanLocalize.
function wpml_site_uses_icl() {
$setting = 'site_does_not_use_icl';
if ( icl_get_setting( $setting, false ) ) {
$cache = new WPML_WP_Cache( 'wpml-checks' );
$site_uses_icl = $cache->get( 'site_uses_icl', $found );
$table_exists = $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}icl_translation_status'" );
$icl_job_count_query = $wpdb->prepare( "SELECT rid
FROM {$wpdb->prefix}icl_translation_status
WHERE translation_service = %s
LIMIT 1;", 'icanlocalize' );
$site_uses_icl = (bool) $wpdb->get_var( $icl_job_count_query );
$cache->set( 'site_uses_icl', $site_uses_icl );
if ( icl_get_setting( 'setup_complete', false ) && ! $site_uses_icl ) {
icl_set_setting( $setting, true, true );
* Returns the value of a given key setting.
* @param string $key The setting's key.
* @param mixed|false $default The value to use if the setting does not exist.
* @deprecated 3.2 use `\wpml_setting` or 'wpml_get_setting_filter' filter instead
function icl_get_setting( $key, $default = false ) {
return wpml_get_setting( $key, $default );
* Get a WPML setting value.
* If the Main SitePress Class cannot be accessed by the function it will read the setting from the database.
* It will return `$default` if the requested key is not set.
* @param string $key The setting's key.
* @param mixed|null $default Required. The value to return if the settings key does not exist
* (typically it's false, but you may want to use something else).
* @return mixed The value of the requested setting, or `$default`
function wpml_get_setting( $key, $default = null ) {
global $sitepress_settings;
$sitepress_settings = isset( $sitepress_settings ) ? $sitepress_settings : get_option( 'icl_sitepress_settings' );
return isset( $sitepress_settings[ $key ] ) ? $sitepress_settings[ $key ] : $default;
* Get a WPML setting value.
* If the Main SitePress Class cannot be access to the function will read the setting from the database.
* Will return false if the requested key is not set or.
* the default value passed in the function's second parameter.
* @param mixed|false $default Required. The value to return if the settings key does not exist
* (typically it's false, but you may want to use something else).
* @param string $key The setting's key.
* @return mixed The value of the requested setting, or $default
* @use \SitePress::api_hooks
function wpml_get_setting_filter( $default, $key ) {
if ( count( $args ) > 2 && $args[2] !== null ) {
return wpml_get_setting( $key, $default );
* Returns the value of a given key sub-setting.
* @param string $key The setting's key.
* @param string $sub_key The settings name key to return the value of.
* @param mixed|false $default Required. The value to return if the settings key does not exist
* (typically it's false, but you may want to use something else).
* @deprecated 3.2 use 'wpml_sub_setting' filter instead
function icl_get_sub_setting( $key, $sub_key, $default = false ) {
$parent = icl_get_setting( $key, array() );
return isset( $parent[ $sub_key ] ) ? $parent[ $sub_key ] : $default;
* Gets a WPML sub setting value.
* @uses \wpml_get_setting_filter
* @param mixed|false $default Required. The value to return if the settings key does not exist
* (typically it's false, but you may want to use something else).
* @param string $key The settings name key the sub key belongs to.
* @param string $sub_key The sub key to return the value of.
* @param mixed $deprecated Deprecated param.
* @todo [WPML 3.3] Remove deprecated argument
* @return mixed The value of the requested setting, or $default
* @use \SitePress::api_hooks
function wpml_get_sub_setting_filter( $default, $key, $sub_key, $deprecated = null ) {
$default = null !== $deprecated && ! $default ? $deprecated : $default;
$parent = wpml_get_setting_filter( array(), $key );
return isset( $parent[ $sub_key ] ) ? $parent[ $sub_key ] : $default;
* Saves the value of a given key.
* @param string $key The settings name key the sub key belongs to.
* @param mixed $value The value to assign to the given key.
* @param bool $save_now Must call icl_save_settings() to permanently store the value.
* @return bool Always True. If `$save_now === true`, it returns the result of `update_option`
function icl_set_setting( $key, $value, $save_now = false ) {
global $sitepress_settings;
$sitepress_settings[ $key ] = $value;
if ( true === $save_now ) {
/* We need to save settings anyway, in this case. */
$result = update_option( 'icl_sitepress_settings', $sitepress_settings );
do_action( 'icl_save_settings', $sitepress_settings );
* Save the settings in the db.
function icl_save_settings() {
$sitepress->save_settings();
function icl_get_settings() {
return isset( $sitepress ) ? $sitepress->get_settings() : false;
* Add settings link to plugin page.
function icl_plugin_action_links( $links, $file ) {
if ( $file == WPML_PLUGIN_BASENAME ) {
$links[] = '<a href="admin.php?page=' . WPML_PLUGIN_FOLDER . '/menu/languages.php">' . __( 'Configure', 'sitepress' ) . '</a>';
if ( defined( 'ICL_DEBUG_MODE' ) && ICL_DEBUG_MODE ) {
add_action( 'admin_notices', '_icl_deprecated_icl_debug_mode' );
function _icl_deprecated_icl_debug_mode() {
echo '<div class="updated"><p><strong>ICL_DEBUG_MODE</strong> no longer supported. Please use <strong>WP_DEBUG</strong> instead.</p></div>';
if ( ! function_exists( 'icl_js_escape' ) ) {
function icl_js_escape( $str ) {
$str = htmlspecialchars_decode( $str );
* Read and, if needed, generate the site ID based on the scope.
* @param string $scope Defaults to "global".
* Use a different value when the ID is used for specific scopes.
* @param bool $create_new Forces the creation of a new ID.
* @return string|null The generated/stored ID or null if it wasn't possible to generate/store the value.
function wpml_get_site_id( $scope = WPML_Site_ID::SITE_SCOPES_GLOBAL, $create_new = false ) {
$site_id = new WPML_Site_ID();
return $site_id->get_site_id( $scope, $create_new );
function _icl_tax_has_objects_recursive( $id, $term_id = -1, $rec = 0 ) {
// based on the case where two categories were one the parent of another
// eliminating the chance of infinite loops by letting this function calling itself too many times
// 100 is the default limit in most of teh php configuration
// this limit this function to work only with categories nested up to 60 levels
// should enough for most cases
$term_id = $wpdb->get_var( $wpdb->prepare( "SELECT term_id FROM {$wpdb->term_taxonomy} WHERE term_taxonomy_id=%d", $id ) );
$children = $wpdb->get_results( $wpdb->prepare( "
SELECT term_taxonomy_id, term_id, count FROM {$wpdb->term_taxonomy} WHERE parent = %d
foreach ( $children as $ch ) {
foreach ( $children as $ch ) {
if ( _icl_tax_has_objects_recursive( $ch->term_taxonomy_id, $ch->term_id, $rec + 1 ) ) {
function _icl_trash_restore_prompt() {
if ( isset( $_GET['lang'] ) ) {
$post = get_post( intval( $_GET['post'] ) );
if ( isset( $post->post_status ) && $post->post_status == 'trash' ) {
$post_type_object = get_post_type_object( $post->post_type );
$delete_post_link = '<a href="' . esc_url( get_delete_post_link( $post->ID, '', true ) ) . '">' . esc_html( 'delete it permanently', 'sitepress' ) . '</a>';
$restore_post_link = '<a href="' . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&action=untrash', $post->ID ) ), 'untrash-post_' . $post->ID ) . '">' . esc_html( 'restore', 'sitepress' ) . '</a>';
$ret = '<p>' . sprintf( esc_html__( 'This translation is currently in the trash. You need to either %s or %s it in order to continue.' ), $delete_post_link, $restore_post_link );
* Build or update duplicated posts from a master post.
* @param string $master_post_id The ID of the post to duplicate from. Master post doesn't need to be in the default language.
* @uses TranslationManagement
* @deprecated 3.2 use 'wpml_admin_make_duplicates' action instead
function icl_makes_duplicates( $master_post_id ) {
wpml_admin_make_post_duplicates_action( $master_post_id );
* Build or update duplicated posts from a master post.
* To be used only for admin backend actions
* @see $iclTranslationManagement in \SitePress:: __construct
* @param int $master_post_id The ID of the post to duplicate from.
* The ID can be that of a post, page or custom post
* Master post doesn't need to be in the default language.
* @uses TranslationManagement
* @use \SitePress::api_hooks
function wpml_admin_make_post_duplicates_action( $master_post_id ) {
$post = get_post( $master_post_id );
$post_type = $post->post_type;
if ( $post->post_status == 'auto-draft' || $post->post_type == 'revision' ) {
$iclTranslationManagement = wpml_load_core_tm();
if ( $sitepress->is_translated_post_type( $post_type ) ) {
$iclTranslationManagement->make_duplicates_all( $master_post_id );
* Build duplicated posts from a master post only in case of the duplicate not being present at the time.
* @param string $master_post_id The ID of the post to duplicate from. Master post doesn't need to be in the default language.
* @deprecated 3.2 use 'wpml_make_post_duplicates' action instead
function icl_makes_duplicates_public( $master_post_id ) {
wpml_make_post_duplicates_action( $master_post_id );
* Build duplicated posts from a master post only in case of the duplicate not being present at the time.
* @param int $master_post_id The ID of the post to duplicate from.
* Master post doesn't need to be in the default language.
* @use \SitePress::api_hooks
* @deprecated This function will be removed in future releases.
function wpml_make_post_duplicates_action( $master_post_id ) {
$master_post = get_post( $master_post_id );
if ( 'auto-draft' === $master_post->post_status || 'revision' === $master_post->post_type ) {
$active_langs = $sitepress->get_active_languages();
foreach ( $active_langs as $lang_to => $one ) {
$trid = $sitepress->get_element_trid( $master_post->ID, 'post_' . $master_post->post_type );
$lang_from = $sitepress->get_source_language_by_trid( $trid );
if ( $lang_from == $lang_to ) {
$sitepress->make_duplicate( $master_post_id, $lang_to );
* Wrapper function for deprecated like_escape() and recommended wpdb::esc_like()
function wpml_like_escape( $text ) {
if ( method_exists( $wpdb, 'esc_like' ) ) {
return $wpdb->esc_like( $text );
/** @noinspection PhpDeprecationInspection */
return like_escape( $text );
function icl_do_not_promote() {
return defined( 'ICL_DONT_PROMOTE' ) && ICL_DONT_PROMOTE;
function icl_convert_to_user_time( $time ) {
//offset between server time and user time in seconds
$time_offset = get_option( 'gmt_offset' )*3600;
$local_time = __( 'Last Update Time could not be determined', 'sitepress' );
//unix time stamp in server time
$creation_time = strtotime( $time );
//creating dates before 2014 are impossible
if ( $creation_time !== false ) {
$local_time = date( 'Y-m-d H:i:s', $creation_time + $time_offset );
} catch ( Exception $e ) {
//Ignoring the exception, as we already set the default value in $local_time
* Check if given language is activated
* @global sitepress $sitepress
* @param string $language 2 letters language code
* @deprecated 3.2 use 'wpml_language_is_active' filter instead
function icl_is_language_active( $language ) {
$active_languages = $sitepress->get_active_languages();
return isset( $active_languages[ $language ] );
* Checks if given language is enabled
* @global sitepress $sitepress
* @param mixed $empty_value This is normally the value the filter will be modifying.
* We are not filtering anything here therefore the NULL value
* This for the filter function to actually receive the full argument list:
* apply_filters('wpml_language_is_active', '', $language_code);
* @param string $language_code The language code to check Accepts a 2-letter language code
* @use \SitePress::api_hooks
function wpml_language_is_active_filter( $empty_value, $language_code ) {
return $sitepress->is_active_language( $language_code );
* @param string $url url either with or without schema
* Removes the subdirectory in which WordPress is installed from a url.
* If WordPress is not installed in a subdirectory, then the input is returned unaltered.
* @return string the url input without the blog's subdirectory. Potentially existing schemata on the input are kept intact.
function wpml_strip_subdir_from_url( $url ) {
/** @var WPML_URL_Converter $wpml_url_converter */
global $wpml_url_converter;
$subdir = wpml_parse_url( $wpml_url_converter->get_abs_home(), PHP_URL_PATH );
$subdir_slugs = array_values( array_filter( explode( '/', $subdir ) ) );
$url_path_expl = explode( '/', preg_replace( '#^(http|https)://#', '', $url ) );
array_shift( $url_path_expl );