null, 'last_sync_at' => null, 'plan_renews_at' => null, 'queue_pending' => null, 'remote_error' => new WP_Error( 'addsynapse_search_missing_analytics', __( 'The stats class has not loaded.', 'addsynapse-search-filter' ) ), ); $renews_at = Addsynapse_Search_Admin::array_get( $index, array( 'plan_renews_at' ), '' ); $total_local = (int) wp_count_posts( 'product' )->publish; $indexed_count = is_numeric( $index['indexed_count'] ) ? (int) $index['indexed_count'] : null; $mismatch = ( null !== $indexed_count && $indexed_count !== $total_local ); // 0.8.0: μερική κάλυψη λόγω πακέτου ΔΕΝ είναι «χαλασμένος δείκτης» — το λέει ήρεμα η ειδοποίηση // κάλυψης (τα υπόλοιπα βρίσκονται από την αναζήτηση του WordPress). Όχι κόκκινο «Fix now». if ( $mismatch && class_exists( 'Addsynapse_Search_Coverage' ) && Addsynapse_Search_Coverage::is_partial() ) { $mismatch = false; } // Πακέτο/όριο/χρήση — έρχονται μαζί με τα υπόλοιπα στατιστικά (Addsynapse_Search_Analytics:: // get_index_status(), πεδία plan/limit/current από το ίδιο GET /v1/stats). // $usage_limit === null σημαίνει είτε άγνωστο (καμία ενεργή άδεια/σφάλμα δικτύου) // είτε ρητά απεριόριστο πακέτο -- και στις δύο περιπτώσεις δεν δείχνουμε μπάρα. $plan_code = isset( $index['plan'] ) ? (string) $index['plan'] : ''; $usage_limit = isset( $index['limit'] ) && is_numeric( $index['limit'] ) ? (int) $index['limit'] : null; $usage_current = isset( $index['current'] ) && is_numeric( $index['current'] ) ? (int) $index['current'] : $indexed_count; $usage_ratio = ( null !== $usage_limit && $usage_limit > 0 && null !== $usage_current ) ? min( 1.0, $usage_current / $usage_limit ) : null; $usage_near_limit = ( null !== $usage_ratio && $usage_ratio >= 0.8 ); // 🔴 «Διαφάνεια» (ρητή απαίτηση χρήστη): ΔΕΥΤΕΡΟ, ανεξάρτητο όριο πάνω στις // ΕΓΓΡΑΦΕΣ του δείκτη (records_count/records_limit, GET /v1/stats -- βλ. // backend config/plans.php § record_limit). Ίδια σύμβαση null με το // $usage_limit/$usage_ratio παραπάνω -- ίδιο 80% κατώφλι προειδοποίησης. $records_limit = isset( $index['records_limit'] ) && is_numeric( $index['records_limit'] ) ? (int) $index['records_limit'] : null; $records_current = isset( $index['records_count'] ) && is_numeric( $index['records_count'] ) ? (int) $index['records_count'] : null; $records_ratio = ( null !== $records_limit && $records_limit > 0 && null !== $records_current ) ? min( 1.0, $records_current / $records_limit ) : null; $records_near_limit = ( null !== $records_ratio && $records_ratio >= 0.8 ); // 🔴 «Ακριβής αναζήτηση παραλλαγών» (task-brief §1/§5, read-only εδώ — το // flag το ελέγχει ΜΟΝΟ το εσωτερικό admin μας, βλ. CLAUDE.md). Όταν ενεργή, // products_count/documents_count διαφέρουν (1 προϊόν = Ν έγγραφα, ένα ανά // παραλλαγή) -- δείχνουμε ΚΑΙ ΤΑ ΔΥΟ, όπως ζητά ρητά η ανάθεση // ("214 products · 478 documents"), όχι μόνο ένα νούμερο που κρύβει το άλλο. $variation_indexing = ! empty( $index['variation_indexing'] ); $documents_count = isset( $index['documents_count'] ) && is_numeric( $index['documents_count'] ) ? (int) $index['documents_count'] : null; // records_current πέφτει σε documents_count όταν το records_count λείπει // (π.χ. παλιότερη cache του backend) -- ΙΔΙΟ πλήθος σε κάθε περίπτωση. if ( null === $records_current ) { $records_current = $documents_count; $records_ratio = ( null !== $records_limit && $records_limit > 0 && null !== $records_current ) ? min( 1.0, $records_current / $records_limit ) : null; $records_near_limit = ( null !== $records_ratio && $records_ratio >= 0.8 ); } // Δίκαιη χρήση αναζητήσεων (GET /v1/stats § fair_use, 29/09). ΜΟΝΟ // ενημερωτικό: η αναζήτηση δεν κόβεται. Το Addsynapse_Search_Analytics::normalize() // δίνει null όταν το μπλοκ λείπει (παλιός server) ή η μέτρηση δεν έχει τρέξει // ποτέ (counted_until null) — τότε ΔΕΝ δείχνουμε τίποτα, ποτέ «0» ως γεγονός. // Όριο/ποσοστό έρχονται ΠΑΝΤΑ από τον server, κανένα νούμερο εδώ. $fair_use = ( isset( $index['fair_use'] ) && is_array( $index['fair_use'] ) && isset( $index['fair_use']['limit'], $index['fair_use']['searches'] ) ) ? $index['fair_use'] : null; $fair_use_ratio = null !== $fair_use ? min( 1.0, max( 0.0, (float) $fair_use['percent'] / 100 ) ) : null; $fair_use_notice = null !== $fair_use && in_array( $fair_use['level'], array( 'warning', 'exceeded' ), true ); $billing_interval = isset( $index['billing_interval'] ) && in_array( $index['billing_interval'], array( 'month', 'year' ), true ) ? $index['billing_interval'] : null; // Σημάδι «χτυπήσαμε το όριο κατά τη δεικτοδότηση» (402 plan_limit, βλ. // Addsynapse_Search_Indexer::flag_plan_limit()) — ΞΕΧΩΡΙΣΤΟ από το $usage_near_limit // παραπάνω: αυτό εδώ σημαίνει ότι ΗΔΗ κάποια προϊόντα ΔΕΝ μπήκαν στον δείκτη, // όχι απλώς «πλησιάζεις». $plan_limit_notice = ( class_exists( 'Addsynapse_Search_Indexer' ) && method_exists( 'Addsynapse_Search_Indexer', 'get_plan_limit_notice' ) ) ? Addsynapse_Search_Indexer::get_plan_limit_notice() : null; // 🔴 Ανεξαρτητοποίηση της δεικτοδότησης από το WP-Cron: δύο ελέγχοι ΠΡΙΝ ο // χρήστης πατήσει οτιδήποτε (βλ. Addsynapse_Search_Analytics::get_queue_health() και // "Run now" στο τέλος της κάρτας «Indexing» παρακάτω). $cron_disabled = defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON; $queue_health = ( class_exists( 'Addsynapse_Search_Analytics' ) && method_exists( 'Addsynapse_Search_Analytics', 'get_queue_health' ) ) ? Addsynapse_Search_Analytics::get_queue_health() : array( 'stalled' => false, 'pending_since' => null, 'age_seconds' => null, ); // Γραμμή κατάστασης δεικτοδότησης -- ΚΑΤΑΣΤΑΣΗ, όχι υπόσχεση (βλ. ανάθεση: // "Full reindex scheduled and will run shortly" ΔΕΝ είναι γεγονός όταν το // cron δεν δουλεύει). Το JS (admin.js) αντικαθιστά αυτό το κείμενο ζωντανά // όσο τρέχει το "Run now" (#wosearch-index-status-line). $queue_pending = isset( $index['queue_pending'] ) ? $index['queue_pending'] : null; if ( $mismatch && is_numeric( $queue_pending ) && $queue_pending > 0 && ! $queue_health['stalled'] ) { $status_line = sprintf( /* translators: %d: number of pending Action Scheduler actions in the "addsynapse-search" group */ __( 'Queued: %d pending actions', 'addsynapse-search-filter' ), (int) $queue_pending ); } elseif ( null !== $indexed_count ) { $status_line = sprintf( /* translators: 1: indexed products, 2: products in the store */ __( 'Indexed %1$s of %2$s', 'addsynapse-search-filter' ), $indexed_count, $total_local ); } else { $status_line = __( '—', 'addsynapse-search-filter' ); } ?>
get_error_code() ) : ?>
get_error_message() ); ?>
' . esc_html( $indexed_count ) . '',
'' . esc_html( $total_local ) . ''
);
?>
✓
| ● | |
| · ● ● ● | |
|
|
|