PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.7.0
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.7.0
4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.5.2 All 199 releases
betterdocs / includes / Utils / AIUsage.php

AIUsage.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 4.7.0, at includes/Utils/AIUsage.php

118 lines 3.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPDeveloper\BetterDocs\Utils;
4
5 /**
6 * Exit if accessed directly
7 */
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Lightweight usage counter for AI features.
14 *
15 * Each successful AI invocation is recorded in two places:
16 * - a site-wide autoloaded option ({@see self::OPTION_KEY}) holding lifetime totals
17 * per feature (plus an `*_actions` sub-map for features with action variants, e.g.
18 * AI Edit's improve/rewrite/...). This is what the wpinsight collector ships.
19 * - a per-doc post meta ({@see self::META_KEY}) when a valid post id is available, so
20 * on-site reporting can later break usage down per document.
21 *
22 * Writes are a plain read-modify-write (not atomic) — the same trade-off the existing
23 * `betterdocs_analytics` increments make; acceptable for low-stakes usage telemetry.
24 *
25 * @since 4.5.4
26 */
27 class AIUsage {
28 /**
29 * Autoloaded option holding site-wide lifetime totals.
30 */
31 const OPTION_KEY = 'betterdocs_ai_usage';
32
33 /**
34 * Per-document usage counts.
35 */
36 const META_KEY = '_betterdocs_ai_usage';
37
38 /**
39 * Canonical feature keys. Kept fixed so the wpinsight payload schema is stable —
40 * every key is always present (default 0) even before a feature is ever used.
41 *
42 * @var string[]
43 */
44 const FEATURES = [
45 'write_with_ai',
46 'ai_edit',
47 'article_summary',
48 'quality_score',
49 'glossaries_write_with_ai',
50 'faq_write_with_ai',
51 ];
52
53 /**
54 * Record one successful AI invocation.
55 *
56 * @param string $feature One of {@see self::FEATURES}. Unknown keys are ignored.
57 * @param int $post_id Document id, or 0 when there is no reliable post (e.g. an
58 * unsaved doc or a pre-save glossary/FAQ generation) — the
59 * per-doc meta is then skipped, the site-wide total still bumps.
60 * @param string $sub Optional sub-bucket (e.g. an AI Edit action: improve/rewrite/…).
61 * @return void
62 */
63 public static function record( $feature, $post_id = 0, $sub = '' ) {
64 if ( ! in_array( $feature, self::FEATURES, true ) ) {
65 return;
66 }
67
68 // Site-wide aggregate.
69 $usage = get_option( self::OPTION_KEY, [] );
70 if ( ! is_array( $usage ) ) {
71 $usage = [];
72 }
73 $usage[ $feature ] = (int) ( $usage[ $feature ] ?? 0 ) + 1;
74
75 if ( $sub !== '' ) {
76 $sub = sanitize_key( $sub );
77 if ( $sub !== '' ) {
78 $bucket = $feature . '_actions';
79 $usage[ $bucket ][ $sub ] = (int) ( $usage[ $bucket ][ $sub ] ?? 0 ) + 1;
80 }
81 }
82
83 update_option( self::OPTION_KEY, $usage, true );
84
85 // Per-document breakdown.
86 if ( $post_id > 0 ) {
87 $meta = get_post_meta( $post_id, self::META_KEY, true );
88 if ( ! is_array( $meta ) ) {
89 $meta = [];
90 }
91 $meta[ $feature ] = (int) ( $meta[ $feature ] ?? 0 ) + 1;
92 update_post_meta( $post_id, self::META_KEY, $meta );
93 }
94 }
95
96 /**
97 * Normalised, fixed-schema snapshot for the wpinsight collector. Every feature key
98 * is always present (default 0); the AI Edit action breakdown is included when set.
99 *
100 * @return array<string,int|array<string,int>>
101 */
102 public static function snapshot() {
103 $usage = get_option( self::OPTION_KEY, [] );
104 $usage = is_array( $usage ) ? $usage : [];
105
106 $out = [];
107 foreach ( self::FEATURES as $key ) {
108 $out[ $key ] = (int) ( $usage[ $key ] ?? 0 );
109 }
110
111 if ( ! empty( $usage['ai_edit_actions'] ) && is_array( $usage['ai_edit_actions'] ) ) {
112 $out['ai_edit_actions'] = array_map( 'intval', $usage['ai_edit_actions'] );
113 }
114
115 return $out;
116 }
117 }
118