// LVGR Main Tables Generator // wp-admin top-level menu "MAIN TABLES" -> [lvgr_main_table id="N"] shortcode. // Renders the CLASSIC #tbl_top_casinos look (rank / logo / priority-3..5 columns) - // pixel-matching the live homepage table (snippet 11743) - with ALL of its CSS // embedded inline, so it looks right on ANY page/site regardless of whether // jannah-child/assets/home.css happens to be loaded there. // Casino data (name/logo/link/rating/offer/pros/review/legal) is the SAME shared // pool used by "Casino Table" (option lvgr_ct_items) - edit casinos there; this // admin only picks which casinos go in which table, their order, and what shows. // Delivered as a single Woody snippet per project rules. if ( ! defined( 'ABSPATH' ) ) { return; } if ( ! class_exists( 'LVGR_Main_Tables' ) ) : class LVGR_Main_Tables { const TABLES = 'lvgr_mt_tables'; const NEXTID = 'lvgr_mt_next_id'; const NONCE = 'lvgr_mt_save'; public static function init() { add_shortcode( 'lvgr_main_table', array( __CLASS__, 'shortcode' ) ); add_action( 'admin_menu', array( __CLASS__, 'menu' ) ); add_action( 'admin_post_lvgr_mt_save', array( __CLASS__, 'save' ) ); add_action( 'wp_ajax_lvgr_mt_preview', array( __CLASS__, 'ajax_preview' ) ); add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_dashicons' ) ); } // Dashicons (star icons) are core-registered but only auto-loaded in admin; // enqueue them front-end too so this table is portable to any page/site. public static function enqueue_dashicons() { wp_enqueue_style( 'dashicons' ); } // ---------------------------------------------------------------- DATA // Shared casino pool owned by the "Casino Table" generator (snippet 21653). // Read-only here on purpose - casino data is edited in ONE place. public static function items() { $items = get_option( 'lvgr_ct_items' ); return is_array( $items ) ? $items : array(); } public static function tables() { $t = get_option( self::TABLES ); return is_array( $t ) ? $t : array(); } public static function next_id() { $n = (int) get_option( self::NEXTID, 0 ); if ( $n < 1 ) { $n = 1; foreach ( array_keys( self::tables() ) as $k ) { $n = max( $n, (int) $k + 1 ); } } return $n; } public static function bump_next_id( $used ) { update_option( self::NEXTID, max( self::next_id(), (int) $used + 1 ) ); } public static function table_defaults() { return array( 'label' => '', 'selected' => array(), 'cta_text' => 'ΕΓΓΡΑΦΗ', 'review_text' => 'Διάβασε την αξιολόγηση', 'legal' => '21+ | Ρυθμ. ΕΕΕΠ | ΕΟΠΑΕ 1114 | Υπεύθυνο Παιχνίδι', 'ribbon1' => 'Επιλογή Συντακτών', 'ribbon2' => 'Επιλογή Παικτών', 'ribbon3' => 'Καλύτερη Προσφορά* Γνωριμίας', 'max_width' => 900, 'show_rank' => true, 'show_stars' => true, 'show_offer' => true, 'show_pros' => true, 'show_review' => true, 'show_legal' => false, 'show_ribbons' => true, ); } public static function table( $id ) { $tables = self::tables(); $id = (string) (int) $id; if ( ! isset( $tables[ $id ] ) || ! is_array( $tables[ $id ] ) ) { return null; } $t = array_merge( self::table_defaults(), $tables[ $id ] ); if ( ! is_array( $t['selected'] ) ) { $t['selected'] = array(); } $t['id'] = (int) $id; return $t; } // -------------------------------------------------------------- RENDER protected static function stars_dashicons( $rating ) { $n = (int) round( (float) $rating ); $n = max( 0, min( 5, $n ) ); $out = ''; for ( $i = 0; $i < $n; $i++ ) { $out .= ''; } return $out; } public static function render( $args = array(), $items_override = null ) { $def = self::table_defaults(); $s = array_merge( $def, $args ); $items = is_array( $items_override ) ? $items_override : self::items(); $keys = is_array( $s['selected'] ) ? $s['selected'] : array(); $rows = ''; $rank = 0; foreach ( $keys as $k ) { $k = trim( $k ); if ( ! isset( $items[ $k ] ) ) { continue; } $c = $items[ $k ]; $rank++; $rankhtml = $s['show_rank'] ? '' . $rank . '' : ''; $stars = $s['show_stars'] ? '' . self::stars_dashicons( $c['rating'] ) . '' : ''; $review = ''; if ( $s['show_review'] && ! empty( $c['review'] ) && trim( (string) $c['review'] ) !== '' ) { $review = '' . esc_html( $s['review_text'] ) . ''; } $offer = ''; if ( $s['show_offer'] && ! empty( $c['offer'] ) && trim( (string) $c['offer'] ) !== '' ) { $offer = '' . esc_html( $c['offer'] ) . ''; } $pros = ''; if ( $s['show_pros'] && ! empty( $c['pros'] ) && trim( (string) $c['pros'] ) !== '' ) { $lines = array_slice( array_values( array_filter( array_map( 'trim', preg_split( '#\r\n|\r|\n#', (string) $c['pros'] ) ), function ( $l ) { return $l !== ''; } ) ), 0, 3 ); foreach ( $lines as $line ) { $pros .= ' ' . esc_html( $line ) . '
'; } } $legal_row = ''; if ( $s['show_legal'] ) { $legal_txt = ( isset( $c['legal'] ) && trim( (string) $c['legal'] ) !== '' ) ? $c['legal'] : $s['legal']; if ( trim( (string) $legal_txt ) !== '' ) { $legal_row = '' . esc_html( $legal_txt ) . ''; } } $mobile_review = ''; if ( $review !== '' || $stars !== '' ) { $mobile_review = '' . $stars . ' ' . $review . ''; } $rows .= '' . '' . $rankhtml . '' . '' . '' . '' . esc_attr( $c['name'] ) . ' casino' . '' . esc_attr( $c['name'] ) . ' casino' . '' . '' . $stars . '' . '' . '' . $offer . $pros . $legal_row . $mobile_review . '' . '
' . $stars . ( $review !== '' ? '

