PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.7
Yatra – Travel Booking & Tour Operator Software v3.0.7
3.0.15 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 All 83 releases
yatra / app / Repositories / DiscountRepository.php

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

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