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 / AI / Abilities / Abilities.php
advanced-custom-fields / src / AI / Abilities Last commit date
ACF_REST_Ability.php 5 months ago Abilities.php 5 months ago AbstractAbilityGroup.php 5 months ago FieldGroup.php 3 months ago PostType.php 5 months ago Taxonomy.php 3 months ago
Abilities.php
199 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\AI\Abilities;
13
14 use WP_REST_Request;
15
16 // Exit if accessed directly.
17 defined( 'ABSPATH' ) || exit;
18
19 /**
20 * The ACF Abilities API integration.
21 *
22 * Extends the WordPress Abilities API to expose field groups, post types,
23 * taxonomies, and options pages when the "Allow AI Access" setting is enabled.
24 */
25 class Abilities {
26
27 /**
28 * Array of registered ability group instances
29 *
30 * @var array
31 */
32 private array $ability_groups = array();
33
34 /**
35 * Constructs the class.
36 *
37 * @since 6.8.0
38 *
39 * @return void
40 */
41 public function __construct() {
42 $this->init();
43 }
44
45 /**
46 * Initialize the Abilities API integration.
47 *
48 * @since 6.8.0
49 *
50 * @return void
51 */
52 public function init() {
53 // Register ability group classes.
54 $this->register_ability_group( 'field_group', FieldGroup::class );
55 $this->register_ability_group( 'post_type', PostType::class );
56 $this->register_ability_group( 'taxonomy', Taxonomy::class );
57
58 // Register categories (v0.3.0+ requirement).
59 add_action( 'wp_abilities_api_categories_init', array( $this, 'register_categories' ) );
60
61 // Register abilities.
62 add_action( 'wp_abilities_api_init', array( $this, 'register_abilities' ) );
63
64 // Fix for WordPress 6.9 Abilities API bug: parse JSON from query parameters.
65 add_filter( 'rest_request_before_callbacks', array( $this, 'parse_abilities_json_input' ), 10, 3 );
66 }
67
68 /**
69 * Register an ability group class.
70 *
71 * @since 6.8.0
72 *
73 * @param string $key Unique key for this ability group.
74 * @param string $class_name Fully qualified class name.
75 * @param array $args Optional constructor arguments.
76 * @return void
77 */
78 private function register_ability_group( $key, $class_name, $args = array() ) {
79 if ( ! class_exists( $class_name ) ) {
80 return;
81 }
82
83 // Instantiate the class with any provided arguments.
84 if ( ! empty( $args ) ) {
85 $this->ability_groups[ $key ] = new $class_name( ...$args );
86 } else {
87 $this->ability_groups[ $key ] = new $class_name();
88 }
89 }
90
91 /**
92 * Get an ability group instance by key
93 *
94 * @since 6.8.0
95 *
96 * @param string $key The ability group key.
97 * @return object|null The ability group instance or null if not found.
98 */
99 private function get_ability_group( $key ) {
100 return $this->ability_groups[ $key ] ?? null;
101 }
102
103 /**
104 * Register Ability Categories
105 *
106 * @since 6.8.0
107 *
108 * @return void
109 */
110 public function register_categories() {
111 if ( ! function_exists( 'wp_register_ability_category' ) ) {
112 return;
113 }
114
115 // ACF Field Management category.
116 wp_register_ability_category(
117 'acf-field-management',
118 array(
119 'label' => __( 'ACF Field Management', 'acf' ),
120 'description' => __( 'Abilities for managing Advanced Custom Fields field groups and field data.', 'acf' ),
121 )
122 );
123
124 // WordPress Content Discovery category.
125 wp_register_ability_category(
126 'wordpress-content-discovery',
127 array(
128 'label' => __( 'WordPress Content Discovery', 'acf' ),
129 'description' => __( 'Abilities for discovering WordPress content types, taxonomies, and structure.', 'acf' ),
130 )
131 );
132 }
133
134 /**
135 * Register Abilities for ACF
136 *
137 * @since 6.8.0
138 *
139 * @return void
140 */
141 public function register_abilities() {
142 if ( ! function_exists( 'wp_register_ability' ) ) {
143 return;
144 }
145
146 // Register abilities from all registered ability groups.
147 foreach ( $this->ability_groups as $ability_group ) {
148 if ( method_exists( $ability_group, 'register_abilities' ) ) {
149 $ability_group->register_abilities();
150 }
151 }
152 }
153
154 /**
155 * Parse JSON input from query parameters for Abilities API
156 *
157 * WordPress 6.9's Abilities API REST controller doesn't parse JSON strings
158 * from query parameters in GET requests. This filter fixes that by detecting
159 * JSON strings in the 'input' parameter and parsing them into objects/arrays.
160 *
161 * @since 6.8.0
162 *
163 * @param mixed $response Response object.
164 * @param array $handler Route handler info.
165 * @param WP_REST_Request $request Request object.
166 * @return mixed
167 */
168 public function parse_abilities_json_input( $response, $handler, $request ) {
169 // Only process ACF abilities.
170 $route = $request->get_route();
171 if ( strpos( $route, '/wp-abilities/v1/abilities/acf/' ) !== 0 ) {
172 return $response;
173 }
174
175 // Only process GET and DELETE requests (POST uses JSON body which is already parsed).
176 if ( ! in_array( $request->get_method(), array( 'GET', 'DELETE' ), true ) ) {
177 return $response;
178 }
179
180 // Get the input query parameter.
181 $input = $request->get_param( 'input' );
182
183 // If input is a string that looks like JSON, try to parse it.
184 if ( is_string( $input ) && ! empty( $input ) ) {
185 $first_char = substr( trim( $input ), 0, 1 );
186 // Check if it starts with { or [ (JSON object or array).
187 if ( in_array( $first_char, array( '{', '[' ), true ) ) {
188 $parsed = json_decode( $input, true );
189 if ( json_last_error() === JSON_ERROR_NONE ) {
190 // Successfully parsed JSON - update the request parameter.
191 $request->set_param( 'input', $parsed );
192 }
193 }
194 }
195
196 return $response;
197 }
198 }
199