' . $review . '

' : '' ) . '
' . '' . esc_html( $s['cta_text'] ) . '' . ''; } if ( $rows === '' ) { return ''; } $wrap_class = 'lvgr-mt' . ( $s['show_ribbons'] ? '' : ' lvgr-mt--no-ribbons' ); $max = max( 320, min( 1200, (int) $s['max_width'] ) ); return '
' . self::css( $s ) . '' . $rows . '
'; } public static function render_table( $id, $extra = array() ) { $t = self::table( $id ); if ( ! $t ) { return ''; } $args = array_merge( $t, $extra ); return self::render( $args ); } protected static function css_str( $v ) { return str_replace( array( '\\', '"' ), array( '\\\\', '\\"' ), (string) $v ); } protected static function css( $s = array() ) { $r1 = ( isset( $s['ribbon1'] ) && trim( (string) $s['ribbon1'] ) !== '' ) ? $s['ribbon1'] : 'Επιλογή Συντακτών'; $r2 = ( isset( $s['ribbon2'] ) && trim( (string) $s['ribbon2'] ) !== '' ) ? $s['ribbon2'] : 'Επιλογή Παικτών'; $r3 = ( isset( $s['ribbon3'] ) && trim( (string) $s['ribbon3'] ) !== '' ) ? $s['ribbon3'] : 'Καλύτερη Προσφορά* Γνωριμίας'; $css = ''; return str_replace( array( '__LVGR_MT_RIBBON1__', '__LVGR_MT_RIBBON2__', '__LVGR_MT_RIBBON3__' ), array( self::css_str( $r1 ), self::css_str( $r2 ), self::css_str( $r3 ) ), $css ); } // ----------------------------------------------------------- SHORTCODE public static function shortcode( $atts ) { $atts = shortcode_atts( array( 'id' => '' ), $atts, 'lvgr_main_table' ); if ( $atts['id'] === '' ) { return ''; } $tid = (string) (int) $atts['id']; if ( self::table( $tid ) ) { return self::render_table( $tid ); } return current_user_can( 'manage_options' ) ? '' : ''; } // -------------------------------------------------------------- ADMIN public static function menu() { add_menu_page( 'Main Tables', 'MAIN TABLES', 'manage_options', 'lvgr-main-tables', array( __CLASS__, 'page' ), 'dashicons-editor-table', 60 ); } protected static function selected_from_post( $post, $items ) { $sel = array(); if ( isset( $post['order'] ) && is_array( $post['order'] ) ) { $on = ( isset( $post['enabled'] ) && is_array( $post['enabled'] ) ) ? array_map( 'sanitize_key', array_keys( $post['enabled'] ) ) : array(); $pairs = array(); foreach ( $post['order'] as $key => $p ) { $key = sanitize_key( $key ); if ( in_array( $key, $on, true ) && isset( $items[ $key ] ) ) { $pairs[ $key ] = (float) $p; } } asort( $pairs ); $sel = array_keys( $pairs ); } return $sel; } protected static function sanitize_table( $id, $post, $existing ) { $items = self::items(); $post = is_array( $post ) ? $post : array(); $sel = self::selected_from_post( $post, $items ); if ( empty( $sel ) && ! isset( $post['order'] ) && ! empty( $existing['selected'] ) ) { $sel = $existing['selected']; } $label = sanitize_text_field( wp_unslash( isset( $post['label'] ) ? $post['label'] : '' ) ); if ( $label === '' ) { $label = ! empty( $existing['label'] ) ? $existing['label'] : ( 'Πίνακας ' . (int) $id ); } return array( 'id' => (int) $id, 'label' => $label, 'selected' => $sel, 'cta_text' => sanitize_text_field( wp_unslash( isset( $post['cta_text'] ) ? $post['cta_text'] : '' ) ), 'review_text' => sanitize_text_field( wp_unslash( isset( $post['review_text'] ) ? $post['review_text'] : '' ) ), 'legal' => sanitize_text_field( wp_unslash( isset( $post['legal'] ) ? $post['legal'] : '' ) ), 'ribbon1' => sanitize_text_field( wp_unslash( isset( $post['ribbon1'] ) ? $post['ribbon1'] : '' ) ), 'ribbon2' => sanitize_text_field( wp_unslash( isset( $post['ribbon2'] ) ? $post['ribbon2'] : '' ) ), 'ribbon3' => sanitize_text_field( wp_unslash( isset( $post['ribbon3'] ) ? $post['ribbon3'] : '' ) ), 'max_width' => max( 320, min( 1200, (int) ( isset( $post['max_width'] ) ? $post['max_width'] : 900 ) ) ), 'show_rank' => isset( $post['show_rank'] ), 'show_stars' => isset( $post['show_stars'] ), 'show_offer' => isset( $post['show_offer'] ), 'show_pros' => isset( $post['show_pros'] ), 'show_review' => isset( $post['show_review'] ), 'show_legal' => isset( $post['show_legal'] ), 'show_ribbons' => isset( $post['show_ribbons'] ), ); } public static function save() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( 'Denied' ); } check_admin_referer( self::NONCE ); $tables = self::tables(); if ( isset( $_POST['tbl'] ) && is_array( $_POST['tbl'] ) ) { foreach ( $_POST['tbl'] as $id => $f ) { $id = (string) (int) $id; if ( ! isset( $tables[ $id ] ) ) { continue; } if ( ! empty( $f['delete'] ) ) { unset( $tables[ $id ] ); continue; } $tables[ $id ] = self::sanitize_table( $id, $f, $tables[ $id ] ); } } if ( isset( $_POST['newtbl'] ) && is_array( $_POST['newtbl'] ) && trim( (string) ( isset( $_POST['newtbl']['label'] ) ? wp_unslash( $_POST['newtbl']['label'] ) : '' ) ) !== '' ) { $nid = (string) self::next_id(); $tables[ $nid ] = self::sanitize_table( $nid, $_POST['newtbl'], array() ); self::bump_next_id( $nid ); } update_option( self::TABLES, $tables ); global $wpdb; $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_wbcr_inp_%' OR option_name LIKE '_transient_timeout_wbcr_inp_%'" ); if ( function_exists( 'rocket_clean_domain' ) ) { rocket_clean_domain(); } wp_safe_redirect( add_query_arg( array( 'page' => 'lvgr-main-tables', 'updated' => '1' ), admin_url( 'admin.php' ) ) ); exit; } public static function ajax_preview() { if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( 'denied', 403 ); } if ( ! check_ajax_referer( self::NONCE, '_wpnonce', false ) ) { wp_send_json_error( 'bad nonce', 403 ); } $f = ( isset( $_POST['tbl_one'] ) && is_array( $_POST['tbl_one'] ) ) ? $_POST['tbl_one'] : array(); $id = isset( $_POST['tbl_id'] ) ? (int) $_POST['tbl_id'] : 0; $items = self::items(); $args = self::sanitize_table( $id ?: 0, $f, array() ); $html = self::render( $args, $items ); wp_send_json_success( array( 'preview' => $html, 'html' => $html, 'shortcode' => $id ? ( '[lvgr_main_table id="' . $id . '"]' ) : '', ) ); } protected static function card( $prefix, $tid, $t, $items ) { $def = self::table_defaults(); $t = array_merge( $def, is_array( $t ) ? $t : array() ); $sel = is_array( $t['selected'] ) ? $t['selected'] : array(); $pos = array_flip( $sel ); $is_new = ( (int) $tid < 1 ); $P = esc_attr( $prefix ); $ordered = array(); foreach ( $sel as $k ) { if ( isset( $items[ $k ] ) ) { $ordered[ $k ] = $items[ $k ]; } } foreach ( $items as $k => $c ) { if ( ! isset( $ordered[ $k ] ) ) { $ordered[ $k ] = $c; } } $sc = '[lvgr_main_table id="' . (int) $tid . '"]'; $h = '
'; $h .= '
'; $h .= '

