'Method not allowed', 'allowed_methods' => ['GET', 'POST', 'PUT', 'DELETE'] ]); break; } } catch (Exception $e) { // Log error dengan detail $errorTime = microtime(true); $errorMemory = memory_get_usage(true); error_log("TblocationName CRUD API Error: " . $e->getMessage()); error_log("Error occurred at: " . round($errorTime - $startTime, 2) . " seconds"); error_log("Memory at error: " . number_format($errorMemory / 1024 / 1024, 2) . " MB"); error_log("Error trace: " . $e->getTraceAsString()); http_response_code(500); echo json_encode([ 'error' => 'Internal server error', 'message' => $e->getMessage(), 'processing_time' => round($errorTime - $startTime, 2) . " seconds", 'memory_usage' => number_format(($errorMemory - $startMemory) / 1024 / 1024, 2) . " MB" // Debug version dengan detail error: // 'error_details' => [ // 'message' => $e->getMessage(), // 'file' => $e->getFile(), // 'line' => $e->getLine(), // 'trace' => $e->getTraceAsString() // ] ]); } finally { // Cleanup memory gc_collect_cycles(); } /** * Handle READ operations (GET) * ============================ * Get location names dengan optional filtering * * Query Parameters: * - loc_name: Filter by location name * - company: Filter by company * - lat: Filter by latitude * - lon: Filter by longitude * - limit: Limit results (default: 100) * - offset: Offset for pagination (default: 0) */ function handleRead($pdo, $user) { global $startTime, $startMemory; // Debug: Log read operation // error_log("TblocationName CRUD - READ operation for user: " . $user); // Get query parameters $locName = isset($_GET['loc_name']) ? trim($_GET['loc_name']) : ''; $company = isset($_GET['company']) ? trim($_GET['company']) : ''; $lat = isset($_GET['lat']) ? trim($_GET['lat']) : ''; $lon = isset($_GET['lon']) ? trim($_GET['lon']) : ''; $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 100; $offset = isset($_GET['offset']) ? (int)$_GET['offset'] : 0; // Validate limit if ($limit > 1000) { $limit = 1000; // Maximum 1000 records per request } // Build SQL query $sql = "SELECT loc_name, lat, lon, shapecolor, company, FullName FROM tblocationName WHERE 1=1"; $params = array(); // Add filters if (!empty($locName)) { $sql .= " AND loc_name LIKE ?"; $params[] = '%' . $locName . '%'; } if (!empty($company)) { $sql .= " AND company LIKE ?"; $params[] = '%' . $company . '%'; } if (!empty($lat)) { $sql .= " AND lat = ?"; $params[] = $lat; } if (!empty($lon)) { $sql .= " AND lon = ?"; $params[] = $lon; } // Add ordering dan pagination $sql .= " ORDER BY loc_name ASC"; // SQL Server requires literal values for OFFSET/FETCH, not parameters $sql .= " OFFSET $offset ROWS FETCH NEXT $limit ROWS ONLY"; // Remove offset dan limit dari params karena sudah di-embed ke SQL // $params[] = $offset; // $params[] = $limit; // Debug: Log SQL query // error_log("TblocationName READ SQL: " . $sql); // error_log("TblocationName read params: " . json_encode($params)); // Execute query $stmt = $pdo->prepare($sql); $stmt->execute($params); $results = $stmt->fetchAll(PDO::FETCH_ASSOC); // Get total count untuk pagination info $countSql = "SELECT COUNT(*) as total FROM tblocationName WHERE 1=1"; $countParams = array(); if (!empty($locName)) { $countSql .= " AND loc_name LIKE ?"; $countParams[] = '%' . $locName . '%'; } if (!empty($company)) { $countSql .= " AND company LIKE ?"; $countParams[] = '%' . $company . '%'; } if (!empty($lat)) { $countSql .= " AND lat = ?"; $countParams[] = $lat; } if (!empty($lon)) { $countSql .= " AND lon = ?"; $countParams[] = $lon; } $countStmt = $pdo->prepare($countSql); $countStmt->execute($countParams); $totalCount = $countStmt->fetch(PDO::FETCH_ASSOC)['total']; // Performance monitoring $endTime = microtime(true); $endMemory = memory_get_usage(true); $processingTime = round($endTime - $startTime, 2); $memoryUsed = round(($endMemory - $startMemory) / 1024 / 1024, 2); // Debug: Log performance metrics // error_log("TblocationName READ - Processing completed in {$processingTime}s, Memory: {$memoryUsed}MB"); // Return results http_response_code(200); echo json_encode([ 'success' => true, 'data' => $results, 'pagination' => [ 'total_records' => (int)$totalCount, 'returned_records' => count($results), 'limit' => $limit, 'offset' => $offset, 'has_more' => ($offset + $limit) < $totalCount ], 'filters_applied' => [ 'loc_name' => $locName, 'company' => $company, 'lat' => $lat, 'lon' => $lon ], 'processing_info' => [ 'processing_time' => $processingTime . " seconds", 'memory_usage' => $memoryUsed . " MB", 'user' => $user ] ]); } /** * Handle CREATE operations (POST) * =============================== * Create new location name berdasarkan format original code * * Request Body: * { * "user": "username", * "company": "company_name", * "name": "location_name", * "txt_lat": "latitude", * "txt_lng": "longitude" * } */ function handleCreate($pdo, $user) { global $startTime, $startMemory; // Debug: Log create operation // error_log("TblocationName CRUD - CREATE operation for user: " . $user); // Get request body $input = json_decode(file_get_contents('php://input'), true); if (!$input) { http_response_code(400); echo json_encode([ 'error' => 'Invalid JSON input', 'details' => 'Request body must be valid JSON' ]); return; } // Debug: Log request data // error_log("TblocationName CREATE - Request data: " . json_encode($input)); // Validasi required fields berdasarkan original code $requiredFields = ['user', 'company', 'name', 'txt_lat', 'txt_lng']; $missingFields = array(); foreach ($requiredFields as $field) { if (!isset($input[$field]) || trim($input[$field]) === '') { $missingFields[] = $field; } } if (!empty($missingFields)) { http_response_code(400); echo json_encode([ 'error' => 'Data Not Correct', 'details' => 'Missing or empty required fields', 'missing_fields' => $missingFields, 'required_fields' => $requiredFields ]); return; } // Sanitize input $userInput = trim($input['user']); $company = trim($input['company']); $name = trim($input['name']); $txtLat = trim($input['txt_lat']); $txtLng = trim($input['txt_lng']); // Validate coordinates if (!is_numeric($txtLat) || !is_numeric($txtLng)) { http_response_code(400); echo json_encode([ 'error' => 'Invalid coordinates', 'details' => 'txt_lat and txt_lng must be numeric values', 'received' => [ 'txt_lat' => $txtLat, 'txt_lng' => $txtLng ] ]); return; } // Validate coordinate ranges $lat = (float)$txtLat; $lng = (float)$txtLng; if ($lat < -90 || $lat > 90) { http_response_code(400); echo json_encode([ 'error' => 'Invalid latitude', 'details' => 'Latitude must be between -90 and 90', 'received' => $lat ]); return; } if ($lng < -180 || $lng > 180) { http_response_code(400); echo json_encode([ 'error' => 'Invalid longitude', 'details' => 'Longitude must be between -180 and 180', 'received' => $lng ]); return; } // Build loc_name berdasarkan format original: user_name $locName = $userInput . '_' . $name; // Check if location already exists $checkSql = "SELECT COUNT(*) as count FROM tblocationName WHERE loc_name = ?"; $checkStmt = $pdo->prepare($checkSql); $checkStmt->execute([$locName]); $exists = $checkStmt->fetch(PDO::FETCH_ASSOC)['count'] > 0; if ($exists) { http_response_code(409); echo json_encode([ 'error' => 'Location already exists', 'details' => 'A location with this name already exists', 'existing_loc_name' => $locName ]); return; } // Insert berdasarkan format original code $sql = "INSERT INTO tblocationName (loc_name, lat, lon, shapecolor, company, FullName) VALUES (?, ?, ?, ?, ?, ?)"; $params = [ $locName, // user_name format $txtLat, // latitude $txtLng, // longitude '1000', // shapecolor default $company, // company $name // FullName ]; // Debug: Log SQL query // error_log("TblocationName CREATE SQL: " . $sql); // error_log("TblocationName CREATE params: " . json_encode($params)); // Execute insert $stmt = $pdo->prepare($sql); $result = $stmt->execute($params); if (!$result) { error_log("TblocationName CREATE - Database insert failed for user: " . $user); http_response_code(500); echo json_encode([ 'error' => 'Failed to create location', 'details' => 'Database insert operation failed' ]); return; } // Verify insert berhasil $rowsAffected = $stmt->rowCount(); if ($rowsAffected === 0) { error_log("TblocationName CREATE - No rows affected for user: " . $user); http_response_code(500); echo json_encode([ 'error' => 'Location creation failed', 'details' => 'No database records were created' ]); return; } // Log successful creation untuk audit error_log("TblocationName CREATE - Location successfully created: " . $locName . " by user: " . $user . " from IP: " . SessionHelper::get_ip()); // Performance monitoring $endTime = microtime(true); $endMemory = memory_get_usage(true); $processingTime = round($endTime - $startTime, 2); $memoryUsed = round(($endMemory - $startMemory) / 1024 / 1024, 2); // Debug: Log performance metrics // error_log("TblocationName CREATE - Processing completed in {$processingTime}s, Memory: {$memoryUsed}MB"); // Return success response (format original: echo '1') http_response_code(201); echo json_encode([ 'success' => true, 'message' => 'Location created successfully', 'data' => [ 'loc_name' => $locName, 'lat' => $txtLat, 'lon' => $txtLng, 'shapecolor' => '1000', 'company' => $company, 'FullName' => $name ], 'original_response' => '1', // Sesuai original code 'processing_info' => [ 'processing_time' => $processingTime . " seconds", 'memory_usage' => $memoryUsed . " MB", 'user' => $user, 'ip_address' => SessionHelper::get_ip() ] ]); } /** * Handle UPDATE operations (PUT) * ============================== * Update existing location name * * Request Body: * { * "loc_name": "current_location_name", // Required untuk identify record * "user": "new_username", // Optional * "company": "new_company_name", // Optional * "name": "new_location_name", // Optional * "txt_lat": "new_latitude", // Optional * "txt_lng": "new_longitude" // Optional * } */ function handleUpdate($pdo, $user) { global $startTime, $startMemory; // Debug: Log update operation // error_log("TblocationName CRUD - UPDATE operation for user: " . $user); // Get request body $input = json_decode(file_get_contents('php://input'), true); if (!$input) { http_response_code(400); echo json_encode([ 'error' => 'Invalid JSON input', 'details' => 'Request body must be valid JSON' ]); return; } // Debug: Log request data // error_log("TblocationName UPDATE - Request data: " . json_encode($input)); // Validasi required field untuk identify record if (!isset($input['loc_name']) || trim($input['loc_name']) === '') { http_response_code(400); echo json_encode([ 'error' => 'Missing required field', 'details' => 'loc_name is required to identify the record to update', 'required_fields' => ['loc_name'] ]); return; } $currentLocName = trim($input['loc_name']); // Check if location exists $checkSql = "SELECT * FROM tblocationName WHERE loc_name = ?"; $checkStmt = $pdo->prepare($checkSql); $checkStmt->execute([$currentLocName]); $existingRecord = $checkStmt->fetch(PDO::FETCH_ASSOC); if (!$existingRecord) { http_response_code(404); echo json_encode([ 'error' => 'Location not found', 'details' => 'No location found with the specified loc_name', 'loc_name' => $currentLocName ]); return; } // Build update fields $updateFields = array(); $updateParams = array(); // Handle user dan name update (akan mengubah loc_name) if (isset($input['user']) && isset($input['name'])) { $newUser = trim($input['user']); $newName = trim($input['name']); if (!empty($newUser) && !empty($newName)) { $newLocName = $newUser . '_' . $newName; // Check if new loc_name already exists $checkNewSql = "SELECT COUNT(*) as count FROM tblocationName WHERE loc_name = ? AND loc_name != ?"; $checkNewStmt = $pdo->prepare($checkNewSql); $checkNewStmt->execute([$newLocName, $currentLocName]); $newExists = $checkNewStmt->fetch(PDO::FETCH_ASSOC)['count'] > 0; if ($newExists) { http_response_code(409); echo json_encode([ 'error' => 'New location name already exists', 'details' => 'A location with the new name already exists', 'new_loc_name' => $newLocName ]); return; } $updateFields[] = "loc_name = ?"; $updateParams[] = $newLocName; $updateFields[] = "FullName = ?"; $updateParams[] = $newName; } } else { // Handle individual updates if (isset($input['name']) && trim($input['name']) !== '') { $updateFields[] = "FullName = ?"; $updateParams[] = trim($input['name']); } } // Handle company update if (isset($input['company']) && trim($input['company']) !== '') { $updateFields[] = "company = ?"; $updateParams[] = trim($input['company']); } // Handle coordinate updates if (isset($input['txt_lat']) && trim($input['txt_lat']) !== '') { $txtLat = trim($input['txt_lat']); if (!is_numeric($txtLat)) { http_response_code(400); echo json_encode([ 'error' => 'Invalid latitude', 'details' => 'txt_lat must be numeric', 'received' => $txtLat ]); return; } $lat = (float)$txtLat; if ($lat < -90 || $lat > 90) { http_response_code(400); echo json_encode([ 'error' => 'Invalid latitude range', 'details' => 'Latitude must be between -90 and 90', 'received' => $lat ]); return; } $updateFields[] = "lat = ?"; $updateParams[] = $txtLat; } if (isset($input['txt_lng']) && trim($input['txt_lng']) !== '') { $txtLng = trim($input['txt_lng']); if (!is_numeric($txtLng)) { http_response_code(400); echo json_encode([ 'error' => 'Invalid longitude', 'details' => 'txt_lng must be numeric', 'received' => $txtLng ]); return; } $lng = (float)$txtLng; if ($lng < -180 || $lng > 180) { http_response_code(400); echo json_encode([ 'error' => 'Invalid longitude range', 'details' => 'Longitude must be between -180 and 180', 'received' => $lng ]); return; } $updateFields[] = "lon = ?"; $updateParams[] = $txtLng; } // Check if ada fields untuk update if (empty($updateFields)) { http_response_code(400); echo json_encode([ 'error' => 'No fields to update', 'details' => 'At least one field must be provided for update', 'available_fields' => ['user', 'company', 'name', 'txt_lat', 'txt_lng'] ]); return; } // Build dan execute update query $sql = "UPDATE tblocationName SET " . implode(', ', $updateFields) . " WHERE loc_name = ?"; $updateParams[] = $currentLocName; // Debug: Log SQL query // error_log("TblocationName UPDATE SQL: " . $sql); // error_log("TblocationName UPDATE params: " . json_encode($updateParams)); $stmt = $pdo->prepare($sql); $result = $stmt->execute($updateParams); if (!$result) { error_log("TblocationName UPDATE - Database update failed for user: " . $user); http_response_code(500); echo json_encode([ 'error' => 'Failed to update location', 'details' => 'Database update operation failed' ]); return; } // Verify update berhasil $rowsAffected = $stmt->rowCount(); if ($rowsAffected === 0) { http_response_code(404); echo json_encode([ 'error' => 'No changes made', 'details' => 'No records were updated (possibly no changes detected)', 'loc_name' => $currentLocName ]); return; } // Get updated record $finalLocName = isset($newLocName) ? $newLocName : $currentLocName; $getUpdatedSql = "SELECT * FROM tblocationName WHERE loc_name = ?"; $getUpdatedStmt = $pdo->prepare($getUpdatedSql); $getUpdatedStmt->execute([$finalLocName]); $updatedRecord = $getUpdatedStmt->fetch(PDO::FETCH_ASSOC); // Log successful update untuk audit error_log("TblocationName UPDATE - Location successfully updated: " . $finalLocName . " by user: " . $user . " from IP: " . SessionHelper::get_ip()); // Performance monitoring $endTime = microtime(true); $endMemory = memory_get_usage(true); $processingTime = round($endTime - $startTime, 2); $memoryUsed = round(($endMemory - $startMemory) / 1024 / 1024, 2); // Debug: Log performance metrics // error_log("TblocationName UPDATE - Processing completed in {$processingTime}s, Memory: {$memoryUsed}MB"); // Return success response http_response_code(200); echo json_encode([ 'success' => true, 'message' => 'Location updated successfully', 'data' => $updatedRecord, 'changes' => [ 'fields_updated' => count($updateFields), 'rows_affected' => $rowsAffected ], 'processing_info' => [ 'processing_time' => $processingTime . " seconds", 'memory_usage' => $memoryUsed . " MB", 'user' => $user, 'ip_address' => SessionHelper::get_ip() ] ]); } /** * Handle DELETE operations (DELETE) * ================================= * Delete location name by loc_name * * Request Body: * { * "loc_name": "location_name_to_delete" * } */ function handleDelete($pdo, $user) { global $startTime, $startMemory; // Debug: Log delete operation // error_log("TblocationName CRUD - DELETE operation for user: " . $user); // Get request body $input = json_decode(file_get_contents('php://input'), true); if (!$input) { http_response_code(400); echo json_encode([ 'error' => 'Invalid JSON input', 'details' => 'Request body must be valid JSON' ]); return; } // Debug: Log request data // error_log("TblocationName DELETE - Request data: " . json_encode($input)); // Validasi required field if (!isset($input['loc_name']) || trim($input['loc_name']) === '') { http_response_code(400); echo json_encode([ 'error' => 'Missing required field', 'details' => 'loc_name is required to identify the record to delete', 'required_fields' => ['loc_name'] ]); return; } $locName = trim($input['loc_name']); // Check if location exists dan get data sebelum delete $checkSql = "SELECT * FROM tblocationName WHERE loc_name = ?"; $checkStmt = $pdo->prepare($checkSql); $checkStmt->execute([$locName]); $existingRecord = $checkStmt->fetch(PDO::FETCH_ASSOC); if (!$existingRecord) { http_response_code(404); echo json_encode([ 'error' => 'Location not found', 'details' => 'No location found with the specified loc_name', 'loc_name' => $locName ]); return; } // Execute delete $sql = "DELETE FROM tblocationName WHERE loc_name = ?"; // Debug: Log SQL query // error_log("TblocationName DELETE SQL: " . $sql); // error_log("TblocationName DELETE params: " . json_encode([$locName])); $stmt = $pdo->prepare($sql); $result = $stmt->execute([$locName]); if (!$result) { error_log("TblocationName DELETE - Database delete failed for user: " . $user); http_response_code(500); echo json_encode([ 'error' => 'Failed to delete location', 'details' => 'Database delete operation failed' ]); return; } // Verify delete berhasil $rowsAffected = $stmt->rowCount(); if ($rowsAffected === 0) { http_response_code(404); echo json_encode([ 'error' => 'Location deletion failed', 'details' => 'No records were deleted', 'loc_name' => $locName ]); return; } // Log successful deletion untuk audit error_log("TblocationName DELETE - Location successfully deleted: " . $locName . " by user: " . $user . " from IP: " . SessionHelper::get_ip()); // Performance monitoring $endTime = microtime(true); $endMemory = memory_get_usage(true); $processingTime = round($endTime - $startTime, 2); $memoryUsed = round(($endMemory - $startMemory) / 1024 / 1024, 2); // Debug: Log performance metrics // error_log("TblocationName DELETE - Processing completed in {$processingTime}s, Memory: {$memoryUsed}MB"); // Return success response http_response_code(200); echo json_encode([ 'success' => true, 'message' => 'Location deleted successfully', 'deleted_data' => $existingRecord, 'changes' => [ 'rows_affected' => $rowsAffected ], 'processing_info' => [ 'processing_time' => $processingTime . " seconds", 'memory_usage' => $memoryUsed . " MB", 'user' => $user, 'ip_address' => SessionHelper::get_ip() ] ]); }