Edit File by line
/home/zeestwma/ceyloniy.../wp-conte.../plugins/wpforms-.../src/Integrat.../Abilitie...
File: Abilities.php
<?php
[0] Fix | Delete
[1] Fix | Delete
namespace WPForms\Integrations\Abilities;
[2] Fix | Delete
[3] Fix | Delete
use WP_Error;
[4] Fix | Delete
use WP_Post;
[5] Fix | Delete
use WPForms\Integrations\IntegrationInterface;
[6] Fix | Delete
[7] Fix | Delete
/**
[8] Fix | Delete
* WordPress Abilities API Integration for WPForms.
[9] Fix | Delete
*
[10] Fix | Delete
* Provides a standardized interface for AI assistants and automation tools
[11] Fix | Delete
* to discover and interact with WPForms functionality.
[12] Fix | Delete
*
[13] Fix | Delete
* @since 1.9.9
[14] Fix | Delete
*/
[15] Fix | Delete
abstract class Abilities implements IntegrationInterface {
[16] Fix | Delete
[17] Fix | Delete
/**
[18] Fix | Delete
* Ability namespace for WPForms abilities.
[19] Fix | Delete
*
[20] Fix | Delete
* @since 1.9.9
[21] Fix | Delete
*
[22] Fix | Delete
* @var string
[23] Fix | Delete
*/
[24] Fix | Delete
protected const ABILITY_NAMESPACE = 'wpforms';
[25] Fix | Delete
[26] Fix | Delete
/**
[27] Fix | Delete
* Category slug for WPForms abilities.
[28] Fix | Delete
*
[29] Fix | Delete
* @since 1.9.9
[30] Fix | Delete
*
[31] Fix | Delete
* @var string
[32] Fix | Delete
*/
[33] Fix | Delete
protected const CATEGORY_SLUG = 'wpforms-forms';
[34] Fix | Delete
[35] Fix | Delete
/**
[36] Fix | Delete
* Indicate if the current integration is allowed to load.
[37] Fix | Delete
*
[38] Fix | Delete
* @since 1.9.9
[39] Fix | Delete
*
[40] Fix | Delete
* @return bool
[41] Fix | Delete
*/
[42] Fix | Delete
public function allow_load(): bool {
[43] Fix | Delete
[44] Fix | Delete
// Only load if the Abilities API is available (WordPress 6.9+).
[45] Fix | Delete
return function_exists( 'wp_register_ability' );
[46] Fix | Delete
}
[47] Fix | Delete
[48] Fix | Delete
/**
[49] Fix | Delete
* Load the integration.
[50] Fix | Delete
*
[51] Fix | Delete
* @since 1.9.9
[52] Fix | Delete
*/
[53] Fix | Delete
public function load(): void {
[54] Fix | Delete
[55] Fix | Delete
$this->hooks();
[56] Fix | Delete
}
[57] Fix | Delete
[58] Fix | Delete
/**
[59] Fix | Delete
* Register hooks.
[60] Fix | Delete
*
[61] Fix | Delete
* @since 1.9.9
[62] Fix | Delete
*/
[63] Fix | Delete
protected function hooks(): void {
[64] Fix | Delete
[65] Fix | Delete
add_action( 'wp_abilities_api_categories_init', [ $this, 'register_category' ] );
[66] Fix | Delete
add_action( 'wp_abilities_api_init', [ $this, 'register_abilities' ] );
[67] Fix | Delete
}
[68] Fix | Delete
[69] Fix | Delete
/**
[70] Fix | Delete
* Register the WPForms ability category.
[71] Fix | Delete
*
[72] Fix | Delete
* @since 1.9.9
[73] Fix | Delete
*/
[74] Fix | Delete
public function register_category(): void {
[75] Fix | Delete
[76] Fix | Delete
wp_register_ability_category(
[77] Fix | Delete
self::CATEGORY_SLUG,
[78] Fix | Delete
[
[79] Fix | Delete
'label' => __( 'WPForms', 'wpforms-lite' ),
[80] Fix | Delete
'description' => __( 'Abilities for interacting with WPForms forms and entries.', 'wpforms-lite' ),
[81] Fix | Delete
]
[82] Fix | Delete
);
[83] Fix | Delete
}
[84] Fix | Delete
[85] Fix | Delete
/**
[86] Fix | Delete
* Register WPForms abilities.
[87] Fix | Delete
*
[88] Fix | Delete
* @since 1.9.9
[89] Fix | Delete
*/
[90] Fix | Delete
abstract public function register_abilities();
[91] Fix | Delete
[92] Fix | Delete
/**
[93] Fix | Delete
* Register common abilities shared between Lite and Pro.
[94] Fix | Delete
*
[95] Fix | Delete
* @since 1.9.9
[96] Fix | Delete
*/
[97] Fix | Delete
protected function register_common_abilities(): void {
[98] Fix | Delete
[99] Fix | Delete
$this->register_list_forms_ability();
[100] Fix | Delete
$this->register_get_form_ability();
[101] Fix | Delete
}
[102] Fix | Delete
[103] Fix | Delete
/**
[104] Fix | Delete
* Register the list_forms ability.
[105] Fix | Delete
*
[106] Fix | Delete
* @since 1.9.9
[107] Fix | Delete
*/
[108] Fix | Delete
protected function register_list_forms_ability(): void {
[109] Fix | Delete
[110] Fix | Delete
wp_register_ability(
[111] Fix | Delete
self::ABILITY_NAMESPACE . '/list-forms',
[112] Fix | Delete
[
[113] Fix | Delete
'label' => __( 'List Forms', 'wpforms-lite' ),
[114] Fix | Delete
'description' => __( 'List all available WPForms forms with their metadata.', 'wpforms-lite' ),
[115] Fix | Delete
'category' => self::CATEGORY_SLUG,
[116] Fix | Delete
'execute_callback' => [ $this, 'ability_list_forms' ],
[117] Fix | Delete
'permission_callback' => [ $this, 'check_view_forms_permission' ],
[118] Fix | Delete
'input_schema' => [
[119] Fix | Delete
'type' => 'object',
[120] Fix | Delete
'properties' => [
[121] Fix | Delete
'status' => [
[122] Fix | Delete
'description' => __( 'Filter forms by status.', 'wpforms-lite' ),
[123] Fix | Delete
'type' => 'string',
[124] Fix | Delete
'enum' => [ 'publish', 'draft', 'trash' ],
[125] Fix | Delete
'default' => 'publish',
[126] Fix | Delete
],
[127] Fix | Delete
'limit' => [
[128] Fix | Delete
'description' => __( 'Maximum number of forms to return.', 'wpforms-lite' ),
[129] Fix | Delete
'type' => 'integer',
[130] Fix | Delete
'minimum' => 1,
[131] Fix | Delete
'maximum' => 100,
[132] Fix | Delete
'default' => 20,
[133] Fix | Delete
],
[134] Fix | Delete
'offset' => [
[135] Fix | Delete
'description' => __( 'Number of forms to skip.', 'wpforms-lite' ),
[136] Fix | Delete
'type' => 'integer',
[137] Fix | Delete
'minimum' => 0,
[138] Fix | Delete
'default' => 0,
[139] Fix | Delete
],
[140] Fix | Delete
],
[141] Fix | Delete
],
[142] Fix | Delete
'output_schema' => [
[143] Fix | Delete
'type' => 'object',
[144] Fix | Delete
'properties' => [
[145] Fix | Delete
'forms' => [
[146] Fix | Delete
'type' => 'array',
[147] Fix | Delete
'description' => __( 'Array of form objects.', 'wpforms-lite' ),
[148] Fix | Delete
'items' => [
[149] Fix | Delete
'type' => 'object',
[150] Fix | Delete
'properties' => [
[151] Fix | Delete
'id' => [ 'type' => 'integer' ],
[152] Fix | Delete
'title' => [ 'type' => 'string' ],
[153] Fix | Delete
'status' => [ 'type' => 'string' ],
[154] Fix | Delete
'created' => [ 'type' => 'string' ],
[155] Fix | Delete
'modified' => [ 'type' => 'string' ],
[156] Fix | Delete
],
[157] Fix | Delete
],
[158] Fix | Delete
],
[159] Fix | Delete
'total' => [
[160] Fix | Delete
'type' => 'integer',
[161] Fix | Delete
'description' => __( 'Total number of forms returned.', 'wpforms-lite' ),
[162] Fix | Delete
],
[163] Fix | Delete
],
[164] Fix | Delete
],
[165] Fix | Delete
'meta' => [
[166] Fix | Delete
'annotations' => [
[167] Fix | Delete
'readonly' => true,
[168] Fix | Delete
'destructive' => false,
[169] Fix | Delete
'idempotent' => true,
[170] Fix | Delete
],
[171] Fix | Delete
'show_in_rest' => true,
[172] Fix | Delete
'mcp' => [
[173] Fix | Delete
'public' => true,
[174] Fix | Delete
],
[175] Fix | Delete
],
[176] Fix | Delete
]
[177] Fix | Delete
);
[178] Fix | Delete
}
[179] Fix | Delete
[180] Fix | Delete
/**
[181] Fix | Delete
* Register the get_form ability.
[182] Fix | Delete
*
[183] Fix | Delete
* @since 1.9.9
[184] Fix | Delete
*/
[185] Fix | Delete
protected function register_get_form_ability(): void {
[186] Fix | Delete
[187] Fix | Delete
wp_register_ability(
[188] Fix | Delete
self::ABILITY_NAMESPACE . '/get-form',
[189] Fix | Delete
[
[190] Fix | Delete
'label' => __( 'Get Form', 'wpforms-lite' ),
[191] Fix | Delete
'description' => __( 'Get detailed information about a specific WPForms form including its fields.', 'wpforms-lite' ),
[192] Fix | Delete
'category' => self::CATEGORY_SLUG,
[193] Fix | Delete
'execute_callback' => [ $this, 'ability_get_form' ],
[194] Fix | Delete
'permission_callback' => [ $this, 'check_view_single_form_permission' ],
[195] Fix | Delete
'input_schema' => [
[196] Fix | Delete
'type' => 'object',
[197] Fix | Delete
'properties' => [
[198] Fix | Delete
'form_id' => [
[199] Fix | Delete
'description' => __( 'The ID of the form to retrieve.', 'wpforms-lite' ),
[200] Fix | Delete
'type' => 'integer',
[201] Fix | Delete
'minimum' => 1,
[202] Fix | Delete
],
[203] Fix | Delete
'include_fields' => [
[204] Fix | Delete
'description' => __( 'Whether to include field configuration.', 'wpforms-lite' ),
[205] Fix | Delete
'type' => 'boolean',
[206] Fix | Delete
'default' => true,
[207] Fix | Delete
],
[208] Fix | Delete
],
[209] Fix | Delete
'required' => [ 'form_id' ],
[210] Fix | Delete
],
[211] Fix | Delete
'output_schema' => [
[212] Fix | Delete
'type' => 'object',
[213] Fix | Delete
'properties' => [
[214] Fix | Delete
'id' => [ 'type' => 'integer' ],
[215] Fix | Delete
'title' => [ 'type' => 'string' ],
[216] Fix | Delete
'status' => [ 'type' => 'string' ],
[217] Fix | Delete
'settings' => [ 'type' => 'object' ],
[218] Fix | Delete
'fields' => [ 'type' => 'array' ],
[219] Fix | Delete
],
[220] Fix | Delete
],
[221] Fix | Delete
'meta' => [
[222] Fix | Delete
'annotations' => [
[223] Fix | Delete
'readonly' => true,
[224] Fix | Delete
'destructive' => false,
[225] Fix | Delete
'idempotent' => true,
[226] Fix | Delete
],
[227] Fix | Delete
'show_in_rest' => true,
[228] Fix | Delete
'mcp' => [
[229] Fix | Delete
'public' => true,
[230] Fix | Delete
],
[231] Fix | Delete
],
[232] Fix | Delete
]
[233] Fix | Delete
);
[234] Fix | Delete
}
[235] Fix | Delete
[236] Fix | Delete
/**
[237] Fix | Delete
* Permission callback: Check if the user can view forms.
[238] Fix | Delete
*
[239] Fix | Delete
* @since 1.9.9
[240] Fix | Delete
*
[241] Fix | Delete
* @return bool|WP_Error
[242] Fix | Delete
*/
[243] Fix | Delete
public function check_view_forms_permission() {
[244] Fix | Delete
[245] Fix | Delete
if ( ! wpforms_current_user_can( 'view_forms' ) ) {
[246] Fix | Delete
return new WP_Error(
[247] Fix | Delete
'wpforms_forbidden',
[248] Fix | Delete
__( 'You do not have permission to view forms.', 'wpforms-lite' ),
[249] Fix | Delete
[ 'status' => 403 ]
[250] Fix | Delete
);
[251] Fix | Delete
}
[252] Fix | Delete
[253] Fix | Delete
return true;
[254] Fix | Delete
}
[255] Fix | Delete
[256] Fix | Delete
/**
[257] Fix | Delete
* Permission callback: Check if the user can view a specific form.
[258] Fix | Delete
*
[259] Fix | Delete
* @since 1.9.9
[260] Fix | Delete
*
[261] Fix | Delete
* @param mixed $input Input data containing form_id.
[262] Fix | Delete
*
[263] Fix | Delete
* @return bool|WP_Error
[264] Fix | Delete
*/
[265] Fix | Delete
public function check_view_single_form_permission( $input = null ) {
[266] Fix | Delete
[267] Fix | Delete
$input = $this->normalize_input( $input );
[268] Fix | Delete
$form_id = absint( $input['form_id'] ?? 0 );
[269] Fix | Delete
[270] Fix | Delete
if ( ! $form_id || ! wpforms_current_user_can( 'view_form_single', $form_id ) ) {
[271] Fix | Delete
return new WP_Error(
[272] Fix | Delete
'wpforms_forbidden',
[273] Fix | Delete
__( 'You do not have permission to view this form.', 'wpforms-lite' ),
[274] Fix | Delete
[ 'status' => 403 ]
[275] Fix | Delete
);
[276] Fix | Delete
}
[277] Fix | Delete
[278] Fix | Delete
return true;
[279] Fix | Delete
}
[280] Fix | Delete
[281] Fix | Delete
/**
[282] Fix | Delete
* Ability callback: List forms.
[283] Fix | Delete
*
[284] Fix | Delete
* @since 1.9.9
[285] Fix | Delete
*
[286] Fix | Delete
* @param mixed $input Input data.
[287] Fix | Delete
*
[288] Fix | Delete
* @return array
[289] Fix | Delete
*/
[290] Fix | Delete
public function ability_list_forms( $input = null ): array {
[291] Fix | Delete
[292] Fix | Delete
$args = $this->normalize_input( $input );
[293] Fix | Delete
[294] Fix | Delete
$form_handler = $this->get_form_handler();
[295] Fix | Delete
[296] Fix | Delete
if ( is_wp_error( $form_handler ) ) {
[297] Fix | Delete
return [
[298] Fix | Delete
'forms' => [],
[299] Fix | Delete
'total' => 0,
[300] Fix | Delete
];
[301] Fix | Delete
}
[302] Fix | Delete
[303] Fix | Delete
$limit = absint( $args['limit'] ?? 20 );
[304] Fix | Delete
$offset = absint( $args['offset'] ?? 0 );
[305] Fix | Delete
$status = sanitize_text_field( $args['status'] ?? 'publish' );
[306] Fix | Delete
[307] Fix | Delete
// Get total count efficiently using the cached WordPress function.
[308] Fix | Delete
$counts = wp_count_posts( 'wpforms' );
[309] Fix | Delete
$total = $counts->{$status} ?? 0;
[310] Fix | Delete
[311] Fix | Delete
// Get paginated forms with proper WordPress pagination.
[312] Fix | Delete
$query_args = [
[313] Fix | Delete
'post_status' => $status,
[314] Fix | Delete
'posts_per_page' => $limit,
[315] Fix | Delete
'offset' => $offset,
[316] Fix | Delete
'nopaging' => false, // Override default to enable pagination.
[317] Fix | Delete
'order' => 'DESC',
[318] Fix | Delete
'orderby' => 'date',
[319] Fix | Delete
];
[320] Fix | Delete
[321] Fix | Delete
$forms = $form_handler->get( '', $query_args );
[322] Fix | Delete
[323] Fix | Delete
if ( empty( $forms ) ) {
[324] Fix | Delete
return [
[325] Fix | Delete
'forms' => [],
[326] Fix | Delete
'total' => $total,
[327] Fix | Delete
];
[328] Fix | Delete
}
[329] Fix | Delete
[330] Fix | Delete
$result = [];
[331] Fix | Delete
[332] Fix | Delete
foreach ( $forms as $form ) {
[333] Fix | Delete
$result[] = $this->format_form_summary( $form );
[334] Fix | Delete
}
[335] Fix | Delete
[336] Fix | Delete
return [
[337] Fix | Delete
'forms' => $result,
[338] Fix | Delete
'total' => $total,
[339] Fix | Delete
];
[340] Fix | Delete
}
[341] Fix | Delete
[342] Fix | Delete
/**
[343] Fix | Delete
* Ability callback: Get single form.
[344] Fix | Delete
*
[345] Fix | Delete
* @since 1.9.9
[346] Fix | Delete
*
[347] Fix | Delete
* @param mixed $input Input data.
[348] Fix | Delete
*
[349] Fix | Delete
* @return array|WP_Error
[350] Fix | Delete
*/
[351] Fix | Delete
public function ability_get_form( $input = null ) {
[352] Fix | Delete
[353] Fix | Delete
$args = $this->normalize_input( $input );
[354] Fix | Delete
$form_id = absint( $args['form_id'] ?? 0 );
[355] Fix | Delete
[356] Fix | Delete
if ( empty( $form_id ) ) {
[357] Fix | Delete
return new WP_Error(
[358] Fix | Delete
'wpforms_invalid_form_id',
[359] Fix | Delete
__( 'Invalid form ID.', 'wpforms-lite' ),
[360] Fix | Delete
[ 'status' => 400 ]
[361] Fix | Delete
);
[362] Fix | Delete
}
[363] Fix | Delete
[364] Fix | Delete
$form_handler = $this->get_form_handler();
[365] Fix | Delete
[366] Fix | Delete
if ( is_wp_error( $form_handler ) ) {
[367] Fix | Delete
return $form_handler;
[368] Fix | Delete
}
[369] Fix | Delete
[370] Fix | Delete
$form = $form_handler->get( $form_id );
[371] Fix | Delete
[372] Fix | Delete
if ( empty( $form ) ) {
[373] Fix | Delete
return new WP_Error(
[374] Fix | Delete
'wpforms_form_not_found',
[375] Fix | Delete
__( 'Form not found.', 'wpforms-lite' ),
[376] Fix | Delete
[ 'status' => 404 ]
[377] Fix | Delete
);
[378] Fix | Delete
}
[379] Fix | Delete
[380] Fix | Delete
$include_fields = wp_validate_boolean( $args['include_fields'] ?? true );
[381] Fix | Delete
[382] Fix | Delete
return $this->format_form_detail( $form, $include_fields );
[383] Fix | Delete
}
[384] Fix | Delete
[385] Fix | Delete
/**
[386] Fix | Delete
* Normalize input data to array format.
[387] Fix | Delete
*
[388] Fix | Delete
* @since 1.9.9
[389] Fix | Delete
*
[390] Fix | Delete
* @param mixed $input Input data (can be the array, object, or null).
[391] Fix | Delete
*
[392] Fix | Delete
* @return array
[393] Fix | Delete
*/
[394] Fix | Delete
protected function normalize_input( $input ): array {
[395] Fix | Delete
[396] Fix | Delete
if ( is_array( $input ) ) {
[397] Fix | Delete
return $input;
[398] Fix | Delete
}
[399] Fix | Delete
[400] Fix | Delete
if ( is_object( $input ) ) {
[401] Fix | Delete
return (array) $input;
[402] Fix | Delete
}
[403] Fix | Delete
[404] Fix | Delete
return [];
[405] Fix | Delete
}
[406] Fix | Delete
[407] Fix | Delete
/**
[408] Fix | Delete
* Get the form handler and validate it.
[409] Fix | Delete
*
[410] Fix | Delete
* @since 1.9.9
[411] Fix | Delete
*
[412] Fix | Delete
* @return object|WP_Error Form handler object or WP_Error on failure.
[413] Fix | Delete
*/
[414] Fix | Delete
protected function get_form_handler() {
[415] Fix | Delete
[416] Fix | Delete
$form_handler = wpforms()->obj( 'form' );
[417] Fix | Delete
[418] Fix | Delete
if ( ! $form_handler ) {
[419] Fix | Delete
return new WP_Error(
[420] Fix | Delete
'wpforms_form_handler_error',
[421] Fix | Delete
__( 'Form handler not available.', 'wpforms-lite' ),
[422] Fix | Delete
[ 'status' => 500 ]
[423] Fix | Delete
);
[424] Fix | Delete
}
[425] Fix | Delete
[426] Fix | Delete
return $form_handler;
[427] Fix | Delete
}
[428] Fix | Delete
[429] Fix | Delete
/**
[430] Fix | Delete
* Format form data for summary listing.
[431] Fix | Delete
*
[432] Fix | Delete
* @since 1.9.9
[433] Fix | Delete
*
[434] Fix | Delete
* @param WP_Post $form Form the `post` object.
[435] Fix | Delete
*
[436] Fix | Delete
* @return array
[437] Fix | Delete
*/
[438] Fix | Delete
protected function format_form_summary( WP_Post $form ): array {
[439] Fix | Delete
[440] Fix | Delete
return [
[441] Fix | Delete
'id' => $form->ID,
[442] Fix | Delete
'title' => $form->post_title,
[443] Fix | Delete
'status' => $form->post_status,
[444] Fix | Delete
'created' => $form->post_date,
[445] Fix | Delete
'modified' => $form->post_modified,
[446] Fix | Delete
'author' => absint( $form->post_author ),
[447] Fix | Delete
];
[448] Fix | Delete
}
[449] Fix | Delete
[450] Fix | Delete
/**
[451] Fix | Delete
* Format form data for the detailed view.
[452] Fix | Delete
*
[453] Fix | Delete
* @since 1.9.9
[454] Fix | Delete
*
[455] Fix | Delete
* @param WP_Post $form Form `post` object.
[456] Fix | Delete
* @param bool $include_fields Whether to include fields.
[457] Fix | Delete
*
[458] Fix | Delete
* @return array
[459] Fix | Delete
*/
[460] Fix | Delete
protected function format_form_detail( WP_Post $form, bool $include_fields = true ): array {
[461] Fix | Delete
[462] Fix | Delete
$form_handler = $this->get_form_handler();
[463] Fix | Delete
$form_data = ! is_wp_error( $form_handler ) ? $form_handler->get( $form->ID, [ 'content_only' => true ] ) : [];
[464] Fix | Delete
[465] Fix | Delete
// Ensure form_data is an array.
[466] Fix | Delete
if ( ! is_array( $form_data ) ) {
[467] Fix | Delete
$form_data = [];
[468] Fix | Delete
}
[469] Fix | Delete
[470] Fix | Delete
$result = [
[471] Fix | Delete
'id' => $form->ID,
[472] Fix | Delete
'title' => $form->post_title,
[473] Fix | Delete
'status' => $form->post_status,
[474] Fix | Delete
'created' => $form->post_date,
[475] Fix | Delete
'modified' => $form->post_modified,
[476] Fix | Delete
'author' => absint( $form->post_author ),
[477] Fix | Delete
'settings' => $this->get_safe_settings( $form_data ),
[478] Fix | Delete
];
[479] Fix | Delete
[480] Fix | Delete
if ( $include_fields && ! empty( $form_data['fields'] ) ) {
[481] Fix | Delete
$result['fields'] = $this->format_fields( $form_data['fields'] );
[482] Fix | Delete
}
[483] Fix | Delete
[484] Fix | Delete
return $result;
[485] Fix | Delete
}
[486] Fix | Delete
[487] Fix | Delete
/**
[488] Fix | Delete
* Get safe settings (without sensitive data).
[489] Fix | Delete
*
[490] Fix | Delete
* @since 1.9.9
[491] Fix | Delete
*
[492] Fix | Delete
* @param array $form_data Form data.
[493] Fix | Delete
*
[494] Fix | Delete
* @return array
[495] Fix | Delete
*/
[496] Fix | Delete
protected function get_safe_settings( array $form_data ): array {
[497] Fix | Delete
[498] Fix | Delete
$settings = $form_data['settings'] ?? [];
[499] Fix | Delete
12
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function