PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.3.0
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.3.0
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.2 2.2.1 2.2.0 2.1.2 2.1.1 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 All 66 releases
better-payment / includes / AI / Operations / OperationRegistry.php

OperationRegistry.php in Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More 2.3.0, at includes/AI/Operations/OperationRegistry.php

174 lines 7.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Better_Payment\Lite\AI\Operations;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit;
7 }
8
9 /**
10 * Catalog of Builder Operations — the stable contract between the AI layer and
11 * the Campaign Builder.
12 *
13 * The AI never edits HTML, DOM, or React state. It emits a list of typed
14 * Operations; each one is validated server-side ({@see OperationValidator}) and
15 * then applied client-side by mapping onto an existing reducer action. Because
16 * operations map 1:1 onto reducer actions, every future AI feature (block-level
17 * buttons, bulk edits, templates) reuses this same layer.
18 *
19 * Each entry declares a JSON-schema-ish `params` shape so it can be exported as
20 * provider tool/function definitions AND validated on return.
21 *
22 * Extend from another plugin:
23 * add_filter( 'better_payment/ai/operations', function ( $ops ) {
24 * $ops['my_op'] = [ 'summary' => '...', 'params' => [ ... ] ];
25 * return $ops;
26 * } );
27 *
28 * @see OperationValidator Enforces these shapes.
29 * @see \Better_Payment\Lite\AI\Schema\CampaignSchema Element/meta allowlists.
30 */
31 class OperationRegistry {
32
33 /**
34 * Built-in operation definitions.
35 *
36 * @return array<string, array>
37 */
38 private static function definitions(): array {
39 return [
40 'set_layout' => [
41 'summary' => 'Replace the entire campaign layout. Use only for initial generation or a full structural rebuild.',
42 'params' => [
43 'layout' => [ 'type' => 'string', 'required' => true, 'summary' => 'One of the layout presets (e.g. 2-column).' ],
44 'columns' => [ 'type' => 'array', 'required' => true, 'summary' => 'Ordered columns, each with id, label, width and elements.' ],
45 ],
46 ],
47 'insert_block' => [
48 'summary' => 'Add a new element to a column.',
49 'params' => [
50 'column_id' => [ 'type' => 'string', 'required' => false, 'summary' => 'Target column id. Defaults to the first column.' ],
51 'type' => [ 'type' => 'string', 'required' => true, 'summary' => 'A registered element type.' ],
52 'settings' => [ 'type' => 'object', 'required' => false, 'summary' => 'Element settings (per-type keys).' ],
53 'index' => [ 'type' => 'integer', 'required' => false, 'summary' => 'Insert position; appended when omitted.' ],
54 ],
55 ],
56 'update_block' => [
57 'summary' => 'Change settings on an existing element. Only the provided keys are merged.',
58 'params' => [
59 'element_id' => [ 'type' => 'string', 'required' => true, 'summary' => 'Id of the element to update.' ],
60 'settings' => [ 'type' => 'object', 'required' => true, 'summary' => 'Partial settings to merge.' ],
61 ],
62 ],
63 'delete_block' => [
64 'summary' => 'Remove an element from the campaign.',
65 'params' => [
66 'element_id' => [ 'type' => 'string', 'required' => true ],
67 ],
68 ],
69 'move_block' => [
70 'summary' => 'Move an element to another column and/or position.',
71 'params' => [
72 'element_id' => [ 'type' => 'string', 'required' => true ],
73 'to_column_id' => [ 'type' => 'string', 'required' => true ],
74 'index' => [ 'type' => 'integer', 'required' => false ],
75 ],
76 ],
77 'update_meta' => [
78 'summary' => 'Set a single campaign-level meta value (e.g. bpc_goal_amount).',
79 'params' => [
80 'key' => [ 'type' => 'string', 'required' => true, 'summary' => 'An allowlisted campaign meta key.' ],
81 'value' => [ 'type' => 'mixed', 'required' => true ],
82 ],
83 ],
84 'set_colors' => [
85 'summary' => 'Set the campaign primary and/or background colour (hex).',
86 'params' => [
87 'primary' => [ 'type' => 'string', 'required' => false, 'summary' => 'Hex colour, e.g. #6b63f6.' ],
88 'background' => [ 'type' => 'string', 'required' => false, 'summary' => 'Hex colour.' ],
89 ],
90 ],
91 'set_donation_amounts' => [
92 'summary' => 'Replace the suggested donation amounts.',
93 'params' => [
94 'amounts' => [ 'type' => 'array', 'required' => true, 'summary' => 'List of { amount, description?, is_default? }.' ],
95 ],
96 ],
97 'replace_image' => [
98 'summary' => 'Point a photo element at a media-library image.',
99 'params' => [
100 'element_id' => [ 'type' => 'string', 'required' => true ],
101 'src' => [ 'type' => 'string', 'required' => true, 'summary' => 'Image URL.' ],
102 'src_id' => [ 'type' => 'integer', 'required' => false, 'summary' => 'Attachment id.' ],
103 'src_sizes' => [ 'type' => 'object', 'required' => false ],
104 'alt' => [ 'type' => 'string', 'required' => false ],
105 ],
106 ],
107 'generate_image' => [
108 'summary' => 'Generate a new image from a description and place it in the campaign. Target an existing photo element by element_id to replace it, or omit it to insert a new photo (optionally into column_id).',
109 'params' => [
110 'prompt' => [ 'type' => 'string', 'required' => true, 'summary' => 'A vivid description of the image to generate.' ],
111 'element_id' => [ 'type' => 'string', 'required' => false, 'summary' => 'Existing photo element to replace.' ],
112 'column_id' => [ 'type' => 'string', 'required' => false, 'summary' => 'Column to insert a new photo into.' ],
113 ],
114 ],
115 ];
116 }
117
118 /**
119 * All operation definitions after the extension filter.
120 *
121 * @return array<string, array>
122 */
123 public static function get_all(): array {
124 /**
125 * Filter the registered AI builder operations.
126 *
127 * @param array<string, array> $operations
128 */
129 return apply_filters( 'better_payment/ai/operations', self::definitions() );
130 }
131
132 /**
133 * A single operation definition, or null.
134 *
135 * @return array|null
136 */
137 public static function get( string $name ) {
138 $all = self::get_all();
139 return $all[ $name ] ?? null;
140 }
141
142 public static function exists( string $name ): bool {
143 return null !== self::get( $name );
144 }
145
146 /**
147 * Operation names.
148 *
149 * @return array<int, string>
150 */
151 public static function names(): array {
152 return array_keys( self::get_all() );
153 }
154
155 /**
156 * Provider-agnostic tool descriptors, one per operation.
157 *
158 * Providers translate these into their own tool/function-calling format.
159 *
160 * @return array<int, array{name: string, description: string, params: array}>
161 */
162 public static function as_tools(): array {
163 $tools = [];
164 foreach ( self::get_all() as $name => $def ) {
165 $tools[] = [
166 'name' => $name,
167 'description' => $def['summary'] ?? '',
168 'params' => $def['params'] ?? [],
169 ];
170 }
171 return $tools;
172 }
173 }
174