HEX
Server: Apache/2.4.65 (Debian)
System: Linux localhost 6.9.12 #1 SMP Tue May 5 14:23:20 UTC 2026 x86_64
User: www-data (33)
PHP: 8.2.30
Disabled: NONE
Upload Files
File: /var/www/html/wp-content/plugins/if-so/admin/partials/ifso_geo_page_display.php
<?php
	if ( ! defined( 'ABSPATH' ) ) exit;

	require_once(IFSO_PLUGIN_BASE_DIR . 'services/geolocation-service/geolocation-service.class.php');

	use IfSo\Services\GeolocationService;

    global $wpdb;
	$license = get_option( 'edd_ifso_geo_license_key' );
	$status  = get_option( 'edd_ifso_geo_license_status' );
	$expires = get_option( 'edd_ifso_geo_license_expires' );
	// $item_name = get_option( 'edd_ifso_license_item_name' );

	function is_plusgeo_license_exist($geoData) {
		return ( isset($geoData['has_plusgeo_key']) && $geoData['has_plusgeo_key'] );
	}

	function is_pro_license_exist($geoData) {
		return ( isset($geoData['has_pro_key']) && $geoData['has_pro_key'] );
	}

	function get_subscription($geoData) {
		$subscription = '';

		if ( is_pro_license_exist($geoData) )
			$subscription = "Pro";
		else
			$subscription = "Free";

		if ( is_plusgeo_license_exist($geoData) )
			$subscription .= " +Geolocation";

		return $subscription;
	}

	function is_geo_data_valid($geoData) {
		return ( isset($geoData['success']) && $geoData['success'] );
	}

	function get_used_queries($geoData) {
		if ( is_geo_data_valid($geoData) ) {
			return intval($geoData['realizations']);
		}
		return 0;
	}

	function get_monthly_queries($geoData) {
		if ( is_geo_data_valid($geoData) ) {
			return $geoData['bank'];
		}
		return 0;
	}

	function get_key($geoData, $key) {
		if ( isset( $geoData[$key] ) )
			return $geoData[$key];
		else
			return false;
	}

	function get_date_i18n($date,$shorten_month=false) {
        $month_format = $shorten_month ? 'M' : 'F';
		return date_i18n( "{$month_format} j, Y", strtotime( $date, current_time( 'timestamp' ) ) );
	}

	function get_pro_renewal_date($geoData) {
		return get_key($geoData, 'pro_renewal_date');
	}

	function get_plusgeo_renewal_date($geoData) {
		return get_key($geoData, 'plusgeo_renewal_date');
	}

	function get_pro_and_geo_realizations($geoData){
		$ret = ['pro' => 0, 'geo' => 0,];
		if(isset($geoData['geo_realizations']))
			$ret['geo'] = number_format(intval($geoData['geo_realizations']));
		if(isset($geoData['pro_realizations']))
			$ret['pro'] = number_format(intval($geoData['pro_realizations']));
		return $ret;
	}

    function print_extra_tabs_buttons($tabs){
        $ret = '';
        if(!empty($tabs)){
            foreach($tabs as $tab){
                if(!empty($tab['name'])){
                    $prettyname = !empty($tab['prettyname']) ? $tab['prettyname'] : $tab['name'];
                    $ret .= "<li class='ifso-tab' data-tab='ifso-geo-page-tab-{$tab['name']}'>{$prettyname}</li>";
                }
            }
        }
        return $ret;
    }

    function print_extra_tabs_contents($tabs){
        $ret = '';
        if(!empty($tabs)){
            foreach($tabs as $tab){
                if(!empty($tab['name']) && !empty($tab['content']))
                    $ret .=  "<div class='ifso-geo-page-tab-content ifso-geo-page-tab-{$tab['name']}'>{$tab['content']}</div>";
            }
        }
        return $ret;
    }

	$geoData = GeolocationService\GeolocationService::get_instance()->get_status($license);
	$geo_subscription = get_subscription($geoData, $license, $status);
	$geo_monthly_queries = number_format(get_monthly_queries($geoData));
	$geo_int_monthly_queries = get_monthly_queries($geoData);
	$geo_queries_used = get_used_queries($geoData);
	$separateRealizations = get_pro_and_geo_realizations($geoData);
	$pro_license_type = (isset($geoData['pro_license_type']) && !empty($geoData['pro_license_type'])) ? $geoData['pro_license_type'] : false;
	$geo_license_type = (isset($geoData['geo_license_type']) && !empty($geoData['geo_license_type'])) ? $geoData['geo_license_type'] : false;
	$pro_license_bank = (isset($geoData['product_bank']) && !empty($geoData['product_bank'])) ? number_format($geoData['product_bank']) : 0;
	$geo_license_bank = (isset($geoData['geo_bank']) && !empty($geoData['geo_bank'])) ? number_format($geoData['geo_bank']) : 0;
    $extra_tabs = apply_filters('ifso_geo_page_display_extra_tabs',[]);
    $possible_notif_thresholds = GeolocationService\GeolocationService::get_instance()->get_possible_notification_thresholds();

	$sent_user_email = (isset($_POST["user-email-box"]) && !empty($_POST["user-email-box"]) &&  $_POST["user-email-box"] != get_option('admin_email')) ? sanitize_email($_POST["user-email-box"]) : get_option('admin_email');
    $set_alert_values_array = (!empty($_POST['alert-checkbox-values'])) ? array_unique($_POST['alert-checkbox-values']) : [];
    sort($set_alert_values_array);
    $set_alert_values = implode(' ',$set_alert_values_array);

    function get_notification_data() {
        global $wpdb, $sent_user_email;
        $table = $wpdb->prefix . 'ifso_local_user';
        $user_notification_data = $wpdb->get_results( "SELECT * FROM {$table}"); //add another on reload
        if (count($user_notification_data) > 0) {
            $notifications_data_arr["user_email"] = (isset($user_notification_data[0]->user_email) && !empty($user_notification_data[0]->user_email)) ? $user_notification_data[0]->user_email : $sent_user_email;
            $notifications_data_arr["alert_values"] = isset($user_notification_data[0]->alert_values) ? $user_notification_data[0]->alert_values : '';
            $notifications_data_arr["record_id"] = isset($user_notification_data[0]->id) ? $user_notification_data[0]->id : 0;
            return $notifications_data_arr;
        }
    }

	$data = get_notification_data();
	$table = $wpdb->prefix . 'ifso_local_user';
    $daily_sessions_table_name = $wpdb->prefix . 'ifso_daily_sessions';

	if(isset($_POST['update_notifications'])) {
        $wpdb->query($wpdb->prepare("REPLACE INTO {$table} SET id = %d,user_email = %s,user_sessions = %d,user_bank = %d,alert_values = %s",
            [$data['record_id'],$sent_user_email,$geo_queries_used,$geo_int_monthly_queries,$set_alert_values]));
        $form_alert_values = get_notification_data()["alert_values"];
        if($data['alert_values']!==$form_alert_values)      //alert values were changed
            GeolocationService\GeolocationService::get_instance()->reset_notifications();
    }
    $form_alert_values = isset($form_alert_values) ? explode(" ",$form_alert_values) : explode(" ",$data['alert_values']);
    $noLicenseMessageBox = '<div class="no_license_message">'. __("Enter a Geolocation License to gain extra sessions. ", 'if-so') . '<a href="https://www.if-so.com/plans/geolocation-plans/?ifso=geocredits" target="_blank">'. __("Click here to get a Geolocation license key", 'if-so') . '</a>.</div>';
