PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.4
Yatra – Travel Booking & Tour Operator Software v3.0.4
3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 2.0.10 2.0.11 All 82 releases
yatra / app / Repositories / DiscountRepository.php

DiscountRepository.php in Yatra – Travel Booking & Tour Operator Software 3.0.4, at app/Repositories/DiscountRepository.php

200 lines 5.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Yatra\Repositories;
6
7 use Yatra\Database\Tables\DiscountsTable;
8
9 /**
10 * Discount Repository
11 * Handles database operations for discounts
12 */
13 class DiscountRepository extends BaseRepository
14 {
15 protected function getTableName(): string
16 {
17 return DiscountsTable::getTableName();
18 }
19
20 /**
21 * Strip unknown keys (e.g. created_by_name) before wpdb writes.
22 * Never allow updating the primary key from payloads.
23 *
24 * @param array<string, mixed> $data
25 * @return array<string, mixed>
26 */
27 private function filterToWritableDiscountColumnsForInsert(array $data): array
28 {
29 unset($data['id']);
30
31 return array_intersect_key($data, array_flip(DiscountsTable::getWritableColumnNames()));
32 }
33
34 /**
35 * @param array<string, mixed> $data
36 * @return array<string, mixed>
37 */
38 private function filterToWritableDiscountColumnsForUpdate(array $data): array
39 {
40 unset($data['id']);
41 $allowed = array_values(array_diff(
42 DiscountsTable::getWritableColumnNames(),
43 ['created_at', 'created_by']
44 ));
45
46 return array_intersect_key($data, array_flip($allowed));
47 }
48
49 public function update(int $id, array $data): bool
50 {
51 return parent::update($id, $this->filterToWritableDiscountColumnsForUpdate($data));
52 }
53
54 public function create(array $data): int
55 {
56 return parent::create($this->filterToWritableDiscountColumnsForInsert($data));
57 }
58
59 public function findByCode(string $code): ?\stdClass
60 {
61 $table = esc_sql($this->table);
62 $result = $this->wpdb->get_row(
63 $this->wpdb->prepare(
64 "SELECT * FROM `{$table}` WHERE code = %s",
65 $code
66 )
67 );
68 return $result ?: null;
69 }
70
71 public function getByStatus(string $status, array $args = []): array
72 {
73 $args['where']['status'] = $status;
74 return $this->all($args);
75 }
76
77 public function getByType(string $type, array $args = []): array
78 {
79 $args['where']['type'] = $type;
80 return $this->all($args);
81 }
82
83 public function search(string $search_term, array $args = []): array
84 {
85 $table = esc_sql($this->table);
86 $search_term = '%' . esc_like($search_term) . '%';
87
88 $where_conditions = ["(`code` LIKE %s OR `description` LIKE %s)"];
89 $where_values = [$search_term, $search_term];
90
91 if (isset($args['where'])) {
92 foreach ($args['where'] as $key => $value) {
93 $key = preg_replace('/[^a-zA-Z0-9_]/', '', $key); // Sanitize column name
94 $where_conditions[] = "`{$key}` = %s";
95 $where_values[] = $value;
96 }
97 }
98
99 $where_clause = 'WHERE ' . implode(' AND ', $where_conditions);
100 $order = $this->buildOrderClause($args);
101 $limit = $this->buildLimitClause($args);
102
103 $query = $this->wpdb->prepare(
104 "SELECT * FROM `{$table}` {$where_clause} {$order} {$limit}",
105 ...$where_values
106 );
107
108 return $this->wpdb->get_results($query) ?: [];
109 }
110
111 /**
112 * Get all active group discounts
113 *
114 * @return array Array of group discount objects
115 */
116 public function getActiveGroupDiscounts(): array
117 {
118 global $wpdb;
119 $table = $this->getTableName();
120 $today = date('Y-m-d');
121
122 // Query for active group discounts applicable to this trip
123 // Check both is_group_discount=1 OR discount_mode IN ('group', 'both') for backward compatibility
124 // Status: admin UI uses "publish"; legacy rows may use "active" as live (see DiscountService::isLive).
125 $query = "SELECT * FROM `{$table}`
126 WHERE (is_group_discount = 1 OR discount_mode IN ('group', 'both'))
127 AND status IN ('publish', 'active')";
128
129 return $wpdb->get_results($query) ?: [];
130 }
131
132 /**
133 * Count how many bookings have used a specific discount code
134 *
135 * @param string $code Discount code
136 * @return int Number of bookings that used this code
137 */
138 public function countUsage(string $code): int
139 {
140 global $wpdb;
141
142 // Try new bookings table first, then fallback to old table
143 $bookingsTable = $wpdb->prefix . 'yatra_new_bookings';
144 $tableExists = $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $bookingsTable));
145
146 if (!$tableExists) {
147 $bookingsTable = $wpdb->prefix . 'yatra_bookings';
148 }
149
150 $count = $wpdb->get_var(
151 $wpdb->prepare(
152 "SELECT COUNT(*) FROM `{$bookingsTable}`
153 WHERE discount_code = %s
154 AND status NOT IN ('cancelled', 'failed')",
155 $code
156 )
157 );
158
159 return (int) ($count ?? 0);
160 }
161
162 /**
163 * Status counts for admin toolbar (matches wp_yatra_new_discounts.status values).
164 *
165 * @return array{all: int, publish: int, draft: int, trash: int, expired: int}
166 */
167 public function getAdminStatusCounts(): array
168 {
169 $table = esc_sql($this->table);
170 $all = (int) $this->wpdb->get_var("SELECT COUNT(*) FROM `{$table}`");
171
172 $rows = $this->wpdb->get_results(
173 "SELECT `status`, COUNT(*) AS c FROM `{$table}` GROUP BY `status`"
174 ) ?: [];
175
176 $map = [
177 'publish' => 0,
178 'draft' => 0,
179 'trash' => 0,
180 'expired' => 0,
181 ];
182
183 foreach ($rows as $row) {
184 $st = (string) ($row->status ?? '');
185 if (isset($map[$st])) {
186 $map[$st] = (int) $row->c;
187 }
188 }
189
190 return [
191 'all' => $all,
192 'publish' => $map['publish'],
193 'draft' => $map['draft'],
194 'trash' => $map['trash'],
195 'expired' => $map['expired'],
196 ];
197 }
198 }
199
200