= 0). * @type float pct Percentage reduction (0..100). * @type int tokens_html Estimated tokens for the HTML. * @type int tokens_md Estimated tokens for the Markdown. * @type int tokens_saved Estimated tokens saved. * } */ public static function compute() { $types = (array) ADG_AIM_Plugin::get_setting( 'post_types', array( 'post', 'page' ) ); if ( empty( $types ) ) { $types = array( 'post', 'page' ); } $posts = get_posts( array( 'post_type' => $types, 'post_status' => 'publish', 'numberposts' => self::SAMPLE, 'orderby' => 'modified', 'order' => 'DESC', ) ); $html_bytes = 0; $md_bytes = 0; $counted = 0; foreach ( $posts as $post ) { if ( get_post_meta( $post->ID, '_adg_hide_from_ai_bots', true ) ) { continue; } $html = (string) apply_filters( 'the_content', $post->post_content ); $md = (string) ADG_AIM_Markdown_Cache::get( $post, false ); $h = strlen( $html ); $m = strlen( $md ); if ( 0 === $h ) { continue; } $html_bytes += $h; $md_bytes += $m; ++$counted; } return self::shape( $counted, $html_bytes, $md_bytes ); } /** * Turn raw byte sums into the full result array. * * @param int $posts Sampled posts. * @param int $html_bytes HTML bytes. * @param int $md_bytes Markdown bytes. * @return array */ private static function shape( $posts, $html_bytes, $md_bytes ) { $bytes_saved = max( 0, $html_bytes - $md_bytes ); $pct = $html_bytes > 0 ? round( ( $bytes_saved / $html_bytes ) * 100, 1 ) : 0.0; return array( 'posts' => (int) $posts, 'html_bytes' => (int) $html_bytes, 'md_bytes' => (int) $md_bytes, 'bytes_saved' => (int) $bytes_saved, 'pct' => (float) $pct, 'tokens_html' => self::tokens( $html_bytes ), 'tokens_md' => self::tokens( $md_bytes ), 'tokens_saved' => max( 0, self::tokens( $html_bytes ) - self::tokens( $md_bytes ) ), ); } /** * Estimate tokens from a byte/char count. * * @param int $chars Character count. * @return int */ public static function tokens( $chars ) { return (int) ceil( max( 0, (int) $chars ) / self::CHARS_PER_TOKEN ); } /** * Drop the cached estimate (e.g. after content changes or a manual refresh). */ public static function clear() { delete_transient( self::TRANSIENT ); } }