?>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

<!-- TEMPORARY inner css! -->
<style>
    .percentage {
      font-weight:700;
    }

    /*new info tab styles -start*/
    .geo-dki-description {
        font-size: 16px;
        margin: 0 auto 15px;
    }

    .geo-dki-table,
    .geo-dki-table th,
    .geo-dki-table td {
        border: solid 1px black;
        border-collapse: collapse;
        padding: 14px 10px;
        font-size: 16px;
    }
    .geo-dki-table td:nth-child(2) {
        position: relative;
        padding-right: 30px;
    }

    .geo-dki-table-copy-button {
        position: absolute;
        top: 0;
        right: 0;
        font-size: 15px;
        padding: 2px 6px 6px;
        line-height: 1;
        color: black;
        background-color: #E0E0E0;
        margin: 0 0 0 5px;
        cursor: pointer;
    }
    .geo-dki-table-copy-button:hover {
        background-color: #D5D5D5;
    }
    /* click indicator start */
        .geo-dki-table-copy-button::before {
            content: "";
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            left: -13px;
            width: 0;
            height: 0;
            border-top: 4px solid transparent;
            border-bottom: 4px solid transparent;
            border-left: 8px solid #888888;
        }
        .geo-dki-table-copy-button::after {
            content: "Copied!";
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            right: calc(100% + 13px);
            background-color: #888888;
            color: white;
            font-size: 12px;
            padding: 2px 4px;
            border-radius: 3px;
            white-space: nowrap;
        }
        .geo-dki-table-copy-button::before,
        .geo-dki-table-copy-button::after {
            opacity: 0;
            visibility: hidden;
            transition: visibility 0.1s linear, opacity 0.1s linear;
        }
        .geo-dki-table-copy-button.active::before,
        .geo-dki-table-copy-button.active::after {
            visibility: visible;
            opacity: 1;
        }
    /* click indicator end */

    .geo-dki-table td a {
        text-decoration: none;
    }

    .geo-dki-table code {
        font-size: inherit;
    }

    .geo-dki-button {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: 10px;
        text-decoration: none;
        color: white !important; /* to override wp on hover and active change */
        background-color: #4cb5d2;
        font-weight: 600;
        padding: 10px 22px 10px 19px;
        border-radius: 40px;
        border: none;
        outline: 0;
        margin: 40px auto 0;
    }
    .geo-dki-button:hover,
    .geo-dki-button:active {
        background-color: #48ACC7;
    }

    .geo-info {
        max-width: 974px;
    }

    .ifso-geo-page-tab-info .ifso-settings_paragraph{
        max-width: unset;
        font-size: 16px;
        margin-bottom: 2em;
    }

    .geo-info-download {
        background-color: white;
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 15px 40px;
        border: groove 1px #697BF8;
        margin: 30px auto 20px;
    }
    .geo-info-download p {
        color: #697BF8;
        font-size: 18px;
        font-weight: 600;
        margin: 0;
    }
    .geo-info-download ul {
        color: #697BF8;
        list-style-type: none;
        margin: 6px auto 0;
    }
    .geo-info-download li {
        display: inline-block;
        font-size: 18px;
        line-height: 1.6;
        margin: 0 10px 0 0;
    }
    .geo-info-download li::before {
        content: '';
        display: inline-block;
        width: 11px;
        height: 11px;
        background-image: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512' fill='%23697BF8'%3E%3Cpath d='M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z'/%3E%3C/svg%3E");
        margin-right: 6px;
    }
    .geo-info-download a {
        flex-shrink: 0;
        color: white;
        background-color: #697BF8;
        padding: 6px 16px 8px 22px;
        font-size: 18px;
        text-decoration: none;
    }

    .geo-info-notification {
        margin: 10px auto 0;
    }
    .geo-info-notification svg {
        position: relative;
        top: 2px;
        display: inline-block;
        width: 9px;
        color: #319D56;
        fill: currentColor;
        padding: 3px;
        border: solid 1px currentColor;
        border-radius: 50%;
        margin-right: 1px;
    }
    .geo-info-notification p {
        display: inline;
        font-size: 16px;
        margin: 0 auto;
    }

    .geo-info-cards {
        display: flex;
        align-items: stretch;
        justify-content: baseline;
        flex-wrap: wrap;
        gap: 11px;
        margin: 30px 0 0;
    }
    .geo-info-cards .geo-info-card {
        box-sizing: border-box;
        width: 235px;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: baseline;
        gap: 30px;
        text-align: center;
        background-color: white;
        padding: 14px 14px;
        border: solid 1px #d1d1d1;
    }
    .geo-info-cards .geo-info-card .geo-info-card-title{
        margin: 0 auto;
        font-size: 16px;
    }
    .geo-info-cards .geo-info-card .geo-info-card-content{
        margin: 0 auto;
        font-size: 22px;
        font-weight: 900;
    }
    .geo-info-cards .geo-info-card.next-renewal .geo-info-card-content{
        font-weight: initial;
        font-size: 13px;
    }
    .geo-info-cards .geo-info-card.your-subscription .geo-info-card-content{
        font-weight: initial;
        font-size: 13px;

        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 0px;
    }
    .geo-info-cards .geo-info-card.your-subscription .geo-info-card-content .subsctiption-name, .geo-info-cards .geo-info-card.next-renewal .geo-info-card-content span{
        font-weight: 700;
    }
    .error-label {
        color: #E46A69;
    }
    .geo-info-cards .geo-info-card-link.error-label {
        margin-top: -30px;
    }
    .geo-info-cards .geo-info-card-link{
        font-size:14px;
    }
    .geo-info-cards .geo-info-card.next-renewal .geo-info-card-content .error-label{
        font-weight: normal;
    }
    /*new info tab styles - end*/

    /* new info filter styles - start */
        .geo-info-filter {
            margin: 50px 0 0;
        }
        .geo-info-filter.disabled {
            display: none;
            visibility: none;
        }
        .geo-info-filter-container {
            position: relative;
            display: inline-block;
        }
        .geo-info-filter-container::before {
            content: "\f073";
            color: #555d66;
            font-family: FontAwesome;
            font-size: 16px;
            position: absolute;
            top: 5px;
            left: 9px;
        }
        .geo-info-filter-container .geo-info-filter-picker {
            display: inline-block;
            padding: 5px 0 5px 30px;
            float: none;
            line-height: 1;
            min-height: unset;
            width: 115px;
            margin: 0px;
        }
        .geo-info-filter .geo-info-filter-submit {
            margin-left: 5px;
        }
    /* new info filter styles - end */

    /* new info chart styles - start */
    .geo-info-chart-container {
        margin: 15px 0 0;
        position: relative;
        width: 100%;
        height: 250px;
    }
    .geo-info-chart-container.disabled {
        display: none;
        visibility: none;
    }
    /* new info chart styles - end */

    /* new info table styles - start */
    .geo-info-table-wrapper{
        margin: 50px 0 0;
    }
    .geo-info-table {
        width: 100%;
        text-align: left;
        font-size: 14px;
        font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
        border-spacing: 1px;
        border-collapse: collapse;
    }
    .geo-info-table thead {
        background-color: white;
    }
    .geo-info-table tbody {
        background-color: white;
    }
    .geo-info-table tbody tr:nth-child(odd) {
        background-color: #F6F7F7;
    }
    .geo-info-table td, .geo-info-table th {
        padding: 10px 20px;
        width: 25%;
        border: 1px solid #ddd;
    }
    .geo-info-table th {
        padding: 20px;
        font-weight: normal;
    }
    .geo-info-table .empty-table-notifier p {
        margin: 5px auto 5px;
    }
    .geo-info-table td.empty-table-notifier{
        text-align:center;
    }
    /* new info table styles - end */

    /* new mobile media query - start */
    @media (max-width: 782px) {
        .geo-info-cards {
            justify-content: center;
        }
        .geo-info-cards .geo-info-card {
            width: 100%;
            gap: 14px;
        }
        .geo-info-cards .geo-info-card-link.error-label {
            margin-top: -10px;
        }
        .geo-info-download {
            text-align: center;
            flex-direction: column;
            gap: 15px;
            margin-bottom: 25px;
        }
 
        .geo-info-filter {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 5px;
        }

        .geo-info-chart-container {
            margin: 15px auto 0;
        }

        .geo-info-table {
            text-align: center;
            margin: 50px auto 0;
        }
    }
    /* new mobile media query - end */
