$error); $option_map = array(); $has_selection = false; foreach ($options as $option) { if ((string) $option['it_id'] !== (string) $item['it_id']) return array('error' => $error); if ((string) $option['io_type'] === '0') $has_selection = true; $key = $option['io_type'].':'.$option['io_id']; if (isset($option_map[$key])) return array('error' => $error); $option_map[$key] = $option; } $validated = array(); $quantities = array(); $base_qty = 0; $total = 0; foreach ($rows as $row) { if (!isset($row['io_id'], $row['io_type'], $row['ct_qty']) || !is_string($row['io_id']) || !(is_string($row['io_type']) || is_int($row['io_type'])) || !in_array((string) $row['io_type'], array('0', '1'), true) || !(is_string($row['ct_qty']) || is_int($row['ct_qty'])) || !preg_match('/^[1-9][0-9]*$/D', (string) $row['ct_qty']) || (float) $row['ct_qty'] > 2147483647) return array('error' => $error); $type = (int) $row['io_type']; if (!$validated && $type !== 0) return array('error' => $error); $id = $row['io_id']; $key = $type.':'.$id; if ($id === '') { if ($type !== 0 || $has_selection) return array('error' => $error); $price = 0; $stock = (int) $item['it_stock_qty']; } else { if (!isset($option_map[$key]) || empty($option_map[$key]['io_use'])) return array('error' => $error); $option = $option_map[$key]; $type = (int) $option['io_type']; $price = (int) $option['io_price']; $stock = (int) $option['io_stock_qty']; } $qty = (int) $row['ct_qty']; $quantities[$key] = isset($quantities[$key]) ? $quantities[$key] + $qty : $qty; if ($quantities[$key] > $stock) return array('error' => '상품 또는 옵션의 재고수량이 부족합니다.'); $unit_price = $type === 1 ? $price : (int) $item['it_price'] + $price; if ($unit_price < 0) return array('error' => $error); if ($check_price && (!isset($row['ct_price'], $row['io_price']) || (int) $row['ct_price'] !== (int) $item['it_price'] || (int) $row['io_price'] !== $price)) return array('error' => '상품 또는 옵션 금액이 변경되었습니다. 장바구니를 다시 확인해 주십시오.'); if ($type === 0) $base_qty += $qty; $row['io_type'] = $type; $row['io_price'] = $price; $row['ct_price'] = (int) $item['it_price']; $row['ct_qty'] = $qty; $validated[] = $row; $total += $unit_price * $qty; } if (!$base_qty || (!empty($item['it_buy_min_qty']) && $base_qty < $item['it_buy_min_qty']) || (!empty($item['it_buy_max_qty']) && $base_qty > $item['it_buy_max_qty'])) return array('error' => '상품의 선택옵션과 최소/최대 구매수량을 확인해 주십시오.'); return array('error' => '', 'rows' => $validated, 'total' => $total); } function shop_cart_option_data($it_id) { global $g5; $id = sql_escape_string($it_id); $item = sql_fetch(" select * from {$g5['g5_shop_item_table']} where it_id = '$id' "); $result = sql_query(" select * from {$g5['g5_shop_item_option_table']} where it_id = '$id' "); $options = array(); while ($row = sql_fetch_array($result)) $options[] = $row; return array($item, $options); } // 모든 상품을 먼저 검증한다. 바로구매/옵션수정의 선삭제와 다중 상품의 부분 저장을 막는다. function shop_validate_cart_request($post, $multi = false) { $error = '장바구니 요청 정보가 올바르지 않습니다.'; $products = array(); if (empty($post['it_id']) || !is_array($post['it_id']) || array_keys($post['it_id']) !== range(0, count($post['it_id']) - 1)) return array('error' => $error); foreach ($post['it_id'] as $i => $id) { if ($multi && empty($post['chk_it_id'][$i])) continue; if (!is_string($id) || $id === '' || safe_replace_regex($id, 'it_id') !== $id || isset($products[$id])) return array('error' => $error); foreach (array('io_id', 'io_type', 'ct_qty') as $field) { if (!isset($post[$field][$id]) || !is_array($post[$field][$id]) || !$post[$field][$id]) return array('error' => $error); } $keys = range(0, count($post['io_id'][$id]) - 1); foreach (array('io_id', 'io_type', 'ct_qty') as $field) { if (array_keys($post[$field][$id]) !== $keys) return array('error' => $error); } $rows = array(); foreach ($keys as $k) { $io_id = $post['io_id'][$id][$k]; if (!is_string($io_id) || preg_replace(G5_OPTION_ID_FILTER, '', $io_id) !== $io_id || (isset($post['io_value'][$id][$k]) && !is_string($post['io_value'][$id][$k]))) return array('error' => $error); $rows[] = array('io_id' => $io_id, 'io_type' => $post['io_type'][$id][$k], 'ct_qty' => $post['ct_qty'][$id][$k]); } list($item, $options) = shop_cart_option_data($id); $validated = shop_validate_cart_rows($item, $options, $rows); if ($validated['error'] !== '') return $validated; $validated['item'] = $item; $products[$id] = $validated; } return array('error' => $products ? '' : $error, 'products' => $products); } // 주문 준비/확정 시에는 선택된 행만 검증하여 보조옵션 단독 선택과 과거 조작 행도 차단한다. function shop_validate_order_cart($cart_id) { global $g5; $id = sql_escape_string($cart_id); $result = sql_query(" select * from {$g5['g5_shop_cart_table']} where od_id = '$id' and ct_select = '1' order by ct_id asc "); $products = array(); while ($row = sql_fetch_array($result)) { if ($row['ct_status'] !== '쇼핑') return '이미 처리되었거나 올바르지 않은 장바구니입니다.'; $products[$row['it_id']][] = $row; } if (!$products) return '주문하실 상품을 선택해 주십시오.'; foreach ($products as $it_id => $rows) { list($item, $options) = shop_cart_option_data($it_id); $validated = shop_validate_cart_rows($item, $options, $rows, true); if ($validated['error'] !== '') return $validated['error']; } return ''; }