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.71' ); 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/core/countries.php'; // the ONE country list require_once AEGRA_PATH . 'includes/core/xmlrpc.php'; // does xmlrpc.php really answer? 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 ) { // Reads the single list in includes/core/countries.php (was its own 151-entry copy). $map = aegra_countries(); return $map[ strtoupper( (string) $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