PluginProbe ʕ •ᴥ•ʔ
Event Tickets with Ticket Scanner / 2.8.3
Event Tickets with Ticket Scanner v2.8.3
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 / index.php
event-tickets-with-ticket-scanner Last commit date
3rd 5 months ago css 5 months ago img 5 months ago includes 5 months ago js 5 months ago languages 5 months ago ticket 5 months ago vendors 5 months ago .gitignore 5 months ago SASO_EVENTTICKETS.php 5 months ago backend.js 5 months ago changelog.txt 5 months ago db.php 5 months ago index.php 5 months ago init_file.php 5 months ago order_details.js 5 months ago readme.txt 5 months ago saso-eventtickets-validator.js 5 months ago sasoEventtickets_AdminSettings.php 5 months ago sasoEventtickets_Authtoken.php 5 months ago sasoEventtickets_Base.php 5 months ago sasoEventtickets_Core.php 5 months ago sasoEventtickets_Frontend.php 5 months ago sasoEventtickets_Messenger.php 5 months ago sasoEventtickets_Options.php 5 months ago sasoEventtickets_PDF.php 5 months ago sasoEventtickets_Seating.php 5 months ago sasoEventtickets_Ticket.php 5 months ago sasoEventtickets_TicketBadge.php 5 months ago sasoEventtickets_TicketDesigner.php 5 months ago sasoEventtickets_TicketQR.php 5 months ago ticket_events.js 5 months ago ticket_scanner.js 5 months ago validator.js 5 months ago wc_backend.js 5 months ago wc_frontend.js 5 months ago woocommerce-hooks.php 5 months ago
index.php
1572 lines
1 <?php
2 /**
3 * Plugin Name: Event Tickets with Ticket Scanner
4 * Plugin URI: https://vollstart.com/event-tickets-with-ticket-scanner/docs/
5 * Description: You can create and generate tickets and codes. You can redeem the tickets at entrance using the built-in ticket scanner. You customer can download a PDF with the ticket information. The Premium allows you also to activate user registration and more. This allows your user to register them self to a ticket.
6 * Version: 2.8.3
7 * Author: Vollstart
8 * Author URI: https://vollstart.com
9 * Text Domain: event-tickets-with-ticket-scanner
10 *
11 * Event Tickets with Ticket Scanner is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16 // https://semver.org/
17 // https://developer.wordpress.org/plugins/security/securing-output/
18 // https://developer.wordpress.org/plugins/security/securing-input/
19
20 include_once(plugin_dir_path(__FILE__)."init_file.php");
21
22 if (!defined('SASO_EVENTTICKETS_PLUGIN_VERSION'))
23 define('SASO_EVENTTICKETS_PLUGIN_VERSION', '2.8.3');
24 if (!defined('SASO_EVENTTICKETS_PLUGIN_DIR_PATH'))
25 define('SASO_EVENTTICKETS_PLUGIN_DIR_PATH', plugin_dir_path(__FILE__));
26
27 include_once plugin_dir_path(__FILE__)."SASO_EVENTTICKETS.php";
28
29 class sasoEventtickets_fakeprem{}
30 class sasoEventtickets {
31 private $_js_version;
32 private $_js_file = 'saso-eventtickets-validator.js';
33 public $_js_nonce = 'sasoEventtickets';
34 public $_do_action_prefix = 'saso_eventtickets_';
35 public $_add_filter_prefix = 'saso_eventtickets_';
36 protected $_prefix = 'sasoEventtickets';
37 public $_prefix_session = 'sasoEventtickets_';
38 protected $_shortcode = 'sasoEventTicketsValidator';
39 protected $_shortcode_mycode = 'sasoEventTicketsValidator_code';
40 protected $_shortcode_eventviews = 'sasoEventTicketsValidator_eventsview';
41 protected $_shortcode_ticket_scanner = 'sasoEventTicketsValidator_ticket_scanner';
42 protected $_shortcode_feature_list = 'sasoEventTicketsValidator_feature_list';
43 protected $_divId = 'sasoEventtickets';
44
45 private $_isPrem = null;
46 private $_premium_plugin_name = 'event-tickets-with-ticket-scanner-premium';
47 private $_premium_function_file = 'sasoEventtickets_PremiumFunctions.php';
48 private $PREMFUNCTIONS = null;
49 private $BASE = null;
50 private $CORE = null;
51 private $ADMIN = null;
52 private $FRONTEND = null;
53 private $OPTIONS = null;
54
55 private $isAllowedAccess = null;
56
57 public static function Instance() {
58 static $inst = null;
59 if ($inst === null) {
60 $inst = new self();
61 }
62 return $inst;
63 }
64
65 public function __construct() {
66 $this->_js_version = $this->getPluginVersion();
67 $this->initHandlers();
68 }
69
70 public function initHandlers() {
71 add_action( 'init', [$this, 'load_plugin_textdomain'] );
72 add_action( 'upgrader_process_complete', [$this, 'listener_upgrader_process_complete'], 10, 2 );
73 //add_action('admin_init', [$this, 'initialize_plugin']);
74 if (is_admin()) { // called in backend admin, admin-ajax!
75 $this->init_backend();
76 } else { // called in front end
77 $this->init_frontend();
78 }
79 add_action( 'sasoEventtickets_cronjob_daily', [$this, 'relay_sasoEventtickets_cronjob_daily'], 10, 0 ); // set in tickets.php
80 add_action( 'plugins_loaded', [$this, 'WooCommercePluginLoaded'], 20, 0 );
81 if (basename($_SERVER['SCRIPT_NAME']) == "admin-ajax.php") {
82 add_action('wp_ajax_nopriv_'.$this->_prefix.'_executeFrontend', [$this,'executeFrontend_a'], 10, 0); // nicht angemeldete user, sollen eine antwort erhalten
83 add_action('wp_ajax_'.$this->_prefix.'_executeFrontend', [$this,'executeFrontend_a'], 10, 0); // falls eingeloggt ist
84 add_action('wp_ajax_'.$this->_prefix.'_executeWCBackend', [$this,'executeWCBackend'], 10, 0); // falls eingeloggt ist
85 add_action('wp_ajax_'.$this->_prefix.'_downloadMyCodesAsPDF', [$this,'downloadMyCodesAsPDF'], 10, 0); // logged in users only
86 }
87 if (method_exists($this->getPremiumFunctions(), "initHandlers")) {
88 $this->getPremiumFunctions()->initHandlers();
89 }
90 $this->cronjob_daily_activate();
91 }
92 public function cronjob_daily_activate() {
93 $args = [];
94 if (! wp_next_scheduled ( 'sasoEventtickets_cronjob_daily', $args )) {
95 wp_schedule_event( strtotime("00:05"), 'daily', 'sasoEventtickets_cronjob_daily', $args );
96 }
97 }
98 public function cronjob_daily_deactivate() {
99 wp_clear_scheduled_hook( 'sasoEventtickets_cronjob_daily' );
100 }
101 public function load_plugin_textdomain() {
102 load_plugin_textdomain( 'event-tickets-with-ticket-scanner', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
103 }
104 public function getPluginPath() {
105 return SASO_EVENTTICKETS_PLUGIN_DIR_PATH;
106 }
107 public function getPluginVersion() {
108 return SASO_EVENTTICKETS_PLUGIN_VERSION;
109 }
110 public function getPluginVersions() {
111 $ret = ['basic'=>SASO_EVENTTICKETS_PLUGIN_VERSION, 'premium'=>'', 'debug'=>''];
112 if (defined('SASO_EVENTTICKETS_PREMIUM_PLUGIN_VERSION')) {
113 $ret['premium'] = SASO_EVENTTICKETS_PREMIUM_PLUGIN_VERSION;
114 }
115 if (defined('WP_DEBUG') && WP_DEBUG) {
116 $ret['debug'] = esc_html__('is active', 'event-tickets-with-ticket-scanner');
117 }
118 return $ret;
119 }
120 public function getDB() {
121 return SASO_EVENTTICKETS::getDB(plugin_dir_path(__FILE__), "sasoEventticketsDB", $this);
122 }
123 public function getBase() {
124 if ($this->BASE == null) {
125 if (!class_exists('sasoEventtickets_Base')) {
126 include_once plugin_dir_path(__FILE__)."sasoEventtickets_Base.php";
127 }
128 $this->BASE = new sasoEventtickets_Base($this);
129 }
130 return $this->BASE;
131 }
132 public function getCore() {
133 if ($this->CORE == null) {
134 if (!class_exists('sasoEventtickets_Core')) {
135 include_once plugin_dir_path(__FILE__)."sasoEventtickets_Core.php";
136 }
137 $this->CORE = new sasoEventtickets_Core($this);
138 }
139 return $this->CORE;
140 }
141 public function getAdmin() {
142 if ($this->ADMIN == null) {
143 if (!class_exists('sasoEventtickets_AdminSettings')) {
144 include_once plugin_dir_path(__FILE__)."sasoEventtickets_AdminSettings.php";
145 }
146 $this->ADMIN = new sasoEventtickets_AdminSettings($this);
147 }
148 return $this->ADMIN;
149 }
150 public function getFrontend() {
151 if ($this->FRONTEND == null) {
152 if (!class_exists('sasoEventtickets_Frontend')) {
153 include_once plugin_dir_path(__FILE__)."sasoEventtickets_Frontend.php";
154 }
155 $this->FRONTEND = new sasoEventtickets_Frontend($this);
156 }
157 return $this->FRONTEND;
158 }
159 public function getOptions() {
160 if ($this->OPTIONS == null) {
161 if (!class_exists('sasoEventtickets_Options')) {
162 include_once plugin_dir_path(__FILE__)."sasoEventtickets_Options.php";
163 }
164 $this->OPTIONS = new sasoEventtickets_Options($this, $this->_prefix);
165 $this->OPTIONS->initOptions();
166 }
167 return $this->OPTIONS;
168 }
169 public function getNewPDFObject() {
170 if (!class_exists('sasoEventtickets_PDF')) {
171 require_once("sasoEventtickets_PDF.php");
172 }
173 $pdf = new sasoEventtickets_PDF();
174 $pdf->setFontSize($this->getOptions()->getOptionValue('wcTicketPDFFontSize'));
175 $pdf->setFontFamily($this->getOptions()->getOptionValue('wcTicketPDFFontFamily'));
176 $pdf = apply_filters( $this->_add_filter_prefix.'main_getNewPDFObject', $pdf );
177 return $pdf;
178 }
179 public function loadOnce($className, $filename="") {
180 if (!class_exists($className)) {
181 if ($filename == "") $filename = $className;
182 include_once __DIR__.'/'.$filename.'.php';
183 }
184 }
185
186 /**
187 * Load class from /includes/ folder structure
188 *
189 * @param string $className The class name to load
190 * @param string $relativePath Path relative to plugin root (e.g., 'includes/woocommerce/class-base.php')
191 * @return void
192 */
193 private function loadClass(string $className, string $relativePath): void {
194 if (class_exists($className)) {
195 return; // Already loaded
196 }
197
198 $path = __DIR__ . '/' . $relativePath;
199
200 if (file_exists($path)) {
201 require_once $path;
202 }
203 }
204 public function getWC() {
205 $this->loadOnce('sasoEventtickets_WC', "woocommerce-hooks");
206 return sasoEventtickets_WC::Instance();
207 }
208 public function getTicketHandler() {
209 $this->loadOnce('sasoEventtickets_Ticket');
210 return sasoEventtickets_Ticket::Instance($_SERVER["REQUEST_URI"]);
211 }
212 public function getTicketDesignerHandler($template="") {
213 $this->loadOnce('sasoEventtickets_TicketDesigner');
214 return sasoEventtickets_TicketDesigner::Instance($this, $template);
215 }
216 public function getTicketBadgeHandler() {
217 $this->loadOnce('sasoEventtickets_TicketBadge');
218 return sasoEventtickets_TicketBadge::Instance();
219 }
220 public function getTicketQRHandler() {
221 $this->loadOnce('sasoEventtickets_TicketQR');
222 return sasoEventtickets_TicketQR::Instance();
223 }
224 public function getAuthtokenHandler() {
225 $this->loadOnce('sasoEventtickets_Authtoken');
226 return sasoEventtickets_Authtoken::Instance();
227 }
228 public function getSeating() {
229 $this->loadOnce('sasoEventtickets_Seating');
230 return sasoEventtickets_Seating::Instance($this);
231 }
232 public function getPremiumFunctions() {
233 if ($this->_isPrem == null && $this->PREMFUNCTIONS == null) {
234 $this->_isPrem = false;
235 $this->PREMFUNCTIONS = new sasoEventtickets_fakeprem();
236 if (class_exists('sasoEventtickets_PremiumFunctions')) {
237 $this->PREMFUNCTIONS = new sasoEventtickets_PremiumFunctions($this, plugin_dir_path(__FILE__), $this->_prefix, $this->getDB());
238 $this->_isPrem = $this->PREMFUNCTIONS->isPremium();
239 } else { // old approach before v 2.5.7
240 // this is causing issues with base_dir set
241 $premPluginFolder = $this->getPremiumPluginFolder();
242 if (!empty($premPluginFolder)) {
243 $file = $premPluginFolder.$this->_premium_function_file;
244 $premiumFile = plugin_dir_path(__FILE__)."../".$file;
245 if (file_exists($premiumFile)) { // check ob active ist nicht nötig, das das getPremiumPluginFolder schon macht
246 if (!class_exists('sasoEventtickets_PremiumFunctions')) {
247 include_once $premiumFile;
248 }
249 $this->PREMFUNCTIONS = new sasoEventtickets_PremiumFunctions($this, plugin_dir_path(__FILE__), $this->_prefix, $this->getDB());
250 $this->_isPrem = $this->PREMFUNCTIONS->isPremium();
251 }
252 }
253 }
254 }
255 return $this->PREMFUNCTIONS;
256 }
257 private function getPremiumPluginFolder() {
258 $plugins = get_option('active_plugins', []);
259 $premiumFile = "";
260 foreach($plugins as $plugin) {
261 if (strpos(" ".$plugin, $this->_premium_plugin_name) > 0) {
262 $premiumFile = plugin_dir_path($plugin);
263 break;
264 }
265 }
266 return $premiumFile;
267 }
268 public function isPremium() {
269 if ($this->_isPrem == null) $this->getPremiumFunctions();
270 return $this->_isPrem;
271 }
272 public function getPrefix() {
273 return $this->_prefix;
274 }
275 public function getMV() {
276 $v = ['storeip'=>false,'allowuserreg'=>false,'codes_total'=>0x13,'codes'=>0x12,'lists'=>5,'authtokens_total'=>3];
277 $v["codes"] = (int) hexdec(0x80 / 0x002) / 2;
278 $v["codes_total"] = (int) hexdec(0x80 / 0x002) / 2;
279 $v["seatingplans"] = (int) (0x04 >> 0x02);
280 $v["seats_per_plan"] = (int) (0x50 >> 0x02);
281 return $v;
282 }
283 public function listener_upgrader_process_complete( $upgrader_object, $options ) {
284 $current_plugin_path_name = plugin_basename( __FILE__ );
285 if ($options['action'] == 'update' && $options['type'] == 'plugin' ) {
286 if (isset($options['plugins'])) {
287 foreach($options['plugins'] as $each_plugin) {
288 if ($each_plugin==$current_plugin_path_name) {
289 // .......................... YOUR CODES .............
290 }
291 }
292 }
293 }
294 do_action( $this->_do_action_prefix.'main_listener_upgrader_process_complete' );
295 }
296 /**
297 * check for ticket detail page request
298 */
299 public function wc_checkTicketDetailPage() {
300 if( is_404() ){
301 include_once("SASO_EVENTTICKETS.php");
302 // /wp-content/plugins/event-tickets-with-ticket-scanner/ticket/
303 $p = $this->getCore()->getTicketURLPath(true);
304 $t = explode("/", $_SERVER["REQUEST_URI"]);
305 if (count($t) > 1) {
306 if ($t[count($t)-2] != "scanner") {
307 if(substr($_SERVER["REQUEST_URI"], 0, strlen($p)) == $p) {
308 $this->getTicketHandler()->initFilterAndActions();
309 } else {
310 $wcTicketCompatibilityModeURLPath = trim($this->getOptions()->getOptionValue('wcTicketCompatibilityModeURLPath'));
311 $wcTicketCompatibilityModeURLPath = trim(trim($wcTicketCompatibilityModeURLPath, "/"));
312 if (!empty($wcTicketCompatibilityModeURLPath)) {
313 $uri = trim($_SERVER["REQUEST_URI"]);
314 if (!empty($uri)) {
315 $pos = strpos($uri, $wcTicketCompatibilityModeURLPath);
316 if ($pos > 0) {
317 $this->getTicketHandler()->initFilterAndActions();
318 }
319 }
320 }
321 }
322 }
323
324 if ($t[count($t)-2] == "scanner") {
325 if(substr($_SERVER["REQUEST_URI"], 0, strlen($p)) == $p) {
326 //$this->replacingShortcodeTicketScanner();
327 $this->getTicketHandler()->initFilterAndActionsTicketScanner();
328 } else {
329 $wcTicketCompatibilityModeURLPath = trim($this->getOptions()->getOptionValue('wcTicketCompatibilityModeURLPath'));
330 $wcTicketCompatibilityModeURLPath = trim(trim($wcTicketCompatibilityModeURLPath, "/"));
331 if (!empty($wcTicketCompatibilityModeURLPath)) {
332 $uri = trim($_SERVER["REQUEST_URI"]);
333 if (!empty($uri)) {
334 $pos = strpos($_SERVER["REQUEST_URI"], $wcTicketCompatibilityModeURLPath."/scanner/");
335 if ($pos > 0) {
336 $this->getTicketHandler()->initFilterAndActionsTicketScanner();
337 }
338 }
339 }
340 }
341 }
342 }
343 } // endif 404
344 }
345 private function init_frontend() {
346 add_shortcode($this->_shortcode, [$this, 'replacingShortcode']);
347 add_shortcode($this->_shortcode_mycode, [$this, 'replacingShortcodeMyCode']);
348 add_shortcode($this->_shortcode_ticket_scanner, [$this, 'replacingShortcodeTicketScanner']);
349 add_shortcode($this->_shortcode_eventviews, [$this, 'replacingShortcodeEventViews']);
350 add_shortcode($this->_shortcode_feature_list, [$this, 'replacingShortcodeFeatureList']);
351 do_action( $this->_do_action_prefix.'main_init_frontend' );
352 }
353 private function init_backend() {
354 add_action('admin_menu', [$this, 'register_options_page']);
355 register_activation_hook(__FILE__, [$this, 'plugin_activated']);
356 register_deactivation_hook( __FILE__, [$this, 'plugin_deactivated'] );
357 //register_uninstall_hook( __FILE__, 'sasoEventticketsDB::plugin_uninstall' ); // MUSS NOCH GETESTE WERDEN
358 add_action( 'plugins_loaded', [$this, 'plugins_loaded'] );
359 add_action( 'show_user_profile', [$this, 'show_user_profile'] );
360 add_action( 'admin_notices', [$this, 'showSubscriptionWarning'] );
361 add_action( 'admin_notices', [$this, 'showOutdatedPremiumWarning'] );
362
363 if (basename($_SERVER['SCRIPT_NAME']) == "admin-ajax.php") {
364 add_action('wp_ajax_'.$this->_prefix.'_executeAdminSettings', [$this,'executeAdminSettings_a'], 10, 0);
365 add_action('wp_ajax_'.$this->_prefix.'_executeSeatingAdmin', [$this,'executeSeatingAdmin_a'], 10, 0);
366 }
367
368 do_action( $this->_do_action_prefix.'main_init_backend' );
369 }
370 public function WooCommercePluginLoaded() {
371 // DON'T load WC here - let relay functions do lazy loading
372 //$this->getWC(); // um die wc handler zu laden
373 add_action('woocommerce_review_order_after_cart_contents', [$this, 'relay_woocommerce_review_order_after_cart_contents']);
374 add_action('woocommerce_checkout_process', [$this, 'relay_woocommerce_checkout_process']);
375 add_action('woocommerce_before_cart_table', [$this, 'relay_woocommerce_before_cart_table']);
376 add_action('woocommerce_cart_updated', [$this, 'relay_woocommerce_cart_updated']);
377 add_filter('woocommerce_email_attachments', [$this, 'relay_woocommerce_email_attachments'], 10, 3);
378 add_action('woocommerce_checkout_create_order_line_item', [$this, 'relay_woocommerce_checkout_create_order_line_item'], 20, 4 );
379 add_action('woocommerce_check_cart_items', [$this, 'relay_woocommerce_check_cart_items'] );
380 add_action('woocommerce_new_order', [$this, 'relay_woocommerce_new_order'], 10, 1);
381 add_action('woocommerce_checkout_update_order_meta', [$this, 'relay_woocommerce_checkout_update_order_meta'], 20, 2);
382 add_action('woocommerce_order_status_changed', [$this, 'relay_woocommerce_order_status_changed'], 10, 3);
383 add_filter('woocommerce_order_item_display_meta_key', [$this, 'relay_woocommerce_order_item_display_meta_key'], 20, 3 );
384 add_filter('woocommerce_order_item_display_meta_value', [$this, 'relay_woocommerce_order_item_display_meta_value'], 20, 3);
385 add_action('wpo_wcpdf_after_item_meta', [$this, 'relay_wpo_wcpdf_after_item_meta'], 20, 3 );
386 add_action('woocommerce_order_item_meta_start', [$this, 'relay_woocommerce_order_item_meta_start'], 201, 4);
387 add_action('woocommerce_product_after_variable_attributes', [$this, 'relay_woocommerce_product_after_variable_attributes'], 10, 3);
388 add_action('woocommerce_save_product_variation',[$this, 'relay_woocommerce_save_product_variation'], 10 ,2 );
389 add_action('woocommerce_email_order_meta', [$this, 'relay_woocommerce_email_order_meta'], 10, 4 );
390 add_action('woocommerce_thankyou', [$this, 'relay_woocommerce_thankyou'], 5);
391 if (wp_doing_ajax()) {
392 // erlaube ajax nonpriv und registriere handler
393 add_action('wp_ajax_nopriv_'.$this->getPrefix().'_executeWCFrontend', [$this,'relay_executeWCFrontend']); // nicht angemeldete user, sollen eine antwort erhalten
394 add_action('wp_ajax_'.$this->getPrefix().'_executeWCFrontend', [$this,'relay_executeWCFrontend']); // nicht angemeldete user, sollen eine antwort erhalten
395 // Seating Frontend AJAX (seat selection in shop)
396 add_action('wp_ajax_nopriv_'.$this->getPrefix().'_executeSeatingFrontend', [$this,'relay_executeSeatingFrontend']);
397 add_action('wp_ajax_'.$this->getPrefix().'_executeSeatingFrontend', [$this,'relay_executeSeatingFrontend']);
398 }
399 if (is_admin()) {
400 add_action('woocommerce_delete_order', [$this, 'relay_woocommerce_delete_order'], 10, 1 );
401 add_action('woocommerce_delete_order_item', [$this, 'relay_woocommerce_delete_order_item'], 20, 1);
402 add_action('woocommerce_pre_delete_order_refund', [$this, 'relay_woocommerce_pre_delete_order_refund'], 10, 3);
403 add_action('woocommerce_delete_order_refund', [$this, 'relay_woocommerce_delete_order_refund'], 10, 1 );
404 add_action('woocommerce_order_partially_refunded', [$this, 'relay_woocommerce_order_partially_refunded'], 10, 2);
405 add_filter('woocommerce_product_data_tabs', [$this, 'relay_woocommerce_product_data_tabs'], 98 );
406 add_action('woocommerce_product_data_panels', [$this, 'relay_woocommerce_product_data_panels'] );
407 add_action('woocommerce_process_product_meta', [$this, 'relay_woocommerce_process_product_meta'], 10, 2 );
408 add_action('add_meta_boxes', [$this, 'relay_add_meta_boxes'], 10, 2);
409 add_filter('manage_edit-product_columns', [$this, 'relay_manage_edit_product_columns']);
410 add_action('manage_product_posts_custom_column', [$this, 'relay_manage_product_posts_custom_column'], 2);
411 add_filter("manage_edit-product_sortable_columns", [$this, 'relay_manage_edit_product_sortable_columns']);
412 } else {
413 add_action('woocommerce_single_product_summary', [$this, 'relay_woocommerce_single_product_summary']);
414 }
415
416 // set routing -- NEEDS to be replaced by add_rewrite_rule later
417 add_action( 'template_redirect', [$this, 'wc_checkTicketDetailPage'], 1 );
418 //$this->wc_checkTicketDetailPage();
419 add_action('rest_api_init', function () {
420 SASO_EVENTTICKETS::setRestRoutesTicket();
421 });
422
423 add_action('woocommerce_after_shop_loop_item', [$this, 'relay_woocommerce_after_shop_loop_item'], 9); // with 9 we are just before the add to cart button
424 add_filter('woocommerce_add_to_cart_validation', [$this, 'relay_woocommerce_add_to_cart_validation'], 10, 3);
425 add_filter('woocommerce_add_cart_item_data', [$this, 'relay_woocommerce_add_cart_item_data'], 10, 3);
426 add_action('woocommerce_add_to_cart', [$this, 'relay_woocommerce_add_to_cart'], 10, 6);
427 add_action('woocommerce_cart_item_removed', [$this, 'relay_woocommerce_cart_item_removed'], 10, 2);
428 add_action('woocommerce_after_cart_item_quantity_update', [$this, 'relay_woocommerce_after_cart_item_quantity_update'], 10, 4);
429 add_filter('woocommerce_update_cart_validation', [$this, 'relay_woocommerce_update_cart_validation'], 10, 4);
430 add_action('woocommerce_before_add_to_cart_button', [$this, 'relay_woocommerce_before_add_to_cart_button'], 15);
431
432 do_action( $this->_do_action_prefix.'main_WooCommercePluginLoaded' );
433 }
434 public function relay_woocommerce_after_shop_loop_item() {
435 $this->getWC()->getFrontendManager()->woocommerce_after_shop_loop_item_handler();
436 }
437 public function relay_woocommerce_add_to_cart_validation() {
438 $args = func_get_args();
439 return $this->getWC()->getFrontendManager()->woocommerce_add_to_cart_validation_handler(...$args);
440 }
441 public function relay_woocommerce_add_cart_item_data() {
442 $args = func_get_args();
443 return $this->getWC()->getFrontendManager()->woocommerce_add_cart_item_data_handler(...$args);
444 }
445 public function relay_woocommerce_add_to_cart() {
446 $args = func_get_args();
447 return $this->getWC()->getFrontendManager()->woocommerce_add_to_cart_handler(...$args);
448 }
449 public function relay_woocommerce_cart_item_removed() {
450 $args = func_get_args();
451 $this->getWC()->getFrontendManager()->woocommerce_cart_item_removed_handler(...$args);
452 }
453 public function relay_woocommerce_after_cart_item_quantity_update() {
454 $args = func_get_args();
455 $this->getWC()->getFrontendManager()->woocommerce_after_cart_item_quantity_update_handler(...$args);
456 }
457 public function relay_woocommerce_update_cart_validation() {
458 $args = func_get_args();
459 return $this->getWC()->getFrontendManager()->woocommerce_update_cart_validation_handler(...$args);
460 }
461 public function relay_woocommerce_before_add_to_cart_button() {
462 $this->getWC()->getFrontendManager()->woocommerce_before_add_to_cart_button_handler();
463 }
464 public function relay_woocommerce_review_order_after_cart_contents() {
465 $this->getWC()->getFrontendManager()->woocommerce_review_order_after_cart_contents();
466 }
467 public function relay_woocommerce_checkout_process() {
468 $this->getWC()->getFrontendManager()->woocommerce_checkout_process();
469 }
470 public function relay_woocommerce_before_cart_table() {
471 $this->getWC()->getFrontendManager()->woocommerce_before_cart_table();
472 }
473 public function relay_woocommerce_cart_updated() {
474 $this->getWC()->getFrontendManager()->woocommerce_cart_updated_handler();
475 }
476 public function relay_woocommerce_email_attachments() {
477 $args = func_get_args();
478 return $this->getWC()->getEmailHandler()->woocommerce_email_attachments(...$args);
479 }
480 public function relay_woocommerce_checkout_create_order_line_item() {
481 $args = func_get_args();
482 return $this->getWC()->getOrderManager()->woocommerce_checkout_create_order_line_item(...$args);
483 }
484 public function relay_woocommerce_check_cart_items() {
485 $this->getWC()->getFrontendManager()->woocommerce_check_cart_items();
486 }
487 public function relay_woocommerce_new_order() {
488 $args = func_get_args();
489 return $this->getWC()->getOrderManager()->woocommerce_new_order(...$args);
490 }
491 public function relay_woocommerce_checkout_update_order_meta() {
492 $args = func_get_args();
493 return $this->getWC()->getOrderManager()->woocommerce_checkout_update_order_meta(...$args);
494 }
495 public function relay_executeWCFrontend() {
496 return $this->getWC()->getFrontendManager()->executeWCFrontend();
497 }
498 public function relay_executeSeatingFrontend() {
499 return $this->getSeating()->getFrontendManager()->executeSeatingFrontend();
500 }
501 public function relay_woocommerce_delete_order() {
502 $args = func_get_args();
503 $this->getWC()->getOrderManager()->woocommerce_delete_order(...$args);
504 }
505 public function relay_woocommerce_delete_order_item() {
506 $args = func_get_args();
507 $this->getWC()->getOrderManager()->woocommerce_delete_order_item(...$args);
508 }
509 public function relay_woocommerce_pre_delete_order_refund() {
510 $args = func_get_args();
511 $this->getWC()->getOrderManager()->woocommerce_pre_delete_order_refund(...$args);
512 }
513 public function relay_woocommerce_delete_order_refund() {
514 $args = func_get_args();
515 $this->getWC()->getOrderManager()->woocommerce_delete_order_refund(...$args);
516 }
517 public function relay_woocommerce_product_data_tabs() {
518 $args = func_get_args();
519 return $this->getWC()->getProductManager()->woocommerce_product_data_tabs(...$args);
520 }
521 public function relay_woocommerce_product_data_panels() {
522 $this->getWC()->getProductManager()->woocommerce_product_data_panels();
523 }
524 public function relay_woocommerce_process_product_meta() {
525 $args = func_get_args();
526 $this->getWC()->getProductManager()->woocommerce_process_product_meta(...$args);
527 }
528 public function relay_add_meta_boxes(...$args) {
529 $this->getWC()->add_meta_boxes(...$args);
530 }
531 public function relay_manage_edit_product_columns() {
532 $args = func_get_args();
533 return $this->getWC()->getProductManager()->manage_edit_product_columns(...$args);
534 }
535 public function relay_manage_product_posts_custom_column() {
536 $args = func_get_args();
537 $this->getWC()->getProductManager()->manage_product_posts_custom_column(...$args);
538 }
539 public function relay_manage_edit_product_sortable_columns() {
540 $args = func_get_args();
541 return $this->getWC()->getProductManager()->manage_edit_product_sortable_columns(...$args);
542 }
543 public function relay_woocommerce_single_product_summary() {
544 $this->getWC()->getFrontendManager()->woocommerce_single_product_summary();
545 }
546 public function relay_woocommerce_order_status_changed() {
547 $args = func_get_args();
548 $this->getWC()->getOrderManager()->woocommerce_order_status_changed(...$args);
549 }
550 public function relay_woocommerce_order_partially_refunded() {
551 $args = func_get_args();
552 $this->getWC()->getOrderManager()->woocommerce_order_partially_refunded(...$args);
553 }
554 public function relay_woocommerce_order_item_display_meta_key() {
555 $args = func_get_args();
556 return $this->getWC()->getOrderManager()->woocommerce_order_item_display_meta_key(...$args);
557 }
558 public function relay_woocommerce_order_item_display_meta_value() {
559 $args = func_get_args();
560 return $this->getWC()->getOrderManager()->woocommerce_order_item_display_meta_value(...$args);
561 }
562 public function relay_wpo_wcpdf_after_item_meta() {
563 $args = func_get_args();
564 $this->getWC()->getOrderManager()->wpo_wcpdf_after_item_meta(...$args);
565 }
566 public function relay_woocommerce_order_item_meta_start() {
567 $args = func_get_args();
568 $this->getWC()->getOrderManager()->woocommerce_order_item_meta_start(...$args);
569 }
570 public function relay_woocommerce_product_after_variable_attributes() {
571 $args = func_get_args();
572 $this->getWC()->getProductManager()->woocommerce_product_after_variable_attributes(...$args);
573 }
574 public function relay_woocommerce_save_product_variation() {
575 $args = func_get_args();
576 $this->getWC()->getProductManager()->woocommerce_save_product_variation(...$args);
577 }
578 public function relay_woocommerce_email_order_meta() {
579 $args = func_get_args();
580 $this->getWC()->getEmailHandler()->woocommerce_email_order_meta(...$args);
581 }
582 public function relay_woocommerce_thankyou() {
583 $args = func_get_args();
584 $this->getWC()->getFrontendManager()->woocommerce_thankyou(...$args);
585 }
586 public function relay_sasoEventtickets_cronjob_daily() {
587 $this->getTicketHandler()->cronJobDaily();
588 }
589
590 public function plugin_deactivated() {
591 $this->cronjob_daily_deactivate();
592 $this->getDB();
593 sasoEventticketsDB::plugin_deactivated();
594 do_action( $this->_do_action_prefix.'main_plugin_deactivated' );
595 }
596 public function plugin_uninstall() {
597 $this->getDB();
598 sasoEventticketsDB::plugin_uninstall();
599 $this->getAdmin();
600 sasoEventtickets_AdminSettings::plugin_uninstall();
601 do_action( $this->_do_action_prefix.'main_WooCommercePluginLoaded' );
602 }
603 public function plugin_activated($is_network_wide=false) { // und auch für updates, macht es einfacher
604 $this->getDB(); // um installiere Tabellen auszuführen
605 update_option('SASO_EVENTTICKETS_PLUGIN_VERSION', SASO_EVENTTICKETS_PLUGIN_VERSION);
606 $this->getAdmin()->generateFirstCodeList();
607 $this->cronjob_daily_activate();
608 do_action( $this->_do_action_prefix.'activated' );
609 do_action( $this->_do_action_prefix.'main_plugin_activated' );
610 }
611 public function plugins_loaded() {
612 if (SASO_EVENTTICKETS_PLUGIN_VERSION !== get_option('SASO_EVENTTICKETS_PLUGIN_VERSION', '')) $this->plugin_activated(); // vermutlich wurde die aktivierung übersprungen, bei änderungen direkt an den files
613 }
614 public function initialize_plugin() {
615 $this->getDB(); // um installiere Tabellen auszuführen
616 do_action( $this->_do_action_prefix.'initialized' );
617 do_action( $this->_do_action_prefix.'main_initialize_plugin' );
618 }
619 function show_user_profile($profileuser) {
620 $this->getAdmin()->show_user_profile($profileuser);
621 do_action( $this->_do_action_prefix.'main_show_user_profile' );
622 }
623 function register_options_page() {
624 $allowed = $this->isUserAllowedToAccessAdminArea();
625 $allowed = apply_filters( $this->_add_filter_prefix.'main_options_page', $allowed );
626 if ($allowed) {
627 add_options_page(__('Event Tickets', 'event-tickets-with-ticket-scanner'), 'Event Tickets', 'manage_options', 'event-tickets-with-ticket-scanner', [$this,'options_page']);
628 add_menu_page( __('Event Tickets', 'event-tickets-with-ticket-scanner'), 'Event Tickets', 'read', 'event-tickets-with-ticket-scanner', [$this,'options_page'], plugins_url( "",__FILE__ )."/img/icon_event-tickets-with-ticket-scanner_18px.gif", null );
629 }
630 do_action( $this->_do_action_prefix.'main_register_options_page' );
631 }
632
633 function options_page() {
634 $allowed = $this->isUserAllowedToAccessAdminArea();
635 $allowed = apply_filters( $this->_add_filter_prefix.'main_options_page', $allowed );
636 if ( !$allowed ) {
637 wp_die( __( 'You do not have sufficient permissions to access this page.', 'event-tickets-with-ticket-scanner' ) );
638 }
639
640 wp_enqueue_style("wp-jquery-ui-dialog");
641
642 $js_url = "jquery.qrcode.min.js?_v=".$this->_js_version;
643 wp_register_script('ajax_script2', plugins_url( "3rd/".$js_url,__FILE__ ), array('jquery', 'jquery-ui-dialog'));
644 wp_enqueue_script('ajax_script2');
645
646 wp_enqueue_media(); // um die js wp.media lib zu laden
647
648 // einbinden das js starter skript
649 $js_url = $this->_js_file."?_v=".$this->_js_version;
650 if (defined( 'WP_DEBUG')) $js_url .= '&debug=1';
651 wp_register_script('ajax_script_backend', plugins_url( $js_url,__FILE__ ), array('jquery', 'jquery-ui-dialog', 'wp-i18n'));
652 wp_enqueue_script('ajax_script_backend');
653 wp_set_script_translations('ajax_script_backend', 'event-tickets-with-ticket-scanner', __DIR__.'/languages');
654
655 // per script eine variable einbinden, die url hat den wp-admin prefix
656 // damit im backend.js dann die richtige callback url genutzt werden kann
657 $vars = array(
658 '_plugin_home_url' =>plugins_url( "",__FILE__ ),
659 '_plugin_version' => $this->getPluginVersion(),
660 '_action' => $this->_prefix.'_executeAdminSettings',
661 '_max'=>$this->getBase()->getMaxValues(),
662 '_isPremium'=>$this->isPremium(),
663 '_isUserLoggedin'=>is_user_logged_in(),
664 '_premJS'=>$this->isPremium() && method_exists($this->getPremiumFunctions(), "getJSBackendFile") ? $this->getPremiumFunctions()->getJSBackendFile() : '',
665 'url' => admin_url( 'admin-ajax.php' ),
666 'ticket_url' => $this->getCore()->getTicketURLPath(),
667 'nonce' => wp_create_nonce( $this->_js_nonce ),
668 'ajaxActionPrefix' => $this->_prefix,
669 'divPrefix' => $this->_prefix,
670 'divId' => $this->_divId,
671 'jsFiles' => plugins_url( 'backend.js?_v='.$this->_js_version,__FILE__ )
672 );
673 $vars = apply_filters( $this->_add_filter_prefix.'main_options_page', $vars );
674 wp_localize_script(
675 'ajax_script_backend',
676 'Ajax_'.$this->_prefix, // name der injected variable
677 $vars
678 );
679
680 do_action( $this->_do_action_prefix.'main_options_page' );
681
682 $versions = $this->getPluginVersions();
683 $versions_tail = $versions['basic'].($versions['premium'] != "" ? ', Premium: '.$versions['premium'] : '');
684 $version_tail_add = "";
685 if ($versions['debug'] != "") $version_tail_add .= 'DEBUG: '.$versions['debug'].', LANG: '.determine_locale();
686 ?>
687 <div class="event-tickets-with-ticket-scanner-admin-page">
688 <div class="event-tickets-with-ticket-scanner-header">
689 <div class="event-tickets-with-ticket-scanner-header-left">
690 <img src="<?php echo plugins_url( "",__FILE__ ); ?>/img/logo_event-tickets-with-ticket-scanner.gif"
691 alt="Event Tickets"
692 class="event-tickets-with-ticket-scanner-header-logo">
693
694 <div class="event-tickets-with-ticket-scanner-header-title">
695 <div class="event-tickets-with-ticket-scanner-header-name">
696 Event Tickets with Ticket Scanner
697 </div>
698 <div class="event-tickets-with-ticket-scanner-header-meta">
699 <?php esc_html_e('Version', 'event-tickets-with-ticket-scanner'); ?>: <?php echo $versions_tail; ?> <?php echo $version_tail_add; ?>
700 </div>
701 </div>
702 </div>
703
704 <div class="event-tickets-with-ticket-scanner-header-right" id="event-tickets-with-ticket-scanner-header-actions">
705 <!-- Button kommt via JS -->
706 </div>
707 </div>
708
709 <div style="clear:both;" data-id="plugin_addons"></div>
710 <div style="clear:both;" data-id="plugin_info_area"></div>
711 <div style="clear:both;" id="<?php echo esc_attr($this->_divId); ?>">...loading...</div>
712 <div style="margin-top:100px;">
713 <hr>
714 <a name="shortcodedetails"></a>
715 <h3>Documentation</h3>
716 <p><span class="dashicons dashicons-external"></span><a href="https://vollstart.com/event-tickets-with-ticket-scanner/docs/" target="_blank">Click here, to visit the documentation of this plugin.</a></p>
717 <h3><?php esc_html_e('Plugin Rating', 'event-tickets-with-ticket-scanner'); ?></h3>
718 <p><?php esc_html_e('If you like our plugin, then please give us a', 'event-tickets-with-ticket-scanner'); ?> <a target="_blank" href="https://wordpress.org/support/plugin/event-tickets-with-ticket-scanner/reviews?rate=5#new-post">�
719
720
721
722
723 5-Star Rating</a>.</p>
724 <h3><?php esc_html_e('Ticket Sale option', 'event-tickets-with-ticket-scanner'); ?></h3>
725 <p><?php esc_html_e('You can use this plugin to sell tickets and even redeem them. Check out the documentation for', 'event-tickets-with-ticket-scanner'); ?> <a target="_blank" href="https://vollstart.com/event-tickets-with-ticket-scanner/docs/#ticket"><?php esc_html_e('more details here', 'event-tickets-with-ticket-scanner'); ?></a>.</p>
726 <h3><?php esc_html_e('Premium Homepage', 'event-tickets-with-ticket-scanner'); ?></h3>
727 <p><?php esc_html_e('You can find more details about the', 'event-tickets-with-ticket-scanner'); ?> <a target="_blank" href="https://vollstart.com/event-tickets-with-ticket-scanner/"><?php esc_html_e('premium version here', 'event-tickets-with-ticket-scanner'); ?></a>.</p>
728 <!--
729 <h3>Shortcode parameter In- & Output</h3>
730 <a href="https://vollstart.com/event-tickets-with-ticket-scanner/docs/" target="_blank">Click here for more help about the options</a>
731 <p>You can use your own HTML input, output and trigger component. If you add the parameters (all 3 mandatory to use this feature), then the default input area will not be rendered.</p>
732 <ul>
733 <li><b>inputid</b><br>inputid="html-element-id". The value of this component will be taken. It need to be an HTML input element. We will access the value-parameter of it.</li>
734 <li><b>triggerid</b><br>triggerid="html-element-id". The onclick event of this component will be replaced by our function to call the server validation with the code.</li>
735 <li><b>outputid</b><br>outputid="html-element-id". The content of this component will be replaced by the server result after the check . We will use the innerHTML property of it, so use a DIV, SPAN, TD or similar for best results.</li>
736 </ul>
737 <h3>Shortcode parameter Javascript</h3>
738 <p>You can add your Javascript function name. Both parameters are optional and not required. If functions will be called before the code is sent to the server or displaying the result.</p>
739 <ul>
740 <li><b>jspre</b><br>jspre="function-name". The function will be called. The input parameter will be the code. If your function returns a value, than this returned value will be used otherwise the entered code will be used.</li>
741 <li><b>jsafter</b><br>jsafter="function-name". The function will be called. The input parameter will be the result JSON object from the server.</li>
742 </ul>
743 -->
744 <h3><?php esc_html_e('Shortcode to display the event calendar form within a page', 'event-tickets-with-ticket-scanner'); ?></h3>
745 <b>[<?php echo esc_html($this->_shortcode_eventviews); ?>]</b>
746 <p><?php esc_html_e('The event calendar form will be displayed. You can add the following parameters to change the output:', 'event-tickets-with-ticket-scanner'); ?></p>
747 <ul>
748 <!--<li>view<br>Values: calendar, list or calendar|list<br>Default: list</li>-->
749 <li>months_to_show<br>Values can be a number higher than 0. Default: 3</li>
750 </ul>
751 <p>CSS file: <a href="<?php echo plugins_url( "",__FILE__ ); ?>/css/calendar.css" target="_blank">calendar.css</a></p>
752 <h3><?php esc_html_e('Shortcode to display the assigned tickets and codes of an user within a page', 'event-tickets-with-ticket-scanner'); ?></h3>
753 <b>[<?php echo esc_html($this->_shortcode_mycode); ?>]</b>
754 <p>
755 The list will be human readable in a table - default.<br>
756 You can add two parameter to change the output. <br>
757 format: only json for now possible.
758 display: one or more values. Values are seperated with a comma. Possible values: codes,validation,user,used,confirmedCount,woocommerce,wc_rp,wc_ticket<br>
759 e.g. [<?php echo esc_html($this->_shortcode_mycode); ?> format="json" display="code,wc_ticket"]<br>
760 The return value is a JSON string. So might want to add this shortcode within a Javascript HTML block to access the variable.
761 </p>
762 <h3><?php esc_html_e('Shortcode to display the ticket scanner within a page', 'event-tickets-with-ticket-scanner'); ?></h3>
763 <?php esc_html_e('Useful if you cannot open the ticket scanner due to security issues.', 'event-tickets-with-ticket-scanner'); ?><br>
764 <b>[<?php echo esc_html($this->_shortcode_ticket_scanner); ?>]</b>
765 <h3><?php esc_html_e('PHP Filters', 'event-tickets-with-ticket-scanner'); ?></h3>
766 <p><?php esc_html_e('You can use PHP code to register your filter functions for the validation check.', 'event-tickets-with-ticket-scanner'); ?>
767 <a href="https://vollstart.com/event-tickets-with-ticket-scanner/docs/#filters" target="_blank"><?php esc_html_e('Click here for more help about the functions', 'event-tickets-with-ticket-scanner'); ?></a>
768 </p>
769 <ul>
770 <li>add_filter('<?php echo $this->_add_filter_prefix.'beforeCheckCodePre'; ?>', 'myfunc', 20, 1)</li>
771 <li>add_filter('<?php echo $this->_add_filter_prefix.'beforeCheckCode'; ?>', 'myfunc', 20, 1)</li>
772 <li>add_filter('<?php echo $this->_add_filter_prefix.'afterCheckCodePre'; ?>', 'myfunc', 20, 1)</li>
773 <li>add_filter('<?php echo $this->_add_filter_prefix.'afterCheckCode'; ?>', 'myfunc', 20, 1)</li>
774 </ul>
775 <p>More BETA filters and actions hooks can be found <a href="https://vollstart.com/event-tickets-with-ticket-scanner/docs/ticket-plugin-api/" target="_blank">here (NOT STABLE, be aware that they might be changed in the future)</a>.
776 <p style="text-align:center;"><a target="_blank" href="https://vollstart.com">VOLLSTART</a> - More plugins: <a target="_blank" href="https://wordpress.org/plugins/serial-codes-generator-and-validator/">Serial Code Validator</a></p>
777 </div>
778 </div>
779 <?php
780 do_action( $this->_do_action_prefix.'options_page' );
781 }
782
783 public function isUserAllowedToAccessAdminArea() {
784 if ($this->isAllowedAccess != null) return $this->isAllowedAccess;
785 if ($this->getOptions()->isOptionCheckboxActive('allowOnlySepcificRoleAccessToAdmin')) {
786 // check welche rollen
787 $user = wp_get_current_user();
788 $user_roles = (array) $user->roles;
789 if (in_array("administrator", $user_roles)) {
790 $this->isAllowedAccess = true;
791 } else {
792 $adminAreaAllowedRoles = $this->getOptions()->getOptionValue('adminAreaAllowedRoles');
793 if (!is_array($adminAreaAllowedRoles)) {
794 if (empty($adminAreaAllowedRoles)) {
795 $adminAreaAllowedRoles = [];
796 } else {
797 $adminAreaAllowedRoles = [$adminAreaAllowedRoles];
798 }
799 }
800 foreach($adminAreaAllowedRoles as $role_name) {
801 if (in_array($role_name, $user_roles)) {
802 $this->isAllowedAccess = true;
803 break;
804 };
805 }
806 }
807 } else {
808 // Standard: Only administrators have access
809 $this->isAllowedAccess = current_user_can('manage_options');
810 }
811 $this->isAllowedAccess = apply_filters( $this->_add_filter_prefix.'main_isUserAllowedToAccessAdminArea', $this->isAllowedAccess );
812 return $this->isAllowedAccess;
813 }
814
815 public function executeAdminSettings_a() {
816 if (!SASO_EVENTTICKETS::issetRPara('a_sngmbh')) return wp_send_json_success("a_sngmbh not provided");
817 return $this->executeAdminSettings(SASO_EVENTTICKETS::getRequestPara('a_sngmbh')); // to prevent WP adds parameters
818 }
819
820 public function executeAdminSettings($a=0, $data=null) {
821 if (!$this->isUserAllowedToAccessAdminArea()) {
822 return wp_send_json_error("Access denied", 403);
823 }
824 if ($a === 0 && !SASO_EVENTTICKETS::issetRPara('a_sngmbh')) return wp_send_json_success("a not provided");
825
826 if ($data == null) {
827 $data = SASO_EVENTTICKETS::issetRPara('data') ? SASO_EVENTTICKETS::getRequestPara('data') : [];
828 }
829 if ($a === 0 || empty($a) || trim($a) == "") {
830 $a = SASO_EVENTTICKETS::getRequestPara('a_sngmbh');
831 }
832 do_action( $this->_do_action_prefix.'executeAdminSettings', $a, $data );
833 return $this->getAdmin()->executeJSON($a, $data, false, false); // with nonce check
834 }
835
836 public function executeSeatingAdmin_a() {
837 return $this->executeSeatingAdmin(SASO_EVENTTICKETS::getRequestPara('a'));
838 }
839
840 public function executeSeatingAdmin($a = '', $data = null) {
841 if (!$this->isUserAllowedToAccessAdminArea()) {
842 return wp_send_json_error('Access denied', 403);
843 }
844 if (empty($a) && !SASO_EVENTTICKETS::issetRPara('a')) {
845 return wp_send_json_error('a not provided');
846 }
847 if ($data === null) {
848 $data = SASO_EVENTTICKETS::getRequest();
849 }
850 if (empty($a)) {
851 $a = SASO_EVENTTICKETS::getRequestPara('a');
852 }
853 return $this->getSeating()->getAdminHandler()->executeSeatingJSON($a, $data);
854 }
855
856 public function executeFrontend_a() {
857 return $this->executeFrontend(); // to prevent WP adds parameters
858 }
859
860 public function executeWCBackend() {
861 if (!$this->isUserAllowedToAccessAdminArea()) {
862 return wp_send_json_error("Access denied", 403);
863 }
864 if (!SASO_EVENTTICKETS::issetRPara('a_sngmbh')) return wp_send_json_success("a_sngmbh not provided");
865 $data = SASO_EVENTTICKETS::issetRPara('data') ? SASO_EVENTTICKETS::getRequestPara('data') : [];
866 return $this->getWC()->executeJSON(SASO_EVENTTICKETS::getRequestPara('a_sngmbh'), $data);
867 }
868
869 public function executeFrontend($a=0, $data=null) {
870 $sasoEventtickets_Frontend = $this->getFrontend();
871 if ($a === 0 && !SASO_EVENTTICKETS::issetRPara('a_sngmbh')) return wp_send_json_success("a not provided");
872
873 if ($data == null) {
874 $data = SASO_EVENTTICKETS::issetRPara('data') ? SASO_EVENTTICKETS::getRequestPara('data') : [];
875 }
876 if ($a === 0 || empty($a) || trim($a) == "") {
877 $a = SASO_EVENTTICKETS::getRequestPara('a_sngmbh');
878 }
879 do_action( $this->_do_action_prefix.'executeFrontend', $a, $data );
880 return $sasoEventtickets_Frontend->executeJSON($a, $data);
881 }
882
883 public function replacingShortcode($attr=[], $content = null, $tag = '') {
884 add_filter( $this->_add_filter_prefix.'replaceShortcode', [$this, 'replaceShortcode'], 10, 3 );
885 $ret = apply_filters( $this->_add_filter_prefix.'replaceShortcode', $attr, $content, $tag );
886 return $ret;
887 }
888
889 public function setTicketScannerJS() {
890 wp_enqueue_style("wp-jquery-ui-dialog");
891
892 $js_url = "jquery.qrcode.min.js?_v=".$this->getPluginVersion();
893 wp_enqueue_script(
894 'ajax_script2',
895 plugins_url( "3rd/".$js_url,__FILE__ ),
896 array('jquery', 'jquery-ui-dialog')
897 );
898
899 $js_url = plugin_dir_url(__FILE__)."3rd/html5-qrcode.min.js?_v=".$this->getPluginVersion();
900 wp_register_script('html5-qrcode', $js_url, array('jquery', 'jquery-ui-dialog'));
901 wp_enqueue_script('html5-qrcode');
902
903 // https://github.com/nimiq/qr-scanner - NEW scanner lib
904 $js_url = plugin_dir_url(__FILE__)."3rd/qr-scanner-1.4.2/qr-scanner.umd.min.js?_v=".$this->getPluginVersion();
905 wp_register_script('qr-scanner', $js_url, array('jquery', 'jquery-ui-dialog'));
906 wp_enqueue_script('qr-scanner');
907
908 $js_url = "ticket_scanner.js?_v=".$this->getPluginVersion();
909 if (defined('WP_DEBUG')) $js_url .= '&t='.time();
910 $js_url = plugins_url( $js_url,__FILE__ );
911 wp_register_script('ajax_script_ticket_scanner', $js_url, array('jquery', 'jquery-ui-dialog', 'wp-i18n'));
912 wp_enqueue_script('ajax_script_ticket_scanner');
913 wp_set_script_translations('ajax_script_ticket_scanner', 'event-tickets-with-ticket-scanner', __DIR__.'/languages');
914
915 $ticketScannerDontRememberCamChoice = $this->getOptions()->isOptionCheckboxActive("ticketScannerDontRememberCamChoice") ? true : false;
916
917 $vars = [
918 'root' => esc_url_raw( rest_url() ),
919 '_plugin_home_url' =>plugins_url( "",__FILE__ ),
920 '_action' => $this->_prefix.'_executeAdminSettings',
921 '_isPremium'=>$this->isPremium(),
922 '_isUserLoggedin'=>is_user_logged_in(),
923 '_userId'=>get_current_user_id(),
924 '_restPrefixUrl'=>SASO_EVENTTICKETS::getRESTPrefixURL(),
925 '_siteUrl'=>get_site_url(),
926 '_params'=>["auth"=>$this->getAuthtokenHandler()::$authtoken_param],
927 //'url' => admin_url( 'admin-ajax.php' ), // not used for now in ticketscanner.js
928 'url' => rest_get_server(), // not used for now in ticketscanner.js
929 'nonce' => wp_create_nonce( 'wp_rest' ),
930 //'nonce' => wp_create_nonce( $this->_js_nonce ),
931 'ajaxActionPrefix' => $this->_prefix,
932 'wcTicketCompatibilityModeRestURL' => $this->getOptions()->getOptionValue('wcTicketCompatibilityModeRestURL', ''),
933 'IS_PRETTY_PERMALINK_ACTIVATED' => get_option('permalink_structure') ? true :false,
934 'ticketScannerDontRememberCamChoice' => $ticketScannerDontRememberCamChoice,
935 'ticketScannerStartCamWithoutButtonClicked' => $this->getOptions()->isOptionCheckboxActive('ticketScannerStartCamWithoutButtonClicked'),
936 'ticketScannerDontShowOptionControls' => $this->getOptions()->isOptionCheckboxActive('ticketScannerDontShowOptionControls'),
937 'ticketScannerScanAndRedeemImmediately' => $this->getOptions()->isOptionCheckboxActive('ticketScannerScanAndRedeemImmediately'),
938 'ticketScannerHideTicketInformation' => $this->getOptions()->isOptionCheckboxActive('ticketScannerHideTicketInformation'),
939 'ticketScannerHideTicketInformationShowShortDesc' => $this->getOptions()->isOptionCheckboxActive('ticketScannerHideTicketInformationShowShortDesc'),
940 'ticketScannerDontShowBtnPDF' => $this->getOptions()->isOptionCheckboxActive('ticketScannerDontShowBtnPDF'),
941 'ticketScannerDontShowBtnBadge' => $this->getOptions()->isOptionCheckboxActive('ticketScannerDontShowBtnBadge'),
942 'ticketScannerDisplayTimes' => $this->getOptions()->isOptionCheckboxActive('ticketScannerDisplayTimes')
943 ];
944 $vars = apply_filters( $this->_add_filter_prefix.'main_setTicketScannerJS', $vars );
945 wp_localize_script(
946 'ajax_script_ticket_scanner',
947 'Ajax_'.$this->_prefix, // name der injected variable
948 $vars
949 );
950
951 do_action( $this->_do_action_prefix.'main_setTicketScannerJS', $js_url );
952 }
953
954 public function replacingShortcodeTicketScanner($attr=[], $content = null, $tag = '') {
955 $this->setTicketScannerJS();
956 return '
957 <center>
958 <div style="width:90%;max-width:1024px;">'.$this->getTicketHandler()->getTicketScannerHTMLBoilerplate().'
959 </div>
960 </center>
961 ';
962 }
963
964 public function getCodesTextAsShortList($codes) {
965 $ret = "";
966 if (count($codes) > 0) {
967 $ret = '<table>';
968 $wcTicketUserProfileDisplayTicketDetailURL = $this->getOptions()->isOptionCheckboxActive("wcTicketUserProfileDisplayTicketDetailURL");
969 $wcTicketUserProfileDisplayRedeemAmount = $this->getOptions()->isOptionCheckboxActive("wcTicketUserProfileDisplayRedeemAmount");
970
971 $label_expired = $this->getOptions()->getOptionValue('wcTicketTransTicketExpired', 'EXPIRED');
972 $label_stolen = $this->getOptions()->getOptionValue('wcTicketTransTicketIsStolen', 'REPORTED AS STOLEN');
973 $label_notvalid = $this->getOptions()->getOptionValue('wcTicketTransTicketNotValid', 'DISABLED');
974
975 $myCodes = [];
976 foreach($codes as $idx => $codeObj) {
977 $metaObj = $this->getCore()->encodeMetaValuesAndFillObject($codeObj['meta'], $codeObj);
978
979 $_c = '<tr><td style="text-align:right;">'.($idx + 1).'.</td><td>'.$codeObj['code_display'].'</td><td>';
980 if ($codeObj['aktiv'] == 1) {
981 if ($this->getCore()->checkCodeExpired($codeObj)) {
982 $_c .= $label_expired;
983 }
984 } else if ($codeObj['aktiv'] == 0) {
985 $_c .= $label_notvalid;
986 } else if ($codeObj['aktiv'] == 2) {
987 $_c .= $label_stolen;
988 }
989 $_c .= '</td>';
990
991 if ($wcTicketUserProfileDisplayTicketDetailURL) {
992 $_c .= "<td>";
993 $url = $this->getCore()->getTicketURL($codeObj, $metaObj);
994 if (!empty($url)) {
995 $_c .= '<a href="'.$url.'" target="_blank">Ticket Details</a>';
996 }
997 $_c .= "</td>";
998 }
999 if ($wcTicketUserProfileDisplayRedeemAmount && function_exists("wc_get_product")) {
1000 $_c .= "<td>";
1001 $text_redeem_amount = $this->getTicketHandler()->getRedeemAmountText($codeObj, $metaObj, false);
1002 if (!empty($text_redeem_amount)) {
1003 $_c .= $text_redeem_amount;
1004 }
1005 $_c .= "<td>";
1006 }
1007 $_c .= "</tr>";
1008 $myCodes[] = $_c;
1009 }
1010 $ret .= implode("", $myCodes);
1011 $ret .= "</table>";
1012 }
1013 $ret = apply_filters( $this->_add_filter_prefix.'main_getCodesTextAsShortList', $ret, $codes );
1014 return $ret;
1015 }
1016
1017 public function getMyCodeText($user_id, $attr=[], $content = null, $tag = '') {
1018 $ret = '';
1019 // check ob eingeloggt
1020 $pre_text = $this->getOptions()->getOptionValue('userDisplayCodePrefix', '');
1021 if (!empty($pre_text)) $pre_text .= " ";
1022
1023 if ($user_id > 0) {
1024 // lade codes mit user_id
1025 $codes = $this->getCore()->getCodesByRegUserId($user_id);
1026 $ret .= "<b>".$pre_text."</b><br>";
1027 $ret .= $this->getCodesTextAsShortList($codes);
1028
1029 // Download All as PDF button
1030 $show_download_btn = isset($attr['download_all_pdf']) &&
1031 in_array(strtolower($attr['download_all_pdf']), ['true', '1', 'yes'], true);
1032
1033 if ($show_download_btn && count($codes) > 0) {
1034 $max_tickets = isset($attr['download_all_pdf_max']) ? intval($attr['download_all_pdf_max']) : 100;
1035 $btn_label = isset($attr['download_all_pdf_label']) ?
1036 sanitize_text_field($attr['download_all_pdf_label']) :
1037 __('Download All Tickets as PDF', 'event-tickets-with-ticket-scanner');
1038
1039 $ticket_count = count($codes);
1040 if ($ticket_count > $max_tickets) {
1041 $ret .= '<p><em>' . sprintf(
1042 /* translators: %d: maximum number of tickets */
1043 esc_html__('Too many tickets (%1$d). Maximum %2$d tickets can be downloaded at once.', 'event-tickets-with-ticket-scanner'),
1044 $ticket_count,
1045 $max_tickets
1046 ) . '</em></p>';
1047 } else {
1048 // Generate secure download URL
1049 $nonce = wp_create_nonce('download_my_codes_pdf_' . $user_id);
1050 $download_url = admin_url('admin-ajax.php') . '?' . http_build_query([
1051 'action' => $this->_prefix . '_downloadMyCodesAsPDF',
1052 'nonce' => $nonce
1053 ]);
1054 $ret .= '<p style="margin-top:10px;"><a href="' . esc_url($download_url) . '" class="button" target="_blank">' .
1055 esc_html($btn_label) . ' (' . $ticket_count . ')</a></p>';
1056 }
1057 }
1058 }
1059 if (empty($ret) && $this->getOptions()->isOptionCheckboxActive('userDisplayCodePrefixAlways')) {
1060 $ret .= $pre_text;
1061 }
1062 $ret = apply_filters( $this->_add_filter_prefix.'main_getMyCodeText', $ret, $user_id, $attr, $content, $tag);
1063 return $ret;
1064 }
1065
1066 /**
1067 * AJAX handler: Download all user's tickets as one PDF
1068 * Used by shortcode [sasoEventTicketsValidator_code download_all_pdf="true"]
1069 */
1070 public function downloadMyCodesAsPDF(): void {
1071 $user_id = get_current_user_id();
1072
1073 // Must be logged in
1074 if ($user_id <= 0) {
1075 wp_die(esc_html__('You must be logged in to download tickets.', 'event-tickets-with-ticket-scanner'), 403);
1076 }
1077
1078 // Verify nonce
1079 $nonce = isset($_GET['nonce']) ? sanitize_text_field($_GET['nonce']) : '';
1080 if (!wp_verify_nonce($nonce, 'download_my_codes_pdf_' . $user_id)) {
1081 wp_die(esc_html__('Security check failed. Please refresh the page and try again.', 'event-tickets-with-ticket-scanner'), 403);
1082 }
1083
1084 // Get user's codes
1085 $codes = $this->getCore()->getCodesByRegUserId($user_id);
1086
1087 if (empty($codes)) {
1088 wp_die(esc_html__('No tickets found.', 'event-tickets-with-ticket-scanner'), 404);
1089 }
1090
1091 // Limit to 100 tickets
1092 $max_tickets = 100;
1093 if (count($codes) > $max_tickets) {
1094 wp_die(
1095 sprintf(
1096 /* translators: %d: maximum number of tickets */
1097 esc_html__('Too many tickets. Maximum %d tickets can be downloaded at once.', 'event-tickets-with-ticket-scanner'),
1098 $max_tickets
1099 ),
1100 400
1101 );
1102 }
1103
1104 // Extract code strings
1105 $code_strings = array_map(function($codeObj) {
1106 return $codeObj['code'];
1107 }, $codes);
1108
1109 // Generate merged PDF
1110 $filename = 'my_tickets_' . wp_date('Ymd_Hi') . '.pdf';
1111
1112 try {
1113 $this->getTicketHandler()->generateOnePDFForCodes($code_strings, $filename, 'I');
1114 } catch (Exception $e) {
1115 $this->getAdmin()->logErrorToDB($e, null, 'downloadMyCodesAsPDF');
1116 wp_die(esc_html__('Error generating PDF. Please try again later.', 'event-tickets-with-ticket-scanner'), 500);
1117 }
1118
1119 exit;
1120 }
1121
1122 public function getMyCodeFormatted($user_id, $attr=[], $content = null, $tag = '') {
1123 $format = "json";
1124 if (isset($attr["format"])) {
1125 $format = strtolower(trim(sanitize_key($attr["format"])));
1126 }
1127 $display = ["codes"];
1128 if (isset($attr["display"])) {
1129
1130 $_d = trim(sanitize_text_field($attr["display"]));
1131 $_da = explode(",", $_d);
1132 if (count($_da) > 0) {
1133 $display = [];
1134 }
1135 foreach ($_da as $item) {
1136 $item = trim($item);
1137 $display[] = $item;
1138 }
1139 }
1140
1141 $output = [];
1142 //codes,validation,user,used,confirmedCount,woocommerce,wc_rp,wc_ticket
1143 $codes = $this->getCore()->getCodesByRegUserId($user_id);
1144 $metas = [];
1145 foreach($codes as $codeObj) {
1146 $metas[$codeObj["code"]] = $this->getCore()->encodeMetaValuesAndFillObject($codeObj['meta'], $codeObj);
1147 }
1148 foreach ($display as $item) {
1149 $output[$item] = [];
1150 if ($item == "codes") {
1151 foreach($codes as $codeObj) {
1152 if (isset($codeObj["meta"])) {
1153 unset($codeObj["meta"]);
1154 }
1155 $output[$item][] = $codeObj;
1156 }
1157 } elseif($item == "confirmedCount") {
1158 foreach($metas as $key => $meta) {
1159 $output[$item][] = array_merge(["value"=>$meta[$item]], ["code"=>$key]);
1160 }
1161 } else {
1162 foreach($metas as $key => $m) {
1163 if (is_array($m) && isset($m[$item])) {
1164 $meta = $m[$item];
1165 if (isset($meta["stats_redeemed"])) {
1166 unset($meta["stats_redeemed"]);
1167 }
1168 if (isset($meta["set_by_admin"])) {
1169 unset($meta["set_by_admin"]);
1170 }
1171 if (isset($meta["redeemed_by_admin"])) {
1172 unset($meta["redeemed_by_admin"]);
1173 }
1174 $output[$item][] = array_merge($meta, ["code"=>$key]);
1175 }
1176 }
1177 }
1178 }
1179
1180 switch($format) {
1181 case "json":
1182 default:
1183 $ret = $this->getCore()->json_encode_with_error_handling($output);
1184 }
1185 $ret = apply_filters( $this->_add_filter_prefix.'main_getMyCodeFormatted', $ret, $user_id, $attr, $content, $tag, $output);
1186 return $ret;
1187 }
1188
1189 public function replacingShortcodeMyCode($attr=[], $content = null, $tag = '') {
1190 $user_id = get_current_user_id();
1191
1192 if (count($attr) > 0 && isset($attr["format"])) {
1193 return $this->getMyCodeFormatted($user_id, $attr, $content, $tag);
1194 } else {
1195 return $this->getMyCodeText($user_id, $attr, $content, $tag);
1196 }
1197 }
1198
1199 public function replacingShortcodeFeatureList($attr=[], $content = null, $tag = '') {
1200 //$features = $this->getAdmin()->getOptions();
1201 //$options = $features["options"];
1202 $options = $this->getOptions()->getOptions();
1203 $features = [];
1204 $act_heading = "";
1205 foreach ($options as $option) {
1206 if ($option["key"] == "serial") continue;
1207 if ($option["type"] == "heading") {
1208 $act_heading = $option["key"];
1209 $features[$act_heading] = ["heading"=>$option, "options"=>[]];
1210 } else {
1211 if ($act_heading != "") {
1212 $features[$act_heading]["options"][] = $option;
1213 }
1214 }
1215 }
1216
1217 $ret = "";
1218 uasort($features, function($a, $b) {
1219 return strnatcasecmp($a["heading"]["label"], $b["heading"]["label"]);
1220 });
1221 foreach ($features as $key => $feature) {
1222 $ret .= '<h3>'.$feature["heading"]["label"].'</h3>';
1223 $video = $feature["heading"]["_doc_video"] != "" ? ' <a href="'.$feature["heading"]["_doc_video"].'" target="_blank"><span class="dashicons dashicons-video-alt3"></span> Introduction video</a>' : "";
1224 $ret .= '<p>'.trim($feature["heading"]["desc"].$video).'</p>';
1225 if (count($feature["options"]) > 0) {
1226 $ret .= '<ul>';
1227 foreach ($feature["options"] as $option) {
1228 $label = $option["label"];
1229 $desc = $option["desc"];
1230 $desc .= $option["_doc_video"] != "" ? ' <a href="'.$option["_doc_video"].'" target="_blank"><span class="dashicons dashicons-video-alt3"></span> Introduction video</a>' : "";
1231 $desc = trim($desc);
1232 if ($desc != "") {
1233 $desc = '<p>'.$desc.'</p>';
1234 }
1235 $label = '<span class="dashicons dashicons-yes"></span> '.$label;
1236 $ret .= '<li>'.$label.$desc.'</li>';
1237 }
1238 $ret .= '</ul>';
1239 }
1240 $ret .= '<hr>';
1241 }
1242
1243 return $ret;
1244 }
1245
1246 public function replacingShortcodeEventViews($attr=[], $content = null, $tag = '') {
1247 // iterate over all woocommerce products and check if they are an event
1248 $view = "calendar|list";
1249 if (isset($attr["view"])) {
1250 $view = strtolower(trim(sanitize_key($attr["view"])));
1251 }
1252 $months_to_show = 3;
1253 if (isset($attr["months_to_show"])) {
1254 $m = intval($attr["months_to_show"]);
1255 if ($m > 0) $months_to_show = $m;
1256 }
1257
1258 $month_start = strtotime(wp_date("Y-m-1 00:00:00"));
1259 //$month_end = strtotime(wp_date("Y-m-t 23:59:59"));
1260 $month_end = strtotime(wp_date("Y-m-1 23:59:59", strtotime("+".$months_to_show." month", $month_start)));
1261
1262 $products_args = array(
1263 'post_type' => 'product',
1264 'post_status' => 'publish',
1265 'posts_per_page' => -1, // -1 zeigt alle Produkte an
1266 'meta_query' => array(
1267 [
1268 'key' => 'saso_eventtickets_is_ticket',
1269 'value' => 'yes',
1270 'compare' => '='
1271 ]
1272 )
1273 );
1274 $posts = get_posts($products_args); // get only ticket products
1275
1276 $list_infos = [
1277 'months_to_show'=>$months_to_show,
1278 'month_start'=>$month_start,
1279 'month_end'=>$month_end,
1280 'view'=>$view
1281 ];
1282 $products_to_show = [];
1283 // Ergebnisse überprüfen
1284 foreach ($posts as $post) {
1285 $product_ids = [];
1286 $product = wc_get_product( $post->ID );
1287
1288 // check if event is variant product
1289 $is_variable = $product->get_type() == "variable";
1290 if ($is_variable) {
1291 // check if event dates are the same for all variants
1292 $date_is_for_all_variants = get_post_meta( $product_id, 'saso_eventtickets_is_date_for_all_variants', true ) == "yes" ? true : false;
1293 if ($date_is_for_all_variants == false) {
1294 // if not add also the variants
1295 $childs = $product->get_children();
1296 foreach ($childs as $child_id) {
1297 if (get_post_meta($child_id, '_saso_eventtickets_is_not_ticket', true) == "yes") {
1298 continue;
1299 }
1300 $product_ids[] = $child_id;
1301 }
1302 }
1303 } else {
1304 $product_ids[] = $product->get_id();
1305 }
1306
1307 foreach ($product_ids as $product_id) {
1308 $product = wc_get_product( $product_id );
1309 $dates = $this->getTicketHandler()->calcDateStringAllowedRedeemFrom($product_id);
1310 //if ($dates['ticket_end_date_timestamp'] > $month_start && $dates['ticket_start_date_timestamp'] < $month_end) {
1311 if ($dates['ticket_end_date_timestamp'] >= $month_start || ($dates['ticket_start_date_timestamp'] >= $month_start && $dates['ticket_start_date_timestamp'] <= $month_end)) {
1312 // set product to hidden
1313 $product_data = array(
1314 'ID' => $product_id,
1315 'dates' => $dates,
1316 'event'=> [
1317 'location' => trim(get_post_meta( $product_id, 'saso_eventtickets_event_location', true )),
1318 'location_label' => wp_kses_post(trim($this->getAdmin()->getOptionValue("wcTicketTransLocation")))
1319 ],
1320 'product' => [
1321 'title' => $product->get_name(),
1322 'url' => get_permalink($product_id),
1323 'price' =>$product->get_price(),
1324 'price_html' => $product->get_price_html(),
1325 'type' => $product->get_type(),
1326 ]
1327 );
1328 $products_to_show[] = $product_data;
1329 }
1330 }
1331 }
1332
1333 $divId = "sasoEventTicketsValidator_eventsview";
1334
1335 // add js for the events
1336 wp_enqueue_style("wp-jquery-ui-dialog");
1337
1338 $js_url = "ticket_events.js?_v=".$this->getPluginVersion();
1339 if (defined('WP_DEBUG')) $js_url .= '&t='.time();
1340 $js_url = plugins_url( $js_url,__FILE__ );
1341 wp_register_script('ajax_script_ticket_events', $js_url, array('jquery', 'jquery-ui-dialog', 'wp-i18n'));
1342 wp_enqueue_script('ajax_script_ticket_events');
1343 wp_set_script_translations('ajax_script_ticket_events', 'event-tickets-with-ticket-scanner', __DIR__.'/languages');
1344 wp_enqueue_style("ticket_events_css", plugins_url( "",__FILE__ ).'/css/calendar.css', [], true);
1345
1346 // add all events as an array for max 3 months??? or config parameter
1347 $vars = [
1348 'root' => esc_url_raw( rest_url() ),
1349 '_plugin_home_url' =>plugins_url( "",__FILE__ ),
1350 '_action' => $this->_prefix.'_executeFrontendEvents',
1351 '_isPremium'=>$this->isPremium(),
1352 '_isUserLoggedin'=>is_user_logged_in(),
1353 '_userId'=>get_current_user_id(),
1354 '_premJS'=>$this->isPremium() && method_exists($this->getPremiumFunctions(), "getJSFrontEventFile") ? $this->getPremiumFunctions()->getJSFrontEventFile() : '',
1355 '_siteUrl'=>get_site_url(),
1356 'events' => $products_to_show,
1357 'list_infos' => $list_infos,
1358 'format_date' => $this->getOptions()->getOptionDateFormat(),
1359 'format_time' => $this->getOptions()->getOptionTimeFormat(),
1360 'format_datetime' => $this->getOptions()->getOptionDateTimeFormat(),
1361 'url' => admin_url( 'admin-ajax.php' ),
1362 'nonce' => wp_create_nonce( $this->_js_nonce ),
1363 'ajaxActionPrefix' => $this->_prefix,
1364 'divId' => $divId
1365 ];
1366 $vars = apply_filters( $this->_add_filter_prefix.'main_setTicketEventJS', $vars );
1367 wp_localize_script(
1368 'ajax_script_ticket_events',
1369 'Ajax_ticket_events_'.$this->_prefix, // name der injected variable
1370 $vars
1371 );
1372
1373 do_action( $this->_do_action_prefix.'main_setTicketEventJS', $js_url );
1374
1375 $ret = '';
1376 if (!isset($attr['divid']) || trim($attr['divid']) == "") {
1377 $ret .= '<div id="'.$divId.'">'.__('...loading...', 'event-tickets-with-ticket-scanner').'</div>';
1378 }
1379
1380 $ret = apply_filters( $this->_add_filter_prefix.'main_replacingShortcodeEventViews', $ret );
1381 do_action( $this->_do_action_prefix.'main_replacingShortcodeEventViews', $vars, $ret );
1382
1383 return $ret;
1384 }
1385
1386 public function replaceShortcode($attr=[], $content = null, $tag = '') {
1387 // einbinden das js starter skript
1388 $js_url = $this->_js_file."?_v=".$this->_js_version;
1389 if (defined( 'WP_DEBUG')) $js_url .= '&debug=1';
1390 $userDivId = !isset($attr['divid']) || trim($attr['divid']) == "" ? '' : trim($attr['divid']);
1391
1392 $attr = array_change_key_case( (array) $attr, CASE_LOWER );
1393
1394 wp_enqueue_script(
1395 'ajax_script_validator',
1396 plugins_url( $js_url,__FILE__ ),
1397 array('jquery', 'wp-i18n')
1398 );
1399 wp_set_script_translations('ajax_script_validator', 'event-tickets-with-ticket-scanner', __DIR__.'/languages');
1400
1401 $vars = array(
1402 'shortcode_attr'=>json_encode($attr),
1403 '_plugin_home_url' =>plugins_url( "",__FILE__ ),
1404 '_action' => $this->_prefix.'_executeFrontend',
1405 '_isPremium'=>$this->isPremium(),
1406 '_isUserLoggedin'=>is_user_logged_in(),
1407 '_premJS'=>$this->isPremium() && method_exists($this->getPremiumFunctions(), "getJSFrontFile") ? $this->getPremiumFunctions()->getJSFrontFile() : '',
1408 'url' => admin_url( 'admin-ajax.php' ),
1409 'nonce' => wp_create_nonce( $this->_js_nonce ),
1410 'ajaxActionPrefix' => $this->_prefix,
1411 'divPrefix' => $userDivId == "" ? $this->_prefix : $userDivId,
1412 'divId' => $this->_divId,
1413 'jsFiles' => plugins_url( 'validator.js?_v='.$this->_js_version, __FILE__ )
1414 );
1415 $vars['_messages'] = [
1416 'msgCheck0'=>$this->getOptions()->getOptionValue('textValidationMessage0'),
1417 'msgCheck1'=>$this->getOptions()->getOptionValue('textValidationMessage1'),
1418 'msgCheck2'=>$this->getOptions()->getOptionValue('textValidationMessage2'),
1419 'msgCheck3'=>$this->getOptions()->getOptionValue('textValidationMessage3'),
1420 'msgCheck4'=>$this->getOptions()->getOptionValue('textValidationMessage4'),
1421 'msgCheck5'=>$this->getOptions()->getOptionValue('textValidationMessage5'),
1422 'msgCheck6'=>$this->getOptions()->getOptionValue('textValidationMessage6')
1423 ];
1424 $vars = apply_filters( $this->_add_filter_prefix.'main_replaceShortcode', $vars );
1425
1426 if ($this->isPremium() && method_exists($this->getPremiumFunctions(), "addJSFrontFile")) $this->getPremiumFunctions()->addJSFrontFile();
1427
1428 wp_localize_script(
1429 'ajax_script_validator',
1430 'Ajax_'.$this->_prefix, // name of the injected variable
1431 $vars
1432 );
1433 $ret = '';
1434 if (!isset($attr['divid']) || trim($attr['divid']) == "") {
1435 $ret .= '<div id="'.$this->_divId.'">'.__('...loading...', 'event-tickets-with-ticket-scanner').'</div>';
1436 }
1437
1438 $ret = apply_filters( $this->_add_filter_prefix.'main_replaceShortcode_2', $ret );
1439 do_action( $this->_do_action_prefix.'main_replaceShortcode', $vars, $ret );
1440
1441 return $ret;
1442 }
1443
1444 /**
1445 * Show admin notice when premium subscription is about to expire or has expired
1446 *
1447 * - Warning: 14 days before expiration
1448 * - Error: After expiration (during grace period or after)
1449 *
1450 * @return void
1451 */
1452 public function showSubscriptionWarning(): void {
1453 // Only show for premium users
1454 if (!$this->isPremium()) {
1455 return;
1456 }
1457
1458 // Only show in admin
1459 if (!is_admin()) {
1460 return;
1461 }
1462
1463 // Only show to users who can manage options
1464 if (!current_user_can('manage_options')) {
1465 return;
1466 }
1467
1468 $info = $this->getTicketHandler()->get_expiration();
1469
1470 // No expiration date or lifetime license - no warning needed
1471 if (empty($info['timestamp']) || $info['timestamp'] <= 0 || $info['timestamp'] == -1) {
1472 return;
1473 }
1474
1475 // Lifetime subscription type - no warning needed
1476 if (isset($info['subscription_type']) && $info['subscription_type'] === 'lifetime') {
1477 return;
1478 }
1479
1480 $days_left = ($info['timestamp'] - time()) / 86400;
1481 $renewal_url = 'https://vollstart.com/product/event-tickets-with-ticket-scanner/';
1482
1483 // Warning 14 days before expiration
1484 if ($days_left <= 14 && $days_left > 0) {
1485 $date = date_i18n(get_option('date_format'), $info['timestamp']);
1486 echo '<div class="notice notice-warning is-dismissible"><p>';
1487 printf(
1488 /* translators: %1$s: expiration date, %2$s: renewal URL */
1489 esc_html__('Your Event-Tickets Premium subscription expires on %1$s. %2$sRenew now%3$s to keep all features.', 'event-tickets-with-ticket-scanner'),
1490 '<strong>' . esc_html($date) . '</strong>',
1491 '<a href="' . esc_url($renewal_url) . '" target="_blank">',
1492 '</a>'
1493 );
1494 echo '</p></div>';
1495 }
1496
1497 // Error after expiration
1498 if ($days_left <= 0) {
1499 $grace_days = isset($info['grace_period_days']) ? intval($info['grace_period_days']) : 7;
1500 $grace_left = $grace_days + $days_left; // days_left is negative
1501
1502 echo '<div class="notice notice-error"><p>';
1503 if ($grace_left > 0) {
1504 printf(
1505 /* translators: %1$d: days remaining in grace period, %2$s: renewal URL */
1506 esc_html__('Your Premium subscription has expired. You have %1$d days remaining before features are disabled. %2$sReactivate now%3$s', 'event-tickets-with-ticket-scanner'),
1507 ceil($grace_left),
1508 '<a href="' . esc_url($renewal_url) . '" target="_blank">',
1509 '</a>'
1510 );
1511 } else {
1512 printf(
1513 /* translators: %1$s: renewal URL */
1514 esc_html__('Your Premium subscription has expired. Premium features are now limited. %1$sReactivate now%2$s', 'event-tickets-with-ticket-scanner'),
1515 '<a href="' . esc_url($renewal_url) . '" target="_blank">',
1516 '</a>'
1517 );
1518 }
1519 echo '</p></div>';
1520 }
1521 }
1522
1523 /**
1524 * Show admin notice when premium plugin version is outdated
1525 *
1526 * Encourages users with old premium versions to upgrade
1527 *
1528 * @return void
1529 */
1530 public function showOutdatedPremiumWarning(): void {
1531 // Only show if premium plugin is active
1532 if (!defined('SASO_EVENTTICKETS_PREMIUM_PLUGIN_VERSION')) {
1533 return;
1534 }
1535
1536 // Only show in admin
1537 if (!is_admin()) {
1538 return;
1539 }
1540
1541 // Only show to users who can manage options
1542 if (!current_user_can('manage_options')) {
1543 return;
1544 }
1545
1546 // Only show on our plugin pages
1547 $screen = get_current_screen();
1548 if ($screen === null || strpos($screen->id, 'saso-event-tickets') === false) {
1549 return;
1550 }
1551
1552 // Minimum recommended premium version
1553 $min_premium_version = '1.6.0';
1554
1555 if (version_compare(SASO_EVENTTICKETS_PREMIUM_PLUGIN_VERSION, $min_premium_version, '<')) {
1556 $upgrade_url = 'https://vollstart.com/product/event-tickets-with-ticket-scanner/';
1557 echo '<div class="notice notice-warning is-dismissible"><p>';
1558 printf(
1559 /* translators: %1$s: current version, %2$s: recommended version, %3$s: upgrade URL */
1560 esc_html__('Your Event-Tickets Premium plugin (v%1$s) is outdated. Version %2$s+ includes new features and improvements. %3$sUpgrade now%4$s', 'event-tickets-with-ticket-scanner'),
1561 esc_html(SASO_EVENTTICKETS_PREMIUM_PLUGIN_VERSION),
1562 esc_html($min_premium_version),
1563 '<a href="' . esc_url($upgrade_url) . '" target="_blank">',
1564 '</a>'
1565 );
1566 echo '</p></div>';
1567 }
1568 }
1569 }
1570 $sasoEventtickets = sasoEventtickets::Instance();
1571 ?>
1572