File manager - Edit - /home/premiey/www/wp-includes/images/media/page-bookings.tar
Back
_out/bookings__listing.js 0000666 00000210004 15166373417 0011571 0 ustar 00 "use strict"; function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } jQuery('body').on({ 'touchmove': function touchmove(e) { jQuery('.timespartly').each(function (index) { var td_el = jQuery(this).get(0); if (undefined != td_el._tippy) { var instance = td_el._tippy; instance.hide(); } }); } }); /** * Request Object * Here we can define Search parameters and Update it later, when some parameter was changed * */ var wpbc_ajx_booking_listing = function (obj, $) { // Secure parameters for Ajax ------------------------------------------------------------------------------------ var p_secure = obj.security_obj = obj.security_obj || { user_id: 0, nonce: '', locale: '' }; obj.set_secure_param = function (param_key, param_val) { p_secure[param_key] = param_val; }; obj.get_secure_param = function (param_key) { return p_secure[param_key]; }; // Listing Search parameters ------------------------------------------------------------------------------------ var p_listing = obj.search_request_obj = obj.search_request_obj || { sort: "booking_id", sort_type: "DESC", page_num: 1, page_items_count: 10, create_date: "", keyword: "", source: "" }; obj.search_set_all_params = function (request_param_obj) { p_listing = request_param_obj; }; obj.search_get_all_params = function () { return p_listing; }; obj.search_get_param = function (param_key) { return p_listing[param_key]; }; obj.search_set_param = function (param_key, param_val) { // if ( Array.isArray( param_val ) ){ // param_val = JSON.stringify( param_val ); // } p_listing[param_key] = param_val; }; obj.search_set_params_arr = function (params_arr) { _.each(params_arr, function (p_val, p_key, p_data) { // Define different Search parameters for request this.search_set_param(p_key, p_val); }); }; // Other parameters ------------------------------------------------------------------------------------ var p_other = obj.other_obj = obj.other_obj || {}; obj.set_other_param = function (param_key, param_val) { p_other[param_key] = param_val; }; obj.get_other_param = function (param_key) { return p_other[param_key]; }; return obj; }(wpbc_ajx_booking_listing || {}, jQuery); /** * Ajax ------------------------------------------------------------------------------------------------------ */ /** * Send Ajax search request * for searching specific Keyword and other params */ function wpbc_ajx_booking_ajax_search_request() { console.groupCollapsed('AJX_BOOKING_LISTING'); console.log(' == Before Ajax Send - search_get_all_params() == ', wpbc_ajx_booking_listing.search_get_all_params()); wpbc_booking_listing_reload_button__spin_start(); /* //FixIn: forVideo if ( ! is_this_action ){ //wpbc_ajx_booking__actual_listing__hide(); jQuery( wpbc_ajx_booking_listing.get_other_param( 'listing_container' ) ).html( '<div style="width:100%;text-align: center;" id="wpbc_loading_section"><span class="wpbc_icn_autorenew wpbc_spin"></span></div>' + jQuery( wpbc_ajx_booking_listing.get_other_param( 'listing_container' ) ).html() ); if ( 'function' === typeof (jQuery( '#wpbc_loading_section' ).wpbc_my_modal) ){ //FixIn: 9.0.1.5 jQuery( '#wpbc_loading_section' ).wpbc_my_modal( 'show' ); } else { alert( 'Warning! Booking Calendar. Its seems that you have deactivated loading of Bootstrap JS files at Booking Settings General page in Advanced section.' ) } } is_this_action = false; */ // Start Ajax jQuery.post(wpbc_url_ajax, { action: 'WPBC_AJX_BOOKING_LISTING', wpbc_ajx_user_id: wpbc_ajx_booking_listing.get_secure_param('user_id'), nonce: wpbc_ajx_booking_listing.get_secure_param('nonce'), wpbc_ajx_locale: wpbc_ajx_booking_listing.get_secure_param('locale'), search_params: wpbc_ajx_booking_listing.search_get_all_params() }, /** * S u c c e s s * * @param response_data - its object returned from Ajax - class-live-searcg.php * @param textStatus - 'success' * @param jqXHR - Object */ function (response_data, textStatus, jqXHR) { //FixIn: forVideo //jQuery( '#wpbc_loading_section' ).wpbc_my_modal( 'hide' ); console.log(' == Response WPBC_AJX_BOOKING_LISTING == ', response_data); console.groupEnd(); // Probably Error if (_typeof(response_data) !== 'object' || response_data === null) { jQuery('.wpbc_ajx_under_toolbar_row').hide(); //FixIn: 9.6.1.5 jQuery(wpbc_ajx_booking_listing.get_other_param('listing_container')).html('<div class="wpbc-settings-notice notice-warning" style="text-align:left">' + response_data + '</div>'); return; } // Reload page, after filter toolbar was reseted if (undefined != response_data['ajx_cleaned_params'] && 'reset_done' === response_data['ajx_cleaned_params']['ui_reset']) { location.reload(); return; } // Show listing if (response_data['ajx_count'] > 0) { wpbc_ajx_booking_show_listing(response_data['ajx_items'], response_data['ajx_search_params'], response_data['ajx_booking_resources']); wpbc_pagination_echo(wpbc_ajx_booking_listing.get_other_param('pagination_container'), { 'page_active': response_data['ajx_search_params']['page_num'], 'pages_count': Math.ceil(response_data['ajx_count'] / response_data['ajx_search_params']['page_items_count']), 'page_items_count': response_data['ajx_search_params']['page_items_count'], 'sort_type': response_data['ajx_search_params']['sort_type'] }); wpbc_ajx_booking_define_ui_hooks(); // Redefine Hooks, because we show new DOM elements } else { wpbc_ajx_booking__actual_listing__hide(); jQuery(wpbc_ajx_booking_listing.get_other_param('listing_container')).html('<div class="wpbc-settings-notice0 notice-warning0" style="text-align:center;margin-left:-50px;">' + '<strong>' + 'No results found for current filter options...' + '</strong>' + //'<strong>' + 'No results found...' + '</strong>' + '</div>'); } // Update new booking count if (undefined !== response_data['ajx_new_bookings_count']) { var ajx_new_bookings_count = parseInt(response_data['ajx_new_bookings_count']); if (ajx_new_bookings_count > 0) { jQuery('.wpbc_badge_count').show(); } jQuery('.bk-update-count').html(ajx_new_bookings_count); } wpbc_booking_listing_reload_button__spin_pause(); jQuery('#ajax_respond').html(response_data); // For ability to show response, add such DIV element to page }).fail(function (jqXHR, textStatus, errorThrown) { if (window.console && window.console.log) { console.log('Ajax_Error', jqXHR, textStatus, errorThrown); } jQuery('.wpbc_ajx_under_toolbar_row').hide(); //FixIn: 9.6.1.5 var error_message = '<strong>' + 'Error!' + '</strong> ' + errorThrown; if (jqXHR.responseText) { error_message += jqXHR.responseText; } error_message = error_message.replace(/\n/g, "<br />"); wpbc_ajx_booking_show_message(error_message); }) // .done( function ( data, textStatus, jqXHR ) { if ( window.console && window.console.log ){ console.log( 'second success', data, textStatus, jqXHR ); } }) // .always( function ( data_jqXHR, textStatus, jqXHR_errorThrown ) { if ( window.console && window.console.log ){ console.log( 'always finished', data_jqXHR, textStatus, jqXHR_errorThrown ); } }) ; // End Ajax } /** * Views ----------------------------------------------------------------------------------------------------- */ /** * Show Listing Table and define gMail checkbox hooks * * @param json_items_arr - JSON object with Items * @param json_search_params - JSON object with Search */ function wpbc_ajx_booking_show_listing(json_items_arr, json_search_params, json_booking_resources) { wpbc_ajx_define_templates__resource_manipulation(json_items_arr, json_search_params, json_booking_resources); //console.log( 'json_items_arr' , json_items_arr, json_search_params ); jQuery('.wpbc_ajx_under_toolbar_row').css("display", "flex"); //FixIn: 9.6.1.5 var list_header_tpl = wp.template('wpbc_ajx_booking_list_header'); var list_row_tpl = wp.template('wpbc_ajx_booking_list_row'); // Header jQuery(wpbc_ajx_booking_listing.get_other_param('listing_container')).html(list_header_tpl()); // Body jQuery(wpbc_ajx_booking_listing.get_other_param('listing_container')).append('<div class="wpbc_selectable_body"></div>'); // R o w s console.groupCollapsed('LISTING_ROWS'); // LISTING_ROWS _.each(json_items_arr, function (p_val, p_key, p_data) { if ('undefined' !== typeof json_search_params['keyword']) { // Parameter for marking keyword with different color in a list p_val['__search_request_keyword__'] = json_search_params['keyword']; } else { p_val['__search_request_keyword__'] = ''; } p_val['booking_resources'] = json_booking_resources; jQuery(wpbc_ajx_booking_listing.get_other_param('listing_container') + ' .wpbc_selectable_body').append(list_row_tpl(p_val)); }); console.groupEnd(); // LISTING_ROWS wpbc_define_gmail_checkbox_selection(jQuery); // Redefine Hooks for clicking at Checkboxes } /** * Define template for changing booking resources & update it each time, when listing updating, useful for showing actual booking resources. * * @param json_items_arr - JSON object with Items * @param json_search_params - JSON object with Search * @param json_booking_resources - JSON object with Resources */ function wpbc_ajx_define_templates__resource_manipulation(json_items_arr, json_search_params, json_booking_resources) { // Change booking resource var change_booking_resource_tpl = wp.template('wpbc_ajx_change_booking_resource'); jQuery('#wpbc_hidden_template__change_booking_resource').html(change_booking_resource_tpl({ 'ajx_search_params': json_search_params, 'ajx_booking_resources': json_booking_resources })); // Duplicate booking resource var duplicate_booking_to_other_resource_tpl = wp.template('wpbc_ajx_duplicate_booking_to_other_resource'); jQuery('#wpbc_hidden_template__duplicate_booking_to_other_resource').html(duplicate_booking_to_other_resource_tpl({ 'ajx_search_params': json_search_params, 'ajx_booking_resources': json_booking_resources })); } /** * Show just message instead of listing and hide pagination */ function wpbc_ajx_booking_show_message(message) { wpbc_ajx_booking__actual_listing__hide(); jQuery(wpbc_ajx_booking_listing.get_other_param('listing_container')).html('<div class="wpbc-settings-notice notice-warning" style="text-align:left">' + message + '</div>'); } /** * H o o k s - its Action/Times when need to re-Render Views ----------------------------------------------- */ /** * Send Ajax Search Request after Updating search request parameters * * @param params_arr */ function wpbc_ajx_booking_send_search_request_with_params(params_arr) { // Define different Search parameters for request _.each(params_arr, function (p_val, p_key, p_data) { //console.log( 'Request for: ', p_key, p_val ); wpbc_ajx_booking_listing.search_set_param(p_key, p_val); }); // Send Ajax Request wpbc_ajx_booking_ajax_search_request(); } /** * Search request for "Page Number" * @param page_number int */ function wpbc_ajx_booking_pagination_click(page_number) { wpbc_ajx_booking_send_search_request_with_params({ 'page_num': page_number }); } /** * Keyword Searching ----------------------------------------------------------------------------------------- */ /** * Search request for "Keyword", also set current page to 1 * * @param element_id - HTML ID of element, where was entered keyword */ function wpbc_ajx_booking_send_search_request_for_keyword(element_id) { // We need to Reset page_num to 1 with each new search, because we can be at page #4, but after new search we can have totally only 1 page wpbc_ajx_booking_send_search_request_with_params({ 'keyword': jQuery(element_id).val(), 'page_num': 1 }); } /** * Send search request after few seconds (usually after 1,5 sec) * Closure function. Its useful, for do not send too many Ajax requests, when someone make fast typing. */ var wpbc_ajx_booking_searching_after_few_seconds = function () { var closed_timer = 0; return function (element_id, timer_delay) { // Get default value of "timer_delay", if parameter was not passed into the function. timer_delay = typeof timer_delay !== 'undefined' ? timer_delay : 1500; clearTimeout(closed_timer); // Clear previous timer // Start new Timer closed_timer = setTimeout(wpbc_ajx_booking_send_search_request_for_keyword.bind(null, element_id), timer_delay); }; }(); /** * Define Dynamic Hooks (like pagination click, which renew each time with new listing showing) ------------- */ /** * Define HTML ui Hooks: on KeyUp | Change | -> Sort Order & Number Items / Page * We are hcnaged it each time, when showing new listing, because DOM elements chnaged */ function wpbc_ajx_booking_define_ui_hooks() { if ('function' === typeof wpbc_define_tippy_tooltips) { wpbc_define_tippy_tooltips('.wpbc_listing_container '); } wpbc_ajx_booking__ui_define__locale(); wpbc_ajx_booking__ui_define__remark(); // Items Per Page jQuery('.wpbc_items_per_page').on('change', function (event) { wpbc_ajx_booking_send_search_request_with_params({ 'page_items_count': jQuery(this).val(), 'page_num': 1 }); }); // Sorting jQuery('.wpbc_items_sort_type').on('change', function (event) { wpbc_ajx_booking_send_search_request_with_params({ 'sort_type': jQuery(this).val() }); }); } /** * Show / Hide Listing --------------------------------------------------------------------------------------- */ /** * Show Listing Table - Sending Ajax Request - with parameters that we early defined in "wpbc_ajx_booking_listing" Obj. */ function wpbc_ajx_booking__actual_listing__show() { wpbc_ajx_booking_ajax_search_request(); // Send Ajax Request - with parameters that we early defined in "wpbc_ajx_booking_listing" Obj. } /** * Hide Listing Table ( and Pagination ) */ function wpbc_ajx_booking__actual_listing__hide() { jQuery('.wpbc_ajx_under_toolbar_row').hide(); //FixIn: 9.6.1.5 jQuery(wpbc_ajx_booking_listing.get_other_param('listing_container')).html(''); jQuery(wpbc_ajx_booking_listing.get_other_param('pagination_container')).html(''); } /** * Support functions for Content Template data --------------------------------------------------------------- */ /** * Highlight strings, * by inserting <span class="fieldvalue name fieldsearchvalue">...</span> html elements into the string. * @param {string} booking_details - Source string * @param {string} booking_keyword - Keyword to highlight * @returns {string} */ function wpbc_get_highlighted_search_keyword(booking_details, booking_keyword) { booking_keyword = booking_keyword.trim().toLowerCase(); if (0 == booking_keyword.length) { return booking_details; } // Highlight substring withing HTML tags in "Content of booking fields data" -- e.g. starting from > and ending with < var keywordRegex = new RegExp("fieldvalue[^<>]*>([^<]*".concat(booking_keyword, "[^<]*)"), 'gim'); //let matches = [...booking_details.toLowerCase().matchAll( keywordRegex )]; var matches = booking_details.toLowerCase().matchAll(keywordRegex); matches = Array.from(matches); var strings_arr = []; var pos_previous = 0; var search_pos_start; var search_pos_end; var _iterator = _createForOfIteratorHelper(matches), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var match = _step.value; search_pos_start = match.index + match[0].toLowerCase().indexOf('>', 0) + 1; strings_arr.push(booking_details.substr(pos_previous, search_pos_start - pos_previous)); search_pos_end = booking_details.toLowerCase().indexOf('<', search_pos_start); strings_arr.push('<span class="fieldvalue name fieldsearchvalue">' + booking_details.substr(search_pos_start, search_pos_end - search_pos_start) + '</span>'); pos_previous = search_pos_end; } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } strings_arr.push(booking_details.substr(pos_previous, booking_details.length - pos_previous)); return strings_arr.join(''); } /** * Convert special HTML characters from: & -> & * * @param text * @returns {*} */ function wpbc_decode_HTML_entities(text) { var textArea = document.createElement('textarea'); textArea.innerHTML = text; return textArea.value; } /** * Convert TO special HTML characters from: & -> & * * @param text * @returns {*} */ function wpbc_encode_HTML_entities(text) { var textArea = document.createElement('textarea'); textArea.innerText = text; return textArea.innerHTML; } /** * Support Functions - Spin Icon in Buttons ------------------------------------------------------------------ */ /** * Spin button in Filter toolbar - Start */ function wpbc_booking_listing_reload_button__spin_start() { jQuery('#wpbc_booking_listing_reload_button .menu_icon.wpbc_spin').removeClass('wpbc_animation_pause'); } /** * Spin button in Filter toolbar - Pause */ function wpbc_booking_listing_reload_button__spin_pause() { jQuery('#wpbc_booking_listing_reload_button .menu_icon.wpbc_spin').addClass('wpbc_animation_pause'); } /** * Spin button in Filter toolbar - is Spinning ? * * @returns {boolean} */ function wpbc_booking_listing_reload_button__is_spin() { if (jQuery('#wpbc_booking_listing_reload_button .menu_icon.wpbc_spin').hasClass('wpbc_animation_pause')) { return true; } else { return false; } } //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5jbHVkZXMvcGFnZS1ib29raW5ncy9fb3V0L2Jvb2tpbmdzX19saXN0aW5nLmpzIiwibmFtZXMiOlsiX2NyZWF0ZUZvck9mSXRlcmF0b3JIZWxwZXIiLCJvIiwiYWxsb3dBcnJheUxpa2UiLCJpdCIsIlN5bWJvbCIsIml0ZXJhdG9yIiwiQXJyYXkiLCJpc0FycmF5IiwiX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5IiwibGVuZ3RoIiwiaSIsIkYiLCJzIiwibiIsImRvbmUiLCJ2YWx1ZSIsImUiLCJfZSIsImYiLCJUeXBlRXJyb3IiLCJub3JtYWxDb21wbGV0aW9uIiwiZGlkRXJyIiwiZXJyIiwiY2FsbCIsInN0ZXAiLCJuZXh0IiwiX2UyIiwibWluTGVuIiwiX2FycmF5TGlrZVRvQXJyYXkiLCJPYmplY3QiLCJwcm90b3R5cGUiLCJ0b1N0cmluZyIsInNsaWNlIiwiY29uc3RydWN0b3IiLCJuYW1lIiwiZnJvbSIsInRlc3QiLCJhcnIiLCJsZW4iLCJhcnIyIiwiX3R5cGVvZiIsIm9iaiIsImpRdWVyeSIsIm9uIiwidG91Y2htb3ZlIiwiZWFjaCIsImluZGV4IiwidGRfZWwiLCJnZXQiLCJ1bmRlZmluZWQiLCJfdGlwcHkiLCJpbnN0YW5jZSIsImhpZGUiLCJ3cGJjX2FqeF9ib29raW5nX2xpc3RpbmciLCIkIiwicF9zZWN1cmUiLCJzZWN1cml0eV9vYmoiLCJ1c2VyX2lkIiwibm9uY2UiLCJsb2NhbGUiLCJzZXRfc2VjdXJlX3BhcmFtIiwicGFyYW1fa2V5IiwicGFyYW1fdmFsIiwiZ2V0X3NlY3VyZV9wYXJhbSIsInBfbGlzdGluZyIsInNlYXJjaF9yZXF1ZXN0X29iaiIsInNvcnQiLCJzb3J0X3R5cGUiLCJwYWdlX251bSIsInBhZ2VfaXRlbXNfY291bnQiLCJjcmVhdGVfZGF0ZSIsImtleXdvcmQiLCJzb3VyY2UiLCJzZWFyY2hfc2V0X2FsbF9wYXJhbXMiLCJyZXF1ZXN0X3BhcmFtX29iaiIsInNlYXJjaF9nZXRfYWxsX3BhcmFtcyIsInNlYXJjaF9nZXRfcGFyYW0iLCJzZWFyY2hfc2V0X3BhcmFtIiwic2VhcmNoX3NldF9wYXJhbXNfYXJyIiwicGFyYW1zX2FyciIsIl8iLCJwX3ZhbCIsInBfa2V5IiwicF9kYXRhIiwicF9vdGhlciIsIm90aGVyX29iaiIsInNldF9vdGhlcl9wYXJhbSIsImdldF9vdGhlcl9wYXJhbSIsIndwYmNfYWp4X2Jvb2tpbmdfYWpheF9zZWFyY2hfcmVxdWVzdCIsImNvbnNvbGUiLCJncm91cENvbGxhcHNlZCIsImxvZyIsIndwYmNfYm9va2luZ19saXN0aW5nX3JlbG9hZF9idXR0b25fX3NwaW5fc3RhcnQiLCJwb3N0Iiwid3BiY191cmxfYWpheCIsImFjdGlvbiIsIndwYmNfYWp4X3VzZXJfaWQiLCJ3cGJjX2FqeF9sb2NhbGUiLCJzZWFyY2hfcGFyYW1zIiwicmVzcG9uc2VfZGF0YSIsInRleHRTdGF0dXMiLCJqcVhIUiIsImdyb3VwRW5kIiwiaHRtbCIsImxvY2F0aW9uIiwicmVsb2FkIiwid3BiY19hanhfYm9va2luZ19zaG93X2xpc3RpbmciLCJ3cGJjX3BhZ2luYXRpb25fZWNobyIsIk1hdGgiLCJjZWlsIiwid3BiY19hanhfYm9va2luZ19kZWZpbmVfdWlfaG9va3MiLCJ3cGJjX2FqeF9ib29raW5nX19hY3R1YWxfbGlzdGluZ19faGlkZSIsImFqeF9uZXdfYm9va2luZ3NfY291bnQiLCJwYXJzZUludCIsInNob3ciLCJ3cGJjX2Jvb2tpbmdfbGlzdGluZ19yZWxvYWRfYnV0dG9uX19zcGluX3BhdXNlIiwiZmFpbCIsImVycm9yVGhyb3duIiwid2luZG93IiwiZXJyb3JfbWVzc2FnZSIsInJlc3BvbnNlVGV4dCIsInJlcGxhY2UiLCJ3cGJjX2FqeF9ib29raW5nX3Nob3dfbWVzc2FnZSIsImpzb25faXRlbXNfYXJyIiwianNvbl9zZWFyY2hfcGFyYW1zIiwianNvbl9ib29raW5nX3Jlc291cmNlcyIsIndwYmNfYWp4X2RlZmluZV90ZW1wbGF0ZXNfX3Jlc291cmNlX21hbmlwdWxhdGlvbiIsImNzcyIsImxpc3RfaGVhZGVyX3RwbCIsIndwIiwidGVtcGxhdGUiLCJsaXN0X3Jvd190cGwiLCJhcHBlbmQiLCJ3cGJjX2RlZmluZV9nbWFpbF9jaGVja2JveF9zZWxlY3Rpb24iLCJjaGFuZ2VfYm9va2luZ19yZXNvdXJjZV90cGwiLCJkdXBsaWNhdGVfYm9va2luZ190b19vdGhlcl9yZXNvdXJjZV90cGwiLCJtZXNzYWdlIiwid3BiY19hanhfYm9va2luZ19zZW5kX3NlYXJjaF9yZXF1ZXN0X3dpdGhfcGFyYW1zIiwid3BiY19hanhfYm9va2luZ19wYWdpbmF0aW9uX2NsaWNrIiwicGFnZV9udW1iZXIiLCJ3cGJjX2FqeF9ib29raW5nX3NlbmRfc2VhcmNoX3JlcXVlc3RfZm9yX2tleXdvcmQiLCJlbGVtZW50X2lkIiwidmFsIiwid3BiY19hanhfYm9va2luZ19zZWFyY2hpbmdfYWZ0ZXJfZmV3X3NlY29uZHMiLCJjbG9zZWRfdGltZXIiLCJ0aW1lcl9kZWxheSIsImNsZWFyVGltZW91dCIsInNldFRpbWVvdXQiLCJiaW5kIiwid3BiY19kZWZpbmVfdGlwcHlfdG9vbHRpcHMiLCJ3cGJjX2FqeF9ib29raW5nX191aV9kZWZpbmVfX2xvY2FsZSIsIndwYmNfYWp4X2Jvb2tpbmdfX3VpX2RlZmluZV9fcmVtYXJrIiwiZXZlbnQiLCJ3cGJjX2FqeF9ib29raW5nX19hY3R1YWxfbGlzdGluZ19fc2hvdyIsIndwYmNfZ2V0X2hpZ2hsaWdodGVkX3NlYXJjaF9rZXl3b3JkIiwiYm9va2luZ19kZXRhaWxzIiwiYm9va2luZ19rZXl3b3JkIiwidHJpbSIsInRvTG93ZXJDYXNlIiwia2V5d29yZFJlZ2V4IiwiUmVnRXhwIiwiY29uY2F0IiwibWF0Y2hlcyIsIm1hdGNoQWxsIiwic3RyaW5nc19hcnIiLCJwb3NfcHJldmlvdXMiLCJzZWFyY2hfcG9zX3N0YXJ0Iiwic2VhcmNoX3Bvc19lbmQiLCJfaXRlcmF0b3IiLCJfc3RlcCIsIm1hdGNoIiwiaW5kZXhPZiIsInB1c2giLCJzdWJzdHIiLCJqb2luIiwid3BiY19kZWNvZGVfSFRNTF9lbnRpdGllcyIsInRleHQiLCJ0ZXh0QXJlYSIsImRvY3VtZW50IiwiY3JlYXRlRWxlbWVudCIsImlubmVySFRNTCIsIndwYmNfZW5jb2RlX0hUTUxfZW50aXRpZXMiLCJpbm5lclRleHQiLCJyZW1vdmVDbGFzcyIsImFkZENsYXNzIiwid3BiY19ib29raW5nX2xpc3RpbmdfcmVsb2FkX2J1dHRvbl9faXNfc3BpbiIsImhhc0NsYXNzIl0sInNvdXJjZXMiOlsiaW5jbHVkZXMvcGFnZS1ib29raW5ncy9fc3JjL2Jvb2tpbmdzX19saXN0aW5nLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIlwidXNlIHN0cmljdFwiO1xyXG5cclxualF1ZXJ5KCdib2R5Jykub24oe1xyXG4gICAgJ3RvdWNobW92ZSc6IGZ1bmN0aW9uKGUpIHtcclxuXHJcblx0XHRqUXVlcnkoICcudGltZXNwYXJ0bHknICkuZWFjaCggZnVuY3Rpb24gKCBpbmRleCApe1xyXG5cclxuXHRcdFx0dmFyIHRkX2VsID0galF1ZXJ5KCB0aGlzICkuZ2V0KCAwICk7XHJcblxyXG5cdFx0XHRpZiAoICh1bmRlZmluZWQgIT0gdGRfZWwuX3RpcHB5KSApe1xyXG5cclxuXHRcdFx0XHR2YXIgaW5zdGFuY2UgPSB0ZF9lbC5fdGlwcHk7XHJcblx0XHRcdFx0aW5zdGFuY2UuaGlkZSgpO1xyXG5cdFx0XHR9XHJcblx0XHR9ICk7XHJcblx0fVxyXG59KTtcclxuXHJcbi8qKlxyXG4gKiBSZXF1ZXN0IE9iamVjdFxyXG4gKiBIZXJlIHdlIGNhbiAgZGVmaW5lIFNlYXJjaCBwYXJhbWV0ZXJzIGFuZCBVcGRhdGUgaXQgbGF0ZXIsICB3aGVuICBzb21lIHBhcmFtZXRlciB3YXMgY2hhbmdlZFxyXG4gKlxyXG4gKi9cclxudmFyIHdwYmNfYWp4X2Jvb2tpbmdfbGlzdGluZyA9IChmdW5jdGlvbiAoIG9iaiwgJCkge1xyXG5cclxuXHQvLyBTZWN1cmUgcGFyYW1ldGVycyBmb3IgQWpheFx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0dmFyIHBfc2VjdXJlID0gb2JqLnNlY3VyaXR5X29iaiA9IG9iai5zZWN1cml0eV9vYmogfHwge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR1c2VyX2lkOiAwLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRub25jZSAgOiAnJyxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0bG9jYWxlIDogJydcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCAgfTtcclxuXHJcblx0b2JqLnNldF9zZWN1cmVfcGFyYW0gPSBmdW5jdGlvbiAoIHBhcmFtX2tleSwgcGFyYW1fdmFsICkge1xyXG5cdFx0cF9zZWN1cmVbIHBhcmFtX2tleSBdID0gcGFyYW1fdmFsO1xyXG5cdH07XHJcblxyXG5cdG9iai5nZXRfc2VjdXJlX3BhcmFtID0gZnVuY3Rpb24gKCBwYXJhbV9rZXkgKSB7XHJcblx0XHRyZXR1cm4gcF9zZWN1cmVbIHBhcmFtX2tleSBdO1xyXG5cdH07XHJcblxyXG5cclxuXHQvLyBMaXN0aW5nIFNlYXJjaCBwYXJhbWV0ZXJzXHQtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHR2YXIgcF9saXN0aW5nID0gb2JqLnNlYXJjaF9yZXF1ZXN0X29iaiA9IG9iai5zZWFyY2hfcmVxdWVzdF9vYmogfHwge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRzb3J0ICAgICAgICAgICAgOiBcImJvb2tpbmdfaWRcIixcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0c29ydF90eXBlICAgICAgIDogXCJERVNDXCIsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHBhZ2VfbnVtICAgICAgICA6IDEsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHBhZ2VfaXRlbXNfY291bnQ6IDEwLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRjcmVhdGVfZGF0ZSAgICAgOiBcIlwiLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRrZXl3b3JkICAgICAgICAgOiBcIlwiLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRzb3VyY2UgICAgICAgICAgOiBcIlwiXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9O1xyXG5cclxuXHRvYmouc2VhcmNoX3NldF9hbGxfcGFyYW1zID0gZnVuY3Rpb24gKCByZXF1ZXN0X3BhcmFtX29iaiApIHtcclxuXHRcdHBfbGlzdGluZyA9IHJlcXVlc3RfcGFyYW1fb2JqO1xyXG5cdH07XHJcblxyXG5cdG9iai5zZWFyY2hfZ2V0X2FsbF9wYXJhbXMgPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gcF9saXN0aW5nO1xyXG5cdH07XHJcblxyXG5cdG9iai5zZWFyY2hfZ2V0X3BhcmFtID0gZnVuY3Rpb24gKCBwYXJhbV9rZXkgKSB7XHJcblx0XHRyZXR1cm4gcF9saXN0aW5nWyBwYXJhbV9rZXkgXTtcclxuXHR9O1xyXG5cclxuXHRvYmouc2VhcmNoX3NldF9wYXJhbSA9IGZ1bmN0aW9uICggcGFyYW1fa2V5LCBwYXJhbV92YWwgKSB7XHJcblx0XHQvLyBpZiAoIEFycmF5LmlzQXJyYXkoIHBhcmFtX3ZhbCApICl7XHJcblx0XHQvLyBcdHBhcmFtX3ZhbCA9IEpTT04uc3RyaW5naWZ5KCBwYXJhbV92YWwgKTtcclxuXHRcdC8vIH1cclxuXHRcdHBfbGlzdGluZ1sgcGFyYW1fa2V5IF0gPSBwYXJhbV92YWw7XHJcblx0fTtcclxuXHJcblx0b2JqLnNlYXJjaF9zZXRfcGFyYW1zX2FyciA9IGZ1bmN0aW9uKCBwYXJhbXNfYXJyICl7XHJcblx0XHRfLmVhY2goIHBhcmFtc19hcnIsIGZ1bmN0aW9uICggcF92YWwsIHBfa2V5LCBwX2RhdGEgKXtcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBEZWZpbmUgZGlmZmVyZW50IFNlYXJjaCAgcGFyYW1ldGVycyBmb3IgcmVxdWVzdFxyXG5cdFx0XHR0aGlzLnNlYXJjaF9zZXRfcGFyYW0oIHBfa2V5LCBwX3ZhbCApO1xyXG5cdFx0fSApO1xyXG5cdH1cclxuXHJcblxyXG5cdC8vIE90aGVyIHBhcmFtZXRlcnMgXHRcdFx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0dmFyIHBfb3RoZXIgPSBvYmoub3RoZXJfb2JqID0gb2JqLm90aGVyX29iaiB8fCB7IH07XHJcblxyXG5cdG9iai5zZXRfb3RoZXJfcGFyYW0gPSBmdW5jdGlvbiAoIHBhcmFtX2tleSwgcGFyYW1fdmFsICkge1xyXG5cdFx0cF9vdGhlclsgcGFyYW1fa2V5IF0gPSBwYXJhbV92YWw7XHJcblx0fTtcclxuXHJcblx0b2JqLmdldF9vdGhlcl9wYXJhbSA9IGZ1bmN0aW9uICggcGFyYW1fa2V5ICkge1xyXG5cdFx0cmV0dXJuIHBfb3RoZXJbIHBhcmFtX2tleSBdO1xyXG5cdH07XHJcblxyXG5cclxuXHRyZXR1cm4gb2JqO1xyXG59KCB3cGJjX2FqeF9ib29raW5nX2xpc3RpbmcgfHwge30sIGpRdWVyeSApKTtcclxuXHJcblxyXG4vKipcclxuICogICBBamF4ICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cclxuXHJcbi8qKlxyXG4gKiBTZW5kIEFqYXggc2VhcmNoIHJlcXVlc3RcclxuICogZm9yIHNlYXJjaGluZyBzcGVjaWZpYyBLZXl3b3JkIGFuZCBvdGhlciBwYXJhbXNcclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYWp4X2Jvb2tpbmdfYWpheF9zZWFyY2hfcmVxdWVzdCgpe1xyXG5cclxuY29uc29sZS5ncm91cENvbGxhcHNlZCgnQUpYX0JPT0tJTkdfTElTVElORycpOyBjb25zb2xlLmxvZyggJyA9PSBCZWZvcmUgQWpheCBTZW5kIC0gc2VhcmNoX2dldF9hbGxfcGFyYW1zKCkgPT0gJyAsIHdwYmNfYWp4X2Jvb2tpbmdfbGlzdGluZy5zZWFyY2hfZ2V0X2FsbF9wYXJhbXMoKSApO1xyXG5cclxuXHR3cGJjX2Jvb2tpbmdfbGlzdGluZ19yZWxvYWRfYnV0dG9uX19zcGluX3N0YXJ0KCk7XHJcblxyXG4vKlxyXG4vL0ZpeEluOiBmb3JWaWRlb1xyXG5pZiAoICEgaXNfdGhpc19hY3Rpb24gKXtcclxuXHQvL3dwYmNfYWp4X2Jvb2tpbmdfX2FjdHVhbF9saXN0aW5nX19oaWRlKCk7XHJcblx0alF1ZXJ5KCB3cGJjX2FqeF9ib29raW5nX2xpc3RpbmcuZ2V0X290aGVyX3BhcmFtKCAnbGlzdGluZ19jb250YWluZXInICkgKS5odG1sKFxyXG5cdFx0JzxkaXYgc3R5bGU9XCJ3aWR0aDoxMDAlO3RleHQtYWxpZ246IGNlbnRlcjtcIiBpZD1cIndwYmNfbG9hZGluZ19zZWN0aW9uXCI+PHNwYW4gY2xhc3M9XCJ3cGJjX2ljbl9hdXRvcmVuZXcgd3BiY19zcGluXCI+PC9zcGFuPjwvZGl2PidcclxuXHRcdCsgalF1ZXJ5KCB3cGJjX2FqeF9ib29raW5nX2xpc3RpbmcuZ2V0X290aGVyX3BhcmFtKCAnbGlzdGluZ19jb250YWluZXInICkgKS5odG1sKClcclxuXHQpO1xyXG5cdGlmICggJ2Z1bmN0aW9uJyA9PT0gdHlwZW9mIChqUXVlcnkoICcjd3BiY19sb2FkaW5nX3NlY3Rpb24nICkud3BiY19teV9tb2RhbCkgKXtcdFx0XHQvL0ZpeEluOiA5LjAuMS41XHJcblx0XHRqUXVlcnkoICcjd3BiY19sb2FkaW5nX3NlY3Rpb24nICkud3BiY19teV9tb2RhbCggJ3Nob3cnICk7XHJcblx0fSBlbHNlIHtcclxuXHRcdGFsZXJ0KCAnV2FybmluZyEgQm9va2luZyBDYWxlbmRhci4gSXRzIHNlZW1zIHRoYXQgIHlvdSBoYXZlIGRlYWN0aXZhdGVkIGxvYWRpbmcgb2YgQm9vdHN0cmFwIEpTIGZpbGVzIGF0IEJvb2tpbmcgU2V0dGluZ3MgR2VuZXJhbCBwYWdlIGluIEFkdmFuY2VkIHNlY3Rpb24uJyApXHJcblx0fVxyXG59XHJcbmlzX3RoaXNfYWN0aW9uID0gZmFsc2U7XHJcbiovXHJcblx0Ly8gU3RhcnQgQWpheFxyXG5cdGpRdWVyeS5wb3N0KCB3cGJjX3VybF9hamF4LFxyXG5cdFx0XHRcdHtcclxuXHRcdFx0XHRcdGFjdGlvbiAgICAgICAgICA6ICdXUEJDX0FKWF9CT09LSU5HX0xJU1RJTkcnLFxyXG5cdFx0XHRcdFx0d3BiY19hanhfdXNlcl9pZDogd3BiY19hanhfYm9va2luZ19saXN0aW5nLmdldF9zZWN1cmVfcGFyYW0oICd1c2VyX2lkJyApLFxyXG5cdFx0XHRcdFx0bm9uY2UgICAgICAgICAgIDogd3BiY19hanhfYm9va2luZ19saXN0aW5nLmdldF9zZWN1cmVfcGFyYW0oICdub25jZScgKSxcclxuXHRcdFx0XHRcdHdwYmNfYWp4X2xvY2FsZSA6IHdwYmNfYWp4X2Jvb2tpbmdfbGlzdGluZy5nZXRfc2VjdXJlX3BhcmFtKCAnbG9jYWxlJyApLFxyXG5cclxuXHRcdFx0XHRcdHNlYXJjaF9wYXJhbXNcdDogd3BiY19hanhfYm9va2luZ19saXN0aW5nLnNlYXJjaF9nZXRfYWxsX3BhcmFtcygpXHJcblx0XHRcdFx0fSxcclxuXHRcdFx0XHQvKipcclxuXHRcdFx0XHQgKiBTIHUgYyBjIGUgcyBzXHJcblx0XHRcdFx0ICpcclxuXHRcdFx0XHQgKiBAcGFyYW0gcmVzcG9uc2VfZGF0YVx0XHQtXHRpdHMgb2JqZWN0IHJldHVybmVkIGZyb20gIEFqYXggLSBjbGFzcy1saXZlLXNlYXJjZy5waHBcclxuXHRcdFx0XHQgKiBAcGFyYW0gdGV4dFN0YXR1c1x0XHQtXHQnc3VjY2VzcydcclxuXHRcdFx0XHQgKiBAcGFyYW0ganFYSFJcdFx0XHRcdC1cdE9iamVjdFxyXG5cdFx0XHRcdCAqL1xyXG5cdFx0XHRcdGZ1bmN0aW9uICggcmVzcG9uc2VfZGF0YSwgdGV4dFN0YXR1cywganFYSFIgKSB7XHJcbi8vRml4SW46IGZvclZpZGVvXHJcbi8valF1ZXJ5KCAnI3dwYmNfbG9hZGluZ19zZWN0aW9uJyApLndwYmNfbXlfbW9kYWwoICdoaWRlJyApO1xyXG5cclxuY29uc29sZS5sb2coICcgPT0gUmVzcG9uc2UgV1BCQ19BSlhfQk9PS0lOR19MSVNUSU5HID09ICcsIHJlc3BvbnNlX2RhdGEgKTsgY29uc29sZS5ncm91cEVuZCgpO1xyXG5cdFx0XHRcdFx0Ly8gUHJvYmFibHkgRXJyb3JcclxuXHRcdFx0XHRcdGlmICggKHR5cGVvZiByZXNwb25zZV9kYXRhICE9PSAnb2JqZWN0JykgfHwgKHJlc3BvbnNlX2RhdGEgPT09IG51bGwpICl7XHJcblx0XHRcdFx0XHRcdGpRdWVyeSggJy53cGJjX2FqeF91bmRlcl90b29sYmFyX3JvdycgKS5oaWRlKCk7XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvL0ZpeEluOiA5LjYuMS41XHJcblx0XHRcdFx0XHRcdGpRdWVyeSggd3BiY19hanhfYm9va2luZ19saXN0aW5nLmdldF9vdGhlcl9wYXJhbSggJ2xpc3RpbmdfY29udGFpbmVyJyApICkuaHRtbChcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCc8ZGl2IGNsYXNzPVwid3BiYy1zZXR0aW5ncy1ub3RpY2Ugbm90aWNlLXdhcm5pbmdcIiBzdHlsZT1cInRleHQtYWxpZ246bGVmdFwiPicgK1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZXNwb25zZV9kYXRhICtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCc8L2Rpdj4nXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCk7XHJcblx0XHRcdFx0XHRcdHJldHVybjtcclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHQvLyBSZWxvYWQgcGFnZSwgYWZ0ZXIgZmlsdGVyIHRvb2xiYXIgd2FzIHJlc2V0ZWRcclxuXHRcdFx0XHRcdGlmICggICAgICAgKCAgICAgdW5kZWZpbmVkICE9IHJlc3BvbnNlX2RhdGFbICdhanhfY2xlYW5lZF9wYXJhbXMnIF0pXHJcblx0XHRcdFx0XHRcdFx0JiYgKCAncmVzZXRfZG9uZScgPT09IHJlc3BvbnNlX2RhdGFbICdhanhfY2xlYW5lZF9wYXJhbXMnIF1bICd1aV9yZXNldCcgXSlcclxuXHRcdFx0XHRcdCl7XHJcblx0XHRcdFx0XHRcdGxvY2F0aW9uLnJlbG9hZCgpO1xyXG5cdFx0XHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0Ly8gU2hvdyBsaXN0aW5nXHJcblx0XHRcdFx0XHRpZiAoIHJlc3BvbnNlX2RhdGFbICdhanhfY291bnQnIF0gPiAwICl7XHJcblxyXG5cdFx0XHRcdFx0XHR3cGJjX2FqeF9ib29raW5nX3Nob3dfbGlzdGluZyggcmVzcG9uc2VfZGF0YVsgJ2FqeF9pdGVtcycgXSwgcmVzcG9uc2VfZGF0YVsgJ2FqeF9zZWFyY2hfcGFyYW1zJyBdLCByZXNwb25zZV9kYXRhWyAnYWp4X2Jvb2tpbmdfcmVzb3VyY2VzJyBdICk7XHJcblxyXG5cdFx0XHRcdFx0XHR3cGJjX3BhZ2luYXRpb25fZWNobyhcclxuXHRcdFx0XHRcdFx0XHR3cGJjX2FqeF9ib29raW5nX2xpc3RpbmcuZ2V0X290aGVyX3BhcmFtKCAncGFnaW5hdGlvbl9jb250YWluZXInICksXHJcblx0XHRcdFx0XHRcdFx0e1xyXG5cdFx0XHRcdFx0XHRcdFx0J3BhZ2VfYWN0aXZlJzogcmVzcG9uc2VfZGF0YVsgJ2FqeF9zZWFyY2hfcGFyYW1zJyBdWyAncGFnZV9udW0nIF0sXHJcblx0XHRcdFx0XHRcdFx0XHQncGFnZXNfY291bnQnOiBNYXRoLmNlaWwoIHJlc3BvbnNlX2RhdGFbICdhanhfY291bnQnIF0gLyByZXNwb25zZV9kYXRhWyAnYWp4X3NlYXJjaF9wYXJhbXMnIF1bICdwYWdlX2l0ZW1zX2NvdW50JyBdICksXHJcblxyXG5cdFx0XHRcdFx0XHRcdFx0J3BhZ2VfaXRlbXNfY291bnQnOiByZXNwb25zZV9kYXRhWyAnYWp4X3NlYXJjaF9wYXJhbXMnIF1bICdwYWdlX2l0ZW1zX2NvdW50JyBdLFxyXG5cdFx0XHRcdFx0XHRcdFx0J3NvcnRfdHlwZScgICAgICAgOiByZXNwb25zZV9kYXRhWyAnYWp4X3NlYXJjaF9wYXJhbXMnIF1bICdzb3J0X3R5cGUnIF1cclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdCk7XHJcblx0XHRcdFx0XHRcdHdwYmNfYWp4X2Jvb2tpbmdfZGVmaW5lX3VpX2hvb2tzKCk7XHRcdFx0XHRcdFx0Ly8gUmVkZWZpbmUgSG9va3MsIGJlY2F1c2Ugd2Ugc2hvdyBuZXcgRE9NIGVsZW1lbnRzXHJcblxyXG5cdFx0XHRcdFx0fSBlbHNlIHtcclxuXHJcblx0XHRcdFx0XHRcdHdwYmNfYWp4X2Jvb2tpbmdfX2FjdHVhbF9saXN0aW5nX19oaWRlKCk7XHJcblx0XHRcdFx0XHRcdGpRdWVyeSggd3BiY19hanhfYm9va2luZ19saXN0aW5nLmdldF9vdGhlcl9wYXJhbSggJ2xpc3RpbmdfY29udGFpbmVyJyApICkuaHRtbChcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCc8ZGl2IGNsYXNzPVwid3BiYy1zZXR0aW5ncy1ub3RpY2UwIG5vdGljZS13YXJuaW5nMFwiIHN0eWxlPVwidGV4dC1hbGlnbjpjZW50ZXI7bWFyZ2luLWxlZnQ6LTUwcHg7XCI+JyArXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCc8c3Ryb25nPicgKyAnTm8gcmVzdWx0cyBmb3VuZCBmb3IgY3VycmVudCBmaWx0ZXIgb3B0aW9ucy4uLicgKyAnPC9zdHJvbmc+JyArXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vJzxzdHJvbmc+JyArICdObyByZXN1bHRzIGZvdW5kLi4uJyArICc8L3N0cm9uZz4nICtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCc8L2Rpdj4nXHJcblx0XHRcdFx0XHRcdFx0XHRcdCk7XHJcblx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0Ly8gVXBkYXRlIG5ldyBib29raW5nIGNvdW50XHJcblx0XHRcdFx0XHRpZiAoIHVuZGVmaW5lZCAhPT0gcmVzcG9uc2VfZGF0YVsgJ2FqeF9uZXdfYm9va2luZ3NfY291bnQnIF0gKXtcclxuXHRcdFx0XHRcdFx0dmFyIGFqeF9uZXdfYm9va2luZ3NfY291bnQgPSBwYXJzZUludCggcmVzcG9uc2VfZGF0YVsgJ2FqeF9uZXdfYm9va2luZ3NfY291bnQnIF0gKVxyXG5cdFx0XHRcdFx0XHRpZiAoYWp4X25ld19ib29raW5nc19jb3VudD4wKXtcclxuXHRcdFx0XHRcdFx0XHRqUXVlcnkoICcud3BiY19iYWRnZV9jb3VudCcgKS5zaG93KCk7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0alF1ZXJ5KCAnLmJrLXVwZGF0ZS1jb3VudCcgKS5odG1sKCBhanhfbmV3X2Jvb2tpbmdzX2NvdW50ICk7XHJcblx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0d3BiY19ib29raW5nX2xpc3RpbmdfcmVsb2FkX2J1dHRvbl9fc3Bpbl9wYXVzZSgpO1xyXG5cclxuXHRcdFx0XHRcdGpRdWVyeSggJyNhamF4X3Jlc3BvbmQnICkuaHRtbCggcmVzcG9uc2VfZGF0YSApO1x0XHQvLyBGb3IgYWJpbGl0eSB0byBzaG93IHJlc3BvbnNlLCBhZGQgc3VjaCBESVYgZWxlbWVudCB0byBwYWdlXHJcblx0XHRcdFx0fVxyXG5cdFx0XHQgICkuZmFpbCggZnVuY3Rpb24gKCBqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24gKSB7ICAgIGlmICggd2luZG93LmNvbnNvbGUgJiYgd2luZG93LmNvbnNvbGUubG9nICl7IGNvbnNvbGUubG9nKCAnQWpheF9FcnJvcicsIGpxWEhSLCB0ZXh0U3RhdHVzLCBlcnJvclRocm93biApOyB9XHJcblx0XHRcdFx0XHRqUXVlcnkoICcud3BiY19hanhfdW5kZXJfdG9vbGJhcl9yb3cnICkuaGlkZSgpO1x0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvL0ZpeEluOiA5LjYuMS41XHJcblx0XHRcdFx0XHR2YXIgZXJyb3JfbWVzc2FnZSA9ICc8c3Ryb25nPicgKyAnRXJyb3IhJyArICc8L3N0cm9uZz4gJyArIGVycm9yVGhyb3duIDtcclxuXHRcdFx0XHRcdGlmICgganFYSFIucmVzcG9uc2VUZXh0ICl7XHJcblx0XHRcdFx0XHRcdGVycm9yX21lc3NhZ2UgKz0ganFYSFIucmVzcG9uc2VUZXh0O1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0ZXJyb3JfbWVzc2FnZSA9IGVycm9yX21lc3NhZ2UucmVwbGFjZSggL1xcbi9nLCBcIjxiciAvPlwiICk7XHJcblxyXG5cdFx0XHRcdFx0d3BiY19hanhfYm9va2luZ19zaG93X21lc3NhZ2UoIGVycm9yX21lc3NhZ2UgKTtcclxuXHRcdFx0ICB9KVxyXG5cdCAgICAgICAgICAvLyAuZG9uZSggICBmdW5jdGlvbiAoIGRhdGEsIHRleHRTdGF0dXMsIGpxWEhSICkgeyAgIGlmICggd2luZG93LmNvbnNvbGUgJiYgd2luZG93LmNvbnNvbGUubG9nICl7IGNvbnNvbGUubG9nKCAnc2Vjb25kIHN1Y2Nlc3MnLCBkYXRhLCB0ZXh0U3RhdHVzLCBqcVhIUiApOyB9ICAgIH0pXHJcblx0XHRcdCAgLy8gLmFsd2F5cyggZnVuY3Rpb24gKCBkYXRhX2pxWEhSLCB0ZXh0U3RhdHVzLCBqcVhIUl9lcnJvclRocm93biApIHsgICBpZiAoIHdpbmRvdy5jb25zb2xlICYmIHdpbmRvdy5jb25zb2xlLmxvZyApeyBjb25zb2xlLmxvZyggJ2Fsd2F5cyBmaW5pc2hlZCcsIGRhdGFfanFYSFIsIHRleHRTdGF0dXMsIGpxWEhSX2Vycm9yVGhyb3duICk7IH0gICAgIH0pXHJcblx0XHRcdCAgOyAgLy8gRW5kIEFqYXhcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiAgIFZpZXdzICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xyXG5cclxuLyoqXHJcbiAqIFNob3cgTGlzdGluZyBUYWJsZSBcdFx0YW5kIGRlZmluZSBnTWFpbCBjaGVja2JveCBob29rc1xyXG4gKlxyXG4gKiBAcGFyYW0ganNvbl9pdGVtc19hcnJcdFx0LSBKU09OIG9iamVjdCB3aXRoIEl0ZW1zXHJcbiAqIEBwYXJhbSBqc29uX3NlYXJjaF9wYXJhbXNcdC0gSlNPTiBvYmplY3Qgd2l0aCBTZWFyY2hcclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYWp4X2Jvb2tpbmdfc2hvd19saXN0aW5nKCBqc29uX2l0ZW1zX2FyciwganNvbl9zZWFyY2hfcGFyYW1zLCBqc29uX2Jvb2tpbmdfcmVzb3VyY2VzICl7XHJcblxyXG5cdHdwYmNfYWp4X2RlZmluZV90ZW1wbGF0ZXNfX3Jlc291cmNlX21hbmlwdWxhdGlvbigganNvbl9pdGVtc19hcnIsIGpzb25fc2VhcmNoX3BhcmFtcywganNvbl9ib29raW5nX3Jlc291cmNlcyApO1xyXG5cclxuLy9jb25zb2xlLmxvZyggJ2pzb25faXRlbXNfYXJyJyAsIGpzb25faXRlbXNfYXJyLCBqc29uX3NlYXJjaF9wYXJhbXMgKTtcclxuXHRqUXVlcnkoICcud3BiY19hanhfdW5kZXJfdG9vbGJhcl9yb3cnICkuY3NzKCBcImRpc3BsYXlcIiwgXCJmbGV4XCIgKTtcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vRml4SW46IDkuNi4xLjVcclxuXHR2YXIgbGlzdF9oZWFkZXJfdHBsID0gd3AudGVtcGxhdGUoICd3cGJjX2FqeF9ib29raW5nX2xpc3RfaGVhZGVyJyApO1xyXG5cdHZhciBsaXN0X3Jvd190cGwgICAgPSB3cC50ZW1wbGF0ZSggJ3dwYmNfYWp4X2Jvb2tpbmdfbGlzdF9yb3cnICk7XHJcblxyXG5cclxuXHQvLyBIZWFkZXJcclxuXHRqUXVlcnkoIHdwYmNfYWp4X2Jvb2tpbmdfbGlzdGluZy5nZXRfb3RoZXJfcGFyYW0oICdsaXN0aW5nX2NvbnRhaW5lcicgKSApLmh0bWwoIGxpc3RfaGVhZGVyX3RwbCgpICk7XHJcblxyXG5cdC8vIEJvZHlcclxuXHRqUXVlcnkoIHdwYmNfYWp4X2Jvb2tpbmdfbGlzdGluZy5nZXRfb3RoZXJfcGFyYW0oICdsaXN0aW5nX2NvbnRhaW5lcicgKSApLmFwcGVuZCggJzxkaXYgY2xhc3M9XCJ3cGJjX3NlbGVjdGFibGVfYm9keVwiPjwvZGl2PicgKTtcclxuXHJcblx0Ly8gUiBvIHcgc1xyXG5jb25zb2xlLmdyb3VwQ29sbGFwc2VkKCAnTElTVElOR19ST1dTJyApO1x0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBMSVNUSU5HX1JPV1NcclxuXHRfLmVhY2goIGpzb25faXRlbXNfYXJyLCBmdW5jdGlvbiAoIHBfdmFsLCBwX2tleSwgcF9kYXRhICl7XHJcblx0XHRpZiAoICd1bmRlZmluZWQnICE9PSB0eXBlb2YganNvbl9zZWFyY2hfcGFyYW1zWyAna2V5d29yZCcgXSApe1x0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gUGFyYW1ldGVyIGZvciBtYXJraW5nIGtleXdvcmQgd2l0aCBkaWZmZXJlbnQgY29sb3IgaW4gYSBsaXN0XHJcblx0XHRcdHBfdmFsWyAnX19zZWFyY2hfcmVxdWVzdF9rZXl3b3JkX18nIF0gPSBqc29uX3NlYXJjaF9wYXJhbXNbICdrZXl3b3JkJyBdO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0cF92YWxbICdfX3NlYXJjaF9yZXF1ZXN0X2tleXdvcmRfXycgXSA9ICcnO1xyXG5cdFx0fVxyXG5cdFx0cF92YWxbICdib29raW5nX3Jlc291cmNlcycgXSA9IGpzb25fYm9va2luZ19yZXNvdXJjZXM7XHJcblx0XHRqUXVlcnkoIHdwYmNfYWp4X2Jvb2tpbmdfbGlzdGluZy5nZXRfb3RoZXJfcGFyYW0oICdsaXN0aW5nX2NvbnRhaW5lcicgKSArICcgLndwYmNfc2VsZWN0YWJsZV9ib2R5JyApLmFwcGVuZCggbGlzdF9yb3dfdHBsKCBwX3ZhbCApICk7XHJcblx0fSApO1xyXG5jb25zb2xlLmdyb3VwRW5kKCk7IFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gTElTVElOR19ST1dTXHJcblxyXG5cdHdwYmNfZGVmaW5lX2dtYWlsX2NoZWNrYm94X3NlbGVjdGlvbiggalF1ZXJ5ICk7XHRcdFx0XHRcdFx0Ly8gUmVkZWZpbmUgSG9va3MgZm9yIGNsaWNraW5nIGF0IENoZWNrYm94ZXNcclxufVxyXG5cclxuXHJcblx0LyoqXHJcblx0ICogRGVmaW5lIHRlbXBsYXRlIGZvciBjaGFuZ2luZyBib29raW5nIHJlc291cmNlcyAmICB1cGRhdGUgaXQgZWFjaCB0aW1lLCAgd2hlbiAgbGlzdGluZyB1cGRhdGluZywgdXNlZnVsICBmb3Igc2hvd2luZyBhY3R1YWwgIGJvb2tpbmcgcmVzb3VyY2VzLlxyXG5cdCAqXHJcblx0ICogQHBhcmFtIGpzb25faXRlbXNfYXJyXHRcdC0gSlNPTiBvYmplY3Qgd2l0aCBJdGVtc1xyXG5cdCAqIEBwYXJhbSBqc29uX3NlYXJjaF9wYXJhbXNcdC0gSlNPTiBvYmplY3Qgd2l0aCBTZWFyY2hcclxuXHQgKiBAcGFyYW0ganNvbl9ib29raW5nX3Jlc291cmNlc1x0LSBKU09OIG9iamVjdCB3aXRoIFJlc291cmNlc1xyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIHdwYmNfYWp4X2RlZmluZV90ZW1wbGF0ZXNfX3Jlc291cmNlX21hbmlwdWxhdGlvbigganNvbl9pdGVtc19hcnIsIGpzb25fc2VhcmNoX3BhcmFtcywganNvbl9ib29raW5nX3Jlc291cmNlcyApe1xyXG5cclxuXHRcdC8vIENoYW5nZSBib29raW5nIHJlc291cmNlXHJcblx0XHR2YXIgY2hhbmdlX2Jvb2tpbmdfcmVzb3VyY2VfdHBsID0gd3AudGVtcGxhdGUoICd3cGJjX2FqeF9jaGFuZ2VfYm9va2luZ19yZXNvdXJjZScgKTtcclxuXHJcblx0XHRqUXVlcnkoICcjd3BiY19oaWRkZW5fdGVtcGxhdGVfX2NoYW5nZV9ib29raW5nX3Jlc291cmNlJyApLmh0bWwoXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Y2hhbmdlX2Jvb2tpbmdfcmVzb3VyY2VfdHBsKCB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnYWp4X3NlYXJjaF9wYXJhbXMnICAgIDoganNvbl9zZWFyY2hfcGFyYW1zLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J2FqeF9ib29raW5nX3Jlc291cmNlcyc6IGpzb25fYm9va2luZ19yZXNvdXJjZXNcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9IClcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCk7XHJcblxyXG5cdFx0Ly8gRHVwbGljYXRlIGJvb2tpbmcgcmVzb3VyY2VcclxuXHRcdHZhciBkdXBsaWNhdGVfYm9va2luZ190b19vdGhlcl9yZXNvdXJjZV90cGwgPSB3cC50ZW1wbGF0ZSggJ3dwYmNfYWp4X2R1cGxpY2F0ZV9ib29raW5nX3RvX290aGVyX3Jlc291cmNlJyApO1xyXG5cclxuXHRcdGpRdWVyeSggJyN3cGJjX2hpZGRlbl90ZW1wbGF0ZV9fZHVwbGljYXRlX2Jvb2tpbmdfdG9fb3RoZXJfcmVzb3VyY2UnICkuaHRtbChcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRkdXBsaWNhdGVfYm9va2luZ190b19vdGhlcl9yZXNvdXJjZV90cGwoIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdhanhfc2VhcmNoX3BhcmFtcycgICAgOiBqc29uX3NlYXJjaF9wYXJhbXMsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnYWp4X2Jvb2tpbmdfcmVzb3VyY2VzJzoganNvbl9ib29raW5nX3Jlc291cmNlc1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH0gKVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0KTtcclxuXHR9XHJcblxyXG5cclxuLyoqXHJcbiAqIFNob3cganVzdCBtZXNzYWdlIGluc3RlYWQgb2YgbGlzdGluZyBhbmQgaGlkZSBwYWdpbmF0aW9uXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2FqeF9ib29raW5nX3Nob3dfbWVzc2FnZSggbWVzc2FnZSApe1xyXG5cclxuXHR3cGJjX2FqeF9ib29raW5nX19hY3R1YWxfbGlzdGluZ19faGlkZSgpO1xyXG5cclxuXHRqUXVlcnkoIHdwYmNfYWp4X2Jvb2tpbmdfbGlzdGluZy5nZXRfb3RoZXJfcGFyYW0oICdsaXN0aW5nX2NvbnRhaW5lcicgKSApLmh0bWwoXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCc8ZGl2IGNsYXNzPVwid3BiYy1zZXR0aW5ncy1ub3RpY2Ugbm90aWNlLXdhcm5pbmdcIiBzdHlsZT1cInRleHQtYWxpZ246bGVmdFwiPicgK1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdG1lc3NhZ2UgK1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnPC9kaXY+J1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCk7XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogICBIIG8gbyBrIHMgIC0gIGl0cyBBY3Rpb24vVGltZXMgd2hlbiBuZWVkIHRvIHJlLVJlbmRlciBWaWV3cyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cclxuXHJcbi8qKlxyXG4gKiBTZW5kIEFqYXggU2VhcmNoIFJlcXVlc3QgYWZ0ZXIgVXBkYXRpbmcgc2VhcmNoIHJlcXVlc3QgcGFyYW1ldGVyc1xyXG4gKlxyXG4gKiBAcGFyYW0gcGFyYW1zX2FyclxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19hanhfYm9va2luZ19zZW5kX3NlYXJjaF9yZXF1ZXN0X3dpdGhfcGFyYW1zICggcGFyYW1zX2FyciApe1xyXG5cclxuXHQvLyBEZWZpbmUgZGlmZmVyZW50IFNlYXJjaCAgcGFyYW1ldGVycyBmb3IgcmVxdWVzdFxyXG5cdF8uZWFjaCggcGFyYW1zX2FyciwgZnVuY3Rpb24gKCBwX3ZhbCwgcF9rZXksIHBfZGF0YSApIHtcclxuXHRcdC8vY29uc29sZS5sb2coICdSZXF1ZXN0IGZvcjogJywgcF9rZXksIHBfdmFsICk7XHJcblx0XHR3cGJjX2FqeF9ib29raW5nX2xpc3Rpbmcuc2VhcmNoX3NldF9wYXJhbSggcF9rZXksIHBfdmFsICk7XHJcblx0fSk7XHJcblxyXG5cdC8vIFNlbmQgQWpheCBSZXF1ZXN0XHJcblx0d3BiY19hanhfYm9va2luZ19hamF4X3NlYXJjaF9yZXF1ZXN0KCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTZWFyY2ggcmVxdWVzdCBmb3IgXCJQYWdlIE51bWJlclwiXHJcbiAqIEBwYXJhbSBwYWdlX251bWJlclx0aW50XHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2FqeF9ib29raW5nX3BhZ2luYXRpb25fY2xpY2soIHBhZ2VfbnVtYmVyICl7XHJcblxyXG5cdHdwYmNfYWp4X2Jvb2tpbmdfc2VuZF9zZWFyY2hfcmVxdWVzdF93aXRoX3BhcmFtcygge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCdwYWdlX251bSc6IHBhZ2VfbnVtYmVyXHJcblx0XHRcdFx0XHRcdFx0XHRcdH0gKTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiAgIEtleXdvcmQgU2VhcmNoaW5nICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xyXG5cclxuLyoqXHJcbiAqIFNlYXJjaCByZXF1ZXN0IGZvciBcIktleXdvcmRcIiwgYWxzbyBzZXQgY3VycmVudCBwYWdlIHRvICAxXHJcbiAqXHJcbiAqIEBwYXJhbSBlbGVtZW50X2lkXHQtXHRIVE1MIElEICBvZiBlbGVtZW50LCAgd2hlcmUgd2FzIGVudGVyZWQga2V5d29yZFxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19hanhfYm9va2luZ19zZW5kX3NlYXJjaF9yZXF1ZXN0X2Zvcl9rZXl3b3JkKCBlbGVtZW50X2lkICkge1xyXG5cclxuXHQvLyBXZSBuZWVkIHRvIFJlc2V0IHBhZ2VfbnVtIHRvIDEgd2l0aCBlYWNoIG5ldyBzZWFyY2gsIGJlY2F1c2Ugd2UgY2FuIGJlIGF0IHBhZ2UgIzQsICBidXQgYWZ0ZXIgIG5ldyBzZWFyY2ggIHdlIGNhbiAgaGF2ZSB0b3RhbGx5ICBvbmx5ICAxIHBhZ2VcclxuXHR3cGJjX2FqeF9ib29raW5nX3NlbmRfc2VhcmNoX3JlcXVlc3Rfd2l0aF9wYXJhbXMoIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdrZXl3b3JkJyAgOiBqUXVlcnkoIGVsZW1lbnRfaWQgKS52YWwoKSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdwYWdlX251bSc6IDFcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHR9ICk7XHJcbn1cclxuXHJcblx0LyoqXHJcblx0ICogU2VuZCBzZWFyY2ggcmVxdWVzdCBhZnRlciBmZXcgc2Vjb25kcyAodXN1YWxseSBhZnRlciAxLDUgc2VjKVxyXG5cdCAqIENsb3N1cmUgZnVuY3Rpb24uIEl0cyB1c2VmdWwsICBmb3IgZG8gIG5vdCBzZW5kIHRvbyBtYW55IEFqYXggcmVxdWVzdHMsIHdoZW4gc29tZW9uZSBtYWtlIGZhc3QgdHlwaW5nLlxyXG5cdCAqL1xyXG5cdHZhciB3cGJjX2FqeF9ib29raW5nX3NlYXJjaGluZ19hZnRlcl9mZXdfc2Vjb25kcyA9IGZ1bmN0aW9uICgpe1xyXG5cclxuXHRcdHZhciBjbG9zZWRfdGltZXIgPSAwO1xyXG5cclxuXHRcdHJldHVybiBmdW5jdGlvbiAoIGVsZW1lbnRfaWQsIHRpbWVyX2RlbGF5ICl7XHJcblxyXG5cdFx0XHQvLyBHZXQgZGVmYXVsdCB2YWx1ZSBvZiBcInRpbWVyX2RlbGF5XCIsICBpZiBwYXJhbWV0ZXIgd2FzIG5vdCBwYXNzZWQgaW50byB0aGUgZnVuY3Rpb24uXHJcblx0XHRcdHRpbWVyX2RlbGF5ID0gdHlwZW9mIHRpbWVyX2RlbGF5ICE9PSAndW5kZWZpbmVkJyA/IHRpbWVyX2RlbGF5IDogMTUwMDtcclxuXHJcblx0XHRcdGNsZWFyVGltZW91dCggY2xvc2VkX3RpbWVyICk7XHRcdC8vIENsZWFyIHByZXZpb3VzIHRpbWVyXHJcblxyXG5cdFx0XHQvLyBTdGFydCBuZXcgVGltZXJcclxuXHRcdFx0Y2xvc2VkX3RpbWVyID0gc2V0VGltZW91dCggd3BiY19hanhfYm9va2luZ19zZW5kX3NlYXJjaF9yZXF1ZXN0X2Zvcl9rZXl3b3JkLmJpbmQoICBudWxsLCBlbGVtZW50X2lkICksIHRpbWVyX2RlbGF5ICk7XHJcblx0XHR9XHJcblx0fSgpO1xyXG5cclxuXHJcbi8qKlxyXG4gKiAgIERlZmluZSBEeW5hbWljIEhvb2tzICAobGlrZSBwYWdpbmF0aW9uIGNsaWNrLCB3aGljaCByZW5ldyBlYWNoIHRpbWUgd2l0aCBuZXcgbGlzdGluZyBzaG93aW5nKSAgLS0tLS0tLS0tLS0tLSAqL1xyXG5cclxuLyoqXHJcbiAqIERlZmluZSBIVE1MIHVpIEhvb2tzOiBvbiBLZXlVcCB8IENoYW5nZSB8IC0+IFNvcnQgT3JkZXIgJiBOdW1iZXIgSXRlbXMgLyBQYWdlXHJcbiAqIFdlIGFyZSBoY25hZ2VkIGl0IGVhY2ggIHRpbWUsIHdoZW4gc2hvd2luZyBuZXcgbGlzdGluZywgYmVjYXVzZSBET00gZWxlbWVudHMgY2huYWdlZFxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19hanhfYm9va2luZ19kZWZpbmVfdWlfaG9va3MoKXtcclxuXHJcblx0aWYgKCAnZnVuY3Rpb24nID09PSB0eXBlb2YoIHdwYmNfZGVmaW5lX3RpcHB5X3Rvb2x0aXBzICkgKSB7XHJcblx0XHR3cGJjX2RlZmluZV90aXBweV90b29sdGlwcyggJy53cGJjX2xpc3RpbmdfY29udGFpbmVyICcgKTtcclxuXHR9XHJcblxyXG5cdHdwYmNfYWp4X2Jvb2tpbmdfX3VpX2RlZmluZV9fbG9jYWxlKCk7XHJcblx0d3BiY19hanhfYm9va2luZ19fdWlfZGVmaW5lX19yZW1hcmsoKTtcclxuXHJcblx0Ly8gSXRlbXMgUGVyIFBhZ2VcclxuXHRqUXVlcnkoICcud3BiY19pdGVtc19wZXJfcGFnZScgKS5vbiggJ2NoYW5nZScsIGZ1bmN0aW9uKCBldmVudCApe1xyXG5cclxuXHRcdHdwYmNfYWp4X2Jvb2tpbmdfc2VuZF9zZWFyY2hfcmVxdWVzdF93aXRoX3BhcmFtcygge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3BhZ2VfaXRlbXNfY291bnQnICA6IGpRdWVyeSggdGhpcyApLnZhbCgpLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3BhZ2VfbnVtJzogMVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdH0gKTtcclxuXHR9ICk7XHJcblxyXG5cdC8vIFNvcnRpbmdcclxuXHRqUXVlcnkoICcud3BiY19pdGVtc19zb3J0X3R5cGUnICkub24oICdjaGFuZ2UnLCBmdW5jdGlvbiggZXZlbnQgKXtcclxuXHJcblx0XHR3cGJjX2FqeF9ib29raW5nX3NlbmRfc2VhcmNoX3JlcXVlc3Rfd2l0aF9wYXJhbXMoIHsnc29ydF90eXBlJzogalF1ZXJ5KCB0aGlzICkudmFsKCl9ICk7XHJcblx0fSApO1xyXG59XHJcblxyXG5cclxuLyoqXHJcbiAqICAgU2hvdyAvIEhpZGUgTGlzdGluZyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXHJcblxyXG4vKipcclxuICogIFNob3cgTGlzdGluZyBUYWJsZSBcdC0gXHRTZW5kaW5nIEFqYXggUmVxdWVzdFx0LVx0d2l0aCBwYXJhbWV0ZXJzIHRoYXQgIHdlIGVhcmx5ICBkZWZpbmVkIGluIFwid3BiY19hanhfYm9va2luZ19saXN0aW5nXCIgT2JqLlxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19hanhfYm9va2luZ19fYWN0dWFsX2xpc3RpbmdfX3Nob3coKXtcclxuXHJcblx0d3BiY19hanhfYm9va2luZ19hamF4X3NlYXJjaF9yZXF1ZXN0KCk7XHRcdFx0Ly8gU2VuZCBBamF4IFJlcXVlc3RcdC1cdHdpdGggcGFyYW1ldGVycyB0aGF0ICB3ZSBlYXJseSAgZGVmaW5lZCBpbiBcIndwYmNfYWp4X2Jvb2tpbmdfbGlzdGluZ1wiIE9iai5cclxufVxyXG5cclxuLyoqXHJcbiAqIEhpZGUgTGlzdGluZyBUYWJsZSAoIGFuZCBQYWdpbmF0aW9uIClcclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYWp4X2Jvb2tpbmdfX2FjdHVhbF9saXN0aW5nX19oaWRlKCl7XHJcblx0alF1ZXJ5KCAnLndwYmNfYWp4X3VuZGVyX3Rvb2xiYXJfcm93JyApLmhpZGUoKTtcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvL0ZpeEluOiA5LjYuMS41XHJcblx0alF1ZXJ5KCB3cGJjX2FqeF9ib29raW5nX2xpc3RpbmcuZ2V0X290aGVyX3BhcmFtKCAnbGlzdGluZ19jb250YWluZXInICkgICAgKS5odG1sKCAnJyApO1xyXG5cdGpRdWVyeSggd3BiY19hanhfYm9va2luZ19saXN0aW5nLmdldF9vdGhlcl9wYXJhbSggJ3BhZ2luYXRpb25fY29udGFpbmVyJyApICkuaHRtbCggJycgKTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiAgIFN1cHBvcnQgZnVuY3Rpb25zIGZvciBDb250ZW50IFRlbXBsYXRlIGRhdGEgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xyXG5cclxuLyoqXHJcbiAqIEhpZ2hsaWdodCBzdHJpbmdzLFxyXG4gKiBieSBpbnNlcnRpbmcgPHNwYW4gY2xhc3M9XCJmaWVsZHZhbHVlIG5hbWUgZmllbGRzZWFyY2h2YWx1ZVwiPi4uLjwvc3Bhbj4gaHRtbCAgZWxlbWVudHMgaW50byB0aGUgc3RyaW5nLlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gYm9va2luZ19kZXRhaWxzIFx0LSBTb3VyY2Ugc3RyaW5nXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBib29raW5nX2tleXdvcmRcdC0gS2V5d29yZCB0byBoaWdobGlnaHRcclxuICogQHJldHVybnMge3N0cmluZ31cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfZ2V0X2hpZ2hsaWdodGVkX3NlYXJjaF9rZXl3b3JkKCBib29raW5nX2RldGFpbHMsIGJvb2tpbmdfa2V5d29yZCApe1xyXG5cclxuXHRib29raW5nX2tleXdvcmQgPSBib29raW5nX2tleXdvcmQudHJpbSgpLnRvTG93ZXJDYXNlKCk7XHJcblx0aWYgKCAwID09IGJvb2tpbmdfa2V5d29yZC5sZW5ndGggKXtcclxuXHRcdHJldHVybiBib29raW5nX2RldGFpbHM7XHJcblx0fVxyXG5cclxuXHQvLyBIaWdobGlnaHQgc3Vic3RyaW5nIHdpdGhpbmcgSFRNTCB0YWdzIGluIFwiQ29udGVudCBvZiBib29raW5nIGZpZWxkcyBkYXRhXCIgLS0gZS5nLiBzdGFydGluZyBmcm9tICA+ICBhbmQgZW5kaW5nIHdpdGggPFxyXG5cdGxldCBrZXl3b3JkUmVnZXggPSBuZXcgUmVnRXhwKCBgZmllbGR2YWx1ZVtePD5dKj4oW148XSoke2Jvb2tpbmdfa2V5d29yZH1bXjxdKilgLCAnZ2ltJyApO1xyXG5cclxuXHQvL2xldCBtYXRjaGVzID0gWy4uLmJvb2tpbmdfZGV0YWlscy50b0xvd2VyQ2FzZSgpLm1hdGNoQWxsKCBrZXl3b3JkUmVnZXggKV07XHJcblx0bGV0IG1hdGNoZXMgPSBib29raW5nX2RldGFpbHMudG9Mb3dlckNhc2UoKS5tYXRjaEFsbCgga2V5d29yZFJlZ2V4ICk7XHJcblx0XHRtYXRjaGVzID0gQXJyYXkuZnJvbSggbWF0Y2hlcyApO1xyXG5cclxuXHRsZXQgc3RyaW5nc19hcnIgPSBbXTtcclxuXHRsZXQgcG9zX3ByZXZpb3VzID0gMDtcclxuXHRsZXQgc2VhcmNoX3Bvc19zdGFydDtcclxuXHRsZXQgc2VhcmNoX3Bvc19lbmQ7XHJcblxyXG5cdGZvciAoIGNvbnN0IG1hdGNoIG9mIG1hdGNoZXMgKXtcclxuXHJcblx0XHRzZWFyY2hfcG9zX3N0YXJ0ID0gbWF0Y2guaW5kZXggKyBtYXRjaFsgMCBdLnRvTG93ZXJDYXNlKCkuaW5kZXhPZiggJz4nLCAwICkgKyAxIDtcclxuXHJcblx0XHRzdHJpbmdzX2Fyci5wdXNoKCBib29raW5nX2RldGFpbHMuc3Vic3RyKCBwb3NfcHJldmlvdXMsIChzZWFyY2hfcG9zX3N0YXJ0IC0gcG9zX3ByZXZpb3VzKSApICk7XHJcblxyXG5cdFx0c2VhcmNoX3Bvc19lbmQgPSBib29raW5nX2RldGFpbHMudG9Mb3dlckNhc2UoKS5pbmRleE9mKCAnPCcsIHNlYXJjaF9wb3Nfc3RhcnQgKTtcclxuXHJcblx0XHRzdHJpbmdzX2Fyci5wdXNoKCAnPHNwYW4gY2xhc3M9XCJmaWVsZHZhbHVlIG5hbWUgZmllbGRzZWFyY2h2YWx1ZVwiPicgKyBib29raW5nX2RldGFpbHMuc3Vic3RyKCBzZWFyY2hfcG9zX3N0YXJ0LCAoc2VhcmNoX3Bvc19lbmQgLSBzZWFyY2hfcG9zX3N0YXJ0KSApICsgJzwvc3Bhbj4nICk7XHJcblxyXG5cdFx0cG9zX3ByZXZpb3VzID0gc2VhcmNoX3Bvc19lbmQ7XHJcblx0fVxyXG5cclxuXHRzdHJpbmdzX2Fyci5wdXNoKCBib29raW5nX2RldGFpbHMuc3Vic3RyKCBwb3NfcHJldmlvdXMsIChib29raW5nX2RldGFpbHMubGVuZ3RoIC0gcG9zX3ByZXZpb3VzKSApICk7XHJcblxyXG5cdHJldHVybiBzdHJpbmdzX2Fyci5qb2luKCAnJyApO1xyXG59XHJcblxyXG4vKipcclxuICogQ29udmVydCBzcGVjaWFsIEhUTUwgY2hhcmFjdGVycyAgIGZyb206XHQgJmFtcDsgXHQtPiBcdCZcclxuICpcclxuICogQHBhcmFtIHRleHRcclxuICogQHJldHVybnMgeyp9XHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2RlY29kZV9IVE1MX2VudGl0aWVzKCB0ZXh0ICl7XHJcblx0dmFyIHRleHRBcmVhID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggJ3RleHRhcmVhJyApO1xyXG5cdHRleHRBcmVhLmlubmVySFRNTCA9IHRleHQ7XHJcblx0cmV0dXJuIHRleHRBcmVhLnZhbHVlO1xyXG59XHJcblxyXG4vKipcclxuICogQ29udmVydCBUTyBzcGVjaWFsIEhUTUwgY2hhcmFjdGVycyAgIGZyb206XHQgJiBcdC0+IFx0JmFtcDtcclxuICpcclxuICogQHBhcmFtIHRleHRcclxuICogQHJldHVybnMgeyp9XHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2VuY29kZV9IVE1MX2VudGl0aWVzKHRleHQpIHtcclxuICB2YXIgdGV4dEFyZWEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0ZXh0YXJlYScpO1xyXG4gIHRleHRBcmVhLmlubmVyVGV4dCA9IHRleHQ7XHJcbiAgcmV0dXJuIHRleHRBcmVhLmlubmVySFRNTDtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiAgIFN1cHBvcnQgRnVuY3Rpb25zIC0gU3BpbiBJY29uIGluIEJ1dHRvbnMgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xyXG5cclxuLyoqXHJcbiAqIFNwaW4gYnV0dG9uIGluIEZpbHRlciB0b29sYmFyICAtICBTdGFydFxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19ib29raW5nX2xpc3RpbmdfcmVsb2FkX2J1dHRvbl9fc3Bpbl9zdGFydCgpe1xyXG5cdGpRdWVyeSggJyN3cGJjX2Jvb2tpbmdfbGlzdGluZ19yZWxvYWRfYnV0dG9uIC5tZW51X2ljb24ud3BiY19zcGluJykucmVtb3ZlQ2xhc3MoICd3cGJjX2FuaW1hdGlvbl9wYXVzZScgKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNwaW4gYnV0dG9uIGluIEZpbHRlciB0b29sYmFyICAtICBQYXVzZVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19ib29raW5nX2xpc3RpbmdfcmVsb2FkX2J1dHRvbl9fc3Bpbl9wYXVzZSgpe1xyXG5cdGpRdWVyeSggJyN3cGJjX2Jvb2tpbmdfbGlzdGluZ19yZWxvYWRfYnV0dG9uIC5tZW51X2ljb24ud3BiY19zcGluJyApLmFkZENsYXNzKCAnd3BiY19hbmltYXRpb25fcGF1c2UnICk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTcGluIGJ1dHRvbiBpbiBGaWx0ZXIgdG9vbGJhciAgLSAgaXMgU3Bpbm5pbmcgP1xyXG4gKlxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYm9va2luZ19saXN0aW5nX3JlbG9hZF9idXR0b25fX2lzX3NwaW4oKXtcclxuICAgIGlmICggalF1ZXJ5KCAnI3dwYmNfYm9va2luZ19saXN0aW5nX3JlbG9hZF9idXR0b24gLm1lbnVfaWNvbi53cGJjX3NwaW4nICkuaGFzQ2xhc3MoICd3cGJjX2FuaW1hdGlvbl9wYXVzZScgKSApe1xyXG5cdFx0cmV0dXJuIHRydWU7XHJcblx0fSBlbHNlIHtcclxuXHRcdHJldHVybiBmYWxzZTtcclxuXHR9XHJcbn0iXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7O0FBQUMsU0FBQUEsMkJBQUFDLENBQUEsRUFBQUMsY0FBQSxRQUFBQyxFQUFBLFVBQUFDLE1BQUEsb0JBQUFILENBQUEsQ0FBQUcsTUFBQSxDQUFBQyxRQUFBLEtBQUFKLENBQUEscUJBQUFFLEVBQUEsUUFBQUcsS0FBQSxDQUFBQyxPQUFBLENBQUFOLENBQUEsTUFBQUUsRUFBQSxHQUFBSywyQkFBQSxDQUFBUCxDQUFBLE1BQUFDLGNBQUEsSUFBQUQsQ0FBQSxXQUFBQSxDQUFBLENBQUFRLE1BQUEscUJBQUFOLEVBQUEsRUFBQUYsQ0FBQSxHQUFBRSxFQUFBLE1BQUFPLENBQUEsVUFBQUMsQ0FBQSxZQUFBQSxFQUFBLGVBQUFDLENBQUEsRUFBQUQsQ0FBQSxFQUFBRSxDQUFBLFdBQUFBLEVBQUEsUUFBQUgsQ0FBQSxJQUFBVCxDQUFBLENBQUFRLE1B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 _out/bookings__hooks.js 0000666 00000062536 15166373417 0011262 0 ustar 00 "use strict"; /** * Define HTML ui Hooks: on KeyUp | Change | -> Sort Order & Number Items / Page * * We are chnaged it once, because such elements always the same */ function wpbc_ajx_booking_define_ui_hooks_once() { //------------------------------------------------------------------------------------------------------------------ // Booked dates //------------------------------------------------------------------------------------------------------------------ jQuery('#wh_booking_date').on('change', function (event) { var changed_value = JSON.parse(jQuery('#wh_booking_date').val()); wpbc_ajx_booking_send_search_request_with_params({ 'wh_booking_date': changed_value, 'page_num': 1, // Frontend selected elements (saving for future use, after F5) 'ui_wh_booking_date_radio': jQuery('input[name="ui_wh_booking_date_radio"]:checked').val(), 'ui_wh_booking_date_next': jQuery('#ui_wh_booking_date_next').val(), 'ui_wh_booking_date_prior': jQuery('#ui_wh_booking_date_prior').val(), 'ui_wh_booking_date_checkin': jQuery('#ui_wh_booking_date_checkin').val(), 'ui_wh_booking_date_checkout': jQuery('#ui_wh_booking_date_checkout').val() }); }); //------------------------------------------------------------------------------------------------------------------ // Approved | Pending | All //------------------------------------------------------------------------------------------------------------------ jQuery('#wh_approved').on('change', function (event) { var changed_value = jQuery('#wh_approved').val(); changed_value = JSON.parse(changed_value); wpbc_ajx_booking_send_search_request_with_params({ 'wh_approved': changed_value[0], 'page_num': 1 }); }); //------------------------------------------------------------------------------------------------------------------ // Keywords //------------------------------------------------------------------------------------------------------------------ jQuery('#wpbc_search_field').on("keyup", function (event) { if (13 !== event.which) { wpbc_ajx_booking_searching_after_few_seconds('#wpbc_search_field'); // Searching after 1.5 seconds after Key Up } else { wpbc_ajx_booking_searching_after_few_seconds('#wpbc_search_field', 0); // Immediate search } }); //------------------------------------------------------------------------------------------------------------------ // Existing | Trash | Any //------------------------------------------------------------------------------------------------------------------ jQuery('#wh_trash').on('change', function (event) { var changed_value = JSON.parse(jQuery('#wh_trash').val()); wpbc_ajx_booking_send_search_request_with_params({ 'wh_trash': changed_value[0], 'page_num': 1 }); }); //------------------------------------------------------------------------------------------------------------------ // All bookings | New bookings //------------------------------------------------------------------------------------------------------------------ jQuery('#wh_what_bookings').on('change', function (event) { var changed_value = JSON.parse(jQuery('#wh_what_bookings').val()); wpbc_ajx_booking_send_search_request_with_params({ 'wh_what_bookings': changed_value[0], 'page_num': 1 }); }); //------------------------------------------------------------------------------------------------------------------ // "Creation Date" of bookings //------------------------------------------------------------------------------------------------------------------ jQuery('#wh_modification_date').on('change', function (event) { var changed_value = JSON.parse(jQuery('#wh_modification_date').val()); wpbc_ajx_booking_send_search_request_with_params({ 'wh_modification_date': changed_value, 'page_num': 1, // Frontend selected elements (saving for future use, after F5) 'ui_wh_modification_date_radio': jQuery('input[name="ui_wh_modification_date_radio"]:checked').val(), 'ui_wh_modification_date_prior': jQuery('#ui_wh_modification_date_prior').val(), 'ui_wh_modification_date_checkin': jQuery('#ui_wh_modification_date_checkin').val(), 'ui_wh_modification_date_checkout': jQuery('#ui_wh_modification_date_checkout').val() }); }); //------------------------------------------------------------------------------------------------------------------ // Payment Status //------------------------------------------------------------------------------------------------------------------ jQuery('#wh_pay_status').on('change', function (event) { var changed_value = JSON.parse(jQuery('#wh_pay_status').val()); wpbc_ajx_booking_send_search_request_with_params({ 'wh_pay_status': changed_value, 'page_num': 1, // Frontend selected elements (saving for future use, after F5) 'ui_wh_pay_status_radio': undefined === jQuery('input[name="ui_wh_pay_status_radio"]:checked').val() ? '' : jQuery('input[name="ui_wh_pay_status_radio"]:checked').val(), 'ui_wh_pay_status_custom': jQuery('#ui_wh_pay_status_custom').val() }); }); //------------------------------------------------------------------------------------------------------------------ // Min Cost //------------------------------------------------------------------------------------------------------------------ jQuery('#wh_cost').on('change', function (event) { var changed_value = jQuery('#wh_cost').val(); wpbc_ajx_booking_send_search_request_with_params({ 'wh_cost': changed_value, 'page_num': 1 }); }); //------------------------------------------------------------------------------------------------------------------ // Max Cost //------------------------------------------------------------------------------------------------------------------ jQuery('#wh_cost2').on('change', function (event) { var changed_value = jQuery('#wh_cost2').val(); wpbc_ajx_booking_send_search_request_with_params({ 'wh_cost2': changed_value, 'page_num': 1 }); }); //------------------------------------------------------------------------------------------------------------------ // Booking resources //------------------------------------------------------------------------------------------------------------------ jQuery('#wh_booking_type').on('change', function (event) { var changed_value = jQuery('#wh_booking_type').val(); // it's get as array if (Array.isArray(changed_value) && 0 === changed_value.length) { changed_value = ['-1']; } wpbc_ajx_booking_send_search_request_with_params({ 'wh_booking_type': changed_value, 'page_num': 1 }); }); //------------------------------------------------------------------------------------------------------------------ // Sorting //------------------------------------------------------------------------------------------------------------------ jQuery('#wh_sort').on('change', function (event) { var changed_value = jQuery('#wh_sort').val(); changed_value = JSON.parse(changed_value); wpbc_ajx_booking_send_search_request_with_params({ 'wh_sort': changed_value[0] }); }); } jQuery(document).ready(function () { wpbc_ajx_booking_define_ui_hooks_once(); }); //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5jbHVkZXMvcGFnZS1ib29raW5ncy9fb3V0L2Jvb2tpbmdzX19ob29rcy5qcyIsIm5hbWVzIjpbIndwYmNfYWp4X2Jvb2tpbmdfZGVmaW5lX3VpX2hvb2tzX29uY2UiLCJqUXVlcnkiLCJvbiIsImV2ZW50IiwiY2hhbmdlZF92YWx1ZSIsIkpTT04iLCJwYXJzZSIsInZhbCIsIndwYmNfYWp4X2Jvb2tpbmdfc2VuZF9zZWFyY2hfcmVxdWVzdF93aXRoX3BhcmFtcyIsIndoaWNoIiwid3BiY19hanhfYm9va2luZ19zZWFyY2hpbmdfYWZ0ZXJfZmV3X3NlY29uZHMiLCJ1bmRlZmluZWQiLCJBcnJheSIsImlzQXJyYXkiLCJsZW5ndGgiLCJkb2N1bWVudCIsInJlYWR5Il0sInNvdXJjZXMiOlsiaW5jbHVkZXMvcGFnZS1ib29raW5ncy9fc3JjL2Jvb2tpbmdzX19ob29rcy5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJcInVzZSBzdHJpY3RcIjtcclxuXHJcbi8qKlxyXG4gKiBEZWZpbmUgSFRNTCB1aSBIb29rczogb24gS2V5VXAgfCBDaGFuZ2UgfCAtPiBTb3J0IE9yZGVyICYgTnVtYmVyIEl0ZW1zIC8gUGFnZVxyXG4gKiAqIFdlIGFyZSBjaG5hZ2VkIGl0IG9uY2UsIGJlY2F1c2Ugc3VjaCAgZWxlbWVudHMgYWx3YXlzIHRoZSBzYW1lXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2FqeF9ib29raW5nX2RlZmluZV91aV9ob29rc19vbmNlKCl7XHJcblxyXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0Ly8gQm9va2VkIGRhdGVzXHJcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRqUXVlcnkoICcjd2hfYm9va2luZ19kYXRlJyApLm9uKCAnY2hhbmdlJywgZnVuY3Rpb24oIGV2ZW50ICl7XHJcblxyXG5cdFx0dmFyIGNoYW5nZWRfdmFsdWUgPSBKU09OLnBhcnNlKCBqUXVlcnkoICcjd2hfYm9va2luZ19kYXRlJyApLnZhbCgpICk7XHJcblxyXG5cdFx0d3BiY19hanhfYm9va2luZ19zZW5kX3NlYXJjaF9yZXF1ZXN0X3dpdGhfcGFyYW1zKCB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd3aF9ib29raW5nX2RhdGUnOiBjaGFuZ2VkX3ZhbHVlLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQncGFnZV9udW0nICAgICAgIDogMSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gRnJvbnRlbmQgc2VsZWN0ZWQgZWxlbWVudHMgKHNhdmluZyBmb3IgZnV0dXJlIHVzZSwgYWZ0ZXIgRjUpXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd1aV93aF9ib29raW5nX2RhdGVfcmFkaW8nICAgOiBqUXVlcnkoICdpbnB1dFtuYW1lPVwidWlfd2hfYm9va2luZ19kYXRlX3JhZGlvXCJdOmNoZWNrZWQnICkudmFsKCksXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd1aV93aF9ib29raW5nX2RhdGVfbmV4dCcgICAgOiBqUXVlcnkoICcjdWlfd2hfYm9va2luZ19kYXRlX25leHQnICkudmFsKCksXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd1aV93aF9ib29raW5nX2RhdGVfcHJpb3InICAgOiBqUXVlcnkoICcjdWlfd2hfYm9va2luZ19kYXRlX3ByaW9yJyApLnZhbCgpLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQndWlfd2hfYm9va2luZ19kYXRlX2NoZWNraW4nIDogalF1ZXJ5KCAnI3VpX3doX2Jvb2tpbmdfZGF0ZV9jaGVja2luJyApLnZhbCgpLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQndWlfd2hfYm9va2luZ19kYXRlX2NoZWNrb3V0JzogalF1ZXJ5KCAnI3VpX3doX2Jvb2tpbmdfZGF0ZV9jaGVja291dCcgKS52YWwoKVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fSApO1xyXG5cdH0gKTtcclxuXHJcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHQvLyBBcHByb3ZlZCB8IFBlbmRpbmcgfCBBbGxcclxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdGpRdWVyeSggJyN3aF9hcHByb3ZlZCcgKS5vbiggJ2NoYW5nZScsIGZ1bmN0aW9uKCBldmVudCApe1xyXG5cclxuXHRcdHZhciBjaGFuZ2VkX3ZhbHVlID0galF1ZXJ5KCAnI3doX2FwcHJvdmVkJyApLnZhbCgpO1xyXG5cclxuXHRcdGNoYW5nZWRfdmFsdWUgPSBKU09OLnBhcnNlKCBjaGFuZ2VkX3ZhbHVlICk7XHJcblxyXG5cdFx0d3BiY19hanhfYm9va2luZ19zZW5kX3NlYXJjaF9yZXF1ZXN0X3dpdGhfcGFyYW1zKCB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd3aF9hcHByb3ZlZCc6IGNoYW5nZWRfdmFsdWVbIDAgXSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3BhZ2VfbnVtJyAgIDogMVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fSApO1xyXG5cdH0gKTtcclxuXHJcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHQvLyBLZXl3b3Jkc1xyXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0alF1ZXJ5KCAnI3dwYmNfc2VhcmNoX2ZpZWxkJyApLm9uKCBcImtleXVwXCIsIGZ1bmN0aW9uICggZXZlbnQgKXtcclxuXHRcdGlmICggMTMgIT09IGV2ZW50LndoaWNoICl7XHJcblx0XHRcdHdwYmNfYWp4X2Jvb2tpbmdfc2VhcmNoaW5nX2FmdGVyX2Zld19zZWNvbmRzKCAnI3dwYmNfc2VhcmNoX2ZpZWxkJyApO1x0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gU2VhcmNoaW5nIGFmdGVyIDEuNSBzZWNvbmRzIGFmdGVyIEtleSBVcFxyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0d3BiY19hanhfYm9va2luZ19zZWFyY2hpbmdfYWZ0ZXJfZmV3X3NlY29uZHMoICcjd3BiY19zZWFyY2hfZmllbGQnLCAwICk7XHRcdFx0XHRcdFx0XHRcdFx0Ly8gSW1tZWRpYXRlIHNlYXJjaFxyXG5cdFx0fVxyXG5cdH0gKTtcclxuXHJcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHQvLyBFeGlzdGluZyB8IFRyYXNoIHwgQW55XHJcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRqUXVlcnkoICcjd2hfdHJhc2gnICkub24oICdjaGFuZ2UnLCBmdW5jdGlvbiggZXZlbnQgKXtcclxuXHJcblx0XHR2YXIgY2hhbmdlZF92YWx1ZSA9IEpTT04ucGFyc2UoIGpRdWVyeSggJyN3aF90cmFzaCcgKS52YWwoKSApO1xyXG5cclxuXHRcdHdwYmNfYWp4X2Jvb2tpbmdfc2VuZF9zZWFyY2hfcmVxdWVzdF93aXRoX3BhcmFtcygge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnd2hfdHJhc2gnOiBjaGFuZ2VkX3ZhbHVlWyAwIF0sXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdwYWdlX251bSc6IDFcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH0gKTtcclxuXHR9ICk7XHJcblxyXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0Ly8gQWxsIGJvb2tpbmdzIHwgTmV3IGJvb2tpbmdzXHJcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRqUXVlcnkoICcjd2hfd2hhdF9ib29raW5ncycgKS5vbiggJ2NoYW5nZScsIGZ1bmN0aW9uKCBldmVudCApe1xyXG5cclxuXHRcdHZhciBjaGFuZ2VkX3ZhbHVlID0gSlNPTi5wYXJzZSggalF1ZXJ5KCAnI3doX3doYXRfYm9va2luZ3MnICkudmFsKCkgKTtcclxuXHJcblx0XHR3cGJjX2FqeF9ib29raW5nX3NlbmRfc2VhcmNoX3JlcXVlc3Rfd2l0aF9wYXJhbXMoIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3doX3doYXRfYm9va2luZ3MnOiBjaGFuZ2VkX3ZhbHVlWyAwIF0sXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdwYWdlX251bSc6IDFcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH0gKTtcclxuXHR9ICk7XHJcblxyXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0Ly8gXCJDcmVhdGlvbiBEYXRlXCIgICBvZiBib29raW5nc1xyXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0alF1ZXJ5KCAnI3doX21vZGlmaWNhdGlvbl9kYXRlJyApLm9uKCAnY2hhbmdlJywgZnVuY3Rpb24oIGV2ZW50ICl7XHJcblxyXG5cdFx0dmFyIGNoYW5nZWRfdmFsdWUgPSBKU09OLnBhcnNlKCBqUXVlcnkoICcjd2hfbW9kaWZpY2F0aW9uX2RhdGUnICkudmFsKCkgKTtcclxuXHJcblx0XHR3cGJjX2FqeF9ib29raW5nX3NlbmRfc2VhcmNoX3JlcXVlc3Rfd2l0aF9wYXJhbXMoIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3doX21vZGlmaWNhdGlvbl9kYXRlJzogY2hhbmdlZF92YWx1ZSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3BhZ2VfbnVtJyAgICAgICA6IDEsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIEZyb250ZW5kIHNlbGVjdGVkIGVsZW1lbnRzIChzYXZpbmcgZm9yIGZ1dHVyZSB1c2UsIGFmdGVyIEY1KVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQndWlfd2hfbW9kaWZpY2F0aW9uX2RhdGVfcmFkaW8nICAgOiBqUXVlcnkoICdpbnB1dFtuYW1lPVwidWlfd2hfbW9kaWZpY2F0aW9uX2RhdGVfcmFkaW9cIl06Y2hlY2tlZCcgKS52YWwoKSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3VpX3doX21vZGlmaWNhdGlvbl9kYXRlX3ByaW9yJyAgIDogalF1ZXJ5KCAnI3VpX3doX21vZGlmaWNhdGlvbl9kYXRlX3ByaW9yJyApLnZhbCgpLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQndWlfd2hfbW9kaWZpY2F0aW9uX2RhdGVfY2hlY2tpbicgOiBqUXVlcnkoICcjdWlfd2hfbW9kaWZpY2F0aW9uX2RhdGVfY2hlY2tpbicgKS52YWwoKSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3VpX3doX21vZGlmaWNhdGlvbl9kYXRlX2NoZWNrb3V0JzogalF1ZXJ5KCAnI3VpX3doX21vZGlmaWNhdGlvbl9kYXRlX2NoZWNrb3V0JyApLnZhbCgpXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9ICk7XHJcblx0fSApO1xyXG5cclxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdC8vIFBheW1lbnQgU3RhdHVzXHJcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRqUXVlcnkoICcjd2hfcGF5X3N0YXR1cycgKS5vbiggJ2NoYW5nZScsIGZ1bmN0aW9uKCBldmVudCApe1xyXG5cclxuXHRcdHZhciBjaGFuZ2VkX3ZhbHVlID0gSlNPTi5wYXJzZSggalF1ZXJ5KCAnI3doX3BheV9zdGF0dXMnICkudmFsKCkgKTtcclxuXHJcblx0XHR3cGJjX2FqeF9ib29raW5nX3NlbmRfc2VhcmNoX3JlcXVlc3Rfd2l0aF9wYXJhbXMoIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3doX3BheV9zdGF0dXMnOiBjaGFuZ2VkX3ZhbHVlLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQncGFnZV9udW0nICAgICAgIDogMSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gRnJvbnRlbmQgc2VsZWN0ZWQgZWxlbWVudHMgKHNhdmluZyBmb3IgZnV0dXJlIHVzZSwgYWZ0ZXIgRjUpXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd1aV93aF9wYXlfc3RhdHVzX3JhZGlvJyA6ICggKCB1bmRlZmluZWQgPT09IGpRdWVyeSggJ2lucHV0W25hbWU9XCJ1aV93aF9wYXlfc3RhdHVzX3JhZGlvXCJdOmNoZWNrZWQnICkudmFsKCkgKVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0PyAnJ1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0OiBqUXVlcnkoICdpbnB1dFtuYW1lPVwidWlfd2hfcGF5X3N0YXR1c19yYWRpb1wiXTpjaGVja2VkJyApLnZhbCgpXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCAgICksXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd1aV93aF9wYXlfc3RhdHVzX2N1c3RvbSc6IGpRdWVyeSggJyN1aV93aF9wYXlfc3RhdHVzX2N1c3RvbScgKS52YWwoKVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fSApO1xyXG5cclxuXHJcblx0fSApO1xyXG5cclxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdC8vIE1pbiBDb3N0XHJcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRqUXVlcnkoICcjd2hfY29zdCcgKS5vbiggJ2NoYW5nZScsIGZ1bmN0aW9uKCBldmVudCApe1xyXG5cclxuXHRcdHZhciBjaGFuZ2VkX3ZhbHVlID0galF1ZXJ5KCAnI3doX2Nvc3QnICkudmFsKCk7XHJcblxyXG5cdFx0d3BiY19hanhfYm9va2luZ19zZW5kX3NlYXJjaF9yZXF1ZXN0X3dpdGhfcGFyYW1zKCB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd3aF9jb3N0JyA6IGNoYW5nZWRfdmFsdWUsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdwYWdlX251bSc6IDFcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH0gKTtcclxuXHR9ICk7XHJcblxyXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0Ly8gTWF4IENvc3RcclxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdGpRdWVyeSggJyN3aF9jb3N0MicgKS5vbiggJ2NoYW5nZScsIGZ1bmN0aW9uKCBldmVudCApe1xyXG5cclxuXHRcdHZhciBjaGFuZ2VkX3ZhbHVlID0galF1ZXJ5KCAnI3doX2Nvc3QyJyApLnZhbCgpO1xyXG5cclxuXHRcdHdwYmNfYWp4X2Jvb2tpbmdfc2VuZF9zZWFyY2hfcmVxdWVzdF93aXRoX3BhcmFtcygge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnd2hfY29zdDInIDogY2hhbmdlZF92YWx1ZSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3BhZ2VfbnVtJzogMVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fSApO1xyXG5cdH0gKTtcclxuXHJcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHQvLyBCb29raW5nIHJlc291cmNlc1xyXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0alF1ZXJ5KCAnI3doX2Jvb2tpbmdfdHlwZScgKS5vbiggJ2NoYW5nZScsIGZ1bmN0aW9uKCBldmVudCApe1xyXG5cclxuXHRcdHZhciBjaGFuZ2VkX3ZhbHVlID0gIGpRdWVyeSggJyN3aF9ib29raW5nX3R5cGUnICkudmFsKCk7XHRcdC8vIGl0J3MgZ2V0IGFzIGFycmF5XHJcblx0XHRpZiAoICggQXJyYXkuaXNBcnJheSggY2hhbmdlZF92YWx1ZSApICkgJiYgKCAwID09PSBjaGFuZ2VkX3ZhbHVlLmxlbmd0aCApICl7XHJcblx0XHRcdGNoYW5nZWRfdmFsdWUgPSBbJy0xJ107XHJcblx0XHR9XHJcblx0XHR3cGJjX2FqeF9ib29raW5nX3NlbmRfc2VhcmNoX3JlcXVlc3Rfd2l0aF9wYXJhbXMoIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3doX2Jvb2tpbmdfdHlwZScgOiBjaGFuZ2VkX3ZhbHVlLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQncGFnZV9udW0nOiAxXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9ICk7XHJcblx0fSApO1xyXG5cclxuXHJcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHQvLyBTb3J0aW5nXHJcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRqUXVlcnkoICcjd2hfc29ydCcgKS5vbiggJ2NoYW5nZScsIGZ1bmN0aW9uKCBldmVudCApe1xyXG5cclxuXHRcdHZhciBjaGFuZ2VkX3ZhbHVlID0galF1ZXJ5KCAnI3doX3NvcnQnICkudmFsKCk7XHJcblxyXG5cdFx0Y2hhbmdlZF92YWx1ZSA9IEpTT04ucGFyc2UoIGNoYW5nZWRfdmFsdWUgKTtcclxuXHJcblx0XHR3cGJjX2FqeF9ib29raW5nX3NlbmRfc2VhcmNoX3JlcXVlc3Rfd2l0aF9wYXJhbXMoIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3doX3NvcnQnOiBjaGFuZ2VkX3ZhbHVlWyAwIF1cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdH0gKTtcclxuXHR9ICk7XHJcblxyXG59XHJcblxyXG5qUXVlcnkoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCl7XHJcblx0d3BiY19hanhfYm9va2luZ19kZWZpbmVfdWlfaG9va3Nfb25jZSgpO1xyXG59KTtcclxuIl0sIm1hcHBpbmdzIjoiQUFBQSxZQUFZOztBQUVaO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU0EscUNBQXFDQSxD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 _out/bookings__actions.js 0000666 00000214175 15166373417 0011575 0 ustar 00 "use strict"; /** * Ajax ----------------------------------------------------------------------------------------------------- */ //var is_this_action = false; /** * Send Ajax action request, like approving or cancellation * * @param action_param */ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } function wpbc_ajx_booking_ajax_action_request() { var action_param = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; console.groupCollapsed('WPBC_AJX_BOOKING_ACTIONS'); console.log(' == Ajax Actions :: Params == ', action_param); //is_this_action = true; wpbc_booking_listing_reload_button__spin_start(); // Get redefined Locale, if action on single booking ! if (undefined != action_param['booking_id'] && !Array.isArray(action_param['booking_id'])) { // Not array action_param['locale'] = wpbc_get_selected_locale(action_param['booking_id'], wpbc_ajx_booking_listing.get_secure_param('locale')); } var action_post_params = { action: 'WPBC_AJX_BOOKING_ACTIONS', nonce: wpbc_ajx_booking_listing.get_secure_param('nonce'), wpbc_ajx_user_id: undefined == action_param['user_id'] ? wpbc_ajx_booking_listing.get_secure_param('user_id') : action_param['user_id'], wpbc_ajx_locale: undefined == action_param['locale'] ? wpbc_ajx_booking_listing.get_secure_param('locale') : action_param['locale'], action_params: action_param }; // It's required for CSV export - getting the same list of bookings if (typeof action_param.search_params !== 'undefined') { action_post_params['search_params'] = action_param.search_params; delete action_post_params.action_params.search_params; } // Start Ajax jQuery.post(wpbc_url_ajax, action_post_params, /** * S u c c e s s * * @param response_data - its object returned from Ajax - class-live-searcg.php * @param textStatus - 'success' * @param jqXHR - Object */ function (response_data, textStatus, jqXHR) { console.log(' == Ajax Actions :: Response WPBC_AJX_BOOKING_ACTIONS == ', response_data); console.groupEnd(); // Probably Error if (_typeof(response_data) !== 'object' || response_data === null) { jQuery('.wpbc_ajx_under_toolbar_row').hide(); //FixIn: 9.6.1.5 jQuery(wpbc_ajx_booking_listing.get_other_param('listing_container')).html('<div class="wpbc-settings-notice notice-warning" style="text-align:left">' + response_data + '</div>'); return; } wpbc_booking_listing_reload_button__spin_pause(); wpbc_admin_show_message(response_data['ajx_after_action_message'].replace(/\n/g, "<br />"), '1' == response_data['ajx_after_action_result'] ? 'success' : 'error', 'undefined' === typeof response_data['ajx_after_action_result_all_params_arr']['after_action_result_delay'] ? 10000 : response_data['ajx_after_action_result_all_params_arr']['after_action_result_delay']); // Success response if ('1' == response_data['ajx_after_action_result']) { var is_reload_ajax_listing = true; // After Google Calendar import show imported bookings and reload the page for toolbar parameters update if (false !== response_data['ajx_after_action_result_all_params_arr']['new_listing_params']) { wpbc_ajx_booking_send_search_request_with_params(response_data['ajx_after_action_result_all_params_arr']['new_listing_params']); var closed_timer = setTimeout(function () { if (wpbc_booking_listing_reload_button__is_spin()) { if (undefined != response_data['ajx_after_action_result_all_params_arr']['new_listing_params']['reload_url_params']) { document.location.href = response_data['ajx_after_action_result_all_params_arr']['new_listing_params']['reload_url_params']; } else { document.location.reload(); } } }, 2000); is_reload_ajax_listing = false; } // Start download exported CSV file if (undefined != response_data['ajx_after_action_result_all_params_arr']['export_csv_url']) { wpbc_ajx_booking__export_csv_url__download(response_data['ajx_after_action_result_all_params_arr']['export_csv_url']); is_reload_ajax_listing = false; } if (is_reload_ajax_listing) { wpbc_ajx_booking__actual_listing__show(); // Sending Ajax Request - with parameters that we early defined in "wpbc_ajx_booking_listing" Obj. } } // Remove spin icon from button and Enable this button. wpbc_button__remove_spin(response_data['ajx_cleaned_params']['ui_clicked_element_id']); // Hide modals wpbc_popup_modals__hide(); jQuery('#ajax_respond').html(response_data); // For ability to show response, add such DIV element to page }).fail(function (jqXHR, textStatus, errorThrown) { if (window.console && window.console.log) { console.log('Ajax_Error', jqXHR, textStatus, errorThrown); } jQuery('.wpbc_ajx_under_toolbar_row').hide(); //FixIn: 9.6.1.5 var error_message = '<strong>' + 'Error!' + '</strong> ' + errorThrown; if (jqXHR.responseText) { error_message += jqXHR.responseText; } error_message = error_message.replace(/\n/g, "<br />"); wpbc_ajx_booking_show_message(error_message); }) // .done( function ( data, textStatus, jqXHR ) { if ( window.console && window.console.log ){ console.log( 'second success', data, textStatus, jqXHR ); } }) // .always( function ( data_jqXHR, textStatus, jqXHR_errorThrown ) { if ( window.console && window.console.log ){ console.log( 'always finished', data_jqXHR, textStatus, jqXHR_errorThrown ); } }) ; // End Ajax } /** * Hide all open modal popups windows */ function wpbc_popup_modals__hide() { // Hide modals if ('function' === typeof jQuery('.wpbc_popup_modal').wpbc_my_modal) { jQuery('.wpbc_popup_modal').wpbc_my_modal('hide'); } } /** * Dates Short <-> Wide ----------------------------------------------------------------------------------- */ function wpbc_ajx_click_on_dates_short() { jQuery('#booking_dates_small,.booking_dates_full').hide(); jQuery('#booking_dates_full,.booking_dates_small').show(); wpbc_ajx_booking_send_search_request_with_params({ 'ui_usr__dates_short_wide': 'short' }); } function wpbc_ajx_click_on_dates_wide() { jQuery('#booking_dates_full,.booking_dates_small').hide(); jQuery('#booking_dates_small,.booking_dates_full').show(); wpbc_ajx_booking_send_search_request_with_params({ 'ui_usr__dates_short_wide': 'wide' }); } function wpbc_ajx_click_on_dates_toggle(this_date) { jQuery(this_date).parents('.wpbc_col_dates').find('.booking_dates_small').toggle(); jQuery(this_date).parents('.wpbc_col_dates').find('.booking_dates_full').toggle(); /* var visible_section = jQuery( this_date ).parents( '.booking_dates_expand_section' ); visible_section.hide(); if ( visible_section.hasClass( 'booking_dates_full' ) ){ visible_section.parents( '.wpbc_col_dates' ).find( '.booking_dates_small' ).show(); } else { visible_section.parents( '.wpbc_col_dates' ).find( '.booking_dates_full' ).show(); }*/ console.log('wpbc_ajx_click_on_dates_toggle', this_date); } /** * Locale --------------------------------------------------------------------------------------------------- */ /** * Select options in select boxes based on attribute "value_of_selected_option" and RED color and hint for LOCALE button -- It's called from wpbc_ajx_booking_define_ui_hooks() each time after Listing loading. */ function wpbc_ajx_booking__ui_define__locale() { jQuery('.wpbc_listing_container select').each(function (index) { var selection = jQuery(this).attr("value_of_selected_option"); // Define selected select boxes if (undefined !== selection) { jQuery(this).find('option[value="' + selection + '"]').prop('selected', true); if ('' != selection && jQuery(this).hasClass('set_booking_locale_selectbox')) { // Locale var booking_locale_button = jQuery(this).parents('.ui_element_locale').find('.set_booking_locale_button'); //booking_locale_button.css( 'color', '#db4800' ); // Set button red booking_locale_button.addClass('wpbc_ui_red'); // Set button red if ('function' === typeof wpbc_tippy) { booking_locale_button.get(0)._tippy.setContent(selection); } } } }); } /** * Remark --------------------------------------------------------------------------------------------------- */ /** * Define content of remark "booking note" button and textarea. -- It's called from wpbc_ajx_booking_define_ui_hooks() each time after Listing loading. */ function wpbc_ajx_booking__ui_define__remark() { jQuery('.wpbc_listing_container .ui_remark_section textarea').each(function (index) { var text_val = jQuery(this).val(); if (undefined !== text_val && '' != text_val) { var remark_button = jQuery(this).parents('.ui_group').find('.set_booking_note_button'); if (remark_button.length > 0) { remark_button.addClass('wpbc_ui_red'); // Set button red if ('function' === typeof wpbc_tippy) { //remark_button.get( 0 )._tippy.allowHTML = true; //remark_button.get( 0 )._tippy.setContent( text_val.replace(/[\n\r]/g, '<br>') ); remark_button.get(0)._tippy.setProps({ allowHTML: true, content: text_val.replace(/[\n\r]/g, '<br>') }); } } } }); } /** * Actions ,when we click on "Remark" button. * * @param jq_button - this jQuery button object */ function wpbc_ajx_booking__ui_click__remark(jq_button) { jq_button.parents('.ui_group').find('.ui_remark_section').toggle(); } /** * Change booking resource ---------------------------------------------------------------------------------- */ function wpbc_ajx_booking__ui_click_show__change_resource(booking_id, resource_id) { // Define ID of booking to hidden input jQuery('#change_booking_resource__booking_id').val(booking_id); // Select booking resource that belong to booking jQuery('#change_booking_resource__resource_select').val(resource_id).trigger('change'); var cbr; // Get Resource section cbr = jQuery("#change_booking_resource__section").detach(); // Append it to booking ROW cbr.appendTo(jQuery("#ui__change_booking_resource__section_in_booking_" + booking_id)); cbr = null; // Hide sections of "Change booking resource" in all other bookings ROWs //jQuery( ".ui__change_booking_resource__section_in_booking" ).hide(); if (!jQuery("#ui__change_booking_resource__section_in_booking_" + booking_id).is(':visible')) { jQuery(".ui__under_actions_row__section_in_booking").hide(); } // Show only "change booking resource" section for current booking jQuery("#ui__change_booking_resource__section_in_booking_" + booking_id).toggle(); } function wpbc_ajx_booking__ui_click_save__change_resource(this_el, booking_action, el_id) { wpbc_ajx_booking_ajax_action_request({ 'booking_action': booking_action, 'booking_id': jQuery('#change_booking_resource__booking_id').val(), 'selected_resource_id': jQuery('#change_booking_resource__resource_select').val(), 'ui_clicked_element_id': el_id }); wpbc_button_enable_loading_icon(this_el); // wpbc_ajx_booking__ui_click_close__change_resource(); } function wpbc_ajx_booking__ui_click_close__change_resource() { var cbrce; // Get Resource section cbrce = jQuery("#change_booking_resource__section").detach(); // Append it to hidden HTML template section at the bottom of the page cbrce.appendTo(jQuery("#wpbc_hidden_template__change_booking_resource")); cbrce = null; // Hide all change booking resources sections jQuery(".ui__change_booking_resource__section_in_booking").hide(); } /** * Duplicate booking in other resource ---------------------------------------------------------------------- */ function wpbc_ajx_booking__ui_click_show__duplicate_booking(booking_id, resource_id) { // Define ID of booking to hidden input jQuery('#duplicate_booking_to_other_resource__booking_id').val(booking_id); // Select booking resource that belong to booking jQuery('#duplicate_booking_to_other_resource__resource_select').val(resource_id).trigger('change'); var cbr; // Get Resource section cbr = jQuery("#duplicate_booking_to_other_resource__section").detach(); // Append it to booking ROW cbr.appendTo(jQuery("#ui__duplicate_booking_to_other_resource__section_in_booking_" + booking_id)); cbr = null; // Hide sections of "Duplicate booking" in all other bookings ROWs if (!jQuery("#ui__duplicate_booking_to_other_resource__section_in_booking_" + booking_id).is(':visible')) { jQuery(".ui__under_actions_row__section_in_booking").hide(); } // Show only "Duplicate booking" section for current booking ROW jQuery("#ui__duplicate_booking_to_other_resource__section_in_booking_" + booking_id).toggle(); } function wpbc_ajx_booking__ui_click_save__duplicate_booking(this_el, booking_action, el_id) { wpbc_ajx_booking_ajax_action_request({ 'booking_action': booking_action, 'booking_id': jQuery('#duplicate_booking_to_other_resource__booking_id').val(), 'selected_resource_id': jQuery('#duplicate_booking_to_other_resource__resource_select').val(), 'ui_clicked_element_id': el_id }); wpbc_button_enable_loading_icon(this_el); // wpbc_ajx_booking__ui_click_close__change_resource(); } function wpbc_ajx_booking__ui_click_close__duplicate_booking() { var cbrce; // Get Resource section cbrce = jQuery("#duplicate_booking_to_other_resource__section").detach(); // Append it to hidden HTML template section at the bottom of the page cbrce.appendTo(jQuery("#wpbc_hidden_template__duplicate_booking_to_other_resource")); cbrce = null; // Hide all change booking resources sections jQuery(".ui__duplicate_booking_to_other_resource__section_in_booking").hide(); } /** * Change payment status ------------------------------------------------------------------------------------ */ function wpbc_ajx_booking__ui_click_show__set_payment_status(booking_id) { var jSelect = jQuery('#ui__set_payment_status__section_in_booking_' + booking_id).find('select'); var selected_pay_status = jSelect.attr("ajx-selected-value"); // Is it float - then it's unknown if (!isNaN(parseFloat(selected_pay_status))) { jSelect.find('option[value="1"]').prop('selected', true); // Unknown value is '1' in select box } else { jSelect.find('option[value="' + selected_pay_status + '"]').prop('selected', true); // Otherwise known payment status } // Hide sections of "Change booking resource" in all other bookings ROWs if (!jQuery("#ui__set_payment_status__section_in_booking_" + booking_id).is(':visible')) { jQuery(".ui__under_actions_row__section_in_booking").hide(); } // Show only "change booking resource" section for current booking jQuery("#ui__set_payment_status__section_in_booking_" + booking_id).toggle(); } function wpbc_ajx_booking__ui_click_save__set_payment_status(booking_id, this_el, booking_action, el_id) { wpbc_ajx_booking_ajax_action_request({ 'booking_action': booking_action, 'booking_id': booking_id, 'selected_payment_status': jQuery('#ui_btn_set_payment_status' + booking_id).val(), 'ui_clicked_element_id': el_id + '_save' }); wpbc_button_enable_loading_icon(this_el); jQuery('#' + el_id + '_cancel').hide(); //wpbc_button_enable_loading_icon( jQuery( '#' + el_id + '_cancel').get(0) ); } function wpbc_ajx_booking__ui_click_close__set_payment_status() { // Hide all change payment status for booking jQuery(".ui__set_payment_status__section_in_booking").hide(); } /** * Change booking cost -------------------------------------------------------------------------------------- */ function wpbc_ajx_booking__ui_click_save__set_booking_cost(booking_id, this_el, booking_action, el_id) { wpbc_ajx_booking_ajax_action_request({ 'booking_action': booking_action, 'booking_id': booking_id, 'booking_cost': jQuery('#ui_btn_set_booking_cost' + booking_id + '_cost').val(), 'ui_clicked_element_id': el_id + '_save' }); wpbc_button_enable_loading_icon(this_el); jQuery('#' + el_id + '_cancel').hide(); //wpbc_button_enable_loading_icon( jQuery( '#' + el_id + '_cancel').get(0) ); } function wpbc_ajx_booking__ui_click_close__set_booking_cost() { // Hide all change payment status for booking jQuery(".ui__set_booking_cost__section_in_booking").hide(); } /** * Send Payment request -------------------------------------------------------------------------------------- */ function wpbc_ajx_booking__ui_click__send_payment_request() { wpbc_ajx_booking_ajax_action_request({ 'booking_action': 'send_payment_request', 'booking_id': jQuery('#wpbc_modal__payment_request__booking_id').val(), 'reason_of_action': jQuery('#wpbc_modal__payment_request__reason_of_action').val(), 'ui_clicked_element_id': 'wpbc_modal__payment_request__button_send' }); wpbc_button_enable_loading_icon(jQuery('#wpbc_modal__payment_request__button_send').get(0)); } /** * Import Google Calendar ------------------------------------------------------------------------------------ */ function wpbc_ajx_booking__ui_click__import_google_calendar() { wpbc_ajx_booking_ajax_action_request({ 'booking_action': 'import_google_calendar', 'ui_clicked_element_id': 'wpbc_modal__import_google_calendar__button_send', 'booking_gcal_events_from': jQuery('#wpbc_modal__import_google_calendar__section #booking_gcal_events_from option:selected').val(), 'booking_gcal_events_from_offset': jQuery('#wpbc_modal__import_google_calendar__section #booking_gcal_events_from_offset').val(), 'booking_gcal_events_from_offset_type': jQuery('#wpbc_modal__import_google_calendar__section #booking_gcal_events_from_offset_type option:selected').val(), 'booking_gcal_events_until': jQuery('#wpbc_modal__import_google_calendar__section #booking_gcal_events_until option:selected').val(), 'booking_gcal_events_until_offset': jQuery('#wpbc_modal__import_google_calendar__section #booking_gcal_events_until_offset').val(), 'booking_gcal_events_until_offset_type': jQuery('#wpbc_modal__import_google_calendar__section #booking_gcal_events_until_offset_type option:selected').val(), 'booking_gcal_events_max': jQuery('#wpbc_modal__import_google_calendar__section #booking_gcal_events_max').val(), 'booking_gcal_resource': jQuery('#wpbc_modal__import_google_calendar__section #wpbc_booking_resource option:selected').val() }); wpbc_button_enable_loading_icon(jQuery('#wpbc_modal__import_google_calendar__section #wpbc_modal__import_google_calendar__button_send').get(0)); } /** * Export bookings to CSV ------------------------------------------------------------------------------------ */ function wpbc_ajx_booking__ui_click__export_csv(params) { var selected_booking_id_arr = wpbc_get_selected_row_id(); wpbc_ajx_booking_ajax_action_request({ 'booking_action': params['booking_action'], 'ui_clicked_element_id': params['ui_clicked_element_id'], 'export_type': params['export_type'], 'csv_export_separator': params['csv_export_separator'], 'csv_export_skip_fields': params['csv_export_skip_fields'], 'booking_id': selected_booking_id_arr.join(','), 'search_params': wpbc_ajx_booking_listing.search_get_all_params() }); var this_el = jQuery('#' + params['ui_clicked_element_id']).get(0); wpbc_button_enable_loading_icon(this_el); } /** * Open URL in new tab - mainly it's used for open CSV link for downloaded exported bookings as CSV * * @param export_csv_url */ function wpbc_ajx_booking__export_csv_url__download(export_csv_url) { //var selected_booking_id_arr = wpbc_get_selected_row_id(); document.location.href = export_csv_url; // + '&selected_id=' + selected_booking_id_arr.join(','); // It's open additional dialog for asking opening ulr in new tab // window.open( export_csv_url, '_blank').focus(); } //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5jbHVkZXMvcGFnZS1ib29raW5ncy9fb3V0L2Jvb2tpbmdzX19hY3Rpb25zLmpzIiwibmFtZXMiOlsiX3R5cGVvZiIsIm9iaiIsIlN5bWJvbCIsIml0ZXJhdG9yIiwiY29uc3RydWN0b3IiLCJwcm90b3R5cGUiLCJ3cGJjX2FqeF9ib29raW5nX2FqYXhfYWN0aW9uX3JlcXVlc3QiLCJhY3Rpb25fcGFyYW0iLCJhcmd1bWVudHMiLCJsZW5ndGgiLCJ1bmRlZmluZWQiLCJjb25zb2xlIiwiZ3JvdXBDb2xsYXBzZWQiLCJsb2ciLCJ3cGJjX2Jvb2tpbmdfbGlzdGluZ19yZWxvYWRfYnV0dG9uX19zcGluX3N0YXJ0IiwiQXJyYXkiLCJpc0FycmF5Iiwid3BiY19nZXRfc2VsZWN0ZWRfbG9jYWxlIiwid3BiY19hanhfYm9va2luZ19saXN0aW5nIiwiZ2V0X3NlY3VyZV9wYXJhbSIsImFjdGlvbl9wb3N0X3BhcmFtcyIsImFjdGlvbiIsIm5vbmNlIiwid3BiY19hanhfdXNlcl9pZCIsIndwYmNfYWp4X2xvY2FsZSIsImFjdGlvbl9wYXJhbXMiLCJzZWFyY2hfcGFyYW1zIiwialF1ZXJ5IiwicG9zdCIsIndwYmNfdXJsX2FqYXgiLCJyZXNwb25zZV9kYXRhIiwidGV4dFN0YXR1cyIsImpxWEhSIiwiZ3JvdXBFbmQiLCJoaWRlIiwiZ2V0X290aGVyX3BhcmFtIiwiaHRtbCIsIndwYmNfYm9va2luZ19saXN0aW5nX3JlbG9hZF9idXR0b25fX3NwaW5fcGF1c2UiLCJ3cGJjX2FkbWluX3Nob3dfbWVzc2FnZSIsInJlcGxhY2UiLCJpc19yZWxvYWRfYWpheF9saXN0aW5nIiwid3BiY19hanhfYm9va2luZ19zZW5kX3NlYXJjaF9yZXF1ZXN0X3dpdGhfcGFyYW1zIiwiY2xvc2VkX3RpbWVyIiwic2V0VGltZW91dCIsIndwYmNfYm9va2luZ19saXN0aW5nX3JlbG9hZF9idXR0b25fX2lzX3NwaW4iLCJkb2N1bWVudCIsImxvY2F0aW9uIiwiaHJlZiIsInJlbG9hZCIsIndwYmNfYWp4X2Jvb2tpbmdfX2V4cG9ydF9jc3ZfdXJsX19kb3dubG9hZCIsIndwYmNfYWp4X2Jvb2tpbmdfX2FjdHVhbF9saXN0aW5nX19zaG93Iiwid3BiY19idXR0b25fX3JlbW92ZV9zcGluIiwid3BiY19wb3B1cF9tb2RhbHNfX2hpZGUiLCJmYWlsIiwiZXJyb3JUaHJvd24iLCJ3aW5kb3ciLCJlcnJvcl9tZXNzYWdlIiwicmVzcG9uc2VUZXh0Iiwid3BiY19hanhfYm9va2luZ19zaG93X21lc3NhZ2UiLCJ3cGJjX215X21vZGFsIiwid3BiY19hanhfY2xpY2tfb25fZGF0ZXNfc2hvcnQiLCJzaG93Iiwid3BiY19hanhfY2xpY2tfb25fZGF0ZXNfd2lkZSIsIndwYmNfYWp4X2NsaWNrX29uX2RhdGVzX3RvZ2dsZSIsInRoaXNfZGF0ZSIsInBhcmVudHMiLCJmaW5kIiwidG9nZ2xlIiwid3BiY19hanhfYm9va2luZ19fdWlfZGVmaW5lX19sb2NhbGUiLCJlYWNoIiwiaW5kZXgiLCJzZWxlY3Rpb24iLCJhdHRyIiwicHJvcCIsImhhc0NsYXNzIiwiYm9va2luZ19sb2NhbGVfYnV0dG9uIiwiYWRkQ2xhc3MiLCJ3cGJjX3RpcHB5IiwiZ2V0IiwiX3RpcHB5Iiwic2V0Q29udGVudCIsIndwYmNfYWp4X2Jvb2tpbmdfX3VpX2RlZmluZV9fcmVtYXJrIiwidGV4dF92YWwiLCJ2YWwiLCJyZW1hcmtfYnV0dG9uIiwic2V0UHJvcHMiLCJhbGxvd0hUTUwiLCJjb250ZW50Iiwid3BiY19hanhfYm9va2luZ19fdWlfY2xpY2tfX3JlbWFyayIsImpxX2J1dHRvbiIsIndwYmNfYWp4X2Jvb2tpbmdfX3VpX2NsaWNrX3Nob3dfX2NoYW5nZV9yZXNvdXJjZSIsImJvb2tpbmdfaWQiLCJyZXNvdXJjZV9pZCIsInRyaWdnZXIiLCJjYnIiLCJkZXRhY2giLCJhcHBlbmRUbyIsImlzIiwid3BiY19hanhfYm9va2luZ19fdWlfY2xpY2tfc2F2ZV9fY2hhbmdlX3Jlc291cmNlIiwidGhpc19lbCIsImJvb2tpbmdfYWN0aW9uIiwiZWxfaWQiLCJ3cGJjX2J1dHRvbl9lbmFibGVfbG9hZGluZ19pY29uIiwid3BiY19hanhfYm9va2luZ19fdWlfY2xpY2tfY2xvc2VfX2NoYW5nZV9yZXNvdXJjZSIsImNicmNlIiwid3BiY19hanhfYm9va2luZ19fdWlfY2xpY2tfc2hvd19fZHVwbGljYXRlX2Jvb2tpbmciLCJ3cGJjX2FqeF9ib29raW5nX191aV9jbGlja19zYXZlX19kdXBsaWNhdGVfYm9va2luZyIsIndwYmNfYWp4X2Jvb2tpbmdfX3VpX2NsaWNrX2Nsb3NlX19kdXBsaWNhdGVfYm9va2luZyIsIndwYmNfYWp4X2Jvb2tpbmdfX3VpX2NsaWNrX3Nob3dfX3NldF9wYXltZW50X3N0YXR1cyIsImpTZWxlY3QiLCJzZWxlY3RlZF9wYXlfc3RhdHVzIiwiaXNOYU4iLCJwYXJzZUZsb2F0Iiwid3BiY19hanhfYm9va2luZ19fdWlfY2xpY2tfc2F2ZV9fc2V0X3BheW1lbnRfc3RhdHVzIiwid3BiY19hanhfYm9va2luZ19fdWlfY2xpY2tfY2xvc2VfX3NldF9wYXltZW50X3N0YXR1cyIsIndwYmNfYWp4X2Jvb2tpbmdfX3VpX2NsaWNrX3NhdmVfX3NldF9ib29raW5nX2Nvc3QiLCJ3cGJjX2FqeF9ib29raW5nX191aV9jbGlja19jbG9zZV9fc2V0X2Jvb2tpbmdfY29zdCIsIndwYmNfYWp4X2Jvb2tpbmdfX3VpX2NsaWNrX19zZW5kX3BheW1lbnRfcmVxdWVzdCIsIndwYmNfYWp4X2Jvb2tpbmdfX3VpX2NsaWNrX19pbXBvcnRfZ29vZ2xlX2NhbGVuZGFyIiwid3BiY19hanhfYm9va2luZ19fdWlfY2xpY2tfX2V4cG9ydF9jc3YiLCJwYXJhbXMiLCJzZWxlY3RlZF9ib29raW5nX2lkX2FyciIsIndwYmNfZ2V0X3NlbGVjdGVkX3Jvd19pZCIsImpvaW4iLCJzZWFyY2hfZ2V0X2FsbF9wYXJhbXMiLCJleHBvcnRfY3N2X3VybCJdLCJzb3VyY2VzIjpbImluY2x1ZGVzL3BhZ2UtYm9va2luZ3MvX3NyYy9ib29raW5nc19fYWN0aW9ucy5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJcInVzZSBzdHJpY3RcIjtcclxuXHJcbi8qKlxyXG4gKiAgIEFqYXggICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xyXG4vL3ZhciBpc190aGlzX2FjdGlvbiA9IGZhbHNlO1xyXG4vKipcclxuICogU2VuZCBBamF4IGFjdGlvbiByZXF1ZXN0LCAgbGlrZSBhcHByb3Zpbmcgb3IgY2FuY2VsbGF0aW9uXHJcbiAqXHJcbiAqIEBwYXJhbSBhY3Rpb25fcGFyYW1cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYWp4X2Jvb2tpbmdfYWpheF9hY3Rpb25fcmVxdWVzdCggYWN0aW9uX3BhcmFtID0ge30gKXtcclxuXHJcbmNvbnNvbGUuZ3JvdXBDb2xsYXBzZWQoICdXUEJDX0FKWF9CT09LSU5HX0FDVElPTlMnICk7IGNvbnNvbGUubG9nKCAnID09IEFqYXggQWN0aW9ucyA6OiBQYXJhbXMgPT0gJywgYWN0aW9uX3BhcmFtICk7XHJcbi8vaXNfdGhpc19hY3Rpb24gPSB0cnVlO1xyXG5cclxuXHR3cGJjX2Jvb2tpbmdfbGlzdGluZ19yZWxvYWRfYnV0dG9uX19zcGluX3N0YXJ0KCk7XHJcblxyXG5cdC8vIEdldCByZWRlZmluZWQgTG9jYWxlLCAgaWYgYWN0aW9uIG9uIHNpbmdsZSBib29raW5nICFcclxuXHRpZiAoICAoIHVuZGVmaW5lZCAhPSBhY3Rpb25fcGFyYW1bICdib29raW5nX2lkJyBdICkgJiYgKCAhIEFycmF5LmlzQXJyYXkoIGFjdGlvbl9wYXJhbVsgJ2Jvb2tpbmdfaWQnIF0gKSApICl7XHRcdFx0XHQvLyBOb3QgYXJyYXlcclxuXHJcblx0XHRhY3Rpb25fcGFyYW1bICdsb2NhbGUnIF0gPSB3cGJjX2dldF9zZWxlY3RlZF9sb2NhbGUoIGFjdGlvbl9wYXJhbVsgJ2Jvb2tpbmdfaWQnIF0sIHdwYmNfYWp4X2Jvb2tpbmdfbGlzdGluZy5nZXRfc2VjdXJlX3BhcmFtKCAnbG9jYWxlJyApICk7XHJcblx0fVxyXG5cclxuXHR2YXIgYWN0aW9uX3Bvc3RfcGFyYW1zID0ge1xyXG5cdFx0XHRcdFx0XHRcdFx0YWN0aW9uICAgICAgICAgIDogJ1dQQkNfQUpYX0JPT0tJTkdfQUNUSU9OUycsXHJcblx0XHRcdFx0XHRcdFx0XHRub25jZSAgICAgICAgICAgOiB3cGJjX2FqeF9ib29raW5nX2xpc3RpbmcuZ2V0X3NlY3VyZV9wYXJhbSggJ25vbmNlJyApLFxyXG5cdFx0XHRcdFx0XHRcdFx0d3BiY19hanhfdXNlcl9pZDogKCAoIHVuZGVmaW5lZCA9PSBhY3Rpb25fcGFyYW1bICd1c2VyX2lkJyBdICkgPyB3cGJjX2FqeF9ib29raW5nX2xpc3RpbmcuZ2V0X3NlY3VyZV9wYXJhbSggJ3VzZXJfaWQnICkgOiBhY3Rpb25fcGFyYW1bICd1c2VyX2lkJyBdICksXHJcblx0XHRcdFx0XHRcdFx0XHR3cGJjX2FqeF9sb2NhbGU6ICAoICggdW5kZWZpbmVkID09IGFjdGlvbl9wYXJhbVsgJ2xvY2FsZScgXSApICA/IHdwYmNfYWp4X2Jvb2tpbmdfbGlzdGluZy5nZXRfc2VjdXJlX3BhcmFtKCAnbG9jYWxlJyApICA6IGFjdGlvbl9wYXJhbVsgJ2xvY2FsZScgXSApLFxyXG5cclxuXHRcdFx0XHRcdFx0XHRcdGFjdGlvbl9wYXJhbXNcdDogYWN0aW9uX3BhcmFtXHJcblx0XHRcdFx0XHRcdFx0fTtcclxuXHJcblx0Ly8gSXQncyByZXF1aXJlZCBmb3IgQ1NWIGV4cG9ydCAtIGdldHRpbmcgdGhlIHNhbWUgbGlzdCAgb2YgYm9va2luZ3NcclxuXHRpZiAoIHR5cGVvZiBhY3Rpb25fcGFyYW0uc2VhcmNoX3BhcmFtcyAhPT0gJ3VuZGVmaW5lZCcgKXtcclxuXHRcdGFjdGlvbl9wb3N0X3BhcmFtc1sgJ3NlYXJjaF9wYXJhbXMnIF0gPSBhY3Rpb25fcGFyYW0uc2VhcmNoX3BhcmFtcztcclxuXHRcdGRlbGV0ZSBhY3Rpb25fcG9zdF9wYXJhbXMuYWN0aW9uX3BhcmFtcy5zZWFyY2hfcGFyYW1zO1xyXG5cdH1cclxuXHJcblx0Ly8gU3RhcnQgQWpheFxyXG5cdGpRdWVyeS5wb3N0KCB3cGJjX3VybF9hamF4ICxcclxuXHJcblx0XHRcdFx0YWN0aW9uX3Bvc3RfcGFyYW1zICxcclxuXHJcblx0XHRcdFx0LyoqXHJcblx0XHRcdFx0ICogUyB1IGMgYyBlIHMgc1xyXG5cdFx0XHRcdCAqXHJcblx0XHRcdFx0ICogQHBhcmFtIHJlc3BvbnNlX2RhdGFcdFx0LVx0aXRzIG9iamVjdCByZXR1cm5lZCBmcm9tICBBamF4IC0gY2xhc3MtbGl2ZS1zZWFyY2cucGhwXHJcblx0XHRcdFx0ICogQHBhcmFtIHRleHRTdGF0dXNcdFx0LVx0J3N1Y2Nlc3MnXHJcblx0XHRcdFx0ICogQHBhcmFtIGpxWEhSXHRcdFx0XHQtXHRPYmplY3RcclxuXHRcdFx0XHQgKi9cclxuXHRcdFx0XHRmdW5jdGlvbiAoIHJlc3BvbnNlX2RhdGEsIHRleHRTdGF0dXMsIGpxWEhSICkge1xyXG5cclxuY29uc29sZS5sb2coICcgPT0gQWpheCBBY3Rpb25zIDo6IFJlc3BvbnNlIFdQQkNfQUpYX0JPT0tJTkdfQUNUSU9OUyA9PSAnLCByZXNwb25zZV9kYXRhICk7IGNvbnNvbGUuZ3JvdXBFbmQoKTtcclxuXHJcblx0XHRcdFx0XHQvLyBQcm9iYWJseSBFcnJvclxyXG5cdFx0XHRcdFx0aWYgKCAodHlwZW9mIHJlc3BvbnNlX2RhdGEgIT09ICdvYmplY3QnKSB8fCAocmVzcG9uc2VfZGF0YSA9PT0gbnVsbCkgKXtcclxuXHRcdFx0XHRcdFx0alF1ZXJ5KCAnLndwYmNfYWp4X3VuZGVyX3Rvb2xiYXJfcm93JyApLmhpZGUoKTtcdCBcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvL0ZpeEluOiA5LjYuMS41XHJcblx0XHRcdFx0XHRcdGpRdWVyeSggd3BiY19hanhfYm9va2luZ19saXN0aW5nLmdldF9vdGhlcl9wYXJhbSggJ2xpc3RpbmdfY29udGFpbmVyJyApICkuaHRtbChcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCc8ZGl2IGNsYXNzPVwid3BiYy1zZXR0aW5ncy1ub3RpY2Ugbm90aWNlLXdhcm5pbmdcIiBzdHlsZT1cInRleHQtYWxpZ246bGVmdFwiPicgK1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZXNwb25zZV9kYXRhICtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCc8L2Rpdj4nXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCk7XHJcblx0XHRcdFx0XHRcdHJldHVybjtcclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHR3cGJjX2Jvb2tpbmdfbGlzdGluZ19yZWxvYWRfYnV0dG9uX19zcGluX3BhdXNlKCk7XHJcblxyXG5cdFx0XHRcdFx0d3BiY19hZG1pbl9zaG93X21lc3NhZ2UoXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdCAgcmVzcG9uc2VfZGF0YVsgJ2FqeF9hZnRlcl9hY3Rpb25fbWVzc2FnZScgXS5yZXBsYWNlKCAvXFxuL2csIFwiPGJyIC8+XCIgKVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQsICggJzEnID09IHJlc3BvbnNlX2RhdGFbICdhanhfYWZ0ZXJfYWN0aW9uX3Jlc3VsdCcgXSApID8gJ3N1Y2Nlc3MnIDogJ2Vycm9yJ1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQsICggKCAndW5kZWZpbmVkJyA9PT0gdHlwZW9mKHJlc3BvbnNlX2RhdGFbICdhanhfYWZ0ZXJfYWN0aW9uX3Jlc3VsdF9hbGxfcGFyYW1zX2FycicgXVsgJ2FmdGVyX2FjdGlvbl9yZXN1bHRfZGVsYXknIF0pIClcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQ/IDEwMDAwXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0OiByZXNwb25zZV9kYXRhWyAnYWp4X2FmdGVyX2FjdGlvbl9yZXN1bHRfYWxsX3BhcmFtc19hcnInIF1bICdhZnRlcl9hY3Rpb25fcmVzdWx0X2RlbGF5JyBdIClcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCk7XHJcblxyXG5cdFx0XHRcdFx0Ly8gU3VjY2VzcyByZXNwb25zZVxyXG5cdFx0XHRcdFx0aWYgKCAnMScgPT0gcmVzcG9uc2VfZGF0YVsgJ2FqeF9hZnRlcl9hY3Rpb25fcmVzdWx0JyBdICl7XHJcblxyXG5cdFx0XHRcdFx0XHR2YXIgaXNfcmVsb2FkX2FqYXhfbGlzdGluZyA9IHRydWU7XHJcblxyXG5cdFx0XHRcdFx0XHQvLyBBZnRlciBHb29nbGUgQ2FsZW5kYXIgaW1wb3J0IHNob3cgaW1wb3J0ZWQgYm9va2luZ3MgYW5kIHJlbG9hZCB0aGUgcGFnZSBmb3IgdG9vbGJhciBwYXJhbWV0ZXJzIHVwZGF0ZVxyXG5cdFx0XHRcdFx0XHRpZiAoIGZhbHNlICE9PSByZXNwb25zZV9kYXRhWyAnYWp4X2FmdGVyX2FjdGlvbl9yZXN1bHRfYWxsX3BhcmFtc19hcnInIF1bICduZXdfbGlzdGluZ19wYXJhbXMnIF0gKXtcclxuXHJcblx0XHRcdFx0XHRcdFx0d3BiY19hanhfYm9va2luZ19zZW5kX3NlYXJjaF9yZXF1ZXN0X3dpdGhfcGFyYW1zKCByZXNwb25zZV9kYXRhWyAnYWp4X2FmdGVyX2FjdGlvbl9yZXN1bHRfYWxsX3BhcmFtc19hcnInIF1bICduZXdfbGlzdGluZ19wYXJhbXMnIF0gKTtcclxuXHJcblx0XHRcdFx0XHRcdFx0dmFyIGNsb3NlZF90aW1lciA9IHNldFRpbWVvdXQoIGZ1bmN0aW9uICgpe1xyXG5cclxuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCB3cGJjX2Jvb2tpbmdfbGlzdGluZ19yZWxvYWRfYnV0dG9uX19pc19zcGluKCkgKXtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoIHVuZGVmaW5lZCAhPSByZXNwb25zZV9kYXRhWyAnYWp4X2FmdGVyX2FjdGlvbl9yZXN1bHRfYWxsX3BhcmFtc19hcnInIF1bICduZXdfbGlzdGluZ19wYXJhbXMnIF1bICdyZWxvYWRfdXJsX3BhcmFtcycgXSApe1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0ZG9jdW1lbnQubG9jYXRpb24uaHJlZiA9IHJlc3BvbnNlX2RhdGFbICdhanhfYWZ0ZXJfYWN0aW9uX3Jlc3VsdF9hbGxfcGFyYW1zX2FycicgXVsgJ25ld19saXN0aW5nX3BhcmFtcycgXVsgJ3JlbG9hZF91cmxfcGFyYW1zJyBdO1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRkb2N1bWVudC5sb2NhdGlvbi5yZWxvYWQoKTtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0LCAyMDAwICk7XHJcblx0XHRcdFx0XHRcdFx0aXNfcmVsb2FkX2FqYXhfbGlzdGluZyA9IGZhbHNlO1xyXG5cdFx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0XHQvLyBTdGFydCBkb3dubG9hZCBleHBvcnRlZCBDU1YgZmlsZVxyXG5cdFx0XHRcdFx0XHRpZiAoIHVuZGVmaW5lZCAhPSByZXNwb25zZV9kYXRhWyAnYWp4X2FmdGVyX2FjdGlvbl9yZXN1bHRfYWxsX3BhcmFtc19hcnInIF1bICdleHBvcnRfY3N2X3VybCcgXSApe1xyXG5cdFx0XHRcdFx0XHRcdHdwYmNfYWp4X2Jvb2tpbmdfX2V4cG9ydF9jc3ZfdXJsX19kb3dubG9hZCggcmVzcG9uc2VfZGF0YVsgJ2FqeF9hZnRlcl9hY3Rpb25fcmVzdWx0X2FsbF9wYXJhbXNfYXJyJyBdWyAnZXhwb3J0X2Nzdl91cmwnIF0gKTtcclxuXHRcdFx0XHRcdFx0XHRpc19yZWxvYWRfYWpheF9saXN0aW5nID0gZmFsc2U7XHJcblx0XHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHRcdGlmICggaXNfcmVsb2FkX2FqYXhfbGlzdGluZyApe1xyXG5cdFx0XHRcdFx0XHRcdHdwYmNfYWp4X2Jvb2tpbmdfX2FjdHVhbF9saXN0aW5nX19zaG93KCk7XHQvL1x0U2VuZGluZyBBamF4IFJlcXVlc3RcdC1cdHdpdGggcGFyYW1ldGVycyB0aGF0ICB3ZSBlYXJseSAgZGVmaW5lZCBpbiBcIndwYmNfYWp4X2Jvb2tpbmdfbGlzdGluZ1wiIE9iai5cclxuXHRcdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0XHQvLyBSZW1vdmUgc3BpbiBpY29uIGZyb20gIGJ1dHRvbiBhbmQgRW5hYmxlIHRoaXMgYnV0dG9uLlxyXG5cdFx0XHRcdFx0d3BiY19idXR0b25fX3JlbW92ZV9zcGluKCByZXNwb25zZV9kYXRhWyAnYWp4X2NsZWFuZWRfcGFyYW1zJyBdWyAndWlfY2xpY2tlZF9lbGVtZW50X2lkJyBdIClcclxuXHJcblx0XHRcdFx0XHQvLyBIaWRlIG1vZGFsc1xyXG5cdFx0XHRcdFx0d3BiY19wb3B1cF9tb2RhbHNfX2hpZGUoKTtcclxuXHJcblx0XHRcdFx0XHRqUXVlcnkoICcjYWpheF9yZXNwb25kJyApLmh0bWwoIHJlc3BvbnNlX2RhdGEgKTtcdFx0Ly8gRm9yIGFiaWxpdHkgdG8gc2hvdyByZXNwb25zZSwgYWRkIHN1Y2ggRElWIGVsZW1lbnQgdG8gcGFnZVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0ICApLmZhaWwoIGZ1bmN0aW9uICgganFYSFIsIHRleHRTdGF0dXMsIGVycm9yVGhyb3duICkgeyAgICBpZiAoIHdpbmRvdy5jb25zb2xlICYmIHdpbmRvdy5jb25zb2xlLmxvZyApeyBjb25zb2xlLmxvZyggJ0FqYXhfRXJyb3InLCBqcVhIUiwgdGV4dFN0YXR1cywgZXJyb3JUaHJvd24gKTsgfVxyXG5cdFx0XHRcdFx0alF1ZXJ5KCAnLndwYmNfYWp4X3VuZGVyX3Rvb2xiYXJfcm93JyApLmhpZGUoKTtcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly9GaXhJbjogOS42LjEuNVxyXG5cdFx0XHRcdFx0dmFyIGVycm9yX21lc3NhZ2UgPSAnPHN0cm9uZz4nICsgJ0Vycm9yIScgKyAnPC9zdHJvbmc+ICcgKyBlcnJvclRocm93biA7XHJcblx0XHRcdFx0XHRpZiAoIGpxWEhSLnJlc3BvbnNlVGV4dCApe1xyXG5cdFx0XHRcdFx0XHRlcnJvcl9tZXNzYWdlICs9IGpxWEhSLnJlc3BvbnNlVGV4dDtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGVycm9yX21lc3NhZ2UgPSBlcnJvcl9tZXNzYWdlLnJlcGxhY2UoIC9cXG4vZywgXCI8YnIgLz5cIiApO1xyXG5cclxuXHRcdFx0XHRcdHdwYmNfYWp4X2Jvb2tpbmdfc2hvd19tZXNzYWdlKCBlcnJvcl9tZXNzYWdlICk7XHJcblx0XHRcdCAgfSlcclxuXHQgICAgICAgICAgLy8gLmRvbmUoICAgZnVuY3Rpb24gKCBkYXRhLCB0ZXh0U3RhdHVzLCBqcVhIUiApIHsgICBpZiAoIHdpbmRvdy5jb25zb2xlICYmIHdpbmRvdy5jb25zb2xlLmxvZyApeyBjb25zb2xlLmxvZyggJ3NlY29uZCBzdWNjZXNzJywgZGF0YSwgdGV4dFN0YXR1cywganFYSFIgKTsgfSAgICB9KVxyXG5cdFx0XHQgIC8vIC5hbHdheXMoIGZ1bmN0aW9uICggZGF0YV9qcVhIUiwgdGV4dFN0YXR1cywganFYSFJfZXJyb3JUaHJvd24gKSB7ICAgaWYgKCB3aW5kb3cuY29uc29sZSAmJiB3aW5kb3cuY29uc29sZS5sb2cgKXsgY29uc29sZS5sb2coICdhbHdheXMgZmluaXNoZWQnLCBkYXRhX2pxWEhSLCB0ZXh0U3RhdHVzLCBqcVhIUl9lcnJvclRocm93biApOyB9ICAgICB9KVxyXG5cdFx0XHQgIDsgIC8vIEVuZCBBamF4XHJcbn1cclxuXHJcblxyXG5cclxuLyoqXHJcbiAqIEhpZGUgYWxsIG9wZW4gbW9kYWwgcG9wdXBzIHdpbmRvd3NcclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfcG9wdXBfbW9kYWxzX19oaWRlKCl7XHJcblxyXG5cdC8vIEhpZGUgbW9kYWxzXHJcblx0aWYgKCAnZnVuY3Rpb24nID09PSB0eXBlb2YgKGpRdWVyeSggJy53cGJjX3BvcHVwX21vZGFsJyApLndwYmNfbXlfbW9kYWwpICl7XHJcblx0XHRqUXVlcnkoICcud3BiY19wb3B1cF9tb2RhbCcgKS53cGJjX215X21vZGFsKCAnaGlkZScgKTtcclxuXHR9XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogICBEYXRlcyAgU2hvcnQgPC0+IFdpZGUgICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cclxuXHJcbmZ1bmN0aW9uIHdwYmNfYWp4X2NsaWNrX29uX2RhdGVzX3Nob3J0KCl7XHJcblx0alF1ZXJ5KCAnI2Jvb2tpbmdfZGF0ZXNfc21hbGwsLmJvb2tpbmdfZGF0ZXNfZnVsbCcgKS5oaWRlKCk7XHJcblx0alF1ZXJ5KCAnI2Jvb2tpbmdfZGF0ZXNfZnVsbCwuYm9va2luZ19kYXRlc19zbWFsbCcgKS5zaG93KCk7XHJcblx0d3BiY19hanhfYm9va2luZ19zZW5kX3NlYXJjaF9yZXF1ZXN0X3dpdGhfcGFyYW1zKCB7J3VpX3Vzcl9fZGF0ZXNfc2hvcnRfd2lkZSc6ICdzaG9ydCd9ICk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHdwYmNfYWp4X2NsaWNrX29uX2RhdGVzX3dpZGUoKXtcclxuXHRqUXVlcnkoICcjYm9va2luZ19kYXRlc19mdWxsLC5ib29raW5nX2RhdGVzX3NtYWxsJyApLmhpZGUoKTtcclxuXHRqUXVlcnkoICcjYm9va2luZ19kYXRlc19zbWFsbCwuYm9va2luZ19kYXRlc19mdWxsJyApLnNob3coKTtcclxuXHR3cGJjX2FqeF9ib29raW5nX3NlbmRfc2VhcmNoX3JlcXVlc3Rfd2l0aF9wYXJhbXMoIHsndWlfdXNyX19kYXRlc19zaG9ydF93aWRlJzogJ3dpZGUnfSApO1xyXG59XHJcblxyXG5mdW5jdGlvbiB3cGJjX2FqeF9jbGlja19vbl9kYXRlc190b2dnbGUodGhpc19kYXRlKXtcclxuXHJcblx0alF1ZXJ5KCB0aGlzX2RhdGUgKS5wYXJlbnRzKCAnLndwYmNfY29sX2RhdGVzJyApLmZpbmQoICcuYm9va2luZ19kYXRlc19zbWFsbCcgKS50b2dnbGUoKTtcclxuXHRqUXVlcnkoIHRoaXNfZGF0ZSApLnBhcmVudHMoICcud3BiY19jb2xfZGF0ZXMnICkuZmluZCggJy5ib29raW5nX2RhdGVzX2Z1bGwnICkudG9nZ2xlKCk7XHJcblxyXG5cdC8qXHJcblx0dmFyIHZpc2libGVfc2VjdGlvbiA9IGpRdWVyeSggdGhpc19kYXRlICkucGFyZW50cyggJy5ib29raW5nX2RhdGVzX2V4cGFuZF9zZWN0aW9uJyApO1xyXG5cdHZpc2libGVfc2VjdGlvbi5oaWRlKCk7XHJcblx0aWYgKCB2aXNpYmxlX3NlY3Rpb24uaGFzQ2xhc3MoICdib29raW5nX2RhdGVzX2Z1bGwnICkgKXtcclxuXHRcdHZpc2libGVfc2VjdGlvbi5wYXJlbnRzKCAnLndwYmNfY29sX2RhdGVzJyApLmZpbmQoICcuYm9va2luZ19kYXRlc19zbWFsbCcgKS5zaG93KCk7XHJcblx0fSBlbHNlIHtcclxuXHRcdHZpc2libGVfc2VjdGlvbi5wYXJlbnRzKCAnLndwYmNfY29sX2RhdGVzJyApLmZpbmQoICcuYm9va2luZ19kYXRlc19mdWxsJyApLnNob3coKTtcclxuXHR9Ki9cclxuXHRjb25zb2xlLmxvZyggJ3dwYmNfYWp4X2NsaWNrX29uX2RhdGVzX3RvZ2dsZScsIHRoaXNfZGF0ZSApO1xyXG59XHJcblxyXG4vKipcclxuICogICBMb2NhbGUgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cclxuXHJcbi8qKlxyXG4gKiBcdFNlbGVjdCBvcHRpb25zIGluIHNlbGVjdCBib3hlcyBiYXNlZCBvbiBhdHRyaWJ1dGUgXCJ2YWx1ZV9vZl9zZWxlY3RlZF9vcHRpb25cIiBhbmQgUkVEIGNvbG9yIGFuZCBoaW50IGZvciBMT0NBTEUgYnV0dG9uICAgLS0gIEl0J3MgY2FsbGVkIGZyb20gXHR3cGJjX2FqeF9ib29raW5nX2RlZmluZV91aV9ob29rcygpICBcdGVhY2ggIHRpbWUgYWZ0ZXIgTGlzdGluZyBsb2FkaW5nLlxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19hanhfYm9va2luZ19fdWlfZGVmaW5lX19sb2NhbGUoKXtcclxuXHJcblx0alF1ZXJ5KCAnLndwYmNfbGlzdGluZ19jb250YWluZXIgc2VsZWN0JyApLmVhY2goIGZ1bmN0aW9uICggaW5kZXggKXtcclxuXHJcblx0XHR2YXIgc2VsZWN0aW9uID0galF1ZXJ5KCB0aGlzICkuYXR0ciggXCJ2YWx1ZV9vZl9zZWxlY3RlZF9vcHRpb25cIiApO1x0XHRcdC8vIERlZmluZSBzZWxlY3RlZCBzZWxlY3QgYm94ZXNcclxuXHJcblx0XHRpZiAoIHVuZGVmaW5lZCAhPT0gc2VsZWN0aW9uICl7XHJcblx0XHRcdGpRdWVyeSggdGhpcyApLmZpbmQoICdvcHRpb25bdmFsdWU9XCInICsgc2VsZWN0aW9uICsgJ1wiXScgKS5wcm9wKCAnc2VsZWN0ZWQnLCB0cnVlICk7XHJcblxyXG5cdFx0XHRpZiAoICgnJyAhPSBzZWxlY3Rpb24pICYmIChqUXVlcnkoIHRoaXMgKS5oYXNDbGFzcyggJ3NldF9ib29raW5nX2xvY2FsZV9zZWxlY3Rib3gnICkpICl7XHRcdFx0XHRcdFx0XHRcdC8vIExvY2FsZVxyXG5cclxuXHRcdFx0XHR2YXIgYm9va2luZ19sb2NhbGVfYnV0dG9uID0galF1ZXJ5KCB0aGlzICkucGFyZW50cyggJy51aV9lbGVtZW50X2xvY2FsZScgKS5maW5kKCAnLnNldF9ib29raW5nX2xvY2FsZV9idXR0b24nIClcclxuXHJcblx0XHRcdFx0Ly9ib29raW5nX2xvY2FsZV9idXR0b24uY3NzKCAnY29sb3InLCAnI2RiNDgwMCcgKTtcdFx0Ly8gU2V0IGJ1dHRvbiAgcmVkXHJcblx0XHRcdFx0Ym9va2luZ19sb2NhbGVfYnV0dG9uLmFkZENsYXNzKCAnd3BiY191aV9yZWQnICk7XHRcdC8vIFNldCBidXR0b24gIHJlZFxyXG5cdFx0XHRcdCBpZiAoICdmdW5jdGlvbicgPT09IHR5cGVvZiggd3BiY190aXBweSApICl7XHJcblx0XHRcdFx0XHRib29raW5nX2xvY2FsZV9idXR0b24uZ2V0KDApLl90aXBweS5zZXRDb250ZW50KCBzZWxlY3Rpb24gKTtcclxuXHRcdFx0XHQgfVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fSApO1xyXG59XHJcblxyXG4vKipcclxuICogICBSZW1hcmsgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cclxuXHJcbi8qKlxyXG4gKiBEZWZpbmUgY29udGVudCBvZiByZW1hcmsgXCJib29raW5nIG5vdGVcIiBidXR0b24gYW5kIHRleHRhcmVhLiAgLS0gSXQncyBjYWxsZWQgZnJvbSBcdHdwYmNfYWp4X2Jvb2tpbmdfZGVmaW5lX3VpX2hvb2tzKCkgIFx0ZWFjaCAgdGltZSBhZnRlciBMaXN0aW5nIGxvYWRpbmcuXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2FqeF9ib29raW5nX191aV9kZWZpbmVfX3JlbWFyaygpe1xyXG5cclxuXHRqUXVlcnkoICcud3BiY19saXN0aW5nX2NvbnRhaW5lciAudWlfcmVtYXJrX3NlY3Rpb24gdGV4dGFyZWEnICkuZWFjaCggZnVuY3Rpb24gKCBpbmRleCApe1xyXG5cdFx0dmFyIHRleHRfdmFsID0galF1ZXJ5KCB0aGlzICkudmFsKCk7XHJcblx0XHRpZiAoICh1bmRlZmluZWQgIT09IHRleHRfdmFsKSAmJiAoJycgIT0gdGV4dF92YWwpICl7XHJcblxyXG5cdFx0XHR2YXIgcmVtYXJrX2J1dHRvbiA9IGpRdWVyeSggdGhpcyApLnBhcmVudHMoICcudWlfZ3JvdXAnICkuZmluZCggJy5zZXRfYm9va2luZ19ub3RlX2J1dHRvbicgKTtcclxuXHJcblx0XHRcdGlmICggcmVtYXJrX2J1dHRvbi5sZW5ndGggPiAwICl7XHJcblxyXG5cdFx0XHRcdHJlbWFya19idXR0b24uYWRkQ2xhc3MoICd3cGJjX3VpX3JlZCcgKTtcdFx0Ly8gU2V0IGJ1dHRvbiAgcmVkXHJcblx0XHRcdFx0aWYgKCAnZnVuY3Rpb24nID09PSB0eXBlb2YgKHdwYmNfdGlwcHkpICl7XHJcblx0XHRcdFx0XHQvL3JlbWFya19idXR0b24uZ2V0KCAwICkuX3RpcHB5LmFsbG93SFRNTCA9IHRydWU7XHJcblx0XHRcdFx0XHQvL3JlbWFya19idXR0b24uZ2V0KCAwICkuX3RpcHB5LnNldENvbnRlbnQoIHRleHRfdmFsLnJlcGxhY2UoL1tcXG5cXHJdL2csICc8YnI+JykgKTtcclxuXHJcblx0XHRcdFx0XHRyZW1hcmtfYnV0dG9uLmdldCggMCApLl90aXBweS5zZXRQcm9wcygge1xyXG5cdFx0XHRcdFx0XHRhbGxvd0hUTUw6IHRydWUsXHJcblx0XHRcdFx0XHRcdGNvbnRlbnQgIDogdGV4dF92YWwucmVwbGFjZSggL1tcXG5cXHJdL2csICc8YnI+JyApXHJcblx0XHRcdFx0XHR9ICk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fSApO1xyXG59XHJcblxyXG4vKipcclxuICogQWN0aW9ucyAsd2hlbiB3ZSBjbGljayBvbiBcIlJlbWFya1wiIGJ1dHRvbi5cclxuICpcclxuICogQHBhcmFtIGpxX2J1dHRvbiAgLVx0dGhpcyBqUXVlcnkgYnV0dG9uICBvYmplY3RcclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYWp4X2Jvb2tpbmdfX3VpX2NsaWNrX19yZW1hcmsoIGpxX2J1dHRvbiApe1xyXG5cclxuXHRqcV9idXR0b24ucGFyZW50cygnLnVpX2dyb3VwJykuZmluZCgnLnVpX3JlbWFya19zZWN0aW9uJykudG9nZ2xlKCk7XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogICBDaGFuZ2UgYm9va2luZyByZXNvdXJjZSAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cclxuXHJcbmZ1bmN0aW9uIHdwYmNfYWp4X2Jvb2tpbmdfX3VpX2NsaWNrX3Nob3dfX2NoYW5nZV9yZXNvdXJjZSggYm9va2luZ19pZCwgcmVzb3VyY2VfaWQgKXtcclxuXHJcblx0Ly8gRGVmaW5lIElEIG9mIGJvb2tpbmcgdG8gaGlkZGVuIGlucHV0XHJcblx0alF1ZXJ5KCAnI2NoYW5nZV9ib29raW5nX3Jlc291cmNlX19ib29raW5nX2lkJyApLnZhbCggYm9va2luZ19pZCApO1xyXG5cclxuXHQvLyBTZWxlY3QgYm9va2luZyByZXNvdXJjZSAgdGhhdCBiZWxvbmcgdG8gIGJvb2tpbmdcclxuXHRqUXVlcnkoICcjY2hhbmdlX2Jvb2tpbmdfcmVzb3VyY2VfX3Jlc291cmNlX3NlbGVjdCcgKS52YWwoIHJlc291cmNlX2lkICkudHJpZ2dlciggJ2NoYW5nZScgKTtcclxuXHR2YXIgY2JyO1xyXG5cclxuXHQvLyBHZXQgUmVzb3VyY2Ugc2VjdGlvblxyXG5cdGNiciA9IGpRdWVyeSggXCIjY2hhbmdlX2Jvb2tpbmdfcmVzb3VyY2VfX3NlY3Rpb25cIiApLmRldGFjaCgpO1xyXG5cclxuXHQvLyBBcHBlbmQgaXQgdG8gYm9va2luZyBST1dcclxuXHRjYnIuYXBwZW5kVG8oIGpRdWVyeSggXCIjdWlfX2NoYW5nZV9ib29raW5nX3Jlc291cmNlX19zZWN0aW9uX2luX2Jvb2tpbmdfXCIgKyBib29raW5nX2lkICkgKTtcclxuXHRjYnIgPSBudWxsO1xyXG5cclxuXHQvLyBIaWRlIHNlY3Rpb25zIG9mIFwiQ2hhbmdlIGJvb2tpbmcgcmVzb3VyY2VcIiBpbiBhbGwgb3RoZXIgYm9va2luZ3MgUk9Xc1xyXG5cdC8valF1ZXJ5KCBcIi51aV9fY2hhbmdlX2Jvb2tpbmdfcmVzb3VyY2VfX3NlY3Rpb25faW5fYm9va2luZ1wiICkuaGlkZSgpO1xyXG5cdGlmICggISBqUXVlcnkoIFwiI3VpX19jaGFuZ2VfYm9va2luZ19yZXNvdXJjZV9fc2VjdGlvbl9pbl9ib29raW5nX1wiICsgYm9va2luZ19pZCApLmlzKCc6dmlzaWJsZScpICl7XHJcblx0XHRqUXVlcnkoIFwiLnVpX191bmRlcl9hY3Rpb25zX3Jvd19fc2VjdGlvbl9pbl9ib29raW5nXCIgKS5oaWRlKCk7XHJcblx0fVxyXG5cclxuXHQvLyBTaG93IG9ubHkgXCJjaGFuZ2UgYm9va2luZyByZXNvdXJjZVwiIHNlY3Rpb24gIGZvciBjdXJyZW50IGJvb2tpbmdcclxuXHRqUXVlcnkoIFwiI3VpX19jaGFuZ2VfYm9va2luZ19yZXNvdXJjZV9fc2VjdGlvbl9pbl9ib29raW5nX1wiICsgYm9va2luZ19pZCApLnRvZ2dsZSgpO1xyXG59XHJcblxyXG5mdW5jdGlvbiB3cGJjX2FqeF9ib29raW5nX191aV9jbGlja19zYXZlX19jaGFuZ2VfcmVzb3VyY2UoIHRoaXNfZWwsIGJvb2tpbmdfYWN0aW9uLCBlbF9pZCApe1xyXG5cclxuXHR3cGJjX2FqeF9ib29raW5nX2FqYXhfYWN0aW9uX3JlcXVlc3QoIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdib29raW5nX2FjdGlvbicgICAgICAgOiBib29raW5nX2FjdGlvbixcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdib29raW5nX2lkJyAgICAgICAgICAgOiBqUXVlcnkoICcjY2hhbmdlX2Jvb2tpbmdfcmVzb3VyY2VfX2Jvb2tpbmdfaWQnICkudmFsKCksXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnc2VsZWN0ZWRfcmVzb3VyY2VfaWQnIDogalF1ZXJ5KCAnI2NoYW5nZV9ib29raW5nX3Jlc291cmNlX19yZXNvdXJjZV9zZWxlY3QnICkudmFsKCksXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQndWlfY2xpY2tlZF9lbGVtZW50X2lkJzogZWxfaWRcclxuXHR9ICk7XHJcblxyXG5cdHdwYmNfYnV0dG9uX2VuYWJsZV9sb2FkaW5nX2ljb24oIHRoaXNfZWwgKTtcclxuXHJcblx0Ly8gd3BiY19hanhfYm9va2luZ19fdWlfY2xpY2tfY2xvc2VfX2NoYW5nZV9yZXNvdXJjZSgpO1xyXG59XHJcblxyXG5mdW5jdGlvbiB3cGJjX2FqeF9ib29raW5nX191aV9jbGlja19jbG9zZV9fY2hhbmdlX3Jlc291cmNlKCl7XHJcblxyXG5cdHZhciBjYnJjZTtcclxuXHJcblx0Ly8gR2V0IFJlc291cmNlIHNlY3Rpb25cclxuXHRjYnJjZSA9IGpRdWVyeShcIiNjaGFuZ2VfYm9va2luZ19yZXNvdXJjZV9fc2VjdGlvblwiKS5kZXRhY2goKTtcclxuXHJcblx0Ly8gQXBwZW5kIGl0IHRvIGhpZGRlbiBIVE1MIHRlbXBsYXRlIHNlY3Rpb24gIGF0ICB0aGUgYm90dG9tICBvZiB0aGUgcGFnZVxyXG5cdGNicmNlLmFwcGVuZFRvKGpRdWVyeShcIiN3cGJjX2hpZGRlbl90ZW1wbGF0ZV9fY2hhbmdlX2Jvb2tpbmdfcmVzb3VyY2VcIikpO1xyXG5cdGNicmNlID0gbnVsbDtcclxuXHJcblx0Ly8gSGlkZSBhbGwgY2hhbmdlIGJvb2tpbmcgcmVzb3VyY2VzIHNlY3Rpb25zXHJcblx0alF1ZXJ5KFwiLnVpX19jaGFuZ2VfYm9va2luZ19yZXNvdXJjZV9fc2VjdGlvbl9pbl9ib29raW5nXCIpLmhpZGUoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqICAgRHVwbGljYXRlIGJvb2tpbmcgaW4gb3RoZXIgcmVzb3VyY2UgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXHJcblxyXG5mdW5jdGlvbiB3cGJjX2FqeF9ib29raW5nX191aV9jbGlja19zaG93X19kdXBsaWNhdGVfYm9va2luZyggYm9va2luZ19pZCwgcmVzb3VyY2VfaWQgKXtcclxuXHJcblx0Ly8gRGVmaW5lIElEIG9mIGJvb2tpbmcgdG8gaGlkZGVuIGlucHV0XHJcblx0alF1ZXJ5KCAnI2R1cGxpY2F0ZV9ib29raW5nX3RvX290aGVyX3Jlc291cmNlX19ib29raW5nX2lkJyApLnZhbCggYm9va2luZ19pZCApO1xyXG5cclxuXHQvLyBTZWxlY3QgYm9va2luZyByZXNvdXJjZSAgdGhhdCBiZWxvbmcgdG8gIGJvb2tpbmdcclxuXHRqUXVlcnkoICcjZHVwbGljYXRlX2Jvb2tpbmdfdG9fb3RoZXJfcmVzb3VyY2VfX3Jlc291cmNlX3NlbGVjdCcgKS52YWwoIHJlc291cmNlX2lkICkudHJpZ2dlciggJ2NoYW5nZScgKTtcclxuXHR2YXIgY2JyO1xyXG5cclxuXHQvLyBHZXQgUmVzb3VyY2Ugc2VjdGlvblxyXG5cdGNiciA9IGpRdWVyeSggXCIjZHVwbGljYXRlX2Jvb2tpbmdfdG9fb3RoZXJfcmVzb3VyY2VfX3NlY3Rpb25cIiApLmRldGFjaCgpO1xyXG5cclxuXHQvLyBBcHBlbmQgaXQgdG8gYm9va2luZyBST1dcclxuXHRjYnIuYXBwZW5kVG8oIGpRdWVyeSggXCIjdWlfX2R1cGxpY2F0ZV9ib29raW5nX3RvX290aGVyX3Jlc291cmNlX19zZWN0aW9uX2luX2Jvb2tpbmdfXCIgKyBib29raW5nX2lkICkgKTtcclxuXHRjYnIgPSBudWxsO1xyXG5cclxuXHQvLyBIaWRlIHNlY3Rpb25zIG9mIFwiRHVwbGljYXRlIGJvb2tpbmdcIiBpbiBhbGwgb3RoZXIgYm9va2luZ3MgUk9Xc1xyXG5cdGlmICggISBqUXVlcnkoIFwiI3VpX19kdXBsaWNhdGVfYm9va2luZ190b19vdGhlcl9yZXNvdXJjZV9fc2VjdGlvbl9pbl9ib29raW5nX1wiICsgYm9va2luZ19pZCApLmlzKCc6dmlzaWJsZScpICl7XHJcblx0XHRqUXVlcnkoIFwiLnVpX191bmRlcl9hY3Rpb25zX3Jvd19fc2VjdGlvbl9pbl9ib29raW5nXCIgKS5oaWRlKCk7XHJcblx0fVxyXG5cclxuXHQvLyBTaG93IG9ubHkgXCJEdXBsaWNhdGUgYm9va2luZ1wiIHNlY3Rpb24gIGZvciBjdXJyZW50IGJvb2tpbmcgUk9XXHJcblx0alF1ZXJ5KCBcIiN1aV9fZHVwbGljYXRlX2Jvb2tpbmdfdG9fb3RoZXJfcmVzb3VyY2VfX3NlY3Rpb25faW5fYm9va2luZ19cIiArIGJvb2tpbmdfaWQgKS50b2dnbGUoKTtcclxufVxyXG5cclxuZnVuY3Rpb24gd3BiY19hanhfYm9va2luZ19fdWlfY2xpY2tfc2F2ZV9fZHVwbGljYXRlX2Jvb2tpbmcoIHRoaXNfZWwsIGJvb2tpbmdfYWN0aW9uLCBlbF9pZCApe1xyXG5cclxuXHR3cGJjX2FqeF9ib29raW5nX2FqYXhfYWN0aW9uX3JlcXVlc3QoIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdib29raW5nX2FjdGlvbicgICAgICAgOiBib29raW5nX2FjdGlvbixcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdib29raW5nX2lkJyAgICAgICAgICAgOiBqUXVlcnkoICcjZHVwbGljYXRlX2Jvb2tpbmdfdG9fb3RoZXJfcmVzb3VyY2VfX2Jvb2tpbmdfaWQnICkudmFsKCksXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnc2VsZWN0ZWRfcmVzb3VyY2VfaWQnIDogalF1ZXJ5KCAnI2R1cGxpY2F0ZV9ib29raW5nX3RvX290aGVyX3Jlc291cmNlX19yZXNvdXJjZV9zZWxlY3QnICkudmFsKCksXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQndWlfY2xpY2tlZF9lbGVtZW50X2lkJzogZWxfaWRcclxuXHR9ICk7XHJcblxyXG5cdHdwYmNfYnV0dG9uX2VuYWJsZV9sb2FkaW5nX2ljb24oIHRoaXNfZWwgKTtcclxuXHJcblx0Ly8gd3BiY19hanhfYm9va2luZ19fdWlfY2xpY2tfY2xvc2VfX2NoYW5nZV9yZXNvdXJjZSgpO1xyXG59XHJcblxyXG5mdW5jdGlvbiB3cGJjX2FqeF9ib29raW5nX191aV9jbGlja19jbG9zZV9fZHVwbGljYXRlX2Jvb2tpbmcoKXtcclxuXHJcblx0dmFyIGNicmNlO1xyXG5cclxuXHQvLyBHZXQgUmVzb3VyY2Ugc2VjdGlvblxyXG5cdGNicmNlID0galF1ZXJ5KFwiI2R1cGxpY2F0ZV9ib29raW5nX3RvX290aGVyX3Jlc291cmNlX19zZWN0aW9uXCIpLmRldGFjaCgpO1xyXG5cclxuXHQvLyBBcHBlbmQgaXQgdG8gaGlkZGVuIEhUTUwgdGVtcGxhdGUgc2VjdGlvbiAgYXQgIHRoZSBib3R0b20gIG9mIHRoZSBwYWdlXHJcblx0Y2JyY2UuYXBwZW5kVG8oalF1ZXJ5KFwiI3dwYmNfaGlkZGVuX3RlbXBsYXRlX19kdXBsaWNhdGVfYm9va2luZ190b19vdGhlcl9yZXNvdXJjZVwiKSk7XHJcblx0Y2JyY2UgPSBudWxsO1xyXG5cclxuXHQvLyBIaWRlIGFsbCBjaGFuZ2UgYm9va2luZyByZXNvdXJjZXMgc2VjdGlvbnNcclxuXHRqUXVlcnkoXCIudWlfX2R1cGxpY2F0ZV9ib29raW5nX3RvX290aGVyX3Jlc291cmNlX19zZWN0aW9uX2luX2Jvb2tpbmdcIikuaGlkZSgpO1xyXG59XHJcblxyXG4vKipcclxuICogICBDaGFuZ2UgcGF5bWVudCBzdGF0dXMgICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cclxuXHJcbmZ1bmN0aW9uIHdwYmNfYWp4X2Jvb2tpbmdfX3VpX2NsaWNrX3Nob3dfX3NldF9wYXltZW50X3N0YXR1cyggYm9va2luZ19pZCApe1xyXG5cclxuXHR2YXIgalNlbGVjdCA9IGpRdWVyeSggJyN1aV9fc2V0X3BheW1lbnRfc3RhdHVzX19zZWN0aW9uX2luX2Jvb2tpbmdfJyArIGJvb2tpbmdfaWQgKS5maW5kKCAnc2VsZWN0JyApXHJcblxyXG5cdHZhciBzZWxlY3RlZF9wYXlfc3RhdHVzID0galNlbGVjdC5hdHRyKCBcImFqeC1zZWxlY3RlZC12YWx1ZVwiICk7XHJcblxyXG5cdC8vIElzIGl0IGZsb2F0IC0gdGhlbiAgaXQncyB1bmtub3duXHJcblx0aWYgKCAhaXNOYU4oIHBhcnNlRmxvYXQoIHNlbGVjdGVkX3BheV9zdGF0dXMgKSApICl7XHJcblx0XHRqU2VsZWN0LmZpbmQoICdvcHRpb25bdmFsdWU9XCIxXCJdJyApLnByb3AoICdzZWxlY3RlZCcsIHRydWUgKTtcdFx0XHRcdFx0XHRcdFx0Ly8gVW5rbm93biAgdmFsdWUgaXMgJzEnIGluIHNlbGVjdCBib3hcclxuXHR9IGVsc2Uge1xyXG5cdFx0alNlbGVjdC5maW5kKCAnb3B0aW9uW3ZhbHVlPVwiJyArIHNlbGVjdGVkX3BheV9zdGF0dXMgKyAnXCJdJyApLnByb3AoICdzZWxlY3RlZCcsIHRydWUgKTtcdFx0Ly8gT3RoZXJ3aXNlIGtub3duIHBheW1lbnQgc3RhdHVzXHJcblx0fVxyXG5cclxuXHQvLyBIaWRlIHNlY3Rpb25zIG9mIFwiQ2hhbmdlIGJvb2tpbmcgcmVzb3VyY2VcIiBpbiBhbGwgb3RoZXIgYm9va2luZ3MgUk9Xc1xyXG5cdGlmICggISBqUXVlcnkoIFwiI3VpX19zZXRfcGF5bWVudF9zdGF0dXNfX3NlY3Rpb25faW5fYm9va2luZ19cIiArIGJvb2tpbmdfaWQgKS5pcygnOnZpc2libGUnKSApe1xyXG5cdFx0alF1ZXJ5KCBcIi51aV9fdW5kZXJfYWN0aW9uc19yb3dfX3NlY3Rpb25faW5fYm9va2luZ1wiICkuaGlkZSgpO1xyXG5cdH1cclxuXHJcblx0Ly8gU2hvdyBvbmx5IFwiY2hhbmdlIGJvb2tpbmcgcmVzb3VyY2VcIiBzZWN0aW9uICBmb3IgY3VycmVudCBib29raW5nXHJcblx0alF1ZXJ5KCBcIiN1aV9fc2V0X3BheW1lbnRfc3RhdHVzX19zZWN0aW9uX2luX2Jvb2tpbmdfXCIgKyBib29raW5nX2lkICkudG9nZ2xlKCk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHdwYmNfYWp4X2Jvb2tpbmdfX3VpX2NsaWNrX3NhdmVfX3NldF9wYXltZW50X3N0YXR1cyggYm9va2luZ19pZCwgdGhpc19lbCwgYm9va2luZ19hY3Rpb24sIGVsX2lkICl7XHJcblxyXG5cdHdwYmNfYWp4X2Jvb2tpbmdfYWpheF9hY3Rpb25fcmVxdWVzdCgge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0J2Jvb2tpbmdfYWN0aW9uJyAgICAgICA6IGJvb2tpbmdfYWN0aW9uLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0J2Jvb2tpbmdfaWQnICAgICAgICAgICA6IGJvb2tpbmdfaWQsXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnc2VsZWN0ZWRfcGF5bWVudF9zdGF0dXMnIDogalF1ZXJ5KCAnI3VpX2J0bl9zZXRfcGF5bWVudF9zdGF0dXMnICsgYm9va2luZ19pZCApLnZhbCgpLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3VpX2NsaWNrZWRfZWxlbWVudF9pZCc6IGVsX2lkICsgJ19zYXZlJ1xyXG5cdH0gKTtcclxuXHJcblx0d3BiY19idXR0b25fZW5hYmxlX2xvYWRpbmdfaWNvbiggdGhpc19lbCApO1xyXG5cclxuXHRqUXVlcnkoICcjJyArIGVsX2lkICsgJ19jYW5jZWwnKS5oaWRlKCk7XHJcblx0Ly93cGJjX2J1dHRvbl9lbmFibGVfbG9hZGluZ19pY29uKCBqUXVlcnkoICcjJyArIGVsX2lkICsgJ19jYW5jZWwnKS5nZXQoMCkgKTtcclxuXHJcbn1cclxuXHJcbmZ1bmN0aW9uIHdwYmNfYWp4X2Jvb2tpbmdfX3VpX2NsaWNrX2Nsb3NlX19zZXRfcGF5bWVudF9zdGF0dXMoKXtcclxuXHQvLyBIaWRlIGFsbCBjaGFuZ2UgIHBheW1lbnQgc3RhdHVzIGZvciBib29raW5nXHJcblx0alF1ZXJ5KFwiLnVpX19zZXRfcGF5bWVudF9zdGF0dXNfX3NlY3Rpb25faW5fYm9va2luZ1wiKS5oaWRlKCk7XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogICBDaGFuZ2UgYm9va2luZyBjb3N0ICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cclxuXHJcbmZ1bmN0aW9uIHdwYmNfYWp4X2Jvb2tpbmdfX3VpX2NsaWNrX3NhdmVfX3NldF9ib29raW5nX2Nvc3QoIGJvb2tpbmdfaWQsIHRoaXNfZWwsIGJvb2tpbmdfYWN0aW9uLCBlbF9pZCApe1xyXG5cclxuXHR3cGJjX2FqeF9ib29raW5nX2FqYXhfYWN0aW9uX3JlcXVlc3QoIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdib29raW5nX2FjdGlvbicgICAgICAgOiBib29raW5nX2FjdGlvbixcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdib29raW5nX2lkJyAgICAgICAgICAgOiBib29raW5nX2lkLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0J2Jvb2tpbmdfY29zdCcgXHRcdCAgIDogalF1ZXJ5KCAnI3VpX2J0bl9zZXRfYm9va2luZ19jb3N0JyArIGJvb2tpbmdfaWQgKyAnX2Nvc3QnKS52YWwoKSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd1aV9jbGlja2VkX2VsZW1lbnRfaWQnOiBlbF9pZCArICdfc2F2ZSdcclxuXHR9ICk7XHJcblxyXG5cdHdwYmNfYnV0dG9uX2VuYWJsZV9sb2FkaW5nX2ljb24oIHRoaXNfZWwgKTtcclxuXHJcblx0alF1ZXJ5KCAnIycgKyBlbF9pZCArICdfY2FuY2VsJykuaGlkZSgpO1xyXG5cdC8vd3BiY19idXR0b25fZW5hYmxlX2xvYWRpbmdfaWNvbiggalF1ZXJ5KCAnIycgKyBlbF9pZCArICdfY2FuY2VsJykuZ2V0KDApICk7XHJcblxyXG59XHJcblxyXG5mdW5jdGlvbiB3cGJjX2FqeF9ib29raW5nX191aV9jbGlja19jbG9zZV9fc2V0X2Jvb2tpbmdfY29zdCgpe1xyXG5cdC8vIEhpZGUgYWxsIGNoYW5nZSAgcGF5bWVudCBzdGF0dXMgZm9yIGJvb2tpbmdcclxuXHRqUXVlcnkoXCIudWlfX3NldF9ib29raW5nX2Nvc3RfX3NlY3Rpb25faW5fYm9va2luZ1wiKS5oaWRlKCk7XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogICBTZW5kIFBheW1lbnQgcmVxdWVzdCAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXHJcblxyXG5mdW5jdGlvbiB3cGJjX2FqeF9ib29raW5nX191aV9jbGlja19fc2VuZF9wYXltZW50X3JlcXVlc3QoKXtcclxuXHJcblx0d3BiY19hanhfYm9va2luZ19hamF4X2FjdGlvbl9yZXF1ZXN0KCB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnYm9va2luZ19hY3Rpb24nICAgICAgIDogJ3NlbmRfcGF5bWVudF9yZXF1ZXN0JyxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdib29raW5nX2lkJyAgICAgICAgICAgOiBqUXVlcnkoICcjd3BiY19tb2RhbF9fcGF5bWVudF9yZXF1ZXN0X19ib29raW5nX2lkJykudmFsKCksXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQncmVhc29uX29mX2FjdGlvbicgXHQgICA6IGpRdWVyeSggJyN3cGJjX21vZGFsX19wYXltZW50X3JlcXVlc3RfX3JlYXNvbl9vZl9hY3Rpb24nKS52YWwoKSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCd1aV9jbGlja2VkX2VsZW1lbnRfaWQnOiAnd3BiY19tb2RhbF9fcGF5bWVudF9yZXF1ZXN0X19idXR0b25fc2VuZCdcclxuXHR9ICk7XHJcblx0d3BiY19idXR0b25fZW5hYmxlX2xvYWRpbmdfaWNvbiggalF1ZXJ5KCAnI3dwYmNfbW9kYWxfX3BheW1lbnRfcmVxdWVzdF9fYnV0dG9uX3NlbmQnICkuZ2V0KCAwICkgKTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiAgIEltcG9ydCBHb29nbGUgQ2FsZW5kYXIgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xyXG5cclxuZnVuY3Rpb24gd3BiY19hanhfYm9va2luZ19fdWlfY2xpY2tfX2ltcG9ydF9nb29nbGVfY2FsZW5kYXIoKXtcclxuXHJcblx0d3BiY19hanhfYm9va2luZ19hamF4X2FjdGlvbl9yZXF1ZXN0KCB7XHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnYm9va2luZ19hY3Rpb24nICAgICAgIDogJ2ltcG9ydF9nb29nbGVfY2FsZW5kYXInLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3VpX2NsaWNrZWRfZWxlbWVudF9pZCc6ICd3cGJjX21vZGFsX19pbXBvcnRfZ29vZ2xlX2NhbGVuZGFyX19idXR0b25fc2VuZCdcclxuXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQsICdib29raW5nX2djYWxfZXZlbnRzX2Zyb20nIDogXHRcdFx0XHRqUXVlcnkoICcjd3BiY19tb2RhbF9faW1wb3J0X2dvb2dsZV9jYWxlbmRhcl9fc2VjdGlvbiAjYm9va2luZ19nY2FsX2V2ZW50c19mcm9tIG9wdGlvbjpzZWxlY3RlZCcpLnZhbCgpXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQsICdib29raW5nX2djYWxfZXZlbnRzX2Zyb21fb2Zmc2V0JyA6IFx0XHRqUXVlcnkoICcjd3BiY19tb2RhbF9faW1wb3J0X2dvb2dsZV9jYWxlbmRhcl9fc2VjdGlvbiAjYm9va2luZ19nY2FsX2V2ZW50c19mcm9tX29mZnNldCcgKS52YWwoKVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0LCAnYm9va2luZ19nY2FsX2V2ZW50c19mcm9tX29mZnNldF90eXBlJyA6IFx0alF1ZXJ5KCAnI3dwYmNfbW9kYWxfX2ltcG9ydF9nb29nbGVfY2FsZW5kYXJfX3NlY3Rpb24gI2Jvb2tpbmdfZ2NhbF9ldmVudHNfZnJvbV9vZmZzZXRfdHlwZSBvcHRpb246c2VsZWN0ZWQnKS52YWwoKVxyXG5cclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCwgJ2Jvb2tpbmdfZ2NhbF9ldmVudHNfdW50aWwnIDogXHRcdFx0alF1ZXJ5KCAnI3dwYmNfbW9kYWxfX2ltcG9ydF9nb29nbGVfY2FsZW5kYXJfX3NlY3Rpb24gI2Jvb2tpbmdfZ2NhbF9ldmVudHNfdW50aWwgb3B0aW9uOnNlbGVjdGVkJykudmFsKClcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCwgJ2Jvb2tpbmdfZ2NhbF9ldmVudHNfdW50aWxfb2Zmc2V0JyA6IFx0XHRqUXVlcnkoICcjd3BiY19tb2RhbF9faW1wb3J0X2dvb2dsZV9jYWxlbmRhcl9fc2VjdGlvbiAjYm9va2luZ19nY2FsX2V2ZW50c191bnRpbF9vZmZzZXQnICkudmFsKClcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCwgJ2Jvb2tpbmdfZ2NhbF9ldmVudHNfdW50aWxfb2Zmc2V0X3R5cGUnIDogalF1ZXJ5KCAnI3dwYmNfbW9kYWxfX2ltcG9ydF9nb29nbGVfY2FsZW5kYXJfX3NlY3Rpb24gI2Jvb2tpbmdfZ2NhbF9ldmVudHNfdW50aWxfb2Zmc2V0X3R5cGUgb3B0aW9uOnNlbGVjdGVkJykudmFsKClcclxuXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQsICdib29raW5nX2djYWxfZXZlbnRzX21heCcgOiBcdGpRdWVyeSggJyN3cGJjX21vZGFsX19pbXBvcnRfZ29vZ2xlX2NhbGVuZGFyX19zZWN0aW9uICNib29raW5nX2djYWxfZXZlbnRzX21heCcgKS52YWwoKVxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0LCAnYm9va2luZ19nY2FsX3Jlc291cmNlJyA6IFx0alF1ZXJ5KCAnI3dwYmNfbW9kYWxfX2ltcG9ydF9nb29nbGVfY2FsZW5kYXJfX3NlY3Rpb24gI3dwYmNfYm9va2luZ19yZXNvdXJjZSBvcHRpb246c2VsZWN0ZWQnKS52YWwoKVxyXG5cdH0gKTtcclxuXHR3cGJjX2J1dHRvbl9lbmFibGVfbG9hZGluZ19pY29uKCBqUXVlcnkoICcjd3BiY19tb2RhbF9faW1wb3J0X2dvb2dsZV9jYWxlbmRhcl9fc2VjdGlvbiAjd3BiY19tb2RhbF9faW1wb3J0X2dvb2dsZV9jYWxlbmRhcl9fYnV0dG9uX3NlbmQnICkuZ2V0KCAwICkgKTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiAgIEV4cG9ydCBib29raW5ncyB0byBDU1YgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xyXG5mdW5jdGlvbiB3cGJjX2FqeF9ib29raW5nX191aV9jbGlja19fZXhwb3J0X2NzdiggcGFyYW1zICl7XHJcblxyXG5cdHZhciBzZWxlY3RlZF9ib29raW5nX2lkX2FyciA9IHdwYmNfZ2V0X3NlbGVjdGVkX3Jvd19pZCgpO1xyXG5cclxuXHR3cGJjX2FqeF9ib29raW5nX2FqYXhfYWN0aW9uX3JlcXVlc3QoIHtcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdib29raW5nX2FjdGlvbicgICAgICAgIDogcGFyYW1zWyAnYm9va2luZ19hY3Rpb24nIF0sXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQndWlfY2xpY2tlZF9lbGVtZW50X2lkJyA6IHBhcmFtc1sgJ3VpX2NsaWNrZWRfZWxlbWVudF9pZCcgXSxcclxuXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnZXhwb3J0X3R5cGUnICAgICAgICAgICA6IHBhcmFtc1sgJ2V4cG9ydF90eXBlJyBdLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0J2Nzdl9leHBvcnRfc2VwYXJhdG9yJyAgOiBwYXJhbXNbICdjc3ZfZXhwb3J0X3NlcGFyYXRvcicgXSxcclxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCdjc3ZfZXhwb3J0X3NraXBfZmllbGRzJzogcGFyYW1zWyAnY3N2X2V4cG9ydF9za2lwX2ZpZWxkcycgXSxcclxuXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQnYm9va2luZ19pZCdcdDogc2VsZWN0ZWRfYm9va2luZ19pZF9hcnIuam9pbignLCcpLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0J3NlYXJjaF9wYXJhbXMnIDogd3BiY19hanhfYm9va2luZ19saXN0aW5nLnNlYXJjaF9nZXRfYWxsX3BhcmFtcygpXHJcblx0XHRcdFx0XHRcdFx0XHRcdFx0fSApO1xyXG5cclxuXHR2YXIgdGhpc19lbCA9IGpRdWVyeSggJyMnICsgcGFyYW1zWyAndWlfY2xpY2tlZF9lbGVtZW50X2lkJyBdICkuZ2V0KCAwIClcclxuXHJcblx0d3BiY19idXR0b25fZW5hYmxlX2xvYWRpbmdfaWNvbiggdGhpc19lbCApO1xyXG59XHJcblxyXG4vKipcclxuICogT3BlbiBVUkwgaW4gbmV3IHRhYiAtIG1haW5seSAgaXQncyB1c2VkIGZvciBvcGVuIENTViBsaW5rICBmb3IgZG93bmxvYWRlZCBleHBvcnRlZCBib29raW5ncyBhcyBDU1ZcclxuICpcclxuICogQHBhcmFtIGV4cG9ydF9jc3ZfdXJsXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2FqeF9ib29raW5nX19leHBvcnRfY3N2X3VybF9fZG93bmxvYWQoIGV4cG9ydF9jc3ZfdXJsICl7XHJcblxyXG5cdC8vdmFyIHNlbGVjdGVkX2Jvb2tpbmdfaWRfYXJyID0gd3BiY19nZXRfc2VsZWN0ZWRfcm93X2lkKCk7XHJcblxyXG5cdGRvY3VtZW50LmxvY2F0aW9uLmhyZWYgPSBleHBvcnRfY3N2X3VybDsvLyArICcmc2VsZWN0ZWRfaWQ9JyArIHNlbGVjdGVkX2Jvb2tpbmdfaWRfYXJyLmpvaW4oJywnKTtcclxuXHJcblx0Ly8gSXQncyBvcGVuIGFkZGl0aW9uYWwgZGlhbG9nIGZvciBhc2tpbmcgb3BlbmluZyB1bHIgaW4gbmV3IHRhYlxyXG5cdC8vIHdpbmRvdy5vcGVuKCBleHBvcnRfY3N2X3VybCwgJ19ibGFuaycpLmZvY3VzKCk7XHJcbn0iXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7O0FBRVo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUpBLFNBQUFBLFFBQUFDLEdBQUEsc0NBQUFELE9BQUEsd0JBQUFFLE1BQUEsdUJBQUFBLE1BQUEsQ0FBQUMsUUFBQSxhQUFBRixHQUFBLGtCQUFBQSxHQUFBLGdCQUFBQSxHQUFBLFdBQUFBLEdBQUEseUJBQUFDLE1BQUEsSUFBQUQsR0FBQSxDQUFBRyxXQUFBLEtBQUFGLE1BQUEsSUFBQUQsR0FBQSxLQUFBQyxNQUFBLENBQUFHLFNBQUEscUJBQUFKLEdBQUEsS0FBQUQsT0FBQSxDQUFBQyxHQUFBO0FBS0EsU0FBU0ssb0NBQW9DQSxDQUFBLEVBQXFCO0VBQUEsSUFBbkJDLFlBQVksR0FBQUMsU0FBQSxDQUFBQyxNQUFBLFFBQUFELFNBQUEsUUFBQUUsU0FBQSxHQUFBRixTQUFBLE1BQUcs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 _src/bookings__listing.js 0000666 00000045477 15166373417 0011575 0 ustar 00 "use strict"; jQuery('body').on({ 'touchmove': function(e) { jQuery( '.timespartly' ).each( function ( index ){ var td_el = jQuery( this ).get( 0 ); if ( (undefined != td_el._tippy) ){ var instance = td_el._tippy; instance.hide(); } } ); } }); /** * Request Object * Here we can define Search parameters and Update it later, when some parameter was changed * */ var wpbc_ajx_booking_listing = (function ( obj, $) { // Secure parameters for Ajax ------------------------------------------------------------------------------------ var p_secure = obj.security_obj = obj.security_obj || { user_id: 0, nonce : '', locale : '' }; obj.set_secure_param = function ( param_key, param_val ) { p_secure[ param_key ] = param_val; }; obj.get_secure_param = function ( param_key ) { return p_secure[ param_key ]; }; // Listing Search parameters ------------------------------------------------------------------------------------ var p_listing = obj.search_request_obj = obj.search_request_obj || { sort : "booking_id", sort_type : "DESC", page_num : 1, page_items_count: 10, create_date : "", keyword : "", source : "" }; obj.search_set_all_params = function ( request_param_obj ) { p_listing = request_param_obj; }; obj.search_get_all_params = function () { return p_listing; }; obj.search_get_param = function ( param_key ) { return p_listing[ param_key ]; }; obj.search_set_param = function ( param_key, param_val ) { // if ( Array.isArray( param_val ) ){ // param_val = JSON.stringify( param_val ); // } p_listing[ param_key ] = param_val; }; obj.search_set_params_arr = function( params_arr ){ _.each( params_arr, function ( p_val, p_key, p_data ){ // Define different Search parameters for request this.search_set_param( p_key, p_val ); } ); } // Other parameters ------------------------------------------------------------------------------------ var p_other = obj.other_obj = obj.other_obj || { }; obj.set_other_param = function ( param_key, param_val ) { p_other[ param_key ] = param_val; }; obj.get_other_param = function ( param_key ) { return p_other[ param_key ]; }; return obj; }( wpbc_ajx_booking_listing || {}, jQuery )); /** * Ajax ------------------------------------------------------------------------------------------------------ */ /** * Send Ajax search request * for searching specific Keyword and other params */ function wpbc_ajx_booking_ajax_search_request(){ console.groupCollapsed('AJX_BOOKING_LISTING'); console.log( ' == Before Ajax Send - search_get_all_params() == ' , wpbc_ajx_booking_listing.search_get_all_params() ); wpbc_booking_listing_reload_button__spin_start(); /* //FixIn: forVideo if ( ! is_this_action ){ //wpbc_ajx_booking__actual_listing__hide(); jQuery( wpbc_ajx_booking_listing.get_other_param( 'listing_container' ) ).html( '<div style="width:100%;text-align: center;" id="wpbc_loading_section"><span class="wpbc_icn_autorenew wpbc_spin"></span></div>' + jQuery( wpbc_ajx_booking_listing.get_other_param( 'listing_container' ) ).html() ); if ( 'function' === typeof (jQuery( '#wpbc_loading_section' ).wpbc_my_modal) ){ //FixIn: 9.0.1.5 jQuery( '#wpbc_loading_section' ).wpbc_my_modal( 'show' ); } else { alert( 'Warning! Booking Calendar. Its seems that you have deactivated loading of Bootstrap JS files at Booking Settings General page in Advanced section.' ) } } is_this_action = false; */ // Start Ajax jQuery.post( wpbc_url_ajax, { action : 'WPBC_AJX_BOOKING_LISTING', wpbc_ajx_user_id: wpbc_ajx_booking_listing.get_secure_param( 'user_id' ), nonce : wpbc_ajx_booking_listing.get_secure_param( 'nonce' ), wpbc_ajx_locale : wpbc_ajx_booking_listing.get_secure_param( 'locale' ), search_params : wpbc_ajx_booking_listing.search_get_all_params() }, /** * S u c c e s s * * @param response_data - its object returned from Ajax - class-live-searcg.php * @param textStatus - 'success' * @param jqXHR - Object */ function ( response_data, textStatus, jqXHR ) { //FixIn: forVideo //jQuery( '#wpbc_loading_section' ).wpbc_my_modal( 'hide' ); console.log( ' == Response WPBC_AJX_BOOKING_LISTING == ', response_data ); console.groupEnd(); // Probably Error if ( (typeof response_data !== 'object') || (response_data === null) ){ jQuery( '.wpbc_ajx_under_toolbar_row' ).hide(); //FixIn: 9.6.1.5 jQuery( wpbc_ajx_booking_listing.get_other_param( 'listing_container' ) ).html( '<div class="wpbc-settings-notice notice-warning" style="text-align:left">' + response_data + '</div>' ); return; } // Reload page, after filter toolbar was reseted if ( ( undefined != response_data[ 'ajx_cleaned_params' ]) && ( 'reset_done' === response_data[ 'ajx_cleaned_params' ][ 'ui_reset' ]) ){ location.reload(); return; } // Show listing if ( response_data[ 'ajx_count' ] > 0 ){ wpbc_ajx_booking_show_listing( response_data[ 'ajx_items' ], response_data[ 'ajx_search_params' ], response_data[ 'ajx_booking_resources' ] ); wpbc_pagination_echo( wpbc_ajx_booking_listing.get_other_param( 'pagination_container' ), { 'page_active': response_data[ 'ajx_search_params' ][ 'page_num' ], 'pages_count': Math.ceil( response_data[ 'ajx_count' ] / response_data[ 'ajx_search_params' ][ 'page_items_count' ] ), 'page_items_count': response_data[ 'ajx_search_params' ][ 'page_items_count' ], 'sort_type' : response_data[ 'ajx_search_params' ][ 'sort_type' ] } ); wpbc_ajx_booking_define_ui_hooks(); // Redefine Hooks, because we show new DOM elements } else { wpbc_ajx_booking__actual_listing__hide(); jQuery( wpbc_ajx_booking_listing.get_other_param( 'listing_container' ) ).html( '<div class="wpbc-settings-notice0 notice-warning0" style="text-align:center;margin-left:-50px;">' + '<strong>' + 'No results found for current filter options...' + '</strong>' + //'<strong>' + 'No results found...' + '</strong>' + '</div>' ); } // Update new booking count if ( undefined !== response_data[ 'ajx_new_bookings_count' ] ){ var ajx_new_bookings_count = parseInt( response_data[ 'ajx_new_bookings_count' ] ) if (ajx_new_bookings_count>0){ jQuery( '.wpbc_badge_count' ).show(); } jQuery( '.bk-update-count' ).html( ajx_new_bookings_count ); } wpbc_booking_listing_reload_button__spin_pause(); jQuery( '#ajax_respond' ).html( response_data ); // For ability to show response, add such DIV element to page } ).fail( function ( jqXHR, textStatus, errorThrown ) { if ( window.console && window.console.log ){ console.log( 'Ajax_Error', jqXHR, textStatus, errorThrown ); } jQuery( '.wpbc_ajx_under_toolbar_row' ).hide(); //FixIn: 9.6.1.5 var error_message = '<strong>' + 'Error!' + '</strong> ' + errorThrown ; if ( jqXHR.responseText ){ error_message += jqXHR.responseText; } error_message = error_message.replace( /\n/g, "<br />" ); wpbc_ajx_booking_show_message( error_message ); }) // .done( function ( data, textStatus, jqXHR ) { if ( window.console && window.console.log ){ console.log( 'second success', data, textStatus, jqXHR ); } }) // .always( function ( data_jqXHR, textStatus, jqXHR_errorThrown ) { if ( window.console && window.console.log ){ console.log( 'always finished', data_jqXHR, textStatus, jqXHR_errorThrown ); } }) ; // End Ajax } /** * Views ----------------------------------------------------------------------------------------------------- */ /** * Show Listing Table and define gMail checkbox hooks * * @param json_items_arr - JSON object with Items * @param json_search_params - JSON object with Search */ function wpbc_ajx_booking_show_listing( json_items_arr, json_search_params, json_booking_resources ){ wpbc_ajx_define_templates__resource_manipulation( json_items_arr, json_search_params, json_booking_resources ); //console.log( 'json_items_arr' , json_items_arr, json_search_params ); jQuery( '.wpbc_ajx_under_toolbar_row' ).css( "display", "flex" ); //FixIn: 9.6.1.5 var list_header_tpl = wp.template( 'wpbc_ajx_booking_list_header' ); var list_row_tpl = wp.template( 'wpbc_ajx_booking_list_row' ); // Header jQuery( wpbc_ajx_booking_listing.get_other_param( 'listing_container' ) ).html( list_header_tpl() ); // Body jQuery( wpbc_ajx_booking_listing.get_other_param( 'listing_container' ) ).append( '<div class="wpbc_selectable_body"></div>' ); // R o w s console.groupCollapsed( 'LISTING_ROWS' ); // LISTING_ROWS _.each( json_items_arr, function ( p_val, p_key, p_data ){ if ( 'undefined' !== typeof json_search_params[ 'keyword' ] ){ // Parameter for marking keyword with different color in a list p_val[ '__search_request_keyword__' ] = json_search_params[ 'keyword' ]; } else { p_val[ '__search_request_keyword__' ] = ''; } p_val[ 'booking_resources' ] = json_booking_resources; jQuery( wpbc_ajx_booking_listing.get_other_param( 'listing_container' ) + ' .wpbc_selectable_body' ).append( list_row_tpl( p_val ) ); } ); console.groupEnd(); // LISTING_ROWS wpbc_define_gmail_checkbox_selection( jQuery ); // Redefine Hooks for clicking at Checkboxes } /** * Define template for changing booking resources & update it each time, when listing updating, useful for showing actual booking resources. * * @param json_items_arr - JSON object with Items * @param json_search_params - JSON object with Search * @param json_booking_resources - JSON object with Resources */ function wpbc_ajx_define_templates__resource_manipulation( json_items_arr, json_search_params, json_booking_resources ){ // Change booking resource var change_booking_resource_tpl = wp.template( 'wpbc_ajx_change_booking_resource' ); jQuery( '#wpbc_hidden_template__change_booking_resource' ).html( change_booking_resource_tpl( { 'ajx_search_params' : json_search_params, 'ajx_booking_resources': json_booking_resources } ) ); // Duplicate booking resource var duplicate_booking_to_other_resource_tpl = wp.template( 'wpbc_ajx_duplicate_booking_to_other_resource' ); jQuery( '#wpbc_hidden_template__duplicate_booking_to_other_resource' ).html( duplicate_booking_to_other_resource_tpl( { 'ajx_search_params' : json_search_params, 'ajx_booking_resources': json_booking_resources } ) ); } /** * Show just message instead of listing and hide pagination */ function wpbc_ajx_booking_show_message( message ){ wpbc_ajx_booking__actual_listing__hide(); jQuery( wpbc_ajx_booking_listing.get_other_param( 'listing_container' ) ).html( '<div class="wpbc-settings-notice notice-warning" style="text-align:left">' + message + '</div>' ); } /** * H o o k s - its Action/Times when need to re-Render Views ----------------------------------------------- */ /** * Send Ajax Search Request after Updating search request parameters * * @param params_arr */ function wpbc_ajx_booking_send_search_request_with_params ( params_arr ){ // Define different Search parameters for request _.each( params_arr, function ( p_val, p_key, p_data ) { //console.log( 'Request for: ', p_key, p_val ); wpbc_ajx_booking_listing.search_set_param( p_key, p_val ); }); // Send Ajax Request wpbc_ajx_booking_ajax_search_request(); } /** * Search request for "Page Number" * @param page_number int */ function wpbc_ajx_booking_pagination_click( page_number ){ wpbc_ajx_booking_send_search_request_with_params( { 'page_num': page_number } ); } /** * Keyword Searching ----------------------------------------------------------------------------------------- */ /** * Search request for "Keyword", also set current page to 1 * * @param element_id - HTML ID of element, where was entered keyword */ function wpbc_ajx_booking_send_search_request_for_keyword( element_id ) { // We need to Reset page_num to 1 with each new search, because we can be at page #4, but after new search we can have totally only 1 page wpbc_ajx_booking_send_search_request_with_params( { 'keyword' : jQuery( element_id ).val(), 'page_num': 1 } ); } /** * Send search request after few seconds (usually after 1,5 sec) * Closure function. Its useful, for do not send too many Ajax requests, when someone make fast typing. */ var wpbc_ajx_booking_searching_after_few_seconds = function (){ var closed_timer = 0; return function ( element_id, timer_delay ){ // Get default value of "timer_delay", if parameter was not passed into the function. timer_delay = typeof timer_delay !== 'undefined' ? timer_delay : 1500; clearTimeout( closed_timer ); // Clear previous timer // Start new Timer closed_timer = setTimeout( wpbc_ajx_booking_send_search_request_for_keyword.bind( null, element_id ), timer_delay ); } }(); /** * Define Dynamic Hooks (like pagination click, which renew each time with new listing showing) ------------- */ /** * Define HTML ui Hooks: on KeyUp | Change | -> Sort Order & Number Items / Page * We are hcnaged it each time, when showing new listing, because DOM elements chnaged */ function wpbc_ajx_booking_define_ui_hooks(){ if ( 'function' === typeof( wpbc_define_tippy_tooltips ) ) { wpbc_define_tippy_tooltips( '.wpbc_listing_container ' ); } wpbc_ajx_booking__ui_define__locale(); wpbc_ajx_booking__ui_define__remark(); // Items Per Page jQuery( '.wpbc_items_per_page' ).on( 'change', function( event ){ wpbc_ajx_booking_send_search_request_with_params( { 'page_items_count' : jQuery( this ).val(), 'page_num': 1 } ); } ); // Sorting jQuery( '.wpbc_items_sort_type' ).on( 'change', function( event ){ wpbc_ajx_booking_send_search_request_with_params( {'sort_type': jQuery( this ).val()} ); } ); } /** * Show / Hide Listing --------------------------------------------------------------------------------------- */ /** * Show Listing Table - Sending Ajax Request - with parameters that we early defined in "wpbc_ajx_booking_listing" Obj. */ function wpbc_ajx_booking__actual_listing__show(){ wpbc_ajx_booking_ajax_search_request(); // Send Ajax Request - with parameters that we early defined in "wpbc_ajx_booking_listing" Obj. } /** * Hide Listing Table ( and Pagination ) */ function wpbc_ajx_booking__actual_listing__hide(){ jQuery( '.wpbc_ajx_under_toolbar_row' ).hide(); //FixIn: 9.6.1.5 jQuery( wpbc_ajx_booking_listing.get_other_param( 'listing_container' ) ).html( '' ); jQuery( wpbc_ajx_booking_listing.get_other_param( 'pagination_container' ) ).html( '' ); } /** * Support functions for Content Template data --------------------------------------------------------------- */ /** * Highlight strings, * by inserting <span class="fieldvalue name fieldsearchvalue">...</span> html elements into the string. * @param {string} booking_details - Source string * @param {string} booking_keyword - Keyword to highlight * @returns {string} */ function wpbc_get_highlighted_search_keyword( booking_details, booking_keyword ){ booking_keyword = booking_keyword.trim().toLowerCase(); if ( 0 == booking_keyword.length ){ return booking_details; } // Highlight substring withing HTML tags in "Content of booking fields data" -- e.g. starting from > and ending with < let keywordRegex = new RegExp( `fieldvalue[^<>]*>([^<]*${booking_keyword}[^<]*)`, 'gim' ); //let matches = [...booking_details.toLowerCase().matchAll( keywordRegex )]; let matches = booking_details.toLowerCase().matchAll( keywordRegex ); matches = Array.from( matches ); let strings_arr = []; let pos_previous = 0; let search_pos_start; let search_pos_end; for ( const match of matches ){ search_pos_start = match.index + match[ 0 ].toLowerCase().indexOf( '>', 0 ) + 1 ; strings_arr.push( booking_details.substr( pos_previous, (search_pos_start - pos_previous) ) ); search_pos_end = booking_details.toLowerCase().indexOf( '<', search_pos_start ); strings_arr.push( '<span class="fieldvalue name fieldsearchvalue">' + booking_details.substr( search_pos_start, (search_pos_end - search_pos_start) ) + '</span>' ); pos_previous = search_pos_end; } strings_arr.push( booking_details.substr( pos_previous, (booking_details.length - pos_previous) ) ); return strings_arr.join( '' ); } /** * Convert special HTML characters from: & -> & * * @param text * @returns {*} */ function wpbc_decode_HTML_entities( text ){ var textArea = document.createElement( 'textarea' ); textArea.innerHTML = text; return textArea.value; } /** * Convert TO special HTML characters from: & -> & * * @param text * @returns {*} */ function wpbc_encode_HTML_entities(text) { var textArea = document.createElement('textarea'); textArea.innerText = text; return textArea.innerHTML; } /** * Support Functions - Spin Icon in Buttons ------------------------------------------------------------------ */ /** * Spin button in Filter toolbar - Start */ function wpbc_booking_listing_reload_button__spin_start(){ jQuery( '#wpbc_booking_listing_reload_button .menu_icon.wpbc_spin').removeClass( 'wpbc_animation_pause' ); } /** * Spin button in Filter toolbar - Pause */ function wpbc_booking_listing_reload_button__spin_pause(){ jQuery( '#wpbc_booking_listing_reload_button .menu_icon.wpbc_spin' ).addClass( 'wpbc_animation_pause' ); } /** * Spin button in Filter toolbar - is Spinning ? * * @returns {boolean} */ function wpbc_booking_listing_reload_button__is_spin(){ if ( jQuery( '#wpbc_booking_listing_reload_button .menu_icon.wpbc_spin' ).hasClass( 'wpbc_animation_pause' ) ){ return true; } else { return false; } } _src/bookings__hooks.js 0000666 00000020006 15166373417 0011224 0 ustar 00 "use strict"; /** * Define HTML ui Hooks: on KeyUp | Change | -> Sort Order & Number Items / Page * * We are chnaged it once, because such elements always the same */ function wpbc_ajx_booking_define_ui_hooks_once(){ //------------------------------------------------------------------------------------------------------------------ // Booked dates //------------------------------------------------------------------------------------------------------------------ jQuery( '#wh_booking_date' ).on( 'change', function( event ){ var changed_value = JSON.parse( jQuery( '#wh_booking_date' ).val() ); wpbc_ajx_booking_send_search_request_with_params( { 'wh_booking_date': changed_value, 'page_num' : 1, // Frontend selected elements (saving for future use, after F5) 'ui_wh_booking_date_radio' : jQuery( 'input[name="ui_wh_booking_date_radio"]:checked' ).val(), 'ui_wh_booking_date_next' : jQuery( '#ui_wh_booking_date_next' ).val(), 'ui_wh_booking_date_prior' : jQuery( '#ui_wh_booking_date_prior' ).val(), 'ui_wh_booking_date_checkin' : jQuery( '#ui_wh_booking_date_checkin' ).val(), 'ui_wh_booking_date_checkout': jQuery( '#ui_wh_booking_date_checkout' ).val() } ); } ); //------------------------------------------------------------------------------------------------------------------ // Approved | Pending | All //------------------------------------------------------------------------------------------------------------------ jQuery( '#wh_approved' ).on( 'change', function( event ){ var changed_value = jQuery( '#wh_approved' ).val(); changed_value = JSON.parse( changed_value ); wpbc_ajx_booking_send_search_request_with_params( { 'wh_approved': changed_value[ 0 ], 'page_num' : 1 } ); } ); //------------------------------------------------------------------------------------------------------------------ // Keywords //------------------------------------------------------------------------------------------------------------------ jQuery( '#wpbc_search_field' ).on( "keyup", function ( event ){ if ( 13 !== event.which ){ wpbc_ajx_booking_searching_after_few_seconds( '#wpbc_search_field' ); // Searching after 1.5 seconds after Key Up } else { wpbc_ajx_booking_searching_after_few_seconds( '#wpbc_search_field', 0 ); // Immediate search } } ); //------------------------------------------------------------------------------------------------------------------ // Existing | Trash | Any //------------------------------------------------------------------------------------------------------------------ jQuery( '#wh_trash' ).on( 'change', function( event ){ var changed_value = JSON.parse( jQuery( '#wh_trash' ).val() ); wpbc_ajx_booking_send_search_request_with_params( { 'wh_trash': changed_value[ 0 ], 'page_num': 1 } ); } ); //------------------------------------------------------------------------------------------------------------------ // All bookings | New bookings //------------------------------------------------------------------------------------------------------------------ jQuery( '#wh_what_bookings' ).on( 'change', function( event ){ var changed_value = JSON.parse( jQuery( '#wh_what_bookings' ).val() ); wpbc_ajx_booking_send_search_request_with_params( { 'wh_what_bookings': changed_value[ 0 ], 'page_num': 1 } ); } ); //------------------------------------------------------------------------------------------------------------------ // "Creation Date" of bookings //------------------------------------------------------------------------------------------------------------------ jQuery( '#wh_modification_date' ).on( 'change', function( event ){ var changed_value = JSON.parse( jQuery( '#wh_modification_date' ).val() ); wpbc_ajx_booking_send_search_request_with_params( { 'wh_modification_date': changed_value, 'page_num' : 1, // Frontend selected elements (saving for future use, after F5) 'ui_wh_modification_date_radio' : jQuery( 'input[name="ui_wh_modification_date_radio"]:checked' ).val(), 'ui_wh_modification_date_prior' : jQuery( '#ui_wh_modification_date_prior' ).val(), 'ui_wh_modification_date_checkin' : jQuery( '#ui_wh_modification_date_checkin' ).val(), 'ui_wh_modification_date_checkout': jQuery( '#ui_wh_modification_date_checkout' ).val() } ); } ); //------------------------------------------------------------------------------------------------------------------ // Payment Status //------------------------------------------------------------------------------------------------------------------ jQuery( '#wh_pay_status' ).on( 'change', function( event ){ var changed_value = JSON.parse( jQuery( '#wh_pay_status' ).val() ); wpbc_ajx_booking_send_search_request_with_params( { 'wh_pay_status': changed_value, 'page_num' : 1, // Frontend selected elements (saving for future use, after F5) 'ui_wh_pay_status_radio' : ( ( undefined === jQuery( 'input[name="ui_wh_pay_status_radio"]:checked' ).val() ) ? '' : jQuery( 'input[name="ui_wh_pay_status_radio"]:checked' ).val() ), 'ui_wh_pay_status_custom': jQuery( '#ui_wh_pay_status_custom' ).val() } ); } ); //------------------------------------------------------------------------------------------------------------------ // Min Cost //------------------------------------------------------------------------------------------------------------------ jQuery( '#wh_cost' ).on( 'change', function( event ){ var changed_value = jQuery( '#wh_cost' ).val(); wpbc_ajx_booking_send_search_request_with_params( { 'wh_cost' : changed_value, 'page_num': 1 } ); } ); //------------------------------------------------------------------------------------------------------------------ // Max Cost //------------------------------------------------------------------------------------------------------------------ jQuery( '#wh_cost2' ).on( 'change', function( event ){ var changed_value = jQuery( '#wh_cost2' ).val(); wpbc_ajx_booking_send_search_request_with_params( { 'wh_cost2' : changed_value, 'page_num': 1 } ); } ); //------------------------------------------------------------------------------------------------------------------ // Booking resources //------------------------------------------------------------------------------------------------------------------ jQuery( '#wh_booking_type' ).on( 'change', function( event ){ var changed_value = jQuery( '#wh_booking_type' ).val(); // it's get as array if ( ( Array.isArray( changed_value ) ) && ( 0 === changed_value.length ) ){ changed_value = ['-1']; } wpbc_ajx_booking_send_search_request_with_params( { 'wh_booking_type' : changed_value, 'page_num': 1 } ); } ); //------------------------------------------------------------------------------------------------------------------ // Sorting //------------------------------------------------------------------------------------------------------------------ jQuery( '#wh_sort' ).on( 'change', function( event ){ var changed_value = jQuery( '#wh_sort' ).val(); changed_value = JSON.parse( changed_value ); wpbc_ajx_booking_send_search_request_with_params( { 'wh_sort': changed_value[ 0 ] } ); } ); } jQuery(document).ready(function(){ wpbc_ajx_booking_define_ui_hooks_once(); }); _src/bookings__actions.js 0000666 00000051707 15166373417 0011555 0 ustar 00 "use strict"; /** * Ajax ----------------------------------------------------------------------------------------------------- */ //var is_this_action = false; /** * Send Ajax action request, like approving or cancellation * * @param action_param */ function wpbc_ajx_booking_ajax_action_request( action_param = {} ){ console.groupCollapsed( 'WPBC_AJX_BOOKING_ACTIONS' ); console.log( ' == Ajax Actions :: Params == ', action_param ); //is_this_action = true; wpbc_booking_listing_reload_button__spin_start(); // Get redefined Locale, if action on single booking ! if ( ( undefined != action_param[ 'booking_id' ] ) && ( ! Array.isArray( action_param[ 'booking_id' ] ) ) ){ // Not array action_param[ 'locale' ] = wpbc_get_selected_locale( action_param[ 'booking_id' ], wpbc_ajx_booking_listing.get_secure_param( 'locale' ) ); } var action_post_params = { action : 'WPBC_AJX_BOOKING_ACTIONS', nonce : wpbc_ajx_booking_listing.get_secure_param( 'nonce' ), wpbc_ajx_user_id: ( ( undefined == action_param[ 'user_id' ] ) ? wpbc_ajx_booking_listing.get_secure_param( 'user_id' ) : action_param[ 'user_id' ] ), wpbc_ajx_locale: ( ( undefined == action_param[ 'locale' ] ) ? wpbc_ajx_booking_listing.get_secure_param( 'locale' ) : action_param[ 'locale' ] ), action_params : action_param }; // It's required for CSV export - getting the same list of bookings if ( typeof action_param.search_params !== 'undefined' ){ action_post_params[ 'search_params' ] = action_param.search_params; delete action_post_params.action_params.search_params; } // Start Ajax jQuery.post( wpbc_url_ajax , action_post_params , /** * S u c c e s s * * @param response_data - its object returned from Ajax - class-live-searcg.php * @param textStatus - 'success' * @param jqXHR - Object */ function ( response_data, textStatus, jqXHR ) { console.log( ' == Ajax Actions :: Response WPBC_AJX_BOOKING_ACTIONS == ', response_data ); console.groupEnd(); // Probably Error if ( (typeof response_data !== 'object') || (response_data === null) ){ jQuery( '.wpbc_ajx_under_toolbar_row' ).hide(); //FixIn: 9.6.1.5 jQuery( wpbc_ajx_booking_listing.get_other_param( 'listing_container' ) ).html( '<div class="wpbc-settings-notice notice-warning" style="text-align:left">' + response_data + '</div>' ); return; } wpbc_booking_listing_reload_button__spin_pause(); wpbc_admin_show_message( response_data[ 'ajx_after_action_message' ].replace( /\n/g, "<br />" ) , ( '1' == response_data[ 'ajx_after_action_result' ] ) ? 'success' : 'error' , ( ( 'undefined' === typeof(response_data[ 'ajx_after_action_result_all_params_arr' ][ 'after_action_result_delay' ]) ) ? 10000 : response_data[ 'ajx_after_action_result_all_params_arr' ][ 'after_action_result_delay' ] ) ); // Success response if ( '1' == response_data[ 'ajx_after_action_result' ] ){ var is_reload_ajax_listing = true; // After Google Calendar import show imported bookings and reload the page for toolbar parameters update if ( false !== response_data[ 'ajx_after_action_result_all_params_arr' ][ 'new_listing_params' ] ){ wpbc_ajx_booking_send_search_request_with_params( response_data[ 'ajx_after_action_result_all_params_arr' ][ 'new_listing_params' ] ); var closed_timer = setTimeout( function (){ if ( wpbc_booking_listing_reload_button__is_spin() ){ if ( undefined != response_data[ 'ajx_after_action_result_all_params_arr' ][ 'new_listing_params' ][ 'reload_url_params' ] ){ document.location.href = response_data[ 'ajx_after_action_result_all_params_arr' ][ 'new_listing_params' ][ 'reload_url_params' ]; } else { document.location.reload(); } } } , 2000 ); is_reload_ajax_listing = false; } // Start download exported CSV file if ( undefined != response_data[ 'ajx_after_action_result_all_params_arr' ][ 'export_csv_url' ] ){ wpbc_ajx_booking__export_csv_url__download( response_data[ 'ajx_after_action_result_all_params_arr' ][ 'export_csv_url' ] ); is_reload_ajax_listing = false; } if ( is_reload_ajax_listing ){ wpbc_ajx_booking__actual_listing__show(); // Sending Ajax Request - with parameters that we early defined in "wpbc_ajx_booking_listing" Obj. } } // Remove spin icon from button and Enable this button. wpbc_button__remove_spin( response_data[ 'ajx_cleaned_params' ][ 'ui_clicked_element_id' ] ) // Hide modals wpbc_popup_modals__hide(); jQuery( '#ajax_respond' ).html( response_data ); // For ability to show response, add such DIV element to page } ).fail( function ( jqXHR, textStatus, errorThrown ) { if ( window.console && window.console.log ){ console.log( 'Ajax_Error', jqXHR, textStatus, errorThrown ); } jQuery( '.wpbc_ajx_under_toolbar_row' ).hide(); //FixIn: 9.6.1.5 var error_message = '<strong>' + 'Error!' + '</strong> ' + errorThrown ; if ( jqXHR.responseText ){ error_message += jqXHR.responseText; } error_message = error_message.replace( /\n/g, "<br />" ); wpbc_ajx_booking_show_message( error_message ); }) // .done( function ( data, textStatus, jqXHR ) { if ( window.console && window.console.log ){ console.log( 'second success', data, textStatus, jqXHR ); } }) // .always( function ( data_jqXHR, textStatus, jqXHR_errorThrown ) { if ( window.console && window.console.log ){ console.log( 'always finished', data_jqXHR, textStatus, jqXHR_errorThrown ); } }) ; // End Ajax } /** * Hide all open modal popups windows */ function wpbc_popup_modals__hide(){ // Hide modals if ( 'function' === typeof (jQuery( '.wpbc_popup_modal' ).wpbc_my_modal) ){ jQuery( '.wpbc_popup_modal' ).wpbc_my_modal( 'hide' ); } } /** * Dates Short <-> Wide ----------------------------------------------------------------------------------- */ function wpbc_ajx_click_on_dates_short(){ jQuery( '#booking_dates_small,.booking_dates_full' ).hide(); jQuery( '#booking_dates_full,.booking_dates_small' ).show(); wpbc_ajx_booking_send_search_request_with_params( {'ui_usr__dates_short_wide': 'short'} ); } function wpbc_ajx_click_on_dates_wide(){ jQuery( '#booking_dates_full,.booking_dates_small' ).hide(); jQuery( '#booking_dates_small,.booking_dates_full' ).show(); wpbc_ajx_booking_send_search_request_with_params( {'ui_usr__dates_short_wide': 'wide'} ); } function wpbc_ajx_click_on_dates_toggle(this_date){ jQuery( this_date ).parents( '.wpbc_col_dates' ).find( '.booking_dates_small' ).toggle(); jQuery( this_date ).parents( '.wpbc_col_dates' ).find( '.booking_dates_full' ).toggle(); /* var visible_section = jQuery( this_date ).parents( '.booking_dates_expand_section' ); visible_section.hide(); if ( visible_section.hasClass( 'booking_dates_full' ) ){ visible_section.parents( '.wpbc_col_dates' ).find( '.booking_dates_small' ).show(); } else { visible_section.parents( '.wpbc_col_dates' ).find( '.booking_dates_full' ).show(); }*/ console.log( 'wpbc_ajx_click_on_dates_toggle', this_date ); } /** * Locale --------------------------------------------------------------------------------------------------- */ /** * Select options in select boxes based on attribute "value_of_selected_option" and RED color and hint for LOCALE button -- It's called from wpbc_ajx_booking_define_ui_hooks() each time after Listing loading. */ function wpbc_ajx_booking__ui_define__locale(){ jQuery( '.wpbc_listing_container select' ).each( function ( index ){ var selection = jQuery( this ).attr( "value_of_selected_option" ); // Define selected select boxes if ( undefined !== selection ){ jQuery( this ).find( 'option[value="' + selection + '"]' ).prop( 'selected', true ); if ( ('' != selection) && (jQuery( this ).hasClass( 'set_booking_locale_selectbox' )) ){ // Locale var booking_locale_button = jQuery( this ).parents( '.ui_element_locale' ).find( '.set_booking_locale_button' ) //booking_locale_button.css( 'color', '#db4800' ); // Set button red booking_locale_button.addClass( 'wpbc_ui_red' ); // Set button red if ( 'function' === typeof( wpbc_tippy ) ){ booking_locale_button.get(0)._tippy.setContent( selection ); } } } } ); } /** * Remark --------------------------------------------------------------------------------------------------- */ /** * Define content of remark "booking note" button and textarea. -- It's called from wpbc_ajx_booking_define_ui_hooks() each time after Listing loading. */ function wpbc_ajx_booking__ui_define__remark(){ jQuery( '.wpbc_listing_container .ui_remark_section textarea' ).each( function ( index ){ var text_val = jQuery( this ).val(); if ( (undefined !== text_val) && ('' != text_val) ){ var remark_button = jQuery( this ).parents( '.ui_group' ).find( '.set_booking_note_button' ); if ( remark_button.length > 0 ){ remark_button.addClass( 'wpbc_ui_red' ); // Set button red if ( 'function' === typeof (wpbc_tippy) ){ //remark_button.get( 0 )._tippy.allowHTML = true; //remark_button.get( 0 )._tippy.setContent( text_val.replace(/[\n\r]/g, '<br>') ); remark_button.get( 0 )._tippy.setProps( { allowHTML: true, content : text_val.replace( /[\n\r]/g, '<br>' ) } ); } } } } ); } /** * Actions ,when we click on "Remark" button. * * @param jq_button - this jQuery button object */ function wpbc_ajx_booking__ui_click__remark( jq_button ){ jq_button.parents('.ui_group').find('.ui_remark_section').toggle(); } /** * Change booking resource ---------------------------------------------------------------------------------- */ function wpbc_ajx_booking__ui_click_show__change_resource( booking_id, resource_id ){ // Define ID of booking to hidden input jQuery( '#change_booking_resource__booking_id' ).val( booking_id ); // Select booking resource that belong to booking jQuery( '#change_booking_resource__resource_select' ).val( resource_id ).trigger( 'change' ); var cbr; // Get Resource section cbr = jQuery( "#change_booking_resource__section" ).detach(); // Append it to booking ROW cbr.appendTo( jQuery( "#ui__change_booking_resource__section_in_booking_" + booking_id ) ); cbr = null; // Hide sections of "Change booking resource" in all other bookings ROWs //jQuery( ".ui__change_booking_resource__section_in_booking" ).hide(); if ( ! jQuery( "#ui__change_booking_resource__section_in_booking_" + booking_id ).is(':visible') ){ jQuery( ".ui__under_actions_row__section_in_booking" ).hide(); } // Show only "change booking resource" section for current booking jQuery( "#ui__change_booking_resource__section_in_booking_" + booking_id ).toggle(); } function wpbc_ajx_booking__ui_click_save__change_resource( this_el, booking_action, el_id ){ wpbc_ajx_booking_ajax_action_request( { 'booking_action' : booking_action, 'booking_id' : jQuery( '#change_booking_resource__booking_id' ).val(), 'selected_resource_id' : jQuery( '#change_booking_resource__resource_select' ).val(), 'ui_clicked_element_id': el_id } ); wpbc_button_enable_loading_icon( this_el ); // wpbc_ajx_booking__ui_click_close__change_resource(); } function wpbc_ajx_booking__ui_click_close__change_resource(){ var cbrce; // Get Resource section cbrce = jQuery("#change_booking_resource__section").detach(); // Append it to hidden HTML template section at the bottom of the page cbrce.appendTo(jQuery("#wpbc_hidden_template__change_booking_resource")); cbrce = null; // Hide all change booking resources sections jQuery(".ui__change_booking_resource__section_in_booking").hide(); } /** * Duplicate booking in other resource ---------------------------------------------------------------------- */ function wpbc_ajx_booking__ui_click_show__duplicate_booking( booking_id, resource_id ){ // Define ID of booking to hidden input jQuery( '#duplicate_booking_to_other_resource__booking_id' ).val( booking_id ); // Select booking resource that belong to booking jQuery( '#duplicate_booking_to_other_resource__resource_select' ).val( resource_id ).trigger( 'change' ); var cbr; // Get Resource section cbr = jQuery( "#duplicate_booking_to_other_resource__section" ).detach(); // Append it to booking ROW cbr.appendTo( jQuery( "#ui__duplicate_booking_to_other_resource__section_in_booking_" + booking_id ) ); cbr = null; // Hide sections of "Duplicate booking" in all other bookings ROWs if ( ! jQuery( "#ui__duplicate_booking_to_other_resource__section_in_booking_" + booking_id ).is(':visible') ){ jQuery( ".ui__under_actions_row__section_in_booking" ).hide(); } // Show only "Duplicate booking" section for current booking ROW jQuery( "#ui__duplicate_booking_to_other_resource__section_in_booking_" + booking_id ).toggle(); } function wpbc_ajx_booking__ui_click_save__duplicate_booking( this_el, booking_action, el_id ){ wpbc_ajx_booking_ajax_action_request( { 'booking_action' : booking_action, 'booking_id' : jQuery( '#duplicate_booking_to_other_resource__booking_id' ).val(), 'selected_resource_id' : jQuery( '#duplicate_booking_to_other_resource__resource_select' ).val(), 'ui_clicked_element_id': el_id } ); wpbc_button_enable_loading_icon( this_el ); // wpbc_ajx_booking__ui_click_close__change_resource(); } function wpbc_ajx_booking__ui_click_close__duplicate_booking(){ var cbrce; // Get Resource section cbrce = jQuery("#duplicate_booking_to_other_resource__section").detach(); // Append it to hidden HTML template section at the bottom of the page cbrce.appendTo(jQuery("#wpbc_hidden_template__duplicate_booking_to_other_resource")); cbrce = null; // Hide all change booking resources sections jQuery(".ui__duplicate_booking_to_other_resource__section_in_booking").hide(); } /** * Change payment status ------------------------------------------------------------------------------------ */ function wpbc_ajx_booking__ui_click_show__set_payment_status( booking_id ){ var jSelect = jQuery( '#ui__set_payment_status__section_in_booking_' + booking_id ).find( 'select' ) var selected_pay_status = jSelect.attr( "ajx-selected-value" ); // Is it float - then it's unknown if ( !isNaN( parseFloat( selected_pay_status ) ) ){ jSelect.find( 'option[value="1"]' ).prop( 'selected', true ); // Unknown value is '1' in select box } else { jSelect.find( 'option[value="' + selected_pay_status + '"]' ).prop( 'selected', true ); // Otherwise known payment status } // Hide sections of "Change booking resource" in all other bookings ROWs if ( ! jQuery( "#ui__set_payment_status__section_in_booking_" + booking_id ).is(':visible') ){ jQuery( ".ui__under_actions_row__section_in_booking" ).hide(); } // Show only "change booking resource" section for current booking jQuery( "#ui__set_payment_status__section_in_booking_" + booking_id ).toggle(); } function wpbc_ajx_booking__ui_click_save__set_payment_status( booking_id, this_el, booking_action, el_id ){ wpbc_ajx_booking_ajax_action_request( { 'booking_action' : booking_action, 'booking_id' : booking_id, 'selected_payment_status' : jQuery( '#ui_btn_set_payment_status' + booking_id ).val(), 'ui_clicked_element_id': el_id + '_save' } ); wpbc_button_enable_loading_icon( this_el ); jQuery( '#' + el_id + '_cancel').hide(); //wpbc_button_enable_loading_icon( jQuery( '#' + el_id + '_cancel').get(0) ); } function wpbc_ajx_booking__ui_click_close__set_payment_status(){ // Hide all change payment status for booking jQuery(".ui__set_payment_status__section_in_booking").hide(); } /** * Change booking cost -------------------------------------------------------------------------------------- */ function wpbc_ajx_booking__ui_click_save__set_booking_cost( booking_id, this_el, booking_action, el_id ){ wpbc_ajx_booking_ajax_action_request( { 'booking_action' : booking_action, 'booking_id' : booking_id, 'booking_cost' : jQuery( '#ui_btn_set_booking_cost' + booking_id + '_cost').val(), 'ui_clicked_element_id': el_id + '_save' } ); wpbc_button_enable_loading_icon( this_el ); jQuery( '#' + el_id + '_cancel').hide(); //wpbc_button_enable_loading_icon( jQuery( '#' + el_id + '_cancel').get(0) ); } function wpbc_ajx_booking__ui_click_close__set_booking_cost(){ // Hide all change payment status for booking jQuery(".ui__set_booking_cost__section_in_booking").hide(); } /** * Send Payment request -------------------------------------------------------------------------------------- */ function wpbc_ajx_booking__ui_click__send_payment_request(){ wpbc_ajx_booking_ajax_action_request( { 'booking_action' : 'send_payment_request', 'booking_id' : jQuery( '#wpbc_modal__payment_request__booking_id').val(), 'reason_of_action' : jQuery( '#wpbc_modal__payment_request__reason_of_action').val(), 'ui_clicked_element_id': 'wpbc_modal__payment_request__button_send' } ); wpbc_button_enable_loading_icon( jQuery( '#wpbc_modal__payment_request__button_send' ).get( 0 ) ); } /** * Import Google Calendar ------------------------------------------------------------------------------------ */ function wpbc_ajx_booking__ui_click__import_google_calendar(){ wpbc_ajx_booking_ajax_action_request( { 'booking_action' : 'import_google_calendar', 'ui_clicked_element_id': 'wpbc_modal__import_google_calendar__button_send' , 'booking_gcal_events_from' : jQuery( '#wpbc_modal__import_google_calendar__section #booking_gcal_events_from option:selected').val() , 'booking_gcal_events_from_offset' : jQuery( '#wpbc_modal__import_google_calendar__section #booking_gcal_events_from_offset' ).val() , 'booking_gcal_events_from_offset_type' : jQuery( '#wpbc_modal__import_google_calendar__section #booking_gcal_events_from_offset_type option:selected').val() , 'booking_gcal_events_until' : jQuery( '#wpbc_modal__import_google_calendar__section #booking_gcal_events_until option:selected').val() , 'booking_gcal_events_until_offset' : jQuery( '#wpbc_modal__import_google_calendar__section #booking_gcal_events_until_offset' ).val() , 'booking_gcal_events_until_offset_type' : jQuery( '#wpbc_modal__import_google_calendar__section #booking_gcal_events_until_offset_type option:selected').val() , 'booking_gcal_events_max' : jQuery( '#wpbc_modal__import_google_calendar__section #booking_gcal_events_max' ).val() , 'booking_gcal_resource' : jQuery( '#wpbc_modal__import_google_calendar__section #wpbc_booking_resource option:selected').val() } ); wpbc_button_enable_loading_icon( jQuery( '#wpbc_modal__import_google_calendar__section #wpbc_modal__import_google_calendar__button_send' ).get( 0 ) ); } /** * Export bookings to CSV ------------------------------------------------------------------------------------ */ function wpbc_ajx_booking__ui_click__export_csv( params ){ var selected_booking_id_arr = wpbc_get_selected_row_id(); wpbc_ajx_booking_ajax_action_request( { 'booking_action' : params[ 'booking_action' ], 'ui_clicked_element_id' : params[ 'ui_clicked_element_id' ], 'export_type' : params[ 'export_type' ], 'csv_export_separator' : params[ 'csv_export_separator' ], 'csv_export_skip_fields': params[ 'csv_export_skip_fields' ], 'booking_id' : selected_booking_id_arr.join(','), 'search_params' : wpbc_ajx_booking_listing.search_get_all_params() } ); var this_el = jQuery( '#' + params[ 'ui_clicked_element_id' ] ).get( 0 ) wpbc_button_enable_loading_icon( this_el ); } /** * Open URL in new tab - mainly it's used for open CSV link for downloaded exported bookings as CSV * * @param export_csv_url */ function wpbc_ajx_booking__export_csv_url__download( export_csv_url ){ //var selected_booking_id_arr = wpbc_get_selected_row_id(); document.location.href = export_csv_url;// + '&selected_id=' + selected_booking_id_arr.join(','); // It's open additional dialog for asking opening ulr in new tab // window.open( export_csv_url, '_blank').focus(); } bookings__actions.php 0000666 00000474162 15166373417 0011006 0 ustar 00 <?php /** * @version 1.0 * @description AJX_Bookings * @category AJX_Bookings Actions * @author wpdevelop * * @web-site http://oplugins.com/ * @email info@oplugins.com * * @modified 2022-06-10 */ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Main Ajax handler //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Ajax Actions - Get Listing Data and Response to JS script */ function wpbc_ajax_WPBC_AJX_BOOKING_ACTIONS() { if ( ! isset( $_POST['action_params'] ) || empty( $_POST['action_params'] ) ) { exit; } $ajax_errors = new WPBC_AJAX_ERROR_CATCHING(); // Security ----------------------------------------------------------------------------------------------- // in Ajax Post: 'nonce': wpbc_ajx_booking_listing.get_secure_param( 'nonce' ), $action_name = 'wpbc_ajx_booking_listing_ajx' . '_wpbcnonce'; $nonce_post_key = 'nonce'; $result_check = check_ajax_referer( $action_name, $nonce_post_key ); $user_id = ( isset( $_REQUEST['wpbc_ajx_user_id'] ) ) ? intval( $_REQUEST['wpbc_ajx_user_id'] ) : wpbc_get_current_user_id(); // Get clean Parameters for SQL --------------------------------------------------------------------------- $request_rules_structure = array( 'booking_action' => array( 'validate' => array( 'set_booking_locale', 'set_booking_pending' , 'set_booking_approved', 'move_booking_to_trash', 'restore_booking_from_trash', 'delete_booking_completely', 'set_booking_as_read', 'set_booking_as_unread', 'empty_trash', 'set_booking_note', 'change_booking_resource', 'duplicate_booking_to_other_resource', 'set_payment_status', 'set_booking_cost', 'send_payment_request', 'import_google_calendar', 'export_csv', 'feedback_01' ), 'default' => '' ), 'booking_id' => array( 'validate' => 'digit_or_csd', 'default' => 0 ), 'selected_resource_id' => array( 'validate' => 'd', 'default' => 0 ), 'booking_meta_locale' => array( 'validate' => 's', 'default' => '' ), 'reason_of_action' => array( 'validate' => 's', 'default' => '' ), 'remark' => array( 'validate' => 's', 'default' => '' ), 'ui_clicked_element_id' => array( 'validate' => 's', 'default' => '' ), 'selected_payment_status' => array( 'validate' => 's', 'default' => '' ), 'booking_cost' => array( 'validate' => 's', 'default' => '' ), 'export_type' => array( 'validate' => array( 'csv_all', 'csv_page' ), 'default' => 'csv_page' ), 'csv_export_separator' => array( 'validate' => array( 'semicolon', 'comma' ), 'default' => ';' ), 'csv_export_skip_fields' => array( 'validate' => 's', 'default' => '' ), 'booking_gcal_events_from' => array( 'validate' => 's', 'default' => '' ), 'booking_gcal_events_from_offset' => array( 'validate' => 's', 'default' => '' ), 'booking_gcal_events_from_offset_type' => array( 'validate' => 's', 'default' => '' ), 'booking_gcal_events_until' => array( 'validate' => 's', 'default' => '' ), 'booking_gcal_events_until_offset' => array( 'validate' => 's', 'default' => '' ), 'booking_gcal_events_until_offset_type' => array( 'validate' => 's', 'default' => '' ), 'booking_gcal_events_max' => array( 'validate' => 'd', 'default' => 25 ), 'booking_gcal_resource' => array( 'validate' => 's', 'default' => '' ), 'feedback__note' => array( 'validate' => 's', 'default' => '' ), 'feedback_stars' => array( 'validate' => 'd', 'default' => 0 ) ); $user_request = new WPBC_AJX__REQUEST( array( 'db_option_name' => 'booking_listing_request_params', 'user_id' => wpbc_get_current_user_id(), 'request_rules_structure' => $request_rules_structure ) ); $request_prefix = 'action_params'; $request_params = $user_request->get_sanitized__in_request__value_or_default( $request_prefix ); // NOT Direct: $_REQUEST['action_params']['resource_id'] $action_result = array(); switch ( $request_params['booking_action'] ) { case 'set_booking_locale': $action_result = wpbc_booking_do_action__set_booking_locale( $request_params['booking_id'] , array( 'user_id' => $user_id, 'booking_locale' => $request_params['booking_meta_locale'] ) ); break; case 'set_booking_pending': // Pending $action_result = wpbc_booking_do_action__set_booking_approved_or_pending( $request_params['booking_id'] , array( 'user_id' => $user_id, 'reason_of_action' => $request_params['reason_of_action'], 'is_approve' => '0' ) ); break; case 'set_booking_approved': // Approve $action_result = wpbc_booking_do_action__set_booking_approved_or_pending( $request_params['booking_id'] , array( 'user_id' => $user_id, 'reason_of_action' => $request_params['reason_of_action'], 'is_approve' => '1' ) ); break; case 'move_booking_to_trash': // Approve $action_result = wpbc_booking_do_action__trash_booking_or_restore( $request_params['booking_id'] , array( 'user_id' => $user_id, 'reason_of_action' => $request_params['reason_of_action'], 'is_trash' => '1' ) ); break; case 'restore_booking_from_trash': $action_result = wpbc_booking_do_action__trash_booking_or_restore( $request_params['booking_id'] , array( 'user_id' => $user_id, 'reason_of_action' => $request_params['reason_of_action'], 'is_trash' => '0' ) ); break; case 'delete_booking_completely': $action_result = wpbc_booking_do_action__delete_booking_completely( $request_params['booking_id'] , array( 'user_id' => $user_id, 'reason_of_action' => $request_params['reason_of_action'], ) ); break; case 'set_booking_as_read': $action_result = wpbc_booking_do_action__set_booking_as_read_unread( $request_params['booking_id'] , array( 'user_id' => $user_id, 'is_new' => '0' ) ); break; case 'set_booking_as_unread': $action_result = wpbc_booking_do_action__set_booking_as_read_unread( $request_params['booking_id'] , array( 'user_id' => $user_id, 'is_new' => '1' ) ); break; case 'empty_trash': $action_result = wpbc_booking_do_action__empty_trash( array( 'user_id' => $user_id ) ); break; case 'set_booking_note': $action_result = wpbc_booking_do_action__set_booking_note( $request_params['booking_id'] , array( 'user_id' => $user_id, 'remark' => $request_params['remark'], ) ); break; case 'change_booking_resource': // Pending $action_result = wpbc_booking_do_action__change_booking_resource( $request_params['booking_id'] , $request_params['selected_resource_id'] , array( 'user_id' => $user_id ) ); break; case 'duplicate_booking_to_other_resource': $action_result = wpbc_booking_do_action__duplicate_booking_to_other_resource( $request_params['booking_id'] , $request_params['selected_resource_id'] , array( 'user_id' => $user_id ) ); break; case 'set_payment_status': $action_result = wpbc_booking_do_action__set_payment_status( $request_params['booking_id'] , $request_params['selected_payment_status'] , array( 'user_id' => $user_id ) ); break; case 'set_booking_cost': $action_result = wpbc_booking_do_action__set_booking_cost( $request_params['booking_id'] , $request_params['booking_cost'] , array( 'user_id' => $user_id ) ); break; case 'send_payment_request': $action_result = wpbc_booking_do_action__send_payment_request( $request_params['booking_id'] , $request_params['reason_of_action'] , array( 'user_id' => $user_id ) ); break; case 'import_google_calendar': $action_result = wpbc_booking_do_action__import_google_calendar( $request_params , array( 'user_id' => $user_id ) ); break; case 'export_csv': $action_result = wpbc_booking_do_action__export_csv( $request_params , array( 'user_id' => $user_id ) ); break; case 'feedback_01': $action_result = wpbc_booking_do_action__feedback_01( $request_params , array( 'user_id' => $user_id ) ); break; default: } $defaults = array( 'new_listing_params' => false // required for Import Google Calendar bookings , 'after_action_result' => false , 'after_action_message' => sprintf( __('No actions %s has been processed.', 'booking') , ' <strong>' . $request_params['booking_action'] . '</strong> ' ) ); $action_result = wp_parse_args( $action_result, $defaults ); // Check if there were some errors -------------------------------------------------------------------------------- $error_messages = $ajax_errors->get_error_messages(); if ( ! empty( $error_messages ) ) { $action_result['after_action_message'] .= $error_messages; } // Hook for other integrations do_action( 'wpbc_' . $request_params['booking_action'], $request_params, $action_result ); //FixIn: 9.5.3.3 //------------------------------------------------------------------------------------------------------------------ // Send JSON. Its will make "wp_json_encode" - so pass only array, and This function call wp_die( '', '', array( 'response' => null, ) ) Pass JS OBJ: response_data in "jQuery.post( " function on success. wp_send_json( array( 'ajx_action_params' => $_REQUEST['action_params'], // Do not clean input parameters 'ajx_cleaned_params' => $request_params, // Cleaned input parameters 'ajx_after_action_message' => $action_result['after_action_message'], // Message to show 'ajx_after_action_result' => (int) $action_result['after_action_result'], // Result key 0 | 1 'ajx_after_action_result_all_params_arr' => $action_result // All result parameters ) ); } // <editor-fold defaultstate="collapsed" desc=" == Ajax Actions for bookings == " > /** * Action: set booking as Locale * * @param int $booking_id ID of booking 10 * @param $params * * @return array */ function wpbc_booking_do_action__set_booking_locale( $booking_id, $params ){ $booking_locale = $params['booking_locale']; // LOG --------------------------------------------------------------------------------------------------------- $curr_user = get_user_by( 'id', (int) $params['user_id'] ); wpbc_db__add_log_info( $booking_id, sprintf( __( 'Booking locale changed to %s by:', 'booking' ), $booking_locale ) . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')' ); // Action --------------------------------------------------------------------------------------------------------- $option_arr = array( 'booking_meta_locale' => $booking_locale ); $result = wpbc_save_booking_meta_option( $booking_id, $option_arr ); if ( $result ) { $after_action_result = true; $after_action_message = ( ( false === strpos( $booking_id, ',' ) ) ? sprintf( __( 'Booking has been changed locale to %s', 'booking' ), "<strong>{$booking_locale}</strong>" ) : sprintf( __( 'Bookings have been changed locale to %s', 'booking' ), "<strong>{$booking_locale}</strong>" ) ) . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id . '</strong> )</span>'; } else { $after_action_result = false; $after_action_message = ( ( false === strpos( $booking_id, ',' ) ) ? sprintf( __( 'Booking has NOT been changed locale to %s', 'booking' ), "<strong>{$booking_locale}</strong>" ) : sprintf( __( 'Bookings have NOT been changed locale to %s', 'booking' ), "<strong>{$booking_locale}</strong>" ) ) . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id . '</strong> )</span>'; } return array( 'after_action_result' => $after_action_result, 'after_action_message' => $after_action_message ); } /** * Action: Get Google Calendar Link * * @param $booking_data array( 'form_data' => array( ... ) 'form_show' => .... 'dates_short' => array( ... ) ) * * @return string URL of encoded link for adding to Google Calendar */ function wpbc_booking_do_action__get_google_calendar_link( $booking_data ){ $params = array(); $params['timezone'] = get_bk_option('booking_gcal_timezone'); $booking_gcal_events_form_fields = maybe_unserialize( get_bk_option( 'booking_gcal_events_form_fields') ); // array( [title]=>text^name, [description]=>textarea^details, [where]=>text^ ) // Fields ---------------------------------------------------------------------------------------------------------- $fields = array( 'title' => '', 'description' => '', 'where' => '' ); foreach ( $fields as $key_name => $field_value ) { if ( ! empty( $booking_gcal_events_form_fields[ $key_name ] ) ) { $field_name = explode( '^', $booking_gcal_events_form_fields[ $key_name ] ); $field_name = $field_name[ ( count( $field_name ) - 1 ) ]; //FixIn: 8.7.7.6 if ( 'description' === $key_name ) { //FixIn: 8.1.3.2 if ( isset( $booking_data['form_show'] ) ) { //FixIn: 8.7.3.14 //FixIn: 8.7.11.4 $fields[ $key_name ] = $booking_data['form_show']; $fields[ $key_name ] = htmlspecialchars_decode($fields[ $key_name ], ENT_QUOTES ); $fields[ $key_name ] = urlencode($fields[ $key_name ]); $fields[ $key_name ] = htmlentities($fields[ $key_name ] ); $fields[ $key_name ] = htmlspecialchars_decode ( $fields[ $key_name ], ENT_NOQUOTES ); } } else if ( ( ! empty( $field_name ) ) && ( ! empty( $booking_data['form_data'] ) ) && ( ! empty( $booking_data['form_data'][ $field_name ] ) ) ) { //FixIn: 8.7.11.4 $fields[ $key_name ] = $booking_data['form_data'][ $field_name ]; $fields[ $key_name ] = htmlspecialchars_decode($fields[ $key_name ], ENT_QUOTES ); /** * // Convert here from usual symbols to URL symbols https://www.url-encode-decode.com/ $fields[ $key_name ] = str_replace( array( '%','#', '+', '&' ) , array( '%25','%23', '%2B', '%26') , $fields[ $key_name ] ); */ $fields[ $key_name ] = urlencode($fields[ $key_name ]); $fields[ $key_name ] = htmlentities($fields[ $key_name ] ); $fields[ $key_name ] = htmlspecialchars_decode ( $fields[ $key_name ], ENT_NOQUOTES ); } } } // Dates ----------------------------------------------------------------------------------------------------------- $check_in_timestamp = $check_out_timestamp = ''; if ( ! empty( $booking_data[ 'dates_short' ] ) ) { /** * All day events, you can use 20161208/20161209 - note that the old google documentation gets it wrong. * You must use the following date as the end date for a one day all day event, * or +1 day to whatever you want the end date to be. */ $check_in_timestamp = strtotime( $booking_data[ 'dates_short' ][ 0 ], current_time( 'timestamp' ) ); $check_out_timestamp = strtotime( $booking_data[ 'dates_short' ][ ( count( $booking_data[ 'dates_short' ] ) - 1 ) ], current_time( 'timestamp' ) ); if ( trim( substr( $booking_data[ 'dates_short' ][ 0 ], 11 ) ) == '00:00:00' ) { if ( trim( substr( $booking_data[ 'dates_short' ][ ( count( $booking_data[ 'dates_short' ] ) - 1 ) ], 11 ) ) == '00:00:00' ) { $check_in_timestamp = date( "Ymd", $check_in_timestamp ); // All day } else { $check_in_timestamp = date( "Ymd\T000000", $check_in_timestamp ); // All day starting on 00:00:00 //FixIn: 10.0.0.28 } } else { $check_in_timestamp = date( "Ymd\THis", $check_in_timestamp ); //$check_in_timestamp = date( "Ymd\THis\Z", $check_in_timestamp ); } if ( trim( substr( $booking_data[ 'dates_short' ][ ( count( $booking_data[ 'dates_short' ] ) - 1 ) ], 11 ) ) == '00:00:00' ) { $check_out_timestamp = strtotime( '+1 day', $check_out_timestamp ); $check_out_timestamp = date( "Ymd", $check_out_timestamp ); // All day } else { $check_out_timestamp = date( "Ymd\THis", $check_out_timestamp ); //$check_out_timestamp = date( "Ymd\THis\Z", $check_out_timestamp ); } } // Link ----------------------------------------------------------------------------------------------------------- /** * Convert an ISO date/time to a UNIX timestamp function iso_to_ts( $iso ) { sscanf( $iso, "%u-%u-%uT%u:%u:%uZ", $year, $month, $day, $hour, $minute, $second ); return mktime( $hour, $minute, $second, $month, $day, $year ); 20140127T224000Z date("Ymd\THis\Z", time()); */ /** * action: action=TEMPLATE A default required parameter. src: Example: src=default%40gmail.com Format: src=text This is not covered by Google help but is an optional parameter in order to add an event to a shared calendar rather than a user's default. text: Example: text=Garden%20Waste%20Collection Format: text=text This is a required parameter giving the event title. dates: Example: dates=20090621T063000Z/20090621T080000Z (i.e. an event on 21 June 2009 from 7.30am to 9.0am British Summer Time (=GMT+1)). Format: dates=YYYYMMDDToHHMMSSZ/YYYYMMDDToHHMMSSZ This required parameter gives the start and end dates and times (in Greenwich Mean Time) for the event. location: Example: location=Home Format: location=text The obvious location field. trp: Example: trp=false Format: trp=true/false Show event as busy (true) or available (false) sprop: Example: sprop=http%3A%2F%2Fwww.me.org Example: sprop=name:Home%20Page Format: sprop=website and/or sprop=name:website_name */ //$link_add2gcal = 'http://www.google.com/calendar/event?action=TEMPLATE'; //$link_add2gcal .= '&text=' . $fields['title']; $link_add2gcal = 'https://calendar.google.com/calendar/r/eventedit?'; //FixIn: 8.7.3.10 $link_add2gcal .= 'text=' . $fields['title']; //FixIn: 8.7.11.4 $link_add2gcal .= '&dates=' . $check_in_timestamp . '/' . $check_out_timestamp; //$link_add2gcal .= '&dates=[start-custom format='Ymd\\THi00\\Z']/[end-custom format='Ymd\\THi00\\Z']'; $link_add2gcal .= '&details=' . ( ( 'On' !== get_bk_option( 'booking_g_cal_export_no_data' ) ) ? $fields['description'] : '' ); //FixIn: 10.3.0.1 //FixIn: 8.7.11.4 $link_add2gcal .= '&location=' . ( ( 'On' !== get_bk_option( 'booking_g_cal_export_no_data' ) ) ? $fields['where'] : '' ); //FixIn: 8.7.11.4 $link_add2gcal .= '&trp=false'; if ( ! empty( $params['timezone'] ) ) { $link_add2gcal .= '&ctz=' . str_replace( '%', '%25', $params['timezone'] ); //FixIn: 8.7.3.10 //TimeZone } //$link_add2gcal .= '&sprop='; //$link_add2gcal .= '&sprop=name:'; return $link_add2gcal; } /** * Action: move booking to Trash | Restore * * @param $booking_id_arr array or int of booking ID * @param $params array array of parameters: array( 'user_id' => 1, 'reason_of_action' => 'Because...', 'is_trash' => '1' ) * * @return array * * Example: */ function wpbc_booking_do_action__trash_booking_or_restore( $booking_id_arr, $params ){ make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] ); // Get ID list of bookings, like '1' or '3,7,9' ---------------------------------------------------------------- if ( ! is_array( $booking_id_arr ) ) { $booking_id_arr = array( $booking_id_arr ); } $booking_is_csd = join( ',', $booking_id_arr ); $booking_is_csd = wpbc_clean_digit_or_csd( $booking_is_csd ); // Get reason of action -------------------------------------------------------------------------------------------- $action_reason = $params['reason_of_action']; // stripslashes( $params['reason_of_action'] ); // translate words like don\'t to don't // Get reason of action -------------------------------------------------------------------------------------------- $is_trash_or_restore = $params['is_trash']; // Is send email for this action ---------------------------------------------------------------------------------- $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] ); // ----------------------------------------------------------------------------------------------------------------- if ( empty( $booking_is_csd ) ) { $after_action_result = false; $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' ); } else { $after_action_result = true; if ( $is_trash_or_restore == '1' ) { $after_action_message = '<strong style="font-size: 1.4em;">' . count( explode( ',', $booking_is_csd ) ) .'</strong> ' . ( ( false === strpos( $booking_is_csd, ',' ) ) ? sprintf( __( 'Booking has been %s trashed %s', 'booking' ), '<strong>', '</strong>' ) : sprintf( __( 'Bookings have been %s trashed %s', 'booking' ) , '<strong>', '</strong>' ) ) . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_is_csd . '</strong> )</span>'; } else { $after_action_message = '<strong style="font-size: 1.4em;">' . count( explode( ',', $booking_is_csd ) ) .'</strong> ' . ( ( false === strpos( $booking_is_csd, ',' ) ) ? sprintf( __( 'Booking has been set as %s restored %s', 'booking' ), '<strong>', '</strong>' ) : sprintf( __( 'Bookings have been set as %s restored %s', 'booking' ), '<strong>', '</strong>' ) ) . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_is_csd . '</strong> )</span>'; } // SQL --------------------------------------------------------------------------------------------------- global $wpdb; $prepared_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking AS bk SET bk.trash = %s WHERE booking_id IN ({$booking_is_csd})", $is_trash_or_restore ); if ( $is_trash_or_restore == '1' ) { // Trash $my_trash_date = wpbc_datetime_localized( date( 'Y-m-d H:i:s' ), 'Y-m-d H:i:s' ); $prepared_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking AS bk SET bk.trash = %s, bk.is_trash = %s WHERE booking_id IN ({$booking_is_csd})", $is_trash_or_restore, $my_trash_date ); } else { // Restore $prepared_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking AS bk SET bk.trash = %s, bk.is_trash = NULL WHERE booking_id IN ({$booking_is_csd})", $is_trash_or_restore ); } $after_action_result = $wpdb->query( $prepared_sql ); if ( false === $after_action_result ) { $after_action_message = 'Error during updating to DB. File:' . __FILE__ . ' on line: ' . __LINE__; } else { $after_action_result = true; } // Update the Hash and Cost of the booking $bk_id_arr = explode(',', $booking_is_csd ); //FixIn: 8.6.1.11 foreach ( $bk_id_arr as $bk_id ) { wpbc_hash__update_booking_hash( $bk_id ); } // LOG --------------------------------------------------------------------------------------------------------- $curr_user = get_user_by( 'id', (int) $params['user_id'] ); wpbc_db__add_log_info( explode( ',', $booking_is_csd ), ( ( $is_trash_or_restore == '1' ) ? __( 'Trashed by:', 'booking' ) : __( 'Restored by:', 'booking' ) ) . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')' ); // :: ? :: Update 'is_new' status of bookings in Database // wpbc_db_update_number_new_bookings( explode( ',', $booking_is_csd ), '0', $params['user_id'] ); // Just action hook for some other addons do_action( 'wpbc_booking_action__trash', $booking_is_csd, $is_trash_or_restore ); //FixIn: 8.7.6.2 // Emails ------------------------------------------------------------------------------------------------------ if ( ! empty( $is_send_emeils ) ) { if ( $is_trash_or_restore == '1' ) { wpbc_send_email_trash( $booking_is_csd, $is_send_emeils, $action_reason ); } else { //wpbc_send_email_approved( $booking_is_csd, $is_send_emeils, $action_reason ); //wpbc_send_email_deny( $booking_is_csd, $is_send_emeils, $action_reason ); } } } return array( 'after_action_result' => $after_action_result, 'after_action_message' => $after_action_message ); } /** * Action: set booking as Approved | Pending * * @param $booking_id_arr array or int of booking ID * @param $params array array of parameters: array( 'user_id' => 1, 'reason_of_action' => 'Because...', 'is_approve' => '1' ) * * @return array * * Example: * Approved: $action_result = wpbc_booking_do_action__set_booking_approved_or_pending( $request_params['booking_id'] , array( 'user_id' => $user_id, 'reason_of_action' => $request_params['reason_of_action'], 'is_approve' => '1' ) ); * Pending: $action_result = wpbc_booking_do_action__set_booking_approved_or_pending( $request_params['booking_id'] , array( 'user_id' => $user_id, 'reason_of_action' => $request_params['reason_of_action'], 'is_approve' => '0' ) ); */ function wpbc_booking_do_action__set_booking_approved_or_pending( $booking_id_arr, $params ){ /** * * For creation of new bookings or editing use something like this: * // Be sure to make load in Booking Listing this: wp_enqueue_script( 'wpbc-main-client', wpbc_plugin_url( '/js/client.js' ), array( 'wpbc-datepick' ), WP_BK_VERSION_NUM ); new wpdev_booking(); // Define ability to work with shortcodes $return_sh = do_shortcode('[booking type=1 nummonths=2]'); wp_send_json($return_sh); // Send calendar */ make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] ); // Get ID list of bookings, like '1' or '3,7,9' ---------------------------------------------------------------- if ( ! is_array( $booking_id_arr ) ) { $booking_id_arr = array( $booking_id_arr ); } $booking_id_csd = join( ',', $booking_id_arr ); $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd ); // Get reason of action -------------------------------------------------------------------------------------------- $action_reason = $params['reason_of_action']; // stripslashes( $params['reason_of_action'] ); // translate words like don\'t to don't // Get reason of action -------------------------------------------------------------------------------------------- $is_approve_or_pending = $params['is_approve']; // Is send email for this action ---------------------------------------------------------------------------------- $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] ); // ----------------------------------------------------------------------------------------------------------------- if ( empty( $booking_id_csd ) ) { $after_action_result = false; $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' ); } else { $after_action_result = true; if ( $is_approve_or_pending == '1' ) { $after_action_message = '<strong style="font-size: 1.4em;">' . count( explode( ',', $booking_id_csd ) ) .'</strong> ' . ( ( false === strpos( $booking_id_csd, ',' ) ) ? sprintf( __( 'Booking has been %s approved %s', 'booking' ), '<strong>', '</strong>' ) : sprintf( __( 'Bookings have been %s approved %s', 'booking' ) , '<strong>', '</strong>' ) ) . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>'; } else { $after_action_message = '<strong style="font-size: 1.4em;">' . count( explode( ',', $booking_id_csd ) ) .'</strong> ' . ( ( false === strpos( $booking_id_csd, ',' ) ) ? sprintf( __( 'Booking has been set as %s pending %s', 'booking' ), '<strong>', '</strong>' ) : sprintf( __( 'Bookings have been set as %s pending %s', 'booking' ), '<strong>', '</strong>' ) ) . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>'; } // SQL --------------------------------------------------------------------------------------------------- global $wpdb; $prepared_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}bookingdates SET approved = %s WHERE booking_id IN ({$booking_id_csd})", $is_approve_or_pending ); $after_action_result = $wpdb->query( $prepared_sql ); if ( false === $after_action_result ) { $after_action_message = 'Error during updating to DB. File:' . __FILE__ . ' on line: ' . __LINE__; } else { $after_action_result = true; } // LOG --------------------------------------------------------------------------------------------------------- $curr_user = get_user_by( 'id', (int) $params['user_id'] ); wpbc_db__add_log_info( explode( ',', $booking_id_csd ), ( ( $is_approve_or_pending == '1' ) ? __( 'Approved by:', 'booking' ) : __( 'Declined by:', 'booking' ) ) . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')' ); // Update 'is_new' status of bookings in Database wpbc_db_update_number_new_bookings( explode( ',', $booking_id_csd ), '0', $params['user_id'] ); // Just action hook for some other addons do_action( 'wpbc_booking_action__approved', $booking_id_csd, $is_approve_or_pending ); //FixIn: 8.7.6.1 // Emails ------------------------------------------------------------------------------------------------------ if ( ! empty( $is_send_emeils ) ) { if ( $is_approve_or_pending == '1' ) { wpbc_send_email_approved( $booking_id_csd, $is_send_emeils, $action_reason ); } else { wpbc_send_email_deny( $booking_id_csd, $is_send_emeils, $action_reason ); } } // Cancel other pending bookings for the same date ------------------------------------------------------------ if ( $is_approve_or_pending == '1' ) { $all_bk_id_what_canceled = apply_bk_filter( 'cancel_pending_same_resource_bookings_for_specific_dates', false, $booking_id_csd ); } } return array( 'after_action_result' => $after_action_result, 'after_action_message' => $after_action_message ); } /** * Action: booking Completely Delete * * @param $booking_id_arr array or int of booking ID * @param $params array array of parameters: array( 'user_id' => 1, 'reason_of_action' => 'Because...' ) * * @return array * * Example: */ function wpbc_booking_do_action__delete_booking_completely( $booking_id_arr, $params ){ make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] ); // Get ID list of bookings, like '1' or '3,7,9' ---------------------------------------------------------------- if ( ! is_array( $booking_id_arr ) ) { $booking_id_arr = array( $booking_id_arr ); } $booking_is_csd = join( ',', $booking_id_arr ); $booking_is_csd = wpbc_clean_digit_or_csd( $booking_is_csd ); // Get reason of action -------------------------------------------------------------------------------------------- $action_reason = $params['reason_of_action']; // stripslashes( $params['reason_of_action'] ); // translate words like don\'t to don't // Is send email for this action ---------------------------------------------------------------------------------- $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] ); // ----------------------------------------------------------------------------------------------------------------- if ( empty( $booking_is_csd ) ) { $after_action_result = false; $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' ); } else { $after_action_result = true; $bookings_count = '<strong style="font-size: 1.4em;">' . count( explode( ',', $booking_is_csd ) ) .'</strong> '; $after_action_message = $bookings_count . ' ' . ( ( false === strpos( $booking_is_csd, ',' ) ) ? strtolower( sprintf( __( 'Booking has been %s deleted %s', 'booking' ), '<strong>', '</strong>' ) ) : strtolower( sprintf( __( 'Bookings have been %s deleted %s', 'booking' ) , '<strong>', '</strong>' ) ) ) . ' <span style="font-size:0.9em;">( ID = <strong>' . implode( ', ', explode( ',', $booking_is_csd ) ) . '</strong> )</span>'; // LOG --------------------------------------------------------------------------------------------------------- $curr_user = get_user_by( 'id', (int) $params['user_id'] ); wpbc_db__add_log_info( explode( ',', $booking_is_csd ), __( 'Deleted by:', 'booking' ) . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')' ); // Just action hook for some other addons do_action( 'wpbc_booking_action__delete', $booking_is_csd ); //FixIn: 8.7.6.3 // Emails ------------------------------------------------------------------------------------------------------ if ( ! empty( $is_send_emeils ) ) { wpbc_send_email_deleted( $booking_is_csd, $is_send_emeils, $action_reason ); } // SQL --------------------------------------------------------------------------------------------------- global $wpdb; // Dates $prepared_sql = "DELETE FROM {$wpdb->prefix}bookingdates WHERE booking_id IN ({$booking_is_csd})"; $after_action_result = $wpdb->query( $prepared_sql ); if ( false === $after_action_result ) { $after_action_message = 'Error during deleting dates in DB. File:' . __FILE__ . ' on line: ' . __LINE__; } else { $after_action_result = true; } // Bookings $prepared_sql = "DELETE FROM {$wpdb->prefix}booking WHERE booking_id IN ({$booking_is_csd})"; $after_action_result = $wpdb->query( $prepared_sql ); if ( false === $after_action_result ) { $after_action_message = 'Error during deleting bookings in DB. File:' . __FILE__ . ' on line: ' . __LINE__; } else { $after_action_result = true; } } return array( 'after_action_result' => $after_action_result, 'after_action_message' => $after_action_message ); } /** * Action: set booking as Read (Old) | Unread (New) * * @param $booking_id_arr array or int of booking ID * @param $params array array of parameters: array( 'user_id' => 1, 'is_new' => '1' ) * * @return array * * Example: $action_result = wpbc_booking_do_action__set_booking_as_read_unread( $request_params['booking_id'] , array( 'user_id' => $user_id, 'is_new' => '0' ) ); */ function wpbc_booking_do_action__set_booking_as_read_unread( $booking_id_arr, $params ){ make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] ); // Get ID list of bookings, like '1' or '3,7,9' ---------------------------------------------------------------- if ( ! is_array( $booking_id_arr ) ) { $booking_id_arr = array( $booking_id_arr ); } $booking_id_csd = join( ',', $booking_id_arr ); $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd ); // Get reason of action -------------------------------------------------------------------------------------------- $is_new = $params['is_new']; // Is send email for this action ---------------------------------------------------------------------------------- $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] ); // ----------------------------------------------------------------------------------------------------------------- if ( empty( $booking_id_csd ) ) { $after_action_result = false; $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' ); } else { $after_action_result = true; if ( $is_new == '1' ) { $after_action_message = ( ( false === strpos( $booking_id_csd, ',' ) ) ? sprintf( __( 'Booking has been set as %s new %s', 'booking' ), '<strong>', '</strong>' ) : sprintf( __( 'Bookings have been set as %s new %s', 'booking' ) , '<strong>', '</strong>' ) ) . ' <span style="font-size:0.9em;">( ID = <strong>' . (( '-1' == $booking_id_csd ) ? __( 'all', 'booking' ) : $booking_id_csd) . '</strong> )</span>'; } else { $after_action_message = ( ( false === strpos( $booking_id_csd, ',' ) ) ? sprintf( __( 'The booking has been marked as %s read %s', 'booking' ), '<strong>', '</strong>' ) : sprintf( __( 'Bookings have been marked as %s read %s', 'booking' ), '<strong>', '</strong>' ) ) . ' <span style="font-size:0.9em;">( ID = <strong>' . (( '-1' == $booking_id_csd ) ? __( 'all', 'booking' ) : $booking_id_csd) . '</strong> )</span>'; } // SQL --------------------------------------------------------------------------------------------------- global $wpdb; if ('-1' == $booking_id_csd ){ $prepared_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking AS bk SET bk.is_new = %s", $is_new ); $prepared_sql .= " WHERE ( 1 = 1 ) "; $prepared_sql = apply_bk_filter('update_where_sql_for_getting_bookings_in_multiuser', $prepared_sql ); } else { $prepared_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking AS bk SET bk.is_new = %s WHERE booking_id IN ({$booking_id_csd})", $is_new ); } $after_action_result = $wpdb->query( $prepared_sql ); if ( false === $after_action_result ) { $after_action_message = 'Error during updating to DB. File:' . __FILE__ . ' on line: ' . __LINE__; } else { $after_action_result = true; } // LOG --------------------------------------------------------------------------------------------------------- $curr_user = get_user_by( 'id', (int) $params['user_id'] ); wpbc_db__add_log_info( explode( ',', $booking_id_csd ), ( ( $is_new == '1' ) ? __( 'Set as unread by:', 'booking' ) : __( 'Set as read by:', 'booking' ) ) . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')' ); // Just action hook for some other addons do_action( 'wpbc_booking_action__changed_new_status', $booking_id_csd, $is_new ); //FixIn: 8.7.6.1 // Emails ------------------------------------------------------------------------------------------------------ if ( ! empty( $is_send_emeils ) ) { if ( $is_new == '1' ) { //wpbc_send_email_approved( $booking_id_csd, $is_send_emeils, $action_reason ); } else { //wpbc_send_email_deny( $booking_id_csd, $is_send_emeils, $action_reason ); } } } return array( 'after_action_result' => $after_action_result, 'after_action_message' => $after_action_message ); } /** * Action: Emty Trash * * @param $params array array of parameters: array( 'user_id' => 1 ) * * @return array * * Example: */ function wpbc_booking_do_action__empty_trash( $params ){ make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] ); // Is send email for this action ---------------------------------------------------------------------------------- $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] ); // Get bookings ID to delete ------------------------------------------------------------------------------- global $wpdb; $sql = "SELECT * FROM {$wpdb->prefix}booking as bk WHERE bk.trash = 1"; $sql = apply_bk_filter( 'update_where_sql_for_getting_bookings_in_multiuser', $sql, $params['user_id'] ); // Get booking resources of this user only: $user_id $max_bookings_to_erase = 1000; $sql .= " LIMIT 0, " . $max_bookings_to_erase; $bookings_in_trash = $wpdb->get_results( $sql ); //Get ID of all bookings in a trash. $bookings_id_in_trash_arr = array(); foreach ( $bookings_in_trash as $booking_obj ) { $bookings_id_in_trash_arr[] = $booking_obj->booking_id; } $booking_is_csd = implode( ',', $bookings_id_in_trash_arr ); // Empty trash ------------------------------------------------------------------------------------------------ if ( empty( $booking_is_csd ) ) { $after_action_result = false; $after_action_message = __( 'No bookings in trash to erase.', 'booking' ); } else { $after_action_result = true; if ( count( $bookings_id_in_trash_arr ) < $max_bookings_to_erase ) { $after_action_message = sprintf( __( 'Trash has been erased.', 'booking' ) , '<strong>', '</strong>' ) . ' <span style="font-size:0.9em;">( ID = <strong>' . substr( $booking_is_csd, 0 , 500 ) . '</strong> )</span>'; } else { $after_action_message = sprintf( __( 'From trash has been erased %s bookings.', 'booking' ) , '<strong> ' . count( $bookings_id_in_trash_arr ) . ' </strong> ' ) ; } // LOG ----------------------------------------------------------------------------------------------------- // $curr_user = get_user_by( 'id', (int) $params['user_id'] ); // wpbc_db__add_log_info( explode( ',', $booking_is_csd ), // __( 'Deleted by:', 'booking' ) // . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')' // ); // Just action hook for some other addons do_action( 'wpbc_booking_action__empty_trash' ); //FixIn: 8.7.6.3 // Emails ------------------------------------------------------------------------------------------------------ if ( ! empty( $is_send_emeils ) ) { // wpbc_send_email_deleted( $booking_is_csd, $is_send_emeils, __( 'Empty Trash', 'booking' ) ); } // SQL --------------------------------------------------------------------------------------------------- // Dates $prepared_sql = "DELETE FROM {$wpdb->prefix}bookingdates WHERE booking_id IN ({$booking_is_csd})"; $after_action_result = $wpdb->query( $prepared_sql ); if ( false === $after_action_result ) { $after_action_message = 'Error during deleting dates in DB. File:' . __FILE__ . ' on line: ' . __LINE__; } else { $after_action_result = true; } // Bookings $prepared_sql = "DELETE FROM {$wpdb->prefix}booking WHERE booking_id IN ({$booking_is_csd})"; $after_action_result = $wpdb->query( $prepared_sql ); if ( false === $after_action_result ) { $after_action_message = 'Error during deleting bookings in DB. File:' . __FILE__ . ' on line: ' . __LINE__; } else { $after_action_result = true; } } return array( 'after_action_result' => $after_action_result, 'after_action_message' => $after_action_message ); } /** * Action: save booking Remark * * @param $booking_id_arr array or int of booking ID * @param $params array array of parameters: array( 'user_id' => 1, 'remark' => 'Because...') * * @return array * * Example: */ function wpbc_booking_do_action__set_booking_note( $booking_id_arr, $params ){ make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] ); // Get ID list of bookings, like '1' or '3,7,9' ------------------------------------------------------------ if ( ! is_array( $booking_id_arr ) ) { $booking_id_arr = array( $booking_id_arr ); } $booking_id_csd = join( ',', $booking_id_arr ); $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd ); // Get remark -------------------------------------------------------------------------------------------------- $remark_text = $params['remark']; // stripslashes( $params['reason_of_action'] ); // translate words like don\'t to don't // Is send email for this action ------------------------------------------------------------------------------ // $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] ); // ----------------------------------------------------------------------------------------------------------------- if ( empty( $booking_id_csd ) ) { $after_action_result = false; $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' ); } else { $after_action_result = true; $after_action_message = __( 'Note has been saved', 'booking' ) . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>'; // SQL --------------------------------------------------------------------------------------------------- global $wpdb; $prepared_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking SET remark = %s WHERE booking_id IN ({$booking_id_csd})", $remark_text ); $after_action_result = $wpdb->query( $prepared_sql ); if ( false === $after_action_result ) { $after_action_message = 'Error during updating to DB. File:' . __FILE__ . ' on line: ' . __LINE__; } else { $after_action_result = true; } // LOG --------------------------------------------------------------------------------------------------------- if (0) { $curr_user = get_user_by( 'id', (int) $params['user_id'] ); wpbc_db__add_log_info( explode( ',', $booking_id_csd ), __( 'Note saved by:', 'booking' ) . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')' ); } // Just action hook for some other addons do_action( 'wpbc_booking_action__note_saved', $booking_id_csd, $remark_text ); // Emails ------------------------------------------------------------------------------------------------------ if ( 0 ) { if ( ! empty( $is_send_emeils ) ) { wpbc_send_email_approved( $booking_id_csd, $is_send_emeils, $remark_text ); } } } return array( 'after_action_result' => $after_action_result, 'after_action_message' => $after_action_message ); } /** * Action: change Booking Resource * * @param $booking_id_arr array or int of booking ID * @param $selected_resource_id int of booking resource * @param $params array array of parameters: array( 'user_id' => 1 ) * * @return array * * Example: */ function wpbc_booking_do_action__change_booking_resource( $booking_id_arr, $selected_resource_id, $params ) { make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] ); // Get ID list of bookings, like '1' or '3,7,9' ---------------------------------------------------------------- if ( ! is_array( $booking_id_arr ) ) { $booking_id_arr = array( $booking_id_arr ); } $booking_id_csd = join( ',', $booking_id_arr ); $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd ); // ID of booking resource ------------------------------------------------------------------------------------------ $selected_resource_id = intval($selected_resource_id); // Is send email for this action ---------------------------------------------------------------------------------- $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] ); // ----------------------------------------------------------------------------------------------------------------- if ( empty( $booking_id_csd ) ) { $after_action_result = false; $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' ); } else { $after_action_result = true; $after_action_message = ( ( false === strpos( $booking_id_csd, ',' ) ) ? sprintf( __( 'Booking has been changed %s booking resource %s', 'booking' ), '<strong>', '</strong>' ) : sprintf( __( 'Bookings have been changed %s booking resource %s', 'booking' ), '<strong>', '</strong>' ) ) . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>'; $work_booking_id_arr = explode( ',', $booking_id_csd ); foreach ( $work_booking_id_arr as $selected_booking_id ) { // SQL --------------------------------------------------------------------------------------------------- list( $after_action_result, $after_action_message, $formdata_new ) = wpbc__sql__change_booking_resource_for_booking( $selected_booking_id, $selected_resource_id ); if ( $after_action_result ) { // LOG --------------------------------------------------------------------------------------------------------- $curr_user = get_user_by( 'id', (int) $params['user_id'] ); wpbc_db__add_log_info( explode( ',', $selected_booking_id ), __( 'Booking resource changed by:', 'booking' ) . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')' ); // Just action hook for some other addons do_action( 'wpbc_booking_action__change_booking_resource', $selected_booking_id, $selected_resource_id ); // Emails ------------------------------------------------------------------------------------------------------ if ( ! empty( $is_send_emeils ) ) { wpbc_send_email_modified( $selected_booking_id, $selected_resource_id, $formdata_new ); } } } } return array( 'after_action_result' => $after_action_result, 'after_action_message' => $after_action_message ); } /** * Change booking resource for specific booking -- SQL manipulation * @param $selected_booking_id * @param $selected_resource_id * * @return array */ function wpbc__sql__change_booking_resource_for_booking( $selected_booking_id, $selected_resource_id ){ global $wpdb; $booking_id = intval( $selected_booking_id ); $resource_id = intval( $selected_resource_id ); $db_form_data_new = ''; //////////////////////////////////////////////////////////////////////////////////////////////////////////// // 1.Get dates of SOURCE booking //////////////////////////////////////////////////////////////////////////////////////////////////////////// if ( 1 ) { // 1.1.Get booking data of SOURCE booking $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}booking as bk WHERE booking_id = %d ", $booking_id ); $res = $wpdb->get_row( $sql ); $db_form_data_old = $res->form; $resource_id_old = $res->booking_type; // 1.2. Get dates of SOURCE booking $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}bookingdates as dt WHERE booking_id = %d ORDER BY booking_date ASC ", $booking_id ); $old_resource_dates_array = $wpdb->get_results( $sql ); } //TODO: 2023-10-03 14:49 this is new workflow have to be: if (0){ $booking_p = array( 'dates' => TRANSFORM_IT( $old_resource_dates_array ) // -> array( '2017-06-23 14:00:01', '2017-06-24 00:00:00', '2017-06-25', '2017-06-26 12:00:02' ) , 'resource_id' => $resource_id , 'params' => array() // 'is_use_booking_recurrent_time' => false ) // Commented, because get from Booking > Settings General page ); $is_dates_booked = wpbc_api_is_dates_booked( $booking_p[ 'dates' ], $booking_p[ 'resource_id' ], $booking_p[ 'params' ] ); } //////////////////////////////////////////////////////////////////////////////////////////////////////////// // 2. Get bookings of selected booking resource - checking if some dates there is booked or not //////////////////////////////////////////////////////////////////////////////////////////////////////////// $exist_dates_results = wpbc_get_booking_dates_in_resource_for_folowing_dates( $old_resource_dates_array , $resource_id ); if ( ( count( $exist_dates_results ) == 3 ) && ( false === $exist_dates_results[0] ) ){ // // ERROR :: number of check in/dates does not equal to number of check out dates. return $exist_dates_results; } if ( get_bk_option('booking_change_resource_skip_checking') === 'On' ) { //FixIn: 8.4.5.4 $is_date_time_booked = false; } else { $is_date_time_booked = wpbc_check_dates_intersections( $old_resource_dates_array, $exist_dates_results ); } if ( $is_date_time_booked ) { $after_action_result = false; $after_action_message = __( 'Warning! The resource was not changed. Current dates are already booked there.', 'booking' ); } else { // Possible to change $db_form_data_new = wpbc_update_resource_id_in_dbformatted_booking_data( $db_form_data_old, $resource_id_old, $resource_id ); // Update $update_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking AS bk SET bk.form=%s, bk.booking_type=%d WHERE bk.booking_id=%d;" , $db_form_data_new, $resource_id, $booking_id ); if ( false === $wpdb->query( $update_sql ) ) { $after_action_result = false; $after_action_message = get_debuge_error( 'Error during updating booking reource type in BD', __FILE__, __LINE__ ); return array( $after_action_result, $after_action_message, $db_form_data_new ); } if ( class_exists( 'wpdev_bk_biz_l' ) ) { $update_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}bookingdates SET type_id=NULL WHERE booking_id=%d ", $booking_id ); if ( false === $wpdb->query( $update_sql ) ) { $after_action_result = false; $after_action_message = get_debuge_error( 'Error during updating dates type in BD', __FILE__, __LINE__ ); return array( $after_action_result, $after_action_message, $db_form_data_new ); } } $booking_resources_arr = wpbc_ajx_get_all_booking_resources_arr(); $after_action_result = true; $after_action_message = sprintf( __( 'Booking %s has been changed booking resource from %s to %s' ) , '<strong>[ID=' . $booking_id . ']</strong>' , '<strong>' . wpbc_lang( $booking_resources_arr[ $resource_id_old ]['title'] ) . '</strong>' , '<strong>' . wpbc_lang( $booking_resources_arr[ $resource_id ]['title'] ) . '</strong>' ); // Everything Cool :) - booking resource changed } return array( $after_action_result, $after_action_message , $db_form_data_new ); } /** * Get booking dates (bookings obj) of selected booking resource - checking if some dates there is booked or not * * @param $old_resource_dates_array array of OBJ with ..->booking_date * @param int $resource_id Resource ID, where we get dates. * * @return array array of booking OBJ with ..->booking_date */ function wpbc_get_booking_dates_in_resource_for_folowing_dates( $old_resource_dates_array , $resource_id ){ global $wpdb; $dates_sql_between = ''; $check_in_dates_arr = array(); $check_out_dates_arr = array(); if ( 'On' === get_bk_option( 'booking_recurrent_time' ) ) { // If we are using recurrent time slots ? foreach ( $old_resource_dates_array as $k => $v ) { if ( ':02' == substr( $v->booking_date, - 3 ) ) { $check_out_dates_arr[] = $v->booking_date; } if ( ':01' == substr( $v->booking_date, - 3 ) ) { $check_in_dates_arr[] = $v->booking_date; } } if ( count( $check_out_dates_arr ) == count( $check_in_dates_arr ) ) { $dates_sql_between_arr = array(); foreach ( $check_in_dates_arr as $k => $v ) { $dates_sql_between_arr [] = ' ( dt.booking_date BETWEEN "' . $check_in_dates_arr[ $k ] . '" AND "' . $check_out_dates_arr[ $k ] . '" ) '; } $dates_sql_between = implode( 'OR', $dates_sql_between_arr ); //TODO: remove (), if only 1 element in array } else { // ERROR :: number of check in/dates does not equal to number of check out dates. $after_action_result = false; $after_action_message = '<strong>Error</strong>. Number of check in times of booking dates does not equal to number of check out days.' . '<br>Check in dates: ' . implode( ', ', $check_in_dates_arr ) . '<br>Check out dates: ' . implode( ', ', $check_out_dates_arr ); return array( $after_action_result, $after_action_message, '' ); } } if ( '' == $dates_sql_between ) { $temp_check_in = $old_resource_dates_array[0]->booking_date; $temp_check_out = $old_resource_dates_array[ ( count( $old_resource_dates_array ) - 1 ) ]->booking_date; if ( ':02' != substr( $temp_check_out, - 3 ) ) { $temp_check_out = date( 'Y-m-d H:i:s', strtotime( '+1 day -1 second', strtotime( $temp_check_out ) ) ); } $dates_sql_between .= ' dt.booking_date BETWEEN "' . $temp_check_in . '" AND "' . $temp_check_out . '" '; } $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}booking as bk INNER JOIN {$wpdb->prefix}bookingdates as dt ON bk.booking_id = dt.booking_id WHERE bk.trash != 1 AND bk.booking_type = %d", $resource_id ); $sql .= " AND ( {$dates_sql_between} ) "; // In BL version its does not check for booking belonging to several booking resources if ( class_exists( 'wpdev_bk_biz_l' ) ) { $sql .= " OR bk.booking_id IN ( " . " SELECT DISTINCT booking_id FROM {$wpdb->prefix}bookingdates as dtt WHERE dtt.type_id = {$resource_id} " //."AND DATE(dt.booking_date) IN ( {$dates_string} )" . " AND ( " . str_replace( 'dt.', 'dtt.', $dates_sql_between ) . " ) " . ") "; } $sql .= " ORDER BY bk.booking_id DESC, dt.booking_date ASC "; $exist_dates_results = $wpdb->get_results( $sql ); // We have found only intersected dates. Now we need to get all dates from such bookings, for having correct "Start and end time times for the booking" // and does not add some "start time at the begining of the day inside of wpbc_check_dates_intersections( ) function if ( count( $exist_dates_results ) > 0 ) { // Get ID of all bookings that inside of this interval $my_booking_id_arr = []; foreach ( $exist_dates_results as $key => $booking_obj ) { $my_booking_id_arr[] = $booking_obj->booking_id; } // Get all dates of such bookings (not only intersected! $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}booking as bk INNER JOIN {$wpdb->prefix}bookingdates as dt ON bk.booking_id = dt.booking_id WHERE bk.booking_id IN (" . implode( ',', $my_booking_id_arr ) . ") AND bk.trash != 1 AND bk.booking_type = %d", $resource_id ); $sql .= " ORDER BY bk.booking_id DESC, dt.booking_date ASC "; $exist_dates_results = $wpdb->get_results( $sql ); } return $exist_dates_results; } /** * Update "Content of booking fields data" from old booking resource id SUFFIX to new booking Resource ID * * @param string $db_form_data_old * @param int $resource_id_old * @param int $resource_id_new * * @return void */ function wpbc_update_resource_id_in_dbformatted_booking_data( $db_form_data_old, $resource_id_old, $resource_id_new ) { $db_form_data_new = array(); $form_data_arr = explode( '~', $db_form_data_old ); $fields_count = count( $form_data_arr ); for ( $i = 0; $i < $fields_count; $i ++ ) { list( $type, $element_name, $value ) = explode( '^', $form_data_arr[ $i ] ); if ( substr( $element_name, - 2 ) == '[]' ) { $element_name = str_replace( '[]', '', $element_name ); } $element_name = substr( $element_name, 0, - 1 * strlen( $resource_id_old ) ) . $resource_id_new; // Change resource ID in field $db_form_data_new[] = $type . '^' . $element_name . '^' . $value; } return implode( '~', $db_form_data_new ); } /** * Action: Duplicate Booking into other Resource * * @param $booking_id_arr array or int of booking ID * @param $selected_resource_id int of booking resource * @param $params array array of parameters: array( 'user_id' => 1 ) * * @return array * * Example: */ function wpbc_booking_do_action__duplicate_booking_to_other_resource( $booking_id_arr, $selected_resource_id, $params ) { make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] ); // Get ID list of bookings, like '1' or '3,7,9' ---------------------------------------------------------------- if ( ! is_array( $booking_id_arr ) ) { $booking_id_arr = array( $booking_id_arr ); } $booking_id_csd = join( ',', $booking_id_arr ); $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd ); // ID of booking resource ------------------------------------------------------------------------------------------ $selected_resource_id = intval($selected_resource_id); // Is send email for this action ---------------------------------------------------------------------------------- $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] ); // ----------------------------------------------------------------------------------------------------------------- if ( empty( $booking_id_csd ) ) { $after_action_result = false; $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' ); } else { $after_action_result = true; $after_action_message = ( ( false === strpos( $booking_id_csd, ',' ) ) ? sprintf( __( 'Booking has been %s duplicated %s', 'booking' ), '<strong>', '</strong>' ) : sprintf( __( 'Bookings have been %s duplicated %s', 'booking' ), '<strong>', '</strong>' ) ) . ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>'; $work_booking_id_arr = explode( ',', $booking_id_csd ); foreach ( $work_booking_id_arr as $selected_booking_id ) { // SQL --------------------------------------------------------------------------------------------------- list( $after_action_result, $after_action_message, $formdata_new ) = wpbc__sql__duplicate_booking_to_other_resource_for_booking( $selected_booking_id, $selected_resource_id, $params ); if ( $after_action_result ) { // LOG --------------------------------------------------------------------------------------------------------- $curr_user = get_user_by( 'id', (int) $params['user_id'] ); wpbc_db__add_log_info( explode( ',', $selected_booking_id ), __( 'Booking resource changed by:', 'booking' ) . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')' ); // Just action hook for some other addons do_action( 'wpbc_booking_action__duplicate_booking_to_other_resource', $selected_booking_id, $selected_resource_id ); // Emails ------------------------------------------------------------------------------------------------------ if ( ! empty( $is_send_emeils ) ) { // We are sending emails about the new booking, if we have created it. // wpbc_send_email_modified( $selected_booking_id, $selected_resource_id, $formdata_new ); } } } } return array( 'after_action_result' => $after_action_result, 'after_action_message' => $after_action_message ); } /** * Duplicate booking in another resource -- SQL manipulation * @param $selected_booking_id * @param $selected_resource_id * * @return array */ function wpbc__sql__duplicate_booking_to_other_resource_for_booking( $selected_booking_id, $selected_resource_id, $params ){ global $wpdb; $booking_id = intval( $selected_booking_id ); $resource_id = intval( $selected_resource_id ); $db_form_data_new = ''; $booking_resources_arr = wpbc_ajx_get_all_booking_resources_arr(); $is_send_emails = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] ); //////////////////////////////////////////////////////////////////////////////////////////////////////////// // 1.Get dates of SOURCE booking //////////////////////////////////////////////////////////////////////////////////////////////////////////// if ( 1 ) { // 1.1.Get booking data of SOURCE booking $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}booking as bk WHERE booking_id = %d ", $booking_id ); $res = $wpdb->get_row( $sql ); $db_form_data_old = $res->form; $resource_id_old = $res->booking_type; // 1.2. Get dates of SOURCE booking $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}bookingdates as dt WHERE booking_id = %d ORDER BY booking_date ASC ", $booking_id ); $old_resource_dates_array = $wpdb->get_results( $sql ); } //////////////////////////////////////////////////////////////////////////////////////////////////////////// // 2. Get bookings of selected booking resource - checking if some dates there is booked or not //////////////////////////////////////////////////////////////////////////////////////////////////////////// $exist_dates_results = wpbc_get_booking_dates_in_resource_for_folowing_dates( $old_resource_dates_array , $resource_id ); if ( ( count( $exist_dates_results ) == 3 ) && ( false === $exist_dates_results[0] ) ){ // // ERROR :: number of check in/dates does not equal to number of check out dates. return $exist_dates_results; } if ( get_bk_option('booking_change_resource_skip_checking') === 'On' ) { //FixIn: 8.4.5.4 $is_date_time_booked = false; } else { $is_date_time_booked = wpbc_check_dates_intersections( $old_resource_dates_array, $exist_dates_results ); } if ( $is_date_time_booked ) { $after_action_result = false; $after_action_message = '<strong>' . __( 'Warning', 'booking' ) . '!</strong> ' . sprintf( __( 'Booking %s has not been duplicated in booking resource %s. Current dates are already booked there.' ) , '<strong style="font-size:0.9em;">[ID=' . $booking_id . ']</strong>' , '<strong>' . wpbc_lang( $booking_resources_arr[ $resource_id ]['title'] ) . '</strong>' ); } else { // Possible to change $db_form_data_new = wpbc_update_resource_id_in_dbformatted_booking_data( $db_form_data_old, $resource_id_old, $resource_id ); $wpdev_active_locale = isset( $_REQUEST['wpbc_ajx_locale'] ) ? esc_js( $_REQUEST['wpbc_ajx_locale'] ) : 'en_US'; // Change dates from DateObj( $selected_date->booking_date = '2015-10-17' ) to array ( '17.10.2015' ) $my_dates_for_sql = array(); foreach ($old_resource_dates_array as $selected_date) { $selected_date = explode( '-', $selected_date->booking_date ); $my_dates_for_sql[] = sprintf( "%02d.%02d.%04d", $selected_date[2], $selected_date[1], $selected_date[0] ); } $my_dates_for_sql = implode( ', ', $my_dates_for_sql ); // Create a new booking $request_save_params = array( 'resource_id' => $resource_id, // 2 'dates_ddmmyy_csv' => $my_dates_for_sql, // '04.10.2023, 05.10.2023, 06.10.2023' 'form_data' => $db_form_data_new, // 'text^cost_hint2^150.00฿~selectbox-multiple^rangetime2[]^14:00...' 'booking_hash' => '', // 'sdfsf34534rf' 'custom_form' => '', // 'custom_form_name' 'is_emails_send' => $is_send_emails, // 0 | 1 'is_show_payment_form' => 0 // 0 | 1 // 'request_uri' => $_SERVER['HTTP_REFERER'] // 'user_id' => wpbc_get_current_user_id() // 'sync_gid' => '' // 'is_approve_booking' => 0 ); $booking_save_arr = wpbc_booking_save( $request_save_params ); if ( 'ok' === $booking_save_arr['ajx_data']['status'] ) { // Everything Cool :) - booking has been duplicated $booking_id_new = $booking_save_arr['booking_id']; $after_action_result = true; $after_action_message = sprintf( __( 'Booking %s has been duplicated in booking resource %s. New booking %s.' ) , '<strong style="font-size:0.9em;">[ID=' . $booking_id . ']</strong>' , '<strong>' . wpbc_lang( $booking_resources_arr[ $resource_id ]['title'] ) . '</strong>' , '<strong style="font-size:0.9em;">[ID=' . $booking_id_new . ']</strong>' ); } else { // Error $after_action_result = false; $after_action_message = $booking_save_arr['ajx_data']['ajx_after_action_message']; } } return array( $after_action_result, $after_action_message , $db_form_data_new ); } /** * Action: Set payment status for the booking * * @param $booking_id_arr array or int of booking ID * @param $selected_payment_status string payment status of booking * @param $params array array of parameters: array( 'user_id' => 1 ) * * @return array * * Example: */ function wpbc_booking_do_action__set_payment_status( $booking_id_arr, $selected_payment_status, $params ) { global $wpdb; make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] ); // Get ID list of bookings, like '1' or '3,7,9' ---------------------------------------------------------------- if ( ! is_array( $booking_id_arr ) ) { $booking_id_arr = array( $booking_id_arr ); } $booking_id_csd = join( ',', $booking_id_arr ); $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd ); // Is send email for this action ---------------------------------------------------------------------------------- $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] ); // ----------------------------------------------------------------------------------------------------------------- if ( empty( $booking_id_csd ) ) { $after_action_result = false; $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' ); } else { $after_action_result = true; $after_action_message = ''; $work_booking_id_arr = explode( ',', $booking_id_csd ); foreach ( $work_booking_id_arr as $selected_booking_id ) { // SQL --------------------------------------------------------------------------------------------------- $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}booking as bk WHERE bk.booking_id= %d ", $selected_booking_id ); $result_bk = $wpdb->get_results( $sql ); $old_pay_status = ''; if ( ( 0 == count( $result_bk ) ) ) { // Error $after_action_result = false; $after_action_message .= sprintf( __( 'There is no booking %s', 'booking' ) , ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>' ); } else { $old_pay_status = $result_bk[0]->pay_status; } $update_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking AS bk SET bk.pay_status= %s WHERE bk.booking_id= %d ", $selected_payment_status, $selected_booking_id ); if ( false === $wpdb->query( $update_sql ) ) { // Error $after_action_result = false; $after_action_message .= 'Error during updating to DB. File:' . __FILE__ . ' on line: ' . __LINE__; } else { // Success $after_action_message .= sprintf( __( 'Payment status for Booking %s has been updated from %s to %s', 'booking' ) , ' <span style="font-size:0.9em;">( ID = <strong>' . $selected_booking_id . '</strong> )</span>' , '<strong>"' . wpbc__format__get_payment_status_title( $old_pay_status ) . '"</strong>' , '<strong>"' . wpbc__format__get_payment_status_title( $selected_payment_status ) . '"</strong>' ) . '<br/>'; } if ( $after_action_result ) { // LOG --------------------------------------------------------------------------------------------------------- $curr_user = get_user_by( 'id', (int) $params['user_id'] ); wpbc_db__add_log_info( explode( ',', $selected_booking_id ), $after_action_message . '. ' . __( 'Changed by:', 'booking' ) . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')' ); // Just action hook for some other addons do_action( 'wpbc_booking_action__set_payment_status', $selected_booking_id, $selected_payment_status , $old_pay_status ); // Emails ------------------------------------------------------------------------------------------------------ if ( ! empty( $is_send_emeils ) ) { // We are sending emails about the new booking, if we have created it. // wpbc_send_email_modified( $selected_booking_id, $selected_resource_id, $formdata_new ); } } } } return array( 'after_action_result' => $after_action_result, 'after_action_message' => $after_action_message ); } /** * Get title of the payment status * * @param $payment_status_key * * @return string */ function wpbc__format__get_payment_status_title( $payment_status_key ){ $selected_payment_status_text = $payment_status_key; $select_box_options = get_payment_status_titles(); $select_box_options = array_flip( $select_box_options ); if ( ! empty( $select_box_options[ $payment_status_key ] ) ) { $selected_payment_status_text = $select_box_options[ $payment_status_key ]; } return $selected_payment_status_text; } /** * Action: Set Booking Cost * * @param $booking_id_arr array or int of booking ID * @param $booking_cost string booking cost * @param $params array array of parameters: array( 'user_id' => 1 ) * * @return array * * Example: */ function wpbc_booking_do_action__set_booking_cost( $booking_id_arr, $booking_cost, $params ) { global $wpdb; make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] ); // Get ID list of bookings, like '1' or '3,7,9' ---------------------------------------------------------------- if ( ! is_array( $booking_id_arr ) ) { $booking_id_arr = array( $booking_id_arr ); } $booking_id_csd = join( ',', $booking_id_arr ); $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd ); // Is send email for this action ---------------------------------------------------------------------------------- $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] ); // ----------------------------------------------------------------------------------------------------------------- $booking_cost = str_replace(',', '.', $booking_cost); $booking_cost = floatval( $booking_cost ); if ( empty( $booking_id_csd ) ) { $after_action_result = false; $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' ); } else { $after_action_result = true; $after_action_message = ''; $work_booking_id_arr = explode( ',', $booking_id_csd ); foreach ( $work_booking_id_arr as $selected_booking_id ) { // SQL --------------------------------------------------------------------------------------------------- $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}booking as bk WHERE bk.booking_id= %d ", $selected_booking_id ); $result_bk = $wpdb->get_results( $sql ); $old_booking_cost = ''; if ( ( 0 == count( $result_bk ) ) ) { // Error $after_action_result = false; $after_action_message .= sprintf( __( 'There is no booking %s', 'booking' ) , ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>' ); } else { $old_booking_cost = $result_bk[0]->cost; } $update_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking AS bk SET bk.cost = %f WHERE bk.booking_id = %d ", $booking_cost, $selected_booking_id ); if ( false === $wpdb->query( $update_sql ) ) { // Error $after_action_result = false; $after_action_message .= 'Error during updating to DB. File:' . __FILE__ . ' on line: ' . __LINE__; } else { // Success $after_action_message .= sprintf( __( 'Cost for Booking %s has been updated from %s to %s', 'booking' ) , ' <span style="font-size:0.9em;">( ID = <strong>' . $selected_booking_id . '</strong> )</span>' , '<strong>"' . wpbc__format__get_payment_status_title( $old_booking_cost ) . '"</strong>' , '<strong>"' . wpbc__format__get_payment_status_title( $booking_cost ) . '"</strong>' ) . '<br/>'; } if ( $after_action_result ) { // LOG --------------------------------------------------------------------------------------------------------- $curr_user = get_user_by( 'id', (int) $params['user_id'] ); wpbc_db__add_log_info( explode( ',', $selected_booking_id ), $after_action_message . '. ' . __( 'Changed by:', 'booking' ) . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')' ); // Just action hook for some other addons do_action( 'wpbc_booking_action__set_booking_cost', $selected_booking_id, $booking_cost , $old_booking_cost ); // Emails ------------------------------------------------------------------------------------------------------ if ( ! empty( $is_send_emeils ) ) { if ( get_bk_option( 'booking_send_email_on_cost_change' ) == 'On' ) { //FixIn: 8.1.3.30 $booking_data = apply_bk_filter( 'wpbc_get_booking_data', $selected_booking_id ); wpbc_send_email_modified( $selected_booking_id, $booking_data['type'], $booking_data['form'] ); } } } } } return array( 'after_action_result' => $after_action_result, 'after_action_message' => $after_action_message ); } /** * Action: Send Payment request * * @param $booking_id_arr array or int of booking ID * @param $booking_cost string booking cost * @param $params array array of parameters: array( 'user_id' => 1 ) * * @return array */ function wpbc_booking_do_action__send_payment_request($booking_id_arr, $reason_of_action, $params ) { global $wpdb; make_bk_action('check_multiuser_params_for_client_side_by_user_id', $params['user_id'] ); // Get ID list of bookings, like '1' or '3,7,9' ---------------------------------------------------------------- if ( ! is_array( $booking_id_arr ) ) { $booking_id_arr = array( $booking_id_arr ); } $booking_id_csd = join( ',', $booking_id_arr ); $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd ); // Is send email for this action ---------------------------------------------------------------------------------- $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] ); // ----------------------------------------------------------------------------------------------------------------- if ( empty( $booking_id_csd ) ) { $after_action_result = false; $after_action_message = __( 'No bookings have been selected. Please select one or more bookings.', 'booking' ); } else { $after_action_result = true; $after_action_message = ''; $work_booking_id_arr = explode( ',', $booking_id_csd ); foreach ( $work_booking_id_arr as $selected_booking_id ) { // SQL --------------------------------------------------------------------------------------------------- $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}booking as bk WHERE bk.booking_id= %d ", $selected_booking_id ); $result_bk = $wpdb->get_results( $sql ); $old_booking_cost = ''; if ( ( 0 == count( $result_bk ) ) ) { // Error $after_action_result = false; $after_action_message .= sprintf( __( 'There is no booking %s', 'booking' ) , ' <span style="font-size:0.9em;">( ID = <strong>' . $booking_id_csd . '</strong> )</span>' ); } else { $old_booking_cost = $result_bk[0]->cost; $is_email_payment_request_adress = get_bk_option( 'booking_is_email_payment_request_adress' ); if ( 'Off' != $is_email_payment_request_adress ) { $reason_of_action = htmlspecialchars( str_replace( '\"', '"', $reason_of_action ) ); $reason_of_action = str_replace( "\'", "'", $reason_of_action ); foreach ( $result_bk as $res ) { $is_send = wpbc_send_email_payment_request( $res->booking_id, $res->booking_type, $res->form, $reason_of_action ); if ( $is_send ) { // Update Payment request number $pay_request_numer = $res->pay_request + 1; $update_sql = $wpdb->prepare( "UPDATE {$wpdb->prefix}booking AS bk SET bk.pay_request= %d WHERE bk.booking_id= %d ", $pay_request_numer, $res->booking_id ); if ( false === $wpdb->query( $update_sql ) ) { // Error $after_action_result = false; $after_action_message .= 'Error during updating to DB. File:' . __FILE__ . ' on line: ' . __LINE__; } else { // Success $after_action_message .= sprintf( __( 'Payment request for Booking %s has been sent. Cost for payment: %s', 'booking' ) , ' <span style="font-size:0.9em;">( ID = <strong>' . $selected_booking_id . '</strong> )</span>' , '<strong>"' . wpbc__format__get_payment_status_title( $old_booking_cost ) . '"</strong>' ) . '<br/>'; } } } } } if ( $after_action_result ) { // LOG --------------------------------------------------------------------------------------------------------- $curr_user = get_user_by( 'id', (int) $params['user_id'] ); wpbc_db__add_log_info( explode( ',', $selected_booking_id ), $after_action_message . '. ' . __( 'Send by:', 'booking' ) . ' ' . $curr_user->first_name . ' ' . $curr_user->last_name . ' (' . $curr_user->user_email . ')' ); // Just action hook for some other addons do_action( 'wpbc_booking_action__send_payment_request', $selected_booking_id, $reason_of_action , $old_booking_cost ); // Emails ------------------------------------------------------------------------------------------------------ /* if ( ! empty( $is_send_emeils ) ) { if ( get_bk_option( 'booking_send_email_on_cost_change' ) == 'On' ) { $booking_data = apply_bk_filter( 'wpbc_get_booking_data', $selected_booking_id ); wpbc_send_email_modified( $selected_booking_id, $booking_data['type'], $booking_data['form'] ); } } */ } } } return array( 'after_action_result' => $after_action_result, 'after_action_message' => $after_action_message ); } function wpbc_booking_do_action__import_google_calendar( $request_params, $params ) { $return_array = array(); $user_bk_id = (int) $params['user_id']; global $wpdb; $wpbc_Google_Calendar = new WPBC_Google_Calendar(); $wpbc_Google_Calendar->setSilent(); $wpbc_Google_Calendar->set_timezone( get_bk_option('booking_gcal_timezone') ); $wpbc_Google_Calendar->set_events_from_with_array( array( $request_params['booking_gcal_events_from'], $request_params['booking_gcal_events_from_offset'], $request_params['booking_gcal_events_from_offset_type'] ) ); $wpbc_Google_Calendar->set_events_until_with_array( array( $request_params['booking_gcal_events_until'], $request_params['booking_gcal_events_until_offset'], $request_params['booking_gcal_events_until_offset_type'] ) ); $wpbc_Google_Calendar->set_events_max( $request_params['booking_gcal_events_max'] ); if ( ( isset( $request_params['booking_gcal_resource'] ) ) && ( empty( $request_params['booking_gcal_resource'] ) ) ) { $wpbc_Google_Calendar->setUrl( get_bk_option( 'booking_gcal_feed') ); $import_result = $wpbc_Google_Calendar->run(); } else { if ( $request_params['booking_gcal_resource'] != 'all' ) { // One resource $wpbc_booking_resource_id = intval( $request_params['booking_gcal_resource'] ); $wpbc_Google_Calendar->setResource( $wpbc_booking_resource_id ); $wpbc_booking_resource_feed = get_booking_resource_attr( $wpbc_booking_resource_id ); $wpbc_booking_resource_feed = $wpbc_booking_resource_feed->import; $wpbc_Google_Calendar->setUrl( $wpbc_booking_resource_feed ); $import_result = $wpbc_Google_Calendar->run(); } else { // All resources $where = ''; // Where for the different situation: BL and MU if ( class_exists( 'wpdev_bk_multiuser' ) ) { // MultiUser - only specific booking resources for specific Regular User in Admin panel. $is_user_super_admin = apply_bk_filter( 'is_user_super_admin', $user_bk_id ); if ( ! $is_user_super_admin ) { $where .= ' WHERE users = ' . intval( $user_bk_id ) . ' '; } } $my_sql = "SELECT booking_type_id, import FROM {$wpdb->prefix}bookingtypes {$where}"; $types_list = $wpdb->get_results( $my_sql ); foreach ($types_list as $wpbc_booking_resource) { $wpbc_booking_resource_id = $wpbc_booking_resource->booking_type_id; $wpbc_booking_resource_feed = $wpbc_booking_resource->import; if ( ( ! empty( $wpbc_booking_resource_feed ) ) && ( $wpbc_booking_resource_feed != null ) && ( $wpbc_booking_resource_feed != '/' ) ) { $wpbc_Google_Calendar->setUrl( $wpbc_booking_resource_feed ); $wpbc_Google_Calendar->setResource( $wpbc_booking_resource_id ); $import_result = $wpbc_Google_Calendar->run(); } } } } if ( ( isset( $import_result ) ) && ( false != $import_result ) ) { $after_action_result = true; $after_action_message = sprintf( __( '%s new bookings have been imported', 'booking' ) , ' <span style="font-size:1em;"> <strong>' . count( $wpbc_Google_Calendar->events ) . '</strong> </span>' ) ; if ( 0 != count( $wpbc_Google_Calendar->events ) ) { $after_action_message .= '<br/><br/>' . __( 'The filter settings have been updated to reflect these imported bookings. The page will be reloaded.', 'booking' ); } if ( ! empty( $wpbc_Google_Calendar->getErrorMessage() ) ) { $after_action_message .= '<div style="max-width:60rem;margin:2em 10px;">' . $wpbc_Google_Calendar->getErrorMessage() . '</div>'; $return_array['after_action_result_delay'] = 100000000000000; } } else { $after_action_result = false; $after_action_message = __( 'No bookings have been imported.', 'booking' ) . '<br/><br/>' . sprintf( __( 'Please configure settings for import Google Calendar events', 'booking' ), '<b>', ',</b>' ) . ' <a href="' . wpbc_get_settings_url() . '&tab=sync&subtab=gcal' . '">' . __('here' ,'booking') . '.</a>' . '<br/><br/>' . $wpbc_Google_Calendar->getErrorMessage(); $return_array['after_action_result_delay'] = 100000000000000; } if ( 0 == count( $wpbc_Google_Calendar->events ) ) { $new_listing_params = false; } else { $new_listing_params = array( "sort" => "booking_id", "sort_type" => "DESC", "page_num" => 1, "page_items_count" => "50", "create_date" => "", "keyword" => "", "source" => "", "wh_booking_type" => array( "0" ), "wh_approved" => "", "wh_booking_date" => array( "3" ), "ui_wh_booking_date_radio" => 0, "ui_wh_booking_date_next" => 1, "ui_wh_booking_date_prior" => 1, "ui_wh_booking_date_checkin" => "", "ui_wh_booking_date_checkout" => "", "wh_what_bookings" => "imported", "wh_modification_date" => array( "1" ), "ui_wh_modification_date_prior" => "1", "ui_wh_modification_date_checkin" => "", "ui_wh_modification_date_checkout" => "", "wh_pay_status" => array( "all" ), "ui_wh_pay_status_radio" => "", "ui_wh_pay_status_custom" => "", "wh_cost" => "", "wh_cost2" => "", "wh_sort" => "booking_id__desc", "wh_trash" => "any", 'reload_url_params' => htmlspecialchars_decode( esc_url( wpbc_get_bookings_url() . '&view_mode=vm_booking_listing' ) ) ); } $return_array['after_action_result'] = $after_action_result; $return_array['after_action_message'] = $after_action_message; $return_array['new_listing_params'] = $new_listing_params; return $return_array; } function wpbc_booking_do_action__export_csv( $request_params, $params ){ global $wpdb; make_bk_action( 'check_multiuser_params_for_client_side_by_user_id', $params['user_id'] ); $booking_id_csd = $request_params['booking_id']; $booking_id_csd = wpbc_clean_digit_or_csd( $booking_id_csd ); if ( empty( $booking_id_csd ) ) { // Export all bookings (no selected bookings was in the listing } $export_type = $request_params['export_type']; // csv_page | csv_all // Is send email for this action ---------------------------------------------------------------------------------- $is_send_emeils = wpbc_ajx__user_request_option__is_send_emails( $params['user_id'] ); // ----------------------------------------------------------------------------------------------------------------- if ( ! isset( $_POST['search_params'] ) || empty( $_POST['search_params'] ) ) { $after_action_result = false; $after_action_message = __('Error', 'booking') . '! ' . 'Search parameters for CSV generating are empty.'; } else { $user_request = new WPBC_AJX__REQUEST( array( 'db_option_name' => 'booking_listing_request_params', 'user_id' => wpbc_get_current_user_id(), 'request_rules_structure' => wpbc_ajx_get__request_params__names_default() ) ); $request_prefix = 'search_params'; $request_params_for_listing = $user_request->get_sanitized__in_request__value_or_default( $request_prefix ); // NOT Direct: $_REQUEST['search_params']['resource_id'] // $data_arr = wpbc_ajx_get_booking_data_arr( $request_params_for_listing ); $export_csv_url = wpbc_csv_get_url_export( $request_params_for_listing ); $after_action_result = true; $after_action_message = __('Processing' ,'booking') . '... '; } $wpbc_ajx_locale = ( isset( $_REQUEST['wpbc_ajx_locale'] ) ) ? esc_js( $_REQUEST['wpbc_ajx_locale'] ) : 'en_US'; return array( 'export_csv_url' => $export_csv_url . '&export_type=' . $export_type . '&selected_id=' . $booking_id_csd . '&csv_export_separator=' . $request_params['csv_export_separator'] . '&csv_export_skip_fields=' . $request_params['csv_export_skip_fields'] . '&wpbc_ajx_locale=' . $wpbc_ajx_locale . '&wpbc_ajx_locale_reload=force' , 'after_action_result' => $after_action_result, 'after_action_message' => $after_action_message ); } // </editor-fold> // <editor-fold defaultstate="collapsed" desc=" == Button Actions Templates for UI == " > /** * Show Costs booking Test field */ function wpbc_for_booking_template__action_cost(){ if ( ! class_exists('wpdev_bk_biz_s') ) { return false; } $booking_action = 'set_booking_cost'; $el_id = 'ui_btn_' . $booking_action . '{{data.parsed_fields.booking_id}}'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $params_addon = array( 'type' => 'span' , 'label' => '{{{data[\'parsed_fields\'][\'currency_symbol\']}}}' , 'html' => '{{{data[\'parsed_fields\'][\'currency_symbol\']}}}'//''// '<i class="menu_icon icon-1x wpbc_icn_event"></i>' //'<strong>' . __( 'Dates', 'booking ' ) . '</strong>' //, 'icon' => array( 'icon_font' => 'wpbc_icn_event', 'position' => 'right', 'icon_img' => '' ) //, 'class' => 'wpbc_ui_button inactive' , 'style' => 'font-weight:600;font-size: 14px;line-height: 28px;' , 'attr' => array() ); $param_text = array( 'type' => 'text' , 'id' => $el_id . '_cost' , 'name' => $el_id . '_cost' , 'label' => '' , 'disabled' => false , 'class' => 'set_booking_cost_text_field' , 'style' => 'width:5em;font-weight:600;' , 'placeholder' => '0' , 'attr' => array() , 'is_escape_value' => false , 'value' => '{{data[\'parsed_fields\'][\'cost\']}}' , 'onfocus' => '' , 'onkeydown' => "jQuery('.ui__set_booking_cost__section_in_booking_{{data['parsed_fields']['booking_id']}}').show();" // JavaScript code ); ?><div class="ui_element ui_nowrap"><?php //wpbc_flex_addon( $params_addon ); wpbc_flex_label( $params_addon ); wpbc_flex_text( $param_text ); ?></div><?php $params_button_save = array( 'type' => 'button' , 'title' => __( 'Save cost', 'booking' ) . ' ', // Title of the button 'hint' => array( 'title' => __( 'Save Changes', 'booking' ), 'position' => 'top' ), // Hint 'link' => 'javascript:void(0)', // Direct link or skip it 'action' => "wpbc_ajx_booking__ui_click_save__set_booking_cost( {{data['parsed_fields']['booking_id']}}, this, '{$booking_action}', '{$el_id}' );" , 'style' => '', // Any CSS class here 'mobile_show_text' => true, // Show or hide text, when viewing on Mobile devices (small window size). 'icon' => array( 'icon_font' => 'wpbc_icn_check _circle_outline', 'position' => 'right', 'icon_img' => '' ), 'class' => 'wpbc_ui_button_primary', // '' | 'wpbc_ui_button_primary' 'attr' => array( 'id' => $el_id . '_save' ) ); $params_button_cancel = array( 'type' => 'button' , 'title' => __( 'Cancel', 'booking' ) . ' ', // Title of the button 'hint' => array( 'title' => __('Close' ,'booking'), 'position' => 'top' ), // Hint 'link' => 'javascript:void(0)', // Direct link or skip it 'action' => "wpbc_ajx_booking__ui_click_close__set_booking_cost();" , 'style' => '', // Any CSS class here 'mobile_show_text' => true, // Show or hide text, when viewing on Mobile devices (small window size). 'icon' => array( 'icon_font' => 'wpbc_icn_close _block', 'position' => 'right', 'icon_img' => '' ), 'class' => '', // '' | 'wpbc_ui_button_primary' 'attr' => array( 'id' => $el_id . '_cancel' ) ); ?><div class="ui_element ui_nowrap ui__set_booking_cost__section_in_booking ui__set_booking_cost__section_in_booking_{{data['parsed_fields']['booking_id']}}"><?php wpbc_flex_button( $params_button_save ); ?></div><?php ?><div class="ui_element ui_nowrap ui__set_booking_cost__section_in_booking ui__set_booking_cost__section_in_booking_{{data['parsed_fields']['booking_id']}}"><?php wpbc_flex_button( $params_button_cancel ); ?></div><?php } /** * Show Payment Request booking Button */ function wpbc_for_booking_template__action_payment_request(){ if ( ! class_exists('wpdev_bk_biz_s') ) { return false; } $booking_action = 'send_payment_request'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $params = array( 'type' => 'button', 'title' => '', 'hint' => array( 'title' => __( 'Send payment request to visitor', 'booking' ), 'position' => 'top' ), 'link' => 'javascript:void(0)', //'action' => "js_func( {{data['parsed_fields']['booking_id']}} );", 'action' => "if ( 'function' === typeof( jQuery('#wpbc_modal__payment_request__section').wpbc_my_modal ) ) { jQuery('#wpbc_modal__payment_request__booking_id').val({{data['parsed_fields']['booking_id']}}); jQuery('#wpbc_modal__payment_request__section').wpbc_my_modal('show'); } else { alert( 'Warning! wpbc_my_modal module has not found. Please, recheck about any conflicts by deactivating other plugins.'); }", 'icon' => array( 'icon_font' => 'wpbc_icn_forward_to_inbox', 'position' => 'left', 'icon_img' => '' ), 'class' => '', 'style' => '', 'mobile_show_text' => true, 'attr' => array() ); ?><div class="ui_element"><?php wpbc_flex_button( $params ); ?></div><?php } /** * Show Payment Status booking Button */ function wpbc_for_booking_template__action_set_payment_status(){ if ( ! class_exists('wpdev_bk_biz_s') ) { return false; } $booking_action = 'set_payment_status'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $params = array( 'type' => 'button', 'title' => '', 'hint' => array( 'title' => __( 'Payment status', 'booking' ), 'position' => 'top' ), 'link' => 'javascript:void(0)', 'action' => "wpbc_ajx_booking__ui_click_show__set_payment_status( {{data['parsed_fields']['booking_id']}} );", 'icon' => array( 'icon_font' => 'wpbc_icn_sell', 'position' => 'left', 'icon_img' => '' ), 'class' => '', 'style' => '', 'mobile_show_text' => true, 'attr' => array() ); ?><div class="ui_element"><?php wpbc_flex_button( $params ); ?></div><?php } /** * Selectbox | Save | Close buttons for "Payment status" section * @return false|void */ function wpbc_for_booking_template_section__set_payment_status(){ if ( ! class_exists('wpdev_bk_biz_s') ) { return false; } $booking_action = 'set_payment_status'; $el_id = 'ui_btn_' . $booking_action . '{{data.parsed_fields.booking_id}}'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $select_box_options = get_payment_status_titles(); $select_box_options = array_flip( $select_box_options ); $params_select = array( 'id' => $el_id // HTML ID of element , 'name' => $el_id , 'label' => ''//__( 'Payment status', 'booking' ) // Label (optional) , 'style' => '' // CSS of select element , 'class' => '' // CSS Class of select element , 'multiple' => false , 'attr' => array( 'data-placeholder' => __( 'Change status', 'booking' ), 'ajx-selected-value' => '{{data.parsed_fields.pay_status}}' ) , 'disabled' => false , 'disabled_options' => array() // If some options disabled, then it has to list here , 'options' => $select_box_options //, 'value' => "{{data['parsed_fields']['pay_status']}}"//isset( $escaped_search_request_params[ $el_id ] ) ? $escaped_search_request_params[ $el_id ] : $defaults[ $el_id ] // Some Value from options array that selected by default //, 'onfocus' => "console.log( 'ON FOCUS:', jQuery( this ).val(), 'in element:' , jQuery( this ) );" // JavaScript code //, 'onchange' => "console.log( 'ON CHANGE:', jQuery( this ).val(), 'in element:' , jQuery( this ) );" // JavaScript code ); $params_button_save = array( 'type' => 'button' , 'title' => __( 'Change status', 'booking' ) . ' ', // Title of the button 'hint' => array( 'title' => __( 'Save Changes', 'booking' ), 'position' => 'top' ), // Hint 'link' => 'javascript:void(0)', // Direct link or skip it 'action' => "wpbc_ajx_booking__ui_click_save__set_payment_status( {{data['parsed_fields']['booking_id']}}, this, '{$booking_action}', '{$el_id}' );" , 'style' => '', // Any CSS class here 'mobile_show_text' => true, // Show or hide text, when viewing on Mobile devices (small window size). 'icon' => array( 'icon_font' => 'wpbc_icn_check _circle_outline', 'position' => 'right', 'icon_img' => '' ), 'class' => 'wpbc_ui_button_primary', // '' | 'wpbc_ui_button_primary' 'attr' => array( 'id' => $el_id . '_save' ) ); $params_button_cancel = array( 'type' => 'button' , 'title' => __( 'Cancel', 'booking' ) . ' ', // Title of the button 'hint' => array( 'title' => __('Close' ,'booking'), 'position' => 'top' ), // Hint 'link' => 'javascript:void(0)', // Direct link or skip it 'action' => "wpbc_ajx_booking__ui_click_close__set_payment_status();" , 'style' => '', // Any CSS class here 'mobile_show_text' => true, // Show or hide text, when viewing on Mobile devices (small window size). 'icon' => array( 'icon_font' => 'wpbc_icn_close _block', 'position' => 'right', 'icon_img' => '' ), 'class' => '', // '' | 'wpbc_ui_button_primary' 'attr' => array( 'id' => $el_id . '_cancel' ) ); ?><div class="ui_element" style="flex:100%;"></div> <div id="ui__set_payment_status__section_in_booking_{{data['parsed_fields']['booking_id']}}" class="ui__set_payment_status__section_in_booking ui__under_actions_row__section_in_booking" > <div class="wpbc_ajx_toolbar wpbc_buttons_row wpbc_buttons_row_for_booking highlight_action_section"> <div class="ui_container ui_container_small"> <div class="ui_group"> <div class="ui_element"> <?php wpbc_flex_select($params_select); ?> </div> <div class="ui_element" > <?php wpbc_flex_button($params_button_save); ?> </div> <div class="ui_element"> <?php wpbc_flex_button($params_button_cancel); ?> </div> </div> </div> </div> <div class="clear"></div> </div><?php } /** * Show Edit booking Button */ function wpbc_for_booking_template__action_edit_booking(){ //FixIn: 9.2.3.4 // if ( ! class_exists('wpdev_bk_personal') ) { // return false; // } $booking_action = 'edit_booking'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $edit_booking_url = 'admin.php?page=' . wpbc_get_new_booking_url( false, false) . '&booking_type={{data.parsed_fields.resource_id}}&booking_hash={{data.parsed_fields.hash}}&parent_res=1' ; $edit_booking_url .= ( 'Off' !== get_bk_option( 'booking_is_resource_no_update__during_editing' ) ) ? '&resource_no_update=1' : ''; //FixIn: 9.4.2.3 $edit_booking_url .= '&booking_form={{data.parsed_fields.wpbc_custom_booking_form}}'; //FixIn: 9.4.3.12 $edit_booking_url .= '&is_show_payment_form=Off'; //FixIn: 9.9.0.38 $params = array( 'type' => 'button', 'title' => '', 'hint' => array( 'title' => __( 'Edit Booking', 'booking' ), 'position' => 'top' ), 'link' => $edit_booking_url,//'javascript:void(0)', 'action' => '',//"js_func( {{data['parsed_fields']['booking_id']}} );", 'icon' => array( 'icon_font' => 'wpbc_icn_draw', 'position' => 'left', 'icon_img' => '' ), 'class' => '', 'style' => '', 'mobile_show_text' => true, 'attr' => array() ); ?><div class="ui_element <# if ( '' == data['parsed_fields']['hash']) { #>disabled<# } #>"><?php wpbc_flex_button( $params ); ?></div><?php } /** * Show Change booking resource for booking Button */ function wpbc_for_booking_template__action_change_resource(){ if ( ! class_exists('wpdev_bk_personal') ) { return false; } $booking_action = 'change_booking_resource'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $params = array( 'type' => 'button', 'title' => '', 'hint' => array( 'title' => __( 'Change Resource', 'booking' ), 'position' => 'top' ), 'link' => 'javascript:void(0)', 'action' => "wpbc_ajx_booking__ui_click_show__change_resource( {{data['parsed_fields']['booking_id']}}, {{data['parsed_fields']['resource_id']}} );", 'icon' => array( 'icon_font' => 'wpbc_icn_shuffle', 'position' => 'left', 'icon_img' => '' ), 'class' => '', 'style' => '', 'mobile_show_text' => true, 'attr' => array() ); ?><div class="ui_element"><?php wpbc_flex_button( $params ); ?></div><?php } /** * Selectbox | Save | Close buttons for "Change booking resources" section * @return false|void */ function wpbc_for_booking_template_section__change_booking_resource(){ if ( ! class_exists('wpdev_bk_personal') ) { return false; } $booking_action = 'change_booking_resource'; $el_id = 'ui_btn_' . $booking_action; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } ?><div class="ui_element" style="flex:100%;"></div> <div id="ui__change_booking_resource__section_in_booking_{{data['parsed_fields']['booking_id']}}" class="ui__change_booking_resource__section_in_booking ui__under_actions_row__section_in_booking" ></div><?php } /** * Show Duplicate booking Button */ function wpbc_for_booking_template__action_duplicate_booking_to_other_resource(){ if ( ! class_exists('wpdev_bk_personal') ) { return false; } $booking_action = 'duplicate_booking_to_other_resource'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $params = array( 'type' => 'button', 'title' => '', 'hint' => array( 'title' => __( 'Duplicate Booking', 'booking' ), 'position' => 'top' ), 'link' => 'javascript:void(0)', 'action' => "wpbc_ajx_booking__ui_click_show__duplicate_booking( {{data['parsed_fields']['booking_id']}}, {{data['parsed_fields']['resource_id']}} );", 'icon' => array( 'icon_font' => 'wpbc_icn_content_copy', 'position' => 'left', 'icon_img' => '' ), 'class' => '', 'style' => '', 'mobile_show_text' => true, 'attr' => array() ); ?><div class="ui_element"><?php wpbc_flex_button( $params ); ?></div><?php } /** * Selectbox | Save | Close buttons for "Duplicate booking" section * @return false|void */ function wpbc_for_booking_template_section__duplicate_booking_to_other_resource(){ if ( ! class_exists('wpdev_bk_personal') ) { return false; } $booking_action = 'duplicate_booking_to_other_resource'; $el_id = 'ui_btn_' . $booking_action; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } ?><div class="ui_element" style="flex:100%;"></div> <div id="ui__duplicate_booking_to_other_resource__section_in_booking_{{data['parsed_fields']['booking_id']}}" class="ui__duplicate_booking_to_other_resource__section_in_booking ui__under_actions_row__section_in_booking" ></div><?php } /** * Show Print booking Button */ function wpbc_for_booking_template__action_print(){ if ( ! class_exists('wpdev_bk_personal') ) { //return false; } $booking_action = 'set_print'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $params = array( 'type' => 'button', 'title' => '', 'hint' => array( 'title' => __( 'Print', 'booking' ), 'position' => 'top' ), 'link' => 'javascript:void(0)', 'action' => "wpbc_print_dialog__show( {{data['parsed_fields']['booking_id']}} );", 'icon' => array( 'icon_font' => 'wpbc_icn_print', 'position' => 'left', 'icon_img' => '' ), 'class' => '', 'style' => '', 'mobile_show_text' => true, 'attr' => array() ); ?><div class="ui_element"><?php wpbc_flex_button( $params ); ?></div><?php } /** * Show Remark booking Button */ function wpbc_for_booking_template__action_remark(){ if ( ! class_exists('wpdev_bk_personal') ) { return false; } $booking_action = 'set_booking_note'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $params = array( 'type' => 'button', 'title' => '', 'hint' => array( 'title' => __( 'Edit Note', 'booking' ), 'position' => 'top' ), 'link' => 'javascript:void(0)', 'action' => "wpbc_ajx_booking__ui_click__remark( jQuery( this ) );", 'icon' => array( 'icon_font' => 'wpbc_icn_mode_comment', 'position' => 'left', 'icon_img' => '' ), 'class' => "{$booking_action}_button", 'style' => '', 'mobile_show_text' => true, 'attr' => array( 'id' => "{$booking_action}_button{{data.parsed_fields.booking_id}}" ) ); ?><div class="ui_element"><?php wpbc_flex_button( $params ); ?></div><?php } function wpbc_for_booking_template_section__action_remark_textarea(){ if ( ! class_exists('wpdev_bk_personal') ) { return false; } $booking_action = 'set_booking_note'; $el_id = 'ui_btn_' . $booking_action; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $params_textarea = array( 'id' => "{$booking_action}_text_{{data.parsed_fields.booking_id}}" // HTML ID of element , 'name' => "{$booking_action}_text_{{data.parsed_fields.booking_id}}" // HTML ID of element , 'label' => '' , 'style' => 'height: 8em; width: 100%;' // CSS of select element , 'class' => "{$booking_action}_text" // CSS Class of select element , 'disabled' => false , 'attr' => array() // Any additional attributes, if this radio | checkbox element , 'rows' => '3' , 'cols' => '50' , 'placeholder' => '' , 'value' => '{{{data.parsed_fields.remark}}}' //FixIn: 9.4.4.1 , 'is_escape_value' => true //, 'onfocus' => "console.log( 'ON FOCUS:', jQuery( this ).val() , 'in element:' , jQuery( this ) );" // JavaScript code //, 'onchange' => "console.log( 'ON CHANGE:', jQuery( this ).val() , 'in element:' , jQuery( this ) );" // JavaScript code ); $params_button_save = array( 'type' => 'button' , 'title' => __( 'Save', 'booking' ) . ' ', // Title of the button 'hint' => array( 'title' => __( 'Save Changes', 'booking' ), 'position' => 'top' ), // Hint 'link' => 'javascript:void(0)', // Direct link or skip it 'action' => "wpbc_ajx_booking_ajax_action_request( { 'booking_action' : '{$booking_action}', 'booking_id' : {{data.parsed_fields.booking_id}}, 'remark' : jQuery( '#{$booking_action}_text_{{data.parsed_fields.booking_id}}' ).val(), 'ui_clicked_element_id': '{$el_id}' } ); wpbc_button_enable_loading_icon( this ); " , 'style' => '', // Any CSS class here 'mobile_show_text' => true, // Show or hide text, when viewing on Mobile devices (small window size). 'icon' => array( 'icon_font' => 'wpbc_icn_check _circle_outline', 'position' => 'right', 'icon_img' => '' ), 'class' => 'wpbc_ui_button_primary', // '' | 'wpbc_ui_button_primary' 'attr' => array( 'id' => $el_id ) ); $params_button_cancel = array( 'type' => 'button' , 'title' => __( 'Cancel', 'booking' ) . ' ', // Title of the button 'hint' => array( 'title' => __('Close' ,'booking'), 'position' => 'top' ), // Hint 'link' => 'javascript:void(0)', // Direct link or skip it 'action' => "wpbc_ajx_booking__ui_click__remark( jQuery( '#{$booking_action}_button{{data.parsed_fields.booking_id}}' ) );" , 'style' => '', // Any CSS class here 'mobile_show_text' => true, // Show or hide text, when viewing on Mobile devices (small window size). 'icon' => array( 'icon_font' => 'wpbc_icn_close _block', 'position' => 'right', 'icon_img' => '' ), 'class' => '', // '' | 'wpbc_ui_button_primary' 'attr' => array( 'id' => $el_id . '_cancel' ) ); //$user_id = ( isset( $_REQUEST['wpbc_ajx_user_id'] ) ) ? intval( $_REQUEST['wpbc_ajx_user_id'] ) : wpbc_get_current_user_id(); //$is_expand_remarks = wpbc_ajx__user_request_option__is_expand_remarks( $user_id ); ?><div class="ui_remark_section is_expand_remarks_<?php //echo ($is_expand_remarks) ? 'on' : 'off'; ?>" style="<# if ( 'Off' === wpbc_ajx_booking_listing.search_get_param('ui_usr__is_expand_remarks') ) { #>display: none;<# } #>" ><?php wpbc_flex_textarea( $params_textarea ); ?><div class="ui_group"><?php ?><div class="ui_element" ><?php wpbc_flex_button($params_button_save); ?></div><?php ?><div class="ui_element"><?php wpbc_flex_button($params_button_cancel); ?></div><?php ?></div><?php ?></div><?php } /** * Show Locale booking Button */ function wpbc_for_booking_template__action_locale(){ $booking_action = 'set_booking_locale'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } ?><span class="ui_element_locale"><?php $params = array( 'type' => 'button', 'id' => "button_locale_for_booking{{data['parsed_fields']['booking_id']}}", 'title' => '', 'hint' => array( 'title' => __( 'Change Language', 'booking' ), 'position' => 'top' ), 'link' => 'javascript:void(0)', 'action' => "jQuery('#locale_for_booking{{data[\'parsed_fields\'][\'booking_id\']}}').toggle();jQuery(this).hide();", 'icon' => array( 'icon_font' => 'wpbc_icn_language', 'position' => 'left', 'icon_img' => '' ), 'class' => 'set_booking_locale_button', 'style' => '', 'mobile_show_text' => true, 'attr' => array() ); ?><div class="ui_element"><?php wpbc_flex_button( $params ); ?></div><?php $el_id = "locale_for_booking{{data.parsed_fields.booking_id}}"; ?><# var selected_locale_value = ''; if ( ( 'undefined' !== typeof( data.parsed_fields.booking_options) ) && ( 'undefined' !== typeof( data.parsed_fields.booking_options.booking_meta_locale ) ) ){ var selected_locale_value = data.parsed_fields.booking_options.booking_meta_locale; } #><?php $availbale_locales_in_system = get_available_languages(); $select_box_options = array(); $select_box_options[''] = __( 'Default Locale', 'booking' ); $select_box_options['en_US'] = 'English (United States)'; foreach ( $availbale_locales_in_system as $locale ) { $select_box_options[$locale] = $locale; } $params_select = array( 'id' => $el_id // HTML ID of element , 'name' => $el_id , 'label' => '' // __( 'Next Days', 'booking' ) // Label (optional) , 'style' => 'display: none;' // CSS of select element , 'class' => 'set_booking_locale_selectbox' // CSS Class of select element //, 'multiple' => true , 'attr' => array( 'value_of_selected_option' => '{{selected_locale_value}}' ) // Any additional attributes, if this radio | checkbox element , 'disabled' => false , 'disabled_options' => array() // If some options disabled, then it has to list here , 'options' => $select_box_options //, 'value' => isset( $escaped_search_request_params[ $el_id ] ) ? $escaped_search_request_params[ $el_id ] : $defaults[ $el_id ] // Some Value from options array that selected by default //, 'onfocus' => "console.log( 'ON FOCUS:', jQuery( this ).val(), 'in element:' , jQuery( this ) );" // JavaScript code , 'onchange' => "jQuery(this).hide(); var jButton = jQuery('#button_locale_for_booking{{data[\'parsed_fields\'][\'booking_id\']}}'); jButton.show(); wpbc_button_enable_loading_icon( jButton.get(0) ); " . " wpbc_ajx_booking_ajax_action_request( { 'booking_action' : '{$booking_action}', 'booking_id' : {{data[\'parsed_fields\'][\'booking_id\']}}, 'booking_meta_locale' : jQuery('#locale_for_booking{{data[\'parsed_fields\'][\'booking_id\']}} option:selected').val() } );" ); ?><div class="ui_element"><?php wpbc_flex_select( $params_select ); ?></div><?php ?></span><?php } /** * Show "Add to Google Calendar" booking Button */ function wpbc_for_booking_template__action_add_google_calendar(){ $booking_action = 'booking_add_google_calendar'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $params = array( 'type' => 'button', 'title' => '', 'hint' => array( 'title' => __( 'Add to Google Calendar', 'booking' ), 'position' => 'top' ), 'link' => "{{{data['parsed_fields']['google_calendar_link']}}}", // "{{{encodeURIComponent(data['parsed_fields']['google_calendar_link'])}}}", 'options' => array( 'link' => 'no_decode' ), //'link' => 'javascript:void(0)', //'action' => " wpbc_ajx_booking_ajax_action_request( { // 'booking_action' : '{$booking_action}', // 'booking_id' : {{data['parsed_fields']['booking_id']}} // } ); // ", 'icon' => array( 'icon_font' => 'wpbc_icn_event', 'position' => 'left', 'icon_img' => '' ), 'class' => '', 'style' => '', 'mobile_show_text' => true, 'attr' => array('target'=>'_blank') ); ?><div class="ui_element"><?php wpbc_flex_button( $params ); ?></div><?php } /** * Show Trash booking Button */ function wpbc_for_booking_template__action_trash(){ $booking_action = 'move_booking_to_trash'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $params = array( 'type' => 'button', 'hint' => array( 'title' => __( 'Reject - move to trash', 'booking' ), 'position' => 'top' ), 'title' => '', 'link' => 'javascript:void(0)', 'action' => "if ( wpbc_are_you_sure('" . esc_attr( __( 'Do you really want to do this ?', 'booking' ) ) . "') ) { wpbc_ajx_booking_ajax_action_request( { 'booking_action' : '{$booking_action}', 'booking_id' : {{data['parsed_fields']['booking_id']}} } ); wpbc_button_enable_loading_icon( this ); }", 'icon' => array( 'icon_font' => 'wpbc_icn_delete_outline', 'position' => 'left', 'icon_img' => '' ), 'class' => '', 'style' => '', 'mobile_show_text' => true, 'attr' => array() ); ?><# if ( '0' == data['parsed_fields']['trash']) { #><?php ?><div class="ui_element"><?php wpbc_flex_button( $params ); ?></div><?php ?><# } #><?php } /** * Show Restore from Trash booking Button */ function wpbc_for_booking_template__action_trash_restore(){ $booking_action = 'restore_booking_from_trash'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $params = array( 'type' => 'button', 'hint' => array( 'title' => __( 'Restore', 'booking' ), 'position' => 'top' ), 'title' => '', 'link' => 'javascript:void(0)', 'action' => "if ( wpbc_are_you_sure('" . esc_attr( __( 'Do you really want to do this ?', 'booking' ) ) . "') ) { wpbc_ajx_booking_ajax_action_request( { 'booking_action' : '{$booking_action}', 'booking_id' : {{data['parsed_fields']['booking_id']}} } ); wpbc_button_enable_loading_icon( this ); }", 'icon' => array( 'icon_font' => 'wpbc_icn_rotate_left', 'position' => 'left', 'icon_img' => '' ), 'class' => '', 'style' => '', 'mobile_show_text' => true, 'attr' => array() ); ?><# if ( '1' == data['parsed_fields']['trash']) { #><?php ?><div class="ui_element"><?php wpbc_flex_button( $params ); ?></div><?php ?><# } #><?php } /** * Show Completely Delete booking Button */ function wpbc_for_booking_template__action_delete(){ $booking_action = 'delete_booking_completely'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $params = array( 'type' => 'button', 'hint' => array( 'title' => __( 'Completely Delete', 'booking' ), 'position' => 'top' ), 'title' => '', 'link' => 'javascript:void(0)', 'action' => "if ( wpbc_are_you_sure('" . esc_attr( __( 'Do you really want to delete this booking ?', 'booking' ) ) . "') ) { wpbc_ajx_booking_ajax_action_request( { 'booking_action' : '{$booking_action}', 'booking_id' : {{data['parsed_fields']['booking_id']}} } ); wpbc_button_enable_loading_icon( this ); }", 'icon' => array( 'icon_font' => 'wpbc_icn_close', 'position' => 'left', 'icon_img' => '' ), 'class' => '', 'style' => '', 'mobile_show_text' => true, 'attr' => array() ); ?><# if ( '1' == data['parsed_fields']['trash']) { #><?php ?><div class="ui_element"><?php wpbc_flex_button( $params ); ?></div><?php ?><# } #><?php } /** * Show Approved booking Button */ function wpbc_for_booking_template__action_approved(){ $booking_action = 'set_booking_approved'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $params = array( 'type' => 'button', 'title' => '', 'hint' => array( 'title' => __( 'Approve', 'booking' ), 'position' => 'top' ), 'link' => 'javascript:void(0)', 'action' => "wpbc_ajx_booking_ajax_action_request( { 'booking_action' : '{$booking_action}', 'booking_id' : {{data['parsed_fields']['booking_id']}} } ); wpbc_button_enable_loading_icon( this ); ", 'icon' => array( 'icon_font' => 'wpbc_icn_check_circle_outline', 'position' => 'left', 'icon_img' => '' ), 'class' => '', 'style' => '', 'mobile_show_text' => true, 'attr' => array() ); ?><# if ( '0' == data['approved']) { #><?php ?><div class="ui_element"><?php wpbc_flex_button( $params ); ?></div><?php ?><# } #><?php } /** * Show Pending booking Button */ function wpbc_for_booking_template__action_pending(){ $booking_action = 'set_booking_pending'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $params = array( 'type' => 'button', 'title' => '', 'hint' => array( 'title' => __( 'Pending', 'booking' ), 'position' => 'top' ), 'link' => 'javascript:void(0)', 'action' => "if ( wpbc_are_you_sure('" . esc_attr( __( 'Do you really want to set booking as pending ?', 'booking' ) ) . "') ) { wpbc_ajx_booking_ajax_action_request( { 'booking_action' : '{$booking_action}', 'booking_id' : {{data['parsed_fields']['booking_id']}} } ); wpbc_button_enable_loading_icon( this ); }", 'icon' => array( 'icon_font' => 'wpbc_icn_block', 'position' => 'left', 'icon_img' => '' ), 'class' => '', 'style' => '', 'mobile_show_text' => true, 'attr' => array() ); ?><# if ( '1' == data['approved']) { #><?php ?><div class="ui_element"><?php wpbc_flex_button( $params ); ?></div><?php ?><# } #><?php } /** * Show Read booking Button */ function wpbc_for_booking_template__action_read(){ $booking_action = 'set_booking_as_read'; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { return false; } $params = array( 'type' => 'button', 'title' => '', 'hint' => array( 'title' => __( 'New booking', 'booking' ), 'position' => 'top' ), 'link' => 'javascript:void(0)', 'action' => " wpbc_ajx_booking_ajax_action_request( { 'booking_action' : '{$booking_action}', 'booking_id' : {{data['parsed_fields']['booking_id']}} } ); wpbc_button_enable_loading_icon( this ); ", 'icon' => array( 'icon_font' => 'wpbc_icn_visibility', 'position' => 'left', 'icon_img' => '' ), 'class' => 'wpbc_is_new_button', 'style' => '', 'mobile_show_text' => true, 'attr' => array() ); ?><# if ( '1' == data.parsed_fields.is_new ) { #><?php wpbc_flex_button( $params ); ?><# } #><?php } // </editor-fold> // <editor-fold defaultstate="collapsed" desc=" == Hidden Templates for sub action sections == " > /** * Hidden Templates for - Booking Actions * * @param $page * * @return void */ function wpbc_for_booking_template__hidden_templates( $page ){ // page=wpbc&view_mode=vm_booking_listing if ( 'wpbc-ajx_booking' === $page ) { // it's from >> do_action( 'wpbc_hook_settings_page_footer', 'wpbc-ajx_booking' ); ?><div class="wpbc_hidden_templates"><?php wpbc_hidden_template__change_booking_resource(); wpbc_hidden_template__duplicate_booking_to_other_resource(); ?></div><?php wpbc_hidden_template__content_for_modal_payment_request(); wpbc_hidden_template__content_for_modal_import_google_calendar(); wpbc_hidden_template__content_for_modal_export_csv(); do_action( 'wpbc_hook_booking_template__hidden_templates' ); //FixIn: 9.2.3.6 } } if ( 'vm_booking_listing' == wpbc_ajx_booking_listing__get_default_view_mode() ) { //if ( strpos( $_SERVER['REQUEST_URI'], 'view_mode=vm_booking_listing' ) !== false ) { // Load only at AJX_Bookings Settings Page add_action( 'wpbc_hook_settings_page_footer', 'wpbc_for_booking_template__hidden_templates' ); } /** * Hidden template -- Change booking resources * * We need to have such hidden template for generating select box for booking resource only once, while we show Listing. * It's called each time from wpbc_ajx_define_templates__resource_manipulation() in wpbc_ajx_booking_show_listing() * So we renew booking resource list with each Ajax request for Booking Listing. * * @return void */ function wpbc_hidden_template__change_booking_resource(){ // Here will be composed template with real HTML defined in "booking_listing.js" file in function wpbc_ajx_booking_show_listing( ... ?><div id="wpbc_hidden_template__change_booking_resource"></div><?php // Template ?><script type="text/html" id="tmpl-wpbc_ajx_change_booking_resource"><?php if ( ! class_exists('wpdev_bk_personal') ) { echo '</script>'; return false; } /* ?><# console.log( ' == TEMPLATE PARAMS "wpbc_ajx_change_booking_resource" == ', data ); #><?php */ $booking_action = 'change_booking_resource'; $el_id = 'ui_btn_' . $booking_action; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { echo '</script>'; return false; } $params_button_save = array( 'type' => 'button' , 'title' => __( 'Change', 'booking' ) . ' ', // Title of the button 'hint' => array( 'title' => __( 'Save Changes', 'booking' ), 'position' => 'top' ), // Hint 'link' => 'javascript:void(0)', // Direct link or skip it 'action' => "wpbc_ajx_booking__ui_click_save__change_resource( this, '{$booking_action}', '{$el_id}' );" , 'style' => '', // Any CSS class here 'mobile_show_text' => true, // Show or hide text, when viewing on Mobile devices (small window size). 'icon' => array( 'icon_font' => 'wpbc_icn_check _circle_outline', 'position' => 'right', 'icon_img' => '' ), 'class' => 'wpbc_ui_button_primary', // '' | 'wpbc_ui_button_primary' 'attr' => array( 'id' => $el_id ) ); $params_button_cancel = array( 'type' => 'button' , 'title' => __( 'Cancel', 'booking' ) . ' ', // Title of the button 'hint' => array( 'title' => __('Close' ,'booking'), 'position' => 'top' ), // Hint 'link' => 'javascript:void(0)', // Direct link or skip it 'action' => "wpbc_ajx_booking__ui_click_close__change_resource();" , 'style' => '', // Any CSS class here 'mobile_show_text' => true, // Show or hide text, when viewing on Mobile devices (small window size). 'icon' => array( 'icon_font' => 'wpbc_icn_close _block', 'position' => 'right', 'icon_img' => '' ), 'class' => '', // '' | 'wpbc_ui_button_primary' 'attr' => array( 'id' => $el_id . '_cancel' ) ); ?><div id="change_booking_resource__section" class="highlight_action_section"> <div class="wpbc_ajx_toolbar wpbc_buttons_row wpbc_buttons_row_for_booking"> <div class="ui_container ui_container_small"> <div class="ui_group"> <input type="hidden" value="" id="change_booking_resource__booking_id" /> <div class="ui_element"> <select id="change_booking_resource__resource_select" name="change_booking_resource__resource_select" class="wpbc_ui_control wpbc_ui_select change_booking_resource_selectbox"> <# <?php if (0) { ?><script type="text/javascript"><?php /* Hack for showing JavaScript syntax */ } ?> _.each( data.ajx_booking_resources, function ( p_resource, p_resource_id, p_data ){ #><option value="{{p_resource.booking_type_id}}" style="<# if( undefined != p_resource.parent ) { if( '0' == p_resource.parent ) { #>font-weight:600;<# } else { #>font-size:0.95em;padding-left:20px;<# } } #>" ><# if( undefined != p_resource.parent ) { if( '0' != p_resource.parent ) { #> <# } } #>{{p_resource.title}}</option><# }); <?php if (0) { ?></script><?php /* Hack for showing JavaScript syntax */ } ?> #> </select> </div> <div class="ui_element" > <?php wpbc_flex_button($params_button_save); ?> </div> <div class="ui_element"> <?php wpbc_flex_button($params_button_cancel); ?> </div> </div> </div> </div> <div class="clear"></div> </div> </script><?php } /** * Hidden template -- Duplicate booking to other resources * * We need to have such hidden template for generating select box for booking resource only once, while we show Listing. * It's called each time from wpbc_ajx_define_templates__resource_manipulation() in wpbc_ajx_booking_show_listing() * So we renew booking resource list with each Ajax request for Booking Listing. * * @return void */ function wpbc_hidden_template__duplicate_booking_to_other_resource(){ // Here will be composed template with real HTML defined in "booking_listing.js" file in function wpbc_ajx_booking_show_listing( ... ?><div id="wpbc_hidden_template__duplicate_booking_to_other_resource"></div><?php // Template ?><script type="text/html" id="tmpl-wpbc_ajx_duplicate_booking_to_other_resource"><?php if ( ! class_exists('wpdev_bk_personal') ) { echo '</script>'; return false; } /* ?><# console.log( ' == TEMPLATE PARAMS "wpbc_ajx_duplicate_booking_to_other_resource" == ', data ); #><?php /**/ $booking_action = 'duplicate_booking_to_other_resource'; $el_id = 'ui_btn_' . $booking_action; if ( ! wpbc_is_user_can( $booking_action, wpbc_get_current_user_id() ) ) { echo '</script>'; return false; } $params_button_save = array( 'type' => 'button' , 'title' => __( 'Duplicate Booking', 'booking' ) . ' ', // Title of the button 'hint' => array( 'title' => __( 'Save Changes', 'booking' ), 'position' => 'top' ), // Hint 'link' => 'javascript:void(0)', // Direct link or skip it 'action' => "wpbc_ajx_booking__ui_click_save__duplicate_booking( this, '{$booking_action}', '{$el_id}' );" , 'style' => '', // Any CSS class here 'mobile_show_text' => true, // Show or hide text, when viewing on Mobile devices (small window size). 'icon' => array( 'icon_font' => 'wpbc_icn_check _circle_outline', 'position' => 'right', 'icon_img' => '' ), 'class' => 'wpbc_ui_button_primary', // '' | 'wpbc_ui_button_primary' 'attr' => array( 'id' => $el_id ) ); $params_button_cancel = array( 'type' => 'button' , 'title' => __( 'Cancel', 'booking' ) . ' ', // Title of the button 'hint' => array( 'title' => __('Close' ,'booking'), 'position' => 'top' ), // Hint 'link' => 'javascript:void(0)', // Direct link or skip it 'action' => "wpbc_ajx_booking__ui_click_close__duplicate_booking();" , 'style' => '', // Any CSS class here 'mobile_show_text' => true, // Show or hide text, when viewing on Mobile devices (small window size). 'icon' => array( 'icon_font' => 'wpbc_icn_close _block', 'position' => 'right', 'icon_img' => '' ), 'class' => '', // '' | 'wpbc_ui_button_primary' 'attr' => array( 'id' => $el_id . '_cancel' ) ); ?><div id="duplicate_booking_to_other_resource__section" class="highlight_action_section"> <div class="wpbc_ajx_toolbar wpbc_buttons_row wpbc_buttons_row_for_booking"> <div class="ui_container ui_container_small"> <div class="ui_group"> <input type="hidden" value="" id="duplicate_booking_to_other_resource__booking_id" /> <div class="ui_element"> <select id="duplicate_booking_to_other_resource__resource_select" name="duplicate_booking_to_other_resource__resource_select" class="wpbc_ui_control wpbc_ui_select duplicate_booking_to_other_resource_selectbox"> <# <?php if (0) { ?><script><?php /* Hack for showing JavaScript syntax */ } ?> _.each( data.ajx_booking_resources, function ( p_resource, p_resource_id, p_data ){ #><option value="{{p_resource.booking_type_id}}" style="<# if( undefined != p_resource.parent ) { if( '0' == p_resource.parent ) { #>font-weight:600;<# } else { #>font-size:0.95em;padding-left:20px;<# } } #>" ><# if( undefined != p_resource.parent ) { if( '0' != p_resource.parent ) { #> <# } } #>{{p_resource.title}}</option><# }); <?php if (0) { ?></script><?php /* Hack for showing JavaScript syntax */ } ?> #> </select> </div> <div class="ui_element" > <?php wpbc_flex_button($params_button_save); ?> </div> <div class="ui_element"> <?php wpbc_flex_button($params_button_cancel); ?> </div> </div> </div> </div> <div class="clear"></div> </div> </script><?php } /** Payment Request Layout - Modal Window structure */ function wpbc_hidden_template__content_for_modal_payment_request() { if ( ! class_exists('wpdev_bk_biz_s') ) { return false; } ?><span class="wpdevelop"> <div id="wpbc_modal__payment_request__section" class="modal wpbc_popup_modal" tabindex="-1" role="dialog"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title"><?php _e('Send payment request to customer' ,'booking'); ?></h4> </div> <div class="modal-body"> <textarea id="wpbc_modal__payment_request__reason_of_action" name="wpbc_modal__payment_request__reason_of_action" style="width:100%;" cols="87" rows="5"></textarea> <label class="help-block"><?php printf(__('Type your %sreason for payment%s request' ,'booking'),'<b>',',</b>');?></label> <input type="hidden" id="wpbc_modal__payment_request__booking_id" value="" /> </div> <div class="modal-footer"> <a id="wpbc_modal__payment_request__button_send" class="button button-primary" onclick="javascript: wpbc_ajx_booking__ui_click__send_payment_request();" href="javascript:void(0);" ><?php _e('Send Request' ,'booking'); ?></a> <a href="javascript:void(0)" class="button button-secondary" data-dismiss="modal"><?php _e('Close' ,'booking'); ?></a> </div> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal --> </span><?php } /** Payment Request Loyout - Modal Window structure */ function wpbc_hidden_template__content_for_modal_import_google_calendar() { ?><span class="wpdevelop"><?php $booking_gcal_feed = get_bk_option( 'booking_gcal_feed'); $is_this_btn_disabled = false; if ( ( ! class_exists('wpdev_bk_personal') ) && ( $booking_gcal_feed == '' ) ) { $is_this_btn_disabled = true; $settigns_link = wpbc_get_settings_url() . "&tab=sync&subtab=gcal"; } else { $booking_gcal_events_from = get_bk_option( 'booking_gcal_events_from' ); $booking_gcal_events_from_offset = get_bk_option( 'booking_gcal_events_from_offset' ); $booking_gcal_events_from_offset_type = get_bk_option( 'booking_gcal_events_from_offset_type' ); $booking_gcal_events_until = get_bk_option( 'booking_gcal_events_until' ); $booking_gcal_events_until_offset = get_bk_option( 'booking_gcal_events_until_offset' ); $booking_gcal_events_until_offset_type = get_bk_option( 'booking_gcal_events_until_offset_type' ); $booking_gcal_events_max = get_bk_option( 'booking_gcal_events_max' ); // $booking_gcal_timezone = get_bk_option( 'booking_gcal_timezone'); } ?><div id="wpbc_modal__import_google_calendar__section" class="modal wpbc_popup_modal wpbc_modal__import_google_calendar__section" tabindex="-1" role="dialog"> <div class="modal-dialog modal-lg"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title"><?php if ( $is_this_btn_disabled ) _e('Warning!' ,'booking'); else _e('Retrieve Google Calendar Events ' ,'booking'); ?></h4> </div> <div class="modal-body"> <?php if ($is_this_btn_disabled) { ?> <label class="help-block" style="display:block;"> <?php printf(__('Please configure settings for import Google Calendar events' ,'booking'),'<b>',',</b>'); ?> <a href="<?php echo $settigns_link; ?>"><?php _e('here' ,'booking');?></a> </label> <?php } else { ?> <table class="visibility_gcal_feeds_settings form-table0 settings-table0 table" > <tbody> <?php if ( function_exists('wpbc_gcal_settings_content_field_selection_booking_resources') ) wpbc_gcal_settings_content_field_selection_booking_resources(); else { ?><input type="hidden" name="wpbc_booking_resource" id="wpbc_booking_resource" value="" /><?php } wpbc_gcal_settings_content_field_from( $booking_gcal_events_from, $booking_gcal_events_from_offset, $booking_gcal_events_from_offset_type ); wpbc_gcal_settings_content_field_until( $booking_gcal_events_until, $booking_gcal_events_until_offset, $booking_gcal_events_until_offset_type ); wpbc_gcal_settings_content_field_max_feeds( $booking_gcal_events_max ); // wpbc_gcal_settings_content_field_timezone($booking_gcal_timezone); ?> </tbody> </table> <?php } ?> </div> <div class="modal-footer" style="text-align:center;"> <?php if ($is_this_btn_disabled) { ?> <a href="<?php echo $settigns_link; ?>" class="button button-primary" style="float:none;" > <?php _e('Configure' ,'booking'); ?> </a> <?php } else { ?> <a href="javascript:void(0)" class="button button-primary" style="float:none;" id="wpbc_modal__import_google_calendar__button_send" onclick="javascript:wpbc_ajx_booking__ui_click__import_google_calendar();jQuery('#wpbc_modal__import_google_calendar__section').wpbc_my_modal('hide');" ><?php _e('Import Google Calendar Events' ,'booking'); ?></a> <?php } ?> <a href="javascript:void(0)" class="button" style="float:none;" data-dismiss="modal"><?php _e('Close' ,'booking'); ?></a> </div> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal --> <?php ?></span><?php } /** Payment Request Layout - Modal Window structure */ function wpbc_hidden_template__content_for_modal_export_csv() { if ( ! class_exists('wpdev_bk_personal') ) { return false; } $user_id = ( isset( $_REQUEST['wpbc_ajx_user_id'] ) ) ? intval( $_REQUEST['wpbc_ajx_user_id'] ) : wpbc_get_current_user_id(); $booking_csv_export_params = get_user_option( 'booking_csv_export_params', (int) $user_id ); $booking_csv_export_params = ( ! empty( $booking_csv_export_params ) ) ? $booking_csv_export_params : array(); $defaults= array( 'export_type' => 'csv_all', 'selected_id' => '', 'csv_export_separator' => 'semicolon', 'csv_export_skip_fields' => '' ); $export_params_arr = wp_parse_args( $booking_csv_export_params, $defaults ); ?><span class="wpdevelop"> <div id="wpbc_modal__export_csv__section" class="modal wpbc_popup_modal" tabindex="-1" role="dialog"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title"><?php _e('CSV Export' ,'booking'); ?></h4> </div> <div class="modal-body"> <table class="form-table"><tbody> <?php $default_options_values = wpbc_get_default_options(); $field_options = array( 'semicolon' => '; - ' . __( 'semicolon', 'booking' ) , 'comma' => ', - ' . __( 'comma', 'booking' ) ); $fields = array( 'type' => 'select' , 'value' => $export_params_arr['csv_export_separator'] //';' , 'title' => __('CSV data separator', 'booking') , 'description' => ''//sprintf(__('Select separator of data for export bookings to CSV.' ,'booking'),'<b>','</b>') , 'options' => $field_options , 'label' => '' , 'disabled' => false , 'disabled_options' => array() , 'multiple' => false , 'description_tag' => 'p' , 'tr_class' => '' , 'class' => '' , 'css' => '' , 'only_field' => false , 'attr' => array() //, 'value' => '' ); WPBC_Settings_API::field_select_row_static( 'wpbc_field_booking_csv_export_separator', $fields ); $field_options = array( 'csv_page' => __( 'Current page', 'booking' ) , 'csv_all' => __( 'All pages', 'booking' ) ); $fields = array( 'type' => 'select' , 'value' => $export_params_arr['export_type'] , 'title' => __('Export pages', 'booking') , 'description' => ''//sprintf(__('Select exporting current page or all pages.' ,'booking'),'<b>','</b>') , 'options' => $field_options , 'label' => '' , 'disabled' => false , 'disabled_options' => array() , 'multiple' => false , 'description_tag' => 'p' , 'tr_class' => '' , 'class' => '' , 'css' => '' , 'only_field' => false , 'attr' => array() //, 'value' => '' ); WPBC_Settings_API::field_select_row_static( 'wpbc_field_booking_csv_export_type', $fields ); ?> </tbody></table> <textarea id="wpbc_field_booking_csv_export_skip_fields" name="wpbc_field_booking_csv_export_skip_fields" style="width:100%;" cols="87" rows="2" placeholder="<?php echo 'trash,is_new,secondname'; ?>" ><?php echo esc_textarea( $export_params_arr['csv_export_skip_fields'] ); ?></textarea> <label class="help-block"><?php printf(__('Enter field names separated by commas to %sskip the export%s' ,'booking'),'<b>','</b>');?></label> <input type="hidden" id="wpbc_modal__export_csv__booking_id" value="" /> </div> <div class="modal-footer"> <a id="wpbc_modal__export_csv__button_send" class="button button-primary" onclick="javascript: wpbc_ajx_booking__ui_click__export_csv( { 'booking_action' : 'export_csv', 'ui_clicked_element_id' : 'wpbc_modal__export_csv__button_send', 'export_type' : jQuery('#wpbc_field_booking_csv_export_type option:selected').val(), 'csv_export_separator' : jQuery('#wpbc_field_booking_csv_export_separator option:selected').val(), 'csv_export_skip_fields': jQuery('#wpbc_field_booking_csv_export_skip_fields').val() } );" href="javascript:void(0);" ><?php _e('Export' ,'booking'); ?></a> <a href="javascript:void(0)" class="button button-secondary" data-dismiss="modal"><?php _e('Close' ,'booking'); ?></a> </div> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal --> </span><?php } // </editor-fold> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Support functions //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Catch some errors, if such errors exist during our Ajx request */ class WPBC_AJAX_ERROR_CATCHING{ public $errors_arr; function __construct() { $this->errors_arr = array(); // Catch Error messages add_action( 'wp_error_added', array( $this, 'wpbc_wp_error_added' ), 10, 4 ); if ( ! defined( 'WPBC_AJAX_ERROR_CATCH' ) ) { define( 'WPBC_AJAX_ERROR_CATCH', true ); } // Check somewhere to not show error messages: if ( ( defined( 'WPBC_AJAX_ERROR_CATCH' ) ) && ( WPBC_AJAX_ERROR_CATCH ) ) { return false; } } /** * Catch Error messages * * @param $code * @param $message * @param $data * @param $this_link * * @return void */ function wpbc_wp_error_added( $code, $message, $data, $this_link ){ $this->errors_arr[] = array( 'code' => $code, 'message' => $message, 'data' => $data, 'this_link' => $this_link ) ; } /** * Get summary of all errors * @return string */ function get_error_messages(){ $error_message = array(); foreach ( $this->errors_arr as $error ) { $error_message[] = 'Error: ' . $error['code'] . '. ' . $error['message']; } $error_message = implode( '<br/>', $error_message ); if ( ! empty( $error_message ) ) { $error_message = '<div class="wpbc_ajx_errors">' .'<br/><strong>' . __( 'Some errors were encountered.', 'booking' ) . '</strong><br/>' . $error_message . '</div>'; } return $error_message; } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Check what user can do //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Check permission of this user on specific actions, like approving or deleting of bookings * * @param string $action like 'set_pnding' * @param int $user_id like 1 * * @return bool */ function wpbc_is_user_can( $action, $user_id = 0 ){ if ( 0 == $user_id ) { $user_id = wpbc_get_current_user_id(); } $user = get_userdata( $user_id ); $user_roles = (array) ( empty( $user ) ? array() : $user->roles ); // Standard WordPress Roles: 'administrator' | 'editor' | 'author' | 'contributor' | 'subscriber' // Get here list of actions that user can do switch ( $action ) { case 'set_booking_pending': break; case 'set_booking_approved': break; case 'move_booking_to_trash': break; case 'restore_booking_from_trash': break; case 'delete_booking_completely': // if ( ! in_array( 'administrator', $user_roles ) ) { return false; } break; case 'booking_add_google_calendar': break; case 'set_booking_locale': break; case 'set_booking_as_read': break; case 'set_booking_as_unread': break; case 'empty_trash': break; case 'set_booking_note': break; case 'edit_booking': break; case 'change_booking_resource': break; case 'duplicate_booking_to_other_resource': break; case 'set_payment_status': break; case 'set_booking_cost': break; case 'send_payment_request': break; case 'import_google_calendar': break; case 'export_csv': break; default: // Default } return true; } bookings__page.php 0000666 00000027703 15166373417 0010255 0 ustar 00 <?php /* * @package: AJX_Bookings Page * @category: o Email Reminders * @description: Define AJX_Bookings in admin settings page. - Sending friendly email reminders based on custom ajx_booking. * Plugin URI: https://oplugins.com/plugins/email-reminders/#premium * Author URI: https://oplugins.com * Author: wpdevelop, oplugins * Version: 0.0.1 * @modified 2020-05-11 */ //FixIn: 9.2.1 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly /** Show Content * Update Content * Define Slug * Define where to show */ class WPBC_Page_AJX_Bookings extends WPBC_Page_Structure { public function __construct() { parent::__construct(); // Redefine TAGs Names, becasue 'tab' slug already used in the system for definition of active toolbar. $this->tags['tab'] = 'view_mode'; $this->tags['subtab'] = 'bottom_nav'; } public function in_page() { return 'wpbc'; } public function tabs() { $tabs = array(); $tabs[ 'vm_booking_listing' ] = array( 'title' => __( 'Booking Listing', 'booking' ) // Title of TAB , 'hint' => __( 'Booking Listing', 'booking' ) // Hint , 'page_title' => __( 'Booking Listing', 'booking' ) // Title of Page , 'link' => '' // Can be skiped, then generated link based on Page and Tab tags. Or can be extenral link , 'position' => '' // 'left' || 'right' || '' , 'css_classes' => '' // CSS class(es) , 'icon' => '' // Icon - link to the real PNG img , 'font_icon' => 'wpbc-bi-collection' // CSS definition of forn Icon //FixIn: 9.5.5.3 , 'header_font_icon' => 'wpbc-bi-collection' // CSS definition of forn Icon //FixIn: 9.5.5.3 , 'default' => false // Is this tab activated by default or not: true || false. , 'disabled' => false // Is this tab disabled: true || false. , 'hided' => true // Is this tab hided: true || false. , 'subtabs' => array() ); // $subtabs = array(); // $tabs[ 'items' ][ 'subtabs' ] = $subtabs; return $tabs; } public function content() { do_action( 'wpbc_hook_settings_page_header', 'page_booking_listing'); // Define Notices Section and show some static messages, if needed. if ( ! wpbc_is_mu_user_can_be_here( 'activated_user' ) ) { return false; } // Check if MU user activated, otherwise show Warning message. //?? if ( ! wpbc_set_default_resource_to__get() ) return false; // Define default booking resources for $_GET and check if booking resource belong to user. //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Get and escape request parameters //////////////////////////////////////////////////////////////////////////////////////////////////////////////// $user_request = new WPBC_AJX__REQUEST( array( 'db_option_name' => 'booking_listing_request_params', 'user_id' => wpbc_get_current_user_id(), 'request_rules_structure' => wpbc_ajx_get__request_params__names_default() ) ); $escaped_search_request_params = false; if ( empty( $_REQUEST['overwrite'] ) ) { $escaped_search_request_params = $user_request->get_sanitized__saved__user_request_params(); // Get Saved } if ( ( false === $escaped_search_request_params ) || ( ! empty( $_REQUEST['overwrite'] ) ) ){ // This request was not saved before, then get sanitized direct parameters, like: $_REQUEST['resource_id'] $request_prefix = false; $escaped_search_request_params = $user_request->get_sanitized__in_request__value_or_default( $request_prefix ); // Direct: $_REQUEST['resource_id'] } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Submit ///////////////////////////////////////////////////////////// $submit_form_name = 'wpbc_ajx_booking_form'; // Define form name ?><span class="wpdevelop"><?php // BS UI CSS Class wpbc_js_for_bookings_page(); // JavaScript functions wpbc_welcome_panel(); // Welcome Panel (links) wpbc_ajx_bookings_toolbar( $escaped_search_request_params ); ?></span><?php // BS UI CSS Class ?><div id="wpbc_log_screen" class="wpbc_log_screen"></div><?php // Content //////////////////////////////////////////////////////////// ?> <div class="clear" style="margin-bottom:10px;"></div> <span class="metabox-holder"> <form name="<?php echo $submit_form_name; ?>" id="<?php echo $submit_form_name; ?>" action="" method="post" > <?php // N o n c e field, and key for checking S u b m i t wp_nonce_field( 'wpbc_settings_page_' . $submit_form_name ); ?><input type="hidden" name="is_form_sbmitted_<?php echo $submit_form_name; ?>" id="is_form_sbmitted_<?php echo $submit_form_name; ?>" value="1" /><?php ///wpbc_ajx_booking_modify_container_show(); // Container for showing Edit ajx_booking and define Edit and Delete ajx_booking JavaScript vars. ?><div class="wpbc_ajx_under_toolbar_row"><?php wpbc_ajx__ui__booking_sorting( $escaped_search_request_params , wpbc_ajx_get__request_params__names_default( 'default' ) ); ?><div class="wpbc_ajx_booking_pagination"></div><?php // Pagination container at head // Is send Emails wpbc_ajx__ui__booking__no_toolbar__is_email_sending( $escaped_search_request_params, wpbc_ajx_get__request_params__names_default( 'default' ) ); //FixIn: 9.6.1.5 ?></div><?php wpbc_clear_div(); $is_test_sql_directly = false; if ( ! $is_test_sql_directly ) { $this->show_ajx_booking_listing_container_ajax( $escaped_search_request_params ); $this->show_pagination_container(); } else { $this->show_ajx_booking_listing_container_directly(); // Useful for direct showing of listing without the ajax request, its requirement JavaScript to show data in template!! } ?><div class="clear"></div><?php ?></form> </span> <?php do_action( 'wpbc_hook_settings_page_footer', 'wpbc-ajx_booking' ); wpbc_show_booking_footer(); // Show rating line } private function show_pagination_container(){ ?> <div class="wpbc_ajx_booking_pagination"></div> <?php wpbc_clear_div(); $wpbc_pagination = new WPBC_Pagination(); $wpbc_pagination->init( array( 'load_on_page' => 'wpbc-ajx_booking', 'container' => '.wpbc_ajx_booking_pagination', 'on_click' => 'wpbc_ajx_booking_pagination_click' // onclick = "javascript: wpbc_ajx_booking_pagination_click( page_num );" - need to define this function in JS file )); /** $wpbc_pagination->show( array( // Its showing with JavaScript on document ready 'page_active' => 3, 'pages_count' => 20 )); /**/ } private function show_ajx_booking_listing_container_ajax( $escaped_search_request_params ) { ?> <div class="wpbc_listing_container wpbc_selectable_table wpbc_ajx_booking_listing_container"> <?php // New Spinner Loader //FixIn: 10.0.0.25 ?> <div class="wpbc_spins_loading_container" > <div class="wpbc_booking_form_spin_loader" ><div class="wpbc_spins_loader_wrapper"><div class="wpbc_spins_loader_mini"></div></div></div> <span><?php _e('Loading','booking'); ?> ...</span> </div> </div> <script type="text/javascript"> jQuery( document ).ready( function (){ // Set Security - Nonce for Ajax - Listing wpbc_ajx_booking_listing.set_secure_param( 'nonce', '<?php echo wp_create_nonce( 'wpbc_ajx_booking_listing_ajx' . '_wpbcnonce' ) ?>' ); wpbc_ajx_booking_listing.set_secure_param( 'user_id', '<?php echo wpbc_get_current_user_id(); ?>' ); wpbc_ajx_booking_listing.set_secure_param( 'locale', '<?php echo get_user_locale(); ?>' ); // Set other parameters wpbc_ajx_booking_listing.set_other_param( 'listing_container', '.wpbc_ajx_booking_listing_container' ); wpbc_ajx_booking_listing.set_other_param( 'pagination_container', '.wpbc_ajx_booking_pagination' ); // Send Ajax request and show listing after this. wpbc_ajx_booking_send_search_request_with_params( <?php echo wp_json_encode( $escaped_search_request_params ); ?> ); } ); </script> <?php } private function show_ajx_booking_listing_container_directly(){ //TODO: We need to send Ajax request and then show the listing (its will make one same way of showing listing and pagination)! $my_ajx_booking = new WPBC_AJX_Bookings; //////////////////////////////////// // 0. Check Nonce if Ajax ( ! used now ) //////////////////////////////////// if ( 0 ){ $action_name = 'wpbc_search_field' . '_wpbcnonce'; // $_POST['element_id'] . '_wpbcnonce'; $nonce_post_key = 'nonce'; $result_check = check_ajax_referer( $action_name, $nonce_post_key ); } //////////////////////////////////// // 1. Direct Clean Params //////////////////////////////////// $request_params_ajx_booking = array( 'page_num' => array( 'validate' => 'd', 'default' => 1 ) , 'page_items_count' => array( 'validate' => 'd', 'default' => 10 ) , 'sort' => array( 'validate' => array( 'booking_id' ), 'default' => 'booking_id' ) , 'sort_type' => array( 'validate' => array( 'ASC', 'DESC'),'default' => 'DESC' ) , 'status' => array( 'validate' => 's', 'default' => '' ) , 'keyword' => array( 'validate' => 's', 'default' => '' ) , 'ru_create_date' => array( 'validate' => 'date', 'default' => '' ) ); $request_params_values = array( // Usually $request_params_values is $_REQUEST 'page_num' => 1, 'page_items_count' => 3, 'sort' => 'booking_id', 'sort_type' => 'DESC', 'status' => '', 'keyword' => '', 'ru_create_date' => '' ); $request_params = wpbc_sanitize_params_in_arr( $request_params_values, $request_params_ajx_booking ); //////////////////////////////////// // 2. Get items array from DB //////////////////////////////////// $items_arr = wpbc_ajx_get_booking_data_arr( $request_params ); debuge($items_arr); // Show Pagination - $total_num_of_items_in_all_pages = $sql_res[ [ 'count' ] ]; // $wpbc_pagination->show_pagination( // $request_params_values['page_num'], // ceil( $sql_res[ [ 'count' ] ] / $request_params_values['page_items_count'] ) // ); } } add_action('wpbc_menu_created', array( new WPBC_Page_AJX_Bookings() , '__construct') ); // Executed after creation of Menu bookings__listing.php 0000666 00000070336 15166373417 0011012 0 ustar 00 <?php /** * @version 1.0 * @description AJX_Bookings * @category AJX_Bookings Class * @author wpdevelop * * @web-site http://oplugins.com/ * @email info@oplugins.com * * @modified 2020-01-23 */ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly class WPBC_AJX_Bookings { /* Static Variables */ static $data_separator = array( 'r_separator' => '~' , 'f_separator' => '^' ); // <editor-fold defaultstate="collapsed" desc=" /// JS | CSS files | Tpl loading /// " > // JS | CSS =================================================================================================== /** * Define HOOKs for loading CSS and JavaScript files */ public function init_load_css_js_tpl() { // JS & CSS // Load only at AJX_Bookings Settings Page if ( 'vm_booking_listing' == wpbc_ajx_booking_listing__get_default_view_mode() ) { //if ( strpos( $_SERVER['REQUEST_URI'], 'view_mode=vm_booking_listing' ) !== false ) { add_action( 'wpbc_enqueue_js_files', array( $this, 'js_load_files' ), 50 ); add_action( 'wpbc_enqueue_css_files', array( $this, 'enqueue_css_files' ), 50 ); add_action( 'wpbc_hook_settings_page_footer', array( $this, 'hook__page_footer_tmpl' ) ); } } /** JSS */ public function js_load_files( $where_to_load ) { $in_footer = true; if ( ( is_admin() ) && ( in_array( $where_to_load, array( 'admin', 'both' ) ) ) ) { //wp_enqueue_script( 'wpbc-live_search', wpbc_plugin_url( '/_out/js/live_search.js' ), array( 'wpbc_all' ), WP_BK_VERSION_NUM, $in_footer ); wp_enqueue_script( 'wpbc-booking_ajx_toolbar_hooks' , trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/bookings__hooks.js' /* wpbc_plugin_url( '/_out/js/codemirror.js' ) */ , array( 'wpbc_all' ), WP_BK_VERSION_NUM, $in_footer ); wp_enqueue_script( 'wpbc-booking_ajx_listing' , trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/bookings__listing.js' /* wpbc_plugin_url( '/_out/js/codemirror.js' ) */ , array( 'wpbc_all' ), WP_BK_VERSION_NUM, $in_footer ); wp_enqueue_script( 'wpbc-booking_ajx_actions' , trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/bookings__actions.js' /* wpbc_plugin_url( '/_out/js/codemirror.js' ) */ , array( 'wpbc_all' ), WP_BK_VERSION_NUM, $in_footer ); wp_enqueue_script( 'wpbc-general_ui_js_css' , wpbc_plugin_url( '/includes/_general_ui_js_css/_out/wpbc_main_ui_funcs.js' ) , array( 'wpbc_all' ), WP_BK_VERSION_NUM, $in_footer ); /** wp_localize_script( 'wpbc_all', 'wpbc_live_request_obj' , array( 'ajx_booking' => '', 'reminders' => '' ) ); */ } } /** CSS */ public function enqueue_css_files( $where_to_load ) { if ( ( is_admin() ) && ( in_array( $where_to_load, array( 'admin', 'both' ) ) ) ) { //wp_enqueue_style( 'wpbc-ajx_booking-listing', wpbc_plugin_url( '/includes/listing_ajx_booking/o-ajx_booking-listing.css' ), array(), WP_BK_VERSION_NUM ); //wp_enqueue_style( 'wpbc-listing_ajx_booking', trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/bookings__listing.css' , array(), WP_BK_VERSION_NUM ); } } // </editor-fold> // <editor-fold defaultstate="collapsed" desc=" /// Templates /// " > // Templates =================================================================================================== /** * Templates at footer of page * * @param $page string */ public function hook__page_footer_tmpl( $page ){ // page=wpbc&view_mode=vm_booking_listing if ( 'wpbc-ajx_booking' === $page ) { // it's from >> do_action( 'wpbc_hook_settings_page_footer', 'wpbc-ajx_booking' ); $this->template__listing_header(); $this->template__listing_row(); $this->template__content_data(); } } private function template__listing_header() { // Header ?><script type="text/html" id="tmpl-wpbc_ajx_booking_list_header"> <div class="wpbc_listing_usual_row wpbc_list_header wpbc_selectable_head"> <div class="wpbc_listing_col wpbc_col_id check-column"><div class="content_text"><input type="checkbox" /></div></div> <div class="wpbc_listing_col wpbc_col_booking_labels wpbc_col_labels"><div class="content_text"><?php echo esc_js( __( 'Labels', 'booking' ) . ' / ' . __('Actions' ,'booking' ) ); ?></div></div> <div class="wpbc_listing_col wpbc_col_data"><div class="content_text"><?php echo esc_js( __( 'Booking Data', 'booking' ) ); ?></div></div> <div class="wpbc_listing_col wpbc_col_dates"><div class="content_text"><?php echo esc_js( __( 'Booking Dates', 'booking' ) ); ?> <span class="wpbc_listing_header_action_icon"> <a id="booking_dates_full" onclick="javascript:wpbc_ajx_click_on_dates_wide();" href="javascript:void(0)" title="<?php echo esc_attr( __('Show ALL dates of booking' ,'booking') ); ?>" style="<# if ( 'wide' === wpbc_ajx_booking_listing.search_get_param('ui_usr__dates_short_wide') ) { #>display: none;<# } #>" class="tooltip_top" ><i class="wpbc_icn_swap_horiz" style=" margin-top: 2px;"></i></a> <a id="booking_dates_small" onclick="javascript:wpbc_ajx_click_on_dates_short();" href="javascript:void(0)" title="<?php echo esc_attr( __('Show only check in/out dates' ,'booking') ); ?>" style="<# if ( 'short' === wpbc_ajx_booking_listing.search_get_param('ui_usr__dates_short_wide') ) { #>display: none;<# } #>" class="tooltip_top" ><i class="wpbc_icn_compare_arrows" style=" margin-top: 2px;"></i></a> </span> </div></div> </div> </script><?php } private function template__listing_row() { /** * data objet = { "booking_db": { "booking_id": "3", "trash": "0", "sync_gid": "", "is_new": "0", "status": "", "sort_date": "2022-02-03 12:00:01", "modification_date": "2022-03-14 17:48:23", "form": "selectbox-one^rangetime2^12:00 - 14:00~text^name2^Anthony~text^secondname2^Gomez~text^email2^Gomez.example@wpbookingcalendar.com~text^address2^144 Hitchcock Rd~text^city2^Jacksonville~text^postcode2^38374~text^country2^US~text^phone2^988-48-45~selectbox-one^visitors2^3~checkbox^children2[]^2~textarea^details2^", "hash": "993086af7a382f3956e6a0010932c856", "booking_type": "2", "remark": null, "cost": "58.00", "pay_status": "", "pay_request": "0" }, "id": "3", "approved": "0", "dates": [ "2022-02-03 12:00:01", "2022-02-03 14:00:02" ], "child_id": [ "", "" ], "short_dates": [ "2022-02-03 12:00:01", "-", "2022-02-03 14:00:02" ], "short_dates_child_id": [ "", "", "" ], "parsed_fields": { "rangetime": "12:00 PM - 2:00 PM", "name": "Anthony", "secondname": "Gomez", "email": "Gomez.example@wpbookingcalendar.com", "address": "144 Hitchcock Rd", "city": "Jacksonville", "postcode": "38374", "country": "US", "phone": "988-48-45", "visitors": "3", "children": "2", "details": "", "booking_id": "3", "trash": "0", "sync_gid": "", "is_new": "0", "status": "", "sort_date": "2022-02-03 12:00:01", "modification_date": "March 14, 2022 5:48 PM", "hash": "993086af7a382f3956e6a0010932c856", "booking_type": "2", "cost": "58.00", "pay_status": "", "pay_request": "0", "id": "3", "approved": "0" }, "templates": { "form_show": "<div class=\"standard-content-form\"> \r\n\t<strong>First Name</strong>:<span class=\"fieldvalue\">Anthony</span> \r\n\t<strong>Last Name</strong>:<span class=\"fieldvalue\">Gomez</span> \r\n\t<strong>Email</strong>:<span class=\"fieldvalue\">Gomez.example@wpbookingcalendar.com</span> \r\n\t<strong>Adults</strong>:<span class=\"fieldvalue\"> 3</span> \r\n\t<strong>Children</strong>:<span class=\"fieldvalue\"> 2</span> \r\n\t<strong>Details</strong>: <span class=\"fieldvalue\"> </span> \r\n</div>" }, "__search_request_keyword__": "" } */ // Rows ?><script type="text/html" id="tmpl-wpbc_ajx_booking_list_row"> <div id="row_id_{{{data.parsed_fields.booking_id}}}" class="wpbc_listing_usual_row wpbc_list_row wpbc_row"> <div class="wpbc_listing_col wpbc_col_id check-column"><div class="content_text"><input type="checkbox" /></div></div> <div class="wpbc_listing_col wpbc_col_booking_labels wpbc_col_labels"> <div class="content_text"> <?php wpbc_for_booking_template__action_read(); ?> <span class="wpbc_label wpbc_label_booking_id">{{data['parsed_fields']['booking_id']}}</span><?php /** * Check for errors in translation. * * Example * French translation of this code: * * if ( '<?php _e( 'Resource not exist', 'booking' ); ?>' == data.parsed_fields.resource_title ) { * is: * if ( 'La ressource n'existe pas' == data.parsed_fields.resource_title ) { * * it's generate JS error * * That's why we need to use * if ( '<?php echo esc_js(__( 'Resource not exist', 'booking' )); ?>' == data.parsed_fields.resource_title ) { * which is: * if ( 'La ressource n\'existe pas' == data.parsed_fields.resource_title ) { */ ?> <# if ( '<?php echo esc_js(__( 'Resource not exist', 'booking' )); ?>' == data.parsed_fields.resource_title ) { #><span class="wpbc_label wpbc_label_resource wpbc_label_deleted_resource">{{{data.parsed_fields.resource_title}}}</span><# } else if ( '' != data.parsed_fields.resource_title ) { #><span class="wpbc_label wpbc_label_resource">{{{data.parsed_fields.resource_title}}}</span><# } #><span class="wpbc_label wpbc_label_approved<# if ( '0' == data.approved ) { #> hidden_items <# } #>"><i style="color: #def5d4;" class="menu_icon icon-1x wpbc_icn_done_all"></i><?php echo esc_js(__( 'Approved', 'booking' )); ?></span><# #><span class="wpbc_label wpbc_label_pending<# if ( '1' == data.approved ) { #> hidden_items <# } #>"><i style="color: #f6efe8;" class="menu_icon icon-1x wpbc_icn_hourglass_empty"></i><?php echo esc_js(__( 'Pending', 'booking' )); ?></span><# if ( '' != data.templates.payment_label_template ) { #>{{{data.templates.payment_label_template}}}<# } if ( '' != data.parsed_fields.sync_gid ) { #><span class="wpbc_label wpbc_label_imported"><i class="menu_icon icon-1x wpbc_icn_cloud_download system_update_alt"></i><?php echo esc_js(__( 'Imported', 'booking' )); ?></span><# } #><span class="wpbc_label wpbc_label_trash<# if ( '1' != data.parsed_fields.trash ) { #> hidden_items <# } #>"><i style="color: #f6efe8;" class="menu_icon icon-1x wpbc_icn_delete_forever"></i><?php echo esc_js(__( 'In Trash', 'booking' )); ?></span><# #><?php $labels = get_bk_option( 'wpbc_ajx_booking_labels' ); $labels = explode( "\n",$labels ); $labels = array_map( 'trim',$labels ); // Check for Labels and colors foreach ($labels as $label) { if ( ( ! empty( $label ) ) && ( false !== strpos( ':', $label ) ) ) { list( $label, $color, $text_color ) = explode( ':', $label ); } else{ $color = $text_color = ''; } if ( ! empty( $label ) ) { ?><span class="wpbc_label" style="color:<?php echo $text_color; ?>;background-color:<?php echo $color; ?>;">{{{data.parsed_fields<?php echo $label; ?>}}}</span><?php } } // Predefined internal Labels ?><# if ( ( undefined != data._paid ) && ( -1 != data._paid.toLowerCase().indexOf( 'refund' ) ) ) { #><span class="wpbc_label booking_label__refund"><?php echo esc_js(__('Refund','booking')); ?></span><# } console.log( 'row listing', data ); // LISTING_ROWS #> </div> </div> <div class="wpbc_listing_col wpbc_col_data"> <div class="content_text"> <# <?php if (0) { ?><script type="text/javascript"><?php /* Hack for showing JavaScript syntax */ } ?> var booking_details = data.templates.form_show; var booking_keyword = data[ '__search_request_keyword__' ]; booking_details = wpbc_get_highlighted_search_keyword( booking_details, booking_keyword ); <?php if (0) { ?></script><?php } ?> #> {{{booking_details}}} <?php if ( 0 ) { ?> <div class="wpbc_next_booking_time"> <?php do_action( 'wpbca_show_cron_data_in_ajx_booking_listing' ); ?> <span><strong><?php echo esc_js(__( 'Source', 'booking' )); ?></strong>: <span class="fieldvalue"><strong>{{data['source']}}</strong></span></span> <span><strong><?php echo esc_js(__( 'Booking ID', 'booking' )); ?></strong>: <span class="fieldvalue"><strong>{{data['booking_id']}}</strong></span></span> <span class="wpbc_item_actions wpdevelop"> <a href="javascript:void();" style="margin:0;" onclick="javascript:wpbc_ajx_booking__modify__ajx_reset( wpbc_get_row_id_from_element( this ) );return false;" class="tooltip_top button-secondary button" title="<?php echo esc_js(__('Set last checked booking id to 0', 'booking' )); ?>" data-original-title="Reset" ><i class="-repeat"></i> Reset</a> </span> </div> <hr/> <?php } ?> <# if ( ( !true ) || ( '' == booking_details.trim() ) ) { #> <hr/> <# <?php if (0) { ?><script type="text/javascript"><?php /* Hack for showing JavaScript syntax */ } ?> // Content Data Template var my_content_data = wp.template( 'wpbc_content_data' ); _.each( data['parsed_fields'], function ( p_val, p_key, p_data ) { // Skip these fields if ( ! _.contains( [ '__search_request_keyword__' , 'booking_id', 'source' , 'create_date','edit_date', 'google_calendar_link' ] , p_key ) ){ #>{{{ my_content_data( {"key": p_key, "value": wpbc_decode_HTML_entities( p_val ), "keyword": data['__search_request_keyword__'] } ) }}}<# } }); <?php if (0) { ?></script><?php } ?> #> <# } #> </div> </div> <div class="wpbc_listing_col wpbc_col_dates wpbc_col_labels"> <div class="booking_dates_small booking_dates_expand_section" style="<# if ( 'short' !== wpbc_ajx_booking_listing.search_get_param('ui_usr__dates_short_wide') ) { #>display: none;<# } #>" ><div class="content_text">{{{data.templates.short_dates_content}}}</div></div> <div class="booking_dates_full booking_dates_expand_section" style="<# if ( 'wide' !== wpbc_ajx_booking_listing.search_get_param('ui_usr__dates_short_wide') ) { #>display: none;<# } #>" ><div class="content_text">{{{data.templates.wide_dates_content}}}</div></div> </div><?php $this->for_template__actions_buttons(); ?> </div> </script><?php } private function template__content_data(){ // Content Data ?><script type="text/html" id="tmpl-wpbc_content_data"> <strong>{{data.key}}</strong>:<span class="fieldvalue {{data.key}}<# if ( ( data.keyword != '' ) && ( undefined != data.value ) && ( -1 != data.value.toLowerCase().indexOf( data.keyword.trim().toLowerCase() ) ) ) { #> fieldsearchvalue<# } if ( ( undefined != data.value ) && ( -1 != data.value.toLowerCase().indexOf( 'refund' ) ) ) { #> _refund<# } #>">{{{data.value}}}</span> </script><?php } private function for_template__actions_buttons(){ ?> <div class="wpbc_item_actions wpdevelop"> <div class="wpbc_actions_buttons"> <div class="wpbc_ajx_toolbar wpbc_buttons_row wpbc_buttons_row_for_booking"> <div class="ui_container ui_container_small"> <div class="ui_group"><?php wpbc_for_booking_template__action_cost(); wpbc_for_booking_template__action_payment_request(); wpbc_for_booking_template__action_set_payment_status(); if ( class_exists( 'wpdev_bk_personal' ) ) { wpbc_flex_divider(); } wpbc_for_booking_template__action_edit_booking(); if ( ! class_exists( 'wpdev_bk_personal' ) ) { wpbc_flex_divider(); } wpbc_for_booking_template__action_change_resource(); wpbc_for_booking_template__action_duplicate_booking_to_other_resource(); wpbc_for_booking_template__action_print(); wpbc_for_booking_template__action_remark(); wpbc_for_booking_template__action_locale(); wpbc_for_booking_template__action_add_google_calendar(); wpbc_flex_divider(); wpbc_for_booking_template__action_trash(); wpbc_for_booking_template__action_trash_restore(); wpbc_for_booking_template__action_delete(); wpbc_for_booking_template__action_approved(); wpbc_for_booking_template__action_pending(); ?><div class="ui_element" style="flex:100%;"></div><?php // New line wpbc_for_booking_template_section__action_remark_textarea(); wpbc_for_booking_template_section__change_booking_resource(); wpbc_for_booking_template_section__duplicate_booking_to_other_resource(); wpbc_for_booking_template_section__set_payment_status(); ?></div> </div> </div> </div> <div class="wpbc_actions_sysinfo"> <span><?php echo esc_js(__( 'Booking ID', 'booking' )); ?>: <strong>{{data['parsed_fields']['booking_id']}}</strong></span> <span><?php echo esc_js(__( 'Edited', 'booking' )); ?>: <strong>{{data['parsed_fields']['modification_date']}}</strong></span> <span><?php echo esc_js(__( 'Created', 'booking' )); ?>: <strong>{{data['parsed_fields']['creation_date']}}</strong></span> </div> </div> <?php } // </editor-fold> // <editor-fold defaultstate="collapsed" desc=" /// A J A X /// " > // A J A X ===================================================================================================== /** * Define HOOKs for start loading Ajax */ public function define_ajax_hook(){ // Ajax Handlers. Note. "locale_for_ajax" rechecked in wpbc-ajax.php add_action( 'wp_ajax_' . 'WPBC_AJX_BOOKING_LISTING', array( $this, 'ajax_' . 'WPBC_AJX_BOOKING_LISTING' ) ); // Admin & Client (logged in usres) // Ajax Handlers for actions add_action( 'wp_ajax_' . 'WPBC_AJX_BOOKING_ACTIONS', 'wpbc_ajax_' . 'WPBC_AJX_BOOKING_ACTIONS' ); // add_action( 'wp_ajax_nopriv_' . 'WPBC_AJX_BOOKING_LISTING', array( $this, 'ajax_' . 'WPBC_AJX_BOOKING_LISTING' ) ); // Client (not logged in) } /** * Ajax - Get Listing Data and Response to JS script */ public function ajax_WPBC_AJX_BOOKING_LISTING() { if ( ! isset( $_POST['search_params'] ) || empty( $_POST['search_params'] ) ) { exit; } // Security ----------------------------------------------------------------------------------------------- // in Ajax Post: 'nonce': wpbc_ajx_booking_listing.get_secure_param( 'nonce' ), $action_name = 'wpbc_ajx_booking_listing_ajx' . '_wpbcnonce'; $nonce_post_key = 'nonce'; $result_check = check_ajax_referer( $action_name, $nonce_post_key ); $user_id = ( isset( $_REQUEST['wpbc_ajx_user_id'] ) ) ? intval( $_REQUEST['wpbc_ajx_user_id'] ) : wpbc_get_current_user_id(); /** * SQL --------------------------------------------------------------------------- * * in Ajax Post: 'search_params': wpbc_ajx_booking_listing.search_get_all_params() * * Use prefix "search_params", if Ajax sent - * $_REQUEST['search_params']['page_num'], $_REQUEST['search_params']['page_items_count'],.. */ $user_request = new WPBC_AJX__REQUEST( array( 'db_option_name' => 'booking_listing_request_params', 'user_id' => $user_id, //FixIn: 9.4.3.2 'request_rules_structure' => wpbc_ajx_get__request_params__names_default() ) ); $request_prefix = 'search_params'; $request_params = $user_request->get_sanitized__in_request__value_or_default( $request_prefix ); // NOT Direct: $_REQUEST['search_params']['resource_id'] $data_arr = wpbc_ajx_get_booking_data_arr( $request_params ); $new_bookings_count = wpbc_db_get_number_new_bookings(); if ( 'make_reset' === $request_params['ui_reset'] ) { $is_reseted = wpbc_ajx__user_request_params__delete( $user_id ); $request_params['ui_reset'] = $is_reseted ? 'reset_done' : 'reset_error'; } else { $is_success_update = wpbc_ajx__user_request_params__save( $request_params, $user_id ); // - $request_params - serialized here automatically } //---------------------------------------------------------------------------------------------------------- // Send JSON. Its will make "wp_json_encode" - so pass only array, and This function call wp_die( '', '', array( 'response' => null, ) ) Pass JS OBJ: response_data in "jQuery.post( " function on success. wp_send_json( array( 'ajx_count' => $data_arr['count'], 'ajx_items' => $data_arr['data_arr'], 'ajx_booking_resources' => $data_arr['booking_resources'], 'ajx_search_params' => $_REQUEST['search_params'], 'ajx_cleaned_params' => $request_params, 'ajx_new_bookings_count'=> $new_bookings_count ) ); } // </editor-fold> } /** * Just for loading CSS and JavaScript files */ if ( true ) { $ajx_booking_loading = new WPBC_AJX_Bookings; $ajx_booking_loading->init_load_css_js_tpl(); $ajx_booking_loading->define_ajax_hook(); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // API Hooks //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Get booking data by booking_ID * * @param $booking_id int * * @return false | stdClass Object ( [booking_db] => stdClass Object ( [booking_id] => 130 [booking_options] => [trash] => 0 [sync_gid] => 15l1028ii1v95ctbpgcf2r2s2h_20171201 [is_new] => 0 [status] => [sort_date] => 2022-08-08 00:00:00 [modification_date] => 2022-07-24 11:04:32 [form] => text^name1^Jessica~text^secondname1^.... [hash] => 1d7dc4e06d95726bf9 [booking_type] => 1 [remark] => [cost] => 100.00 [pay_status] => Failed [pay_request] => 0 ) [id] => 130 [approved] => 0 [dates] => Array ( [0] => '2022-08-08 00:00:00' [1] => '2022-08-09 00:00:00' [2] => '2022-08-10 00:00:00' ) [child_id] => Array ( [0] => '' [1] => '' [2] => '' ) [short_dates] => Array ( [0] => '2022-08-08 00:00:00' [1] => '-' [2] => '2022-08-10 00:00:00' ) [short_dates_child_id] => Array ( [0] => '' [1] => '' [2] => '' ) [parsed_fields] => Array ( [name] => Jessica [secondname] => Simson ... [booking_id] => 130 [trash] => 0 [sync_gid] => 15l1028ii1v95ctbpgcf2r2s2h_20171201 [is_new] => 0 [status] => [sort_date] => 2022-08-08 00:00:00 [modification_date] => July 24, 2022 11:04 [hash] => 1d7dc4e06d95726bf9060a66235b7dc6 [booking_type] => 1 [remark] => [cost] => 100.00 [pay_status] => Failed [pay_request] => 0 [id] => 130 [approved] => 0 [booking_options] => [is_paid] => 0 [pay_print_status] => Failed [currency_symbol] => $ [resource_title] => Standard [resource_id] => 1 [resource_owner_user] => 1 [google_calendar_link] => https://calendar.google.com/calendar/r/eventedit?text=... ) [templates] => Array ( [form_show] => First Name:Jessica Last Name:Simson Email:simson@gmail.com Phone:724 895 34 88 Address:Oliver street 10 City:Manchester Post code:78998 Country:UK Adults: 2 Children: 0 Details: I want a room with a terrace [form_show_nohtml] => First Name:Jessica Last Name:Simson Email:simson@gmail.com Phone:724 895 34 88 Address:Oliver street 10 City:Manchester Post code:78998 Country:UK Adults: 2 Children: 0 Details: I want a room with a terrace [short_dates_content] => August 8, 2022 - August 10, 2022 [wide_dates_content] => August 8, 2022, August 9, 2022, August 10, 2022 [payment_label_template] => Payment Failed ) ) */ function wpbc_search_booking_by_id( $booking_id ) { $booking_id = intval( $booking_id ); if ( ! empty( $booking_id ) ) { $booking_data = wpbc_search_booking_by_keyword( 'id:' . $booking_id ); if ( ! empty( $booking_data['data_arr'] ) ) { return $booking_data['data_arr'][0]; } } return false; } /** * Search specific booking(s) by Keyword * * @param string $keyword 'email@serv.com' * @param array $search_params default array() array( 'source' => 'csv' ) * * @return array( [data_arr] => Array ( [0] => Array( [booking_id] => 2772 [product_name] => Personal [date_placed] => 2019-10-16 [order] => XXA3443ASDDA-232423-423423 [email] => email@serv.com [_license_key] => 74826576578436 [full_product_name] => Personal (single site) .... ) ) [count] => 1 * */ function wpbc_search_booking_by_keyword( $keyword , $search_params = array() ){ $ajx_booking_listing = new WPBC_AJX_Bookings; $request_params = array( 'page_num' => 1, 'page_items_count' => 99999, 'sort' => 'booking_id', 'sort_type' => 'DESC', 'keyword' => '' ); // Get Default Parameters $default_param_values = wpbc_ajx_get__request_params__names_default( 'default' ); $request_params = wp_parse_args( $request_params, $default_param_values ); // Get Search Parameters, if passed into function $request_params = wp_parse_args( $search_params, $request_params ); $request_params['keyword'] = wpbc_sanitize_text( $keyword ); $ajx_booking_arr = wpbc_ajx_get_booking_data_arr( $request_params ); return $ajx_booking_arr; } add_filter( 'wpbc_search_booking_by_keyword' , 'wpbc_search_booking_by_keyword' ,10, 2 ); /** * DevApi: apply_filters( 'wpbc_search_booking_by_keyword', ' d1ca3d0b476c ', array( 'source' => 'csv' ) ); */ bookings__sql.php 0000666 00000330754 15166373417 0010143 0 ustar 00 <?php /** * @version 1.0 * @description Bookings Listing SQL * @category Booking Listing * @author wpdevelop * * @web-site http://oplugins.com/ * @email info@oplugins.com * * @modified 2022-04-07 */ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly // <editor-fold defaultstate="collapsed" desc=" D E F A U L T R E Q U E S T " > /** * Get params names for escaping and/or default value of such params * * @param string $structure_type 'validate_and_default' (default) | 'validate' | 'default' * * @return array * if $structure_type == '' array ( 'keyword' => array( 'validate' => 's', 'default' => '' ) * , 'wh_booking_date' => array( 'validate' => 'digit_or_date', 'default' => '3' ), ... * if $structure_type == 'validate' array ( 'keyword' => 's' * , 'wh_booking_date' => 'digit_or_date'), ... * if $structure_type == 'default' array ( 'keyword' => '' ) * , 'wh_booking_date' => '3' ), ... */ function wpbc_ajx_get__request_params__names_default( $structure_type = 'validate_and_default' ){ // Clean specific $_REQUEST params, if param is NOT set then return "default" $params_for_cleaning = array( // 'wh_booking_id' => array( 'validate' => 'digit_or_date', 'default' => '' ), // 'digit_or_csd' can check about 'digit_or_csd' in arrays, as well 'wh_booking_type' => array( 'validate' => 'digit_or_csd', 'default' => array( '0' ) ) // if ['0'] - All booking resources, ['-1'] - lost bookings in deleted resources , 'wh_approved' => array( 'validate' => 'digit_or_csd', 'default' => '' ) // '0' | '1' | '' , 'wh_booking_date' => array( 'validate' => 'array', 'default' => array( "3" ) ) // array( "0" ) - Current dates, | array( "3" ) - All dates // number | date 2016-07-20 , 'ui_wh_booking_date_radio' => array( 'validate' => 'd', 'default' => 0 ) // '1' | '2' .... , 'ui_wh_booking_date_next' => array( 'validate' => 'd', 'default' => 0 ) // '1' | '2' .... , 'ui_wh_booking_date_prior' => array( 'validate' => 'd', 'default' => 0 ) // '1' | '2' .... , 'ui_wh_booking_date_checkin' => array( 'validate' => 'digit_or_date', 'default' => '' ) // number | date 2016-07-20 , 'ui_wh_booking_date_checkout' => array( 'validate' => 'digit_or_date', 'default' => '' ) // number | date 2016-07-20 , 'wh_what_bookings' => array( 'validate' => array( 'any', 'new', 'imported', 'in_plugin' ), 'default' => 'any' ) // '1' | '' , 'wh_modification_date' => array( 'validate' => 'array', 'default' => array( "3" ) ) // number | date 2016-07-20 , 'ui_wh_modification_date_radio' => array( 'validate' => 'd', 'default' => 0 ) // '1' | '2' .... , 'ui_wh_modification_date_prior' => array( 'validate' => 'd', 'default' => 0 ) // '1' | '2' .... , 'ui_wh_modification_date_checkin' => array( 'validate' => 'digit_or_date', 'default' => '' ) // number | date 2016-07-20 , 'ui_wh_modification_date_checkout' => array( 'validate' => 'digit_or_date', 'default' => '' ) // number | date 2016-07-20 , 'keyword' => array( 'validate' => 's', 'default' => '' ) //string , 'wh_pay_status' => array( 'validate' => 'array', 'default' => array( 'all' ) ) , 'ui_wh_pay_status_radio' => array( 'validate' => 's', 'default' => '' ) // string , 'ui_wh_pay_status_custom' => array( 'validate' => 's', 'default' => '' ) // string , 'wh_cost' => array( 'validate' => 'float_or_empty', 'default' => '' ) // '1' | '' , 'wh_cost2' => array( 'validate' => 'float_or_empty', 'default' => '' ) // '1' | '' , 'wh_sort' => array( 'validate' => array( 'booking_id__asc', 'booking_id__desc', 'dates__asc', 'dates__desc', 'resource__asc', 'resource__desc', 'cost__asc', 'cost__desc' ), 'default' => 'booking_id__desc' ) , 'wh_trash' => array( 'validate' => array( '0', 'trash', 'any' ), 'default' => 'any' ) , 'page_num' => array( 'validate' => 'd', 'default' => 1 ) // '1' | '' , 'page_items_count' => array( 'validate' => 'd', 'default' => 10 ) // '1' | '' , 'ui_usr__send_emails' => array( 'validate' => array( 'send', 'not_send' ), 'default' => 'send' ) , 'ui_usr__is_expand_remarks' => array( 'validate' => array( 'On', 'Off' ), 'default' => 'Off' ) , 'ui_usr__default_selected_toolbar' => array( 'validate' => array( 'filters', 'actions', 'options' ), 'default' => 'filters' ) //////////////////////////////////////////////////////////////////////////////////////////////////////////////// , 'ui_reset' => array( 'validate' => 's', 'default' => '' ) // string , 'ui_usr__dates_short_wide' => array( 'validate' => array( 'short', 'wide' ), 'default' => 'short' ) //////////////////////////////////////////////////////////////////////////////////////////////////////////////// , 'view_days_num' => array( 'validate' => 'd', 'default' => 30 ) // '1' | '' //FixIn: 8.9.2.1 , 'scroll_start_date' => array( 'validate' => 'digit_or_date', 'default' => '' ) // number | date 2016-07-20 , 'scroll_day' => array( 'validate' => 'd', 'default' => 0 ) // '1' | '' , 'scroll_month' => array( 'validate' => 'd', 'default' => 0 ) // '1' | '' , 'limit_hours' => array( 'validate' => 'digit_or_csd', 'default' => '' ) // , 'only_booked_resources' => array( 'validate' => 'd', 'default' => 0 ) // '1' | '' ); if ( 'validate_and_default' == $structure_type ) { return $params_for_cleaning; } $return_simple_arr = array(); foreach ( $params_for_cleaning as $key => $value ) { $return_simple_arr[ $key ] = $value[ $structure_type ]; } return $return_simple_arr; } // </editor-fold> // <editor-fold defaultstate="collapsed" desc=" S A V E U S E R R E Q U E S T " > /** * Save user filter request - saving user filters in toolbar * * @param array $params * @param integer $user_id * * @return bool|int */ function wpbc_ajx__user_request_params__save( $params, $user_id ) { // Reset some parameters, like selected page if ( isset( $params['page_num'] ) ) { $params['page_num'] = 1; $params['keyword'] = ''; } return update_user_option( (int) $user_id, 'booking_listing_request_params' , $params ); } /** * Delete saved user request - used for resetting user filters in toolbar * @param integer $user_id * * @return bool */ function wpbc_ajx__user_request_params__delete( $user_id ) { if ( empty( $user_id ) ) { $user_id = wpbc_get_current_user_id(); } return delete_user_option( (int) $user_id, 'booking_listing_request_params' ); } /** * Get saved user filter request - params for user filters in toolbar * * @param integer $user_id * * @return false|mixed */ function wpbc_ajx__user_request_params__get( $user_id ) { if ( empty( $user_id ) ) { $user_id = wpbc_get_current_user_id(); } // wpbc_ajx__user_request_params__delete($user_id); //For debugging. delete it. return get_user_option( 'booking_listing_request_params', (int) $user_id ); } /** * Get sanitized array of use request parameters that was saved before * * @param $user_id int * * @return array|false */ function wpbc_ajx__user_request_params__get_sanitized( $user_id ) { $request_params_values_arr = wpbc_ajx__user_request_params__get( $user_id ); // - $request_params_values_arr - unserialized here automatically if ( false !== $request_params_values_arr ) { $request_params_structure = wpbc_ajx_get__request_params__names_default(); /** * array( 'page_num' => array( 'validate' => 'd', 'default' => 1 ) * , 'page_items_count' => array( 'validate' => 'd', 'default' => 10 ) * , 'sort' => array( 'validate' => array( 'booking_id' ), 'default' => 'booking_id' ) * , 'sort_type' => array( 'validate' => array( 'ASC', 'DESC'),'default' => 'DESC' ) * , 'keyword' => array( 'validate' => 's', 'default' => '' ) * , 'create_date' => array( 'validate' => 'date', 'default' => '' ) * ) */ $escaped_request_params = wpbc_sanitize_params_in_arr( $request_params_values_arr, $request_params_structure ); // Escaping params here return $escaped_request_params; } else { return false; } } /** * Get user saved option from Request in Booking Listing * * @param $user_id int 1 * @param $option_name string 'ui_usr__send_emails' * * @return false|mixed */ function wpbc_ajx__user_request_params__get_option( $user_id, $option_name ){ // Get User saved option from request $escaped_request_params = wpbc_ajx__user_request_params__get_sanitized( $user_id ); if ( ( ! empty( $escaped_request_params ) ) && ( ! empty( $escaped_request_params[ $option_name ] ) ) ) { return $escaped_request_params[ $option_name ]; } // Get default option $default_param_values = wpbc_ajx_get__request_params__names_default( 'default' ); if ( ! empty( $default_param_values[ $option_name ] ) ) { return $default_param_values[ $option_name ]; } // There is no such option return false; } /** * Is send emails ? Check DB SAVED user defined option from Options toolbar. * @param $user_id int ID of user * * @return int 1 | 0 */ function wpbc_ajx__user_request_option__is_send_emails( $user_id ){ $is_send_emeils = wpbc_ajx__user_request_params__get_option( $user_id, 'ui_usr__send_emails' ); $is_send_emeils = ( 'send' == $is_send_emeils ) ? 1 : 0; return $is_send_emeils; } /** * Is expand remarks by default ? Check DB SAVED user defined option from Options toolbar. * * It's useful only, when we are checking during Ajax action requests, where need to check data in Database, * For templates, need to use JavaScript: * <# if ( 'Off' === wpbc_ajx_booking_listing.search_get_param('ui_usr__is_expand_remarks') ) { #>display: none;<# } #> * * * @param $user_id int ID of user * * @return int 1 | 0 */ function wpbc_ajx__user_request_option__is_expand_remarks( $user_id ){ $is_send_emeils = wpbc_ajx__user_request_params__get_option( $user_id, 'ui_usr__is_expand_remarks' ); $is_send_emeils = ( 'On' == $is_send_emeils ) ? 1 : 0; return $is_send_emeils; } // </editor-fold> // <editor-fold defaultstate="collapsed" desc=" S Q L " > /** * Get array of bookings and total number of items in all pages. * * @param array $request_params = Array( [wh_booking_id] => [wh_booking_type] => [booking_type] => [wh_approved] => [wh_booking_date] => [wh_booking_date2] => [wh_booking_datenext] => 0 [wh_booking_dateprior] => 0 [wh_booking_datefixeddates] => [wh_booking_date2fixeddates] => [wh_is_new] => 0 [wh_modification_date] => [wh_modification_date2] => [wh_modification_dateprior] => 0 [wh_modification_datefixeddates] => [wh_modification_date2fixeddates] => [wh_pay_statuscustom] => [wh_pay_status] => [wh_cost] => 0 [wh_cost2] => 0 [wh_sort] => [wh_trash] => [page_num] => 1 [page_items_count] => 10 [view_days_num] => 30 [scroll_start_date] => [scroll_day] => 0 [scroll_month] => 0 [limit_hours] => [only_booked_resources] => 0 ) * * @return array = Array( [count] => 14 [data_arr] => Array ( [0] => Array ( [ajx_booking_id] => 14 [last_check_booking_id] => 0 [status] => [last_run_date] => [booking] => Array ( [email_template] => super_new [conditions] => Array ( [0] => Array ( [if] => __system__|source [sign] => >= [value] => 1"0'0\0 ) ), ... ) [ru_create_date] => 2020-01-25 10:36:55 ... ), ... */ function wpbc_ajx_get_booking_data_arr( $request_params ){ // 1. Get booking resources (sql) $resources_arr = wpbc_ajx_get_all_booking_resources_arr(); /** * Array ( [0] => Array ( [booking_type_id] => 1 [title] => Standard [users] => 1 [import] => [export] => [cost] => 25 [default_form] => standard [prioritet] => 0 [parent] => 0 [visitors] => 2 ), ... */ $resources_arr_sorted = wpbc_ajx_get_sorted_booking_resources_arr( $resources_arr ); // 2. Get all bookings (sql) $bookings = wpbc_ajx_get__bookings_obj__sql( $request_params ); /** * Array ( [count] => 172, [bookings] => Array ( * [0] => stdClass Object ( [booking_id] => 175 [trash] => 0 [sync_gid] => [is_new] => 1 [status] => [sort_date] => 2022-04-19 12:00:01 [modification_date] => 2022-04-03 08:05:13 [form] => selectbox-one^rangetime5^12:00 - 14:00~text^name5^test data~ ... ~checkbox^term_and_condition5[]^I Accept terms [hash] => ae964965356f7c735139764eebe12a63 [booking_type] => 5 [remark] => [cost] => 50.00 [pay_status] => 164896951360.82 [pay_request] => 0 ), .... */ $bookings_obj = $bookings['bookings']; $bookings_count = $bookings['count']; // 3. Get booking dates (sql) $booking_dates_obj = wpbc_ajx_get__booking_dates_obj__sql( $bookings_obj ); /** * Array ( [0] => stdClass Object ( [booking_dates_id] => 333 [booking_id] => 165 [booking_date] => 2022-03-28 11:00:01 [approved] => 0 [type_id] => ) [1] => .... */ // 4. Include dates into bookings (Wide and Short dates view) $bookings_with_dates = wpbc_ajx_include_bookingdates_in_bookings( $bookings_obj, $booking_dates_obj ); /** Array ( [182] => stdClass Object ( [booking_db] => stdClass Object ( [booking_id] => 182 [trash] => 0 [sync_gid] => [is_new] => 1 [status] => [sort_date] => 2023-01-23 10:00:01 [modification_date] => 2022-04-18 12:23:30 [form] => selectbox-one^rangetime2^10:00 - 12:00~text^name2^rr~text^secondname2^hjk~email^email2^hyui@nbco.csdf~text^phone2^h~text^address2^khj~text^city2^e~text^postcode2^hj~selectbox-one^country2^HT~selectbox-one^visitors2^1~selectbox-one^children2^0~textarea^details2^djkh~checkbox^term_and_condition2[]^I Accept term and conditions [hash] => a1ae510d8fee961b7f8ae53101632151 [booking_type] => 2 [remark] => [cost] => 75.00 [pay_status] => 165028101080.84 [pay_request] => 0 ) [id] => 182 [approved] => 0 [dates] => Array ( [0] => 2023-01-23 10:00:01 [1] => 2023-01-25 00:00:00 [2] => 2023-01-27 12:00:02 ) [child_id] => Array ( [0] => [1] => [2] => ) [short_dates] => Array ( [0] => 2023-01-23 10:00:01 [1] => , [2] => 2023-01-25 00:00:00 [3] => , [4] => 2023-01-27 12:00:02 ) [short_dates_child_id] => Array ( [0] => [1] => [2] => [3] => [4] => ) ) [181] => stdClass Object ... */ // 4.5 remove some bookings, that does not fit to Dates conditions list( $bookings_with_dates, $bookings_count ) = wpbc_ajx_get__remove_bookings__where_dates_outside( $request_params, $bookings_with_dates, $bookings_count ); // 5. Parse forms $parsed_bookings = wpbc_ajx_parse_bookings( $bookings_with_dates, $resources_arr ); /** array( [188] => stdClass Object ( [booking_db] => stdClass Object ( [booking_id] => 188 [trash] => 0 [sync_gid] => [is_new] => 1 [status] => [sort_date] => 2023-03-05 10:00:01 [modification_date] => 2022-04-19 11:58:31 [form] => text^selected_short_dates_hint4^March 5, 2023~text^days_number_hint4^1~text^cost_hint4^&#36;95~selectbox-one^rangetime4^10:00 - 12:00~text^name4^test~email^email4^test@wpbookingcalendar.com~selectbox-one^my_select4^1~selectbox-multiple^multi_select4[]^0,1,2,3~checkbox^my_checkbx4[]^false~checkbox^my_multi_checkbx4[]^1~checkbox^my_multi_checkbx4[]^~checkbox^my_multi_checkbx4[]^3~checkbox^exclusive_multi_checkbx4^~checkbox^exclusive_multi_checkbx4^2~checkbox^exclusive_multi_checkbx4^~radio^my_radio4^2~selectbox-one^country4^GB~textarea^details4^s~checkbox^term_and_condition4[]^I Accept term and conditions [hash] => dd12c3a61f14aaca693f52d110d2723a [booking_type] => 4 [remark] => [cost] => 95.00 [pay_status] => 165036591118.88 [pay_request] => 0 ) [id] => 188 [approved] => 0 [dates] => Array ( [0] => 2023-03-05 10:00:01 [1] => 2023-03-05 12:00:02 ) [child_id] => Array([0] => [1] => ) [short_dates] => Array ( [0] => 2023-03-05 10:00:01 [1] => - [2] => 2023-03-05 12:00:02 ) [short_dates_child_id] => Array ( [0] => [1] => [2] => ) [form_data] => Array ( [selected_short_dates_hint] => March 5, 2023 [days_number_hint] => 1 [cost_hint] => &#36;95 [rangetime] => 10:00 AM - 12:00 PM [name] => test ... [term_and_condition] => I Accept term and conditions [booking_id] => 188 [trash] => 0 [sync_gid] => [is_new] => 1 [status] => [sort_date] => 2023-03-05 10:00:01 [modification_date] => 2022-04-19 11:58:31 [hash] => dd12c3a61f14aaca693f52d110d2723a [booking_type] => 4 [cost] => 95.00 [pay_status] => 165036591118.88 [pay_request] => 0 [id] => 188 [approved] => 0 [resource_title] => Apartment#3 [_form_show] => "<div class="payment-content-form"><strong>Times</strong>:<span class="fieldvalue">10:00 AM - 12:00 PM</span> ...." ) ... */ // Reset array keys for correct DESC sorting during sending Ajax request. $parsed_bookings = array_values( $parsed_bookings ); return array( 'booking_resources' => $resources_arr_sorted, //$resources_arr, 'data_arr' => $parsed_bookings, 'count' => $bookings_count ); } /** * R E S O U R C E S - Get SORTED booking resources as array * * @param $resources_arr array Array ( [1] => Array ( [booking_type_id] => 1 [title] => Standard [users] => 1 [import] => [export] => [cost] => 25 [default_form] => standard [prioritet] => 0 [parent] => 0 [visitors] => 2 ), ... * * @return array */ function wpbc_ajx_get_sorted_booking_resources_arr( $resources_arr ) { if ( ! empty( $resources_arr ) ) { $resources_arr_sorted = wpbc_ajx_arrange_booking_resources_arr( $resources_arr ); $resources_arr_sorted = $resources_arr_sorted['linear_resources']; foreach ( $resources_arr_sorted as $key_id => $resource ) { $resources_arr_sorted[ $key_id ]['title'] = wpbc_lang( $resources_arr_sorted[ $key_id ]['title'] ); } // Reset keys for having correct sorting (important for parent/child resources) after ajax response $resources_arr_sorted = array_values( $resources_arr_sorted ); } else { $resources_arr_sorted = $resources_arr; } return $resources_arr_sorted; } /** * R E S O U R C E S - Get all booking resources as array * * @return array Array ( [1] => Array ( [booking_type_id] => 1 [title] => Standard [users] => 1 [import] => [export] => [cost] => 25 [default_form] => standard [prioritet] => 0 [parent] => 0 [visitors] => 2 ), ... */ function wpbc_ajx_get_all_booking_resources_arr( ){ if ( ! class_exists( 'wpdev_bk_personal' ) ) { return array(); } $db_names = wpbc_get_db_names(); $sql = array(); $sql['select'] = "SELECT * FROM {$db_names['resources']} as bt"; $sql['where'] = " WHERE ( 1 = 1 )"; if ( class_exists( 'wpdev_bk_multiuser' ) ) { // MultiUser - only specific booking resources for specific Regular User in Admin panel. if ( isset( $_REQUEST['wpbc_ajx_user_id'] ) ) { $user_bk_id = intval( $_REQUEST['wpbc_ajx_user_id'] ); } else { $user_bk_id = wpbc_get_current_user_id(); } $is_user_super_admin = apply_bk_filter( 'is_user_super_admin', $user_bk_id ); if ( ! $is_user_super_admin ) { $sql['where'] .= 'AND users = ' . $user_bk_id . ' '; } } // Order depends from version //FixIn: 9.9.0.23 if ( class_exists( 'wpdev_bk_biz_l' ) ) { $sql['order'] = " ORDER BY parent, prioritet, title, booking_type_id"; } else { $sql['order'] = " ORDER BY title, booking_type_id"; } global $wpdb; $sql_prepared = //$wpdb->prepare( $sql['select'] . $sql['where'] . $sql['order']; // , $sql['sql_args'] // ); $resources = $wpdb->get_results( $sql_prepared ); $resources_arr = array(); foreach ( $resources as $resource ) { $resources_arr[ $resource->booking_type_id ] = get_object_vars( $resource ); } return $resources_arr; } /** * Get arranged / sorted booking resources arrays * * @param $resources_sql_arr array( ... * [4] => Array ( [booking_type_id] => 4 [title] => Apartment#3 [users] => 1 [import] => [export] => [cost] => 270 [default_form] => standard [prioritet] => 1 [parent] => 0 [visitors] => 1 ) [5] => Array ( [booking_type_id] => 5 [title] => Standard-1 [users] => 1 [import] => [export] => [cost] => 25 [default_form] => standard [prioritet] => 1 [parent] => 1 [visitors] => 1 ) ... */ function wpbc_ajx_arrange_booking_resources_arr( $all_resources ){ if ( count( $all_resources ) > 0 ) { $resources = array(); $child_resources = array(); $parent_single_resources = array(); foreach ( $all_resources as $single_resources ) { $single_resources = $single_resources ; $single_resources['id'] = $single_resources['booking_type_id']; // Child booking resource if ( ( ! empty( $single_resources[ 'parent' ] ) ) ){ // Child if ( ! isset( $child_resources[ $single_resources['parent'] ] ) ) $child_resources[ $single_resources['parent'] ] = array(); $child_resources[ $single_resources['parent'] ][ $single_resources['id'] ] = $single_resources; } else { // Parent or Single $parent_single_resources[ $single_resources['id'] ] = $single_resources; } // All resources $resources[ $single_resources['id'] ] = $single_resources; } $final_resource_array = array(); foreach ( $parent_single_resources as $key => $res) { // Calc Capacity if ( isset( $child_resources[$res['id']] ) ) $res['count'] = count( $child_resources[$res['id']] ) + 1; else $res['count'] = 1; // Fill the parent resource $final_resource_array[ $res['id'] ] = $res; // Fill all child resources (its already sorted) - for having linear array with child resourecs. if ( isset( $child_resources[ $res['id'] ] ) ) { foreach ( $child_resources[ $res['id'] ] as $child_obj ) { $child_obj['count'] = 1; $final_resource_array[ $child_obj['id'] ] = $child_obj; } } } return array( 'linear_resources' => $final_resource_array , 'single_or_parent' => $parent_single_resources , 'child' => $child_resources ); } else { return false; } } /** * S Q L - B O O K I N G S - Get array of "Bookings" objects from DB * based on request params * * @param array $request_params * * @return array of bookings sql objects */ function wpbc_ajx_get__bookings_obj__sql( $request_params ) { $defaults = wpbc_ajx_get__request_params__names_default( 'default' ); $params = wp_parse_args( $request_params, $defaults ); global $wpdb; $db_names = wpbc_get_db_names(); $sql_args = array(); $sql = array(); $sql['start_select'] = " SELECT * "; $sql['start_count'] = " SELECT COUNT(*) as count"; $sql['from'] = " FROM {$db_names['bookings']} as bk"; $sql['where'] = " WHERE ( 1 = 1 )"; //////////////////////////////////////////////////////////////////////////////////////////////////////////// // DATES //////////////////////////////////////////////////////////////////////////////////////////////////////////// $sql['where'] .= " AND ( EXISTS ( SELECT * FROM {$db_names['dates']} as dt WHERE bk.booking_id = dt.booking_id "; // W H E R E : Approved | Pending ---------------------------------------------------------------------- if ( $request_params['wh_approved'] !== '' ) { $sql['where'] .= " AND approved = {$request_params['wh_approved']} "; } // W H E R E : D A T E S -------------------------------------------------------------------------------- if (1){ if ( is_array( $request_params['wh_booking_date'] ) ) { $wh_booking_date = array_replace( array( '', '' ), $request_params['wh_booking_date'] ); // Always have minimum 2 values in arr } else { $wh_booking_date = array( '', '' ); } if ( count( $wh_booking_date ) > 2 ) { $removed_el = array_shift( $wh_booking_date ); // Remove an element off the beginning of array } } $sql['where'] .= wpbc_ajx__sql_where_for_dates( (string) $wh_booking_date[0], (string) $wh_booking_date[1] ); $sql['where'] .= " ) )"; //////////////////////////////////////////////////////////////////////////////////////////////////////////// // W H E R E : M o d i f i c a t i o n D A T E S -------------------------------------------------- if (1){ if ( is_array( $request_params['wh_modification_date'] ) ) { $wh_modification_date = array_replace( array( '', '' ), $request_params['wh_modification_date'] ); // Always have minimum 2 values in arr } else { $wh_modification_date = array( '', '' ); } if ( count( $wh_modification_date ) > 2 ) { $removed_el = array_shift( $wh_modification_date ); // Remove an element off the beginning of array } } $sql['where'] .= wpbc_ajx__sql_where_for_modification_date( (string) $wh_modification_date[0], (string) $wh_modification_date[1] ); // W H E R E : Resources ------------------------------------------------------------------------------ if ( class_exists( 'wpdev_bk_personal' ) ) { if ( ! empty( $request_params['wh_booking_type'] ) ) { $sql['where'] .= wpbc_ajx__sql_where_for_resources( $request_params['wh_booking_type'], $request_params['wh_approved'], (string) $wh_booking_date[0], (string) $wh_booking_date[1] ); } } // W H E R E : Payment Status ------------------------------------------------------------------------- if ( class_exists( 'wpdev_bk_biz_s' ) ) { if ( ! empty( $request_params['wh_pay_status'] ) ) { $sql_and_args = wpbc_ajx__sql_where_for_payment_status( $request_params['wh_pay_status'] ); $sql['where'] .= $sql_and_args[0]; if ( count( $sql_and_args[1] ) > 0 ) { foreach ( $sql_and_args[1] as $my_arg ) { $sql_args[] = $my_arg; } } } } // W H E R E : C o s t Min - Max ------------------------------------------------------------------- if ( class_exists( 'wpdev_bk_biz_s' ) ) { if ( ( isset( $request_params['wh_cost'] ) ) || ( isset( $request_params['wh_cost2'] ) ) ) { $wh_cost_min = ( isset( $request_params['wh_cost'] ) ) ? $request_params['wh_cost'] : ''; $wh_cost_max = ( isset( $request_params['wh_cost2'] ) ) ? $request_params['wh_cost2'] : ''; $sql_and_args = wpbc_ajx__sql_where_cost_min_max( $wh_cost_min, $wh_cost_max ); $sql['where'] .= $sql_and_args[0]; if ( count( $sql_and_args[1] ) > 0 ) { foreach ( $sql_and_args[1] as $my_arg ) { $sql_args[] = $my_arg; } } } } // W H E R E : Trash ----------------------------------------------------------------------------------- if ( isset( $request_params['wh_trash'] ) ) { if ( '0' === $request_params['wh_trash'] ) { // Existing $sql['where'] .= " AND bk.trash = 0 "; } if ( 'trash' === $request_params['wh_trash'] ) { // In trash $sql['where'] .= " AND bk.trash = 1 "; } //if ( 'any' === $request_params['wh_trash'] ) { } // Any } // W H E R E : All bookings | New bookings | Imported bookings | Plugin bookings if ( isset( $request_params['wh_what_bookings'] ) ) { if ( 'any' === $request_params['wh_what_bookings'] ) { //$sql['where'] .= " AND bk.is_new = 0 "; } if ( 'new' === $request_params['wh_what_bookings'] ) { $sql['where'] .= " AND bk.is_new = 1"; } if ( 'imported' === $request_params['wh_what_bookings'] ) { $sql['where'] .= " AND bk.sync_gid != '' "; } if ( 'in_plugin' === $request_params['wh_what_bookings'] ) { $sql['where'] .= " AND bk.sync_gid = '' "; } } // W H E R E : K E Y W O R D if ( ! empty( $params['keyword'] ) ) { $sql['where'] .= " AND ( "; /** * Relative configuration of LIKE sanitization * check at the bottom here https://code.tutsplus.com/articles/data-sanitization-and-validation-with-wordpress--wp-25536 * * So this is a correct way: * * $sql['where'] .= "( bk.form LIKE %s ) "; * $sql_args[] = '%' . $wpdb->esc_like( $params['keyword'] ) . '%'; * */ $sql['where'] .= "( bk.form LIKE %s ) "; $sql_args[] = '%' . $wpdb->esc_like( $params['keyword'] ) . '%'; if ( is_numeric( $params['keyword'] ) ) { $sql['where'] .= " OR ( bk.booking_id = %d ) "; $sql_args[] = intval( $params['keyword'] ); } $sql['where'] .= " OR ( bk.sync_gid LIKE %s ) "; $sql_args[] = '%' . $wpdb->esc_like( $params['keyword'] ) . '%'; if ( class_exists( 'wpdev_bk_personal' ) ) { $sql['where'] .= " OR ( bk.remark LIKE %s ) "; $sql_args[] = '%' . $wpdb->esc_like( $params['keyword'] ) . '%'; $sql['where'] .= " OR ( bk.hash LIKE %s ) "; $sql_args[] = '%' . $wpdb->esc_like( $params['keyword'] ) . '%'; } $sql['where'] .= " )"; // W H E R E : booking ID //FixIn: 9.4.3.9 $is_id = strpos( trim( strtolower( $params['keyword'] ) ) , 'id:' ); // Keyword, like 'id:200' OR 'id:100,105' if ( 0 === $is_id ){ $search_booking_id = substr( trim( $params['keyword'] ), 3 ); $search_booking_id_arr = explode( ',', $search_booking_id ); // Get array of booking ID: from 'id:200,201,15' we get [200,201,15] $sql_where_arr = array(); $sql_args = array(); // It's last WHERE in a list so all previous arguments ($sql_args) we are resetting foreach ( $search_booking_id_arr as $bk_id ) { $sql_where_arr[] = ' bk.booking_id = %d '; $sql_args[] = intval( $bk_id ); } $sql['where'] = " WHERE ( " . implode( ' OR ', $sql_where_arr ) . ") "; $sql['where'] = apply_bk_filter('update_where_sql_for_getting_bookings_in_multiuser', $sql['where'] ); // Add 'AND bk.booking_type IN ( $user_resources )' to the end of Where } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// switch ( $params['wh_sort'] ) { case 'booking_id__asc': $order_by = 'booking_id ASC '; break; case 'booking_id__desc': $order_by = 'booking_id DESC '; break; case 'dates__asc': $order_by = 'sort_date ASC '; break; case 'dates__desc': $order_by = 'sort_date DESC '; break; case 'resource__asc': $order_by = 'booking_type ASC '; break; case 'resource__desc': $order_by = 'booking_type DESC '; break; case 'cost__asc': $order_by = 'cost ASC '; break; case 'cost__desc': $order_by = 'cost DESC '; break; default: $order_by = 'booking_id ASC '; } $sql['order'] = " ORDER BY bk." . $order_by; // $sql['order'] = " ORDER BY bk." . esc_sql( $params['sort'] ) . ( ( 'DESC' == $params['sort_type'] ) ? " DESC " : " ASC " ); $sql_args_count = $sql_args; // For SELECT COUNT(*) as count we do not need other parameters $sql['limit'] = " LIMIT %d, %d "; $sql_args[] = ( $params['page_num'] - 1 ) * $params['page_items_count']; $sql_args[] = $params['page_items_count']; /** * Good Practice: https://blog.ircmaxell.com/2017/10/disclosure-wordpress-wpdb-sql-injection-technical.html * fixed in WordPress 4.8.3 * $where = "WHERE foo = %s"; $args = [$_GET['data']]; $args[] = 1; $args[] = 2; $query = $wpdb->prepare("SELECT * FROM something $where LIMIT %d, %d", $args); * */ //////////////////////////////////////////////////////////////////////////////////////////////////////////// // SELECT at this specific PAGE ///////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////// $sql_prepared = $wpdb->prepare( $sql['start_select'] . $sql['from'] . $sql['where'] . $sql['order'] . $sql['limit'] , $sql_args ); $bookings_sql_obj = $wpdb->get_results($sql_prepared); //////////////////////////////////////////////////////////////////////////////////////////////////////////// // COUNT of items with this WHERE /////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////// $sql_for_listing_count = $sql['start_count'] . $sql['from'] . $sql['where']; if ( false === strpos( $sql_for_listing_count, '%' ) ) { $sql_prepared = $sql_for_listing_count; } else { $sql_prepared = $wpdb->prepare( $sql_for_listing_count , $sql_args_count ); } $bookings_count = $wpdb->get_results( $sql_prepared ); $bookings_count = ( ( count( $bookings_count ) > 0 ) ? $bookings_count[0]->count : 0 ); return array( 'count' => $bookings_count , 'bookings' => $bookings_sql_obj ); } // W H E R E C O N D I T I O N S /** * Get SQL W H E R E conditions for D a t e s of bookings * * @param string $wh_booking_date - Parameter from Booking Listing request (usually its number) * @param string $wh_booking_date2 - Parameter from Booking Listing request (usually its number) * @param string $pref - Optional. Prefix for table. * @return string - WHERE conditions for SQL */ function wpbc_ajx__sql_where_for_dates( $wh_booking_date, $wh_booking_date2, $pref = 'dt.' ) { $wh_booking_date = (string) $wh_booking_date; $wh_booking_date2 = (string) $wh_booking_date2; $sql_where= ''; if ($pref == 'dt.') { $and_pre = ' AND '; $and_suf = ''; } else { $and_pre = ''; $and_suf = ' AND '; } // Actual if ( ( ( $wh_booking_date === '' ) && ( $wh_booking_date2 === '' ) ) || ($wh_booking_date === '0') ) { $sql_where = $and_pre."( ".$pref."booking_date >= ( CURDATE() - INTERVAL '00:00:01' HOUR_SECOND ) ) ".$and_suf ; //FixIn: 8.5.2.14 } else if ($wh_booking_date === '1') { // Today //FixIn: 7.1.2.8 $sql_where = $and_pre."( ".$pref."booking_date <= ( CURDATE() + INTERVAL '23:59:59' HOUR_SECOND ) ) ".$and_suf ; $sql_where .= $and_pre."( ".$pref."booking_date >= ( CURDATE() - INTERVAL '00:00:01' HOUR_SECOND ) ) ".$and_suf ; //FixIn: 8.4.7.21 } else if ($wh_booking_date === '2') { // Previous $sql_where = $and_pre."( ".$pref."booking_date <= ( CURDATE() - INTERVAL '00:00:01' HOUR_SECOND ) ) ".$and_suf ; //FixIn: 8.5.2.16 } else if ($wh_booking_date === '3') { // All $sql_where = ''; } else if ($wh_booking_date === '4') { // Next $sql_where = $and_pre."( ".$pref."booking_date <= ( CURDATE() + INTERVAL ". $wh_booking_date2 . " DAY ) ) ".$and_suf ; // $sql_where .= $and_pre."( ".$pref."booking_date >= ( CURDATE() - INTERVAL 1 DAY ) ) ".$and_suf ; $sql_where .= $and_pre."( ".$pref."booking_date > ( CURDATE() ) ) ".$and_suf ; //FixIn: 8.0.1.1 } else if ($wh_booking_date === '5') { // Prior $wh_booking_date2 = str_replace('-', '', $wh_booking_date2); $sql_where = $and_pre."( ".$pref."booking_date >= ( CURDATE() - INTERVAL ". $wh_booking_date2 . " DAY ) ) ".$and_suf ; $sql_where .= $and_pre."( ".$pref."booking_date <= ( CURDATE() + INTERVAL 1 DAY ) ) ".$and_suf ; } else if ($wh_booking_date === '7') { // Check In date - Today/Tomorrow // $sql_where = $and_pre."( ".$pref."booking_date <= ( CURDATE() + INTERVAL '23:59:59' HOUR_SECOND ) ) ".$and_suf ; // $sql_where .= $and_pre."( ".$pref."booking_date >= ( CURDATE() ) ) ".$and_suf ; $sql_where = $and_pre."( ".$pref."booking_date <= ( CURDATE() + INTERVAL '1 23:59:59' DAY_SECOND ) ) ".$and_suf ; $sql_where .= $and_pre."( ".$pref."booking_date >= ( CURDATE() + INTERVAL 1 DAY ) ) ".$and_suf ; } else if ($wh_booking_date === '8') { // Check Out date - Tomorrow $sql_where = $and_pre."( ".$pref."booking_date <= ( CURDATE() + INTERVAL '1 23:59:59' DAY_SECOND ) ) ".$and_suf ; $sql_where .= $and_pre."( ".$pref."booking_date >= ( CURDATE() + INTERVAL 1 DAY ) ) ".$and_suf ; } else if ( ( $wh_booking_date === '9' ) || ( $wh_booking_date === '10' ) || ( $wh_booking_date === '11' ) ) { // Today check in/out $sql_where = $and_pre."( ".$pref."booking_date <= ( CURDATE() + INTERVAL 1 DAY ) ) ".$and_suf ; $sql_where .= $and_pre."( ".$pref."booking_date >= ( CURDATE() - INTERVAL 1 DAY ) ) ".$and_suf ; } else { // Fixed $wh_booking_date = wpbc_sanitize_date( $wh_booking_date ); $wh_booking_date2 = wpbc_sanitize_date( $wh_booking_date2 ); /* if ( $wh_booking_date !== '' ){ $sql_where .= $and_pre . "( " . $pref . "booking_date >= ( '" . $wh_booking_date . "' - INTERVAL '00:00:01' HOUR_SECOND ) ) " . $and_suf; } if ( $wh_booking_date2 !== '' ) { $sql_where .= $and_pre . "( " . $pref . "booking_date <= ( '" . $wh_booking_date2 . "' + INTERVAL '23:59:59' HOUR_SECOND ) ) " . $and_suf; } */ if ( $wh_booking_date !== '' ) { if ( strpos( $wh_booking_date, ':' ) === false ) { $sql_where .= $and_pre . "( " . $pref . "booking_date >= '" . $wh_booking_date . " 00:00:00' ) " . $and_suf; } else { $sql_where .= $and_pre . "( " . $pref . "booking_date >= '" . $wh_booking_date . "' ) " . $and_suf; } } if ( $wh_booking_date2 !== '' ) { if ( strpos( $wh_booking_date2, ':' ) === false ) { $sql_where .= $and_pre . "( " . $pref . "booking_date <= '" . $wh_booking_date2 . " 23:59:59' ) " . $and_suf; } else { $sql_where .= $and_pre . "( " . $pref . "booking_date <= '" . $wh_booking_date2 . "' ) " . $and_suf; } } } return $sql_where; } /** * Get SQL W H E R E conditions for M o d i f i c a t i o n D a t e of bookings * * @param string $wh_modification_date - Parameter from Booking Listing request (usually its number) * @param string $wh_modification_date2 - Parameter from Booking Listing request (usually its number) * @param string $pref - Optional. Prefix for table. * @return string - WHERE conditions for SQL */ function wpbc_ajx__sql_where_for_modification_date( $wh_modification_date, $wh_modification_date2, $pref = 'bk.' ) { $sql_where = ''; if ($pref == 'bk.') { $and_pre = ' AND '; $and_suf = ''; } else { $and_pre = ''; $and_suf = ' AND '; } if ($wh_modification_date === '1') { // Today $sql_where = $and_pre."( ".$pref."modification_date <= ( CURDATE() + INTERVAL '23:59:59' HOUR_SECOND ) ) ".$and_suf ; //FixIn: 8.4.7.22 $sql_where .= $and_pre."( ".$pref."modification_date >= ( CURDATE() - INTERVAL '00:00:01' HOUR_SECOND ) ) ".$and_suf ; //FixIn: 8.4.7.22 } else if ($wh_modification_date === '3') { // All $sql_where = ''; } else if ($wh_modification_date === '5') { // Prior $wh_modification_date2 = str_replace('-', '', $wh_modification_date2); $sql_where = $and_pre."( ".$pref."modification_date >= ( CURDATE() - INTERVAL ". $wh_modification_date2 . " DAY ) ) ".$and_suf ; $sql_where .= $and_pre."( ".$pref."modification_date <= ( CURDATE() + INTERVAL 1 DAY ) ) ".$and_suf ; } else { // Fixed $wh_modification_date = wpbc_sanitize_date( $wh_modification_date ); //FixIn: 9.4.4.1 $wh_modification_date2 = wpbc_sanitize_date( $wh_modification_date2 ); if ( $wh_modification_date !== '' ) $sql_where.= $and_pre."( ".$pref."modification_date >= ( '" . $wh_modification_date . "' - INTERVAL '00:00:01' HOUR_SECOND ) ) ".$and_suf; if ( $wh_modification_date2 !== '' ) $sql_where.= $and_pre."( ".$pref."modification_date <= ( '" . $wh_modification_date2 . "' + INTERVAL '23:59:59' HOUR_SECOND ) ) ".$and_suf; } return $sql_where; } /** * Get SQL W H E R E conditions for B o o k i n g R e s o u r c e s * * @param $wh_booking_type * @param $wh_approved * @param $wh_booking_date * @param $wh_booking_date2 * * @return string - SQL */ function wpbc_ajx__sql_where_for_resources( $wh_booking_type, $wh_approved, $wh_booking_date, $wh_booking_date2 ){ global $wpdb; if ( ! class_exists( 'wpdev_bk_personal' ) ) { return ''; } if ( is_array( $wh_booking_type ) ) { $wh_booking_type = implode( ',', $wh_booking_type ); } $sql_where = ''; if ( '0' === $wh_booking_type ) { // All booking resources // Get all booking resources of this user $resources_sql_arr = wpbc_ajx_get_all_booking_resources_arr(); $wh_booking_type = implode( ',', array_keys( $resources_sql_arr ) ); //$resources_arr = wpbc_ajx_arrange_booking_resources_arr( $resources_sql_arr ); } if ( '-1' === $wh_booking_type ) { // Lost booking resources $is_show_lost = true; if ( class_exists( 'wpdev_bk_multiuser' ) ) { // MultiUser - Only for super booking admin user $user_bk_id = ( isset( $_REQUEST['wpbc_ajx_user_id'] ) ) ? intval( $_REQUEST['wpbc_ajx_user_id'] ) : wpbc_get_current_user_id(); $is_user_super_admin = apply_bk_filter( 'is_user_super_admin', $user_bk_id ); if ( ! $is_user_super_admin ) { $is_show_lost = false; // For regular user show all bookings from the booking resources that belong to this user. $sql_where .= " AND bk.booking_type IN ( SELECT DISTINCT booking_type_id FROM {$wpdb->prefix}bookingtypes WHERE users = " . $user_bk_id . " ) "; } } // "Lost" bookings in deleted booking resources if ( $is_show_lost ) { $sql_where .= " AND bk.booking_type NOT IN ( SELECT DISTINCT booking_type_id FROM {$wpdb->prefix}bookingtypes ) "; } } else if ( ! empty( $wh_booking_type ) ) { // P $sql_where .= " AND ( "; $sql_where .= " ( bk.booking_type IN ( " . $wh_booking_type . " ) ) "; // BL - Show bookings from child booking resources, if was selected only parent booking resource $is_show_bookings_for_child_resources = true; if ( $is_show_bookings_for_child_resources ) { $sql_where .= wpbc_ajx__sql_where_for_resources_bl( $wh_booking_type, $wh_approved, $wh_booking_date, $wh_booking_date2 ); } // P $sql_where .= " ) "; // MU - Check if searching bookings are belongs to specific user in Booking Calendar MultiUser version $sql_where = apply_bk_filter( 'update_where_sql_for_getting_bookings_in_multiuser', $sql_where ); } return $sql_where; } /** * Get SQL W H E R E conditions for B o o k i n g R e s o u r c e s BL - Capacity * * @param $wh_booking_type * @param $wh_approved * @param $wh_booking_date * @param $wh_booking_date2 * * @return string - SQL */ function wpbc_ajx__sql_where_for_resources_bl( $wh_booking_type, $wh_approved, $wh_booking_date, $wh_booking_date2 ){ if ( ! class_exists( 'wpdev_bk_biz_l' ) ) { return ''; } global $wpdb; $sql_where = ''; // BL // Childs in dif sub resources $sql_where.= " OR ( bk.booking_id IN ( SELECT DISTINCT booking_id FROM {$wpdb->prefix}bookingdates as dtt WHERE " ; if ($wh_approved !== '') $sql_where.= " dtt.approved = $wh_approved AND " ; $sql_where .= wpbc_ajx__sql_where_for_dates( $wh_booking_date, $wh_booking_date2, 'dtt.' ); $sql_where.= " ( dtt.type_id IN ( ". $wh_booking_type ." ) OR dtt.type_id IN ( SELECT booking_type_id FROM {$wpdb->prefix}bookingtypes as bt WHERE bt.parent IN ( ". $wh_booking_type ." ) ) ) ) ) " ; if ( ( isset($_REQUEST['view_mode']) ) && ( $_REQUEST['view_mode']== 'vm_calendar' ) ) { // Skip the bookings from the children resources, if we are in the Calendar view mode at the admin panel } else { // BL // Just children booking resources $sql_where .= " OR ( bk.booking_type IN ( SELECT booking_type_id FROM {$wpdb->prefix}bookingtypes as bt WHERE bt.parent IN ( " . $wh_booking_type . " ) ) )"; } return $sql_where; } /** * Get SQL W H E R E conditions for P a y m e n t S t a t u s * * @param $wh_pay_status [ 'any ' ] | ['group_ok'] | ['group_unknown' ] | ['group_pending'] | ['group_failed'] | [ 'user_entered', 'myCustom status' ] * * @return array [ string SQL, array ARGS ] */ function wpbc_ajx__sql_where_for_payment_status( $wh_pay_status_arr ){ // [ 'any ' ] | ['group_ok'] | ['group_unknown' ] | ['group_pending'] | ['group_failed'] | [ 'user_entered', 'myCustom status' ] $wh_pay_status_custom = ''; $wh_pay_status = ''; if ( ! empty( $wh_pay_status_arr ) ) { if ( count( $wh_pay_status_arr ) > 1 ) { $wh_pay_status_custom = $wh_pay_status_arr[1]; } $wh_pay_status = $wh_pay_status_arr[0]; } $sql_where = ''; $sql_args = array(); if ( ( '' != $wh_pay_status ) && ( 'all' != $wh_pay_status ) ) { $sql_where .= " AND ( "; // Check firstly if we are selected some goup of payment status if ( $wh_pay_status == 'group_ok' ) { // SUCCESS $payment_status = wpbc_get_payment_status_ok(); foreach ( $payment_status as $label ) { $sql_where .= " ( bk.pay_status = '" . $label . "' ) OR"; } $sql_where = substr( $sql_where, 0, - 2 ); } else if ( ( $wh_pay_status == 'group_unknown' ) || ( is_numeric( $wh_pay_status_custom ) ) ) { // UNKNOWN $payment_status = wpbc_get_payment_status_unknown(); foreach ( $payment_status as $label ) { $sql_where .= " ( bk.pay_status = '" . $label . "' ) OR"; } //$sql_where = substr($sql_where, 0, -2); $sql_where .= " ( bk.pay_status = '' ) OR ( bk.pay_status regexp '^[0-9]') "; } else if ( $wh_pay_status == 'group_pending' ) { // Pending $payment_status = wpbc_get_payment_status_pending(); foreach ( $payment_status as $label ) { $sql_where .= " ( bk.pay_status = '" . $label . "' ) OR"; } $sql_where = substr( $sql_where, 0, - 2 ); } else if ( $wh_pay_status == 'group_failed' ) { // Failed $payment_status = wpbc_get_payment_status_error(); foreach ( $payment_status as $label ) { $sql_where .= " ( bk.pay_status = '" . $label . "' ) OR"; } $sql_where = substr( $sql_where, 0, - 2 ); } else { // CUSTOM Payment Status $sql_where .= " bk.pay_status = %s "; // $wh_pay_status_custom = htmlspecialchars_decode( $wh_pay_status_custom ); // ? Convert special HTML entities back to characters: "< - >" to "< - >" $sql_args[] = $wh_pay_status_custom; } $sql_where .= " ) "; } return array( $sql_where, $sql_args ); } /** * Get SQL W H E R E conditions for C o s t Min - Max * * @param $wh_cost_min '' or number * @param $wh_cost_max '' or number * * @return array [ string SQL, array ARGS ] */ function wpbc_ajx__sql_where_cost_min_max( $wh_cost_min, $wh_cost_max ) { $sql_where = ''; $sql_args = array(); if ( $wh_cost_min !== '' ) { $sql_where .= " AND ( bk.cost >= %f ) "; $sql_args[] = $wh_cost_min; } if ( $wh_cost_max !== '' ) { $sql_where .= " AND ( bk.cost <= %f ) "; $sql_args[] = $wh_cost_max; } return array( $sql_where, $sql_args ); } /** * D A T E S - Get array of "Booking Dates" objects from DB * relative to specific bookings - array of Bookings objects from DB * * @param array of object $bookings_sql_obj * * @return array of booking dates sql objects */ function wpbc_ajx_get__booking_dates_obj__sql( $bookings_sql_obj ){ global $wpdb; $db_names = wpbc_get_db_names(); // Get list of booking ID from bookings obj /////////////////////////////////////////////////////////////// $booking_id_list = array(); foreach ( $bookings_sql_obj as $booking ) { $booking_id_list[] = intval( $booking->booking_id ); } $booking_id_list = array_unique( $booking_id_list ); // remove duplicates $booking_id_list = implode( ",", $booking_id_list ); //////////////////////////////////////////////////////////////////////////////////////////////////////////// if ( ! empty( $booking_id_list ) ) { // Get Dates for all our Bookings $sql = "SELECT * FROM {$db_names['dates']} as dt WHERE dt.booking_id in ( {$booking_id_list} ) "; if ( class_exists( 'wpdev_bk_biz_l' ) ) { $sql .= " ORDER BY booking_id, type_id, booking_date "; } else { $sql .= " ORDER BY booking_id, booking_date "; } $booking_dates_sql_obj = $wpdb->get_results( $sql ); } else { $booking_dates_sql_obj = array(); } return $booking_dates_sql_obj; } /** * S Q L - B O O K I N G S - Get array of "Bookings" objects from DB * based on request params * * @param array $request_params * @param array of object $bookings_sql_obj * * @return array of array( booking dates, $bookings_count) array( sql objects, int ) */ function wpbc_ajx_get__remove_bookings__where_dates_outside($request_params, $bookings_obj, $bookings_count){ $is_id = strpos( trim( strtolower( $request_params['keyword'] ) ) , 'id:' ); if ( false !== $is_id ) { return array( $bookings_obj, $bookings_count ); } // W H E R E : D A T E S -------------------------------------------------------------------------------- if (1){ if ( is_array( $request_params['wh_booking_date'] ) ) { $wh_booking_date_arr = array_replace( array( '', '' ), $request_params['wh_booking_date'] ); // Always have minimum 2 values in arr } else { $wh_booking_date_arr = array( '', '' ); } if ( count( $wh_booking_date_arr ) > 2 ) { $removed_el = array_shift( $wh_booking_date_arr ); // Remove an element off the beginning of array } } $wh_booking_date = (string) $wh_booking_date_arr[0]; $wh_booking_date2 =(string) $wh_booking_date_arr[1]; // Check In date - Tomorrow if ( $wh_booking_date === '7' ) { $today_mysql_format = date_i18n( 'Y-m-d', time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) + DAY_IN_SECONDS ); // Tommorow day with gmt offset foreach ( $bookings_obj as $bc_id => $bc_value ) { $check_in_date = $bc_value->short_dates[0]; $check_in_date = explode( ' ', $check_in_date ); $check_in_date = $check_in_date[0]; // 2014-02-25 if ( $today_mysql_format != $check_in_date ) { unset( $bookings_obj[ $bc_id ] ); $bookings_count--; } } } // Check Out date - Tomorrow if ( $wh_booking_date === '8' ) { $tomorrow_mysql_format = date_i18n( 'Y-m-d', time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) + DAY_IN_SECONDS ); // Tommorow day with gmt offset foreach ( $bookings_obj as $bc_id => $bc_value ) { if ( 1 == count( $bc_value->short_dates ) ) { $check_out_date = $bc_value->short_dates[0]; } else { $check_out_date = $bc_value->short_dates[2]; } $check_out_date = explode( ' ', $check_out_date ); $check_out_date = $check_out_date[0]; // 2014-02-25 if ( $tomorrow_mysql_format != $check_out_date ) { unset( $bookings_obj[ $bc_id ] ); $bookings_count --; } } } // Today == check in/out | Today = Check in | Today = Check out if ( ( $wh_booking_date === '9' ) || ( $wh_booking_date === '10' ) || ( $wh_booking_date === '11' ) ) { $today_mysql_format = date_i18n( 'Y-m-d', time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) + 0 * DAY_IN_SECONDS ); // Today day with gmt offset foreach ( $bookings_obj as $bc_id => $bc_value ) { $check_in_date = $bc_value->short_dates[0]; $check_in_date = explode( ' ', $check_in_date ); $check_in_date = $check_in_date[0]; // 2014-02-25 if ( count( $bc_value->short_dates ) == 1 ) { $check_out_date = $bc_value->short_dates[0]; } else { $check_out_date = $bc_value->short_dates[2]; } $check_out_date = explode( ' ', $check_out_date ); $check_out_date = $check_out_date[0]; // 2014-02-25 // Check In if ( $wh_booking_date === '10' ) { if ( $today_mysql_format != $check_in_date ) { unset( $bookings_obj[ $bc_id ] ); $bookings_count --; } } // Check out if ( $wh_booking_date === '11' ) { if ( $today_mysql_format != $check_out_date ) { unset( $bookings_obj[ $bc_id ] ); $bookings_count --; } } // Check In | Check out //FixIn: 9.6.3.12 if ( $wh_booking_date === '9' ) { if ( ( $today_mysql_format != $check_in_date ) && ( $today_mysql_format != $check_out_date ) ) { unset( $bookings_obj[ $bc_id ] ); $bookings_count --; } } } } return array( $bookings_obj, $bookings_count ); } /** * Get array of bookings with dates (wide and short dates view) * after inserting dates into the bookings * * @param $bookings_obj Array ( [0] => stdClass Object ( [booking_id] => 182 [trash] => 0 [sync_gid] => [is_new] => 1 [status] => [sort_date] => 2023-01-23 10:00:01 [modification_date] => 2022-04-18 12:23:30 [form] => selectbox-one^rangetime2^10:00 - 12:00~text^name2^rr~text^secondname2^hjk~email^email2^hyui@nbco.csdf~text^phone2^h~text^address2^khj~text^city2^e~text^postcode2^hj~selectbox-one^country2^HT~selectbox-one^visitors2^1~selectbox-one^children2^0~textarea^details2^djkh~checkbox^term_and_condition2[]^I Accept term and conditions [hash] => a1ae510d8fee961b7f8ae53101632151 [booking_type] => 2 [remark] => [cost] => 75.00 [pay_status] => 165028101080.84 [pay_request] => 0 ) [1] => stdClass Object, .... * @param $booking_dates_obj Array ( [0] => stdClass Object ( [booking_dates_id] => 294 [booking_id] => 147 [booking_date] => 2022-06-27 12:00:01 [approved] => 0 [type_id] => ) [1] => stdClass Object, ... * * @return array Array ( * [182] => stdClass Object ( * ... many other props .... * [id] => 182 * [approved] => 0 * [dates] => Array ( * [0] => 2023-01-23 10:00:01 * [1] => 2023-01-25 00:00:00 * [2] => 2023-01-27 12:00:02 * ) * [child_id] => Array ( * [0] => * [1] => * [2] => * ) * [short_dates] => Array ( * [0] => 2023-01-23 10:00:01 * [1] => , * [2] => 2023-01-25 00:00:00 * [3] => , * [4] => 2023-01-27 12:00:02 * ) * [short_dates_child_id] => Array ( * [0] => * [1] => * [2] => * [3] => * [4] => * ) * ) * [181] => stdClass Object ( * .... */ function wpbc_ajx_include_bookingdates_in_bookings( $bookings_obj, $booking_dates_obj ){ $bookings_arr = array(); foreach ( $bookings_obj as $booking ) { $bookings_arr[$booking->booking_id] = new StdClass; $bookings_arr[$booking->booking_id]->booking_db = $booking; $bookings_arr[$booking->booking_id]->id = $booking->booking_id; $bookings_arr[$booking->booking_id]->approved = 0; $bookings_arr[$booking->booking_id]->dates = array(); $bookings_arr[$booking->booking_id]->child_id = array(); /* $resource_id = (isset( $booking->booking_type )) ? $booking->booking_type : '1'; // booking Form parse can be here if ( ( isset( $booking->sync_gid ) ) && (!empty( $booking->sync_gid )) ) { $booking->form .= "~text^sync_gid{$booking->booking_type}^{$booking->sync_gid}"; } $cont = wpbc__legacy__get_form_content_arr( $booking->form , $resource_id , '' , array( 'booking_id' => $booking->booking_id , 'resource_title' => (isset( $booking_types[$booking->booking_type] )) ? $booking_types[$booking->booking_type] : '' ) ); $search = array( "'(<br[ ]?[/]?>)+'si", "'(<[/]?p[ ]?>)+'si" ); $replace = array( " ", " ", " " ); $cont['content'] = preg_replace( $search, $replace, $cont['content'] ); //debuge( htmlentities( $cont['content'] ) );die; $bookings_arr[$booking->booking_id]->form_show = $cont['content']; unset( $cont['content'] ); $bookings_arr[$booking->booking_id]->form_data = $cont; /**/ } // Wide dates in bookings foreach ( $booking_dates_obj as $date ) { $bookings_arr[ $date->booking_id ]->approved = $date->approved; $bookings_arr[ $date->booking_id ]->dates[] = $date->booking_date; $bookings_arr[ $date->booking_id ]->child_id[] = ( isset( $date->type_id ) ) ? $date->type_id : ''; } // Short dates foreach ( $bookings_arr as $booking_id => $booking ) { if ( count( $booking->dates ) == 0 ) { continue; } // If no dates, then skip $bookings_arr[ $booking_id ]->short_dates = array( $booking->dates[0] ); // First Day $bookings_arr[ $booking_id ]->short_dates_child_id = array( $bookings_arr[ $booking_id ]->child_id[0] ); $previous = array( 'date' => $booking->dates[0], 'date_index' => 0, 'separator' => false ); if ( count( $booking->dates ) == 1 ) { continue; } // if 1 date, then skip for ( $date_indx = 1; $date_indx < ( count( $booking->dates ) ); $date_indx ++ ) { // Start from 2nd day $date = $booking->dates[ $date_indx ]; // if ( wpbc_is_next_day( $date, $previous['date'] ) ) { $next_day_if__check_in__then__check_out = true; if ( wpbc_is_less_than_next_day( $date, $previous['date'], $next_day_if__check_in__then__check_out ) ) { if ( '-' != $previous['separator'] ) { $bookings_arr[ $booking_id ]->short_dates[] = '-'; $bookings_arr[ $booking_id ]->short_dates_child_id[] = ''; } $previous['separator'] = '-'; } else { if ( '-' == $previous['separator'] ) { $bookings_arr[ $booking_id ]->short_dates[] = $previous['date']; $bookings_arr[ $booking_id ]->short_dates_child_id[] = $bookings_arr[ $booking_id ]->child_id[ $previous['date_index'] ]; } $bookings_arr[ $booking_id ]->short_dates[] = ','; $bookings_arr[ $booking_id ]->short_dates_child_id[] = ''; $bookings_arr[ $booking_id ]->short_dates[] = $date; $bookings_arr[ $booking_id ]->short_dates_child_id[] = $bookings_arr[ $booking_id ]->child_id[ $date_indx ]; $previous['separator'] = ','; } $previous['date'] = $date; $previous['date_index'] = $date_indx; } // dates loop: $date_indx => $date if ( '-' == $previous['separator'] ) { $bookings_arr[ $booking_id ]->short_dates[] = $previous['date']; $bookings_arr[ $booking_id ]->short_dates_child_id[] = $bookings_arr[ $booking_id ]->child_id[ $previous['date_index'] ]; } } // bookings loop: $booking_id => $booking return $bookings_arr; } function wpbc_ajx_parse_bookings( $bookings_arr, $resources_arr ) { $user_id = ( isset( $_REQUEST['wpbc_ajx_user_id'] ) ) ? intval( $_REQUEST['wpbc_ajx_user_id'] ) : wpbc_get_current_user_id(); foreach ( $bookings_arr as $booking_id => $booking ) { // Booking resource ------------------------------------------------------------------------------------ $resource_id = ( isset( $booking->booking_db->booking_type ) ) ? $booking->booking_db->booking_type : '1'; $resource_title = ''; $resource_owner_user = $user_id; if ( class_exists( 'wpdev_bk_personal' ) ) { $resource_title = ( isset( $resources_arr[ $resource_id ] ) ) ? $resources_arr[ $resource_id ]['title'] : __( 'Resource not exist', 'booking' ); $resource_title = wpbc_lang( $resource_title ); } if ( class_exists( 'wpdev_bk_multiuser' ) ) { $resource_owner_user = ( isset( $resources_arr[ $resource_id ] ) ) ? $resources_arr[ $resource_id ]['users'] : $user_id; } // Parse form fields only from $booking->booking_db->form ------------------------------------------ $booking_data_arr = wpbc_parse_booking_data_fields( $booking->booking_db->form, array( 'resource_id' => $resource_id ) ); foreach ( $booking_data_arr as $booking_data_arr_key => $booking_data_arr_value ) { // Booking Listing escaping $booking_data_arr[$booking_data_arr_key] = wpbc_string__escape__then_convert__n_amp__html( $booking_data_arr_value ); } // Add system keys to data fields arr, like ( 'booking_id', 'trash', 'sync_gid'... --------------------- $booking_data_arr = wpbc_add_system_booking_data_fields( $booking_data_arr, array_merge( get_object_vars( $booking->booking_db ), array( 'id' => $booking->id, 'approved' => $booking->approved, 'wpbc_custom_booking_form' => '' //FixIn: 9.4.3.12 //FixIn: 9.4.4.9 ) ) , array( 'booking_id', 'trash', 'sync_gid', 'is_new', 'status', 'sort_date', 'modification_date', 'creation_date', 'hash', 'booking_type', 'remark', 'cost', 'pay_status', 'pay_request', 'id', 'approved', 'booking_options', 'wpbc_custom_booking_form', //FixIn: 9.4.3.12 ) ); // Set dates and times in correct format --------------------------------------------------------------- $booking_data_arr = wpbc_parse_booking_data_fields_formats( $booking_data_arr ); // Get SHORT / WIDE Dates showing data ----------------------------------------------------------------- $short_dates_content = wpbc_get_formated_dates__short( $booking->short_dates, (boolean) $booking->approved, $booking->short_dates_child_id, $resources_arr ); $wide_dates_content = wpbc_get_formated_dates__wide( $booking->dates, (boolean) $booking->approved, $booking->child_id, $resources_arr ); //------------------------------------------------------------------------------------------------------ // Payment Status //------------------------------------------------------------------------------------------------------ if ( 1 ) { $booking_data_arr['is_paid'] = 0; // 0 | 1 $booking_data_arr['pay_print_status'] = ''; // "Unknown" | "Stripe_v3:OK" // $booking_data_arr['pay_status'] // "165458416073.66" | "Stripe_v3:OK" | "PayPal:Ok" if ( class_exists( 'wpdev_bk_biz_s' ) ) { if ( wpbc_is_payment_status_ok( trim( $booking_data_arr['pay_status'] ) ) ) { $booking_data_arr['is_paid'] = 1; } $payment_status_titles = get_payment_status_titles(); $current_payment_status_title = array_search( $booking_data_arr['pay_status'], $payment_status_titles ); if ( $current_payment_status_title === false ) { $current_payment_status_title = $booking_data_arr['pay_status']; } if ( $booking_data_arr['is_paid'] ) { $booking_data_arr['pay_print_status'] = $booking_data_arr['pay_status']; if ( $current_payment_status_title == 'Completed' ) { $booking_data_arr['pay_print_status'] = $current_payment_status_title; } } else if ( ( is_numeric( $booking_data_arr['pay_status'] ) ) || ( $booking_data_arr['pay_status'] == '' ) ) { $booking_data_arr['pay_print_status'] = __( 'Unknown', 'booking' ); } else { $booking_data_arr['pay_print_status'] = $current_payment_status_title; } //////////////////////////////////////////////////////////////////////////////////////////////////// if ( $booking_data_arr['pay_print_status'] == 'Completed' ) { //FixIn: 8.4.7.11 $booking_data_arr['pay_print_status'] = __( 'Completed', 'booking' ); } $real_payment_css = empty( $booking_data_arr['pay_status'] ) ? $current_payment_status_title : $booking_data_arr['pay_status']; //FixIn: 8.7.7.13 $css_payment_label = 'wpbc_label_payment_status_' . wpbc_check_payment_status( $real_payment_css ); // 'success' | 'pending' | 'unknown' | 'error' //FixIn: 8.7.7.13 if ( $booking_data_arr['is_paid'] ) { $css_payment_label .= ' wpbc_label_payment_status_success'; } $payment_label_template = '<span class="wpbc_label wpbc_label_payment_status ' . $css_payment_label . '">' . '<span style="font-size:07px;padding: 0 1em 0 0;line-height: 2em;">' . __( 'Payment', 'booking' ) . '</span> ' . '<span>' . $booking_data_arr['pay_print_status'] . '</span> ' . '</span>'; } else { $payment_label_template = ''; } } //------------------------------------------------------------------------------------------------------ // Currency //------------------------------------------------------------------------------------------------------ if ( class_exists( 'wpdev_bk_biz_s' ) ) { $currency_symbol = wpbc_get_currency_symbol_for_user( $resource_id ); $booking_data_arr['currency_symbol'] = $currency_symbol; } //------------------------------------------------------------------------------------------------------ // Add some fields to [ 'parsed_fields' ] //------------------------------------------------------------------------------------------------------ $booking_data_arr['resource_title'] = $resource_title; $booking_data_arr['resource_id'] = $resource_id; $booking_data_arr['resource_owner_user'] = $resource_owner_user; //$booking_data_arr['short_dates_content'] = $short_dates_content; //$booking_data_arr['wide_dates_content'] = $wide_dates_content; //------------------------------------------------------------------------------------------------------ // Form Show - "Content of booking fields data" form //------------------------------------------------------------------------------------------------------ $custom_booking_form_name = ( ! empty( $booking_data_arr['wpbc_custom_booking_form'] ) ) ? $booking_data_arr['wpbc_custom_booking_form'] : ''; //FixIn: 9.4.3.12 $form_show_template = wpbc_get_content_booking_form_show( $resource_id , $custom_booking_form_name ); // <strong>First Name</strong>:<span class="fieldvalue">[name]</span> ... $parsed_form_show = wpbc_get_parsed_content_booking_form_show( $booking_data_arr, $form_show_template ); // <strong>First Name</strong>:<span class="fieldvalue">John</span> ... //------------------------------------------------------------------------------------------------------ // Google Calendar link //------------------------------------------------------------------------------------------------------ $booking_data_arr['google_calendar_link'] = wpbc_booking_do_action__get_google_calendar_link( array( 'form_data' => $booking_data_arr, 'form_show' => $parsed_form_show, //strip_tags( $parsed_form_show ), 'dates_short' => $booking->short_dates ) ); // ===================================================================================================== $bookings_arr[ $booking_id ]->parsed_fields = $booking_data_arr; // ===================================================================================================== $bookings_arr[ $booking_id ]->templates = array( 'form_show' => $parsed_form_show, 'form_show_nohtml' => strip_tags( $parsed_form_show ), 'short_dates_content' => $short_dates_content, 'wide_dates_content' => $wide_dates_content, 'payment_label_template' => $payment_label_template ); } return $bookings_arr; } /** * Get SHORT Dates showing data * * @param array $short_dates_arr - Array of dates * @param bool $is_approved - is dates approved or not * @param type $dates_type_id_arr * @param type $booking_resources_arr * * @return string */ function wpbc_get_formated_dates__short( $short_dates_arr, $is_approved = false, $dates_type_id_arr = array() , $booking_resources_arr = array() ){ $css_class_approved = ( $is_approved ) ? 'approved' : ''; $short_dates_content = ''; $date_number = 0; foreach ( $short_dates_arr as $dt ) { if ( $dt == '-' ) { $short_dates_content .= '<span class="date_tire"> - </span>'; } elseif ( $dt == ',' ) { $short_dates_content .= '<span class="date_tire">, </span>'; } else { list( $formatted_date, $formatted_time ) = wpbc_get_date_in_correct_format( $dt ); $short_dates_content .= '<a href="javascript:void(0)" onclick="javascript:wpbc_ajx_click_on_dates_toggle(this);" class="wpbc_label wpbc_label_booking_dates ' . $css_class_approved . '"><span>'; $short_dates_content .= $formatted_date; $short_dates_content .= '<sup class="field-booking-time">' . $formatted_time . '</sup>'; // BL if ( ( class_exists( 'wpdev_bk_biz_l' ) ) && ( ! empty( $dates_type_id_arr[ $date_number ] ) ) && ( isset( $booking_resources_arr[ $dates_type_id_arr[ $date_number ] ] ) ) ){ $resource_title = ( isset( $booking_resources_arr[ $dates_type_id_arr[ $date_number ] ] ) ) ? $booking_resources_arr[ $dates_type_id_arr[ $date_number ] ]['title'] : __( 'Resource not exist', 'booking' ); $resource_title = wpbc_lang( $resource_title ); if ( strlen( $resource_title ) > 19 ) { $resource_title = substr( $resource_title, 0, 13 ) . '...' . substr( $resource_title, - 3 ); } $short_dates_content .= '<sup class="field-booking-time date_from_dif_type"> ' . $resource_title . '</sup>'; } $short_dates_content .= '</span></a>'; } $date_number++; } return $short_dates_content; } /** * Get Wide Dates showing data * * @param array $dates_arr - array of dates in sql string format * @param bool $is_approved - is approved (true) or pending (false) * @param array $dates_type_id_arr - array of $date->type_id from the dates SQL object * @param type $booking_resources_arr - array of booking resources objects * * @return string */ function wpbc_get_formated_dates__wide( $dates_arr, $is_approved = false, $dates_type_id_arr = array(), $booking_resources_arr = array() ){ $wide_dates_arr = array(); $css_class_approved = ( $is_approved ) ? 'approved' : ''; foreach ( $dates_arr as $date_number => $sql_booking_date ) { list( $formatted_date, $formatted_time ) = wpbc_get_date_in_correct_format( $sql_booking_date ); $wide_date = '<a href="javascript:void(0)" onclick="javascript:wpbc_ajx_click_on_dates_toggle(this);" class="wpbc_label wpbc_label_booking_dates ' . $css_class_approved . '"><span>'; $wide_date .= $formatted_date; $wide_date .= '<sup class="field-booking-time">' . $formatted_time . '</sup>'; // BL if ( ( class_exists( 'wpdev_bk_biz_l' ) ) && ( '' != $dates_type_id_arr[ $date_number ] ) && ( isset( $booking_resources_arr[ $dates_type_id_arr[ $date_number ] ] ) ) ){ $resource_title = ( isset( $booking_resources_arr[ $dates_type_id_arr[ $date_number ] ] ) ) ? $booking_resources_arr[ $dates_type_id_arr[ $date_number ] ]['title'] : __( 'Resource not exist', 'booking' ); $resource_title = wpbc_lang( $resource_title ); if ( strlen( $resource_title ) > 19 ) { $resource_title = substr( $resource_title, 0, 13 ) . '...' . substr( $resource_title, - 3 ); } $wide_date .= '<sup class="field-booking-time date_from_dif_type"> ' . $resource_title . '</sup>'; } $wide_date .= '</span></a>'; $wide_dates_arr[] = $wide_date; } $wide_dates_content = implode( '<span class="date_tire">, </span>' , $wide_dates_arr ); return $wide_dates_content; } /** * Parse booking "data field" and get array * * @param string $data - "id^2~booking_type^Standard~status^Approved~dates^2019-09-18 00:00:00 - 2019-09-20 00:00:00 , 2019-09-18 00:00:00 (Standard-1) - 2019-09-20 00:00:00 (Standard-1)~modification_date^2019-09-05 10:50:04~cost^100.00~pay_status^156766972609.7~selected_short_timedates_hint^09/18/2019 - 09/20/2019~nights_number_hint^2~cost_hint^$75.00~name^John test~secondname^Smith~email^user@beta.com~phone^~visitors^4~children^~details^~term_and_condition^~user^Support A~wpbc_other_action^~rangetime^~other_email^~visitorsselector^~visitors_fee^~visitors_fee_hint^~trash^~remark^Approved by:John Smith (user@beta.com) [2019-09-11 09:30] Declined by:John Smith (user@beta.com) [2019-09-11 09:30]" * @param array $attr - array( 'r_separator' => '~', 'f_separator' => '^' ) * * @return array - Array ( [id] => 2 [booking_type] => Standard [status] => Approved ... ) */ function wpbc_parse_booking_data_fields( $data , $attr = array() ){ $defaults = array( 'r_separator' => '~' , 'f_separator' => '^' , 'resource_id' => '1' , 'system_fields' => array( 'booking_id', 'trash', //'sync_gid', 'is_new', 'status', 'sort_date', 'modification_date', 'hash', 'booking_type', 'remark', 'cost', 'pay_status', 'pay_request', 'id', 'approved' ) ); $attr = wp_parse_args( $attr, $defaults ); $data_arr = array(); if ( ! empty( $data ) ) { $data = explode( $attr['r_separator'] , $data ); // ~ foreach ( $data as $data_rows ) { $data_rows = explode( $attr['f_separator'] , $data_rows ); // ^ $data_field = array( 'type' => $data_rows[0], 'name' => $data_rows[1], 'value' => $data_rows[2] ); // remove checkboxes suffix [] $data_field['name'] = str_replace( '[]', '', $data_field['name'] ); // remove booking resource ID suffix $data_field['name'] = substr( $data_field['name'], 0, - 1 * strlen( strval( $attr['resource_id'] ) ) ); // System fields - adjust fields with same name if ( in_array( $data_field['name'], $attr['system_fields'] ) ) { $data_field['name'] .= '_data'; } //Checkboxes if ( ( 'checkbox' == $data_field['type'] ) && ( empty( $data_field['value'] ) ) ) { continue; } if ( ( 'checkbox' == $data_field['type'] ) && ( ! is_array( $data_field['value'] ) ) ) { $data_field['value'] = str_replace( array( 'true', 'false' ), array( strtolower( __( 'Yes', 'booking' ) ), strtolower( __( 'No', 'booking' ) ) ), $data_field['value'] ); } // Several items with same name - multi checkboxes if ( ! isset( $data_arr[ $data_field['name'] ] ) ) { $data_arr[ $data_field['name'] ] = $data_field['value']; } else { if ( is_array( $data_arr[ $data_field['name'] ] ) ) { $data_arr[ $data_field['name'] ][] = $data_field['value']; } else { $data_arr[ $data_field['name'] ] = array( $data_arr[ $data_field['name'] ], $data_field['value'] ); } } } } foreach ( $data_arr as $key => $value ) { // Multi checkboxes: [9] => checkbox^my_multi_checkbx4[]^1 [10] => checkbox^my_multi_checkbx4[]^ [11] => checkbox^my_multi_checkbx4[]^3 if ( is_array( $value ) ) { $value = implode( ',', $value ); $data_arr[$key] = $value; } } return $data_arr; } /** * Add system fields to Booking fields array and get final array of fields * @param array $booking_data_arr Original array of form fields from DB Array ( [selected_short_dates_hint] => March 5, 2023 [days_number_hint] => 1 [cost_hint] => &#36;95 [rangetime] => 10:00 AM - 12:00 PM [name] => test [email] => test@wpbookingcalendar.com ... ) * @param array $booking_system_arr array of system fields from DB Array ( [booking_id] => 188 [trash] => 0 ... [cost] => 95.00 [pay_status] => 165036591118.88 [pay_request] => 0 [id] => 188 [approved] => 0 ) * @param array $system_keys_arr system fields keys that need to be added, like this: Array ( booking_id, trash, sync_gid, is_new, status , sort_date, modification_date, hash, booking_type , remark, cost, pay_status, pay_request, id, approved ) * @return array array of form fields with system fields */ function wpbc_add_system_booking_data_fields( $booking_data_arr, $booking_system_arr, $system_keys_arr ){ foreach ( $system_keys_arr as $key ) { if ( ( ! isset( $booking_system_arr[ $key ] ) ) || ( is_null( $booking_system_arr[ $key ] ) ) ) { $booking_system_arr[ $key ] = ''; //Some fields, like remark or booking_options can be null, so we define them as '' } if ( isset( $booking_system_arr[ $key ] ) ) { if ( ! isset( $booking_data_arr[ $key ] ) ) { $booking_data_arr[ $key ] = maybe_unserialize( $booking_system_arr[ $key ] ); } else { $booking_data_arr[ $key . '_system' ] = maybe_unserialize( $booking_system_arr[ $key ] ); } } } return $booking_data_arr; } /** * Parse booking form fields format - for example: time fields in specific format * @param $data_arr * * @return array */ function wpbc_parse_booking_data_fields_formats( $data_arr ){ foreach ( $data_arr as $key => $value ) { if ( 'rangetime' == $key ) { $data_arr[$key] = wpbc_time_slot_in_format( $value ); $data_arr[ $key . '_in_24_hour' ] = $value; //FixIn: 10.0.0.52 } if ( in_array( $key, array( 'starttime', 'endtime' ) ) ) { $data_arr[$key] = wpbc_time_in_format( $value ); $data_arr[ $key . '_in_24_hour' ] = $value; //FixIn: 10.0.0.52 } if ( in_array( $key, array( 'modification_date', 'creation_date' ) ) ) { //$data_arr[$key] = wpbc_get_dates_comma_string_localized( $value ); // This date $values in GMT date/Time format. So we need to switch to WordPress locale with TIME sum of actual GMT date/time value + shift of timezone from WordPress. $is_add_wp_timezone = true; $its_for_default_datetime_format = ''; $data_arr[ $key ] = wpbc_datetime_localized( $value, $its_for_default_datetime_format, $is_add_wp_timezone ); $data_arr[ $key . '_in_24_hour' ] = $value; //FixIn: 10.0.0.52 } if ( ( 'hash' === $key ) && ( empty( $value ) ) ) { //FixIn: 9.2.3.4 //FixIn: 9.4.3.10 // Update booking Hash if it was empty wpbc_hash__update_booking_hash( $data_arr['id'], $data_arr['booking_type'] ); // Get new booking hash $hash__arr = wpbc_hash__get_booking_hash__resource_id( $data_arr['id'] ); if ( ! empty( $hash__arr ) ) { $data_arr[ $key ] = $hash__arr[0]; } } } return $data_arr; } /** * Get pure "Content of booking fields data" with shortcodes inside. * it can depend on specific booking resource in Business Medium version or User in MultiUser version * * @param int $resource_id * @param sting $custom_booking_form_name - use this custom booking form, if possible * * @return string */ function wpbc_get_content_booking_form_show( $resource_id , $custom_booking_form_name = '' ){ //FixIn: 9.4.3.12 if ( $resource_id == -1 ) { if ( function_exists('get__default_type') ) $resource_id = get__default_type(); else $resource_id = 1; } if ( ! class_exists('wpdev_bk_personal') ) { $booking_form_show = wpbc_get_free_booking_show_form(); } else { $booking_form_show = get_bk_option( 'booking_form_show' ); $booking_form_show = wpbc_bf__replace_custom_html_shortcodes( $booking_form_show ); if ( class_exists('wpdev_bk_biz_m') ) { if ( ! empty( $custom_booking_form_name ) ) { //FixIn: 9.4.3.12 $booking_form_show = apply_bk_filter( 'wpdev_get_booking_form_content', $booking_form_show, $custom_booking_form_name ); $my_booking_form_name = $custom_booking_form_name; } else { // BM :: Get default Custom Form of Resource $my_booking_form_name = apply_bk_filter( 'wpbc_get_default_custom_form', 'standard', $resource_id ); if ( ( $my_booking_form_name != 'standard' ) && ( ! empty( $my_booking_form_name ) ) ) { $booking_form_show = apply_bk_filter( 'wpdev_get_booking_form_content', $booking_form_show, $my_booking_form_name ); } } //MU :: if resource of "Regular User" - then GET STANDARD user form ( if ( get_bk_option( 'booking_is_custom_forms_for_regular_users' ) !== 'On' ) ) $booking_form_show = apply_bk_filter( 'wpbc_multiuser_get_booking_form_show_of_regular_user', $booking_form_show, $resource_id, $my_booking_form_name ); //FixIn: 8.1.3.19 } } // Language $booking_form_show = wpbc_lang( $booking_form_show ); $search = array( "'(<br[ ]?[/]?>)+'si", "'(<[/]?p[ ]?>)+'si" ); $replace = array( " ", " ", " " ); $booking_form_show = preg_replace( $search, $replace, $booking_form_show ); return $booking_form_show; } /** * Get parsed "Content of booking fields data" - Shortcodes replaced by Values * * @param array $booking_data_arr * @param string $booking_form_show * * @return string */ function wpbc_get_parsed_content_booking_form_show( $booking_data_arr, $booking_form_show ){ foreach ( $booking_data_arr as $key_param => $value_param ) { if ( ( gettype ( $value_param ) != 'array' ) && ( gettype ( $value_param ) != 'object' ) ) { $booking_form_show = str_replace( '['. $key_param .']', $value_param ,$booking_form_show); } } // Remove all shortcodes, which have not replaced early. $booking_form_show = preg_replace ('/[\s]{0,}\[[a-zA-Z0-9.,-_]{0,}\][\s]{0,}/', '', $booking_form_show); $booking_form_show = str_replace( "&", '&', $booking_form_show ); return $booking_form_show; } // </editor-fold> // <editor-fold defaultstate="collapsed" desc=" F u n c t i o n s f o r C l e a n i ng s " > //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Escaping //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Escaping for inline JavaScript. * Based on WordPress esc_js() * plus removing \n in the code * and back converting escaped single quotes from \' to ' * * This function has to be used in the code marked with double quote symbols, not single. * Example: onclick="javascript:<?php echo wpbc_esc_js( $item_params['action'] ); ?>" * * @param $text * * @return string */ function wpbc_esc_js( $text ) { $text = str_replace( "\n", '', $text ); // removing \n in the code //$safe_text = esc_js( $text ); // js // This code get from esc_js() and modified for correct working with (' symbols) in translations $safe_text = wp_check_invalid_utf8( $text ); $safe_text = _wp_specialchars( $safe_text, ENT_COMPAT ); $safe_text = preg_replace( '/&#(x)?0*(?(1)27|39);?/i', "\'", stripslashes( $safe_text ) ); $safe_text = str_replace( "\r", '', $safe_text ); $safe_text = str_replace( "\n", '\\n', addslashes( $safe_text ) ); $safe_text = str_replace( "\'", "'", $safe_text ); // back converting escaped single quotes from \' to ' $safe_text = str_replace( "\\\'", "\'", $safe_text ); // back converting escaped single quotes from \' to ' return $safe_text; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // DB //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Check $value for injections. Basically can be used in Requests params checking. * * @param type $value * * @return type */ function wpbc_esc_clean_parameter( $value ) { $value = preg_replace( '/<[^>]*>/', '', $value ); // clean any tags $value = str_replace( '<', ' ', $value ); $value = str_replace( '>', ' ', $value ); $value = strip_tags( $value ); // Strip HTML and PHP tags from a string // Clean SQL injection $value = esc_sql( $value ); $value = esc_textarea( $value ); //FixIn: 7.1.1.2 return $value; } function wpbc_esc_sql_like( $value_trimmed ) { // check here https://code.tutsplus.com/articles/data-sanitization-and-validation-with-wordpress--wp-25536 global $wpdb; if ( method_exists( $wpdb ,'esc_like' ) ) return $wpdb->esc_like( $value_trimmed ); // Its require minimum WP 4.0.0 else return addcslashes( $value_trimmed, '_%\\' ); // Direct implementation from $wpdb->esc_like( } /** * Clean user string for using in SQL LIKE statement - append to LIKE sql * * @param string $value - to clean * * @return string - escaped * Exmaple: * $search_escaped_like_title = wpbc_esc_clean_like_string_for_append_in_sql_for_db( $input_var ); * * $where_sql = " WHERE title LIKE ". $search_escaped_like_title ." "; */ function wpbc_esc_clean_like_string_for_append_in_sql_for_db( $value ) { // check here https://code.tutsplus.com/articles/data-sanitization-and-validation-with-wordpress--wp-25536 global $wpdb; $value_trimmed = trim( stripslashes( $value ) ); $wild = '%'; $like = $wild . wpbc_esc_sql_like( $value_trimmed ) . $wild; $sql = $wpdb->prepare( "'%s'", $like ); return $sql; /* Help: * First half of escaping for LIKE special characters % and _ before preparing for MySQL. * Use this only before wpdb::prepare() or esc_sql(). Reversing the order is very bad for security. * * Example Prepared Statement: * * $wild = '%'; * $find = 'only 43% of planets'; * $like = $wild . wpbc_esc_sql_like( $find ) . $wild; * $sql = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE '%s'", $like ); * * Example Escape Chain: * * $sql = esc_sql( wpbc_esc_sql_like( $input ) ); */ } /** * Clean string for using in SQL LIKE requests inside single quotes: WHERE title LIKE '%". $escaped_search_title ."%' * Replaced _ to \_ % to \% \ to \\ * * @param string $value - to clean * * @return string - escaped * Exmaple: * $search_escaped_like_title = wpbc_esc_clean_like_string_for_db( $input_var ); * * $where_sql = " WHERE title LIKE '%". $search_escaped_like_title ."%' "; * * Important! Use SINGLE quotes after in SQL query: LIKE '%".$data."%' */ function wpbc_esc_clean_like_string_for_db( $value ){ // check here https://code.tutsplus.com/articles/data-sanitization-and-validation-with-wordpress--wp-25536 global $wpdb; $value_trimmed = trim( stripslashes( $value ) ); $value_trimmed = wpbc_esc_sql_like( $value_trimmed ); $value = trim( $wpdb->prepare( "'%s'", $value_trimmed ) , "'" ); return $value; /* Help: * First half of escaping for LIKE special characters % and _ before preparing for MySQL. * Use this only before wpdb::prepare() or esc_sql(). Reversing the order is very bad for security. * * Example Prepared Statement: * * $wild = '%'; * $find = 'only 43% of planets'; * $like = $wild . wpbc_esc_sql_like( $find ) . $wild; * $sql = $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_content LIKE '%s'", $like ); * * Example Escape Chain: * * $sql = esc_sql( wpbc_esc_sql_like( $input ) ); */ } // </editor-fold> // <editor-fold defaultstate="collapsed" desc=" D B " > /*** * Get list of DB of this plugin * @return array */ function wpbc_get_db_names(){ global $wpdb; $db_names = array( 'bookings' => $wpdb->prefix . 'booking', 'dates' => $wpdb->prefix . 'bookingdates', 'resources' => $wpdb->prefix . 'bookingtypes', 'resources_meta' => $wpdb->prefix . 'booking_types_meta', 'seasons' => $wpdb->prefix . 'booking_seasons', 'coupons' => $wpdb->prefix . 'booking_coupons' ); return $db_names; } // </editor-fold> // <editor-fold defaultstate="collapsed" desc=" E r r o r s H a n d l i n g " > /** * PHP Fatal Error! Display expanded error info at Booking Listing page * * @param $message * @param $error * * @return mixed|string */ function wpbc_php_error_message( $message, $error ) { // Check to show this error, only from Booking Listing page, checking secure parameters from wpbc_ajx_booking_listing in ..{Booking Calendar Folder}/includes/page-bookings/_src/ajx_booking_listing.js if ( ! ( ! isset( $_POST['search_params'] ) || empty( $_POST['search_params'] ) ) ) { // Security ----------------------------------------------------------------------------------------------- // in Ajax Post: 'nonce': wpbc_ajx_booking_listing.get_secure_param( 'nonce' ), $action_name = 'wpbc_ajx_booking_listing_ajx' . '_wpbcnonce'; $nonce_post_key = 'nonce'; // $result_check = check_ajax_referer( $action_name, $nonce_post_key ); if ( isset( $_REQUEST[ $nonce_post_key ] ) ) { $nonce_request = $_REQUEST[ $nonce_post_key ]; $result_verify_nonce = wp_verify_nonce( $nonce_request, $action_name ); if ( false !== $result_verify_nonce ) { if ( ( ! empty( $error ) ) && ( ! empty( $error['message'] ) ) ) { $message .= '<br>' . $error['message']; } } } } return $message; } add_filter( 'wp_php_error_message', 'wpbc_php_error_message', 2 , 10 ); /** * Nonce Error! Error Handing for not passed nonce, in booking Listing page. * Probably nonce was expired (more than 24 hours) * * @param $action * @param $result - 1 Good ( 0-12 hours ago ) , 2 Good ( 12-24 hours ago ) , false - Error ( > 24 hours - nonce is invalid ) */ function wpbc_check_ajax_referer__for_booking_listing( $action, $result ){ if ( ( false === $result ) && ( 'wpbc_ajx_booking_listing_ajx' . '_wpbcnonce' === $action ) && ( wp_doing_ajax() ) ) { die( '<strong>Error!</strong> Probably nonce for this page has been expired. Please <a href="javascript:void(0)" onclick="javascript:location.reload();">reload the page</a>.' ); } } add_action( 'check_ajax_referer', 'wpbc_check_ajax_referer__for_booking_listing', 2, 10 ); // </editor-fold>