| @@ -360,8 +360,10 @@ | ||
| 360 | 360 | $attribute->field_options = $metadata['field_options'] ?? null; |
| 361 | 361 | $attribute->validation_rules = $metadata['validation_rules'] ?? null; |
| 362 | 362 | } |
| 363 | 363 | } |
| 364 | + | |
| 365 | + $this->attachDecodedIconToAttribute($attribute); | |
| 364 | 366 | |
| 365 | 367 | return $this->success_response($attribute, 201); |
| 366 | 368 | } |
| 367 | 369 | |
| @@ -404,39 +406,9 @@ | ||
| 404 | 406 | $attribute->validation_rules = $metadata['validation_rules'] ?? null; |
| 405 | 407 | } |
| 406 | 408 | } |
| 407 | 409 | |
| 408 | - // Process icon field - unserialize if it's serialized | |
| 409 | - if (!empty($attribute->icon)) { | |
| 410 | - $icon_data = maybe_unserialize($attribute->icon); | |
| 411 | - if (is_array($icon_data)) { | |
| 412 | - // Resolve image URLs for image type icons | |
| 413 | - if ($icon_data['type'] === 'image' && !empty($icon_data['value'])) { | |
| 414 | - $value = $icon_data['value']; | |
| 415 | - $image_url = ''; | |
| 416 | - | |
| 417 | - if (is_numeric($value)) { | |
| 418 | - $maybe_url = wp_get_attachment_image_url((int) $value, 'large'); | |
| 419 | - if (!empty($maybe_url)) { | |
| 420 | - $image_url = $maybe_url; | |
| 421 | - } | |
| 422 | - } elseif (is_string($value) && filter_var($value, FILTER_VALIDATE_URL)) { | |
| 423 | - $image_url = $value; | |
| 424 | - } | |
| 425 | - | |
| 426 | - $icon_data['value'] = $image_url; | |
| 427 | - } | |
| 428 | - $attribute->icon = $icon_data; | |
| 429 | - } else { | |
| 430 | - // Handle legacy string format | |
| 431 | - $attribute->icon = [ | |
| 432 | - 'type' => 'icon', | |
| 433 | - 'value' => $attribute->icon | |
| 434 | - ]; | |
| 435 | - } | |
| 436 | - } else { | |
| 437 | - $attribute->icon = null; | |
| 438 | - } | |
| 410 | + $this->attachDecodedIconToAttribute($attribute); | |
| 439 | 411 | |
| 440 | 412 | return $this->success_response($attribute); |
| 441 | 413 | |
| 442 | 414 | } catch (\Exception $e) { |
| @@ -743,17 +715,18 @@ | ||
| 743 | 715 | // Handle icon field |
| 744 | 716 | if ($request->has_param('icon')) { |
| 745 | 717 | $icon = $request->get_param('icon'); |
| 746 | 718 | if (is_array($icon)) { |
| 747 | - // Sanitize icon array | |
| 748 | - $data['icon'] = [ | |
| 749 | - 'type' => isset($icon['type']) && in_array($icon['type'], ['icon', 'image'], true) | |
| 750 | - ? $icon['type'] | |
| 751 | - : 'icon', | |
| 752 | - 'value' => isset($icon['value']) | |
| 753 | - ? sanitize_text_field($icon['value']) | |
| 754 | - : '', | |
| 755 | - ]; | |
| 719 | + $data['icon'] = function_exists('yatra_normalize_icon_picker_for_storage') | |
| 720 | + ? yatra_normalize_icon_picker_for_storage($icon) | |
| 721 | + : [ | |
| 722 | + 'type' => isset($icon['type']) && in_array($icon['type'], ['icon', 'image'], true) | |
| 723 | + ? $icon['type'] | |
| 724 | + : 'icon', | |
| 725 | + 'value' => isset($icon['value']) | |
| 726 | + ? sanitize_text_field((string) $icon['value']) | |
| 727 | + : '', | |
| 728 | + ]; | |
| 756 | 729 | } elseif (is_string($icon)) { |
| 757 | 730 | // Handle legacy string format |
| 758 | 731 | $data['icon'] = sanitize_text_field($icon); |
| 759 | 732 | } |
| @@ -837,42 +810,33 @@ | ||
| 837 | 810 | return $data; |
| 838 | 811 | } |
| 839 | 812 | |
| 840 | 813 | /** |
| 841 | - * Check permissions for read operations | |
| 814 | + * Granular permission checks. Trip attributes are a trip-taxonomy | |
| 815 | + * concept — they classify trips for filtering / display — so the | |
| 816 | + * Team module's `yatra_manage_trip_taxonomies` cap is the right | |
| 817 | + * gate for write operations, and `yatra_view_trips` for reads. | |
| 818 | + * WP administrators pass every cap via the Team module's admin- | |
| 819 | + * fallback filter so no explicit `manage_options` check is needed. | |
| 842 | 820 | */ |
| 843 | 821 | public function get_permissions_check(): bool |
| 844 | 822 | { |
| 845 | - return current_user_can('manage_options'); | |
| 823 | + return current_user_can('yatra_view_trips'); | |
| 846 | 824 | } |
| 847 | 825 | |
| 848 | - /** | |
| 849 | - * Check permissions for create/update/delete operations | |
| 850 | - */ | |
| 851 | 826 | public function check_permission(?WP_REST_Request $request = null): bool |
| 852 | 827 | { |
| 853 | - $hasPermission = current_user_can('manage_options'); | |
| 854 | - | |
| 855 | - if (defined('WP_DEBUG') && WP_DEBUG) { | |
| 856 | - } | |
| 857 | - | |
| 858 | - return $hasPermission; | |
| 828 | + return current_user_can('yatra_manage_trip_taxonomies'); | |
| 859 | 829 | } |
| 860 | 830 | |
| 861 | - /** | |
| 862 | - * Check permissions for search operations | |
| 863 | - */ | |
| 864 | 831 | public function search_permissions_check(): bool |
| 865 | 832 | { |
| 866 | - return current_user_can('manage_options'); | |
| 833 | + return current_user_can('yatra_view_trips'); | |
| 867 | 834 | } |
| 868 | 835 | |
| 869 | - /** | |
| 870 | - * Check permissions for update operations | |
| 871 | - */ | |
| 872 | 836 | public function update_permissions_check(): bool |
| 873 | 837 | { |
| 874 | - return current_user_can('manage_options'); | |
| 838 | + return current_user_can('yatra_manage_trip_taxonomies'); | |
| 875 | 839 | } |
| 876 | 840 | |
| 877 | 841 | /** |
| 878 | 842 | * Get item schema |
| @@ -987,7 +951,44 @@ | ||
| 987 | 951 | $stats = $this->attributeService->getStatusCounts(); |
| 988 | 952 | return $this->success_response($stats); |
| 989 | 953 | } catch (\Exception $e) { |
| 990 | 954 | return $this->error_response($e->getMessage(), 500); |
| 955 | + } | |
| 956 | + } | |
| 957 | + | |
| 958 | + /** | |
| 959 | + * Replace raw DB icon (serialized array or legacy string) with REST JSON (preserves Font Awesome provider). | |
| 960 | + * | |
| 961 | + * @param object $attribute Row from AttributeService::getById() | |
| 962 | + */ | |
| 963 | + private function attachDecodedIconToAttribute(object $attribute): void | |
| 964 | + { | |
| 965 | + if (!empty($attribute->icon)) { | |
| 966 | + $icon_data = maybe_unserialize($attribute->icon); | |
| 967 | + if (is_array($icon_data)) { | |
| 968 | + if ($icon_data['type'] === 'image' && !empty($icon_data['value'])) { | |
| 969 | + $value = $icon_data['value']; | |
| 970 | + $image_url = ''; | |
| 971 | + | |
| 972 | + if (is_numeric($value)) { | |
| 973 | + $maybe_url = wp_get_attachment_image_url((int) $value, 'large'); | |
| 974 | + if (!empty($maybe_url)) { | |
| 975 | + $image_url = $maybe_url; | |
| 976 | + } | |
| 977 | + } elseif (is_string($value) && filter_var($value, FILTER_VALIDATE_URL)) { | |
| 978 | + $image_url = $value; | |
| 979 | + } | |
| 980 | + | |
| 981 | + $icon_data['value'] = $image_url; | |
| 982 | + } | |
| 983 | + $attribute->icon = $icon_data; | |
| 984 | + } else { | |
| 985 | + $attribute->icon = [ | |
| 986 | + 'type' => 'icon', | |
| 987 | + 'value' => (string) $attribute->icon, | |
| 988 | + ]; | |
| 989 | + } | |
| 990 | + } else { | |
| 991 | + $attribute->icon = null; | |
| 991 | 992 | } |
| 992 | 993 | } |
| 993 | 994 | } |