db = $db; } public function listForAdmin( array $filters = [], string $sortColumn = 'name', string $sortDir = 'ASC', int $page = 1, int $perPage = 15 ): array { $allowedSortColumns = [ 'id' => 'st.id', 'name' => 'st.name', 'status' => 'st.status', 'cost' => 'st.cost', 'max_wp' => 'st.max_wp', 'default' => 'st.default', 'o' => 'st.o', ]; $sortSql = $allowedSortColumns[$sortColumn] ?? 'st.name'; $sortDir = strtoupper(trim($sortDir)) === 'DESC' ? 'DESC' : 'ASC'; $page = max(1, $page); $perPage = min(self::MAX_PER_PAGE, max(1, $perPage)); $offset = ($page - 1) * $perPage; $where = ['1 = 1']; $params = []; $name = trim((string)($filters['name'] ?? '')); if ($name !== '') { if (strlen($name) > 255) { $name = substr($name, 0, 255); } $where[] = 'st.name LIKE :name'; $params[':name'] = '%' . $name . '%'; } $status = trim((string)($filters['status'] ?? '')); if ($status === '0' || $status === '1') { $where[] = 'st.status = :status'; $params[':status'] = (int)$status; } $whereSql = implode(' AND ', $where); $sqlCount = " SELECT COUNT(0) FROM pp_shop_transports AS st WHERE {$whereSql} "; $stmtCount = $this->db->query($sqlCount, $params); $countRows = $stmtCount ? $stmtCount->fetchAll() : []; $total = isset($countRows[0][0]) ? (int)$countRows[0][0] : 0; $sql = " SELECT st.id, st.name, st.name_visible, st.description, st.status, st.cost, st.max_wp, st.default, st.apilo_carrier_account_id, st.delivery_free, st.o FROM pp_shop_transports AS st WHERE {$whereSql} ORDER BY {$sortSql} {$sortDir}, st.id ASC LIMIT {$perPage} OFFSET {$offset} "; $stmt = $this->db->query($sql, $params); $items = $stmt ? $stmt->fetchAll() : []; if (!is_array($items)) { $items = []; } foreach ($items as &$item) { $item = $this->normalizeTransport($item); } unset($item); return [ 'items' => $items, 'total' => $total, ]; } public function find(int $transportId): ?array { if ($transportId <= 0) { return null; } $transport = $this->db->get('pp_shop_transports', '*', ['id' => $transportId]); if (!is_array($transport)) { return null; } $transport = $this->normalizeTransport($transport); $paymentMethods = $this->db->select( 'pp_shop_transport_payment_methods', 'id_payment_method', ['id_transport' => $transportId] ); $transport['payment_methods'] = is_array($paymentMethods) ? $paymentMethods : []; return $transport; } public function save(array $data): ?int { $transportId = isset($data['id']) ? (int)$data['id'] : 0; $name = trim((string)($data['name'] ?? '')); $nameVisible = trim((string)($data['name_visible'] ?? '')); $description = trim((string)($data['description'] ?? '')); $status = $this->toSwitchValue($data['status'] ?? 0); $cost = isset($data['cost']) ? (float)$data['cost'] : 0.0; $maxWp = isset($data['max_wp']) && $data['max_wp'] !== '' ? (int)$data['max_wp'] : null; $default = $this->toSwitchValue($data['default'] ?? 0); $apiloCarrierAccountId = isset($data['apilo_carrier_account_id']) && $data['apilo_carrier_account_id'] !== '' ? (int)$data['apilo_carrier_account_id'] : null; $deliveryFree = $this->toSwitchValue($data['delivery_free'] ?? 0); $paymentMethods = $data['payment_methods'] ?? []; if ($default === 1) { $this->db->update('pp_shop_transports', ['default' => 0]); } $transportData = [ 'name' => $name, 'name_visible' => $nameVisible, 'description' => $description, 'status' => $status, 'default' => $default, 'cost' => $cost, 'max_wp' => $maxWp, 'apilo_carrier_account_id' => $apiloCarrierAccountId, 'delivery_free' => $deliveryFree, ]; if (!$transportId) { $this->db->insert('pp_shop_transports', $transportData); $id = $this->db->id(); if ($id) { $this->savePaymentMethodLinks((int)$id, $paymentMethods); return (int)$id; } return null; } else { $this->db->update('pp_shop_transports', $transportData, ['id' => $transportId]); $this->db->delete('pp_shop_transport_payment_methods', ['id_transport' => $transportId]); $this->savePaymentMethodLinks($transportId, $paymentMethods); return $transportId; } } public function allActive(): array { $transports = $this->db->select( 'pp_shop_transports', '*', [ 'status' => 1, 'ORDER' => ['o' => 'ASC'], ] ); if (!is_array($transports)) { return []; } foreach ($transports as &$transport) { $transport = $this->normalizeTransport($transport); } unset($transport); return $transports; } public function findActiveById(int $transportId): ?array { if ($transportId <= 0) { return null; } $transport = $this->db->get( 'pp_shop_transports', '*', ['AND' => ['id' => $transportId, 'status' => 1]] ); if (!$transport) { return null; } return $this->normalizeTransport($transport); } public function getApiloCarrierAccountId(int $transportId): ?int { if ($transportId <= 0) { return null; } $result = $this->db->get( 'pp_shop_transports', 'apilo_carrier_account_id', ['id' => $transportId] ); return $result !== null ? (int)$result : null; } public function getTransportCost(int $transportId): ?float { if ($transportId <= 0) { return null; } $result = $this->db->get( 'pp_shop_transports', 'cost', ['AND' => ['id' => $transportId, 'status' => 1]] ); return $result !== null ? (float)$result : null; } public function lowestTransportPrice(int $wp): ?float { $result = $this->db->get( 'pp_shop_transports', 'cost', [ 'AND' => [ 'status' => 1, 'id' => [2, 4, 6, 8, 9], 'max_wp[>=]' => $wp ], 'ORDER' => ['cost' => 'ASC'] ] ); return $result !== null ? (float)$result : null; } public function allForAdmin(): array { $transports = $this->db->select( 'pp_shop_transports', '*', ['ORDER' => ['o' => 'ASC']] ); if (!is_array($transports)) { return []; } foreach ($transports as &$transport) { $transport = $this->normalizeTransport($transport); } unset($transport); return $transports; } private function savePaymentMethodLinks(int $transportId, $paymentMethods): void { if (is_array($paymentMethods)) { foreach ($paymentMethods as $paymentMethodId) { $this->db->insert('pp_shop_transport_payment_methods', [ 'id_payment_method' => (int)$paymentMethodId, 'id_transport' => $transportId, ]); } } elseif ($paymentMethods) { $this->db->insert('pp_shop_transport_payment_methods', [ 'id_payment_method' => (int)$paymentMethods, 'id_transport' => $transportId, ]); } } private function normalizeTransport(array $transport): array { $transport['id'] = isset($transport['id']) ? (int)$transport['id'] : 0; $transport['status'] = $this->toSwitchValue($transport['status'] ?? 0); $transport['default'] = $this->toSwitchValue($transport['default'] ?? 0); $transport['delivery_free'] = $this->toSwitchValue($transport['delivery_free'] ?? 0); $transport['cost'] = isset($transport['cost']) ? (float)$transport['cost'] : 0.0; $transport['max_wp'] = isset($transport['max_wp']) && $transport['max_wp'] !== null ? (int)$transport['max_wp'] : null; $transport['apilo_carrier_account_id'] = isset($transport['apilo_carrier_account_id']) && $transport['apilo_carrier_account_id'] !== null ? (int)$transport['apilo_carrier_account_id'] : null; $transport['o'] = isset($transport['o']) ? (int)$transport['o'] : 0; return $transport; } private function toSwitchValue($value): int { if (is_bool($value)) { return $value ? 1 : 0; } if (is_numeric($value)) { return ((int)$value) === 1 ? 1 : 0; } if (is_string($value)) { $normalized = strtolower(trim($value)); return in_array($normalized, ['1', 'on', 'true', 'yes'], true) ? 1 : 0; } return 0; } }