';
$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 'affkeeper.com';
}
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' );