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.6 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 All 49 releases
← All changes | app/Modules/MCP/Support/AdvancedSearch.php +60 -4 1.5.4 → 1.6.5 View file →
@@ -3,8 +3,9 @@
3 3 namespace FluentCart\App\Modules\MCP\Support;
4 4
5 5 use FluentCart\Api\ModuleSettings;
6 6 use FluentCart\App\App;
7 +use FluentCart\App\Modules\MCP\Tools\ContextTools;
7 8 use FluentCart\App\Modules\Subscriptions\Services\Filter\SubscriptionFilter;
8 9 use FluentCart\App\Services\Filter\CustomerFilter;
9 10 use FluentCart\App\Services\Filter\LicenseFilter;
10 11 use FluentCart\App\Services\Filter\OrderFilter;
@@ -133,9 +134,9 @@
133 134 return self::unknownEntityError($entity);
134 135 }
135 136
136 137 $filterClass = Arr::get($spec, 'filter');
137 - $catalog = self::catalog($filterClass);
138 + $catalog = self::catalog($filterClass, $entity);
138 139 if (!$catalog) {
139 140 return MCPHelper::error(
140 141 'no_advanced_options',
141 142 sprintf(
@@ -278,13 +279,36 @@
278 279 // Catalog — live property map per entity
279 280 // -----------------------------------------------------------------
280 281
281 282 /**
283 + * Status properties whose admin dropdown is a curated subset of the values
284 + * the column can actually hold, mapped to the canonical enum that completes
285 + * them. The admin UI ships the short list on purpose (those are the statuses
286 + * a merchant filters by day to day); an agent needs the full set, because
287 + * "find the failed orders" is a normal question and the engine executes
288 + * WHERE status IN (...) against the raw column either way.
289 + *
290 + * MCP-side only — the shared fluent_cart/{name}_filter_options hook is left
291 + * untouched so the admin dropdowns keep their curated lists.
292 + */
293 + const CANONICAL_OPTIONS = [
294 + 'orders.order.status' => 'order_statuses',
295 + 'orders.order.payment_status' => 'payment_statuses',
296 + 'orders.order.type' => 'order_types',
297 + 'subscriptions.subscription.status' => 'subscription_statuses',
298 + 'subscriptions.subscription.billing_interval' => 'billing_intervals',
299 + ];
300 +
301 + /**
282 302 * provider.property => { provider, property, def } for one filter class,
283 303 * through the same fluent_cart/{name}_filter_options hook the engine
284 304 * applies, so Pro/add-on providers appear here exactly as they execute.
305 + *
306 + * $entity is used only to complete curated status option lists from the
307 + * canonical enums (see CANONICAL_OPTIONS); pass it so the schema the agent
308 + * reads and the values normalize() accepts stay the same list.
285 309 */
286 - private static function catalog($filterClass): array
310 + private static function catalog($filterClass, $entity = ''): array
287 311 {
288 312 if (!$filterClass || !class_exists($filterClass) || !is_callable([$filterClass, 'advanceFilterOptions'])) {
289 313 return [];
290 314 }
@@ -316,9 +340,9 @@
316 340 }
317 341 $map[$key] = [
318 342 'provider' => (string) $providerKey,
319 343 'property' => $property,
320 - 'def' => $child,
344 + 'def' => self::completeOptions($entity, $key, $child),
321 345 ];
322 346 }
323 347 }
324 348
@@ -324,8 +348,40 @@
324 348
325 349 return $map;
326 350 }
327 351
352 + /**
353 + * Union a curated status dropdown with its canonical enum, preserving the
354 + * catalog's labels for the values it already had. Returns the definition
355 + * unchanged for every property without a canonical counterpart.
356 + */
357 + private static function completeOptions($entity, $key, array $def): array
358 + {
359 + $enumKey = Arr::get(self::CANONICAL_OPTIONS, $entity . '.' . $key);
360 + if (!$enumKey) {
361 + return $def;
362 + }
363 + // Only selection widgets carry an options map; leave anything else alone.
364 + if (Arr::get($def, 'type') !== 'selections') {
365 + return $def;
366 + }
367 +
368 + $enums = ContextTools::enums();
369 + if (empty($enums[$enumKey])) {
370 + return $def;
371 + }
372 +
373 + $options = (array) Arr::get($def, 'options', []);
374 + foreach ($enums[$enumKey] as $value) {
375 + if (!array_key_exists($value, $options)) {
376 + $options[$value] = $value;
377 + }
378 + }
379 + $def['options'] = $options;
380 +
381 + return $def;
382 + }
383 +
328 384 /** Money columns for the entity, so values can be documented/validated as store-currency decimals. */
329 385 private static function centColumnsFor($filterClass): array
330 386 {
331 387 try {
@@ -442,9 +498,9 @@
442 498 if (count($raw) > self::MAX_GROUPS) {
443 499 return self::limitError($entity);
444 500 }
445 501
446 - $catalog = self::catalog($filterClass);
502 + $catalog = self::catalog($filterClass, $entity);
447 503 $centColumns = self::centColumnsFor($filterClass);
448 504
449 505 $groups = [];
450 506 $warnings = [];