' . ( $is_new ? '+ Νέος Πίνακας' : ( 'Πίνακας #' . (int) $tid ) ) . '

'; $h .= ''; $h .= ''; if ( ! $is_new ) { $h .= ''; } $h .= ''; $h .= ''; $h .= ''; $h .= ''; $h .= ''; $tog = array( 'show_ribbons' => 'Κορδέλες Top 3', 'show_rank' => 'Αριθμός θέσης', 'show_stars' => 'Αστέρια', 'show_offer' => 'Κείμενο προσφοράς', 'show_pros' => 'Pros (✔)', 'show_review' => 'Σύνδεσμος κριτικής', 'show_legal' => 'Νομικό πλαίσιο', ); $h .= ''; $h .= '
Όνομα (εσωτ.)
Shortcode
Κείμενο κουμπιού
Κείμενο κριτικής
Νομικό κείμενο (fallback)
Κείμενο κορδελών (Top 3)' . '' . '' . '
Μέγιστο πλάτος px
Τι εμφανίζεται'; foreach ( $tog as $tk => $tl ) { $h .= ''; } $h .= '
'; $h .= '

Τα καζίνο (logo, link, βαθμολογία, προσφορά, pros, νομικό) διαχειρίζονται στο Casino Table. Εδώ διαλέγεις ποια μπαίνουν σε αυτόν τον πίνακα και με τι σειρά.

