From cda76c89664ecaf1adabe5aeae2218bffff14d19 Mon Sep 17 00:00:00 2001 From: otrok7 <50595291+otrok7@users.noreply.github.com> Date: Tue, 26 May 2026 23:19:11 +0200 Subject: [PATCH 01/20] Create AJAX mechanism --- includes/class-bread-bmlt.php | 97 ++++++++++++++++---- includes/class-bread.php | 6 +- public/class-bread-content-generator.php | 12 +-- public/class-bread-public.php | 96 +++++++++++++------- public/css/bread-public.css | 4 - public/js/bread-public.js | 67 +++++++------- public/js/fetch-jsonp.js | 111 +++++++++++++++++++++++ 7 files changed, 295 insertions(+), 98 deletions(-) delete mode 100644 public/css/bread-public.css create mode 100644 public/js/fetch-jsonp.js diff --git a/includes/class-bread-bmlt.php b/includes/class-bread-bmlt.php index 90ca05e1..90235be7 100644 --- a/includes/class-bread-bmlt.php +++ b/includes/class-bread-bmlt.php @@ -14,9 +14,9 @@ function __construct($bread) $this->bread = $bread; } - public function get_configured_root_server_request($url, $raw = false) + private function get_configured_root_server_request($url, $raw = false) { - $results = $this->bread->bmlt()->get($this->bread->getOption('root_server') . "/" . $url); + $results = $this->get($this->bread->getOption('root_server') . "/$url"); if ($raw) { return $results; } @@ -24,7 +24,7 @@ public function get_configured_root_server_request($url, $raw = false) } public function get_formats_by_language(string $lang) { - return $this->bread->bmlt()->get_configured_root_server_request("client_interface/json/?switcher=GetFormats&lang_enum=$lang"); + return $this->get_configured_root_server_request("client_interface/json/?switcher=GetFormats&lang_enum=$lang"); } /** * Undocumented function @@ -57,10 +57,10 @@ private function get(string $url): WP_Error | array */ public function get_all_meetings(): array { - $lang = $this->bread->bmlt()->get_bmlt_server_lang(); - $result = $this->bread->bmlt()->get_configured_root_server_request("client_interface/json/?switcher=GetSearchResults&data_field_key=weekday_tinyint,start_time,service_body_bigint,id_bigint,meeting_name,location_text,email_contact&sort_keys=meeting_name,service_body_bigint,weekday_tinyint,start_time"); + $lang = $this->get_bmlt_server_lang(); + $result = $this->get_configured_root_server_request("client_interface/json/?switcher=GetSearchResults&data_field_key=weekday_tinyint,start_time,service_body_bigint,id_bigint,meeting_name,location_text,email_contact&sort_keys=meeting_name,service_body_bigint,weekday_tinyint,start_time"); - $unique_areas = $this->bread->bmlt()->get_areas(); + $unique_areas = $this->get_areas(); $all_meetings = array(); foreach ($result as $value) { foreach ($unique_areas as $unique_area) { @@ -79,7 +79,7 @@ public function get_all_meetings(): array } public function get_fieldkeys() { - $ret = $this->bread->bmlt()->get_configured_root_server_request("client_interface/json/?switcher=GetFieldKeys"); + $ret = $this->get_configured_root_server_request("client_interface/json/?switcher=GetFieldKeys"); return is_null($ret) ? array() : $ret; } private $standard_keys = array( @@ -108,7 +108,7 @@ public function get_fieldkeys() ); public function get_nonstandard_fieldkeys() { - $all_fks = $this->bread->bmlt()->get_fieldkeys(); + $all_fks = $this->get_fieldkeys(); $ret = array(); foreach ($all_fks as $fk) { if (!in_array($fk['key'], $this->standard_keys)) { @@ -131,7 +131,7 @@ public function get_areas() if (!empty($this->unique_areas)) { return $this->unique_areas; } - $result = $this->bread->bmlt()->get_configured_root_server_request("client_interface/json/?switcher=GetServiceBodies"); + $result = $this->get_configured_root_server_request("client_interface/json/?switcher=GetServiceBodies"); $this->unique_areas = array(); foreach ($result as $value) { @@ -149,15 +149,80 @@ public function get_areas() return $this->unique_areas; } + public function generateMainQuery($json = 'json') + { + $sort_keys = 'weekday_tinyint,start_time,meeting_name'; + $get_used_formats = '&get_used_formats'; + $select_language = ''; + if ($this->bread->getOption('weekday_language') != $this->get_bmlt_server_lang()) { + $select_language = '&lang_enum=' . substr($this->bread->getOption('weekday_language'), 0, 2); + } + $services = $this->generateDefaultQuery(); + if (isset($_GET['custom_query'])) { + $services = $_GET['custom_query']; + } elseif ($this->bread->getOption('custom_query') !== '') { + $services = $this->bread->getOption('custom_query'); + } + if ($this->bread->getOption('used_format_1') == '') { + return "client_interface/$json/?switcher=GetSearchResults$services&sort_keys=$sort_keys$get_used_formats$select_language"; + } else { + return "client_interface/$json/?switcher=GetSearchResults$services&sort_keys=$sort_keys&get_used_formats&formats[]=" . $this->bread->getOption('used_format_1') . $select_language; + } + } + public function doMainQuery() + { + return $this->get_configured_root_server_request($this->generateMainQuery()); + } + public function generateExtraMeetingQuery($json = 'json') + { + if (empty($this->bread->getOption('extra_meetings'))) { + return null; + } + $sort_keys = 'weekday_tinyint,start_time,meeting_name'; + $get_used_formats = '&get_used_formats'; + $select_language = ''; + $extras = ""; + foreach ((array)$this->bread->getOption('extra_meetings') as $value) { + $data = array(" [", "]"); + $value = str_replace($data, "", $value); + $extras .= "&meeting_ids[]=" . $value; + } + + return "client_interface/$json/?switcher=GetSearchResults&sort_keys=" . $sort_keys . "" . $extras . "" . $get_used_formats . $select_language; + } + public function doExtraMeetingQuery() + { + return $this->get_configured_root_server_request($this->generateExtraMeetingQuery()); + } + public function generateAdditionalListQuery($json = 'json') + { + if (!empty($this->options['additional_list_custom_query'])) { + $sort_order = $this->bread->getOption('additional_list_sort_order'); + if ($sort_order == 'same') { + $sort_order = 'weekday_tinyint,start_time'; + } + $services = $this->bread->getOption('additional_list_custom_query'); + return "client_interface/$json/?switcher=GetSearchResults$services&sort_keys=$sort_order"; + } + return null; + } + public function doAdditionalListQuery() + { + $url = $this->generateAdditionalListQuery(); + if ($url == null) { + return []; + } + return $this->get_configured_root_server_request($url); + } /** * Gets the default language of the root server. * * @return string 2 character string ISO standard for the language. */ - public function get_bmlt_server_lang(): string + private function get_bmlt_server_lang(): string { if ($this->bmlt_server_lang == '') { - $result = $this->bread->bmlt()->testRootServer(); + $result = $this->testRootServer(); if (!($result && is_array($result) && is_array($result[0]))) { return 'en'; } @@ -174,9 +239,9 @@ public function get_bmlt_server_lang(): string public function testRootServer(string $override_root_server = null): array|bool { if ($override_root_server == null) { - $results = $this->bread->bmlt()->get_configured_root_server_request("client_interface/json/?switcher=GetServerInfo", true); + $results = $this->get_configured_root_server_request("client_interface/json/?switcher=GetServerInfo", true); } else { - $results = $this->bread->bmlt()->get($override_root_server . "/client_interface/json/?switcher=GetServerInfo", true); + $results = $this->get($override_root_server . "client_interface/json/?switcher=GetServerInfo", true); } if ($results instanceof WP_Error) { $this->connection_error = $results->get_error_message(); @@ -199,8 +264,8 @@ public function testRootServer(string $override_root_server = null): array|bool public function getFormatsForSelect(bool $all = false): array { if ($all) { - $results = $this->bread->bmlt()->get_configured_root_server_request("client_interface/json/?switcher=GetFormats"); - $this->bread->bmlt()->sortBySubkey($results, 'key_string'); + $results = $this->get_configured_root_server_request("client_interface/json/?switcher=GetFormats"); + $this->sortBySubkey($results, 'key_string'); return $results; } $area_data = explode(',', $this->bread->getOption('service_body_1')); @@ -215,7 +280,7 @@ public function getFormatsForSelect(bool $all = false): array } else { $queryUrl = "client_interface/json/?switcher=GetSearchResults$services&get_formats_only"; } - $results = $this->bread->bmlt()->get_configured_root_server_request($queryUrl); + $results = $this->get_configured_root_server_request($queryUrl); $results = empty($service_body_id) ? $results : $results['formats']; $this->sortBySubkey($results, 'key_string'); return $results; diff --git a/includes/class-bread.php b/includes/class-bread.php index 94da3290..0ddf8250 100644 --- a/includes/class-bread.php +++ b/includes/class-bread.php @@ -305,7 +305,7 @@ public function &getConfigurationForSettingId($current_setting) if ($current_setting < 1) { $current_setting = is_admin() ? 1 : $this->requested_setting; } - if (is_array($this->allSettings[$current_setting])) { + if ($this->allSettings && !empty($this->allSettings[$current_setting]) && is_array($this->allSettings[$current_setting])) { $this->options = $this->allSettings[$current_setting]; } else { $this->optionsName = $this->generateOptionName($current_setting); @@ -529,6 +529,8 @@ private function define_public_hooks() $this->loader->add_action('wp_enqueue_scripts', $plugin_public, 'enqueue_styles'); $this->loader->add_action('wp_enqueue_scripts', $plugin_public, 'enqueue_scripts'); $this->loader->add_action('plugins_loaded', $plugin_public, 'bmlt_meeting_list'); + $this->loader->add_action('wp_ajax_bread_preload_action', $plugin_public, 'bread_preload'); + $this->loader->add_action('wp_ajax_nopriv_bread_preload_action', $plugin_public, 'bread_preload'); } /** @@ -721,7 +723,7 @@ private function upgrade_settings(): void || $this->options['meeting_sort'] === 'weekday_city' || $this->options['meeting_sort'] === 'weekday_county' || $this->options['meeting_sort'] === 'day')) { - $this->options['weekday_language'] = $this->bmlt()->get_bmlt_server_lang(); + $this->options['weekday_language'] = 'en'; } if ($this->options['page_fold'] == 'half') { if ($this->options['page_size'] == 'A5') { diff --git a/public/class-bread-content-generator.php b/public/class-bread-content-generator.php index 7dc8d125..6d6596b3 100644 --- a/public/class-bread-content-generator.php +++ b/public/class-bread-content-generator.php @@ -580,17 +580,7 @@ function write_additional_meetinglist() * If we are selecting the meetings in the second list based on some format, we don't need another BMLT query. */ if (empty($this->options['additional_list_format_key'])) { - $additional_list_query = true; - $sort_order = $this->options['additional_list_sort_order']; - if ($sort_order == 'same') { - $sort_order = 'weekday_tinyint,start_time'; - } - $services = $this->bread->bmlt()->generateDefaultQuery(); - if (!empty($this->options['additional_list_custom_query'])) { - $services = $this->options['additional_list_custom_query']; - } - $additional_list_query = "client_interface/json/?switcher=GetSearchResults$services&sort_keys=$sort_order"; - $additional_meetinglist_result = $this->bread->bmlt()->get_configured_root_server_request($additional_list_query); + $additional_meetinglist_result = $this->bread->bmlt()->doAdditionalListQuery(); $this->adjust_timezone($additional_meetinglist_result, $this->target_timezone); } if ($additional_list_query || $this->options['weekday_language'] != $this->options['additional_list_language']) { diff --git a/public/class-bread-public.php b/public/class-bread-public.php index 4f3e9cd6..a990e014 100644 --- a/public/class-bread-public.php +++ b/public/class-bread-public.php @@ -67,6 +67,10 @@ public function __construct($plugin_name, $version, $bread) $this->version = $version; $this->bread = $bread; $this->options = $bread->getOptions(); + add_shortcode('bread_button', array( + &$this, + "doBreadButton" + )); } /** @@ -76,7 +80,6 @@ public function __construct($plugin_name, $version, $bread) */ public function enqueue_styles() { - wp_enqueue_style($this->plugin_name, plugin_dir_url(__FILE__) . 'css/bread-public.css', array(), $this->version, 'all'); } /** @@ -86,9 +89,64 @@ public function enqueue_styles() */ public function enqueue_scripts() { - wp_enqueue_script($this->plugin_name, plugin_dir_url(__FILE__) . 'js/bread-public.js', array('jquery'), $this->version, false); + if (($current = $this->doPreloading()) > 0) { + wp_enqueue_script('fetch-jsonp', plugin_dir_url(__FILE__) . 'js/fetch-jsonp.js', array(), $this->version, true); + wp_enqueue_script($this->plugin_name, plugin_dir_url(__FILE__) . 'js/bread-public.js', array('jquery','fetch-jsonp'), $this->version, true); + wp_localize_script($this->plugin_name, 'bread_ajax_obj', [ + 'ajaxurl' => admin_url('admin-ajax.php'), + 'nonce' => wp_create_nonce('bread-ajax-nonce'), + 'config' => $this->generatePreloadConfiguration($current) + ]); + } + } + /** + * Check if the shortcode is being used on this page. + * + * @return boolean + */ + private function doPreloading(): int + { + $post_to_check = get_post(get_the_ID()); + $post_content = $post_to_check->post_content ?? ''; + $tags = ['bread_button']; + preg_match_all('/' . get_shortcode_regex($tags) . '/', $post_content, $matches, PREG_SET_ORDER); + if (empty($matches)) { + return -1; + } + foreach ($matches as $shortcode) { + switch ($shortcode[2]) { + case 'bread_button': + $atts = shortcode_parse_atts($shortcode[3]); + return intval($atts['current_meeting_list']); + } + } + return -1; + } + private function generatePreloadConfiguration(int $id): array + { + $options = $this->bread->getConfigurationForSettingId($id); + return [ + 'root_server' => $options['root_server'], + 'main_query' => $this->bread->bmlt()->generateMainQuery('jsonp'), + 'extra_meetings_query' => $this->bread->bmlt()->generateExtraMeetingQuery('jsonp'), + 'additional_list_query' => $this->bread->bmlt()->generateAdditionalListQuery('jsonp'), + 'weekday_language' => $options['weekday_language'], + 'additional_list_language' => $options['additional_list_language'], + ]; + } + public function doBreadButton($atts) + { + $label = $atts['label'] ?? 'Generate PDF'; + return ''; + } + public function bread_preload() + { + if (! wp_verify_nonce($_POST['nonce'], 'bread-ajax-nonce')) { + die; + } + $preload = json_decode(stripslashes($_POST['preload'])); + wp_send_json_success('Success!'); } - public function bmlt_meeting_list($atts = null, $content = null) { if (!$this->bread->generatingMeetingList()) { @@ -175,23 +233,7 @@ public function bmlt_meeting_list($atts = null, $content = null) ) { $this->drawLinesSeperatingColumns($mode, $mpdf_init_options['format'], $default_font); } - $sort_keys = 'weekday_tinyint,start_time,meeting_name'; - $get_used_formats = '&get_used_formats'; - $select_language = ''; - if ($this->options['weekday_language'] != $this->bread->bmlt()->get_bmlt_server_lang()) { - $select_language = '&lang_enum=' . $this->getSingleLanguage($this->options['weekday_language']); - } - $services = $this->bread->bmlt()->generateDefaultQuery(); - if (isset($_GET['custom_query'])) { - $services = $_GET['custom_query']; - } elseif ($this->options['custom_query'] !== '') { - $services = $this->options['custom_query']; - } - if ($this->options['used_format_1'] == '') { - $result = $this->bread->bmlt()->get_configured_root_server_request("client_interface/json/?switcher=GetSearchResults$services&sort_keys=$sort_keys$get_used_formats$select_language"); - } elseif ($this->options['used_format_1'] != '') { - $result = $this->bread->bmlt()->get_configured_root_server_request("client_interface/json/?switcher=GetSearchResults$services&sort_keys=$sort_keys&get_used_formats&formats[]=" . $this->options['used_format_1'] . $select_language); - } + $result = $this->bread->bmlt()->doMainQuery(); if ($result == null) { echo "
diff --git a/admin/partials/bread-admin-display.php b/admin/partials/bread-admin-display.php index e927d3c9..32706c3a 100644 --- a/admin/partials/bread-admin-display.php +++ b/admin/partials/bread-admin-display.php @@ -61,43 +61,6 @@ public function getServerVersion() { return $this->server_version; } - public function select_service_bodies() - { - for ($i = 1; $i <= 5; $i++) { ?> -
[page_break]
' => '[new_column]
' => 'bread Error: BMLT Server missing.
Please go to Settings -> bread and verify BMLT Server
bread Error: Service Body 1 missing from configuration.
Please go to Settings -> bread and verify Service Body
Contact the bread administrator and report this problem!
'+href+''; $('#wizard-show-link').html(tag); } - BreadWizard.prototype.generate_meeting_list = function() { + BreadWizard.generate_meeting_list = function() { window.open(href, '_blank').focus(); } - BreadWizard.prototype.redo_layout = function() { + BreadWizard.redo_layout = function() { $('#wizard_setting_id').val(setting); $('#bread-wizard').smartWizard("goToStep", 2); } - BreadWizard.prototype.test_root_server = function() { - const context = { - root_server: 'wizard_root_server', - service_bodies: 'wizard_service_bodies', - service_bodies_selected: [] - } - ask_bmlt(context, "switcher=GetServerInfo", - (context, info) => { + BreadWizard.test_root_server = function() { + BreadWizard.ask_bmlt("switcher=GetServerInfo", + (info) => { $('#wizard_root_server_result').removeClass('invalid-feedback dashicons-dismiss') .addClass('valid-feedback dashicons-before dashicons-yes-alt').html($('#wizard_connected_message').html()+info[0].version); }, - (context, error) => { + (error) => { $('#wizard_root_server_result').removeClass('valid-feedback dashicons-yes-alt') .addClass('invalid-feedback dashicons-before dashicons-dismiss').html($('#wizard_disconnected_message').html()); }); } - BreadWizard.prototype.root_server_keypress = function(event) { + BreadWizard.root_server_keypress = function(event) { if (event.code == 'Enter') this.test_root_server(); } - BreadWizard.prototype.root_server_changed = function() { + BreadWizard.root_server_changed = function() { $('#wizard_root_server_result').removeClass('valid-feedback').addClass('invalid-feedback dashicons-before dashicons-dismiss') .html($('#wizard_testnow_message').html()); } - BreadWizard.prototype.finish = function() { + BreadWizard.finish = function() { $('#bread-wizard').smartWizard("reset"); var form = document.createElement("form"); form.method = "POST"; @@ -77,8 +88,44 @@ jQuery(document).ready(function($){ document.body.appendChild(form); form.submit(); } - var hasVirtualMeetings = false; - layout_options = function(meetings) { + BreadWizard.write_service_body_with_childern = function(options, sb, parents, my_parent, level) { + let prefix = ''; + for (i=0; i
Do I have the BMLT? to find your BMLT server', 'bread')) ?>
-
+ onKeypress="BreadWizard.root_server_keypress(event)" onChange="BreadWizard.root_server_changed()" />
+
@@ -150,19 +150,19 @@
- +
-
+
- +
'+href+''; + BreadWizard.href = window.location.href.substring(0, window.location.href.indexOf('/wp-admin')); + BreadWizard.setting = response.result.setting; + BreadWizard.href = href+"?current-meeting-list="+BreadWizard.setting; + const tag = '
'+BreadWizard.href+''; $('#wizard-show-link').html(tag); } BreadWizard.generate_meeting_list = function() { - window.open(href, '_blank').focus(); + window.open(BreadWizard.href, '_blank').focus(); } BreadWizard.redo_layout = function() { - $('#wizard_setting_id').val(setting); + $('#wizard_setting_id').val(BreadWizard.setting); $('#bread-wizard').smartWizard("goToStep", 2); } BreadWizard.test_root_server = function() { @@ -83,7 +83,7 @@ jQuery(document).ready(function($){ var input = document.createElement("input"); input.type = "hidden"; input.name = "current-meeting-list"; - input.value = setting; + input.value = BreadWizard.setting; form.appendChild(input); document.body.appendChild(form); form.submit(); @@ -96,7 +96,7 @@ jQuery(document).ready(function($){ found = parents.find((p) => p.id == sb.id); if (typeof found !== 'undefined') found.children.forEach((child) => - options = write_service_body_with_childern(options, child, parents, sb.name, level+1)); + options = BreadWizard.write_service_body_with_childern(options, child, parents, sb.name, level+1)); return options; } BreadWizard.fill_service_bodies = function(service_bodies) { @@ -127,7 +127,7 @@ jQuery(document).ready(function($){ BreadWizard.hasVirtualMeetings = false; BreadWizard.layout_options = function(meetings) { const meeting_count = meetings.length; - hasVirtualMeetings = meetings.some((m) => m.formats.split(',').some(format => ['VM','HY'].includes(format))); + BreadWizard.hasVirtualMeetings = meetings.some((m) => m.formats.split(',').some(format => ['VM','HY'].includes(format))); $('#wizard_meeting_count').html(meeting_count); const layouts = breadLayouts.find((layouts) => meeting_count <= Number(layouts.maxSize)); const options = breadLayouts.reduce((carry,group) => { diff --git a/includes/class-bread.php b/includes/class-bread.php index 0903908f..4090252a 100644 --- a/includes/class-bread.php +++ b/includes/class-bread.php @@ -682,6 +682,7 @@ private function fillUnsetOptionsInner() $this->fillUnsetStringOption('used_format_1', ''); $this->fillUnsetOption('base_font', 'dejavusanscondensed'); $this->fillUnsetOption('colorspace', 0); + $this->fillUnsetArrayOption('service_bodies', []); $this->fillUnsetOption('recurse_service_bodies', 1); $this->fillUnsetOption('extra_meetings_enabled', 0); $this->fillUnsetOption('include_protection', 0); From 5863996bdf571ee4bf300d905e92d6804572236d Mon Sep 17 00:00:00 2001 From: otrok7 <50595291+otrok7@users.noreply.github.com> Date: Mon, 1 Jun 2026 17:58:14 +0200 Subject: [PATCH 09/20] small fixes --- admin/partials/bread-admin-display.php | 21 --------------------- includes/class-bread-bmlt.php | 5 +---- public/class-bread-content-generator.php | 12 ++++++------ public/class-bread-public.php | 4 ++-- 4 files changed, 9 insertions(+), 33 deletions(-) diff --git a/admin/partials/bread-admin-display.php b/admin/partials/bread-admin-display.php index 32706c3a..aeedc854 100644 --- a/admin/partials/bread-admin-display.php +++ b/admin/partials/bread-admin-display.php @@ -32,26 +32,6 @@ function __construct($admin) { $this->admin = $admin; $this->bread = $admin->get_bread_instance(); - $this->refresh_status(); - } - private function refresh_status() - { - $serverInfo = $this->bread->bmlt()->testRootServer(); - $this->connected = is_array($serverInfo) && array_key_exists("version", $serverInfo[0]) ? $serverInfo[0]["version"] : ''; - if ($this->connected) { - $this->unique_areas = $this->bread->bmlt()->get_areas(); - asort($this->unique_areas); - if ($serverInfo[0]["aggregator_mode_enabled"] ?? false) { - $this->server_version = "".__('Using Tomato Server', 'bread').""; - } elseif ($this->connected) { - /* translators: string is the version number of the BMLT Server */ - $this->server_version = "".sprintf(__('Your BMLT Server is running %s', 'bread'), esc_html($this->connected)). ""; - } - } - } - public function isConnected() - { - return $this->connected; } public function getBreadInstance() { @@ -122,7 +102,6 @@ function admin_options_page($filename = '') - refresh_status(); ?>