<?php
/**
* Get default settings
*
 * @return array
 */
function wpmsProGetDefaultSettings()
{
    return array(
        'home_meta_active'       => 1,
        'metaseo_title_home'     => '',
        'metaseo_desc_home'      => '',
        'metaseo_showfacebook'   => '',
        'metaseo_showfbappid'    => '',
        'metaseo_showtwitter'    => '',
        'metaseo_twitter_card'   => 'summary',
        'metaseo_showkeywords'   => 0,
        'metaseo_showtmetablock' => 1,
        'metaseo_showsocial'     => 1,
        'metaseo_seovalidate'    => 0,
        'metaseo_linkfield'      => 1,
        'metaseo_metatitle_tab'  => 1,
        'metaseo_follow'         => 0,
        'metaseo_index'          => 0,
        'metaseo_overridemeta'   => 1,
        'metaseo_canonical' => 0,
        'metaseo_removecatprefix' => 0,
        'metaseo_linkeditor' => 0,
        'metaseo_specific_keywords' => '',
        'metaseo_enable_default_fb_image' => array(
            'active' => 0,
            'source' => 'featured',
            'default_set' => ''
        ),
        'metaseo_enable_default_twitter_image' => array(
            'active' => 0,
            'source' => 'featured',
            'default_set' => ''
        ),
    );
}

/**
 * Get a option
 *
 * @param string $option_name Option name
 *
 * @return mixed
 */
function wpmsProGetOption($option_name)
{
    $default_settings = wpmsProGetDefaultSettings();
    $settings         = get_option('_metaseo_settings');
    if (isset($settings) && isset($settings[$option_name])) {
        return $settings[$option_name];
    }

    return $default_settings[$option_name];
}

/**
 * Retrieve the date of the post/page/cpt for use as replacement string
 *
 * @param object $current_post Current post info
 *
 * @return string|null
 */
function wpmsProRetrieveDate($current_post)
{
    $replacement = null;
    if (isset($current_post->post_date) && $current_post->post_date !== '') {
        $replacement = mysql2date(get_option('date_format'), $current_post->post_date, true);
    } else {
        if (get_query_var('day') && get_query_var('day') !== '') {
            $replacement = get_the_date();
        } else {
            if (single_month_title(' ', false) && single_month_title(' ', false) !== '') {
                $replacement = single_month_title(' ', false);
            } elseif (get_query_var('year') !== '') {
                $replacement = get_query_var('year');
            }
        }
    }

    return $replacement;
}


/**
 * Extract specific HTML tags and their attributes from a string.
 *
 * You can either specify one tag, an array of tag names, or a regular expression that matches the tag name(s).
 * If multiple tags are specified you must also set the $selfclosing parameter and it must be the same for
 * all specified tags (so you can't extract both normal and self-closing tags in one go).
 *
 * The function returns a numerically indexed array of extracted tags. Each entry is an associative array
 * with these keys :
 *    tag_name    - the name of the extracted tag, e.g. "a" or "img".
 *    offset        - the numberic offset of the first character of the tag within the HTML source.
 *    contents    - the inner HTML of the tag. This is always empty for self-closing tags.
 *    attributes    - a name -> value array of the tag's attributes, or an empty array if the tag has none.
 *    full_tag    - the entire matched tag, e.g. '<a href="http://example.com">example.com</a>'. This key
 *                  will only be present if you set $return_the_entire_tag to true.
 *
 * @param string       $html                  The HTML code to search for tags.
 * @param string|array $tag                   The tag(s) to extract.
 * @param boolean      $selfclosing           Whether the tag is self-closing or not.
 *                                            Setting it to null will force the script to try and make an educated guess.
 * @param boolean      $return_the_entire_tag Return the entire matched tag in 'full_tag' key of the results array.
 * @param string       $charset               The character set of the HTML code. Defaults to ISO-8859-1.
 *
 * @return array An array of extracted tags, or an empty array if no matching tags were found.
 */
