prefix + // literal names) for monitoring/diagnostics. Object caching is intentionally // skipped — the data must be fresh — and table-name interpolation uses // $wpdb->prefix-derived names (never user input), which cannot be placeholders. // Justified suppression for this monitoring module. // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching // phpcs:disable WordPress.DB.DirectDatabaseQuery.SchemaChange // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter define( 'AEGRA_VERSION', '1.0.55' ); define( 'AEGRA_PATH', plugin_dir_path( __FILE__ ) ); define( 'AEGRA_URL', plugin_dir_url( __FILE__ ) ); define( 'AEGRA_PURCHASE_URL', 'https://rob-art-plugs-books.lemonsqueezy.com/checkout/buy/35e71ca8-0d03-4c1c-a46b-4c2499383881' ); // ── Activation ──────────────────────────────────────────────────────────────── register_activation_hook( __FILE__, 'aegra_activate' ); function aegra_activate() { require_once AEGRA_PATH . 'includes/activity-logger.php'; ( new Aegra_Activity_Logger() )->create_table(); require_once AEGRA_PATH . 'includes/broken-link-checker.php'; ( new Aegra_Broken_Link_Checker() )->create_table(); require_once AEGRA_PATH . 'includes/traffic-tracker.php'; ( new Aegra_Traffic_Tracker() )->create_table(); $aegra = new AegraWP(); if ( method_exists( $aegra, 'create_brute_force_table' ) ) { $aegra->create_brute_force_table(); } set_transient( 'aegra_activation_redirect', true, 30 ); if ( ! get_option( 'aegra_install_date' ) ) { update_option( 'aegra_install_date', time() ); } } // Redirect to splash on activation add_action( 'admin_init', function() { if ( wp_doing_ajax() ) return; if ( get_transient( 'aegra_activation_redirect' ) ) { delete_transient( 'aegra_activation_redirect' ); wp_safe_redirect( admin_url( 'admin.php?page=aegra-site-monitor-splash' ) ); exit; } } ); // ── Includes ────────────────────────────────────────────────────────────────── require_once AEGRA_PATH . 'includes/activity-logger.php'; require_once AEGRA_PATH . 'includes/broken-link-checker.php'; require_once AEGRA_PATH . 'includes/traffic-tracker.php'; require_once AEGRA_PATH . 'includes/core/mmdb.php'; require_once AEGRA_PATH . 'includes/core/geo.php'; require_once AEGRA_PATH . 'includes/admin/maxmind-install.php'; require_once AEGRA_PATH . 'includes/admin/splash.php'; require_once AEGRA_PATH . 'includes/admin/wizard.php'; require_once AEGRA_PATH . 'includes/compat.php'; require_once AEGRA_PATH . 'includes/review-notice.php'; // ── PRO loader ──────────────────────────────────────────────────────────────── // Elementor model: the Pro extension is a SEPARATE plugin the user installs // from their purchase. The free package only DETECTS it and loads it if present // — it never downloads or installs Pro code itself (no auto-installer ships in // the free .org package). if ( file_exists( AEGRA_PATH . 'pro/pro.php' ) ) { require_once AEGRA_PATH . 'pro/pro.php'; } // ── Licence (Pro-side) ────────────────────────────────────────────────────── // Licence handling lives in the Pro extension (pro/licence.php, loaded by // pro/pro.php above) — NOT in the free package. When Pro is present it has // already defined aegra_get_tier() / aegra_has_licence() by this point. When // Pro is absent we define lightweight free-tier fallbacks so the ~89 call // sites (87 already function_exists-guarded, plus 2 direct) resolve cleanly to // the Free tier instead of fatalling. This is the Elementor-model split: the // free plugin only DETECTS Pro; it contains no licence/tier engine. if ( ! function_exists( 'aegra_has_licence' ) ) { function aegra_has_licence() { return false; } } if ( ! function_exists( 'aegra_get_tier' ) ) { function aegra_get_tier() { return defined( 'AEGRA_PRO_VERSION' ) ? 'Pro' : 'Free'; } } // ── Admin helpers ───────────────────────────────────────────────────────────── function aegra_upgrade_overlay() { ?> tag, .org compliant). $aegra_overlay_js = <<<'JS' (function() { var overlay = document.getElementById('aegra-upgrade-overlay'); if ( ! overlay ) return; function openOverlay() { overlay.style.display = 'flex'; document.body.style.overflow = 'hidden'; setTimeout(function() { overlay.classList.add('aegra-overlay-visible'); }, 10); } function closeOverlay() { overlay.classList.remove('aegra-overlay-visible'); document.body.style.overflow = ''; setTimeout(function() { overlay.style.display = 'none'; }, 220); } document.addEventListener('click', function(e) { if ( e.target.closest('.aegra-upgrade-trigger') ) { e.preventDefault(); openOverlay(); } if ( e.target === overlay ) closeOverlay(); }); document.getElementById('aegra-overlay-close').addEventListener('click', closeOverlay); document.addEventListener('keydown', function(e) { if ( e.key === 'Escape' ) closeOverlay(); }); // Seat selector var seats = overlay.querySelectorAll('.aegra-seat-btn'); var prices = { '1': { proYr: '€19/yr', proLife: 'or €49 lifetime' }, '5': { proYr: '€39/yr', proLife: 'or €89 lifetime' }, 'u': { proYr: '€59/yr', proLife: 'or €129 lifetime' }, }; seats.forEach(function(btn) { btn.addEventListener('click', function() { seats.forEach(function(b) { b.classList.remove('aegra-seat-btn--active'); }); btn.classList.add('aegra-seat-btn--active'); var s = btn.dataset.seat; if ( prices[s] ) { document.getElementById('aegra-price-pro-yr').innerHTML = prices[s].proYr; document.getElementById('aegra-price-pro-life').innerHTML = prices[s].proLife; } }); }); // Licence-key entry + Pro install/activate scripting removed — licence // handling lives in the Pro extension (Elementor model). The free modal // is advertising only: it shows Pro benefits and links to checkout. })(); JS; if ( function_exists( 'wp_add_inline_script' ) ) { wp_add_inline_script( 'aegra-site-monitor-admin', $aegra_overlay_js ); } } function aegra_country_name( $cc ) { static $map = [ 'AF'=>'Afghanistan','AL'=>'Albania','DZ'=>'Algeria','AO'=>'Angola','AR'=>'Argentina', 'AU'=>'Australia','AT'=>'Austria','AZ'=>'Azerbaijan','BD'=>'Bangladesh','BY'=>'Belarus', 'BE'=>'Belgium','BO'=>'Bolivia','BA'=>'Bosnia & Herzegovina','BW'=>'Botswana','BR'=>'Brazil', 'BG'=>'Bulgaria','BF'=>'Burkina Faso','BI'=>'Burundi','KH'=>'Cambodia','CM'=>'Cameroon', 'CA'=>'Canada','CF'=>'Central African Republic','TD'=>'Chad','CL'=>'Chile','CN'=>'China', 'CO'=>'Colombia','CD'=>'Congo (DR)','CG'=>'Congo','CR'=>'Costa Rica','CI'=>"Côte d'Ivoire", 'HR'=>'Croatia','CU'=>'Cuba','CZ'=>'Czech Republic','DK'=>'Denmark','DJ'=>'Djibouti', 'DO'=>'Dominican Republic','EC'=>'Ecuador','EG'=>'Egypt','SV'=>'El Salvador','ER'=>'Eritrea', 'EE'=>'Estonia','ET'=>'Ethiopia','FI'=>'Finland','FR'=>'France','GA'=>'Gabon','GM'=>'Gambia', 'GE'=>'Georgia','DE'=>'Germany','GH'=>'Ghana','GR'=>'Greece','GT'=>'Guatemala','GN'=>'Guinea', 'GW'=>'Guinea-Bissau','GY'=>'Guyana','HT'=>'Haiti','HN'=>'Honduras','HU'=>'Hungary', 'IS'=>'Iceland','IN'=>'India','ID'=>'Indonesia','IR'=>'Iran','IQ'=>'Iraq','IE'=>'Ireland', 'IL'=>'Israel','IT'=>'Italy','JM'=>'Jamaica','JP'=>'Japan','JO'=>'Jordan','KZ'=>'Kazakhstan', 'KE'=>'Kenya','KP'=>'North Korea','KR'=>'South Korea','KW'=>'Kuwait','LA'=>'Laos', 'LB'=>'Lebanon','LS'=>'Lesotho','LR'=>'Liberia','LY'=>'Libya','LT'=>'Lithuania', 'LU'=>'Luxembourg','MG'=>'Madagascar','MW'=>'Malawi','MY'=>'Malaysia','ML'=>'Mali', 'MT'=>'Malta','MR'=>'Mauritania','MX'=>'Mexico','MD'=>'Moldova','MN'=>'Mongolia', 'ME'=>'Montenegro','MA'=>'Morocco','MZ'=>'Mozambique','MM'=>'Myanmar','NA'=>'Namibia', 'NP'=>'Nepal','NL'=>'Netherlands','NZ'=>'New Zealand','NI'=>'Nicaragua','NE'=>'Niger', 'NG'=>'Nigeria','MK'=>'North Macedonia','NO'=>'Norway','PK'=>'Pakistan','PA'=>'Panama', 'PG'=>'Papua New Guinea','PY'=>'Paraguay','PE'=>'Peru','PH'=>'Philippines','PL'=>'Poland', 'PT'=>'Portugal','RO'=>'Romania','RU'=>'Russia','RW'=>'Rwanda','SA'=>'Saudi Arabia', 'SN'=>'Senegal','RS'=>'Serbia','SL'=>'Sierra Leone','SK'=>'Slovakia','SI'=>'Slovenia', 'SO'=>'Somalia','ZA'=>'South Africa','SS'=>'South Sudan','ES'=>'Spain','LK'=>'Sri Lanka', 'SD'=>'Sudan','SR'=>'Suriname','SZ'=>'Eswatini','SE'=>'Sweden','CH'=>'Switzerland', 'SY'=>'Syria','TW'=>'Taiwan','TJ'=>'Tajikistan','TZ'=>'Tanzania','TH'=>'Thailand', 'TG'=>'Togo','TT'=>'Trinidad & Tobago','TN'=>'Tunisia','TR'=>'Turkey','TM'=>'Turkmenistan', 'UG'=>'Uganda','UA'=>'Ukraine','AE'=>'United Arab Emirates','GB'=>'United Kingdom', 'US'=>'United States','UY'=>'Uruguay','UZ'=>'Uzbekistan','VE'=>'Venezuela','VN'=>'Vietnam', 'YE'=>'Yemen','ZM'=>'Zambia','ZW'=>'Zimbabwe', ]; return $map[ strtoupper( $cc ) ] ?? $cc; } function aegra_icon( $name, $class = '' ) { // Look in the free icon set first, then fall back to the Pro extension's // icon set. Pro-only icons live in pro/assets/icons/ (not shipped in the // free .org package); this fallback lets Pro modules keep using // aegra_icon('name') transparently when the Pro extension is installed. $file = AEGRA_PATH . 'assets/icons/' . $name . '.svg'; if ( ! file_exists( $file ) ) { $pro_file = AEGRA_PATH . 'pro/assets/icons/' . $name . '.svg'; if ( ! file_exists( $pro_file ) ) return ''; $file = $pro_file; } $svg = file_get_contents( $file ); // Strip XML declaration and comments $svg = preg_replace( '/<\?xml[^>]*\?>\s*/i', '', $svg ); $svg = preg_replace( '//s', '', $svg ); // Icons with data-keep-fill preserve their hardcoded colours — skip fill normalisation $keep_fill = preg_match( '/\bdata-keep-fill\b/', $svg ); // Strip embedded