PluginProbe
Dr. Flex / trunk
Dr. Flex vtrunk
trunk 1.0.2 1.0.3 1.0.4 2.0.0 2.0.1 2.0.2 2.0.3
dr-flex / dr-flex.php

dr-flex.php in Dr. Flex trunk, at dr-flex.php

811 lines 31.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: Dr. Flex
4 Plugin URI: https://dr-flex.de/
5 Description: The official Dr. Flex® Wordpress plugin for easy integration of the Dr. Flex® booking tool on your website.
6 Version: 2.0.3
7 Requires at least: 5.0
8 Author: Dr. Flex
9 Author URI: https://dr-flex.de
10 Text Domain: dr-flex
11 Domain Path: /languages
12 License: GNU GPLv3
13 Contributors: Johannes Dato
14 */
15
16 /*
17 Copyright (C) 2020 Dr. Flex® GmbH, https://dr-flex.de
18
19 This program is free software; you can redistribute it and/or modify
20 it under the terms of the GNU General Public License as published by
21 the Free Software Foundation; version 3 of the License.
22
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU General Public License for more details.
27
28 You should have received a copy of the GNU General Public License
29 along with this program. If not, see <http://www.gnu.org/licenses/>.
30 */
31
32 if (!defined('ABSPATH')) {
33 return;
34 }
35
36 include_once 'components/drflex_constants.php';
37 include_once 'components/drflex_cache.php';
38 include_once 'components/drflex_utils.php';
39 include_once 'components/drflex_rest_api.php';
40 include_once 'components/drflex_shortcode.php';
41
42 /**
43 * Debug logger.
44 */
45 function drflex_debug($log)
46 {
47 if (true === WP_DEBUG) {
48 if (is_array($log) || is_object($log)) {
49 error_log(print_r($log, true));
50 } else {
51 error_log($log);
52 }
53 }
54 }
55
56 /**
57 * Error logger for debugging.
58 */
59 function drflex_error($message)
60 {
61 if (is_array($message)) {
62 $message = json_encode($message);
63 }
64 $file = fopen("drflex_error.log", "a");
65 fwrite($file, '[' . date('j-M-Y H:i:s e') . "] " . $message . "\n");
66 fclose($file);
67 }
68
69 ////////////////////////////////////////////////////////////////////////////////////////////////////////
70
71 // Activation and Deactivation Hooks.
72
73 /**
74 * On activation of plugin.
75 */
76 function drflex_activate()
77 {
78 if (!drflex_cache_upgrade()) {
79 drflex_error('Upgrade failed.');
80 }
81 // else {
82 // drflex_debug('Upgrade succeeded.');
83 // }
84 // debug("Dr.Flex plugin activated!");
85 }
86
87 register_activation_hook(__FILE__, 'drflex_activate');
88
89 /**
90 * On deactivation of plugin.
91 */
92 function drflex_deactivate()
93 {
94 if (drflex_cache_downgrade()) {
95 delete_option('drflex_connection_status');
96 delete_option('drflex_api_key');
97 delete_option('drflex_callback_textarea');
98 delete_option('drflex_button_configs');
99 // debug('Downgrade succeeded.');
100 } else {
101 drflex_error('Downgrade failed.');
102 }
103 // debug("Dr.Flex plugin deactivated!");
104 }
105
106 register_deactivation_hook(__FILE__, 'drflex_deactivate');
107
108 ////////////////////////////////////////////////////////////////////////////////////////////////////////
109
110 /**
111 * Initialize Plugin Internationalization.
112 */
113 function drflex_load_plugin_textdomain() {
114 load_plugin_textdomain( 'dr-flex', FALSE, basename( dirname( __FILE__ ) ) . '/languages/' );
115 }
116
117 add_action( 'plugins_loaded', 'drflex_load_plugin_textdomain' );
118
119 /**
120 * Registers stylesheets and scripts for admin page.
121 */
122 function drflex_register_plugin_styles_and_scripts()
123 {
124 $p = plugin_dir_path( __FILE__ );
125
126 // At first styles - order matters!
127 $styles = array(
128 'codemirror' => 'css/codemirror.css',
129 'drflex' => 'css/drflex.css'
130 );
131
132 // Second scripts
133 $scripts = array(
134 'drflex' => 'js/drflex.js',
135 'codemirror' => 'js/codemirror.js',
136 'cmjavascript' => 'js/javascript.js'
137 );
138
139 foreach ($styles as $handle => $uri) {
140 wp_register_style($handle, plugins_url('dr-flex/' . $uri), array(), date('YmdHis', filemtime($p . $uri)));
141 wp_enqueue_style($handle);
142 }
143
144 foreach ($scripts as $handle => $uri) {
145 wp_register_script($handle, plugins_url('dr-flex/' . $uri), array(), date('YmdHis', filemtime($p . $uri)));
146 wp_enqueue_script($handle);
147 }
148 }
149
150 // Register style sheets and scripts.
151 add_action('admin_enqueue_scripts', 'drflex_register_plugin_styles_and_scripts');
152
153 /**
154 * Registers stylesheets and scripts for site.
155 */
156 function drflex_register_styles_and_scripts()
157 {
158 $p = plugin_dir_path(__FILE__);
159
160 // At first styles - order matters!
161 $styles = array(
162 'drflex-site' => 'css/drflex-site.css'
163 );
164
165 foreach ($styles as $handle => $uri) {
166 wp_register_style($handle, plugins_url('dr-flex/' . $uri), array(), date('YmdHis', filemtime($p . $uri)));
167 wp_enqueue_style($handle);
168 }
169
170 if (get_option('drflex_callback_textarea', null) != null) {
171 $handle = $GLOBALS['drflex_callback_function_file_name'];
172 wp_register_script($handle, drflex_utils_get_rest_route() . $handle, array(), date('YmdHis', filemtime($p . $uri)));
173 wp_enqueue_script($handle);
174 }
175
176 $corejs = drflex_cache_check_latest_resource_by_uri('generatedEmbedScript');
177
178 if (count($corejs) > 0) {
179 $vars = get_object_vars($corejs[0]);
180
181 $content = $vars['resource_data'];
182 wp_register_script('generated-embed-script', false);
183 wp_enqueue_script('generated-embed-script');
184 wp_add_inline_script('generated-embed-script', $content);
185 }
186 }
187
188 add_action('wp_enqueue_scripts', 'drflex_register_styles_and_scripts');
189
190 ////////////////////////////////////////////////////////////////////////////////////////////////////////
191
192 /**
193 * Function to create the Dr. Flex Admin Menu Page Settings
194 *
195 */
196 function drflex_register_plugin_settings()
197 {
198 register_setting('drflex-plugin-settings-group', 'drflex_connection_status');
199 register_setting('drflex-plugin-settings-group', 'drflex_api_key');
200 register_setting('drflex-plugin-settings-group', 'drflex_callback_textarea');
201 register_setting('drflex-plugin-settings-group', 'drflex_button_configs');
202 }
203
204 /**
205 * Function to create the Dr. Flex Admin Menu Page
206 *
207 */
208 function drflex_plugin_create_menu()
209 {
210 $title = __('Dr. Flex', 'dr-flex');
211 //create new top-level menu
212 add_menu_page($title, $title, 'administrator', 'drflex_plugin_settings', 'drflex_plugin_settings_page', 'dashicons-calendar-alt');
213 add_submenu_page('drflex_plugin_settings', $title, __('Configuration', 'dr-flex'), 'administrator', 'drflex_plugin_settings', '');
214
215 add_submenu_page('drflex_plugin_settings', $title, __('Button integration', 'dr-flex'), 'administrator', 'drflex_plugin_settings_integration', 'drflex_plugin_settings_integration_subpage');
216 add_submenu_page('drflex_plugin_settings', $title, __('Code examples', 'dr-flex'), 'administrator', 'drflex_plugin_settings_examples', 'drflex_plugin_settings_examples_subpage');
217
218 //call register settings function
219 add_action('admin_init', 'drflex_register_plugin_settings');
220 }
221
222 // create custom plugin settings menu
223 add_action('admin_menu', 'drflex_plugin_create_menu');
224
225
226
227 function drflex_heading($title)
228 {
229 ?> <h1><?php echo get_admin_page_title(); ?> <?php echo $title; ?> </h1> <?php
230 }
231
232 function drflex_plugin_settings_page()
233 {
234 $fn_arr = explode('(', $GLOBALS['drflex_callback_function_name']);
235 $fn_name = $fn_arr[0];
236 $fn_arg = rtrim($fn_arr[1], ")");
237
238 ?>
239 <div class="wrap">
240 <?php drflex_heading(__('Plugin Settings', 'dr-flex'));?>
241
242 <form action="options.php" method="post">
243
244 <?php settings_fields('drflex-plugin-settings-group');?>
245 <?php do_settings_sections('drflex-plugin-settings-group');?>
246
247 <h2><?php _e("Settings for the booking tool on your website", 'dr-flex') ?></h2>
248 <table class="form-table" role="presentation">
249 <tbody>
250 <tr>
251 <th scope="row"><label for="drflex_connection_status"><?php _e("Connection status", 'dr-flex') ?></label></th>
252 <td><input class="regular-text" id="drflex_connection_status"
253 name="drflex_connection_status" title="<?php _e("Connection status", 'dr-flex') ?>" type="hidden"
254 value="">
255 <p class="help">
256 <?php echo drflex_check_status(); ?>
257 </p>
258 </td>
259 </tr>
260 <tr>
261 <th scope="row"><label for="drflex_api_key"><?php _e("Dr. Flex API Key", 'dr-flex') ?></label></th>
262 <td><input class="regular-text" id="drflex_api_key" name="drflex_api_key"
263 placeholder="<?php _e("Please enter your Dr. Flex API Key", 'dr-flex') ?>" title="<?php _e("Dr. Flex API Key", 'dr-flex') ?>" type="password"
264 value="<?php echo esc_attr(get_option('drflex_api_key')); ?>">
265 <span class="dashicons dashicons-visibility" id="togglePassword"></span>
266 <p class="help">
267 <?php printf( '%s<br>%s',
268 __('The API key has probably already been sent to you by the Dr. Flex support team by email.<br>You can also find it in the Dr. Flex Praxis-Konfigurator under <strong>Praxis &rarr; Verbindung und Integrationen</strong>. <a href="https://dr-flex.de/login" target="_blank"> (here)</a>', 'dr-flex'),
269 __('Please insert it into the field <strong>API Key</strong>.', 'dr-flex')
270 ); ?>
271 </p>
272 </td>
273 </tr>
274 <tr>
275 <th scope="row"><label for="drflex_callback_textarea"><?php _e("Callback", 'dr-flex') ?></label></th>
276 <td>
277 <div class="drflex-code-snippet cm-s-default"><span class="cm-keyword"><?php echo $fn_name; ?></span>(<span class="cm-def"><?php echo $fn_arg; ?></span>) {</div>
278 <textarea class="large-text drflex-textarea" id="drflex_callback_textarea"
279 name="drflex_callback_textarea"
280 placeholder="<?php _e("Optional JavaScript callback.", 'dr-flex') ?>" rows="5" cols="100" wrap="hard"
281 style="width: auto; white-space: pre-wrap; display: none;"
282 title="<?php _e("Callback", 'dr-flex') ?>"><?php echo esc_attr(get_option('drflex_callback_textarea')); ?></textarea>
283 <div class="drflex-code-snippet">}</div>
284 <p class="help">
285 <?php printf(
286 '%s <a href="%s">%s</a>.',
287 __('The JavaScript code you enter is executed during certain user actions. How this code might look like in different scenarios can be found at', 'dr-flex'),
288 menu_page_url("drflex_plugin_settings_examples", false),
289 __('Examples', 'dr-flex')
290 ); ?>
291 </p>
292 </td>
293 </tr>
294 <tr>
295 <th scope="row"><label for="drflex_button_configs"><?php _e("Your Buttons", 'dr-flex') ?></label></th>
296 <td><input class="regular-text" id="drflex_button_configs"
297 name="drflex_button_configs" title="<?php _e("Your Buttons", 'dr-flex') ?>" type="hidden"
298 value="">
299 <p class="help"></p>
300 <?php echo drflex_check_configuration(); ?>
301 </td>
302 </tr>
303 </tbody>
304 </table>
305 <?php submit_button(null, "primary drflex-submit"); ?>
306 </form>
307 </div>
308
309 <?php
310 }
311
312 /**
313 * Function to create the Dr. Flex Admin Menu Integration Subpage
314 *
315 */
316 function drflex_plugin_settings_integration_subpage()
317 {
318 ?>
319 <div class="wrap">
320 <?php
321 drflex_heading(__("Optimal button integration", 'dr-flex'));
322 ?>
323 <div class="drflex_integration">
324 <h2><?php _e("The following points should be considered when integrating the booking button on the practice website.", 'dr-flex') ?></h2>
325
326 <ol>
327 <li>
328 <div><?php _e("<span class='green'>Appearance and placement of the booking button</span> for the user (patient) on the practice website (user interface = UI).", 'dr-flex'); ?></div>
329 <ul>
330 <li><?php _e("How does the button stand out from the rest of the website (color, shape, placement)? <span class='green'>(the more striking, the better the service is used)</span>", 'dr-flex'); ?></li>
331 <li><?php _e("Is a button placed in the header, footer and under contact / appointment / service (combination with the best conversion) and thus clearly visible to the user on all sub-pages?", 'dr-flex'); ?></li>
332 </ul>
333 </li>
334 <li>
335 <div><?php _e("<span class='green'>Behavior of the booking button</span> (User Experience = UX)", 'dr-flex'); ?></div>
336 <ul>
337 <li><?php _e("Does the button react or move when the mouse is moved or clicked on it?", 'dr-flex'); ?></li>
338 <li><?php _e("Does a click open the Dr. Flex booking calendar?", 'dr-flex'); ?></li>
339 </ul>
340 </li>
341 <li>
342 <div class="green"><?php _e("Desktop, Tablet & Mobile", 'dr-flex'); ?></div>
343 <ul>
344 <li><?php _e("Is the button also well integrated in the mobile and tablet version under the above mentioned criteria?", 'dr-flex'); ?></li>
345 </ul>
346 </li>
347 </ol>
348 </div>
349 <?php
350 }
351
352 /**
353 * Function to create the Dr. Flex Admin Menu Examples Subpage
354 *
355 */
356 function drflex_plugin_settings_examples_subpage()
357 {
358 ?>
359 <div class="wrap">
360 <?php drflex_heading(__("Callback Code Examples", 'dr-flex'));?>
361 <p><?php _e("Here are some sample code snippets for the callback function which could be used on the configuration page.
362 When using such functions, data protection aspects must be considered, observed and marked accordingly on the page!
363 These examples are provided without any warranty and for informative purposes only.", 'dr-flex'); ?>
364 </p>
365 <div>
366 <?php
367 $drflex_callback_examples_url = $GLOBALS['drflex_host'] . $GLOBALS['drflex_wordpress_callback_examples_relurl'];
368 $response = drflex_utils_fetch_from_url($drflex_callback_examples_url);
369
370 if ($response != false && count($response) > 1 && $response['status'] == 200) {
371 $examples_array = json_decode($response['content']);
372
373 foreach($examples_array as $example_obj) {
374 $example = get_object_vars($example_obj)
375 ?>
376 <h2><?php echo $example['title']; ?></h2>
377 <p><?php echo $example['description']; ?></p>
378 <textarea class="large-text drflex-textarea drflex_examples_textarea"
379 name="drflex_examples_textarea"
380 placeholder="<?php _e("If you reload the page, you will see the code snippets again.", 'dr-flex'); ?>"
381 title="<?php _e("Callback examples", 'dr-flex'); ?>"><?php echo $example['code']; ?></textarea>
382 <?php
383 }
384 }
385 ?>
386 </div>
387 <?php
388 }
389
390 /**
391 * Function attached to Add and Update Hooks for the plugin options in wordpress.
392 *
393 * @param array $old_option_value the old option value
394 * @param array $new_option_value the new option value
395 * @param string $op options
396 */
397 function drflex_update_api_key_option($old_option_value, $new_option_value, $op = '')
398 {
399 if ($old_option_value === $old_option_value) {
400 drflex_cache_clear_cache();
401 }
402
403 if ($new_option_value !== '') {
404 drflex_update_resources();
405 }
406 }
407
408 /**
409 * Function attached to Add and Update Hooks for the plugin options in wordpress.
410 *
411 * @param array $old_option_value the old option value
412 * @param array $new_option_value the new option value
413 * @param string $op options
414 */
415 function drflex_update_callback_option($old_option_value, $new_option_value, $op = '')
416 {
417 $label = '/' . $GLOBALS['drflex_callback_function_file_name'];
418
419 if (!empty($new_option_value)) {
420 $drflex_callable = "function {$GLOBALS['drflex_callback_function_name']} {\n\t" . $new_option_value . "\n}";
421 // debug("Insert: $drflex_callable");
422 drflex_cache_insert_or_update_resource($label, $drflex_callable, 'application/javascript; charset=utf-8', null, true, true);
423 } else {
424 drflex_cache_delete_resource_by_uri($label);
425 }
426 }
427
428 add_action('add_option_drflex_api_key', 'drflex_update_api_key_option', 10, 2);
429 add_action('update_option_drflex_api_key', 'drflex_update_api_key_option', 10, 3);
430
431 add_action('add_option_drflex_callback_textarea', 'drflex_update_callback_option', 10, 2);
432 add_action('update_option_drflex_callback_textarea', 'drflex_update_callback_option', 10, 3);
433
434 ////////////////////////////////////////////////////////////////////////////////////////////////////////
435
436 /**
437 * Check configuration, function that returns the cofiguration HTML for the settings page.
438 *
439 * @return string settings HTML
440 */
441 function drflex_check_configuration()
442 {
443
444 $buttons = '';
445
446 function button_html($button_id, $button_text, $default = false)
447 {
448
449 if (!$default) {
450 $display = "\ndisplay: none;";
451 } else {
452 $display = '';
453 }
454
455 printf("<div class='dr-flex-button'>
456 <div class='dr-flex-btn-header'>
457 <div class='dr-flex-btn-title'>%s [ <span>%s</span> ]</div>
458 <div class='dr-flex-btn-type'><span style='%s'>%s</span></div>
459 </div>
460 <div class='dr-flex-btn-body'><strong>%s: </strong>%s</div>
461 <div class='dr-flex-btn-shortcode'><strong>%s:</strong> <span class='dr-flex-code'>[drflex id=%s]</span></div>
462 </div>",
463 __('Button ID', 'dr-flex'),
464 $button_id,
465 $display,
466 __('Standard', 'dr-flex'),
467 __('Description', 'dr-flex'),
468 $button_text,
469 __('Minimal shortcode', 'dr-flex'),
470 $button_id
471 );
472 }
473
474 if (drflex_cache_db_ready()) {
475 $button_configs = drflex_cache_check_latest_resource_by_uri('buttonConfigurations');
476
477 if (!empty($button_configs)) {
478 $object_vars = get_object_vars($button_configs[0]);
479 $button_configs_objects = json_decode($object_vars['resource_data']);
480 if ($button_configs_objects != null) {
481 $button_configs_array = array_map(function ($a) {
482 return get_object_vars($a);
483 }, $button_configs_objects);
484 foreach ($button_configs_array as $button) {
485 button_html($button['id'], $button['html_description'], $button['is_default']);
486 }
487
488 $hw = menu_page_url('drflex_plugin_settings_integration', false);
489
490 $buttons .= sprintf("<h3><span class=\"dashicons dashicons-shortcode dr-flex-heading-icon\"></span> %s:</h3>
491 %s <a href=\"%s\">%s</a>.
492 <br>
493 <br>
494 %s
495 <ol>
496 <li>%s: <span class=\"dr-flex-code\">background=#68e697</span></li>
497 <li>%s: <span class=\"dr-flex-code\">color=#ffffff</span></li>
498 <li>%s: <span class=\"dr-flex-code\">border_radius=1.0em</span></li>
499 <li>%s: <span class=\"dr-flex-code\">padding=1.0em</span></li>
500 <li>%s: <span class=\"dr-flex-code\">text='Termin online buchen'</span></li>
501 <li>%s: <span class=\"dr-flex-code\">css-classes='drflex-button'</span></li>
502 </ol>
503 %s
504 <br><br>
505 %s:<br><span class=\"dr-flex-code\">[drflex id=1 background=#f50 color=#00f border-radius=15.0px padding=10.0px text='Termin mit Dr. Flex buchen!' css-classes='custom-css-button weitere-klasse']</span>
506 <br>
507 <br>
508 <h3><span class=\"dashicons dashicons-menu-alt3 dr-flex-heading-icon\"></span> %s:</h3>
509 %s:
510 <br>
511 <br>
512 <span class=\"dr-flex-code\">https://toggleDrFlexAppointments()</span>
513 <br>
514 <br>
515 %s
516 <br>
517 %s
518 ",
519 __('Button integration with shortcode on pages', 'dr-flex'),
520 __('The buttons can be integrated via their ID\'s (e.g. id=1) via <a href="https://codex.wordpress.org/shortcode" target="_blank">Wordpress Shortcodes</a>. Please see also the', 'dr-flex'),
521 $hw,
522 __('Notes on button integration', 'dr-flex'),
523 __('The following optional attributes can be used in addition to <strong>id</strong> (CSS notation):', 'dr-flex'),
524 __('Background color as HEX value', 'dr-flex'),
525 __('Font color as HEX value', 'dr-flex'),
526 __('Rounded edges as decimal number + CSS unit (px, em, vw, vh, rem, %)', 'dr-flex'),
527 __('Padding as decimal number + CSS unit (px, em, vw, vh, rem, %)', 'dr-flex'),
528 __('Individual text for the button', 'dr-flex'),
529 __('Custom CSS classes for the button', 'dr-flex'),
530 __('If the attributes are not set, the above default values are used. By the way, the attributes can also only be added individually.', 'dr-flex'),
531 __('Here is an example short code with all attributes', 'dr-flex'),
532
533 __('Button integration as wordpress menu item', 'dr-flex'),
534 __('To integrate the booking button as a menu item in the site navigation, create a new individual link item in the wordpress menu and add the follwing text as the link URL', 'dr-flex'),
535 __('Now add a text to your link such as "Schedule appointment online" and save the new menu configuration.', 'dr-flex'),
536 __('Note that, the URL has to contain all the characters above, including the parentheses, in order to work properly.', 'dr-flex')
537 );
538
539 $msg = $buttons;
540 } else {
541 $msg = __("Configuration data have the wrong format. Error 230", 'dr-flex');
542 }
543 } else {
544 $msg = __("There is no configuration data available at the moment.", 'dr-flex');
545 }
546 } else {
547 $msg = __("The data for your account could not be loaded.", 'dr-flex');
548 }
549
550 return $msg;
551 }
552
553 /**
554 * Function that checks whether the entered API Key is valid or not.
555 *
556 * @return string HTML API Key validity indicator
557 */
558 function drflex_check_status()
559 {
560
561 $indicator_gen = '<span class="dr-flex-status-indicator" style="background-color: <<status_color>>;"><<status_text>></span>';
562
563 function invalid($indicator_gen)
564 {
565 $indicator = str_replace('<<status_color>>', $GLOBALS['drflex_colors_primary_red'], $indicator_gen);
566 $indicator = str_replace('<<status_text>>', __('API key invalid', 'dr-flex'), $indicator);
567 return $indicator;
568 }
569
570 function incomplete($indicator_gen)
571 {
572 $indicator = str_replace('<<status_color>>', $GLOBALS['drflex_colors_primary_orange'], $indicator_gen);
573 $indicator = str_replace('<<status_text>>', __('Not yet connected', 'dr-flex'), $indicator);
574 return $indicator;
575 }
576
577 // debug(db_ready());
578 if (drflex_cache_db_ready()) {
579 $api_key_data = drflex_cache_check_latest_resource_by_uri('generatedEmbedScript');
580
581 if (!empty($api_key_data) && get_option('drflex_api_key', null) != null) {
582 $indicator = str_replace('<<status_color>>', $GLOBALS['drflex_colors_primary_green'], $indicator_gen);
583 $indicator = str_replace('<<status_text>>', __('API key valid', 'dr-flex'), $indicator);
584 return $indicator;
585 } else {
586 return invalid($indicator_gen);
587 }
588 } else {
589 return incomplete($indicator_gen);
590 }
591 }
592
593 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
594
595 /**
596 * Helper function to fetch a resource form a url and insert it into the database cache.
597 *
598 * @param string $resource_uri uri of the resource to fetch
599 */
600 function drflex_fetch_and_insert_latest_resource_version($resource_uri)
601 {
602
603 $response = drflex_utils_fetch_from_url($resource_uri, true);
604
605 if ($response != false && count($response) > 1) {
606 $content = $response['content'];
607 $contentType = $response['content-type'];
608 $xContentEncoding = $response['x-content-encoding'];
609 drflex_debug("X-Content-Encoding: " . $xContentEncoding);
610
611 drflex_cache_insert_or_update_resource($resource_uri, $content, $contentType, $xContentEncoding, true);
612 } else {
613 drflex_error("CURL fehler.");
614 }
615 }
616
617 ////////////////////////////////////////////////////////////////////////////////////////////////////////
618
619 /**
620 * Main function that is being excecuted on every pageload. This function checks if the resources
621 * that are listed in the config json file, that was fetched from the Dr. Flex service, are
622 * already cached in the database and if not it fetches and inserts them. On every load the hash
623 * values of the files are checked and if they have changed the resource will be updated. There is
624 * a delay which is defined in components/constants.php that will be applied to the update process
625 * in order to make the operation less resource-intensive.
626 *
627 */
628 function drflex_update_resources()
629 {
630 if (drflex_plugin_database_needs_update()) {
631 drflex_debug("Database needs update. Updating...");
632 if (drflex_cache_upgrade()) {
633 drflex_debug("Update successful.");
634 } else {
635 drflex_error("Error ocurred updating database");
636 }
637 }
638
639 function update()
640 {
641 // drflex_debug("Update Resources.");
642
643 function has_hash($im_cache, $hash)
644 {
645 foreach ($im_cache as $item) {
646 if ($hash === $item['resource_hash_md5']) {
647 return true;
648 }
649 }
650
651 return false;
652 }
653
654 function get_data($im_cache, $uri)
655 {
656 foreach ($im_cache as $item) {
657 if ($uri === $item['resource_uri']) {
658 return $item['resource_data'];
659 }
660 }
661
662 return array();
663 }
664
665 function clean_up_deprecated($im_cache, $config_files)
666 {
667 $items_to_remove = array();
668 foreach ($im_cache as $cached_item) {
669 if (
670 $cached_item['resource_uri'] !== "generatedEmbedScript" &&
671 $cached_item['resource_uri'] !== "buttonConfigurations" &&
672 $cached_item['permanent'] != true
673 ) {
674 $items_to_remove[] = $cached_item;
675 $position = count($items_to_remove) - 1;
676 foreach ($config_files as $config_item) {
677 if ($cached_item['resource_uri'] === $config_item['drflex_url']) {
678 array_splice($items_to_remove, $position, 1);
679 }
680 }
681 }
682 }
683
684 $delete_ids = array_map(function ($a) {
685 return $a['id'];
686 }, $items_to_remove);
687
688 drflex_cache_delete_resources($delete_ids);
689 }
690
691 $cache = drflex_cache_get_cache();
692 $im_cache = array();
693
694 foreach ($cache as $item) {
695 $cachable_item = get_object_vars($item);
696 $im_cache[] = $cachable_item;
697 }
698
699 $drflex_config_file_url = $GLOBALS['drflex_host'] . $GLOBALS['drflex_cofig_relpath'];
700
701 $response = drflex_utils_fetch_from_url($drflex_config_file_url);
702
703 if ($response != false && count($response) > 1 && $response['status'] == 200) {
704 $configObject = json_decode($response['content']);
705 $config = get_object_vars($configObject);
706
707 // Fetch embed script
708 $embed_script_data = $config['generated_embed_script'];
709 $es_vars = get_object_vars($embed_script_data);
710
711 if (!has_hash($im_cache, $es_vars['md5_hash'])) {
712 if (!drflex_cache_insert_or_update_resource('generatedEmbedScript', drflex_utils_json_unescape($es_vars['data']), null, null)) {
713 drflex_error("An error occurred while writing the generated embed script to the database.");
714 }
715 }
716
717 $config_files = array();
718
719 // Fetch files
720 foreach ($config['files'] as $fileObject) {
721 $file = get_object_vars($fileObject);
722 $config_files[] = $file;
723 $resource_uri = $file['drflex_url'];
724
725 if (!has_hash($im_cache, $file['md5_hash'])) {
726 // debug( "Resource does not exist or is deprecated in mysql db." );
727 if ($file['md5_hash'] !== null) {
728 drflex_fetch_and_insert_latest_resource_version($resource_uri);
729 } else {
730 drflex_cache_insert_or_update_resource($resource_uri, null, null, null, true);
731 }
732 } // else {
733 // debug("Latest resource version already exists in mysql db.");
734 // Do nothing
735 // debug("f cache: $resource_uri");
736 // }
737 ;
738 }
739
740 // DB cleanup
741 clean_up_deprecated($im_cache, $config_files);
742
743 // Fetch configs
744 if (array_key_exists('button_configurations', $config)) {
745 $btn_cnf = json_encode($config['button_configurations']);
746 drflex_cache_insert_or_update_resource('buttonConfigurations', $btn_cnf, null, null);
747 } else {
748 drflex_error("Button configuration missing in config json.");
749 }
750
751 // Update fetch timestamp
752 drflex_cache_insert_config_item("last_update_timestamp", null);
753
754 } else {
755 if ($response['status'] === 401){
756 drflex_cache_clear_cache();
757 drflex_error($response['content']);
758 } else {
759 drflex_error("Error trying to fetch config.json.");
760 }
761 }
762 }
763
764 $last_update = drflex_cache_get_config_item("last_update_timestamp");
765
766 if (count($last_update) > 0) {
767 $last_update = get_object_vars($last_update[0]);
768
769 if (array_key_exists("created_at", $last_update)) {
770
771 $created_date_time = date_create_from_format("Y-m-d H:i:s", $last_update["created_at"]);
772 $last_timestamp = $created_date_time->getTimestamp();
773
774 $drflex_update_interval_secs = $GLOBALS['drflex_update_interval_secs'];
775
776 if (time() - $drflex_update_interval_secs > $last_timestamp) {
777 update();
778 } // else {
779 // debug("Wait");
780 //}
781 } else {
782 update();
783 }
784 } else {
785 update();
786 }
787 }
788
789 add_action('wp', 'drflex_update_resources');
790
791 ////////////////////////////////////////////////////////////////////////////////////////////////////////
792
793 /**
794 * Function to replace Dr. Flex Menu items with the toggle logic.
795 *
796 * @param string $items Menu items from wordpress navigation fuction
797 * @return string the modified items sting with the proper toggle command
798 */
799 function drflex_replace_dr_flex_placeholer_menu_item($items) {
800
801 $replacement = $GLOBALS['drflex_toggle_href'];
802
803 $items = str_replace('https://toggleDrFlexAppointments()', $replacement, $items);
804 $items = str_replace('http://toggleDrFlexAppointments()', $replacement, $items);
805 $items = str_replace('https://javascript:toggleDrFlexAppointments()', $replacement, $items);
806 $items = str_replace('http://javascript:toggleDrFlexAppointments()', $replacement, $items);
807
808 return $items;
809 }
810
811 add_filter('wp_nav_menu_items', 'drflex_replace_dr_flex_placeholer_menu_item');