function wpmsProExtractTags(
    $html,
    $tag,
    $selfclosing = null,
    $return_the_entire_tag = false,
    $charset = 'ISO-8859-1'
) {

    if (is_array($tag)) {
        $tag = implode('|', $tag);
    }

    $selfclosing_tags = array(
        'area',
        'base',
        'basefont',
        'br',
        'hr',
        'input',
        'img',
        'link',
        'meta',
        'col',
        'param'
    );
    if (is_null($selfclosing)) {
        $selfclosing = in_array($tag, $selfclosing_tags);
    }

    if ($selfclosing) {
        $tag_pattern = '@<(?P<tag>' . $tag . ')			# <tag
				(?P<attributes>\s[^>]+)?		# attributes, if any
				\s*/?>							# /> or just >, being lenient here 
				@xsi';
    } else {
        $tag_pattern = '@<(?P<tag>' . $tag . ')			# <tag
				(?P<attributes>\s[^>]+)?		# attributes, if any
				\s*>							# >
				(?P<contents>.*?)				# tag contents
				</(?P=tag)>						# the closing </tag>
				@xsi';
    }

    $attribute_pattern = '@
			(?P<name>\w+)											# attribute name
			\s*=\s*
			(
				(?P<quote>[\"\'])(?P<value_quoted>.*?)(?P=quote)	# a quoted value
				|							# or
				(?P<value_unquoted>[^\s"\']+?)(?:\s+|$)	 # an unquoted value (terminated by whitespace or EOF) 
			)
			@xsi';

    //Find all tags
    if (!preg_match_all($tag_pattern, $html, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) {
        //Return an empty array if we didn't find anything
        return array();
    }

    $tags = array();
    foreach ($matches as $match) {
        //Parse tag attributes, if any
        $attributes = array();
        if (!empty($match['attributes'][0])) {
            if (preg_match_all($attribute_pattern, $match['attributes'][0], $attribute_data, PREG_SET_ORDER)) {
                //Turn the attribute data into a name->value array
                foreach ($attribute_data as $attr) {
                    if (!empty($attr['value_quoted'])) {
                        $value = $attr['value_quoted'];
                    } elseif (!empty($attr['value_unquoted'])) {
                        $value = $attr['value_unquoted'];
                    } else {
                        $value = '';
                    }

                    //Passing the value through html_entity_decode is handy when you want
                    //to extract link URLs or something like that. You might want to remove
                    //or modify this call if it doesn't fit your situation.
                    $value = html_entity_decode($value, ENT_QUOTES, $charset);

                    $attributes[$attr['name']] = $value;
                }
            }
        }

        $tag = array(
            'tag_name'   => $match['tag'][0],
            'offset'     => $match[0][1],
            'contents'   => !empty($match['contents']) ? $match['contents'][0] : '', //empty for self-closing tags
            'attributes' => $attributes,
        );
        if ($return_the_entire_tag) {
            $tag['full_tag'] = $match[0][0];
        }

        $tags[] = $tag;
    }

    return $tags;
}
/**
 * Get breadcrumb
 *
 * @param boolean $return  Return breadcrumb or not
 * @param boolean $reverse Reverse breadcrumb or not
 *
 * @return string
 */
function wpmsProBreadcrumb($return = false, $reverse = false)
{
    require_once(WPMETASEO_ADDON_PLUGIN_DIR . 'inc/breadcrumb/class.metaseo-breadcrumb.php');
    $breadcrumb = new MetaSeoBreadcrumb;
    if ($breadcrumb !== null) {
        $breadcrumb->checkPosts();
        return $breadcrumb->breadcrumbDisplay($return, $reverse);
    }
    return '';
}

    /**
     * Create shortcode for breadcrumb
     *
     * @param array $params Shortcode attribute
     *
     * @return string
     */
function wpmsBreadcrumbShortcode($params)
{
    $html = '<div class="breadcrumbs" typeof="BreadcrumbList" vocab="https://schema.org/">';
    if (isset($params['reverse']) && (int)$params['reverse'] === 1) {
        $html .= wpmsProBreadcrumb(true, true);
    } else {
        $html .= wpmsProBreadcrumb(true, false);
    }
    $html .= '</div>';

    return $html;
}

/**
 * WPMS frontend head
 *
 * @return void
 */
function wpmshead()
{
    global $wp_query;

    $old_wp_query = null;

    if (!$wp_query->is_main_query()) {
        $old_wp_query = $wp_query;
        wp_reset_query();
    }

    do_action('wpmsseo_head');

    if (!empty($old_wp_query)) {
        // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- This combines all the output on the frontend
        $GLOBALS['wp_query'] = $old_wp_query;
        unset($old_wp_query);
    }
}

/**
 * Render meta title tag
 *
 * @param string $title Title
 *
 * @return mixed|string
 */
function wpmstitle($title)
{
    global $wp_query;
    $default_settings = wpmsProGetDefaultSettings();
    $settings         = get_option('_metaseo_settings');
    if (is_array($settings)) {
        $settings = array_merge($default_settings, $settings);
    } else {
        $settings = $default_settings;
    }
    if (empty($settings)) {
        return esc_html($title);
    }

    if (empty($settings['metaseo_metatitle_tab'])) {
        return esc_html($title);
    }
    if (empty($wp_query->post)) {
        return esc_html($title);
    }

    $is_shop = false;
    if (function_exists('is_shop')) {
        if (is_shop()) {
            $is_shop = true;
            $id      = wc_get_page_id('shop');
        } else {
            $id = $wp_query->post->ID;
        }
    } else {
        $id = $wp_query->post->ID;
    }

    $opengraph  = new MetaSeoOpenGraph();
    $meta_title = $opengraph->getTitle($is_shop, $id);

    if (is_home()) {
        $metas      = $opengraph->getHome($settings);
        $meta_title = $metas['title'];
    }

    // is front page
    if (is_front_page() && 'page' === get_option('show_on_front') && is_page(get_option('page_on_front'))) {
        $metas      = $opengraph->getFrontPageMeta($settings, $id);
        $meta_title = $metas['title'];
    }

    $term = $wp_query->get_queried_object();
    if (is_category() || is_tag() || is_tax()) {
        if (function_exists('get_term_meta')) {
            $meta_title = get_term_meta($term->term_id, 'wpms_category_metatitle', true);
        } else {
            $meta_title = get_metadata('term', $term->term_id, 'wpms_category_metatitle', true);
        }

        $meta_title = $opengraph->replaceSnippet($meta_title, null, $term);
    } elseif (is_post_type_archive()) { //use WP default title of archive page for custom post type
        $meta_title = '';
    }

    if (empty($meta_title)) {
        $meta_title = $title;
    }

    return esc_html($meta_title);
}

/**
 * Render graph meta tag
 *
 * @return void
 */
function wpmsopengraph()
{
    global $wp_query;
    $is_shop = false;
    if (function_exists('is_shop')) {
        if (is_shop()) {
            $is_shop = true;
            $id      = wc_get_page_id('shop');
            $post    = get_post($id);
            $content = $post->post_content;
        } else {
            if (empty($wp_query->post)) {
                return;
            }
            if ($wp_query->post->post_password && post_password_required()) {
                return;
            }
            $id      = $wp_query->post->ID;
            $content = $wp_query->post->post_content;
        }
    } else {
        if (empty($wp_query->post)) {
            return;
        }
        if ($wp_query->post->post_password && post_password_required()) {
            return;
        }
        $id      = $wp_query->post->ID;
        $content = $wp_query->post->post_content;
    }
    wp_reset_query();

    $default_settings = wpmsProGetDefaultSettings();
    $settings         = get_option('_metaseo_settings');
    if (is_array($settings)) {
        $settings = array_merge($default_settings, $settings);
    } else {
        $settings = $default_settings;
    }

    // get meta title
    $opengraph      = new MetaSeoOpenGraph();
    $meta_title     = $opengraph->getTitle($is_shop, $id);
    $meta_title_esc = $opengraph->getMetaTitle($settings, $meta_title);
    // get meta description
    $meta_desc_esc = $opengraph->getDesc($settings, $id, $content);
    // get meta keyword
    $meta_keywords_esc = $opengraph->getKeyword($settings, $id);

    $page_follow       = get_post_meta($id, '_metaseo_metafollow', true);
    $page_index        = get_post_meta($id, '_metaseo_metaindex', true);
    // get meta title for twitter
    $meta_twtitle = $opengraph->getTwtitle($id);
    // get meta description for twitter
    $meta_twdesc = $opengraph->getTwdesc($id);
    // get twiter card
    $meta_twcard = $opengraph->getTwCard($settings);

    // get facebook admin and twiter site meta
    $usermeta          = $opengraph->getUserMeta($settings, $id);
    $meta_twitter_site = $usermeta['meta_twitter_site'];
    $facebook_admin    = $usermeta['facebook_admin'];
    $sitename          = get_bloginfo('name');

    // get meta title for facebook
    $meta_fbtitle = $opengraph->getFbtitle($id);
    // get meta description for facebook
    $meta_fbdesc = $opengraph->getFbdesc($id);
    // get facebook app id
    if (isset($settings['metaseo_showfbappid'])) {
        $fbapp_id = esc_attr($settings['metaseo_showfbappid']);
    } else {
        $fbapp_id = '';
    }
    // get meta image for facebook & twiter
    $images       = $opengraph->getImage($id, $settings);
    $meta_fbimage = $images[0];
    $meta_twimage = $images[1];

    $current_url      = $opengraph->getCurentUrl($settings, $id);
    $type             = $opengraph->getType();
    $home_meta_active = wpmsProGetOption('home_meta_active');
    // check homepage is latest post
    if (is_home() && !empty($home_meta_active)) {
        $metas          = $opengraph->getHome($settings);
        $meta_title_esc = $metas['title'];
        $meta_twtitle   = $metas['title'];
        $meta_fbtitle   = $metas['title'];
        if ($metas['desc']) {
            $meta_desc_esc = $metas['desc'];
            $meta_twdesc   = $metas['desc'];
            $meta_fbdesc   = $metas['desc'];
        }
        $page_follow = $metas['page_follow'];
        $page_index  = $metas['page_index'];
    }

    // is front page
    if (is_front_page() && 'page' === get_option('show_on_front') && is_page(get_option('page_on_front'))) {
        $metas          = $opengraph->getFrontPageMeta($settings, $id);
        $meta_title_esc = $metas['title'];
        $meta_twtitle   = $metas['title'];
        $meta_fbtitle   = $metas['title'];
        if ($metas['desc']) {
            $meta_desc_esc  = $metas['desc'];
            $meta_twdesc    = $metas['desc'];
            $meta_fbdesc    = $metas['desc'];
        }

        $page_follow    = $metas['page_follow'];
        $page_index     = $metas['page_index'];
    }

    if (is_category() || is_tag() || is_tax()) {
        $metas             = $opengraph->getTagMeta($wp_query, $settings);
        $meta_keywords_esc = $metas['keyword'];
        $meta_title_esc    = $metas['title'];
        $meta_fbtitle      = $metas['title'];
        $meta_twtitle      = $metas['title'];
        $meta_desc_esc     = $metas['desc'];
        $meta_fbdesc       = $metas['desc'];
        $meta_twdesc       = $metas['desc'];
        if (!empty($metas['canonical'])) {
            $current_url = $metas['canonical'];
        }
        $page_follow       = 'follow';
    }

    if (empty($page_index)) {
        $page_index = 'index';
    }

    if (empty($page_follow)) {
        $page_follow = 'follow';
    }

    $post       = get_post($id);
    $canonical_url = apply_filters('get_canonical_url', $current_url, $post);
    // Create canonical meta link
    $canonical_meta = $opengraph->getCanonical($id, $settings, $canonical_url, $page_index);
    if (!empty($canonical_meta)) {
        // phpcs:ignore WordPress.Security.EscapeOutput -- Content escaped in some method in class MetaSeoOpenGraph
        echo $canonical_meta;
    }

    $patterns = $opengraph->getPatterns(
        $id,
        $settings,
        $meta_twimage,
        $meta_twcard,
        $meta_twitter_site,
        $sitename,
        strip_tags(html_entity_decode($meta_twdesc, ENT_COMPAT, 'UTF-8')),
        strip_tags(html_entity_decode($meta_twtitle, ENT_COMPAT, 'UTF-8')),
        $facebook_admin,
        $meta_fbimage,
        strip_tags(html_entity_decode($meta_fbdesc, ENT_COMPAT, 'UTF-8')),
        $current_url,
        $type,
        $fbapp_id,
        strip_tags(html_entity_decode($meta_fbtitle, ENT_COMPAT, 'UTF-8')),
        esc_html($meta_desc_esc, 'wpmsPro'),
        esc_html($meta_keywords_esc, 'wpmsPro'),
        strip_tags(html_entity_decode($meta_title_esc, ENT_COMPAT, 'UTF-8')),
        $page_index,
        $page_follow
    );

    foreach ($patterns as $k => $pattern) {
        // phpcs:ignore WordPress.Security.EscapeOutput -- Content escaped in some method in class MetaSeoOpenGraph
        echo $pattern[1];
    }
}


/**
 * Set a option
 *
 * @param string              $option_name Option name
 * @param string|array|object $value       Value of option
 *
 * @return void
 */
function wpmsProSetOption($option_name, $value)
{
    $settings = get_option('_metaseo_settings');
    if (empty($settings)) {
        $settings               = array();
        $settings[$option_name] = $value;
    } else {
        $settings[$option_name] = $value;
    }

    update_option('_metaseo_settings', $settings);
}

/**
 * Handle import of meta data from other installed plugins for SEO
 *
 * @return void
 */
function wpmsProYoastMessage()
{
    $activated = 0;
    // Check if All In One Pack is active
    if (!get_option('_aio_import_notice_flag')) {
        if (is_plugin_active('all-in-one-seo-pack/all_in_one_seo_pack.php')) {
            add_action('admin_notices', 'wpmsProImportMetaNotice', 2);
            $activated ++;
        }

        if (get_option('_aio_import_notice_flag') === false) {
            update_option('_aio_import_notice_flag', 0);
        }
    }
    // Check if Yoast is active
    if (!get_option('_yoast_import_notice_flag', false)) {
        if (is_plugin_active('wordpress-seo/wp-seo.php')
            || is_plugin_active('Yoast-SEO-Premium/wp-seo-premium.php') || class_exists('WPSEO_Premium')) {
            add_action('admin_notices', 'wpmsProImportYoastMetaNotice', 3);
            $activated ++;
        }

        if (get_option('_yoast_import_notice_flag') === false) {
            update_option('_yoast_import_notice_flag', 0);
        }
    }

    if ($activated === 2 && !get_option('plugin_to_sync_with', false)) {
        add_action('admin_notices', 'wpmsProNoticeSameFeature', 1);
    }
}

/**
 * Show notice
 *
 * @return void
 */
function wpmsProNoticeSameFeature()
{
    echo '<div class="error metaseo-import-wrn"><p>' . esc_html__('Be careful you installed 2 extensions doing almost the same thing, please deactivate AIOSEO or Yoast in order to work more clearly!', 'wpmsPro') . '</p></div>';
}


/**
 * Notice import meta
 *
 * @return void
 */
function wpmsProImportMetaNotice()
{
    echo '<div class="error metaseo-import-wrn"><p>' . sprintf(esc_html__('We have found that you&#39;re using
     All In One Pack Plugin, WP Meta SEO can import the meta
      from this plugin, %s', 'wpmsPro'), '<a href="#" class="button mseo-import-action"
 style="position:relative" onclick="importMetaData(this, event)" id="_aio_">
 <span class="spinner-light"></span>Import now</a> or
  <a href="#" class="dissmiss-import">dismiss this</a>') . '</p></div>';
}

/**
 * Notice import Yoast meta
 *
 * @return void
 */
function wpmsProImportYoastMetaNotice()
{
    echo '<div class="error metaseo-import-wrn"><p>' . sprintf(esc_html__('We have found that you&#39;re using Yoast SEO Plugin,
     WP Meta SEO can import the meta from this plugin, %s', 'wpmsPro'), '<a href="#"
 class="button mseo-import-action" style="position:relative"
  onclick="importMetaData(this, event)" id="_yoast_">Import now<span class="spinner-light"></span></a>
   or <a href="#" class="dissmiss-import">dismiss this</a>') . '</p></div>';
}

/**
 * Encode or decode all values in string format of an array
 *
 * @param array  $obj    List string
 * @param string $action Action
 *
 * @return mixed
 */
function wpmsProUtf8($obj, $action = 'encode')
{
    $action = strtolower(trim($action));
    $fn     = 'utf8_' . $action;
    if (is_array($obj)) {
        foreach ($obj as &$el) {
            if (is_array($el)) {
                if (is_callable($fn)) {
                    $el = wpmsProUtf8($el, $action);
                }
            } elseif (is_string($el)) {
                $isASCII = mb_detect_encoding($el, 'ASCII');
                if ($action === 'encode' && !$isASCII) {
                    $el = mb_convert_encoding($el, 'UTF-8', 'auto');
                }

                $el = $fn($el);
            }
        }
    } elseif (is_object($obj)) {
        $vars = array_keys(get_object_vars($obj));
        foreach ($vars as $var) {
            wpmsProUtf8($obj->$var, $action);
        }
    }

    return $obj;
}

/**
 * Cmb render text link
 *
 * @param array  $field Field
 * @param string $meta  Meta value
 *
 * @return void
 */
function wpmsProTextLink($field, $meta)
{
    echo '<input class="cmb_text_link" type="text" size="45" id="', esc_html($field['id']), '"
     name="', esc_html($field['id']), '" value="', esc_html($meta), '" />';
    echo '<input class="cmb_link_button button" type="button"
 value="Voeg link toe" />', '<p class="cmb_metabox_description">', esc_html($field['desc']), '</p>';
}


/**
 * Redirect 404 url and insert url to database
 *
 * @return void
 */
function wpmsProTemplateRedirect()
{
    global $wpdb;
    // redirect by rule
    $url = '';
    if (isset($_SERVER['REQUEST_URI'])) {
        $url = $_SERVER['REQUEST_URI'];
    }

    if (!is_home() && !is_front_page()) {
        $redirects       = $wpdb->get_results($wpdb->prepare('SELECT * FROM ' . $wpdb->prefix . 'wpms_links WHERE (link_url = %s AND link_url != "/") OR type = "add_rule" OR type = "add_custom"', array(
            $url
        )));
        $target          = '';
        $status_redirect = 302;
        foreach ($redirects as $link) {
            // If redirect success, not redirect again
            $parse_url = parse_url($link->link_url_redirect);
            if (isset($parse_url['path'])) {
                if (rtrim($parse_url['path'], '/') === rtrim($url, '/')) {
                    break;
                }
            }
            // Fix with xlink
            $query_str = parse_url($url, PHP_URL_QUERY);
            if (!empty($query_str) && strpos($query_str, 'xlink') !== false) {
                break;
            }

            $link->link_url = str_replace(' ', '%20', $link->link_url);
            $matches        = false;
            // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- remove warning if match the URL
            if ((($link->link_url === $url || $link->link_url === rtrim($url, '/') || $link->link_url === urldecode($url))) || (@preg_match('@' . str_replace('@', '\\@', $link->link_url) . '@', $url, $matches) > 0) || (@preg_match('@' . str_replace('@', '\\@', $link->link_url) . '@', urldecode($url), $matches) > 0)) {
                $target = $link->link_url_redirect;
                if ($link->type === 'add_custom') {
                    $status_redirect = $link->status_code;
                }

                break;
            }
        }

        if ($target) {
            if (empty($status_redirect) || !in_array($status_redirect, array(301, 302, 307))) {
                $status_redirect = 302;
            }
            wp_redirect($target, $status_redirect);
            exit();
        } else {
            if (is_404()) {
                if (isset($_SERVER['REQUEST_URI'])) {
                    $path_infos = pathinfo($_SERVER['REQUEST_URI']);
                    if (isset($path_infos['extension'])) {
                        return;
                    }

                    $url = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
                    if (isset($_SERVER['HTTPS']) &&
                        ($_SERVER['HTTPS'] === 'on' || (int) $_SERVER['HTTPS'] === 1) ||
                        isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
                        $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
                        $protocol = 'https://';
                    } else {
                        $protocol = 'http://';
                    }
                    // append protocol if not in url.esc_url will return empty string for url with no protocol
                    if (strpos($url, 'http') === false) {
                        $url = $protocol . $url;
                    }
                    $esc_url = str_replace(array('http://', 'https://'), $protocol, esc_url($url));
                    $check   = $wpdb->get_results($wpdb->prepare(
                        'SELECT * FROM ' . $wpdb->prefix . 'wpms_links WHERE (link_url=%s OR link_url=%s OR link_url=%s)',
                        array(
                            $url,
                            $esc_url,
                            $_SERVER['REQUEST_URI']
                        )
                    ));

                    // get referer url
                    $referer_url = '';
                    if (wp_get_raw_referer()) {
                        $referer_url = wp_sanitize_redirect(wp_get_raw_referer());
                    }

                    if ($referer_url === '') {
                        $referer_url = $esc_url;
                    }
                    if (count($check) === 0) {
                        if (!function_exists('wp_validate_redirect')) {
                            require_once(ABSPATH . 'wp-includes/pluggable.php');
                        }

                        // insert url
                        $insert = array(
                            'link_url'        => ($url),
                            'status_code'     => '404 Not Found',
                            'status_text'     => '404 Not Found',
                            'type'            => '404_automaticaly',
                            'broken_indexed'  => 1,
                            'broken_internal' => 0,
                            'warning'         => 0,
                            'dismissed'       => 0,
                            'referrer'        => $referer_url
                        );

                        $wpdb->insert($wpdb->prefix . 'wpms_links', $insert);
                    } else {
                        // update url
                        $links_broken = $wpdb->get_row($wpdb->prepare(
                            'SELECT * FROM ' . $wpdb->prefix . 'wpms_links WHERE (link_url=%s OR link_url=%s OR link_url=%s) ',
                            array(
                                $url,
                                $esc_url,
                                $_SERVER['REQUEST_URI']
                            )
                        ));

                        if (!empty($links_broken)) {
                            $list_referrers = explode('||', $links_broken->referrer);
                            if (!in_array($referer_url, $list_referrers)) {
                                $list_referrers[] = $referer_url;
                            }

                            $referrers = implode('||', $list_referrers);
                            $referrers = trim($referrers, '||');
                            $value     = array(
                                'hit'      => (int) $links_broken->hit + 1,
                                'referrer' => $referrers
                            );

                            $wpdb->update(
                                $wpdb->prefix . 'wpms_links',
                                $value,
                                array('id' => $links_broken->id),
                                array('%d', '%s'),
                                array('%d')
                            );

                            if (($url === $links_broken->link_url || $esc_url === $links_broken->link_url)
                                && $links_broken->link_url_redirect !== '') {
                                if (!empty($links_broken->meta_title)) {
                                    $status_redirect = $links_broken->meta_title;
                                } else {
                                    $status_redirect = 302;
                                }

                                if (empty($status_redirect) && !in_array($status_redirect, array(301, 302, 307))) {
                                    $status_redirect = 302;
                                }

                                wp_redirect($links_broken->link_url_redirect, $status_redirect);
                                exit();
                            }
                        }
                    }
                }

                $defaul_settings_404 = array(
                    'wpms_redirect_homepage' => 0,
                    'wpms_type_404'          => 'none',
                    'wpms_page_redirected'   => 'none'
                );
                $wpms_settings_404   = get_option('wpms_settings_404');

                if (is_array($wpms_settings_404)) {
                    $defaul_settings_404 = array_merge($defaul_settings_404, $wpms_settings_404);
                }

                // redirect url by settings
                if (isset($defaul_settings_404['wpms_redirect_homepage'])
                    && (int) $defaul_settings_404['wpms_redirect_homepage'] === 1) {
                    wp_redirect(get_home_url());
                    exit();
                } else {
                    if (isset($defaul_settings_404['wpms_type_404'])) {
                        switch ($defaul_settings_404['wpms_type_404']) {
                            case 'wp-meta-seo-page':
                                global $wpdb;
                                $wpms_page = $wpdb->get_row($wpdb->prepare(
                                    'SELECT * FROM ' . $wpdb->prefix . 'posts WHERE post_title = %s AND post_excerpt = %s',
                                    array(
                                        '404 Error, content does not exist anymore',
                                        'metaseo_404_page'
                                    )
                                ));
                                if (!empty($wpms_page)) {
                                    $link_redirect = get_permalink($wpms_page->ID);
                                    if ($link_redirect) {
                                        wp_redirect($link_redirect);
                                        exit();
                                    }
                                }
                                break;

                            case 'custom_page':
                                if (isset($defaul_settings_404['wpms_page_redirected'])
                                    && $defaul_settings_404['wpms_page_redirected'] !== 'none') {
                                    $link_redirect = get_permalink($defaul_settings_404['wpms_page_redirected']);
                                    if ($link_redirect) {
                                        wp_redirect($link_redirect);
                                        exit();
                                    }
                                }
                                break;
                        }
                    }
                }
            }
        }
    }
}


/**
 * Remove hello elementor meta description that uses excerpt.
 *
 * @return void
 */
function wpmsProRemoveHelloElementorMetaDesc()
{
    remove_action('wp_head', 'hello_elementor_add_description_meta_tag');
}
