PluginProbe
VikBooking Hotel Booking Engine & PMS / trunk
VikBooking Hotel Booking Engine & PMS vtrunk
1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 All 36 releases
vikbooking / site / controllers / checkin.php

checkin.php in VikBooking Hotel Booking Engine & PMS trunk, at site/controllers/checkin.php

286 lines 10.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage com_vikbooking
5 * @author Alessio Gaggii - E4J srl
6 * @copyright Copyright (C) 2025 E4J srl. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 * @link https://vikwp.com
9 */
10
11 // No direct access to this file
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 /**
15 * VikBooking check-in controller.
16 *
17 * @since 1.17.4 (J) - 1.7.4 (WP)
18 */
19 class VikBookingControllerCheckin extends JControllerAdmin
20 {
21 /**
22 * AJAX endpoint for storing a customer signature during pre-checkin.
23 * Endpoint originally introduced for the PaxField of type "signature".
24 */
25 public function saveSignature()
26 {
27 $app = JFactory::getApplication();
28 $dbo = JFactory::getDbo();
29
30 if (!JSession::checkToken()) {
31 // missing CSRF-proof token
32 VBOHttpDocument::getInstance($app)->close(403, JText::translate('JINVALID_TOKEN'));
33 }
34
35 // gather request values
36 $sid = $app->input->getAlnum('sid', '');
37 $ts = $app->input->getUInt('ts', 0);
38 $pad_ratio = $app->input->getUInt('pad_ratio', 1);
39 $pad_width = $app->input->getUInt('pad_width', 0);
40 $signature = $app->input->get('signature', '', 'raw');
41
42 if (empty($signature)) {
43 VBOHttpDocument::getInstance($app)->close(400, 'Missing signature image data');
44 }
45
46 // get the booking record involved
47 $dbo->setQuery(
48 $dbo->getQuery(true)
49 ->select('*')
50 ->from($dbo->qn('#__vikbooking_orders'))
51 ->where($dbo->qn('ts') . ' = ' . $ts)
52 ->where($dbo->qn('status') . ' = ' . $dbo->q('confirmed'))
53 ->andWhere([
54 $dbo->qn('sid') . ' = ' . $dbo->q($sid),
55 $dbo->qn('idorderota') . ' = ' . $dbo->q($sid),
56 ])
57 );
58
59 $booking = $dbo->loadObject();
60
61 if (!$booking) {
62 VBOHttpDocument::getInstance($app)->close(404, 'Booking not found');
63 }
64
65 // get the customer record involved
66 $customer = VikBooking::getCPinInstance()->getCustomerFromBooking($booking->id);
67
68 if (!$customer) {
69 VBOHttpDocument::getInstance($app)->close(404, 'Customer not found');
70 }
71
72 // get signature image data
73 $signature_data = '';
74 $img_type = '';
75 if (preg_match("/^data:image\/(png|jpe?g|svg);base64,([A-Za-z0-9\/=+]+)$/", $signature, $safe_match)) {
76 $signature_data = base64_decode($safe_match[2]);
77 $img_type = $safe_match[1];
78 }
79
80 if (empty($signature_data)) {
81 VBOHttpDocument::getInstance($app)->close(500, 'Unexpected signature image data format');
82 }
83
84 // store image data
85 $sign_fname = implode('_', [$booking->id, $sid, $customer['id']]) . '.' . $img_type;
86 $file_path = implode(DIRECTORY_SEPARATOR, [VBO_ADMIN_PATH, 'resources', 'idscans', $sign_fname]);
87 $file_uri = VBO_ADMIN_URI . 'resources/idscans/' . $sign_fname;
88 if (!JFile::write($file_path, $signature_data)) {
89 VBOHttpDocument::getInstance($app)->close(500, 'Could not store the signature image data');
90 }
91
92 // update the customer signature on the db
93 $dbo->setQuery(
94 $dbo->getQuery(true)
95 ->update($dbo->qn('#__vikbooking_customers_orders'))
96 ->set($dbo->qn('signature') . ' = ' . $dbo->q($sign_fname))
97 ->where($dbo->qn('idorder') . ' = ' . (int) $booking->id)
98 );
99 $dbo->execute();
100
101 // resize image for screens with high resolution (retina)
102 if ($pad_ratio > 1 && $pad_width) {
103 $new_width = floor(($pad_width / 2));
104 (new VikResizer)->proportionalImage($file_path, $file_path, $new_width, $new_width);
105 }
106
107 if (VBOPlatformDetection::isWordPress()) {
108 // trigger file mirroring
109 VikBookingLoader::import('update.manager');
110 VikBookingUpdateManager::triggerUploadBackup($file_path);
111 }
112
113 // send response to output
114 VBOHttpDocument::getInstance($app)->json([
115 'signatureFileUri' => $file_uri,
116 'signatureFileName' => $sign_fname,
117 ]);
118 }
119
120 /**
121 * AJAX endpoint for validating fields during pre-checkin before submission.
122 *
123 * @since 1.17.7 (J) - 1.7.7 (WP)
124 */
125 public function validatePrecheckinFields()
126 {
127 $app = JFactory::getApplication();
128 $dbo = JFactory::getDbo();
129
130 if (!JSession::checkToken()) {
131 // missing CSRF-proof token
132 VBOHttpDocument::getInstance($app)->close(403, JText::translate('JINVALID_TOKEN'));
133 }
134
135 // gather request values
136 $sid = $app->input->getAlnum('sid', '');
137 $ts = $app->input->getUInt('ts', 0);
138 $guests = $app->input->get('guests', [], 'array');
139
140 // get the booking record involved
141 $dbo->setQuery(
142 $dbo->getQuery(true)
143 ->select('*')
144 ->from($dbo->qn('#__vikbooking_orders'))
145 ->where($dbo->qn('ts') . ' = ' . $ts)
146 ->where($dbo->qn('status') . ' = ' . $dbo->q('confirmed'))
147 ->andWhere([
148 $dbo->qn('sid') . ' = ' . $dbo->q($sid),
149 $dbo->qn('idorderota') . ' = ' . $dbo->q($sid),
150 ])
151 );
152
153 $booking = $dbo->loadObject();
154
155 if (!$booking) {
156 VBOHttpDocument::getInstance($app)->close(404, 'Booking not found');
157 }
158
159 // get booking rooms data
160 $booking_rooms = VikBooking::loadOrdersRoomsData($booking->id);
161
162 // get the customer record involved
163 $customer = VikBooking::getCPinInstance()->getCustomerFromBooking($booking->id);
164
165 if (!$customer) {
166 VBOHttpDocument::getInstance($app)->close(404, 'Customer not found');
167 }
168
169 // validate guests registration fields
170 if (!$guests) {
171 VBOHttpDocument::getInstance($app)->close(500, 'Missing guest fields for validation.');
172 }
173
174 // access pax fields registration object
175 $pax_fields_obj = VBOCheckinPax::getInstance();
176
177 try {
178 // let the driver perform the fields validation
179 $pax_fields_obj->validateRegistrationFieldTypes((array) $booking, $booking_rooms, $guests);
180 } catch (Exception $e) {
181 // raise an error
182 VBOHttpDocument::getInstance($app)->close($e->getCode() ?: 500, $e->getMessage());
183 }
184
185 // send successful response to output
186 VBOHttpDocument::getInstance($app)->json(['success' => 1]);
187 }
188
189 /**
190 * AJAX endpoint that serves as an helper method for pax-field-type objects
191 * to perform specific operations during the pre-check-in of a booking reference.
192 *
193 * @since 1.18.0 (J) - 1.8.0 (WP)
194 */
195 public function invokePaxFieldType()
196 {
197 $app = JFactory::getApplication();
198 $dbo = JFactory::getDbo();
199
200 if (!JSession::checkToken()) {
201 // missing CSRF-proof token
202 VBOHttpDocument::getInstance($app)->close(403, JText::translate('JINVALID_TOKEN'));
203 }
204
205 // gather booking and pax-field request values
206 $sid = $app->input->getAlnum('sid', '');
207 $ts = $app->input->getUInt('ts', 0);
208 $type = $app->input->getString('type', '');
209 $call = $app->input->getString('call', '');
210 $data = $app->input->get('data', [], 'array');
211
212 if (!$type) {
213 VBOHttpDocument::getInstance($app)->close(400, 'Missing pax field type identifier.');
214 }
215
216 if (!$call) {
217 VBOHttpDocument::getInstance($app)->close(400, 'Missing pax field type call operation.');
218 }
219
220 // get the booking record involved
221 $dbo->setQuery(
222 $dbo->getQuery(true)
223 ->select('*')
224 ->from($dbo->qn('#__vikbooking_orders'))
225 ->where($dbo->qn('ts') . ' = ' . $ts)
226 ->where($dbo->qn('status') . ' = ' . $dbo->q('confirmed'))
227 ->andWhere([
228 $dbo->qn('sid') . ' = ' . $dbo->q($sid),
229 $dbo->qn('idorderota') . ' = ' . $dbo->q($sid),
230 ])
231 );
232
233 $booking = $dbo->loadObject();
234
235 if (!$booking) {
236 VBOHttpDocument::getInstance($app)->close(404, 'Booking not found');
237 }
238
239 // get booking rooms data
240 $booking_rooms = VikBooking::loadOrdersRoomsData($booking->id);
241
242 if (!$booking_rooms) {
243 VBOHttpDocument::getInstance($app)->close(500, 'Invalid booking structure');
244 }
245
246 // get the customer record involved to ensure pre-check-in operations are safe
247 $customer = VikBooking::getCPinInstance()->getCustomerFromBooking($booking->id);
248
249 if (!$customer) {
250 VBOHttpDocument::getInstance($app)->close(404, 'Customer not found');
251 }
252
253 // access pax fields registration object
254 $pax_fields_obj = VBOCheckinPax::getInstance();
255
256 // find the first pax field key of this type
257 $pax_field_key = $pax_fields_obj->getFieldTypeKey($type);
258
259 if (!$pax_field_key) {
260 VBOHttpDocument::getInstance($app)->close(404, 'Unknown pax field type');
261 }
262
263 // get an instance of the requested VBOCheckinPaxfield object
264 $pax_field_obj = $pax_fields_obj->getField($pax_field_key);
265
266 // set known object data
267 $pax_field_obj->setBooking((array) $booking)
268 ->setBookingRooms($booking_rooms);
269
270 // get the field implementor
271 $implementor = $pax_fields_obj->getFieldTypeImplementor($pax_field_obj);
272
273 if (!method_exists($implementor, $call) || !is_callable([$implementor, $call])) {
274 VBOHttpDocument::getInstance($app)->close(403, 'Un-callable pax field value');
275 }
276
277 try {
278 // send successful response to output by executing the request pax-field type method
279 VBOHttpDocument::getInstance($app)->json($implementor->{$call}($data));
280 } catch (Exception $e) {
281 // propagate the error
282 VBOHttpDocument::getInstance($app)->close($e->getCode() ?: 500, $e->getMessage());
283 }
284 }
285 }
286