'; $logo_url = affkeeper_logo_url(); if ( $logo_url ) { echo ''; } else { // No logo yet — show the domain wordmark; the slot keeps its size when a logo is dropped in. echo ''; } echo '
'; echo '

' . esc_html( $title ) . '

'; echo '' . esc_html( $sub ) . ''; echo '
'; echo ''; } require_once AFFKEEPER_DIR . 'includes/class-affkeeper-api.php'; require_once AFFKEEPER_DIR . 'includes/class-affkeeper-local.php'; require_once AFFKEEPER_DIR . 'includes/class-affkeeper-sync.php'; require_once AFFKEEPER_DIR . 'includes/class-affkeeper-ajax.php'; require_once AFFKEEPER_DIR . 'includes/class-affkeeper-settings.php'; require_once AFFKEEPER_DIR . 'includes/class-affkeeper-shortcode.php'; require_once AFFKEEPER_DIR . 'includes/class-affkeeper-links-page.php'; require_once AFFKEEPER_DIR . 'includes/class-affkeeper-dashboard-widget.php'; /** * Boot the plugin once WordPress is ready. */ function affkeeper_init() { // Bundled translations (languages/affkeeper-{locale}.mo). A wp.org language pack, once one // exists for a locale, is loaded from wp-content/languages first and wins automatically. load_plugin_textdomain( 'affkeeper', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); // Schema migration on update (activation hooks don't run then) — dbDelta is idempotent. // Must wait for 'init': install() touches rewrite rules, and $wp_rewrite doesn't exist yet // at plugins_loaded (fatal). Priority 20 = after AffKeeper_Local registered its rule. if ( get_option( 'affkeeper_db_version' ) !== AFFKEEPER_DB_VERSION ) { add_action( 'init', function () { AffKeeper_Local::install(); update_option( 'affkeeper_db_version', AFFKEEPER_DB_VERSION ); }, 20 ); } AffKeeper_Settings::instance()->hooks(); AffKeeper_Local::instance()->hooks(); AffKeeper_Ajax::instance()->hooks(); AffKeeper_Shortcode::instance()->hooks(); AffKeeper_Links_Page::instance()->hooks(); AffKeeper_Dashboard_Widget::instance()->hooks(); // Report locally-counted /go/ clicks up to the account so panel stats stay in sync. Best-effort // WP-Cron (fires on visits); only changed counts are actually sent (see AffKeeper_Sync). add_action( 'affkeeper_push_clicks', array( 'AffKeeper_Sync', 'push_clicks' ) ); // Same hourly tick, downward leg: apply panel-side edits (slug/destination) to the local // redirects even when nobody opens wp-admin. Fresh map — a stale cache would miss the flags. add_action( 'affkeeper_push_clicks', function () { if ( AffKeeper_API::is_configured() ) { AffKeeper_Sync::push_unsynced(); // heal any local link whose initial push failed AffKeeper_API::flush_cache(); $map = AffKeeper_API::link_map(); if ( ! is_wp_error( $map ) ) { AffKeeper_Sync::pull_updates( $map ); } } } ); if ( ! wp_next_scheduled( 'affkeeper_push_clicks' ) ) { wp_schedule_event( time() + 300, 'hourly', 'affkeeper_push_clicks' ); } } add_action( 'plugins_loaded', 'affkeeper_init' ); /** * Link to the settings page from the plugins list — the first thing a new user needs. * * @param array $links Existing action links. * @return array */ function affkeeper_action_links( $links ) { $url = admin_url( 'admin.php?page=' . AffKeeper_Settings::MENU_SLUG ); $settings = '' . esc_html__( 'Settings', 'affkeeper' ) . ''; $support = '' . esc_html__( 'Support', 'affkeeper' ) . ''; array_unshift( $links, $settings, $support ); return $links; } add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'affkeeper_action_links' ); /** * On activation: create the local-links table and register + flush rewrite rules so * site.com/go/slug starts resolving immediately, without a Settings > Permalinks save. */ function affkeeper_activate() { AffKeeper_Local::install(); update_option( 'affkeeper_db_version', AFFKEEPER_DB_VERSION ); } register_activation_hook( __FILE__, 'affkeeper_activate' ); /** * Clear cached API data on deactivation so a reconnect starts clean. Rewrite rules are flushed too * so the /go/ prefix stops resolving once the plugin is off. */ function affkeeper_deactivate() { AffKeeper_API::flush_cache(); flush_rewrite_rules(); wp_clear_scheduled_hook( 'affkeeper_push_clicks' ); } register_deactivation_hook( __FILE__, 'affkeeper_deactivate' );