/* Plugin Name: AFP Loyalty Video Unlock Description: Locks selected posts/videos until a visitor reaches a configurable number of site visits (counted no more than once per interval). Includes admin-page thresholds, meta-box & list-table toggle (iOS style in WP-blue), blurred thumbnails with lock icon + click popup, front-end blur/overlay, and a bottom-right visit counter. Version: 1.0.7 Author: AdFreePorn.net License: GPL-2.0+ */ defined( 'ABSPATH' ) || exit; /*──────────────────────────────────────────── 0. DEFAULT OPTIONS (on activation) ────────────────────────────────────────────*/ register_activation_hook( __FILE__, function () { add_option( 'afp_loyalty_required', 5 ); // visits needed add_option( 'afp_loyalty_interval', 43200 ); // seconds between counted visits (12 h) } ); /*──────────────────────────────────────────── 1. HELPER FUNCTIONS ────────────────────────────────────────────*/ function afp_loyalty_required() { return max( 1, (int) get_option( 'afp_loyalty_required', 5 ) ); } function afp_loyalty_interval() { return max( 60, (int) get_option( 'afp_loyalty_interval', 43200 ) ); } function afp_loyalty_get_count() { if ( is_user_logged_in() ) { return (int) get_user_meta( get_current_user_id(), 'afp_loyalty_visits', true ); } return (int) ( $_COOKIE['afp_loyalty_visits'] ?? 0 ); } function afp_loyalty_is_unlocked() { return afp_loyalty_get_count() >= afp_loyalty_required(); } function afp_loyalty_post_locked( $post_id ) { return (bool) get_post_meta( $post_id, 'afp_loyalty_locked', true ); } /*──────────────────────────────────────────── 2. VISIT COUNTER (front-end only) ────────────────────────────────────────────*/ add_action( 'init', function () { if ( is_admin() ) { return; } $now = time(); $interval = afp_loyalty_interval(); if ( is_user_logged_in() ) { $uid = get_current_user_id(); $last = (int) get_user_meta( $uid, 'afp_loyalty_last', true ); if ( $now - $last >= $interval ) { update_user_meta( $uid, 'afp_loyalty_visits', afp_loyalty_get_count() + 1 ); update_user_meta( $uid, 'afp_loyalty_last', $now ); } } else { $visits = afp_loyalty_get_count(); $last = (int) ( $_COOKIE['afp_loyalty_last'] ?? 0 ); if ( $now - $last >= $interval ) { $visits++; $cookie = array( 'expires' => $now + YEAR_IN_SECONDS * 5, 'path' => COOKIEPATH ?: '/', 'domain' => COOKIE_DOMAIN, 'secure' => is_ssl(), 'httponly' => true, 'samesite' => 'Lax', ); setcookie( 'afp_loyalty_visits', $visits, $cookie ); setcookie( 'afp_loyalty_last', $now, $cookie ); } } }, 1 ); /*──────────────────────────────────────────── 3. ADMIN – SETTINGS PAGE ────────────────────────────────────────────*/ add_action( 'admin_menu', function () { add_options_page( 'Loyalty Unlock', 'Loyalty Unlock', 'manage_options', 'afp-loyalty', function () { if ( isset( $_POST['afp_loyalty_save'] ) && check_admin_referer( 'afp_loyalty_settings' ) ) { update_option( 'afp_loyalty_required', max( 1, (int) $_POST['afp_loyalty_required'] ) ); update_option( 'afp_loyalty_interval', max( 1, (int) $_POST['afp_loyalty_interval'] ) * 3600 ); echo '

Settings saved.

'; } $req = afp_loyalty_required(); $intH = afp_loyalty_interval() / 3600; echo '

Loyalty Unlock Settings

'; wp_nonce_field( 'afp_loyalty_settings' ); echo '
Visits required
Hours between counted visits
'; submit_button(); echo '
'; } ); } ); /*──────────────────────────────────────────── 4. META-BOX TOGGLE ────────────────────────────────────────────*/ add_action( 'add_meta_boxes', function () { foreach ( array( 'post', 'video' ) as $type ) { if ( post_type_exists( $type ) ) { add_meta_box( 'afp_loyalty_box', 'Premium Lock', function ( $post ) { wp_nonce_field( 'afp_loyalty_save', 'afp_loyalty_nonce' ); $checked = afp_loyalty_post_locked( $post->ID ) ? 'checked' : ''; echo ' '; }, $type, 'side', 'high' ); } } } ); add_action( 'save_post', function ( $post_id ) { if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } if ( ! isset( $_POST['afp_loyalty_nonce'] ) || ! wp_verify_nonce( $_POST['afp_loyalty_nonce'], 'afp_loyalty_save' ) ) { return; } if ( isset( $_POST['afp_loyalty_locked'] ) ) { update_post_meta( $post_id, 'afp_loyalty_locked', 1 ); } else { delete_post_meta( $post_id, 'afp_loyalty_locked' ); } } ); /*──────────────────────────────────────────── 5. LIST-TABLE COLUMN + AJAX TOGGLE ────────────────────────────────────────────*/ add_filter( 'manage_posts_columns', function ( $c ) { $c['afp_lock'] = 'Lock'; return $c; }, 99 ); add_filter( 'manage_edit-post_columns', function ( $c ) { $c['afp_lock'] = 'Lock'; return $c; }, 99 ); add_filter( 'manage_edit-video_columns', function ( $c ) { $c['afp_lock'] = 'Lock'; return $c; }, 99 ); add_action( 'manage_posts_custom_column', function ( $col, $id ) { if ( $col !== 'afp_lock' ) { return; } $checked = afp_loyalty_post_locked( $id ) ? 'checked' : ''; echo ' '; }, 10, 2 ); add_action( 'manage_post_custom_column', 'afp_loyalty_render_fallback', 10, 2 ); add_action( 'manage_video_custom_column', 'afp_loyalty_render_fallback', 10, 2 ); function afp_loyalty_render_fallback( $col, $id ) { if ( $col !== 'afp_lock' ) { return; } $checked = afp_loyalty_post_locked( $id ) ? 'checked' : ''; echo ' '; } /* AJAX */ add_action( 'wp_ajax_afp_loyalty_toggle', function () { if ( ! current_user_can( 'edit_posts' ) ) { wp_send_json_error(); } check_ajax_referer( 'afp_loyalty_nonce', 'nonce', false ); $id = (int) ( $_POST['post'] ?? 0 ); $lock = (int) ( $_POST['lock'] ?? 0 ); if ( ! $id ) { wp_send_json_error(); } $lock ? update_post_meta( $id, 'afp_loyalty_locked', 1 ) : delete_post_meta( $id, 'afp_loyalty_locked' ); wp_send_json_success(); } ); /*──────────────────────────────────────────── 6. THUMBNAIL OVERLAY (blur + icon) ────────────────────────────────────────────*/ add_filter( 'post_thumbnail_html', function ( $html, $id ) { if ( ! afp_loyalty_post_locked( $id ) || afp_loyalty_is_unlocked() ) { return $html; } $r = afp_loyalty_required() - afp_loyalty_get_count(); return ' ' . $html . ' '; }, 10, 2 ); /*──────────────────────────────────────────── 7. CONTENT OVERLAY ────────────────────────────────────────────*/ add_filter( 'the_content', function ( $html ) { if ( ! is_singular() ) { return $html; } global $post; if ( ! afp_loyalty_post_locked( $post->ID ) || afp_loyalty_is_unlocked() ) { return $html; } $r = afp_loyalty_required() - afp_loyalty_get_count(); return '
Visit ' . $r . ' more time' . ( $r === 1 ? '' : 's' ) . ' to unlock this video.
' . $html . '
'; }, 8 ); /*──────────────────────────────────────────── 8. STYLES + SCRIPTS ────────────────────────────────────────────*/ add_action( 'admin_enqueue_scripts', function ( $hook ) { if ( ! in_array( $hook, array( 'edit.php', 'post.php', 'post-new.php' ), true ) ) { return; } wp_enqueue_style( 'dashicons' ); wp_add_inline_style( 'wp-admin', ' .afp-switch{position:relative;display:inline-block;width:46px;height:24px;vertical-align:middle;cursor:pointer} .afp-switch input{opacity:0;width:0;height:0} .afp-slider{position:absolute;top:0;left:0;right:0;bottom:0;background:#ccc;border-radius:34px;transition:.4s} .afp-slider:before{content:"";position:absolute;height:18px;width:18px;left:3px;bottom:3px;background:#fff;border-radius:50%;transition:.4s} .afp-switch input:checked + .afp-slider{background:#2271b1} .afp-switch input:checked + .afp-slider:before{transform:translateX(22px)} .afp-switch input:focus + .afp-slider{box-shadow:0 0 1px #2271b1} ' ); wp_add_inline_script( 'jquery-core', ' jQuery(function($){ const n="' . wp_create_nonce( 'afp_loyalty_nonce' ) . '"; $(document).on("change",".afp-lock-toggle",function(){ $.post(ajaxurl,{action:"afp_loyalty_toggle",nonce:n,post:$(this).data("post"),lock:this.checked?1:0}); }); }); ' ); } ); add_action( 'wp_enqueue_scripts', function () { wp_enqueue_style( 'dashicons' ); /* ─── NEW LOOK ───────────────────────── */ $css = ' /* common wrapper (IMG thumbs) */ .afp-thumb-wrap{position:relative;display:inline-block;overflow:hidden} .afp-thumb-wrap img{display:block;width:100%;height:auto;transform:scale(1.05);filter:blur(8px)} .afp-thumb-lock{position:absolute;inset:0;background:rgba(0,0,0,.35);pointer-events:none} .afp-thumb-lock:before{content:"\f160";font-family:"Dashicons";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:64px;line-height:1;color:#fff} /* background-image thumbs (WP-Script & co) */ a.thumb.afp-locked-thumb{position:relative;display:block;overflow:hidden} a.thumb.afp-locked-thumb:before{ content:"";position:absolute;inset:0;transform:scale(1.05); filter:blur(8px);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px); } a.thumb.afp-locked-thumb:after{ content:"\f160";font-family:"Dashicons";position:absolute;top:50%;left:50%; transform:translate(-50%,-50%);font-size:64px;line-height:1;color:#fff } /* single-post lock overlay */ .afp-locked{position:relative} .afp-locked-msg{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.85);color:#fff;font-size:20px;text-align:center;padding:20px;z-index:10} .afp-locked-blur{filter:blur(8px);pointer-events:none} /* visit counter bubble */ #afp-loyalty-popup{position:fixed;bottom:20px;right:20px;z-index:9999;background:#222;color:#fff;padding:10px 14px;border-radius:6px;font-size:14px;line-height:1.3;box-shadow:0 2px 6px rgba(0,0,0,.4)} '; wp_add_inline_style( 'wp-block-library', $css ); /* list of locked posts visible on the current query */ $locked = array(); if ( ! afp_loyalty_is_unlocked() && isset( $GLOBALS['wp_query']->posts ) ) { foreach ( $GLOBALS['wp_query']->posts as $p ) { if ( afp_loyalty_post_locked( $p->ID ) ) { $locked[] = $p->ID; } } } wp_add_inline_script( 'wp-hooks', ' const afpLockedPosts=' . json_encode( $locked ) . '; const afpVisits=' . afp_loyalty_get_count() . '; const afpReq=' . afp_loyalty_required() . '; document.addEventListener("DOMContentLoaded",function(){ document.querySelectorAll("a.thumb[data-post-id]").forEach(function(el){ const id=parseInt(el.dataset.postId||0); if(afpLockedPosts.includes(id)){ el.classList.add("afp-locked-thumb"); el.dataset.afpRem=afpReq-afpVisits; } }); }); document.addEventListener("click",function(e){ const w=e.target.closest(".afp-thumb-wrap, a.thumb.afp-locked-thumb"); if(!w){return;} e.preventDefault(); const r=w.dataset.afpRem||0; alert("Locked. Visit "+r+" more time"+(r==1?"":"s")+" to unlock!"); }); ' ); } ); /*──────────────────────────────────────────── 9. VISIT COUNTER POPUP ────────────────────────────────────────────*/ add_action( 'wp_footer', function () { echo '
Visits: ' . afp_loyalty_get_count() . ' / ' . afp_loyalty_required() . '
'; } );