'; $h .= '
'; $i = 0; $ro_style = 'font-size:11px;color:#666;max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;'; foreach ( $ordered as $k => $c ) { $on = in_array( $k, $sel, true ); $order = isset( $pos[ $k ] ) ? ( $pos[ $k ] + 1 ) : ( 100 + $i ); $e = esc_attr( $k ); $h .= ''; $h .= ''; $h .= ''; $h .= ''; $h .= ''; $h .= ''; $h .= ''; $h .= ''; $h .= ''; $h .= ''; $h .= ''; $h .= ''; $i++; } $h .= '
Εμφ.ΣειράΌνομαLogo URLAffiliate linkΚριτική (link)Βαθμ.Κείμενο προσφοράςProsΝομικό κείμενο
' . esc_html( $c['name'] ) . '' . esc_html( $c['logo'] ) . '' . esc_html( $c['url'] ) . '' . esc_html( $c['review'] ) . '' . esc_html( $c['rating'] ) . '' . esc_html( $c['offer'] ) . '' . esc_html( isset( $c['pros'] ) ? $c['pros'] : '' ) . '' . esc_html( isset( $c['legal'] ) ? $c['legal'] : '' ) . '
'; if ( ! $is_new ) { $h .= '

'; } $h .= '
'; $h .= '
'; $h .= '

Προεπισκόπηση (ζωντανή)

'; $h .= '
' . ( $is_new ? 'Διάλεξε καζίνο και πάτα Αποθήκευση…' : self::render_table( (string) (int) $tid ) ) . '
'; $h .= '

Αυτόνομο HTML

'; $h .= ''; $h .= ''; $h .= '
'; $h .= '
'; return $h; } public static function page() { if ( ! current_user_can( 'manage_options' ) ) { return; } $items = self::items(); echo '

MAIN TABLES — Κλασικός Πίνακας Σύγκρισης

'; if ( isset( $_GET['updated'] ) ) { echo '

Αποθηκεύτηκε. Οι κρυφές μνήμες καθαρίστηκαν.

'; } echo '

Ίδιο σκεπτικό με το Casino Table, αλλά ο πίνακας βγαίνει ακριβώς όπως ο πίνακας της αρχικής σελίδας (ίδιο CSS, ενσωματωμένο — δουλεύει σε οποιαδήποτε σελίδα, χωρίς να εξαρτάται από το home.css). Κάθε πίνακας παίρνει το δικό του shortcode [lvgr_main_table id="N"].

'; echo '
'; echo ''; wp_nonce_field( self::NONCE ); foreach ( self::tables() as $tbl_id => $tbl_conf ) { echo self::card( 'tbl[' . (int) $tbl_id . ']', (int) $tbl_id, $tbl_conf, $items ); } echo self::card( 'newtbl', 0, array(), $items ); echo '

'; echo '
'; echo ''; echo '
'; } } LVGR_Main_Tables::init(); endif;