getConnection(); // Handle method override and multipart data parsing $method = $_SERVER['REQUEST_METHOD']; $parsed_data = array(); // Parse multipart form data manually if needed if (($method === 'PUT' || $method === 'PATCH') && empty($_POST) && isset($_SERVER['CONTENT_TYPE']) && strpos($_SERVER['CONTENT_TYPE'], 'multipart/form-data') !== false) { // Force treat as POST to get parsed form data $raw_input = file_get_contents('php://input'); $parsed_data = parseMultipartFormData($raw_input, $_SERVER['CONTENT_TYPE']); // If we found form data, treat this as a method override if (!empty($parsed_data)) { if (isset($parsed_data['_method'])) { $method = strtoupper($parsed_data['_method']); unset($parsed_data['_method']); } // Populate $_POST with parsed data for compatibility $_POST = $parsed_data; } } // Check for X-HTTP-Method-Override header if (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) { $method = $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']; } // Check for _method parameter (Laravel style) - now works with manually parsed data too if (isset($_POST['_method'])) { $method = strtoupper($_POST['_method']); unset($_POST['_method']); // Clean it up } $response = array('success' => false, 'message' => '', 'data' => null); // Log only important requests for production if ($method === 'PUT' || $method === 'DELETE') { error_log("FTTH API - " . $method . " request, ID: " . (isset($_POST['id']) ? $_POST['id'] : 'N/A')); } try { switch($method) { case 'GET': if (isset($_GET['id'])) { // Get single item $query = "SELECT i.*, i.serial_number, it.name as item_type_name, it.icon, it.color, tc.color_name as tube_color_name, tc.hex_code, cc.color_name as core_color_name, cc.hex_code as core_hex_code, sm.ratio as splitter_main_ratio, so.ratio as splitter_odp_ratio FROM ftth_items i LEFT JOIN item_types it ON i.item_type_id = it.id LEFT JOIN tube_colors tc ON i.tube_color_id = tc.id LEFT JOIN tube_colors cc ON i.core_color_id = cc.id LEFT JOIN splitter_types sm ON i.splitter_main_id = sm.id LEFT JOIN splitter_types so ON i.splitter_odp_id = so.id WHERE i.id = :id"; $stmt = $db->prepare($query); $stmt->bindParam(':id', $_GET['id']); $stmt->execute(); $item = $stmt->fetch(PDO::FETCH_ASSOC); if ($item) { $response['success'] = true; $response['data'] = $item; } else { $response['message'] = 'Item not found'; } } else { // Get all items $query = "SELECT i.*, i.serial_number, it.name as item_type_name, it.icon, it.color, tc.color_name as tube_color_name, tc.hex_code, cc.color_name as core_color_name, cc.hex_code as core_hex_code, sm.ratio as splitter_main_ratio, so.ratio as splitter_odp_ratio FROM ftth_items i LEFT JOIN item_types it ON i.item_type_id = it.id LEFT JOIN tube_colors tc ON i.tube_color_id = tc.id LEFT JOIN tube_colors cc ON i.core_color_id = cc.id LEFT JOIN splitter_types sm ON i.splitter_main_id = sm.id LEFT JOIN splitter_types so ON i.splitter_odp_id = so.id ORDER BY i.created_at DESC"; $stmt = $db->prepare($query); $stmt->execute(); $items = $stmt->fetchAll(PDO::FETCH_ASSOC); $response['success'] = true; $response['data'] = $items; } break; case 'POST': // Create new item $item_type_id = $_POST['item_type'] ?? null; $name = $_POST['name'] ?? null; $description = $_POST['description'] ?? null; $latitude = $_POST['latitude'] ?? null; $longitude = $_POST['longitude'] ?? null; $address = $_POST['address'] ?? null; $serial_number = $_POST['serial_number'] ?? null; // <--- Tambahan // Handle foreign key fields - convert empty strings to NULL $tube_color_id = (!empty($_POST['tube_color_id']) && $_POST['tube_color_id'] !== '0') ? $_POST['tube_color_id'] : null; $core_used = (!empty($_POST['core_used']) && $_POST['core_used'] !== '0') ? $_POST['core_used'] : null; $core_color_id = (!empty($_POST['core_color_id']) && $_POST['core_color_id'] !== '0') ? $_POST['core_color_id'] : null; $item_cable_type = $_POST['item_cable_type'] ?? 'distribution'; $total_core_capacity = $_POST['total_core_capacity'] ?? 24; $splitter_main_id = (!empty($_POST['splitter_main_id']) && $_POST['splitter_main_id'] !== '0') ? $_POST['splitter_main_id'] : null; $splitter_odp_id = (!empty($_POST['splitter_odp_id']) && $_POST['splitter_odp_id'] !== '0') ? $_POST['splitter_odp_id'] : null; $status = $_POST['status'] ?? 'active'; if (!$item_type_id || !$name || !$latitude || !$longitude) { $response['message'] = 'Required fields missing'; break; } $query = "INSERT INTO ftth_items ( item_type_id, name, description, latitude, longitude, address, serial_number, tube_color_id, core_used, core_color_id, item_cable_type, total_core_capacity, splitter_main_id, splitter_odp_id, status ) VALUES ( :item_type_id, :name, :description, :latitude, :longitude, :address, :serial_number, :tube_color_id, :core_used, :core_color_id, :item_cable_type, :total_core_capacity, :splitter_main_id, :splitter_odp_id, :status )"; $stmt = $db->prepare($query); $stmt->bindParam(':item_type_id', $item_type_id); $stmt->bindParam(':name', $name); $stmt->bindParam(':description', $description); $stmt->bindParam(':latitude', $latitude); $stmt->bindParam(':longitude', $longitude); $stmt->bindParam(':address', $address); $stmt->bindParam(':serial_number', $serial_number); // <--- Bind $stmt->bindParam(':tube_color_id', $tube_color_id); $stmt->bindParam(':core_used', $core_used); $stmt->bindParam(':core_color_id', $core_color_id); $stmt->bindParam(':item_cable_type', $item_cable_type); $stmt->bindParam(':total_core_capacity', $total_core_capacity); $stmt->bindParam(':splitter_main_id', $splitter_main_id); $stmt->bindParam(':splitter_odp_id', $splitter_odp_id); $stmt->bindParam(':status', $status); if ($stmt->execute()) { $item_id = $db->lastInsertId(); // Get the created item with joins $query = "SELECT i.*, i.serial_number, it.name as item_type_name, it.icon, it.color, tc.color_name as tube_color_name, tc.hex_code, cc.color_name as core_color_name, cc.hex_code as core_hex_code, sm.ratio as splitter_main_ratio, so.ratio as splitter_odp_ratio FROM ftth_items i LEFT JOIN item_types it ON i.item_type_id = it.id LEFT JOIN tube_colors tc ON i.tube_color_id = tc.id LEFT JOIN tube_colors cc ON i.core_color_id = cc.id LEFT JOIN splitter_types sm ON i.splitter_main_id = sm.id LEFT JOIN splitter_types so ON i.splitter_odp_id = so.id WHERE i.id = :id"; $stmt = $db->prepare($query); $stmt->bindParam(':id', $item_id); $stmt->execute(); $response['success'] = true; $response['message'] = 'Item created successfully'; $response['data'] = $stmt->fetch(PDO::FETCH_ASSOC); } else { $response['message'] = 'Failed to create item'; } break; case 'PUT': // Update item - now $_POST should be properly populated $put_data = $_POST; $id = $put_data['id'] ?? null; if (!$id) { $response['message'] = 'ID required for update'; break; } // Build dynamic update query $update_fields = array(); $params = array(':id' => $id); $allowed_fields = ['item_type', 'name', 'description', 'latitude', 'longitude', 'address', 'serial_number','tube_color_id', 'core_used', 'core_color_id', 'item_cable_type', 'total_core_capacity', 'splitter_main_id', 'splitter_odp_id', 'status']; foreach ($allowed_fields as $field) { if (isset($put_data[$field])) { $db_field = $field === 'item_type' ? 'item_type_id' : $field; $update_fields[] = "$db_field = :$field"; // Handle empty values for foreign key fields - convert to NULL $value = $put_data[$field]; if (in_array($field, ['tube_color_id', 'core_color_id', 'splitter_main_id', 'splitter_odp_id']) && ($value === '' || $value === '0' || $value === 0)) { $value = null; } $params[":$field"] = $value; } } if (empty($update_fields)) { $response['message'] = 'No fields to update'; break; } $query = "UPDATE ftth_items SET " . implode(', ', $update_fields) . " WHERE id = :id"; $stmt = $db->prepare($query); if ($stmt->execute($params)) { // Get updated item $query = "SELECT i.*, i.serial_number, it.name as item_type_name, it.icon, it.color, tc.color_name as tube_color_name, tc.hex_code, cc.color_name as core_color_name, cc.hex_code as core_hex_code, sm.ratio as splitter_main_ratio, so.ratio as splitter_odp_ratio FROM ftth_items i LEFT JOIN item_types it ON i.item_type_id = it.id LEFT JOIN tube_colors tc ON i.tube_color_id = tc.id LEFT JOIN tube_colors cc ON i.core_color_id = cc.id LEFT JOIN splitter_types sm ON i.splitter_main_id = sm.id LEFT JOIN splitter_types so ON i.splitter_odp_id = so.id WHERE i.id = :id"; $stmt = $db->prepare($query); $stmt->bindParam(':id', $id); $stmt->execute(); $response['success'] = true; $response['message'] = 'Item updated successfully'; $response['data'] = $stmt->fetch(PDO::FETCH_ASSOC); } else { $response['message'] = 'Failed to update item'; } break; case 'DELETE': // Delete item $input = file_get_contents("php://input"); $delete_data = array(); // Try to parse JSON first, then form data $json_data = json_decode($input, true); if ($json_data) { $delete_data = $json_data; } else { parse_str($input, $delete_data); } // Also check for regular POST data (for compatibility) if (empty($delete_data)) { $delete_data = $_POST; } $id = $delete_data['id'] ?? null; if (!$id) { $response['message'] = 'ID required for deletion'; break; } // Delete related routes first $query = "DELETE FROM cable_routes WHERE from_item_id = :id OR to_item_id = :id"; $stmt = $db->prepare($query); $stmt->bindParam(':id', $id); $stmt->execute(); // Delete the item $query = "DELETE FROM ftth_items WHERE id = :id"; $stmt = $db->prepare($query); $stmt->bindParam(':id', $id); if ($stmt->execute()) { $response['success'] = true; $response['message'] = 'Item deleted successfully'; } else { $response['message'] = 'Failed to delete item'; } break; default: $response['message'] = 'Method not allowed'; break; } } catch (Exception $e) { $response['message'] = 'Database error: ' . $e->getMessage(); } echo json_encode($response); ?>