</style>
</head>
<body>
    <div class="wrap">
        <h2> <?php _e('If-So Dynamic Content | Geolocation'); ?> </h2>
        <div class="ifso-geo-tabs-select-wrapper">
            <ul class="ifso-admin-tabs-header">
                <li class="ifso-tab default-tab" data-tab="ifso-geo-page-tab-info">	 <?php _e('Info', 'if-so');?></li>
                <li class="ifso-tab" data-tab="ifso-geo-page-tab-notifications"><?php _e('Notifications', 'if-so'); ?></li>
                <li class="ifso-tab" data-tab="ifso-geo-page-tab-dki"><?php _e('DKI Shortcodes', 'if-so'); ?></li>
                <?php echo wp_kses_post(print_extra_tabs_buttons($extra_tabs)); ?>
            </ul>
        </div>
        <!-- new -->
        <div class="ifso-geo-tabs-contents-wrapper">
            <!-- dki tab contents: -->
            <script> 
                // script to copy the shortcode when clicking on the copy buttons
                document.addEventListener('DOMContentLoaded', () => {
                    let buttons = document.querySelectorAll('.geo-dki-table-copy-button')
                    buttons.forEach((button) => {
                        let code = button.parentElement.querySelector('code')
                        button.addEventListener('click', () => copyClickHandler(button, code))
                    })
                })
                function copyClickHandler(button, code) {
                    button.classList.add('active')
                    setTimeout(() => { button.classList.remove('active') }, 2000)
                    navigator.clipboard.writeText(code.innerHTML)
                }
            </script>
            <div class="ifso-geo-page-tab-content ifso-geo-page-tab-dki">
                <p class="geo-dki-description">
                    Save time with Dynamic Keyword Insertion (DKI) shortcodes! Automatically display personalized content instead of setting up multiple versions of dynamic content manually.
                </p>

                <table class="geo-dki-table">
                    <thead>
                        <tr>
                            <th>Shortcode Name</th>
                            <th>The Shortcode</th>
                            <th>Description</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>Country Name</td>
                            <td>
                                <code>[ifsoDKI type='geo' show='country' fallback='' ajax='yes']</code><div class="geo-dki-table-copy-button">🗊</div></td>
                            <td>Display the user’s country name</td>
                        </tr>
                        <tr>
                            <td>User's Country Flag</td>
                            <td><code>[ifsoDKI type='geo' show='flag' width='50px' ajax='yes']</code><div class="geo-dki-table-copy-button">🗊</div></td>
                            <td>
                                Insert the user’s country flag
                                &#40;<a href="https://www.if-so.com/display-the-users-country-flag/?utm_source=Plugin&utm_medium=dki-table&utm_campaign=geolocation&utm_term=info-top&utm_content=a" target="_blank">learn more</a>&#41;
                            </td>
                        </tr>
                        <tr>
                            <td>City Name</td>
                            <td><code>[ifsoDKI type='geo' show='city' fallback='' ajax='yes']</code><div class="geo-dki-table-copy-button">🗊</div></td>
                            <td>Display the user’s city name</td>
                        </tr>
                        <tr>
                            <td>State Name</td>
                            <td><code>[ifsoDKI type='geo' show='state' fallback='' ajax='yes']</code><div class="geo-dki-table-copy-button">🗊</div></td>
                            <td>Display the user’s state name</td>
                        </tr>
                        <tr>
                            <td>Continent Name</td>
                            <td><code>[ifsoDKI type='geo' show='continent' fallback='' ajax='yes']</code><div class="geo-dki-table-copy-button">🗊</div></td>
                            <td>Display the user’s continent name</td>
                        </tr>
                        <tr>
                            <td>User's Time zone</td>
                            <td><code>[ifsoDKI type='geo' show='timezone' ajax='yes']</code><div class="geo-dki-table-copy-button">🗊</div></td>
                            <td>Display the user’s time zone</td>
                        </tr>
                        <tr>
                            <td>Event Auto-local Time Display</td>
                            <td><code>[ifsoDKI type='time' show='user-geo-timezone-sensitive' time='04/25/2022 08:00' format='n/j/o, G:i' ajax='yes']</code><div class="geo-dki-table-copy-button">🗊</div></td>
                            <td>
                                Show an event time calculated according to the user’s time zone
                                &#40;<a href="https://www.if-so.com/auto-local-time-display/?utm_source=Plugin&utm_medium=dki-table&utm_campaign=geolocation&utm_term=info-top&utm_content=a" target="_blank">learn more</a>&#41;
                            </td>
                        </tr>
                    </tbody>
                </table>

                <!-- more DKI button - START -->
                    <a class="geo-dki-button" target="_blank" href="https://www.if-so.com/help/documentation/dynamic-keyword-insertion/?utm_source=Plugin&utm_medium=dki-table&utm_campaign=geolocation&utm_term=info-top&utm_content=a">
                        MORE DKI SHORTCODES
                        <svg class="geo-dki-button-arrow" width="15" height="14" viewBox="0 0 26 25">
                            <path fill="white" d="M13.758 25l-2.12-2.167 8.62-8.808H.003v-3.06h20.255l-8.62-8.808 2.12-2.164 12.238 12.503z"></path>
                        </svg> 
                    </a>
                <!-- more DKI button - END -->
            </div>
        </div>
        <!-- new -->

        <div class="ifso-geo-tabs-contents-wrapper">
            <!-- Notifications tab contents: -->
            <div class="ifso-geo-page-tab-content ifso-geo-page-tab-notifications">
                <div class="geolocation-info-wrapper">
                    <form method="post" action="" class="license-form">
                    <?php settings_fields('edd_ifso_license'); ?>
                    <table class="form-table license-tbl">
                        <tbody>
                            <tr valign="top">
                                <th class="licenseTable" scope="row"  valign="top">
                                    <?php _e('Send Email Alerts'); ?>
                                </th>
                                <td >
                                <input type="checkbox" class="box" name="alert-checkbox-values[]" id="dimming-checkbox" value="100"  <?php echo in_array('100', $form_alert_values) ? 'checked' : '';?>>
                                <span class="notification-line">  <i><?php _e('Check this box if you would like to be notified regarding your quota threshold', 'if-so'); ?></i> </span>
                                </td>
                            </tr>
                            <tr valign="top">
                                <th class="licenseTable" scope="row" valign="top">
                                    <?php _e('Quota Threshold', 'if-so'); ?>
                                </th>
                                <td>
                                    <?php
                                        foreach ($possible_notif_thresholds as $threshold){
                                            $checked =  in_array((string) $threshold, $form_alert_values) ? 'checked' : '';
                                            $disabled = !in_array('100', $form_alert_values) ? 'disabled' : '';
                                            echo "<input type='checkbox' class='group1' id='1st-box' name='alert-checkbox-values[]' value='{$threshold}'" . $checked . " " . $disabled . "><span class='notification-line'><span class='percentage'>{$threshold}%</span> &nbsp <i>" . __("Receive an email alert when quota reaches {$threshold}%", 'if-so') . "</i> </span><br><br>";
                                        }
                                    ?>
                                </td>
                            </tr>
                            <?php if(in_array('100', $form_alert_values) != 1 )
                                    echo "<script>$('.notification-line').css('color', '#DCDCDC	') </script>";
                                else
                                    echo "<script> $('.notification-line').css('color', 'black') </script>";
                            ?>

                            <tr valign="top">
                                <th class="licenseTable" scope="row" valign="top">
                                    <?php _e('Email'); ?>
                                </th>
                                <td>
                                <input id name="user-email-box" type="email" class="emailBox" value = "<?php echo get_notification_data()['user_email'];?>" >
                                </td>
                            </tr>

                            <tr valign="top">
                                <th></th>
                                <td style="padding-top:0;"><?php _e('Make sure emails don’t go to spam.','if-so') ?> <a id="ifso_send_test_email" href="#"><?php _e('Send a test email.','if-so') ?> </a></td>
                            </tr>
                        </tbody>
                    </table>
                    <br>
                    <input type="submit" class="button-primary" name="update_notifications" value=<?php _e('Save', 'if-so')?>>
                    </form>
                </div>
            </div>
            <!--end of Notifications div  -->

            <!--Info Tab Contents--->
            <div class="ifso-geo-page-tab-content ifso-geo-page-tab-info">
                <!-- new geo info cards - START -->
                <div class="geo-info">
                    <?php _e('<p class="ifso-settings_paragraph">The geolocation service is limited to 250 monthly <span title="A session is defined as beginning when a visitor first visits a page with a geolocation trigger and ends when a visitor closes the browser, the user ip is changed, or after 25 minutes of inactivity." class="tm-tip ifso_tooltip line-tooltip">sessions</span>  with the free version and 1,000 monthly sessions for the duration of one year with the pro version.  <a class="buy-more-credits-link" href=" https://www.if-so.com/plans/geolocation-plans/?utm_source=Plugin&utm_medium=message&utm_campaign=geolocation&utm_term=info-top&utm_content=a" target="_blank">Click here</a> for additional options if your website handles a larger amount.</p>','if-so'); ?>
                    <div class="geo-info-notification">
                        <svg viewBox="0 0 512 512">
                            <path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998
                                26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203
                                36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/>
                        </svg>
                        <p>
                            <b><?php _e('Not every page view counts as a session')?></b>
                            - <?php _e('If-So stores the users location during their visit so that a geolocation session is only counted once when users browse different pages on the same visit.'); ?>
                        </p>
                    </div>
                    <?php if(!defined('IFSO_GEOLOCATION_ON') || !IFSO_GEOLOCATION_ON){ ?>
                        <div class="geo-info-download">
                            <div>
                                <p><?php _e('Download our free geolocation extension for more options')?></p>
                                <ul>
                                    <li><?php _e('Browser-based Location (HTML5 Geolocation API)')?></li>
                                    <li><?php _e('Countries flag DKI shortcode')?></li>
                                    <li><?php _e('Log geolocation requests')?></li>
                                    <li><?php _e('Location override')?></li>
                                    <li><?php _e('Bots block mode')?></li>
                                </ul>
                            </div>
                            <a target="_blank" href="https://wordpress.org/plugins/if-so-geolocation/">
                                <?php _e('Free Download >')?>
                            </a>
                        </div>
                    <?php } ?>
                    <div class="geo-info-cards">
                        <div class="geo-info-card">
                            <p class="geo-info-card-title">
                                <?php _e('Monthly Sessions'); ?>
                            </p>

                            <?php if(!is_geo_data_valid($geoData)){ ?>
                                <p class="geo-info-card-content error-label">
                                    <?php echo number_format($geo_int_monthly_queries); ?>
                                </p>
                                <p class="geo-info-card-link error-label">
                                    Communication failure
                                    <br>
                                    <a class="geo-info-card-link error-label" href="https://www.if-so.com/help/communication-failure/?utm_source=Plugin&utm_medium=error&utm_campaign=geolocation&utm_term=comm_failure&utm_content=a" target="_blank">
                                        Click to solve
                                    </a>
                                </p>
                            <?php } else{ ?>
                                <p class="geo-info-card-content">
                                    <?php echo number_format($geo_int_monthly_queries); ?>
                                </p>
                                <a class="geo-info-card-link" target="_blank" href="https://www.if-so.com/plans/geolocation-plans/?utm_source=Plugin&utm_medium=message&utm_campaign=geolocation&utm_term=info-tab&utm_content=a">
                                    <?php _e('Upgrade'); ?>
                                </a>
                            <?php } ?>

                        </div>
                        <div class="geo-info-card">
                            <p class="geo-info-card-title">
                                <?php _e('Used Monthly Sessions'); ?>
                            </p>
                            <p class="geo-info-card-content">
                                <?php echo number_format($geo_queries_used); ?>
                            </p>
                            <a class="geo-info-card-link" href="https://www.if-so.com/faq-items/how-do-we-define-a-geolocation-session/?utm_source=Plugin&utm_medium=message&utm_campaign=geolocation&utm_term=info-tab&utm_content=session" target="_blank">
                                <?php _e('What is a session?'); ?>
                            </a>
                        </div>
                        <div class="geo-info-card">
                            <p class="geo-info-card-title">
                                <?php _e('Remaining Monthly Sessions'); ?>
                            </p>
                            <p class="geo-info-card-content">
                                <?php echo number_format($geo_int_monthly_queries - $geo_queries_used); ?>
                            </p>
                        </div>
                        <?php if(is_geo_data_valid($geoData)): ?>
                        <div class="geo-info-card next-renewal">
                            <p class="geo-info-card-title">
                                <?php _e('Next Renewal Date'); ?>
                            </p>
                            <p class="geo-info-card-content">
                                <?php
                                $renewal_date_format = 'd-m-Y';
                                $pro_license_expiration = !empty($geoData['pro_expiration']) ? new \DateTime('@' . (int)$geoData['pro_expiration']) : false;
                                $geo_license_expiration = !empty($geoData['geo_expiration']) ? new \DateTime('@' . (int)$geoData['geo_expiration']) : false;
                                $geo_renewal_date = get_plusgeo_renewal_date($geoData) ? get_plusgeo_renewal_date($geoData) : '';
                                $pro_renewal_date = get_pro_renewal_date($geoData) ? get_pro_renewal_date($geoData) : '';
                                $pro_license_name = $pro_license_type ? ucfirst($pro_license_type) : "Product";
                                $geo_license_name = $geo_license_type ? ucfirst($geo_license_type) : "Geo";

                                $license_renewal_message = function($expiration_date,$renewal_date) use ($renewal_date_format){
                                    if($expiration_date){
                                        $expiration_date_str = get_date_i18n($expiration_date->format($renewal_date_format),true);
                                        if($expiration_date < new \DateTime('now') )
                                            return '<span class="error-label">Expired on ' . $expiration_date_str . '</span>';
                                        if($expiration_date < $renewal_date)
                                            return '<span class="error-label">Expires on ' . $expiration_date_str . '</span>';
                                    }
                                    return get_date_i18n($renewal_date->format($renewal_date_format),true);
                                };

                                echo !empty($pro_renewal_date) ? "<span> {$pro_license_name} : </span>" .
                                    $license_renewal_message($pro_license_expiration,\DateTime::createFromFormat($renewal_date_format,$pro_renewal_date)) . '<br>' : '';
                                echo !empty($geo_renewal_date) ? "<span> {$geo_license_name} : </span>" .
                                    $license_renewal_message($geo_license_expiration,\DateTime::createFromFormat($renewal_date_format,$geo_renewal_date)) : '';
                                ?>
                            </p>
                        </div>
                        <?php endif; ?>
                        <?php if(is_geo_data_valid($geoData) && ($pro_license_type!='free' || $geo_license_type)): ?>
                            <div class="geo-info-card your-subscription">
                                <p class="geo-info-card-title">
                                    <?php _e('Your Subscriptions'); ?>
                                </p>
                                <p class="geo-info-card-content">
                                    <?php echo (($pro_license_type && $pro_license_type!='free' || $pro_license_type=='free' && !$geo_license_type ) ?
                                            '<span class="geo-pro-subscription-span"><span class="subsctiption-name">' .  ucwords($pro_license_type) . '</span>' . " ({$separateRealizations['pro']}/{$pro_license_bank} sessions)</span>" : '') .
                                            (($geo_license_type) ? '<span class="geo-subscription-span"><span class="subsctiption-name">' . ucwords($geo_license_type) . '</span>'  . " ({$separateRealizations['geo']}/{$geo_license_bank} sessions)</span>" : '');?>
                                </p>
                                <a class="geo-info-card-link" target="_blank" href="https://www.if-so.com/plans/geolocation-plans/?utm_source=Plugin&utm_medium=message&utm_campaign=geolocation&utm_term=info-tab&utm_content=a">
                                    <?php _e('Upgrade','if-so'); ?>
                                </a>
                            </div>
                        <?php endif; ?>
                    </div>


                    <!-- new central call to DB - START -->
                    <?php
                        $results = $wpdb->get_results( "SELECT * FROM {$daily_sessions_table_name} ORDER BY id DESC");
                        $data_array = array();
                        $sessions_contain_badly_formatted_dates = false;
                        foreach ($results as $res) {
                            try{
                                $date = DateTime::createFromFormat(GeolocationService\GeolocationService::get_instance()->get_daily_sessions_table_date_format(),$res->sessions_date);
                                if ($date===false) throw new \Exception('Wrong date format in daily sessions table');
                                $sessions = intval($res->num_of_sessions);
                                $data = array(
                                    'date' => $date->format('Y-m-d'),
                                    'sessions' => $sessions
                                );
                                array_push($data_array, $data);
                            }
                            catch(\Exception $e){
                                $sessions_contain_badly_formatted_dates = true;
                                continue;
                            }
                        }
                        echo '<script>';
                        echo 'var rawSessionData = ' . json_encode($data_array) . ';';
                        echo '</script>';
                    ?>
                    <!-- new central call to DB - END -->

                    <!-- new date controls - START -->
                    <script src='<?php echo IFSO_PLUGIN_DIR_URL . 'admin/js/jquery.ifsodatetimepicker.full.min.js'; ?>' id='if-soDateTimePickerFullMinJs-js'></script>
                    <link rel='stylesheet' id='if-soDateTimePickerCss-css' href='<?php echo IFSO_PLUGIN_DIR_URL . 'admin/css/jquery.ifsodatetimepicker.css'; ?>' media='all' />
                    
                    <div class="geo-info-filter">  
                        <div class="geo-info-filter-container">
                            <input type="text" class="geo-info-filter-picker" id="start-date">
                        </div>
                        <div class="geo-info-filter-container">
                            <input type="text" class="geo-info-filter-picker" id="end-date">
                        </div>
                        <button class="geo-info-filter-submit button" onclick="dateActions.onFilterChange()">Filter</button>
                    </div>
                    <!-- new date controls - END -->

                    <!-- new chart - START -->
                    <div class="geo-info-chart-container">
                        <canvas class="geo-info-chart"></canvas>
                    </div>

                    <script 
                        src="https://cdn.jsdelivr.net/npm/chart.js" 
                        crossorigin="anonymous" 
                        referrerpolicy="no-referrer">
                    </script>

                    <script>
                        class DateActions {
                            constructor(rawData, tableBodySelector, chartContainerSelector, chartSelector, filterSelector, startDateSelector, endDateSelector) {
                                this.rawData = rawData
                                this.data = this.formatSessionData(rawSessionData)
                                this.filteredData = undefined

                                this.startDateSelector = startDateSelector
                                this.endDateSelector = endDateSelector
                             
                                document.addEventListener('DOMContentLoaded', () => { 
                                    this.tbody = document.querySelector(tableBodySelector)
                                    this.chartContainerElem = document.querySelector(chartContainerSelector)
                                    this.chartElem = this.chartContainerElem.querySelector(chartSelector)
                                    this.filterElem = document.querySelector(filterSelector)
                                    this.startDateElem = this.filterElem.querySelector(startDateSelector)
                                    this.endDateElem = this.filterElem.querySelector(endDateSelector)
                                    if(typeof(this.data)==='undefined' || this.data.length===0) {
                                        this.chartContainerElem.classList.toggle('nodisplay');
                                        this.filterElem.classList.toggle('nodisplay');
                                        return;
                                    }
                                    this.initFilters()
                                    this.initChart()
                                    this.fillChart()
                                    this.fillTable()
                                })
                            }

                            initFilters = function() {
                                let start = new Date()
                                start.setHours(0,0,0,0)
                                start.setMonth(start.getMonth() - 1)
                                let end = new Date()
                                end.setHours(0,0,0,0)
                                let minDate = new Date(this.data[0].date.valueOf())
                                minDate.setHours(0,0,0,0)
                                
                                let startStr = start.toISOString().substring(0, 10).split('-').join('/')
                                let endStr = end.toISOString().substring(0, 10).split('-').join('/')

                                let startDateSelector = this.startDateSelector
                                let endDateSelector = this.endDateSelector

                                jQuery(startDateSelector).ifsodatetimepicker({
                                    timepicker: false,
                                    format: 'm/d/Y',
                                    defaultDate: start,
                                    minDate: minDate,
                                    onShow: function(ct) {
                                        let endValue = jQuery(endDateSelector).val()
                                        this.setOptions({
                                            maxDate: endValue ? endValue : false
                                        })
                                    },
                                })
                                jQuery(endDateSelector).ifsodatetimepicker({
                                    timepicker: false,
                                    format: 'm/d/Y',
                                    defaultDate: end,
                                    maxDate:'0',
                                    onShow: function(ct) {
                                        let startValue = jQuery(startDateSelector).val()
                                        this.setOptions({
                                            // todo - cant set the minDate value because it disables all past value for some reason
                                            minDate: false // startValue ? startValue : false
                                        })
                                    },
                                })

                                this.startDateElem.value = this.formatForInput(start)
                                this.endDateElem.value = this.formatForInput(end)
                                this.filterDates(start, end)
                            }
                            formatForInput(date) {
                                let mm = (date.getMonth() + 1).toString().padStart('0', 2)
                                let dd = date.getDate().toString().padStart('0', 2)
                                let yyyy = date.getFullYear().toString()
                                return `${mm}/${dd}/${yyyy}`
                            }

                            initChart = function() {
                                let backgroundColorPlugin = {
                                    beforeDraw: function (chart, easing) {
                                        if (chart.config.options.chartArea && chart.config.options.chartArea.backgroundColor) {
                                            var ctx = chart.ctx
                                            var chartArea = chart.chartArea
                                            ctx.save()
                                            ctx.fillStyle = chart.config.options.chartArea.backgroundColor
                                            ctx.fillRect(chartArea.left, chartArea.top, chartArea.right - chartArea.left, chartArea.bottom - chartArea.top)
                                            ctx.restore()
                                        }
                                    }
                                }

                                this.chart = new Chart(this.chartElem, {
                                    type: 'line',
                                    data: {
                                        labels: undefined,
                                        datasets: [{
                                            label: 'sessions',
                                            data: undefined,
                                            borderWidth: 2,
                                            borderColor: '#EDC240',
                                            backgroundColor: 'white',
                                        }],
                                    },
                                    options: {
                                        scales: {
                                            y: { beginAtZero: true },
                                            x: {
                                                ticks: {
                                                    align: 'center',
                                                    autoSkip: true,
                                                    maxRotation: 0,
                                                    maxTicksLimit: 8
                                                },
                                            },

                                        },
                                        maintainAspectRatio: false,
                                        chartArea: { backgroundColor: '#F9F9F9' },
                                        plugins: {
                                            legend: { display: false },
                                            tooltip: { displayColors: false }
                                        }
                                    },
                                    plugins: [backgroundColorPlugin]
                                });
                            }

                            getChartLabels = function() {
                                return this.filteredData.map(val => val.date.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }))
                            }
                            getChartData = function() {
                                return this.filteredData.map(val => val.sessions)
                            }

                            formatSessionData = function(data) {
                                let reversed = data.reverse()
                                let dateObjectified = reversed.map(item => { item.date = new Date(Date.parse(item.date)); return item;} )
                                let filled = this.addEmptyDates(dateObjectified)
                                return filled
                            }

                            addEmptyDates = function(data) {
                                if (data.length <= 1) return data
                                let start = data[0].date
                                let end = data[data.length - 1].date
                                for (let d = start; d <= end; d = new Date(d.getTime() + 86400000)) { // milliseconds in day
                                    let dateExists = data.find(item => item.date.getTime() === d.getTime())
                                    if (!dateExists) data.push({ date: d, sessions: 0 })
                                }
                                data.sort((a, b) => new Date(a.date) - new Date(b.date))  // Sort again by date
                                return data
                            }

                            filterDates = function(start, end) {
                                let startValid = start instanceof Date && !isNaN(start)
                                let endValid = end instanceof Date && !isNaN(end)

                                if ( !startValid || !endValid ) return
                                if ( start.getTime() >= end.getTime() ) return

                                let startDay = new Date(start.getTime())
                                let endDay = new Date(end.getTime())
                                startDay.setHours(0,0,0,0)
                                endDay.setHours(0,0,0,0)

                                this.filteredData = this.data.filter(val => {
                                    let day = new Date(val.date.getTime())
                                    day.setHours(0,0,0,0)
                                    return (day.getTime() >= startDay.getTime()) && 
                                           (day.getTime() <= endDay.getTime())
                                })
                            }

                            fillTable = function() {
                                this.tbody.innerHTML = ''
                                if (this.filteredData.length === 0) {
                                    let tr = document.createElement('tr')
                                    let notif = document.createElement('td')
                                    let par = document.createElement('p')
                                    notif.colSpan = 4
                                    notif.className = 'empty-table-notifier'
                                    par.innerHTML = "<?php _e('You haven`t used the geolocation service','if-so');?>"
                                    notif.appendChild(par)
                                    tr.appendChild(notif)
                                    this.tbody.appendChild(tr)
                                } else {
                                    this.filteredData.forEach(val => {
                                        let tr = document.createElement('tr')
                                        let dateTd = document.createElement('td')
                                        dateTd.innerHTML = val.date.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })
                                        let sessionsTd = document.createElement('td')
                                        sessionsTd.innerHTML = val.sessions
                                        tr.appendChild(dateTd)
                                        tr.appendChild(sessionsTd)
                                        this.tbody.appendChild(tr)
                                    })
                                }
                            }

                            fillChart = function() {
                                if (this.filteredData.length === 0) { 
                                    this.chartContainerElem.classList.add('disabled')
                                    this.filterElem.classList.add('disabled')
                                } else {
                                    this.chart.data.labels = this.getChartLabels()
                                    this.chart.data.datasets[0].data = this.getChartData()
                                    this.chart.update()
                                }
                            }

                            onFilterChange = function() {
                                let start = new Date(this.startDateElem.value)
                                let end = new Date(this.endDateElem.value)
                                this.filterDates(start, end)
                                this.fillTable()
                                this.fillChart()
                            }
                        }

                        let dateActions = new DateActions(
                            window.rawSessionData,
                            '.geo-info-table tbody',
                            '.geo-info-chart-container',
                            '.geo-info-chart',
                            '.geo-info-filter',
                            '#start-date',
                            '#end-date',
                        )
                    </script>
                    <!-- new chart - END -->
                    
                    <div class="geo-info-table-wrapper">
                        <?php if($sessions_contain_badly_formatted_dates): ?>
                            <div class="red-noticebox">
                                One or more dates in your session log aren't being displayed due to incorrect formatting.
                            </div>
                        <?php endif; ?>
                        <!-- new table - START -->
                        <table class="geo-info-table">
                            <thead>
                            <tr>
                                <th><?php _e('Date','if-so');?></th>
                                <th><?php _e('Daily geolocation sessions','if-so');?></th>
                            </tr>
                            </thead>
                            <tbody></tbody>
                        </table>
                        <!-- new table - END -->
                    </div>
                </div>
                <!-- new geo info cards - END -->

                <div>
                    <?php if(!is_geo_data_valid($geoData)){ ?>
                        <span class="error-label" style="padding-left:10px;">Communication failure! <a href="https://www.if-so.com/help/communication-failure/?utm_source=Plugin&utm_medium=error&utm_campaign=geolocation&utm_term=comm_failure&utm_content=a" target="_blank">Click to solve</a> </span>
                    <?php } ?>
                </div>

            </div>
            <!-- end Info Tab -->

            <!--start extra tabs-->
            <?php echo print_extra_tabs_contents($extra_tabs); ?>
            <!--end extra tabs-->

        </div> <!-- end of ifso-geo-tabs-contents-wrapper -->
    </div>
</body>
</html>