PluginProbe
avalex – Automatisch sichere Rechtstexte / trunk
avalex – Automatisch sichere Rechtstexte vtrunk
trunk 1.5.6 1.5.7 1.5.8 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 3.1.4
avalex / avalex.php

avalex.php in avalex – Automatisch sichere Rechtstexte trunk, at avalex.php

819 lines 25.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: avalex - Automatisch sichere Rechtstexte
4 Description: Ermöglicht die Einbindung der automatisch aktuellen Rechtstexte von avalex. Einen API Key erhalten Sie auf www.avalex.de.
5 Author: avalex GmbH
6 Author URI: https://avalex.de/
7 Version: 3.1.4
8 Text Domain: Avalex
9 Domain Path: /languages
10 */
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit;
14 } // Exit if accessed directly
15
16 class Avalex
17 {
18 const PLUGIN_VERSION = '3.1.4'; //TODO update corresponding version digit on each code update
19 protected $pluginPath = '';
20 protected $tableName = '';
21 protected $wp_version = '';
22 protected $apiKey = '';
23 protected $isKeyValid = false;
24 protected $isDomainValid = false;
25 protected $response = false;
26 protected $recursiveCalls = 0;
27 protected $notice = false;
28 protected $cachePath = '';
29 protected $dseHtml = '';
30 protected $noticeType = '';
31 protected $noticeMessage = '';
32 protected $apiUrl = 'https://avalex.de';
33 protected $fallbackApiUrl = 'https://proxy.avalex.de';
34 protected $types = [
35 'dse' => '/avx-datenschutzerklaerung',
36 'imprint' => '/avx-impressum',
37 'agb' => '/avx-bedingungen',
38 'widerruf' => '/avx-widerruf',
39 ];
40
41 protected $shortcodes = [
42 'datenschutz' => 'dse',
43 'impressum' => 'imprint',
44 'agb' => 'agb',
45 'widerrufsbelehrung' => 'widerruf',
46 // 'avalex' => 'dse', //deprecated as of 3.0.0
47 ];
48
49 protected $endpointsShortcodes = [
50 'datenschutzerklaerung' => 'datenschutz',
51 'impressum' => 'impressum',
52 'bedingungen' => 'agb',
53 'widerruf' => 'widerrufsbelehrung',
54 ];
55
56 protected $shortcodesLegaltexts = [];
57
58 public function __construct()
59 {
60 // Call the functions that handle the stuff we need to do on plugin activation.
61 register_activation_hook( __FILE__, array( $this, 'activatePlugin' ) );
62
63 // And call the functions, when the user deactivates the plugin.
64 register_deactivation_hook( __FILE__, array( $this, 'deactivatePlugin' ) );
65
66 // We also want to load the language files (To make WordPress think it is translated).
67 $this->loadLanguageFiles();
68
69 // Set our variables.
70 global $wpdb;
71 global $wp_version;
72 $this->pluginPath = dirname( __FILE__ );
73 $this->tableName = $wpdb->prefix . 'avalex';
74 $this->wp_version = $wp_version;
75 $this->apiKey = esc_attr( get_option( 'avalex_api_key', false ) );
76 $this->isKeyValid = get_option( 'avalex_valid_api_key', false );
77 $this->isDomainValid = false;
78 $this->response = false;
79 $this->recursiveCalls = 0;
80 $this->notice = false;
81 $this->cachePath = WP_CONTENT_DIR . '/cache';
82 $this->avalexCronAction();
83 $this->maybeUpdateDatabase();
84
85 // Register a new cron schedule.
86 add_filter( 'cron_schedules', array( $this, 'addQuarterlyCronSchedule' ) );
87
88 // We also want to check if our cronjob is still active, because it is crucial for the functionality of this plugin.
89 $this->registerCronJob();
90
91 // Call our methods that we need as early as possible.
92 add_action( 'admin_init', array( $this, 'init' ) );
93
94 // Add our admin menu page.
95 add_action( 'admin_menu', array( $this, 'addAdminMenu' ) );
96
97 // Add update functionality.
98 add_action( 'pre_set_site_transient_update_plugins', array( $this, 'pluginUpdateNotification' ) );
99
100 // We need an action to make it possible to force a DSE update from outside for important updates that can't wait.
101 add_action( 'init', array( $this, 'forceUpdate' ) );
102
103 // Add settings link to plugin page.
104 add_action( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'addSettingsLink' ) );
105
106 // Add fallback for old shortcode which was deprecated as of 3.0.0, added with 3.0.1
107 add_shortcode( 'avalex', array( $this, 'renderAvalexShortcodeFallback' ) );
108
109 // Replace shortcodes with their corresponding avalex legal texts from DB.
110 global $wpdb;
111 if( $this->wp_version < 6.2 ) {
112 $typeRows = $wpdb->get_results( "SELECT type FROM $this->tableName" );
113 } else {
114 $typeRows = $wpdb->get_results( $wpdb->prepare( "SELECT type FROM %i", $this->tableName ) );
115 }
116
117 foreach ( $typeRows as $typeRow ) {
118 $typeParts = explode( '_', $typeRow->type );
119 $shortcode = array_search( $typeParts[0], $this->shortcodes );
120 if ( $shortcode ) {
121 $shortcode = 'avalex_' . ( count( $typeParts ) > 1 ? "{$typeParts[1]}_" : 'de_' ) . $shortcode;
122 add_shortcode( $shortcode, array( $this, 'renderAvalexShortcode' ) );
123 }
124 }
125 }
126
127 public function activatePlugin()
128 {
129 $this->createTable();
130 $this->maybeDeleteOldCronJob();
131 $this->registerCronJob();
132 }
133
134 public function checkPhpVersion()
135 {
136 if ( version_compare( PHP_VERSION, '7.0.0', '>' ) ) {
137 return;
138 }
139
140 wp_die( 'PHP Version zu alt. Bitte nutzen Sie mindestens PHP 7.0.<br>Sie nutzen aktuell Version: ' . PHP_VERSION );
141 }
142
143 public function createTable()
144 {
145 global $wpdb;
146 $charsetCollate = $wpdb->get_charset_collate();
147
148 // First we want to drop any old tables of avalex, if there are some.
149 $this->deleteAvalexTable();
150
151 // Now create our new table.
152 $sql = "CREATE TABLE $this->tableName (
153 id mediumint(9) NOT NULL AUTO_INCREMENT,
154 time datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
155 type text NOT NULL,
156 data longtext NOT NULL,
157 PRIMARY KEY (id)
158 ) $charsetCollate;";
159
160 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
161 maybe_create_table( $this->tableName, $sql );
162 }
163
164 public function maybeUpdateDatabase()
165 {
166 global $wpdb;
167 $charsetCollate = $wpdb->get_charset_collate();
168
169 // Now create our new table.
170 $sql = "CREATE TABLE $this->tableName (
171 id mediumint(9) NOT NULL AUTO_INCREMENT,
172 time datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
173 data longtext NOT NULL,
174 type text NOT NULL,
175 PRIMARY KEY (id)
176 ) $charsetCollate;";
177
178 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
179 maybe_create_table( $this->tableName, $sql );
180 }
181
182 public function maybeDeleteOldCronJob()
183 {
184 if ( wp_next_scheduled( 'avalex_cron_event' ) ) {
185 wp_clear_scheduled_hook( 'avalex_cron_event' );
186 }
187
188 if ( wp_next_scheduled( 'avalex_update_dse_cron_event' ) ) {
189 wp_clear_scheduled_hook( 'avalex_update_dse_cron_event' );
190 }
191 }
192
193 public function registerCronJob()
194 {
195 if ( ! wp_next_scheduled( 'avalex_update_dse_cron_event' ) ) {
196 wp_schedule_event( time(), 'avalex_interval', 'avalex_update_dse_cron_event' );
197 }
198 }
199
200 public function deactivatePlugin()
201 {
202 $this->maybeDeleteOldCronJob();
203 }
204
205 public function deleteAvalexTable()
206 {
207 global $wpdb;
208
209 if( $this->wp_version < 6.2 ) {
210 $wpdb->query( "DROP TABLE IF EXISTS $this->tableName" );
211 } else {
212 $wpdb->query( $wpdb->prepare( "DROP TABLE IF EXISTS %i", $this->tableName ) );
213 }
214 }
215
216 public function deleteOptions()
217 {
218 delete_option( 'avalex_api_key' );
219 delete_option( 'avalex_valid_api_key' );
220 }
221
222 public function avalexCronAction()
223 {
224 add_action( 'avalex_update_dse_cron_event', array( $this, 'fetchAvalexTexts' ) );
225 }
226
227 public function addQuarterlyCronSchedule( $schedules )
228 {
229 $schedules['avalex_interval'] = array(
230 'interval' => 21600,
231 'display' => __( '4 times a day' )
232 );
233 return $schedules;
234 }
235
236 public function loadLanguageFiles()
237 {
238 load_plugin_textdomain( 'Avalex', false, basename( dirname( __FILE__ ) ) . '/languages/' );
239 }
240
241 public function init()
242 {
243 // If the user hits the submit button, we want to store the new apikey.
244 if ( ! isset( $_POST['save_avalex'] ) ) {
245 return;
246 }
247
248 if ( ! $this->saveApiKey() ) {
249 return;
250 }
251
252 if ( ! $this->validateApiKey() ) {
253 return;
254 }
255
256 $this->fetchAvalexTexts();
257 }
258
259 public function addAdminMenu()
260 {
261 add_options_page( 'avalex', 'avalex', 'manage_options', 'avalex', array( $this, 'avalexAdminPage' ) );
262 }
263
264 public function avalexAdminPage()
265 {
266 include $this->pluginPath . '/templates/admin_page.php';
267 }
268
269 public function addNotice()
270 {
271 if ( ! $this->notice ) {
272 return false;
273 }
274
275 echo '<div class="notice notice-' . esc_attr( $this->noticeType ) . '"><p>' . esc_html( $this->noticeMessage ) . '</p></div>';
276 return true;
277 }
278
279 private function saveApiKey()
280 {
281 // check permissions
282 if ( ! current_user_can( 'manage_options' ) ) {
283 return false;
284 }
285
286 // verify nonce
287 check_admin_referer( 'save_avalex' );
288
289 // Check if api key was entered.
290 $apiKey = sanitize_text_field( $_POST['avalex_api_key'] );
291 update_option( 'avalex_api_key', $apiKey );
292
293 if ( ! $apiKey ) {
294 $this->notice = true;
295 $this->noticeType = 'error';
296 $this->noticeMessage = __( 'Please enter an API key.', 'Avalex' );
297 return false;
298 }
299
300 if ( $apiKey ) {
301 $this->apiKey = $apiKey;
302 return true;
303 }
304 }
305
306 private function showApiKey()
307 {
308 if ( $this->apiKey ) {
309 echo esc_attr( $this->apiKey );
310 return;
311 }
312
313 return false;
314 }
315
316 private function validateApiKey()
317 {
318
319 // Build the api url.
320 $apiUrlDomain = $this->apiUrl . '/avx-datenschutzerklaerung';
321 if ( $this->recursiveCalls == 1 ) {
322 // $apiUrlDomain = $this->fallbackApiUrl . 'avx-datenschutzerklaerung';
323 }
324
325 $serverDomain = $this->trimDomain( home_url() );
326
327 $apiUrlDomain = add_query_arg( 'apikey', $this->apiKey, $apiUrlDomain );
328 $apiUrlDomain = add_query_arg( 'domain', $serverDomain, $apiUrlDomain );
329
330 // Call the api.
331 $response = wp_remote_get( $apiUrlDomain );
332 $responseCode = wp_remote_retrieve_response_code( $response );
333
334 // If we have a 401, the key is not valid.
335 if ( $responseCode == 401 ) {
336 $this->notice = true;
337 $this->noticeType = 'error';
338 $this->noticeMessage = 'Der API-Key ist ungültig.';
339 $this->isKeyValid = false;
340 update_option( 'avalex_valid_api_key', false );
341 return false;
342 }
343
344 // 200 means api key is valid, so we can grab the domain and proceed.
345 if ( $responseCode == 200 ) {
346 update_option( 'avalex_valid_api_key', true );
347 $this->isKeyValid = 1;
348 $this->response = json_decode( wp_remote_retrieve_body( $response ), true );
349 $this->recursiveCalls = 0;
350 return true;
351 }
352
353 if ( is_wp_error( $response ) ) {
354 // When this is the first time the error happens, we want to try the fallback url.
355 if ( $this->recursiveCalls == 0 ) {
356 $this->recursiveCalls = 1;
357 return $this->validateApiKey();
358 }
359
360 $errorMessage = $response->get_error_message();
361 $this->notice = true;
362 $this->noticeType = 'error';
363 $this->noticeMessage = 'Beim Datenabgleich mit dem Avalex Server ist etwas schiefgelaufen. Bitte wenden Sie sich an den Support mit den folgenden Informationen:<br>' . $errorMessage;
364 return false;
365 }
366
367 if ( $responseCode == 400 ) {
368 // Website not configured.
369 $this->notice = true;
370 $this->noticeType = 'error';
371 $this->noticeMessage = 'Webseite noch nicht fertig konfiguriert oder die hinterlegte Domain stimmt nicht mit ihrem Server überein.';
372 $this->isKeyValid = false;
373 update_option( 'avalex_valid_api_key', false );
374 return false;
375 }
376
377
378 update_option( 'avalex_valid_api_key', false );
379 return false;
380 }
381
382 public function trimDomain( $domain )
383 {
384 // Clean domain
385 $domain = preg_replace( '/^https?:\/\/(www\.)?([^\/]+).*/', '$2', $domain );
386 return $domain;
387 }
388
389 public function fetchAvalexTexts()
390 {
391 // Get languages used on the current domain.
392 $apiUrl = $this->apiUrl . '/avx-get-domain-langs';
393 $serverDomain = $this->trimDomain( home_url() );
394 $apiUrl = add_query_arg( 'apikey', $this->apiKey, $apiUrl );
395 $apiUrl = add_query_arg( 'domain', $serverDomain, $apiUrl );
396 $apiUrl = add_query_arg( 'version', Avalex::PLUGIN_VERSION, $apiUrl );
397 $response = wp_remote_get( $apiUrl );
398 $responseCode = wp_remote_retrieve_response_code( $response );
399 $addedTexts = [];
400
401 if ( $responseCode == 401 ) {
402 // API Key not authorized, shouldn't happen at this point, but you never know.
403 return;
404 }
405
406 // We got something back, let's see if the body has some data.
407 $langs = wp_remote_retrieve_body( $response );
408
409 // If the data is empty (no langs have been entered on the avalex side), we only retrieve the default German legal texts types.
410 if ( empty( $langs ) ) {
411 // Loop trough every type and save everything in its own row.
412 foreach ( $this->types as $type => $endpoint ) {
413 $this->fetchAvalexDse( $endpoint, $type, 'de' );
414 }
415 } // The customer has entered the set of languages used on their domain, we loop through them and retrieve each one's corresponding legal text.
416 else {
417 $langs = json_decode( $langs, true );
418 foreach ( $langs as $langCode => $langTexts ) {
419 foreach ($langTexts as $endpoint => $legaltextUrl) {
420 $type = array_search ("/avx-$endpoint", $this->types) . ($langCode !== 'de' ? "_$langCode" : '');
421 if($this->fetchAvalexDse("/avx-$endpoint", $type, $langCode)) {
422 $addedTexts[] = $type;
423 $this->shortcodesLegaltexts[] = "avalex_{$langCode}_{$this->endpointsShortcodes[$endpoint]}";
424 }
425 }
426 }
427 }
428
429 // clear not existing languages
430 global $wpdb;
431 if( $this->wp_version < 6.2 ) {
432 $currentDb = $wpdb->get_results( "SELECT id, type FROM $this->tableName" );
433 } else {
434 $currentDb = $wpdb->get_results( $wpdb->prepare( "SELECT id, type FROM %i", $this->tableName ) );
435 }
436
437 if ( $addedTexts && $currentDb ) {
438 foreach ( $currentDb as $entry ) {
439 if ( ! in_array( $entry->type, $addedTexts ) ) {
440 if( $this->wp_version < 6.2 ) {
441 $wpdb->query( $wpdb->prepare( "DELETE FROM $this->tableName WHERE id = %d", $entry->id ) );
442 } else {
443 $wpdb->query( $wpdb->prepare( "DELETE FROM %i WHERE id = %d", $this->tableName, $entry->id ) );
444 }
445 }
446 }
447 }
448
449 }
450
451 public function fetchAvalexDse( $endpoint, $type, $langCode = null )
452 {
453 $apiUrl = $this->apiUrl . $endpoint;
454
455 if ( $this->recursiveCalls == 1 ) {
456 $apiUrl = $this->fallbackApiUrl . $endpoint;
457 }
458
459 $serverDomain = $this->trimDomain( home_url() );
460
461 $apiUrl = add_query_arg( 'apikey', $this->apiKey, $apiUrl );
462 $apiUrl = add_query_arg( 'domain', $serverDomain, $apiUrl );
463
464 if ( $langCode ) {
465 $apiUrl = add_query_arg( 'lang', $langCode, $apiUrl );
466 }
467
468 $args = [
469 'timeout' => 10, //Set connection timeout to 10 seconds.
470 ];
471
472 $response = wp_remote_get( $apiUrl, $args );
473 $responseCode = wp_remote_retrieve_response_code( $response );
474
475 if ( $responseCode == 401 ) {
476 // API Key not authorized, shouldn't happen at this point, but you never know.
477 return;
478 }
479
480 if ( $responseCode == 200 ) {
481 // We got something back, let's see if the body has some data.
482 $data = wp_remote_retrieve_body( $response );
483
484 // If the data is empty, we do nothing to avoid overwriting the DSE with empty content.
485 if ( empty( $data ) ) {
486 return false;
487 }
488
489 // Alright, we should be safe to actually save the dse in the database. But to be sure, we sanitize the data.
490 $sanitizedData = sanitize_post_field('post_content', trim($data), false, 'display');
491 $trimmedData = preg_replace("/\r|\n/", '', $sanitizedData);
492 $this->dseHtml = $trimmedData;
493 $this->writeDseIntoDatabase($type);
494 $this->recursiveCalls = 0;
495
496 // Set the data for the successfull update notice.
497 $this->notice = true;
498 $this->noticeType = 'success';
499 $this->noticeMessage = 'Der API Key und die avalex Rechtstexte wurden aktualisiert.';
500
501 // Now we delete the whole cache of WordPress to make sure the update actually shows.
502 $this->emptyCache();
503
504 return true;
505 }
506
507 if ( is_wp_error( $response ) ) {
508 if ( $this->recursiveCalls == 0 ) {
509 $this->recursiveCalls = 1;
510 return $this->fetchAvalexDse( $endpoint, $type, $langCode );
511 }
512
513 $errorMessage = $response->get_error_message();
514 $this->notice = true;
515 $this->noticeType = 'error';
516 $this->noticeMessage = 'Beim Datenabgleich mit dem Avalex Server ist etwas schiefgelaufen. Bitte wenden Sie sich an den Support mit den folgenden Informationen:<br>' . $errorMessage;
517 return false;
518 }
519 }
520
521 public function writeDseIntoDatabase( $type )
522 {
523 if ( ! $this->dseHtml ) {
524 return;
525 }
526
527 // Write our new data into the database. And delete the old row beforehand.
528 global $wpdb;
529 if( $this->wp_version < 6.2 ) {
530 $wpdb->query( $wpdb->prepare( "DELETE FROM $this->tableName WHERE type = %s", $type ) );
531 } else {
532 $wpdb->query( $wpdb->prepare( "DELETE FROM %i WHERE type = %s", $this->tableName, $type ) );
533 }
534
535 $wpdb->insert(
536 $this->tableName, array(
537 'time' => current_time( 'mysql' ),
538 'data' => $this->dseHtml,
539 'type' => $type,
540 ), array(
541 '%s',
542 '%s',
543 '%s',
544 )
545 );
546 }
547
548 public function getDseFromDatabase( $type )
549 {
550 // Write our new data into the database.
551 global $wpdb;
552 if( $this->wp_version < 6.2 ) {
553 $dseRow = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $this->tableName WHERE type = %s ORDER BY time DESC LIMIT 1", $type ) );
554 } else {
555 $dseRow = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM %i WHERE type = %s ORDER BY time DESC LIMIT 1", $this->tableName, $type ) );
556 }
557
558 if ( ! $dseRow ) {
559 return;
560 }
561
562 return $dseRow[0]->data;
563 }
564
565 // Retrieve existing types of legal texts other than German.
566 public function getOtherLangsLegaltextsFromDatabase()
567 {
568 global $wpdb;
569 if( $this->wp_version < 6.2 ) {
570 $typeRow = $wpdb->get_results( "SELECT data, type FROM $this->tableName WHERE type LIKE '%\_%'" );
571 } else {
572 $typeRow = $wpdb->get_results( $wpdb->prepare( "SELECT data, type FROM %i WHERE type LIKE '%\_%'", $this->tableName ) );
573 }
574
575 if ( ! $typeRow ) {
576 return [];
577 }
578
579 return $typeRow;
580 }
581
582 public function renderAvalexShortcodeFallback( $atts, $content )
583 {
584 return do_shortcode( '[avalex_de_datenschutz]' );
585 }
586
587 public function renderAvalexShortcode( $atts, $content, $shortcode )
588 {
589 if ( ! $this->isKeyValid ) {
590
591 // Try to revalidate.
592 if ( $this->validateApiKey() ) {
593 $this->renderAvalexShortcode( false, false, $shortcode );
594 }
595
596 return 'Avalex ist noch nicht fertig eingerichtet.';
597 }
598
599 // Add lang code (if relevant) to legal text type while keeping consistency with legacy content from older plugin versions
600 $shortcodeParts = explode( '_', $shortcode );
601 $type = $this->shortcodes[$shortcodeParts[2]];
602 if ( $shortcodeParts[1] != 'de' ) {
603 $type .= '_' . $shortcodeParts[1];
604 }
605
606 // First we check if by whatever reason the dse is empty, if it is, we try to fetch the new data.
607 if ( ! $this->getDseFromDatabase( $type ) || empty( $this->getDseFromDatabase( $type ) ) ) {
608 if ( ! $this->validateApiKey() ) {
609 if ( $this->addNotice() ) {
610 return;
611 }
612 return 'API Key ungültig.';
613 }
614
615 if ( ! $this->fetchAvalexTexts() && $this->recursiveCalls < 2 ) {
616 $this->recursiveCalls ++;
617 $this->renderAvalexShortcode( false, false, $shortcode );
618 return false;
619 }
620 }
621
622 // We have a DSE and we will use it!
623 return $this->getDseFromDatabase( $type );
624 }
625
626 public function getDseTime()
627 {
628 global $wpdb;
629 // first try to get the timestamp of an german version
630 if( $this->wp_version < 6.2 ) {
631 $result = $wpdb->get_row( "SELECT time FROM $this->tableName WHERE type = 'dse' or type = 'imprint' or type = 'agb' or type = 'widerruf'" );
632 } else {
633 $result = $wpdb->get_row( $wpdb->prepare( "SELECT time FROM %i WHERE type = 'dse' or type = 'imprint' or type = 'agb' or type = 'widerruf'", $this->tableName ) );
634 }
635
636 if ( ! $result ) {
637 // no timestamp found? try to get another timestamp
638 if( $this->wp_version < 6.2 ) {
639 $result = $wpdb->get_row( "SELECT time FROM $this->tableName" );
640 } else {
641 $result = $wpdb->get_row( $wpdb->prepare( "SELECT time FROM %i", $this->tableName ) );
642 }
643 }
644
645 if ( ! $result ) {
646 echo 'Noch keine DSE vorhanden.';
647 return false;
648 }
649
650 // We want to show the date in a nice format.
651 $timestamp = esc_attr( $result->time );
652 echo date_i18n( 'd.m.Y H:i', strtotime( $timestamp ) ) . ' Uhr';
653 }
654
655 public function pluginUpdateNotification( $transient )
656 {
657 if ( empty( $transient->checked ) ) {
658 return $transient;
659 }
660
661 $url = $this->apiUrl . '/files/wordpress/package.json';
662
663 if ( $this->recursiveCalls == 1 ) {
664 $url = $this->fallbackApiUrl . '/files/wordpress/package.json';
665 }
666
667 $response = wp_remote_get( $url );
668
669 if ( is_wp_error( $response ) ) {
670 if ( $this->recursiveCalls == 0 ) {
671 $this->recursiveCalls = 1;
672 return $this->pluginUpdateNotification( $transient );
673 }
674
675 $errorMessage = $response->get_error_message();
676 $this->notice = true;
677 $this->noticeType = 'error';
678 $this->noticeMessage = 'Beim Datenabgleich mit dem Avalex Server ist etwas schiefgelaufen. Bitte wenden Sie sich an den Support mit den folgenden Informationen:<br>' . $errorMessage;
679 return false;
680 }
681
682 $body = json_decode( wp_remote_retrieve_body( $response ) );
683 $version = $body->version;
684
685 $pluginData = get_plugin_data( __FILE__, false, false );
686
687 if ( version_compare( $version, $pluginData['Version'], '<=' ) ) {
688 return $transient;
689 }
690
691 if ( $this->recursiveCalls == 0 ) {
692 $updateInfo = array(
693 'plugin' => plugin_basename( __FILE__ ),
694 'slug' => plugin_basename( __FILE__ ),
695 'new_version' => $version,
696 'url' => 'https://avalex.de',
697 'package' => 'https://avalex.de/files/wordpress/avalex_wordpress.zip',
698 );
699 }
700
701 if ( $this->recursiveCalls == 1 ) {
702 $updateInfo = array(
703 'plugin' => plugin_basename( __FILE__ ),
704 'slug' => plugin_basename( __FILE__ ),
705 'new_version' => $version,
706 'url' => 'https://avalex.de',
707 'package' => 'https://proxy.avalex.de/files/wordpress/avalex_wordpress.zip',
708 );
709 }
710
711 $this->recursiveCalls = 0;
712
713 $transient->response[plugin_basename( __FILE__ )] = (object)$updateInfo;
714 return $transient;
715 }
716
717 public function forceUpdate()
718 {
719 if ( ! isset( $_GET['force_dse_update'] ) || $_GET['force_dse_update'] != true ) {
720 return;
721 }
722
723 if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], 'avalex_force_update' ) ) {
724 return;
725 }
726
727 if ( ! current_user_can( 'edit_pages' ) ) {
728 return;
729 }
730
731 $this->fetchAvalexTexts();
732 $this->emptyCache();
733 }
734
735 /**
736 * Clear the cache of compatible plugins to prevent old content on relevant pages
737 *
738 * Inspired by: https://wordpress.org/plugins/clear-cache-for-widgets/
739 *
740 * Last Update: 2023-11-02
741 *
742 * @return void
743 */
744 public function emptyCache()
745 {
746 // if W3 Total Cache is being used, clear the cache
747 if ( function_exists( 'w3tc_pgcache_flush' ) ) {
748 w3tc_pgcache_flush();
749 } // if WP Super Cache is being used, clear the cache
750 elseif ( function_exists( 'wp_cache_clean_cache' ) ) {
751 global $file_prefix, $supercachedir;
752 if ( empty( $supercachedir ) && function_exists( 'get_supercache_dir' ) ) {
753 $supercachedir = get_supercache_dir();
754 }
755 wp_cache_clean_cache( $file_prefix );
756 } elseif ( class_exists( 'WpeCommon' ) ) {
757 // be extra careful, just in case 3rd party changes things on us
758 if ( method_exists( 'WpeCommon', 'purge_memcached' ) ) {
759 WpeCommon::purge_memcached();
760 }
761 if ( method_exists( 'WpeCommon', 'clear_maxcdn_cache' ) ) {
762 WpeCommon::clear_maxcdn_cache();
763 }
764 if ( method_exists( 'WpeCommon', 'purge_varnish_cache' ) ) {
765 WpeCommon::purge_varnish_cache();
766 }
767 } // WP Fastest Cache
768 elseif ( method_exists( 'WpFastestCache', 'deleteCache' ) && ! empty( $wp_fastest_cache ) ) {
769 $wp_fastest_cache->deleteCache( true );
770 } // Kinsta Cache
771 elseif ( class_exists( '\Kinsta\Cache' ) && ! empty( $kinsta_cache ) ) {
772 $kinsta_cache->kinsta_cache_purge->purge_complete_caches();
773 } // GoDaddy Cache
774 elseif ( function_exists( 'ccfm_godaddy_purge' ) ) {
775 ccfm_godaddy_purge();
776 } // WP Optimize
777 elseif ( class_exists( 'WP_Optimize' ) && defined( 'WPO_PLUGIN_MAIN_PATH' ) ) {
778 if ( ! class_exists( 'WP_Optimize_Cache_Commands' ) ) {
779 include_once( WPO_PLUGIN_MAIN_PATH . 'cache/class-cache-commands.php' );
780 }
781
782 if ( class_exists( 'WP_Optimize_Cache_Commands' ) ) {
783 $wpoptimize_cache_commands = new WP_Optimize_Cache_Commands();
784 $wpoptimize_cache_commands->purge_page_cache();
785 }
786 } // Breeze Admin
787 elseif ( class_exists( 'Breeze_Admin' ) ) {
788 do_action( 'breeze_clear_all_cache' );
789 } // LSCWP_V
790 elseif ( defined( 'LSCWP_V' ) ) {
791 do_action( 'litespeed_purge_all' );
792 } // SG CachePress
793 elseif ( function_exists( 'sg_cachepress_purge_cache' ) ) {
794 sg_cachepress_purge_cache();
795 } // Autooptimize
796 elseif ( class_exists( 'autoptimizeCache' ) ) {
797 autoptimizeCache::clearall();
798 } // Cache Enabler
799 elseif ( class_exists( 'Cache_Enabler' ) ) {
800 Cache_Enabler::clear_total_cache();
801 } // WP Rocket
802 elseif ( function_exists( 'rocket_clean_domain' ) ) {
803 rocket_clean_domain();
804 if ( function_exists( 'rocket_clean_minify' ) ) {
805 rocket_clean_minify();
806 }
807 }
808 }
809
810 public function addSettingsLink($links) {
811 $links = array_merge(array(
812 '<a href="' . esc_url(admin_url('/options-general.php?page=avalex')) . '">Einstellungen</a>',
813 ), $links);
814 return $links;
815 }
816 }
817
818 // Call our class.
819 new Avalex();