PluginProbe ʕ •ᴥ•ʔ
Event Tickets with Ticket Scanner / 3.1.2
Event Tickets with Ticket Scanner v3.1.2
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 / sasoEventtickets_TicketBadge.php
event-tickets-with-ticket-scanner Last commit date
3rd 1 week ago css 1 week ago img 1 week ago includes 1 week ago js 1 week ago languages 1 week ago ticket 1 week ago vendors 1 week ago SASO_EVENTTICKETS.php 1 week ago backend.js 1 week ago changelog-features.json 1 week ago changelog.txt 1 week ago db.php 1 week ago index.php 1 week ago init_file.php 1 week ago order_details.js 1 week ago pwa-sw.js 1 week ago readme.txt 1 week ago saso-eventtickets-validator.js 1 week ago sasoEventtickets_AdminSettings.php 1 week ago sasoEventtickets_Authtoken.php 1 week ago sasoEventtickets_Base.php 1 week ago sasoEventtickets_Core.php 1 week ago sasoEventtickets_Frontend.php 1 week ago sasoEventtickets_Messenger.php 1 week ago sasoEventtickets_Options.php 1 week ago sasoEventtickets_PDF.php 1 week ago sasoEventtickets_Seating.php 1 week ago sasoEventtickets_Ticket.php 1 week ago sasoEventtickets_TicketBadge.php 1 week ago sasoEventtickets_TicketDesigner.php 1 week ago sasoEventtickets_TicketQR.php 1 week ago ticket_events.js 1 week ago ticket_scanner.js 1 week ago validator.js 1 week ago version-notices.json 1 week ago vollstart-cross-promo.php 1 week ago wc_backend.js 1 week ago wc_frontend.js 1 week ago woocommerce-hooks.php 1 week ago
sasoEventtickets_TicketBadge.php
462 lines
1 <?php
2 include_once(plugin_dir_path(__FILE__)."init_file.php");
3 class sasoEventtickets_TicketBadge {
4 private $MAIN;
5
6 private $codeObj;
7
8 private $html;
9 private $size_width;
10 private $size_height;
11
12 private $filepath = "";
13
14 private $date_time_format;
15
16 public static function Instance($html="") {
17 static $inst = null;
18 if ($inst === null) {
19 $inst = new self($html);
20 }
21 return $inst;
22 }
23
24 public function __construct($html="") {
25 global $sasoEventtickets;
26 $this->MAIN = $sasoEventtickets;
27 }
28
29 private function setTemplate($html) {
30 $this->html = trim($html);
31 return $this;
32 }
33
34 public function getTemplate() {
35 if (empty($this->html)) {
36 return $this->getDefaultTemplate();
37 }
38 return $this->html;
39 }
40
41 public function getDefaultTemplate() {
42 $html = '
43 <b>{OPTIONS.wcTicketHeading}</b>
44 <h2>{PRODUCT.name}</h2>
45 <b>{TICKET.PRODUCT.ticket_start_date}</b>
46 <h4>{ORDER.billing.first_name} {ORDER.billing.last_name}</h4>
47 <br><center>{QRCODE_INLINE}</center>
48 <br>{TICKET.code_display}
49 <br>{TICKET.meta.wc_ticket._public_ticket_id}
50 ';
51 return $html;
52 }
53
54 /**
55 * Single source of truth for the available replacement tags, grouped.
56 * Used both for the help text (getReplacementTagsExplanation) and the
57 * visual editor tag picker (vtext option type).
58 *
59 * @return array<int, array{group:string, tags:array<int,string>}>
60 */
61 public function getReplacementTags(): array {
62 $groups = [];
63 $groups[] = ['group' => 'Special', 'tags' => ['{QRCODE_INLINE}']];
64 $groups[] = ['group' => 'TICKET', 'tags' => [
65 '{TICKET.id}', '{TICKET.time}', '{TICKET.code}', '{TICKET.code_display}', '{TICKET.cvv}',
66 ]];
67
68 $metaTags = [];
69 $metaObj = $this->MAIN->getCore()->getMetaObject();
70 foreach ($metaObj as $key => $value) {
71 $name = 'TICKET.meta.' . $key;
72 if (is_array($value)) {
73 foreach ($value as $k => $v) {
74 $metaTags[] = '{' . $name . '.' . $k . '}';
75 }
76 }
77 }
78 if ($metaTags) {
79 $groups[] = ['group' => 'TICKET meta', 'tags' => $metaTags];
80 }
81
82 $groups[] = ['group' => 'Order', 'tags' => [
83 '{ORDER.id}', '{ORDER.formatted_order_total}', '{ORDER.cart_tax}', '{ORDER.currency}',
84 '{ORDER.item_count}', '{ORDER.item_total}', '{ORDER.items}', '{ORDER.coupon_codes}',
85 '{ORDER.shipping_method}', '{ORDER.shipping_to_display}', '{ORDER.date.created}',
86 '{ORDER.date.paid}', '{ORDER.date.completed}', '{ORDER.customer_id}', '{ORDER.user_id}',
87 '{ORDER.customer_ip_address}', '{ORDER.customer_note}', '{ORDER.billing.first_name}',
88 '{ORDER.billing.last_name}', '{ORDER.billing.company}', '{ORDER.billing.address_1}',
89 '{ORDER.billing.address_2}', '{ORDER.billing.city}', '{ORDER.billing.state}',
90 '{ORDER.billing.postcode}', '{ORDER.billing.country}', '{ORDER.billing.email}',
91 '{ORDER.billing.phone}', '{ORDER.shipping_address}', '{ORDER.formatted_billing_full_name}',
92 '{ORDER.formatted_shipping_full_name}', '{ORDER.formatted_billing_address}',
93 '{ORDER.formatted_shipping_address}', '{ORDER.payment_method}', '{ORDER.payment_method_title}',
94 '{ORDER.transaction_id}', '{ORDER.status}',
95 ]];
96
97 $groups[] = ['group' => 'Product', 'tags' => [
98 '{PRODUCT.id}', '{PRODUCT.name}', '{PRODUCT.slug}', '{PRODUCT.date.created}',
99 '{PRODUCT.date.modified}', '{PRODUCT.status}', '{PRODUCT.description}',
100 '{PRODUCT.short_description}', '{PRODUCT.sku}', '{PRODUCT.price}', '{PRODUCT.regular_price}',
101 '{PRODUCT.sale_price}', '{PRODUCT.stock_quantity}', '{PRODUCT.categories}', '{PRODUCT.average_rating}',
102 ]];
103
104 return $groups;
105 }
106
107 public function getReplacementTagsExplanation() {
108 $text = "Values from the <b>option</b> area can be referenced with the mentioned tag next to the label of the option.<br>";
109 $text .= "{QRCODE_INLINE} = add the public ticket number as a QR Code.<br>";
110 foreach ($this->getReplacementTags() as $g) {
111 if ($g['group'] === 'Special') continue; // QRCODE_INLINE already explained above
112 $text .= '<b>' . esc_html($g['group']) . '</b><ul>';
113 foreach ($g['tags'] as $tag) {
114 $text .= '<li>' . esc_html($tag) . '</li>';
115 if ($tag === '{ORDER.items}') {
116 $text .= "<li><i>Use the loop to access the items. e.g. '&lt;ul>{{LOOP ORDER.items AS item}} &lt;li>{item.quantity} x {item.name}&lt;/li> {{LOOPEND}}&lt;/ul>'</i></li>";
117 }
118 }
119 $text .= '</ul>';
120 if ($g['group'] === 'Order') {
121 $text .= "<p>If you need a meta value of the order, like an additional field. Get the field name and create the code like this: {ORDER.get_meta.YOURFIELDNAME}.<br>This will call the get_meta('YOURFIELDNAME').</p>";
122 }
123 }
124 return $text;
125 }
126
127 public function setHTMLAndRender($codeObj, $html_to_render, $width=0, $height=0, $filemode="I") {
128 $this->setHTMLToRender($codeObj, $html_to_render, $width, $height);
129 return $this->renderPDF($filemode);
130 }
131
132 public function downloadPDFTicketBadge($codeObj) {
133 $html = $this->MAIN->getOptions()->getOptionValue("wcTicketBadgeText", "");
134 $w = $this->MAIN->getOptions()->getOptionValue("wcTicketBadgeSizeWidth", 0);
135 $h = $this->MAIN->getOptions()->getOptionValue("wcTicketBadgeSizeHeight", 0);
136 $this->setHTMLAndRender($codeObj, $html, $w, $h);
137 exit;
138 }
139 public function getPDFTicketBadgeFilepath($codeObj, $filepath) {
140 $this->filepath = trim($filepath);
141 $html = $this->MAIN->getOptions()->getOptionValue("wcTicketBadgeText", "");
142 $w = $this->MAIN->getOptions()->getOptionValue("wcTicketBadgeSizeWidth", 0);
143 $h = $this->MAIN->getOptions()->getOptionValue("wcTicketBadgeSizeHeight", 0);
144 return $this->setHTMLAndRender($codeObj, $html, $w, $h, "F");
145 }
146
147 private function setHTMLToRender($codeObj, $html_to_render, $width=0, $height=0) {
148 $this->codeObj = $codeObj;
149 $this->setTemplate($html_to_render);
150 $this->size_width = intval($width);
151 $this->size_height = intval($height);
152 }
153
154 private function renderPDF($filemode="I") {
155 $metaObj = $this->MAIN->getCore()->encodeMetaValuesAndFillObject($this->codeObj['meta'], $this->codeObj);
156 $ticket_id = $this->MAIN->getCore()->getTicketId($this->codeObj, $metaObj);
157 $qr_content = $this->MAIN->getCore()->getQRCodeContent($this->codeObj, $metaObj);
158
159 $width = $this->size_width > 0 ? $this->size_width : 80;
160 $height = $this->size_height > 0 ? $this->size_height : 120;
161
162 $html = $this->replacePlaceholder();
163
164 $pdf = $this->MAIN->getNewPDFObject();
165 $pdf->setFilemode($filemode);
166
167 $pdf->setFilepath($this->filepath);
168 $filename = "ticketbadge_".$this->codeObj['order_id']."_".$ticket_id.".pdf";
169 $pdf->setFilename($filename);
170
171 $pdf->setQRParams(['style'=>['position'=>'C'],'align'=>'N']);
172 $qr_code_size = intval($this->MAIN->getOptions()->getOptionValue("wcTicketBadgeQRSize", 0));
173 if ($qr_code_size > 0) {
174 $pdf->setQRParams(['size'=>['width'=>$qr_code_size, 'height'=>$qr_code_size]]);
175 }
176
177 if($this->MAIN->getOptions()->isOptionCheckboxActive('wcTicketBadgePDFisRTL')) {
178 $pdf->setRTL(true);
179 }
180 if ($pdf->isRTL()) {
181 $lg = Array();
182 $lg['a_meta_charset'] = 'UTF-8';
183 $lg['a_meta_dir'] = 'rtl';
184 $lg['a_meta_language'] = 'fa';
185 $lg['w_page'] = 'page';
186 // set some language-dependent strings (optional)
187 $pdf->setLanguageArray($lg);
188 $pdf->setQRParams(['style'=>['position'=>'T'],'align'=>'T']);
189 }
190
191 $product_id = intval($metaObj['woocommerce']['product_id']);
192
193 // Background color (as fallback when no image or to fill gaps)
194 $wcTicketPDFBackgroundColor = $this->MAIN->getOptions()->getOptionValue('wcTicketPDFBackgroundColor');
195 if (!empty($wcTicketPDFBackgroundColor)) {
196 $pdf->setBackgroundColor($wcTicketPDFBackgroundColor);
197 }
198
199 $wcTicketBadgeBG = $this->MAIN->getAdmin()->getOptionValue('wcTicketBadgeBG');
200 $wcTicketBadgeBG = apply_filters( $this->MAIN->_add_filter_prefix.'wcTicketBadgeBG', $wcTicketBadgeBG, $product_id);
201 if (!empty($wcTicketBadgeBG) && intval($wcTicketBadgeBG) >0) {
202 $mediaData = SASO_EVENTTICKETS::getMediaData($wcTicketBadgeBG);
203 if ($this->MAIN->getOptions()->isOptionCheckboxActive('wcTicketCompatibilityUseURL')) {
204 if (!empty($mediaData['url'])) {
205 $pdf->setBackgroundImage($mediaData['url']);
206 }
207 } else {
208 if (!empty($mediaData['for_pdf'])) {
209 $pdf->setBackgroundImage($mediaData['for_pdf']);
210 }
211 }
212 }
213
214 $pdf->addPart($html);
215 $qrTicketPDFPadding = intval($this->MAIN->getOptions()->getOptionValue('qrTicketPDFPadding'));
216 $pdf->setQRCodeContent(["text"=>$qr_content, "style"=>["vpadding"=>$qrTicketPDFPadding, "hpadding"=>$qrTicketPDFPadding]]);
217 $pdf->setSize($width, $height);
218 $pdf->render();
219 if ($pdf->getFilemode() == "F") {
220 return $pdf->getFullFilePath();
221 } else {
222 exit;
223 }
224 }
225
226 private function getPurchasedItemFromOderOnTicket($order) {
227 $codeObj = $this->codeObj;
228 $metaObj = $this->MAIN->getCore()->encodeMetaValuesAndFillObject($codeObj['meta'], $codeObj);
229
230 if ($order == null) {
231 $order_id = intval($codeObj['order_id']);
232 $order = wc_get_order($order_id);
233 }
234
235 $ret = [];
236 if ($order != null) {
237 if (count($order->get_items()) > 1) {
238 foreach ( $order->get_items() as $item_id => $item ) {
239 if ($item_id == $metaObj['woocommerce']['item_id']) continue;
240 $product_id = $item->get_product_id();
241 $ret[] = $item;
242 }
243 }
244 }
245 return $ret;
246 }
247
248 private function replacePlaceholder() {
249 $codeObj = $this->codeObj;
250 $order = null;
251
252 $html = " ".trim($this->getTemplate());
253
254 $is_expired = $this->MAIN->getCore()->checkCodeExpired($codeObj);
255 $this->date_time_format = $this->MAIN->getOptions()->getOptionDateTimeFormat();
256 $date_format = $this->MAIN->getOptions()->getOptionDateFormat();
257 $time_format = $this->MAIN->getOptions()->getOptionTimeFormat();
258
259 while(true) {
260 $loop = $this->MAIN->getCore()->parser_search_loop($html);
261 if ($loop !== false) {
262 // replace loop part with the actual values
263 $loop_text = "";
264 if (strtolower($loop['collection']) == "order.items") {
265 if ($order == null) {
266 $order_id = intval($codeObj['order_id']);
267 $order = wc_get_order($order_id);
268 }
269 $items = $this->getPurchasedItemFromOderOnTicket($order);
270 // iterate over items
271 foreach($items as $item) {
272 // create text for the items
273 $loop_text .= $this->replaceProductTemplateTags($item, $loop["loop_part"], $loop["item_var"]);
274 }
275 }
276 // replace loop with generated text
277 $html = str_replace($loop["found_str"], $loop_text, $html);
278 } else {
279 break;
280 }
281 }
282
283 $matches = [];
284 if (preg_match_all('/\{OPTIONS\..*?\}/', $html, $matches)) {
285 foreach($matches[0] as $item) {
286 $key = substr(substr($item, 9), 0, -1);
287 $value = $this->MAIN->getOptions()->getOptionValue($key, "");
288 $html = str_replace($item, $value, $html);
289 }
290 }
291
292 $metaObj = null;
293 $product = null;
294
295 if (!empty($html) && strpos($html, "{SITE_URL}")) $html = str_replace("{SITE_URL}", site_url(), $html);
296 if (!empty($html) && strpos($html, "{TICKET.")) {
297 $metaObj = $this->MAIN->getCore()->encodeMetaValuesAndFillObject($codeObj['meta'], $codeObj);
298 $codeObj['metaObj'] = $metaObj;
299
300 $product_id = intval($metaObj['woocommerce']['product_id']);
301 $product = wc_get_product( $product_id );
302 $is_variation = $product->get_type() == "variation" ? true : false;
303 $product_parent = $product;
304 $product_parent_id = $product->get_parent_id();
305
306 $saso_eventtickets_is_date_for_all_variants = true;
307 if ($is_variation && $product_parent_id > 0) {
308 $product_parent = wc_get_product( $product_parent_id );
309 $saso_eventtickets_is_date_for_all_variants = get_post_meta( $product_parent->get_id(), 'saso_eventtickets_is_date_for_all_variants', true ) == "yes" ? true : false;
310 }
311 $product_for_dates = $product_parent;
312 if (!$saso_eventtickets_is_date_for_all_variants) $product_for_dates = $product; // unter Umständen die Variante
313 $product_dates = $this->MAIN->getTicketHandler()->calcDateStringAllowedRedeemFrom($product_for_dates->get_id(), $codeObj);
314
315 $matches = [];
316 if (preg_match_all('/\{TICKET\.PRODUCT\..*?\}/', $html, $matches)) {
317 foreach($matches[0] as $item) {
318 $key = substr(substr($item, 16), 0, -1);
319 $value = $this->getValueOfArrayByPlaceholder($key, $product_dates);
320 if (!empty($value)) {
321 // Use date_i18n with gmt=true - ticket dates are stored in local time, gmt=true prevents timezone conversion but translates month/day names
322 if ($key == "ticket_start_date" || $key == "ticket_end_date") {
323 $value = date_i18n($date_format, strtotime($value), true);
324 }
325 if ($key == "ticket_start_time" || $key == "ticket_end_time") {
326 $value = date_i18n($date_format, strtotime($product_dates['ticket_start_date']." ".$value), true);
327 }
328 }
329 $html = str_replace($item, wp_kses_post($value), $html);
330 }
331 }
332
333 $matches = [];
334 if (preg_match_all('/\{TICKET\.meta\..*?\}/', $html, $matches)) {
335 foreach($matches[0] as $item) {
336 $key = substr(substr($item, 8), 0, -1);
337 $value = $this->getValueOfArrayByPlaceholder($key, $metaObj);
338 $html = str_replace($item, wp_kses_post($value), $html);
339 }
340 }
341
342 $cobj = $codeObj;
343 $cobj['meta'] = $metaObj; // if special meta values are needed . ticket.meta.....
344 $matches = [];
345 if (preg_match_all('/\{TICKET\..*?\}/', $html, $matches)) {
346 foreach($matches[0] as $item) {
347 $key = substr(substr($item, 8), 0, -1);
348 $value = $this->getValueOfArrayByPlaceholder($key, $codeObj);
349 $html = str_replace($item, wp_kses_post($value), $html);
350 }
351 }
352 }
353
354 if (!empty($html) && strpos($html, "{ORDER.")) {
355 if ($order == null) {
356 $order_id = intval($codeObj['order_id']);
357 $order = wc_get_order($order_id);
358 }
359 if ($order != null) {
360 $matches = [];
361 if (preg_match_all('/\{ORDER\..*?\}/', $html, $matches)) {
362 foreach($matches[0] as $item) {
363 $key = substr(substr($item, 7), 0, -1);
364 if (is_array($order) && isset($order[$key])) {
365 $value = $this->getValueOfArrayByPlaceholder($key, $order);
366 } else {
367 $value = $this->getValueOfWCObject($key, $order);
368 }
369 if ($key == "date.paid" || $key == "date.completed" || $key == "date.created") {
370 $value = wp_date($this->date_time_format, strtotime($value));
371 }
372 $html = str_replace($item, wp_kses_post($value), $html);
373 }
374 }
375 }
376 }
377 if (!empty($html) && strpos($html, "{PRODUCT.")) {
378 if ($product == null) {
379 if ($metaObj == null) {
380 $metaObj = $this->MAIN->getCore()->encodeMetaValuesAndFillObject($codeObj['meta'], $codeObj);
381 }
382 $product_id = intval($metaObj['woocommerce']['product_id']);
383 $product = wc_get_product( $product_id );
384 }
385 $html = $this->setProductValues($product, $html);
386 }
387
388 return trim($html);
389 }
390
391 private function setProductValues($product, $html, $pattern='PRODUCT') {
392 if ($product != null) {
393 $html = $this->replaceProductTemplateTags($product, $html, $pattern);
394 }
395 return $html;
396 }
397
398 private function replaceProductTemplateTags($product, $html, $pattern) {
399 $len_pattern = strlen($pattern) + 2;
400 $matches = [];
401 if (preg_match_all('/\{'.$pattern.'\..*?\}/', $html, $matches)) {
402 foreach($matches[0] as $item) {
403 $key = substr(substr($item, $len_pattern), 0, -1);
404 $value = $this->getValueOfWCObject($key, $product);
405 if ($key == "date.modified" || $key == "date.created") {
406 $value = wp_date($this->date_time_format, strtotime($value));
407 }
408 $html = str_replace($item, wp_kses_post($value), $html);
409 }
410 }
411 return $html;
412 }
413
414 private function getValueOfArrayByPlaceholder($key, $object) {
415 $value = "";
416 $parts = explode(".", $key);
417 $obj = $object;
418 foreach($parts as $part) {
419 if (isset($obj[$part])) {
420 $obj = $obj[$part];
421 $value = $obj;
422 }
423 }
424 if (is_array($value)) {
425 $value = $this->MAIN->getCore()->json_encode_with_error_handling($value);
426 }
427 return $value;
428 }
429
430 private function getValueOfWCObject($key, $object) {
431 if (method_exists($object, "get_id")) {
432 $product_original_id = $this->MAIN->getTicketHandler()->getWPMLProductId($object->get_id());
433 $product_original = null;
434 if ($product_original_id != $object->get_id()) {
435 $product_original = $this->MAIN->getTicketHandler()->get_product($product_original_id);
436 }
437 if ($product_original != null) {
438 $object = $product_original;
439 }
440 }
441
442 $value = "";
443 $method = "get_".str_replace(".", "_", $key);
444 //if (method_exists($object, $method) && is_callable($object, $method)) {
445 if (method_exists($object, $method)) {
446 $value = $object->$method();
447 if (is_array($value)) {
448 $value = join(", ", $value);
449 }
450 } else {
451 $teile = explode(".", $key);
452 if (count($teile) > 1) { // min 2 elemente
453 if ($teile[0] == "get_meta") {
454 $value = $object->get_meta($teile[1]);
455 }
456 }
457 }
458 return $value;
459 }
460
461 }
462 ?>