PluginProbe
Dr. Flex / 2.0.0
Dr. Flex v2.0.0
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 2.0.0, at dr-flex.php

813 lines 31.8 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.0
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<br>%s%s',
268 __('The API key can be found in the settings in the Dr. Flex client application (or <a href="https://dr-flex.de/doctors" target="_blank">here online</a>).', 'dr-flex'),
269 __('Navigate to the <strong>Account tab</strong> and then go to <strong>Settings</strong>.', 'dr-flex'),
270 __('Here you can generate a <strong>new API Key for the Wordpress Plugin</strong>.', 'dr-flex'),
271 __('Please insert it into the field <strong>API Key</strong>.', 'dr-flex')
272 ); ?>
273 </p>
274 </td>
275 </tr>
276 <tr>
277 <th scope="row"><label for="drflex_callback_textarea"><?php _e("Callback", 'dr-flex') ?></label></th>
278 <td>
279 <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>
280 <textarea class="large-text drflex-textarea" id="drflex_callback_textarea"
281 name="drflex_callback_textarea"
282 placeholder="<?php _e("Optional JavaScript callback.", 'dr-flex') ?>" rows="5" cols="100" wrap="hard"
283 style="width: auto; white-space: pre-wrap; display: none;"
284 title="<?php _e("Callback", 'dr-flex') ?>"><?php echo esc_attr(get_option('drflex_callback_textarea')); ?></textarea>
285 <div class="drflex-code-snippet">}</div>
286 <p class="help">
287 <?php printf(
288 '%s <a href="%s">%s</a>.',
289 __('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'),
290 menu_page_url("drflex_plugin_settings_examples", false),
291 __('Examples', 'dr-flex')
292 ); ?>
293 </p>
294 </td>
295 </tr>
296 <tr>
297 <th scope="row"><label for="drflex_button_configs"><?php _e("Your Buttons", 'dr-flex') ?></label></th>
298 <td><input class="regular-text" id="drflex_button_configs"
299 name="drflex_button_configs" title="<?php _e("Your Buttons", 'dr-flex') ?>" type="hidden"
300 value="">
301 <p class="help"></p>
302 <?php echo drflex_check_configuration(); ?>
303 </td>
304 </tr>
305 </tbody>
306 </table>
307 <?php submit_button(null, "primary drflex-submit"); ?>
308 </form>
309 </div>
310
311 <?php
312 }
313
314 /**
315 * Function to create the Dr. Flex Admin Menu Integration Subpage
316 *
317 */
318 function drflex_plugin_settings_integration_subpage()
319 {
320 ?>
321 <div class="wrap">
322 <?php
323 drflex_heading(__("Optimal button integration", 'dr-flex'));
324 ?>
325 <div class="drflex_integration">
326 <h2><?php _e("The following points should be considered when integrating the booking button on the practice website.", 'dr-flex') ?></h2>
327
328 <ol>
329 <li>
330 <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>
331 <ul>
332 <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>
333 <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>
334 </ul>
335 </li>
336 <li>
337 <div><?php _e("<span class='green'>Behavior of the booking button</span> (User Experience = UX)", 'dr-flex'); ?></div>
338 <ul>
339 <li><?php _e("Does the button react or move when the mouse is moved or clicked on it?", 'dr-flex'); ?></li>
340 <li><?php _e("Does a click open the Dr. Flex booking calendar?", 'dr-flex'); ?></li>
341 </ul>
342 </li>
343 <li>
344 <div class="green"><?php _e("Desktop, Tablet & Mobile", 'dr-flex'); ?></div>
345 <ul>
346 <li><?php _e("Is the button also well integrated in the mobile and tablet version under the above mentioned criteria?", 'dr-flex'); ?></li>
347 </ul>
348 </li>
349 </ol>
350 </div>
351 <?php
352 }
353
354 /**
355 * Function to create the Dr. Flex Admin Menu Examples Subpage
356 *
357 */
358 function drflex_plugin_settings_examples_subpage()
359 {
360 ?>
361 <div class="wrap">
362 <?php drflex_heading(__("Callback Code Examples", 'dr-flex'));?>
363 <p><?php _e("Here are some sample code snippets for the callback function which could be used on the configuration page.
364 When using such functions, data protection aspects must be considered, observed and marked accordingly on the page!
365 These examples are provided without any warranty and for informative purposes only.", 'dr-flex'); ?>
366 </p>
367 <div>
368 <?php
369 $drflex_callback_examples_url = $GLOBALS['drflex_host'] . $GLOBALS['drflex_wordpress_callback_examples_relurl'];
370 $response = drflex_utils_fetch_from_url($drflex_callback_examples_url);
371
372 if ($response != false && count($response) > 1 && $response['status'] == 200) {
373 $examples_array = json_decode($response['content']);
374
375 foreach($examples_array as $example_obj) {
376 $example = get_object_vars($example_obj)
377 ?>
378 <h2><?php echo $example['title']; ?></h2>
379 <p><?php echo $example['description']; ?></p>
380 <textarea class="large-text drflex-textarea drflex_examples_textarea"
381 name="drflex_examples_textarea"
382 placeholder="<?php _e("If you reload the page, you will see the code snippets again.", 'dr-flex'); ?>"
383 title="<?php _e("Callback examples", 'dr-flex'); ?>"><?php echo $example['code']; ?></textarea>
384 <?php
385 }
386 }
387 ?>
388 </div>
389 <?php
390 }
391
392 /**
393 * Function attached to Add and Update Hooks for the plugin options in wordpress.
394 *
395 * @param array $old_option_value the old option value
396 * @param array $new_option_value the new option value
397 * @param string $op options
398 */
399 function drflex_update_api_key_option($old_option_value, $new_option_value, $op = '')
400 {
401 if ($old_option_value === $old_option_value) {
402 drflex_cache_clear_cache();
403 }
404
405 if ($new_option_value !== '') {
406 drflex_update_resources();
407 }
408 }
409
410 /**
411 * Function attached to Add and Update Hooks for the plugin options in wordpress.
412 *
413 * @param array $old_option_value the old option value
414 * @param array $new_option_value the new option value
415 * @param string $op options
416 */
417 function drflex_update_callback_option($old_option_value, $new_option_value, $op = '')
418 {
419 $label = '/' . $GLOBALS['drflex_callback_function_file_name'];
420
421 if (!empty($new_option_value)) {
422 $drflex_callable = "function {$GLOBALS['drflex_callback_function_name']} {\n\t" . $new_option_value . "\n}";
423 // debug("Insert: $drflex_callable");
424 drflex_cache_insert_or_update_resource($label, $drflex_callable, 'application/javascript; charset=utf-8', null, true, true);
425 } else {
426 drflex_cache_delete_resource_by_uri($label);
427 }
428 }
429
430 add_action('add_option_drflex_api_key', 'drflex_update_api_key_option', 10, 2);
431 add_action('update_option_drflex_api_key', 'drflex_update_api_key_option', 10, 3);
432
433 add_action('add_option_drflex_callback_textarea', 'drflex_update_callback_option', 10, 2);
434 add_action('update_option_drflex_callback_textarea', 'drflex_update_callback_option', 10, 3);
435
436 ////////////////////////////////////////////////////////////////////////////////////////////////////////
437
438 /**
439 * Check configuration, function that returns the cofiguration HTML for the settings page.
440 *
441 * @return string settings HTML
442 */
443 function drflex_check_configuration()
444 {
445
446 $buttons = '';
447
448 function button_html($button_id, $button_text, $default = false)
449 {
450
451 if (!$default) {
452 $display = "\ndisplay: none;";
453 } else {
454 $display = '';
455 }
456
457 printf("<div class='dr-flex-button'>
458 <div class='dr-flex-btn-header'>
459 <div class='dr-flex-btn-title'>%s [ <span>%s</span> ]</div>
460 <div class='dr-flex-btn-type'><span style='%s'>%s</span></div>
461 </div>
462 <div class='dr-flex-btn-body'><strong>%s: </strong>%s</div>
463 <div class='dr-flex-btn-shortcode'><strong>%s:</strong> <span class='dr-flex-code'>[drflex id=%s]</span></div>
464 </div>",
465 __('Button ID', 'dr-flex'),
466 $button_id,
467 $display,
468 __('Standard', 'dr-flex'),
469 __('Description', 'dr-flex'),
470 $button_text,
471 __('Minimal shortcode', 'dr-flex'),
472 $button_id
473 );
474 }
475
476 if (drflex_cache_db_ready()) {
477 $button_configs = drflex_cache_check_latest_resource_by_uri('buttonConfigurations');
478
479 if (!empty($button_configs)) {
480 $object_vars = get_object_vars($button_configs[0]);
481 $button_configs_objects = json_decode($object_vars['resource_data']);
482 if ($button_configs_objects != null) {
483 $button_configs_array = array_map(function ($a) {
484 return get_object_vars($a);
485 }, $button_configs_objects);
486 foreach ($button_configs_array as $button) {
487 button_html($button['id'], $button['html_description'], $button['is_default']);
488 }
489
490 $hw = menu_page_url('drflex_plugin_settings_integration', false);
491
492 $buttons .= sprintf("<h3><span class=\"dashicons dashicons-shortcode dr-flex-heading-icon\"></span> %s:</h3>
493 %s <a href=\"%s\">%s</a>.
494 <br>
495 <br>
496 %s
497 <ol>
498 <li>%s: <span class=\"dr-flex-code\">background=#68e697</span></li>
499 <li>%s: <span class=\"dr-flex-code\">color=#ffffff</span></li>
500 <li>%s: <span class=\"dr-flex-code\">border_radius=1.0em</span></li>
501 <li>%s: <span class=\"dr-flex-code\">padding=1.0em</span></li>
502 <li>%s: <span class=\"dr-flex-code\">text='Termin online buchen'</span></li>
503 <li>%s: <span class=\"dr-flex-code\">css-classes='drflex-button'</span></li>
504 </ol>
505 %s
506 <br><br>
507 %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>
508 <br>
509 <br>
510 <h3><span class=\"dashicons dashicons-menu-alt3 dr-flex-heading-icon\"></span> %s:</h3>
511 %s:
512 <br>
513 <br>
514 <span class=\"dr-flex-code\">https://toggleDrFlexAppointments()</span>
515 <br>
516 <br>
517 %s
518 <br>
519 %s
520 ",
521 __('Button integration with shortcode on pages', 'dr-flex'),
522 __('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'),
523 $hw,
524 __('Notes on button integration', 'dr-flex'),
525 __('The following optional attributes can be used in addition to <strong>id</strong> (CSS notation):', 'dr-flex'),
526 __('Background color as HEX value', 'dr-flex'),
527 __('Font color as HEX value', 'dr-flex'),
528 __('Rounded edges as decimal number + CSS unit (px, em, vw, vh, rem, %)', 'dr-flex'),
529 __('Padding as decimal number + CSS unit (px, em, vw, vh, rem, %)', 'dr-flex'),
530 __('Individual text for the button', 'dr-flex'),
531 __('Custom CSS classes for the button', 'dr-flex'),
532 __('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'),
533 __('Here is an example short code with all attributes', 'dr-flex'),
534
535 __('Button integration as wordpress menu item', 'dr-flex'),
536 __('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'),
537 __('Now add a text to your link such as "Schedule appointment online" and save the new menu configuration.', 'dr-flex'),
538 __('Note that, the URL has to contain all the characters above, including the parentheses, in order to work properly.', 'dr-flex')
539 );
540
541 $msg = $buttons;
542 } else {
543 $msg = __("Configuration data have the wrong format. Error 230", 'dr-flex');
544 }
545 } else {
546 $msg = __("There is no configuration data available at the moment.", 'dr-flex');
547 }
548 } else {
549 $msg = __("The data for your account could not be loaded.", 'dr-flex');
550 }
551
552 return $msg;
553 }
554
555 /**
556 * Function that checks whether the entered API Key is valid or not.
557 *
558 * @return string HTML API Key validity indicator
559 */
560 function drflex_check_status()
561 {
562
563 $indicator_gen = '<span class="dr-flex-status-indicator" style="background-color: <<status_color>>;"><<status_text>></span>';
564
565 function invalid($indicator_gen)
566 {
567 $indicator = str_replace('<<status_color>>', $GLOBALS['drflex_colors_primary_red'], $indicator_gen);
568 $indicator = str_replace('<<status_text>>', __('API key invalid', 'dr-flex'), $indicator);
569 return $indicator;
570 }
571
572 function incomplete($indicator_gen)
573 {
574 $indicator = str_replace('<<status_color>>', $GLOBALS['drflex_colors_primary_orange'], $indicator_gen);
575 $indicator = str_replace('<<status_text>>', __('Not yet connected', 'dr-flex'), $indicator);
576 return $indicator;
577 }
578
579 // debug(db_ready());
580 if (drflex_cache_db_ready()) {
581 $api_key_data = drflex_cache_check_latest_resource_by_uri('generatedEmbedScript');
582
583 if (!empty($api_key_data) && get_option('drflex_api_key', null) != null) {
584 $indicator = str_replace('<<status_color>>', $GLOBALS['drflex_colors_primary_green'], $indicator_gen);
585 $indicator = str_replace('<<status_text>>', __('API key valid', 'dr-flex'), $indicator);
586 return $indicator;
587 } else {
588 return invalid($indicator_gen);
589 }
590 } else {
591 return incomplete($indicator_gen);
592 }
593 }
594
595 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
596
597 /**
598 * Helper function to fetch a resource form a url and insert it into the database cache.
599 *
600 * @param string $resource_uri uri of the resource to fetch
601 */
602 function drflex_fetch_and_insert_latest_resource_version($resource_uri)
603 {
604
605 $response = drflex_utils_fetch_from_url($resource_uri, true);
606
607 if ($response != false && count($response) > 1) {
608 $content = $response['content'];
609 $contentType = $response['content-type'];
610 $xContentEncoding = $response['x-content-encoding'];
611 drflex_debug("X-Content-Encoding: " . $xContentEncoding);
612
613 drflex_cache_insert_or_update_resource($resource_uri, $content, $contentType, $xContentEncoding, true);
614 } else {
615 drflex_error("CURL fehler.");
616 }
617 }
618
619 ////////////////////////////////////////////////////////////////////////////////////////////////////////
620
621 /**
622 * Main function that is being excecuted on every pageload. This function checks if the resources
623 * that are listed in the config json file, that was fetched from the Dr. Flex service, are
624 * already cached in the database and if not it fetches and inserts them. On every load the hash
625 * values of the files are checked and if they have changed the resource will be updated. There is
626 * a delay which is defined in components/constants.php that will be applied to the update process
627 * in order to make the operation less resource-intensive.
628 *
629 */
630 function drflex_update_resources()
631 {
632 if (drflex_plugin_database_needs_update()) {
633 drflex_debug("Database needs update. Updating...");
634 if (drflex_cache_upgrade()) {
635 drflex_debug("Update successful.");
636 } else {
637 drflex_error("Error ocurred updating database");
638 }
639 }
640
641 function update()
642 {
643 // drflex_debug("Update Resources.");
644
645 function has_hash($im_cache, $hash)
646 {
647 foreach ($im_cache as $item) {
648 if ($hash === $item['resource_hash_md5']) {
649 return true;
650 }
651 }
652
653 return false;
654 }
655
656 function get_data($im_cache, $uri)
657 {
658 foreach ($im_cache as $item) {
659 if ($uri === $item['resource_uri']) {
660 return $item['resource_data'];
661 }
662 }
663
664 return array();
665 }
666
667 function clean_up_deprecated($im_cache, $config_files)
668 {
669 $items_to_remove = array();
670 foreach ($im_cache as $cached_item) {
671 if (
672 $cached_item['resource_uri'] !== "generatedEmbedScript" &&
673 $cached_item['resource_uri'] !== "buttonConfigurations" &&
674 $cached_item['permanent'] != true
675 ) {
676 $items_to_remove[] = $cached_item;
677 $position = count($items_to_remove) - 1;
678 foreach ($config_files as $config_item) {
679 if ($cached_item['resource_uri'] === $config_item['drflex_url']) {
680 array_splice($items_to_remove, $position, 1);
681 }
682 }
683 }
684 }
685
686 $delete_ids = array_map(function ($a) {
687 return $a['id'];
688 }, $items_to_remove);
689
690 drflex_cache_delete_resources($delete_ids);
691 }
692
693 $cache = drflex_cache_get_cache();
694 $im_cache = array();
695
696 foreach ($cache as $item) {
697 $cachable_item = get_object_vars($item);
698 $im_cache[] = $cachable_item;
699 }
700
701 $drflex_config_file_url = $GLOBALS['drflex_host'] . $GLOBALS['drflex_cofig_relpath'];
702
703 $response = drflex_utils_fetch_from_url($drflex_config_file_url);
704
705 if ($response != false && count($response) > 1 && $response['status'] == 200) {
706 $configObject = json_decode($response['content']);
707 $config = get_object_vars($configObject);
708
709 // Fetch embed script
710 $embed_script_data = $config['generated_embed_script'];
711 $es_vars = get_object_vars($embed_script_data);
712
713 if (!has_hash($im_cache, $es_vars['md5_hash'])) {
714 if (!drflex_cache_insert_or_update_resource('generatedEmbedScript', drflex_utils_json_unescape($es_vars['data']), null, null)) {
715 drflex_error("An error occurred while writing the generated embed script to the database.");
716 }
717 }
718
719 $config_files = array();
720
721 // Fetch files
722 foreach ($config['files'] as $fileObject) {
723 $file = get_object_vars($fileObject);
724 $config_files[] = $file;
725 $resource_uri = $file['drflex_url'];
726
727 if (!has_hash($im_cache, $file['md5_hash'])) {
728 // debug( "Resource does not exist or is deprecated in mysql db." );
729 if ($file['md5_hash'] !== null) {
730 drflex_fetch_and_insert_latest_resource_version($resource_uri);
731 } else {
732 drflex_cache_insert_or_update_resource($resource_uri, null, null, null, true);
733 }
734 } // else {
735 // debug("Latest resource version already exists in mysql db.");
736 // Do nothing
737 // debug("f cache: $resource_uri");
738 // }
739 ;
740 }
741
742 // DB cleanup
743 clean_up_deprecated($im_cache, $config_files);
744
745 // Fetch configs
746 if (array_key_exists('button_configurations', $config)) {
747 $btn_cnf = json_encode($config['button_configurations']);
748 drflex_cache_insert_or_update_resource('buttonConfigurations', $btn_cnf, null, null);
749 } else {
750 drflex_error("Button configuration missing in config json.");
751 }
752
753 // Update fetch timestamp
754 drflex_cache_insert_config_item("last_update_timestamp", null);
755
756 } else {
757 if ($response['status'] === 401){
758 drflex_cache_clear_cache();
759 drflex_error($response['content']);
760 } else {
761 drflex_error("Error trying to fetch config.json.");
762 }
763 }
764 }
765
766 $last_update = drflex_cache_get_config_item("last_update_timestamp");
767
768 if (count($last_update) > 0) {
769 $last_update = get_object_vars($last_update[0]);
770
771 if (array_key_exists("created_at", $last_update)) {
772
773 $created_date_time = date_create_from_format("Y-m-d H:i:s", $last_update["created_at"]);
774 $last_timestamp = $created_date_time->getTimestamp();
775
776 $drflex_update_interval_secs = $GLOBALS['drflex_update_interval_secs'];
777
778 if (time() - $drflex_update_interval_secs > $last_timestamp) {
779 update();
780 } // else {
781 // debug("Wait");
782 //}
783 } else {
784 update();
785 }
786 } else {
787 update();
788 }
789 }
790
791 add_action('wp', 'drflex_update_resources');
792
793 ////////////////////////////////////////////////////////////////////////////////////////////////////////
794
795 /**
796 * Function to replace Dr. Flex Menu items with the toggle logic.
797 *
798 * @param string $items Menu items from wordpress navigation fuction
799 * @return string the modified items sting with the proper toggle command
800 */
801 function drflex_replace_dr_flex_placeholer_menu_item($items) {
802
803 $replacement = $GLOBALS['drflex_toggle_href'];
804
805 $items = str_replace('https://toggleDrFlexAppointments()', $replacement, $items);
806 $items = str_replace('http://toggleDrFlexAppointments()', $replacement, $items);
807 $items = str_replace('https://javascript:toggleDrFlexAppointments()', $replacement, $items);
808 $items = str_replace('http://javascript:toggleDrFlexAppointments()', $replacement, $items);
809
810 return $items;
811 }
812
813 add_filter('wp_nav_menu_items', 'drflex_replace_dr_flex_placeholer_menu_item');