PluginProbe ʕ •ᴥ•ʔ
Event Tickets with Ticket Scanner / 2.9.4
Event Tickets with Ticket Scanner v2.9.4
3.1.2 3.1.1 3.1.0 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.4 trunk 2.6.0 2.7.0 2.7.1 2.7.10 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.8.0 2.8.1 2.8.10 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.0 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 2.9.8 2.9.9 3.0.0 3.0.1 3.0.2 3.0.3
event-tickets-with-ticket-scanner / tests / TimezoneRedeemBlockingTest.php
event-tickets-with-ticket-scanner / tests Last commit date
bin 3 months ago fixtures 3 months ago AdminCodeCleanupAndPDFTest.php 3 months ago AdminCodesByProductTest.php 3 months ago AdminCustomerNameTest.php 3 months ago AdminErrorLogTest.php 3 months ago AdminFormatWarningTest.php 3 months ago AdminListAndCodeOpsTest.php 3 months ago AdminListQueryTest.php 3 months ago AdminMetaAndErrorTest.php 3 months ago AdminOptionsAndMigrationTest.php 3 months ago AdminOrderInfoTest.php 3 months ago AdminRedeemAmountTest.php 3 months ago AdminRestrictionAndRstrTest.php 3 months ago AdminSettingsAndDatepickerTest.php 3 months ago AdminSettingsCodeTest.php 3 months ago AdminTicketInfoTest.php 3 months ago AdminTimezoneAndMiscTest.php 3 months ago AdminWCCodeOpsTest.php 3 months ago AuthtokenAccessTest.php 3 months ago AuthtokenCRUDTest.php 3 months ago AuthtokenEditAndRemoveTest.php 3 months ago AuthtokenTest.php 3 months ago BaseLimitsTest.php 3 months ago CartCodeRestrictionAndAssignTest.php 3 months ago CartMetaAndBeforeCartTest.php 3 months ago CartValidationTest.php 3 months ago ContextWizardTest.php 3 months ago CoreAlignAndSearchTest.php 3 months ago CoreCodeOpsAndDBLogTest.php 3 months ago CoreDecodeAndReplaceTest.php 3 months ago CoreEncodeMetaTest.php 3 months ago CoreExpiredAndRegisteredTest.php 3 months ago CoreMetaAndUrlTest.php 3 months ago CoreMetaObjectStructureTest.php 3 months ago CoreMetaTest.php 3 months ago CoreMethodsTest.php 3 months ago CoreOrderAndIPTest.php 3 months ago CoreParserAndQueryTest.php 3 months ago CoreParserURLAndMergePDFTest.php 3 months ago CoreReplaceAndExpireTest.php 3 months ago CoreTicketIdAndExpirationTest.php 3 months ago CoreTicketIdAndUrlTest.php 3 months ago CoreTicketURLComponentsTest.php 3 months ago CountRedeemsTodayTest.php 3 months ago CronjobTest.php 3 months ago DBOperationsTest.php 3 months ago DBSanitizeAndQueryTest.php 3 months ago DBSanitizeTest.php 3 months ago DBTablesAndUpdateTest.php 3 months ago DatabaseTest.php 3 months ago DateCalcAndCorrectProductTest.php 3 months ago DaychooserTest.php 3 months ago EmailHandlerTest.php 3 months ago EmailOrderMetaAndAttachmentsTest.php 3 months ago ErrorLogAndSanitizeTest.php 3 months ago EventTimeWindowTest.php 3 months ago FrontendCheckCodeTest.php 3 months ago FrontendCountConfirmedTest.php 3 months ago FrontendExecuteJSONAndCheckCodeTest.php 3 months ago FrontendIsUsedAndOptionsTest.php 3 months ago FrontendMarkUsedTest.php 3 months ago FrontendValidationTest.php 3 months ago FullTicketFlowTest.php 3 months ago HelpersTest.php 3 months ago ListManagementTest.php 3 months ago MaxRedeemPerDayTest.php 3 months ago MessengerAndRESTEndpointsTest.php 3 months ago MessengerTypeCheckTest.php 3 months ago OldPremiumGuardTest.php 3 months ago OneTimeUseTest.php 3 months ago OptionsChangeAndLoadTest.php 3 months ago OptionsDeleteAndResetTest.php 3 months ago OptionsExportImportTest.php 3 months ago OptionsFormatsTest.php 3 months ago OptionsHistoryTest.php 3 months ago OptionsMigrationTest.php 3 months ago OptionsResetAndFormatTest.php 3 months ago OptionsTest.php 3 months ago OrderDeleteAndRefundDeleteTest.php 3 months ago OrderMetaKeyValueDisplayTest.php 3 months ago OrderStatusHandlerTest.php 3 months ago OrderTicketGenerationTest.php 3 months ago OrderTicketQueryTest.php 3 months ago PDFAndQRConfigTest.php 3 months ago PDFMergeAndPWAServiceWorkerTest.php 3 months ago PDFSettersTest.php 3 months ago PDFSettingsTest.php 3 months ago PDFUtilsTest.php 3 months ago PWAManifestAndSessionTest.php 3 months ago PartialRefundAndCodeCleanupTest.php 3 months ago PluginInitAndShortcodeTest.php 3 months ago ProductSettingsTest.php 3 months ago QRCodeAndDesignerTest.php 3 months ago QRPDFAndBadgePDFTest.php 3 months ago RESTRoutesAndPingTest.php 3 months ago RefundTest.php 3 months ago RestApiTest.php 3 months ago RestApiTicketTest.php 3 months ago ScannerBoilerplateAndFormatWarningsTest.php 3 months ago SeatingBlockTest.php 3 months ago SeatingCoordinatorTest.php 3 months ago SeatingExportTest.php 3 months ago SeatingMetaTest.php 3 months ago SeatingPlanCRUDTest.php 3 months ago SeatingPlanTest.php 3 months ago SeatingSeatCRUDTest.php 3 months ago SetupWizardTest.php 3 months ago ShortcodeAndCartCheckTest.php 3 months ago ShortcodeAndCodesDisplayTest.php 3 months ago ShortcodesAndCodeListTest.php 3 months ago StaticDateAndTimeTest.php 3 months ago StaticHelpersAndMessengerTest.php 3 months ago StaticUtilMethodsTest.php 3 months ago TicketBadgeTemplateTest.php 3 months ago TicketCalcDateTest.php 3 months ago TicketDesignerAndBadgeTest.php 3 months ago TicketDesignerTemplateTest.php 3 months ago TicketDesignerTest.php 3 months ago TicketDisplayTest.php 3 months ago TicketExpirationAndICSTest.php 3 months ago TicketLabelAndDisplayTest.php 3 months ago TicketLabelsAndStaticsTest.php 3 months ago TicketQRSettersTest.php 3 months ago TicketRedeemTest.php 3 months ago TicketRoutingTest.php 3 months ago TicketScannerMethodsTest.php 3 months ago TicketSettersAndOrderTest.php 3 months ago TicketUtilAndICSTest.php 3 months ago TicketUtilMethodsTest.php 3 months ago TicketWPMLAndSubscriptionTest.php 3 months ago TimezoneRedeemBlockingTest.php 3 months ago UrlParsingTest.php 3 months ago VariationTicketTest.php 3 months ago WCBaseMetaConstantsTest.php 3 months ago WCCheckoutCartFlowTest.php 3 months ago WCEmailAttachmentTest.php 3 months ago WCFrontendAjaxAndDatepickerTest.php 3 months ago WCFrontendCartHandlerTest.php 3 months ago WCFrontendCartHandlersTest.php 3 months ago WCFrontendCartTest.php 3 months ago WCFrontendCartValidationTest.php 3 months ago WCFrontendHandlersTest.php 3 months ago WCFrontendLabelsTest.php 3 months ago WCFrontendMethodsTest.php 3 months ago WCOrderDeleteTest.php 3 months ago WCOrderDisplayMetaTest.php 3 months ago WCOrderHasTicketsTest.php 3 months ago WCOrderHooksTest.php 3 months ago WCOrderItemMetaDisplayTest.php 3 months ago WCOrderItemOpsTest.php 3 months ago WCOrderLifecycleTest.php 3 months ago WCOrderMethodsTest.php 3 months ago WCOrderTicketDetectionTest.php 3 months ago WCOrderTicketNumberTest.php 3 months ago WCProductAndVariationTest.php 3 months ago WCProductColumnsTest.php 3 months ago WCProductConfigAndColumnsTest.php 3 months ago WCProductIsTicketAndListsTest.php 3 months ago WCProductMetaSaveTest.php 3 months ago WCProductMethodsTest.php 3 months ago WCProductTabsAndSideBoxTest.php 3 months ago WCProductTicketTest.php 3 months ago WebhooksAndMigrationTest.php 3 months ago bootstrap.php 3 months ago composer.json 3 months ago phpunit.xml 3 months ago test-premium-compat.sh 3 months ago
TimezoneRedeemBlockingTest.php
196 lines
1 <?php
2 /**
3 * Tests that ticket timestamps respect the WordPress timezone setting.
4 *
5 * Bug: strtotime() interprets local dates as UTC (because WordPress sets
6 * date_default_timezone_set('UTC')). The fix uses DateTime with wp_timezone()
7 * to correctly interpret admin-entered dates in the WordPress timezone.
8 */
9
10 class TimezoneRedeemBlockingTest extends WP_UnitTestCase {
11
12 private $main;
13 private $original_timezone;
14
15 public function set_up(): void {
16 parent::set_up();
17 $this->main = sasoEventtickets::Instance();
18
19 if (!class_exists('WC_Product_Simple')) {
20 $this->markTestSkipped('WooCommerce not available');
21 }
22
23 // Save original timezone
24 $this->original_timezone = get_option('timezone_string');
25 }
26
27 public function tear_down(): void {
28 // Restore original timezone
29 if (!empty($this->original_timezone)) {
30 update_option('timezone_string', $this->original_timezone);
31 } else {
32 delete_option('timezone_string');
33 }
34 parent::tear_down();
35 }
36
37 private function createProductWithDates(
38 string $startDate,
39 string $startTime = '',
40 string $endDate = '',
41 string $endTime = ''
42 ): int {
43 $product = new WC_Product_Simple();
44 $product->set_name('TZ Test Product ' . uniqid());
45 $product->set_regular_price('10.00');
46 $product->set_status('publish');
47 $product->save();
48 $productId = $product->get_id();
49
50 update_post_meta($productId, 'saso_eventtickets_is_ticket', 'yes');
51 update_post_meta($productId, 'saso_eventtickets_ticket_start_date', $startDate);
52 if (!empty($startTime)) {
53 update_post_meta($productId, 'saso_eventtickets_ticket_start_time', $startTime);
54 }
55 if (!empty($endDate)) {
56 update_post_meta($productId, 'saso_eventtickets_ticket_end_date', $endDate);
57 }
58 if (!empty($endTime)) {
59 update_post_meta($productId, 'saso_eventtickets_ticket_end_time', $endTime);
60 }
61
62 return $productId;
63 }
64
65 // ── Timestamp correctness with non-UTC timezone ─────────────
66
67 public function test_start_timestamp_respects_positive_timezone(): void {
68 // Berlin = UTC+1 (winter) / UTC+2 (summer)
69 // 2026-01-15 is winter → UTC+1
70 update_option('timezone_string', 'Europe/Berlin');
71
72 $productId = $this->createProductWithDates('2026-01-15', '19:00:00');
73 $ticket = $this->main->getTicketHandler();
74 $result = $ticket->calcDateStringAllowedRedeemFrom($productId);
75
76 // 19:00 Berlin (UTC+1) = 18:00 UTC
77 $expected = gmmktime(18, 0, 0, 1, 15, 2026);
78 $this->assertEquals($expected, $result['ticket_start_date_timestamp'],
79 '19:00 Europe/Berlin should be 18:00 UTC');
80 }
81
82 public function test_start_timestamp_respects_negative_timezone(): void {
83 // São Paulo = UTC-3
84 update_option('timezone_string', 'America/Sao_Paulo');
85
86 $productId = $this->createProductWithDates('2026-01-15', '19:00:00');
87 $ticket = $this->main->getTicketHandler();
88 $result = $ticket->calcDateStringAllowedRedeemFrom($productId);
89
90 // 19:00 São Paulo (UTC-3) = 22:00 UTC
91 $expected = gmmktime(22, 0, 0, 1, 15, 2026);
92 $this->assertEquals($expected, $result['ticket_start_date_timestamp'],
93 '19:00 America/Sao_Paulo should be 22:00 UTC');
94 }
95
96 public function test_end_timestamp_respects_timezone(): void {
97 update_option('timezone_string', 'America/Sao_Paulo');
98
99 $productId = $this->createProductWithDates('2026-01-15', '19:00:00', '2026-01-15', '23:00:00');
100 $ticket = $this->main->getTicketHandler();
101 $result = $ticket->calcDateStringAllowedRedeemFrom($productId);
102
103 // 23:00 São Paulo (UTC-3) = 02:00 UTC next day
104 $expected = gmmktime(2, 0, 0, 1, 16, 2026);
105 $this->assertEquals($expected, $result['ticket_end_date_timestamp'],
106 '23:00 America/Sao_Paulo should be 02:00 UTC next day');
107 }
108
109 public function test_utc_timezone_unchanged(): void {
110 update_option('timezone_string', 'UTC');
111
112 $productId = $this->createProductWithDates('2026-06-15', '10:00:00');
113 $ticket = $this->main->getTicketHandler();
114 $result = $ticket->calcDateStringAllowedRedeemFrom($productId);
115
116 $expected = gmmktime(10, 0, 0, 6, 15, 2026);
117 $this->assertEquals($expected, $result['ticket_start_date_timestamp'],
118 'UTC timezone should produce unchanged timestamp');
119 }
120
121 // ── Parsed components still match local time ────────────────
122
123 public function test_parsed_hour_shows_local_time(): void {
124 update_option('timezone_string', 'America/Sao_Paulo');
125
126 $productId = $this->createProductWithDates('2026-01-15', '19:30:00');
127 $ticket = $this->main->getTicketHandler();
128 $result = $ticket->calcDateStringAllowedRedeemFrom($productId);
129
130 // wp_date() formats in local timezone, so parsed components should show 19:30
131 $this->assertEquals('19', $result['ticket_start_p_hour']);
132 $this->assertEquals('30', $result['ticket_start_p_min']);
133 }
134
135 public function test_parsed_date_shows_local_date(): void {
136 update_option('timezone_string', 'America/Sao_Paulo');
137
138 $productId = $this->createProductWithDates('2026-01-15', '19:00:00');
139 $ticket = $this->main->getTicketHandler();
140 $result = $ticket->calcDateStringAllowedRedeemFrom($productId);
141
142 $this->assertEquals('15', $result['ticket_start_p_date']);
143 $this->assertEquals('01', $result['ticket_start_p_month']);
144 $this->assertEquals('2026', $result['ticket_start_p_year']);
145 }
146
147 // ── DST handling ────────────────────────────────────────────
148
149 public function test_summer_time_offset_differs_from_winter(): void {
150 update_option('timezone_string', 'Europe/Berlin');
151
152 // Winter: 2026-01-15 → UTC+1
153 $winterProd = $this->createProductWithDates('2026-01-15', '12:00:00');
154 // Summer: 2026-07-15 → UTC+2
155 $summerProd = $this->createProductWithDates('2026-07-15', '12:00:00');
156
157 $ticket = $this->main->getTicketHandler();
158 $winterResult = $ticket->calcDateStringAllowedRedeemFrom($winterProd);
159 $summerResult = $ticket->calcDateStringAllowedRedeemFrom($summerProd);
160
161 // Winter 12:00 Berlin = 11:00 UTC
162 $expectedWinter = gmmktime(11, 0, 0, 1, 15, 2026);
163 // Summer 12:00 Berlin = 10:00 UTC
164 $expectedSummer = gmmktime(10, 0, 0, 7, 15, 2026);
165
166 $this->assertEquals($expectedWinter, $winterResult['ticket_start_date_timestamp'],
167 'Winter: 12:00 Berlin should be 11:00 UTC');
168 $this->assertEquals($expectedSummer, $summerResult['ticket_start_date_timestamp'],
169 'Summer: 12:00 Berlin should be 10:00 UTC');
170 }
171
172 // ── Redeem blocking uses correct timestamp ──────────────────
173
174 public function test_future_event_not_blocked_in_negative_tz(): void {
175 update_option('timezone_string', 'America/Sao_Paulo');
176
177 // Event far in the future — should never be "too late"
178 $productId = $this->createProductWithDates('2030-06-15', '19:00:00', '2030-06-15', '23:00:00');
179 $ticket = $this->main->getTicketHandler();
180 $result = $ticket->calcDateStringAllowedRedeemFrom($productId);
181
182 $this->assertFalse($result['redeem_allowed_too_late']);
183 }
184
185 public function test_past_event_blocked_in_negative_tz(): void {
186 update_option('timezone_string', 'America/Sao_Paulo');
187
188 // Event in the past
189 $productId = $this->createProductWithDates('2020-01-01', '10:00:00', '2020-01-01', '22:00:00');
190 $ticket = $this->main->getTicketHandler();
191 $result = $ticket->calcDateStringAllowedRedeemFrom($productId);
192
193 $this->assertTrue($result['redeem_allowed_too_late']);
194 }
195 }
196