getInputs(); $location_id = $inputs['location_id'] ?? '?'; $changes = []; if ( ! empty( $inputs['restaurant_name'] ) ) { $changes[] = "name to \"{$inputs['restaurant_name']}\""; } if ( ! empty( $inputs['location'] ) ) { $changes[] = "address to \"{$inputs['location']}\""; } if ( isset( $inputs['enable_reservation'] ) ) { $changes[] = 'reservation ' . ( $inputs['enable_reservation'] ? 'enabled' : 'disabled' ); } if ( isset( $inputs['enable_pickup'] ) ) { $changes[] = 'pickup ' . ( $inputs['enable_pickup'] ? 'enabled' : 'disabled' ); } if ( isset( $inputs['enable_delivery'] ) ) { $changes[] = 'delivery ' . ( $inputs['enable_delivery'] ? 'enabled' : 'disabled' ); } if ( isset( $inputs['delivery_fee'] ) ) { $changes[] = "delivery fee to {$inputs['delivery_fee']}"; } $summary = "Update location #{$location_id}"; if ( ! empty( $changes ) ) { $summary .= ': ' . implode( ', ', $changes ); } return $summary; } /** * Human-readable version of tool inputs for the approval card. * * @return array */ public function get_approval_inputs(): array { return $this->getInputs(); } /** * Execute the tool * * @param int $location_id Location ID to update. * @param string|null $restaurant_name New name. * @param string|null $location New address. * @param bool|null $enable_reservation Enable/disable reservations. * @param bool|null $enable_pickup Enable/disable pickup. * @param bool|null $enable_delivery Enable/disable delivery. * @param float|null $delivery_fee Updated delivery fee. * @param int|null $reservation_minimum_guest Updated minimum guests. * @param int|null $reservation_maximum_guest Updated maximum guests. * @return array */ public function __invoke( int $location_id, ?string $restaurant_name = null, ?string $location = null, ?bool $enable_reservation = null, ?bool $enable_pickup = null, ?bool $enable_delivery = null, ?float $delivery_fee = null, ?int $reservation_minimum_guest = null, ?int $reservation_maximum_guest = null ): array { $check = $this->guard( 'manage_options' ); if ( $check ) { return $check; } if ( $location_id <= 0 ) { return [ 'error' => 'location_id must be a positive integer.' ]; } try { // Pre-fetch the existing location so we can (a) return a clean not-found // error and (b) fill the required restaurant_name + location fields that // prepare_item_for_database() always validates, even on a partial PATCH. $existing = \WpCafe\Models\Location_Model::find( $location_id ); if ( ! $existing ) { return [ 'error' => "Location #{$location_id} not found." ]; } $body = []; // restaurant_name and location are required by the controller's // prepare_item_for_database() even on a partial update; fall back to // the existing values so a caller who only changes delivery_fee doesn't // get a validation error. $body['restaurant_name'] = null !== $restaurant_name ? sanitize_text_field( $restaurant_name ) : (string) $existing->restaurant_name; $body['location'] = null !== $location ? sanitize_text_field( $location ) : (string) $existing->location; if ( null !== $enable_reservation ) { $body['enable_reservation'] = $enable_reservation; } if ( null !== $enable_pickup ) { $body['enable_pickup'] = $enable_pickup; } if ( null !== $enable_delivery ) { $body['enable_delivery'] = $enable_delivery; } if ( null !== $delivery_fee ) { $body['delivery_fee'] = max( 0.0, $delivery_fee ); } if ( null !== $reservation_minimum_guest ) { $body['reservation_minimum_guest'] = max( 1, $reservation_minimum_guest ); } if ( null !== $reservation_maximum_guest ) { $body['reservation_maximum_guest'] = max( 1, $reservation_maximum_guest ); } if ( isset( $body['reservation_minimum_guest'], $body['reservation_maximum_guest'] ) && $body['reservation_minimum_guest'] > $body['reservation_maximum_guest'] ) { return [ 'error' => 'reservation_minimum_guest cannot exceed reservation_maximum_guest.' ]; } // $body always has restaurant_name + location (from existing); check // that the caller actually provided at least one meaningful change. $caller_supplied = array_diff_key( $body, array_flip( [ 'restaurant_name', 'location' ] ) ); $name_changed = null !== $restaurant_name; $address_changed = null !== $location; if ( empty( $caller_supplied ) && ! $name_changed && ! $address_changed ) { return [ 'error' => 'No fields provided to update.' ]; } $json = wp_json_encode( $body ); if ( false === $json ) { Log::error( 'Wpcafe_Update_Location_Tool JSON encoding failed', [ 'body_keys' => array_keys( $body ) ] ); return [ 'error' => 'Failed to encode request data. Ensure all input values are valid text.' ]; } $request = new \WP_REST_Request( 'PATCH', '/wpcafe/v2/locations/' . $location_id ); $request->set_header( 'content-type', 'application/json' ); $request->set_url_params( [ 'id' => $location_id ] ); $request->set_body( $json ); $controller = new \WpCafe\Location\Controllers\Location_Controller(); $response = $controller->update_item( $request ); // Write-specific unwrapper: update_item() returns a raw Model, not a Resource array. $data = $this->extract_write_result( $response, 'Failed to update location.' ); if ( isset( $data['error'] ) ) { return $data; } return [ 'success' => true, 'location_id' => $location_id, 'updated_fields' => array_keys( $body ), 'message' => "Location #{$location_id} updated successfully.", ]; } catch ( \Throwable $e ) { Log::error( 'Wpcafe_Update_Location_Tool error', [ 'error' => $e->getMessage() ] ); return [ 'error' => 'Failed to update location: ' . $e->getMessage() ]; } } }