PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.5
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.5
1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk All 48 releases
← All changes | app/Modules/MCP/Support/MCPHelper.php +116 -0 1.5.2 → 1.6.5 View file →
@@ -84,8 +84,85 @@
84 84 return new \WP_Error($code, $json !== false ? $json : $message, $details);
85 85 }
86 86
87 87 // -----------------------------------------------------------------
88 + // Output schema (advertised to clients; not validated server-side)
89 + // -----------------------------------------------------------------
90 +
91 + /**
92 + * JSON Schema fragment for the full money object returned by money(). Inlined
93 + * by each tool's output_schema (rather than a $ref) so it never depends on the
94 + * client validator resolving $defs across JSON-Schema draft versions.
95 + *
96 + * @return array
97 + */
98 + public static function moneyDef()
99 + {
100 + // Field docs live in the object description (once), not per-property: this
101 + // object is inlined many times across an output_schema (10x on the sales
102 + // report alone), so per-field descriptions multiply into real token cost
103 + // for names that are already self-explanatory.
104 + return [
105 + 'type' => 'object',
106 + 'description' => 'Money: amount (decimal), amount_cents (integer, smallest unit), currency (ISO 4217), display (formatted string, e.g. "$19.99").',
107 + 'properties' => [
108 + 'amount' => ['type' => 'number'],
109 + 'amount_cents' => ['type' => 'integer'],
110 + 'currency' => ['type' => 'string'],
111 + 'display' => ['type' => 'string'],
112 + ],
113 + ];
114 + }
115 +
116 + /**
117 + * JSON Schema for the shared meta block. Permissive (extra keys allowed) so a
118 + * tool can add its own meta (mode, date_basis, page, warnings, …) without a
119 + * client that validates structuredContent tripping on the extras.
120 + *
121 + * @param array $extraProps additional documented meta properties for this tool
122 + * @return array
123 + */
124 + public static function metaSchema(array $extraProps = [])
125 + {
126 + return [
127 + 'type' => 'object',
128 + 'description' => 'Envelope metadata: schema version, currency, plus per-tool keys (date_basis, mode, page, warnings).',
129 + 'properties' => array_merge([
130 + 'schema_version' => ['type' => 'string'],
131 + 'generated_at' => ['type' => 'string', 'description' => 'ISO-8601 UTC timestamp.'],
132 + 'currency' => ['type' => 'string', 'description' => 'ISO 4217 store currency for reference.'],
133 + 'warnings' => ['type' => 'array', 'items' => ['type' => 'string'], 'description' => 'Non-fatal notes, e.g. an ignored parameter.'],
134 + ], $extraProps),
135 + ];
136 + }
137 +
138 + /**
139 + * Wrap a `data` schema in the canonical { summary, data, meta } envelope every
140 + * tool returns.
141 + *
142 + * `data` keys are DESCRIBED but not required: the fields[] projection may prune
143 + * them and summary_only omits records, so a client should treat declared data
144 + * keys as optional. The adapter advertises this to the model but does not
145 + * validate results against it, so it is documentation, not a runtime gate.
146 + *
147 + * @param array $dataSchema JSON Schema for the tool's data payload
148 + * @param array $metaProps extra documented meta properties
149 + * @return array
150 + */
151 + public static function envelopeSchema(array $dataSchema, array $metaProps = [])
152 + {
153 + return [
154 + 'type' => 'object',
155 + 'properties' => [
156 + 'summary' => ['type' => 'string', 'description' => 'One-line, human-readable answer — quotable verbatim.'],
157 + 'data' => $dataSchema,
158 + 'meta' => self::metaSchema($metaProps),
159 + ],
160 + 'required' => ['summary', 'data', 'meta'],
161 + ];
162 + }
163 +
164 + // -----------------------------------------------------------------
88 165 // Money
89 166 // -----------------------------------------------------------------
90 167
91 168 /**
@@ -333,8 +410,47 @@
333 410
334 411 // -----------------------------------------------------------------
335 412 // People / labels
336 413 // -----------------------------------------------------------------
414 +
415 + // -----------------------------------------------------------------
416 + // Field selection
417 + // -----------------------------------------------------------------
418 +
419 + /**
420 + * Project a record down to a caller-requested subset of top-level keys, to
421 + * shrink heavy payloads. Returns the record UNCHANGED when $fields is empty
422 + * or not an array (the default, backward-compatible behavior). Only keys that
423 + * actually exist are kept, in the record's own order; unknown requested keys
424 + * are ignored. Keys in $alwaysKeep (the record's identifier) are retained
425 + * regardless so a projected record is never anonymous.
426 + *
427 + * @param array $row
428 + * @param mixed $fields array of key names, or null/non-array for "all"
429 + * @param array $alwaysKeep keys to keep even if not requested (e.g. the id)
430 + */
431 + public static function pickFields($row, $fields, array $alwaysKeep = [])
432 + {
433 + if (empty($fields) || !is_array($fields)) {
434 + return $row;
435 + }
436 +
437 + $wanted = [];
438 + foreach ($alwaysKeep as $k) {
439 + $wanted[$k] = true;
440 + }
441 + foreach ($fields as $f) {
442 + $wanted[(string) $f] = true;
443 + }
444 +
445 + $out = [];
446 + foreach ($row as $key => $val) {
447 + if (isset($wanted[$key])) {
448 + $out[$key] = $val;
449 + }
450 + }
451 + return $out;
452 + }
337 453
338 454 /** "First Last <email>" style name from a customer/person-ish model. */
339 455 public static function personName($model)
340 456 {