PluginProbe ʕ •ᴥ•ʔ
Advanced Custom Fields (ACF®) / 6.8.8
Advanced Custom Fields (ACF®) v6.8.8
6.8.9 6.8.8 6.8.7 6.8.6 6.8.5 6.8.4 6.8.3 6.8.2 6.8.1 5.8.5 5.8.6 5.8.7 5.8.8 5.8.9 5.9.0 5.9.1 5.9.2 5.9.3 5.9.4 5.9.5 5.9.6 5.9.7 5.9.8 5.9.9 6.0.0 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.0.6 6.0.7 6.1.0 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.1.6 6.1.7 6.1.8 6.2.0 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.2.6 6.2.6.1 6.2.7 6.2.8 6.2.9 6.3.0 6.3.1 6.3.10.2 6.3.11 6.3.12 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.6.1 6.4.0 6.4.0.1 6.4.1 6.4.2 6.4.3 6.5.0 6.5.1 6.6.0 6.6.1 6.6.2 6.7.0 6.7.1 6.7.2 6.8.0 trunk 1.0.0 1.0.2 1.0.3 1.0.5 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.1.1 2.1.3 2.1.4 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.6 3.0.7 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.5.6 3.5.7 3.5.8 4.0.0 4.0.1 4.0.2 4.0.3 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.8 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.3.8 4.3.9 4.4.0 4.4.1 4.4.10 4.4.11 4.4.12 4.4.2 4.4.3 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 5.10 5.10.1 5.10.2 5.11 5.11.1 5.11.2 5.11.3 5.11.4 5.12 5.12.1 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.6.10 5.6.2 5.6.3 5.6.4 5.6.5 5.6.6 5.6.7 5.6.8 5.6.9 5.7.0 5.7.1 5.7.10 5.7.12 5.7.13 5.7.2 5.7.3 5.7.4 5.7.5 5.7.6 5.7.7 5.7.8 5.7.9 5.8.0 5.8.1 5.8.10 5.8.11 5.8.12 5.8.13 5.8.14 5.8.2 5.8.3 5.8.4
advanced-custom-fields / src / Site_Health / AI_Usage.php
advanced-custom-fields / src / Site_Health Last commit date
AI_Usage.php 5 months ago Site_Health.php 2 weeks ago
AI_Usage.php
218 lines
1 <?php
2 /**
3 * @package ACF
4 * @author WP Engine
5 *
6 * © 2026 Advanced Custom Fields (ACF®). All rights reserved.
7 * "ACF" is a trademark of WP Engine.
8 * Licensed under the GNU General Public License v2 or later.
9 * https://www.gnu.org/licenses/gpl-2.0.html
10 */
11
12 namespace ACF\Site_Health;
13
14 use WP_Error;
15 use WP_REST_Request;
16
17 // Exit if accessed directly.
18 defined( 'ABSPATH' ) || exit;
19
20 /**
21 * AI Usage
22 *
23 * Logs information about ACF AI/Abilities usage for the ACF Site Health report.
24 * Measures opt-in, potential (AI-ready objects), discovery (browsing), and utility (execution).
25 */
26 class AI_Usage {
27
28 /**
29 * An instance of the ACF Site_Health class.
30 *
31 * @var Site_Health
32 */
33 private Site_Health $site_health;
34
35 /**
36 * Constructs the class.
37 *
38 * @since 6.8.0
39 *
40 * @param Site_Health $site_health An instance of Site_Health.
41 * @return void
42 */
43 public function __construct( Site_Health $site_health ) {
44 $this->site_health = $site_health;
45
46 add_action( 'init', array( $this, 'init' ) );
47 }
48
49 /**
50 * Initializes the class on init if the ACF Abilities API is available.
51 *
52 * @since 6.8.0
53 *
54 * @return void
55 */
56 public function init() {
57 // Only hook if AI is enabled and Abilities API exists.
58 if ( ! $this->is_acf_abilities_api_available() ) {
59 return;
60 }
61
62 // Execution logging - hook after ability execution.
63 add_action( 'wp_after_execute_ability', array( $this, 'log_execution' ), 10, 3 );
64 }
65
66 /**
67 * Checks if ACF AI and the Abilities API are enabled.
68 *
69 * @since 6.8.0
70 *
71 * @return boolean
72 */
73 private function is_acf_abilities_api_available(): bool {
74 return acf_get_setting( 'enable_acf_ai' ) && function_exists( 'wp_register_ability' );
75 }
76
77 /**
78 * Log execution events (when agents execute ACF abilities).
79 *
80 * Hooks into wp_after_execute_ability to log successful ability executions.
81 *
82 * @since 6.8.0
83 *
84 * @param string $ability_name The namespaced ability name.
85 * @param mixed $input The input data passed to the ability.
86 * @param mixed $result The result returned by the ability.
87 * @return void
88 */
89 public function log_execution( string $ability_name, $input, $result ) {
90 // Only log ACF abilities.
91 if ( strpos( $ability_name, 'acf/' ) !== 0 ) {
92 return;
93 }
94
95 $is_error = $result instanceof WP_Error;
96
97 $this->increment_execution_count( $ability_name, $is_error );
98 }
99
100 /**
101 * Increment execution counts.
102 *
103 * @since 6.8.0
104 *
105 * @param string $ability_name The ability that was executed.
106 * @param boolean $is_error Whether the execution resulted in an error.
107 * @return boolean Success status.
108 */
109 private function increment_execution_count( string $ability_name, bool $is_error ): bool {
110 $data = $this->site_health->get_site_health();
111
112 if ( ! isset( $data['ai_usage'] ) ) {
113 $data['ai_usage'] = $this->get_default_usage_structure();
114 }
115
116 // Increment total executions.
117 ++$data['ai_usage']['total_executions'];
118 $data['ai_usage']['last_execution_at'] = time();
119
120 // Increment per-ability count.
121 if ( ! isset( $data['ai_usage']['executions_by_ability'][ $ability_name ] ) ) {
122 $data['ai_usage']['executions_by_ability'][ $ability_name ] = 0;
123 }
124 ++$data['ai_usage']['executions_by_ability'][ $ability_name ];
125
126 if ( $is_error ) {
127 ++$data['ai_usage']['error_count'];
128 }
129
130 return $this->site_health->update_site_health( $data );
131 }
132
133 /**
134 * Get the default log data structure.
135 *
136 * @since 6.8.0
137 *
138 * @return array
139 */
140 private function get_default_usage_structure(): array {
141 return array(
142 'total_executions' => 0,
143 'error_count' => 0,
144 'last_execution_at' => null,
145 'executions_by_ability' => array(),
146 );
147 }
148
149 /**
150 * Get AI-ready object counts for Site Health display.
151 *
152 * @since 6.8.0
153 *
154 * @param array $field_groups An array of ACF field groups.
155 * @param array $post_types An array of ACF post types.
156 * @param array $taxonomies An array of ACF taxonomies.
157 * @return array Counts of AI-ready objects by type.
158 */
159 public function get_ai_ready_counts( $field_groups, $post_types, $taxonomies ): array {
160 $counts = array(
161 'field_groups' => 0,
162 'post_types' => 0,
163 'taxonomies' => 0,
164 );
165
166 // Count AI-ready field groups.
167 foreach ( $field_groups as $field_group ) {
168 if ( ! empty( $field_group['allow_ai_access'] ) && ! empty( $field_group['active'] ) ) {
169 ++$counts['field_groups'];
170 }
171 }
172
173 // Count AI-ready post types.
174 foreach ( $post_types as $post_type ) {
175 if ( ! empty( $post_type['allow_ai_access'] ) && ! empty( $post_type['active'] ) ) {
176 ++$counts['post_types'];
177 }
178 }
179
180 // Count AI-ready taxonomies.
181 foreach ( $taxonomies as $taxonomy ) {
182 if ( ! empty( $taxonomy['allow_ai_access'] ) && ! empty( $taxonomy['active'] ) ) {
183 ++$counts['taxonomies'];
184 }
185 }
186
187 return $counts;
188 }
189
190 /**
191 * Get the usage metrics for Site Health display.
192 *
193 * @since 6.8.0
194 *
195 * @return array The usage metrics.
196 */
197 public function get_usage_metrics(): array {
198 $site_health = $this->site_health->get_site_health();
199
200 if ( ! isset( $site_health['ai_usage'] ) ) {
201 return array(
202 'total_discovery_hits' => 0,
203 'total_executions' => 0,
204 'error_count' => 0,
205 );
206 }
207
208 $usage = $site_health['ai_usage'];
209
210 return array(
211 'total_discovery_hits' => $usage['total_discovery_hits'] ?? 0,
212 'total_executions' => $usage['total_executions'] ?? 0,
213 'error_count' => $usage['error_count'] ?? 0,
214 'executions_by_ability' => $usage['executions_by_ability'] ?? array(),
215 );
216 }
217 }
218