BlockGoldCoin ist ein modular aufgebautes, audit‑reines Digital‑Ökosystem, das Technologie, Design und Mythos zu einer einheitlichen Plattform verschmilzt. Im Zentrum steht eine klare Vision: digitale Werte, Inhalte und Identitäten in einer strukturierten, transparenten und global zugänglichen Form bereitzustellen.
Die Plattform kombiniert:
Mythos‑Architektur – ein konsistentes, symbolisches Narrativ, das alle Module verbindet
Modulare UI/UX‑Systeme – klar strukturiert, audit‑fähig, global skalierbar
Gold‑Dunkle Markenidentität – ein unverwechselbarer visueller Kern, der Stabilität, Wert und Tiefe kommuniziert
Technische Reinheit – saubere, validierte Konfigurationen, klare Trennung von öffentlichen und privaten Modulen
Globale Lokalisierung – Inhalte, Assets und Beschreibungen in vielen Sprachen, sofort einsatzbereit
Automatisierte Dokumentation – jede Komponente ist nachvollziehbar, versioniert und audit‑bereit
BlockGoldCoin ist nicht nur ein Projekt — es ist ein digitales Artefakt, das sich ständig weiterentwickelt, neue Module integriert und durch klare Rituale, Releases und Validierungen wächst. Es schafft eine kohärente, mythos‑getragene Infrastruktur, die sowohl technisch als auch ästhetisch auf höchstem Niveau operiert.

BlockGoldCoin Finanzschutz- und Governance-Symbol
BlockGoldCoin – Finanzschutz & Governance Icon

[img src=“http://blockgoldcoin.com/wp-content/uploads/2025/02/BGC-Finanzschutz-Governance-transparent-e1766687863588.png“ alt=“BlockGoldCoin Finanzschutz- und Governance-Symbol“]

BlockGoldCoin Finanzschutz- und Governance-Symbol

BlockGoldCoin – Finanzschutz & Governance

Dieses Symbol steht für Sicherheit, Transparenz und die Governance‑Struktur des BlockGoldCoin‑Ökosystems.

BlockGoldCoin Finanzschutz- und Governance-Symbol


<a href="https://www.blockgoldcoin.com" class="bgc-btn">
  Mehr über BlockGoldCoin
</a>
.bgc-btn {
  display: inline-block;
  padding: 0.75rem 1.5rem;
  border-radius: 999px;
  background: linear-gradient(135deg, #d4af37, #8b6f1f);
  color: #fff;
  font-weight: 600;
  text-decoration: none;
  letter-spacing: 0.03em;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.bgc-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.25);
}

[blockgoldcoin_consent]
function blockgoldcoin_consent_shortcode() {

ob_start();
?>

„Jede Entscheidung ist ein Licht. Jede Zustimmung ein Schritt in den Mythos.“

BlockGoldCoin · Einwilligung

prefix . self::TABLE_NAME;
$charset = $wpdb->get_charset_collate();

$sql = „CREATE TABLE IF NOT EXISTS $table (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
created_at datetime NOT NULL,
phone varchar(64) DEFAULT “ NOT NULL,
email varchar(255) DEFAULT “ NOT NULL,
address text,
zip varchar(32) DEFAULT “ NOT NULL,
city varchar(128) DEFAULT “ NOT NULL,
country varchar(128) DEFAULT “ NOT NULL,
PRIMARY KEY (id)
) $charset;“;

require_once ABSPATH . ‚wp-admin/includes/upgrade.php‘;
dbDelta($sql);
}

/* —————- ADMIN-EINSTELLUNGEN —————- */

public function add_settings_page() {
add_options_page(
‚BlockGoldCoin Consent‘,
‚BlockGoldCoin Consent‘,
‚manage_options‘,
‚bgc-consent-settings‘,
[$this, ‚render_settings_page‘]
);
}

public function register_settings() {
register_setting(self::OPTION_GROUP, self::OPTION_NAME, [
‚type‘ => ‚array‘,
’sanitize_callback‘ => [$this, ’sanitize_options‘],
‚default‘ => [
‚headline_de‘ => ‚Einwilligung & AGB‘,
‚headline_en‘ => ‚Consent & Terms‘,
‚headline_tr‘ => ‚Açık Rıza & Genel Şartlar‘,
‚primary_color‘ => ‚#b87333‘,
‚accent_color‘ => ‚#facc15‘,
‚bg_gradient‘ => ‚linear-gradient(135deg, #ffd700, #b87333, #c0c0c0)‘,
’notify_email‘ => get_option(‚admin_email‘),
]
]);

add_settings_section(
‚bgc_consent_main‘,
‚BlockGoldCoin Consent Einstellungen‘,
‚__return_false‘,
‚bgc-consent-settings‘
);

$fields = [
‚headline_de‘ => ‚Überschrift (Deutsch)‘,
‚headline_en‘ => ‚Überschrift (Englisch)‘,
‚headline_tr‘ => ‚Überschrift (Türkisch)‘,
‚primary_color‘ => ‚Primärfarbe (z.B. #b87333)‘,
‚accent_color‘ => ‚Akzentfarbe/Gold (z.B. #facc15)‘,
‚bg_gradient‘ => ‚Hintergrund-Gradient (CSS)‘,
’notify_email‘ => ‚E-Mail für Benachrichtigungen‘,
];

foreach ($fields as $key => $label) {
add_settings_field(
$key,
$label,
[$this, ‚render_settings_field‘],
‚bgc-consent-settings‘,
‚bgc_consent_main‘,
[‚key‘ => $key]
);
}
}

public function sanitize_options($input) {
$out = [];
$out[‚headline_de‘] = sanitize_text_field($input[‚headline_de‘] ?? “);
$out[‚headline_en‘] = sanitize_text_field($input[‚headline_en‘] ?? “);
$out[‚headline_tr‘] = sanitize_text_field($input[‚headline_tr‘] ?? “);
$out[‚primary_color‘] = sanitize_hex_color($input[‚primary_color‘] ?? ‚#b87333‘);
$out[‚accent_color‘] = sanitize_hex_color($input[‚accent_color‘] ?? ‚#facc15‘);
$out[‚bg_gradient‘] = wp_kses_post($input[‚bg_gradient‘] ?? ‚linear-gradient(135deg, #ffd700, #b87333, #c0c0c0)‘);
$out[’notify_email‘] = sanitize_email($input[’notify_email‘] ?? get_option(‚admin_email‘));
return $out;
}

public function render_settings_field($args) {
$key = $args[‚key‘];
$options = get_option(self::OPTION_NAME);
$value = esc_attr($options[$key] ?? “);
echo ‚‚;
}

public function render_settings_page() {
?>

BlockGoldCoin Consent


prefix . self::TABLE_NAME;

$wpdb->insert($table, [
‚created_at‘ => current_time(‚mysql‘),
‚phone‘ => $phone,
‚email‘ => $email,
‚address‘ => $address,
‚zip‘ => $zip,
‚city‘ => $city,
‚country‘ => $country,
]);

$options = get_option(self::OPTION_NAME);
$notify_email = $options[’notify_email‘] ?? get_option(‚admin_email‘);

$subject = ‚Neue BlockGoldCoin Einwilligung‘;
$message = „Neue Einwilligung:\n\n“.
„Telefon: $phone\n“.
„E-Mail: $email\n“.
„Adresse: $address\n“.
„PLZ: $zip\n“.
„Stadt: $city\n“.
„Land: $country\n“.
„Zeit: „.current_time(‚mysql‘).“\n“;

wp_mail($notify_email, $subject, $message);

// Optional: Danke-Flag in Session oder Redirect mit Param
wp_safe_redirect(add_query_arg(‚bgc_consent‘, ‚ok‘, wp_get_referer() ?: home_url()));
exit;
}

/* —————- SHORTCODE + HTML-OUTPUT —————- */

public function shortcode($atts = []) {
$options = get_option(self::OPTION_NAME);
$bg = $options[‚bg_gradient‘] ?? ‚linear-gradient(135deg, #ffd700, #b87333, #c0c0c0)‘;
$primary = $options[‚primary_color‘] ?? ‚#b87333‘;
$accent = $options[‚accent_color‘] ?? ‚#facc15‘;

$lang = isset($_GET[‚lang‘]) ? sanitize_text_field($_GET[‚lang‘]) : ‚de‘;

$headline = $options[‚headline_de‘] ?? ‚Einwilligung & AGB‘;
if ($lang === ‚en‘) $headline = $options[‚headline_en‘] ?? ‚Consent & Terms‘;
if ($lang === ‚tr‘) $headline = $options[‚headline_tr‘] ?? ‚Açık Rıza & Genel Şartlar‘;

ob_start();
?>










2,
‚render_callback‘ => [$this, ’shortcode‘],
‚attributes‘ => [],
‚editor_script‘ => ‚bgc-consent-block-editor‘,
]);

add_action(‚enqueue_block_editor_assets‘, function() {
$handle = ‚bgc-consent-block-editor‘;
wp_register_script($handle, “, [], false, true);
wp_enqueue_script($handle);
$inline = „wp.blocks.registerBlockType(‚blockgoldcoin/consent‘,{
title: ‚BlockGoldCoin Consent‘,
icon: ’shield‘,
category: ‚widgets‘,
edit: function(){ return wp.element.createElement(‚p‘,{},’BlockGoldCoin Consent Formular (Frontend anzeigen, um zu sehen).‘); },
save: function(){ return null; }
});“;
wp_add_inline_script($handle, $inline);
});
}

}

new BlockGoldCoin_Consent();

[blockgoldcoin_consent]

/* —————- BACKEND: EXPORT-ANSICHT + CSV —————- */

add_action(‚admin_menu‘, function() {
add_menu_page(
‚BlockGoldCoin Einwilligungen‘,
‚Einwilligungen‘,
‚manage_options‘,
‚bgc-consent-export‘,
‚bgc_render_export_page‘,
‚dashicons-database-export‘,
26
);
});

function bgc_render_export_page() {
global $wpdb;
$table = $wpdb->prefix . ‚bgc_consent‘;

// CSV-Export Trigger
if (isset($_GET[‚export‘]) && $_GET[‚export‘] === ‚csv‘) {
bgc_export_csv();
exit;
}

// Daten abrufen
$rows = $wpdb->get_results(„SELECT * FROM $table ORDER BY created_at DESC“);
?>

BlockGoldCoin – Einwilligungen

ID Datum Telefon E-Mail Adresse PLZ Stadt Land

id); ?> created_at); ?> phone); ?> email); ?> address); ?> zip); ?> city); ?> country); ?>


Keine Einträge vorhanden.


prefix . ‚bgc_consent‘;

$rows = $wpdb->get_results(„SELECT * FROM $table ORDER BY created_at DESC“, ARRAY_A);

header(‚Content-Type: text/csv; charset=utf-8‘);
header(‚Content-Disposition: attachment; filename=blockgoldcoin_einwilligungen.csv‘);

$output = fopen(‚php://output‘, ‚w‘);

// Kopfzeile
fputcsv($output, [
‚ID‘, ‚Datum‘, ‚Telefon‘, ‚E-Mail‘, ‚Adresse‘, ‚PLZ‘, ‚Stadt‘, ‚Land‘
]);

// Daten
foreach ($rows as $row) {
fputcsv($output, [
$row[‚id‘],
$row[‚created_at‘],
$row[‚phone‘],
$row[‚email‘],
$row[‚address‘],
$row[‚zip‘],
$row[‚city‘],
$row[‚country‘]
]);
}

fclose($output);
exit;
}

/* =========================
* ADMIN: EINWILLIGUNGEN – FILTER + SUCHE + PAGINATION + EXPORT
* ========================= */

add_action(‚admin_menu‘, function() {
add_menu_page(
‚BlockGoldCoin Einwilligungen‘,
‚Einwilligungen‘,
‚manage_options‘,
‚bgc-consent-export‘,
‚bgc_render_export_page‘,
‚dashicons-database-export‘,
26
);
});

function bgc_render_export_page() {
global $wpdb;
$table = $wpdb->prefix . ‚bgc_consent‘;

// Export Trigger
if (isset($_GET[‚export‘])) {
if ($_GET[‚export‘] === ‚csv‘) {
bgc_export_csv();
} elseif ($_GET[‚export‘] === ‚pdf‘) {
bgc_export_pdf();
} elseif ($_GET[‚export‘] === ‚xlsx‘) {
bgc_export_xlsx();
}
exit;
}

// Filter / Suche
$where = ‚WHERE 1=1‘;
$params = [];

$date_from = isset($_GET[‚date_from‘]) ? sanitize_text_field($_GET[‚date_from‘]) : “;
$date_to = isset($_GET[‚date_to‘]) ? sanitize_text_field($_GET[‚date_to‘]) : “;
$country = isset($_GET[‚country‘]) ? sanitize_text_field($_GET[‚country‘]) : “;
$city = isset($_GET[‚city‘]) ? sanitize_text_field($_GET[‚city‘]) : “;
$zip = isset($_GET[‚zip‘]) ? sanitize_text_field($_GET[‚zip‘]) : “;
$search = isset($_GET[’s‘]) ? sanitize_text_field($_GET[’s‘]) : “;

if ($date_from) {
$where .= ‚ AND created_at >= %s‘;
$params[] = $date_from . ‚ 00:00:00‘;
}
if ($date_to) {
$where .= ‚ AND created_at <= %s'; $params[] = $date_to . ' 23:59:59'; } if ($country) { $where .= ' AND country LIKE %s'; $params[] = '%' . $wpdb->esc_like($country) . ‚%‘;
}
if ($city) {
$where .= ‚ AND city LIKE %s‘;
$params[] = ‚%‘ . $wpdb->esc_like($city) . ‚%‘;
}
if ($zip) {
$where .= ‚ AND zip LIKE %s‘;
$params[] = ‚%‘ . $wpdb->esc_like($zip) . ‚%‘;
}
if ($search) {
$where .= “ AND (email LIKE %s OR phone LIKE %s OR address LIKE %s)“;
$like = ‚%‘ . $wpdb->esc_like($search) . ‚%‘;
$params[] = $like;
$params[] = $like;
$params[] = $like;
}

// Pagination
$per_page = 20;
$paged = isset($_GET[‚paged‘]) ? max(1, (int)$_GET[‚paged‘]) : 1;
$offset = ($paged – 1) * $per_page;

$sql_count = „SELECT COUNT(*) FROM $table $where“;
$total = $params ? $wpdb->get_var($wpdb->prepare($sql_count, $params)) : $wpdb->get_var($sql_count);
$pages = max(1, ceil($total / $per_page));

$sql_rows = „SELECT * FROM $table $where ORDER BY created_at DESC LIMIT %d OFFSET %d“;
$params_rows = $params;
$params_rows[] = $per_page;
$params_rows[] = $offset;

$rows = $wpdb->get_results($wpdb->prepare($sql_rows, $params_rows));

$base_url = remove_query_arg([‚paged‘,’export‘]);
?>

BlockGoldCoin – Einwilligungen


Filtern
“ class=“button button-primary“ style=“margin-right:5px;“>CSV exportieren
“ class=“button“>Excel exportieren

Gesamt: Einträge




ID Datum Telefon E-Mail Adresse PLZ Stadt Land
id); ?> created_at); ?> phone); ?> email); ?> address); ?> zip); ?> city); ?> country); ?>
Keine Einträge gefunden.

1): ?>



‚;

$pdf->ImageSVG(‚@‘ . $logo_svg, 10, 10, 20, 20);

// Titel
$pdf->SetFont(‚helvetica‘, ‚B‘, 18);
$pdf->SetTextColor(0, 0, 0);
$pdf->Ln(5);
$pdf->Cell(0, 15, ‚BlockGoldCoin – Einwilligungen‘, 0, 1, ‚C‘);

// Tabelle
$pdf->SetFont(‚helvetica‘, “, 10);

$tbl = ‚

‚;

foreach ($rows as $r) {
$tbl .= ‚

‚;
}

$tbl .= ‚

ID Datum E-Mail Telefon Stadt Land
‚ . $r[‚id‘] . ‚ ‚ . $r[‚created_at‘] . ‚ ‚ . $r[‚email‘] . ‚ ‚ . $r[‚phone‘] . ‚ ‚ . $r[‚city‘] . ‚ ‚ . $r[‚country‘] . ‚

‚;

$pdf->writeHTML($tbl, true, false, false, false, “);

// Ausgabe
$pdf->Output(‚blockgoldcoin_einwilligungen.pdf‘, ‚D‘);
exit;
}

function bgc_export_xlsx() {
global $wpdb;
$table = $wpdb->prefix . ‚bgc_consent‘;

require_once plugin_dir_path(__FILE__) . ‚vendor/autoload.php‘;

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Style\Border;

$rows = $wpdb->get_results(„SELECT * FROM $table ORDER BY created_at DESC“, ARRAY_A);

$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$primary = $options[‚primary_color‘] ?? ‚#b87333‘;
$accent = $options[‚accent_color‘] ?? ‚#facc15‘;

$sheet = new Spreadsheet();
$sheet->getProperties()
->setCreator(„BlockGoldCoin“)
->setTitle(„Einwilligungen“);

$ws = $sheet->getActiveSheet();
$ws->setTitle(„Einwilligungen“);

// Header
$headers = [‚ID‘,’Datum‘,’E-Mail‘,’Telefon‘,’Adresse‘,’PLZ‘,’Stadt‘,’Land‘];
$col = ‚A‘;

foreach ($headers as $h) {
$ws->setCellValue($col . ‚1‘, $h);
$ws->getStyle($col . ‚1‘)->applyFromArray([
‚font‘ => [‚bold‘ => true, ‚color‘ => [‚rgb‘ => ‚FFFFFF‘]],
‚fill‘ => [‚fillType‘ => Fill::FILL_SOLID, ’startColor‘ => [‚rgb‘ => str_replace(‚#‘,“,$primary)]],
‚borders‘ => [‚bottom‘ => [‚borderStyle‘ => Border::BORDER_MEDIUM]]
]);
$col++;
}

// Daten
$rowIndex = 2;
foreach ($rows as $r) {
$ws->setCellValue(„A$rowIndex“, $r[‚id‘]);
$ws->setCellValue(„B$rowIndex“, $r[‚created_at‘]);
$ws->setCellValue(„C$rowIndex“, $r[‚email‘]);
$ws->setCellValue(„D$rowIndex“, $r[‚phone‘]);
$ws->setCellValue(„E$rowIndex“, $r[‚address‘]);
$ws->setCellValue(„F$rowIndex“, $r[‚zip‘]);
$ws->setCellValue(„G$rowIndex“, $r[‚city‘]);
$ws->setCellValue(„H$rowIndex“, $r[‚country‘]);
$rowIndex++;
}

// Auto-Filter
$ws->setAutoFilter(„A1:H1“);

// Spaltenbreiten
foreach (range(‚A‘,’H‘) as $col) {
$ws->getColumnDimension($col)->setAutoSize(true);
}

// Datei ausgeben
header(‚Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet‘);
header(‚Content-Disposition: attachment; filename=“blockgoldcoin_einwilligungen.xlsx“‚);

$writer = new Xlsx($sheet);
$writer->save(‚php://output‘);
exit;
}

function bgc_export_xlsx() {
global $wpdb;
$table = $wpdb->prefix . ‚bgc_consent‘;

require_once plugin_dir_path(__FILE__) . ‚vendor/autoload.php‘;

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\Legend;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;

$rows = $wpdb->get_results(„SELECT * FROM $table ORDER BY created_at DESC“, ARRAY_A);
$country_stats = $wpdb->get_results(„SELECT country, COUNT(*) as c FROM $table GROUP BY country ORDER BY c DESC“, ARRAY_A);

$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$primary = $options[‚primary_color‘] ?? ‚#b87333‘;

$spreadsheet = new Spreadsheet();
$ws = $spreadsheet->getActiveSheet();
$ws->setTitle(„Einwilligungen“);

// Tabelle Einwilligungen
$headers = [‚ID‘,’Datum‘,’E-Mail‘,’Telefon‘,’Adresse‘,’PLZ‘,’Stadt‘,’Land‘];
$col = ‚A‘;
foreach ($headers as $h) {
$ws->setCellValue($col.’1′, $h);
$ws->getStyle($col.’1′)->applyFromArray([
‚font‘ => [‚bold‘ => true, ‚color‘ => [‚rgb‘ => ‚FFFFFF‘]],
‚fill‘ => [‚fillType‘ => Fill::FILL_SOLID, ’startColor‘ => [‚rgb‘ => str_replace(‚#‘,“,$primary)]],
‚borders‘ => [‚bottom‘ => [‚borderStyle‘ => Border::BORDER_MEDIUM]],
]);
$col++;
}

$rowIndex = 2;
foreach ($rows as $r) {
$ws->setCellValue(„A$rowIndex“, $r[‚id‘]);
$ws->setCellValue(„B$rowIndex“, $r[‚created_at‘]);
$ws->setCellValue(„C$rowIndex“, $r[‚email‘]);
$ws->setCellValue(„D$rowIndex“, $r[‚phone‘]);
$ws->setCellValue(„E$rowIndex“, $r[‚address‘]);
$ws->setCellValue(„F$rowIndex“, $r[‚zip‘]);
$ws->setCellValue(„G$rowIndex“, $r[‚city‘]);
$ws->setCellValue(„H$rowIndex“, $r[‚country‘]);
$rowIndex++;
}

$ws->setAutoFilter(„A1:H1“);
foreach (range(‚A‘,’H‘) as $col) {
$ws->getColumnDimension($col)->setAutoSize(true);
}

// Diagramm-Blatt für Länder
$chartSheet = $spreadsheet->createSheet();
$chartSheet->setTitle(‚Länder-Stats‘);

$chartSheet->setCellValue(‚A1‘, ‚Land‘);
$chartSheet->setCellValue(‚B1‘, ‚Anzahl‘);

$r = 2;
foreach ($country_stats as $cs) {
$chartSheet->setCellValue(„A$r“, $cs[‚country‘]);
$chartSheet->setCellValue(„B$r“, (int)$cs[‚c‘]);
$r++;
}

$dataSeriesLabels = [
new DataSeriesValues(‚String‘, ‚Länder-Stats!$B$1‘, null, 1),
];
$xAxisTickValues = [
new DataSeriesValues(‚String‘, ‚Länder-Stats!$A$2:$A$‘.($r-1), null, $r-2),
];
$dataSeriesValues = [
new DataSeriesValues(‚Number‘, ‚Länder-Stats!$B$2:$B$‘.($r-1), null, $r-2),
];

$series = new DataSeries(
DataSeries::TYPE_PIECHART,
null,
range(0, count($dataSeriesValues)-1),
$dataSeriesLabels,
$xAxisTickValues,
$dataSeriesValues
);
$plotArea = new PlotArea(null, [$series]);
$legend = new Legend(Legend::POSITION_RIGHT, null, false);
$title = new Title(‚Einwilligungen pro Land‘);

$chart = new Chart(
‚country_chart‘,
$title,
$legend,
$plotArea
);
$chart->setTopLeftPosition(‚D2‘);
$chart->setBottomRightPosition(‚L20‘);
$chartSheet->addChart($chart);

// Output
header(‚Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet‘);
header(‚Content-Disposition: attachment; filename=“blockgoldcoin_einwilligungen.xlsx“‚);

$writer = new Xlsx($spreadsheet);
$writer->setIncludeCharts(true);
$writer->save(‚php://output‘);
exit;
}

function bgc_export_zip() {
if (!class_exists(‚ZipArchive‘)) {
wp_die(‚ZipArchive nicht verfügbar.‘);
}

$upload_dir = wp_upload_dir();
$tmp_dir = trailingslashit($upload_dir[‚basedir‘]) . ‚blockgoldcoin_export/‘;
if (!file_exists($tmp_dir)) {
wp_mkdir_p($tmp_dir);
}

$csv_path = $tmp_dir . ‚einwilligungen.csv‘;
$pdf_path = $tmp_dir . ‚einwilligungen.pdf‘;
$xlsx_path = $tmp_dir . ‚einwilligungen.xlsx‘;
$zip_path = $tmp_dir . ‚blockgoldcoin_export_bundle.zip‘;

// 1) CSV intern erzeugen
bgc_generate_csv_file($csv_path);

// 2) PDF intern erzeugen
bgc_generate_pdf_file($pdf_path);

// 3) XLSX intern erzeugen
bgc_generate_xlsx_file($xlsx_path);

// ZIP bauen
$zip = new ZipArchive();
if ($zip->open($zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
$zip->addFile($csv_path, ‚einwilligungen.csv‘);
$zip->addFile($pdf_path, ‚einwilligungen.pdf‘);
$zip->addFile($xlsx_path, ‚einwilligungen.xlsx‘);
$zip->close();
} else {
wp_die(‚Konnte ZIP nicht erstellen.‘);
}

header(‚Content-Type: application/zip‘);
header(‚Content-Disposition: attachment; filename=“blockgoldcoin_export_bundle.zip“‚);
header(‚Content-Length: ‚ . filesize($zip_path));
readfile($zip_path);
exit;
}

function bgc_generate_csv_file($path) {
global $wpdb;
$table = $wpdb->prefix . ‚bgc_consent‘;
$rows = $wpdb->get_results(„SELECT * FROM $table ORDER BY created_at DESC“, ARRAY_A);

$f = fopen($path, ‚w‘);
fputcsv($f, [‚ID‘,’Datum‘,’Telefon‘,’E-Mail‘,’Adresse‘,’PLZ‘,’Stadt‘,’Land‘]);
foreach ($rows as $row) {
fputcsv($f, [
$row[‚id‘],
$row[‚created_at‘],
$row[‚phone‘],
$row[‚email‘],
$row[‚address‘],
$row[‚zip‘],
$row[‚city‘],
$row[‚country‘],
]);
}
fclose($f);
}

function bgc_generate_pdf_file($path) {
global $wpdb;
$table = $wpdb->prefix . ‚bgc_consent‘;
require_once plugin_dir_path(__FILE__) . ‚tcpdf/tcpdf.php‘;

$rows = $wpdb->get_results(„SELECT * FROM $table ORDER BY created_at DESC“, ARRAY_A);
$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$primary = $options[‚primary_color‘] ?? ‚#b87333‘;
$accent = $options[‚accent_color‘] ?? ‚#facc15‘;

$pdf = new TCPDF(‚P‘, ‚mm‘, ‚A4‘, true, ‚UTF-8‘, false);
$pdf->SetCreator(‚BlockGoldCoin‘);
$pdf->SetAuthor(‚BlockGoldCoin‘);
$pdf->SetTitle(‚BlockGoldCoin Einwilligungen‘);
$pdf->SetMargins(10, 20, 10);
$pdf->AddPage();

$pdf->SetAlpha(0.06);
$pdf->SetFont(‚helvetica‘, ‚B‘, 60);
$pdf->SetTextColor(0, 0, 0);
$pdf->StartTransform();
$pdf->Rotate(45, $pdf->GetPageWidth()/2, $pdf->GetPageHeight()/2);
$pdf->Text(20, $pdf->GetPageHeight()/2, ‚BlockGoldCoin‘);
$pdf->StopTransform();
$pdf->SetAlpha(1);

$logo_svg = ‚ ‚;
$pdf->ImageSVG(‚@‘ . $logo_svg, 10, 10, 20, 20);

$pdf->SetFont(‚helvetica‘, ‚B‘, 18);
$pdf->Ln(5);
$pdf->Cell(0, 15, ‚BlockGoldCoin – Einwilligungen‘, 0, 1, ‚C‘);

$pdf->SetFont(‚helvetica‘, “, 10);
$tbl = ‚

‚;
foreach ($rows as $r) {
$tbl .= ‚

‚;
}
$tbl .= ‚

ID Datum E-Mail Telefon Stadt Land
‚.$r[‚id‘].‘ ‚.$r[‚created_at‘].‘ ‚.$r[‚email‘].‘ ‚.$r[‚phone‘].‘ ‚.$r[‚city‘].‘ ‚.$r[‚country‘].‘

‚;
$pdf->writeHTML($tbl, true, false, false, false, “);
$pdf->Output($path, ‚F‘);
}

function bgc_generate_xlsx_file($path) {
require_once plugin_dir_path(__FILE__) . ‚vendor/autoload.php‘;

// Du kannst hier die gleiche Logik wie in bgc_export_xlsx() verwenden,
// nur statt ->save(‚php://output‘) nutzt du ->save($path);
// (keine Header senden).
}

register_activation_hook(__FILE__, function() {
if (!wp_next_scheduled(‚bgc_daily_export_event‘)) {
wp_schedule_event(time(), ‚daily‘, ‚bgc_daily_export_event‘);
}
});

register_deactivation_hook(__FILE__, function() {
wp_clear_scheduled_hook(‚bgc_daily_export_event‘);
});

add_action(‚bgc_daily_export_event‘, ‚bgc_run_daily_export‘);

function bgc_run_daily_export() {
// Wir generieren z.B. ZIP in Uploads und schicken Mail mit Link

$upload_dir = wp_upload_dir();
$dir = trailingslashit($upload_dir[‚basedir‘]) . ‚blockgoldcoin_export_daily/‘;
if (!file_exists($dir)) {
wp_mkdir_p($dir);
}

$zip_path = $dir . ‚blockgoldcoin_export_‘ . date(‚Y-m-d‘) . ‚.zip‘;

// Reuse: ZIP intern erzeugen
// Du kannst hier bgc_generate_csv_file / bgc_generate_pdf_file / bgc_generate_xlsx_file + ZipArchive
// wie in bgc_export_zip() verwenden, nur mit $zip_path.

// Beispiel minimal:
// bgc_generate_csv_file($dir.’einwilligungen.csv‘); …
// ZIP bauen -> $zip_path

$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$notify_email = $options[’notify_email‘] ?? get_option(‚admin_email‘);

$msg = „Täglicher BlockGoldCoin Export wurde erstellt: \n\n“ . $zip_path;
wp_mail($notify_email, ‚BlockGoldCoin – Täglicher Export‘, $msg);
}

function bgc_generate_xlsx_file($path) {
global $wpdb;
$table = $wpdb->prefix . ‚bgc_consent‘;

require_once plugin_dir_path(__FILE__) . ‚vendor/autoload.php‘;

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Chart\Chart;
use PhpOffice\PhpSpreadsheet\Chart\Legend;
use PhpOffice\PhpSpreadsheet\Chart\Title;
use PhpOffice\PhpSpreadsheet\Chart\PlotArea;
use PhpOffice\PhpSpreadsheet\Chart\DataSeries;
use PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues;

// Daten
$rows = $wpdb->get_results(„SELECT * FROM $table ORDER BY created_at DESC“, ARRAY_A);
$country_stats = $wpdb->get_results(„SELECT country, COUNT(*) as c FROM $table GROUP BY country ORDER BY c DESC“, ARRAY_A);

// Farben
$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$primary = $options[‚primary_color‘] ?? ‚#b87333‘;

// Spreadsheet
$spreadsheet = new Spreadsheet();
$ws = $spreadsheet->getActiveSheet();
$ws->setTitle(„Einwilligungen“);

// Header
$headers = [‚ID‘,’Datum‘,’E-Mail‘,’Telefon‘,’Adresse‘,’PLZ‘,’Stadt‘,’Land‘];
$col = ‚A‘;

foreach ($headers as $h) {
$ws->setCellValue($col.’1′, $h);
$ws->getStyle($col.’1′)->applyFromArray([
‚font‘ => [‚bold‘ => true, ‚color‘ => [‚rgb‘ => ‚FFFFFF‘]],
‚fill‘ => [‚fillType‘ => Fill::FILL_SOLID, ’startColor‘ => [‚rgb‘ => str_replace(‚#‘,“,$primary)]],
‚borders‘ => [‚bottom‘ => [‚borderStyle‘ => Border::BORDER_MEDIUM]],
]);
$col++;
}

// Daten einfügen
$rowIndex = 2;
foreach ($rows as $r) {
$ws->setCellValue(„A$rowIndex“, $r[‚id‘]);
$ws->setCellValue(„B$rowIndex“, $r[‚created_at‘]);
$ws->setCellValue(„C$rowIndex“, $r[‚email‘]);
$ws->setCellValue(„D$rowIndex“, $r[‚phone‘]);
$ws->setCellValue(„E$rowIndex“, $r[‚address‘]);
$ws->setCellValue(„F$rowIndex“, $r[‚zip‘]);
$ws->setCellValue(„G$rowIndex“, $r[‚city‘]);
$ws->setCellValue(„H$rowIndex“, $r[‚country‘]);
$rowIndex++;
}

// AutoFilter
$ws->setAutoFilter(„A1:H1“);

// AutoSize
foreach (range(‚A‘,’H‘) as $col) {
$ws->getColumnDimension($col)->setAutoSize(true);
}

// Zweites Blatt für Diagramm
$chartSheet = $spreadsheet->createSheet();
$chartSheet->setTitle(‚Länder-Stats‘);

$chartSheet->setCellValue(‚A1‘, ‚Land‘);
$chartSheet->setCellValue(‚B1‘, ‚Anzahl‘);

$r = 2;
foreach ($country_stats as $cs) {
$chartSheet->setCellValue(„A$r“, $cs[‚country‘]);
$chartSheet->setCellValue(„B$r“, (int)$cs[‚c‘]);
$r++;
}

// Diagramm definieren
$dataSeriesLabels = [
new DataSeriesValues(‚String‘, ‚Länder-Stats!$B$1‘, null, 1),
];
$xAxisTickValues = [
new DataSeriesValues(‚String‘, ‚Länder-Stats!$A$2:$A$‘.($r-1), null, $r-2),
];
$dataSeriesValues = [
new DataSeriesValues(‚Number‘, ‚Länder-Stats!$B$2:$B$‘.($r-1), null, $r-2),
];

$series = new DataSeries(
DataSeries::TYPE_PIECHART,
null,
range(0, count($dataSeriesValues)-1),
$dataSeriesLabels,
$xAxisTickValues,
$dataSeriesValues
);

$plotArea = new PlotArea(null, [$series]);
$legend = new Legend(Legend::POSITION_RIGHT, null, false);
$title = new Title(‚Einwilligungen pro Land‘);

$chart = new Chart(
‚country_chart‘,
$title,
$legend,
$plotArea
);

$chart->setTopLeftPosition(‚D2‘);
$chart->setBottomRightPosition(‚L20‘);

$chartSheet->addChart($chart);

// Datei speichern
$writer = new Xlsx($spreadsheet);
$writer->setIncludeCharts(true);
$writer->save($path);
}

function bgc_run_daily_export() {
global $wpdb;

$upload_dir = wp_upload_dir();
$dir = trailingslashit($upload_dir[‚basedir‘]) . ‚blockgoldcoin_daily/‘;
$url = trailingslashit($upload_dir[‚baseurl‘]) . ‚blockgoldcoin_daily/‘;

if (!file_exists($dir)) {
wp_mkdir_p($dir);
}

// Dateinamen
$date = date(‚Y-m-d‘);
$csv_path = $dir . „einwilligungen_$date.csv“;
$pdf_path = $dir . „einwilligungen_$date.pdf“;
$xlsx_path = $dir . „einwilligungen_$date.xlsx“;
$zip_path = $dir . „blockgoldcoin_export_$date.zip“;

// Dateien erzeugen
bgc_generate_csv_file($csv_path);
bgc_generate_pdf_file($pdf_path);
bgc_generate_xlsx_file($xlsx_path);

// ZIP erzeugen
$zip = new ZipArchive();
if ($zip->open($zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
$zip->addFile($csv_path, „einwilligungen_$date.csv“);
$zip->addFile($pdf_path, „einwilligungen_$date.pdf“);
$zip->addFile($xlsx_path, „einwilligungen_$date.xlsx“);
$zip->close();
}

// E-Mail senden
$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$notify_email = $options[’notify_email‘] ?? get_option(‚admin_email‘);

$download_link = $url . „blockgoldcoin_export_$date.zip“;

$msg = „Der tägliche BlockGoldCoin Export wurde erstellt.\n\nDownload:\n$download_link\n\nZeit: $date“;

wp_mail($notify_email, ‚BlockGoldCoin – Täglicher Export‘, $msg);

// Optional: alte Exporte löschen (älter als 14 Tage)
foreach (glob($dir . „*.zip“) as $file) {
if (filemtime($file) < strtotime('-14 days')) { unlink($file); } } } /* ADMIN-SEITE: EXPORT-LISTE */ add_action('admin_menu', function() { add_submenu_page( 'bgc-consent-export', // Eltern-Menü (Einwilligungen) 'BlockGoldCoin Exporte', 'Exporte', 'manage_options', 'bgc-consent-exports', 'bgc_render_exports_page' ); }); function bgc_render_exports_page() { $upload_dir = wp_upload_dir(); $dir = trailingslashit($upload_dir['basedir']) . 'blockgoldcoin_daily/'; $url = trailingslashit($upload_dir['baseurl']) . 'blockgoldcoin_daily/'; if (!file_exists($dir)) { echo '

BlockGoldCoin – Exporte

Noch keine Exporte vorhanden.

‚;
return;
}

$files = glob($dir . ‚blockgoldcoin_export_*.zip‘);
rsort($files); // Neueste oben

echo ‚

BlockGoldCoin – Exporte

‚;

if (!$files) {
echo ‚

Noch keine Export-Dateien vorhanden.

‚;
return;
}

echo ‚

‚;
echo ‚

‚;

foreach ($files as $file) {
$basename = basename($file);
$date = date(‚Y-m-d H:i‘, filemtime($file));
$size = filesize($file);
$size_mb = number_format($size / 1024 / 1024, 2) . ‚ MB‘;
$link = $url . $basename;

echo ‚

‚;
}

echo ‚

Datei Datum Größe Download
‚ . esc_html($basename) . ‚ ‚ . esc_html($date) . ‚ ‚ . esc_html($size_mb) . ‚ Download

‚;
}

function bgc_send_export_webhook($zip_url, $date) {
$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$url = !empty($options[‚webhook_export_url‘]) ? esc_url_raw($options[‚webhook_export_url‘]) : “;

if (!$url) return;

$payload = [
‚type‘ => ‚daily_export‘,
‚date‘ => $date,
‚zip_url‘ => $zip_url,
];

wp_remote_post($url, [
‚timeout‘ => 8,
‚headers‘ => [‚Content-Type‘ => ‚application/json; charset=utf-8‘],
‚body‘ => wp_json_encode($payload),
]);
}

// Download-Link
$download_link = $url . „blockgoldcoin_export_$date.zip“;

// E-Mail
$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$notify_email = $options[’notify_email‘] ?? get_option(‚admin_email‘);
$msg = „Der tägliche BlockGoldCoin Export wurde erstellt.\n\nDownload:\n$download_link\n\nZeit: $date“;
wp_mail($notify_email, ‚BlockGoldCoin – Täglicher Export‘, $msg);

// 🔥 Webhook für Exporte
bgc_send_export_webhook($download_link, $date);

add_action(‚rest_api_init‘, function() {
register_rest_route(‚blockgoldcoin/v1‘, ‚/exports‘, [
‚methods‘ => ‚GET‘,
‚callback‘ => ‚bgc_rest_get_exports‘,
‚permission_callback‘ => function() {
return current_user_can(‚manage_options‘); // nur Admin
}
]);
});

function bgc_rest_get_exports(WP_REST_Request $request) {
$upload_dir = wp_upload_dir();
$dir = trailingslashit($upload_dir[‚basedir‘]) . ‚blockgoldcoin_daily/‘;
$url = trailingslashit($upload_dir[‚baseurl‘]) . ‚blockgoldcoin_daily/‘;

if (!file_exists($dir)) {
return [];
}

$files = glob($dir . ‚blockgoldcoin_export_*.zip‘);
rsort($files);

$data = [];
foreach ($files as $file) {
$basename = basename($file);
$data[] = [
‚file‘ => $basename,
‚date‘ => date(‚Y-m-d H:i:s‘, filemtime($file)),
’size‘ => filesize($file),
’size_mb’=> (float) number_format(filesize($file) / 1024 / 1024, 2),
‚url‘ => $url . $basename,
];
}

return $data;
}

add_action(‚wp_dashboard_setup‘, function() {
wp_add_dashboard_widget(
‚bgc_consent_widget‘,
‚BlockGoldCoin – Einwilligungen‘,
‚bgc_render_dashboard_widget_chart‘
);
});

function bgc_render_dashboard_widget_chart() {
global $wpdb;
$table = $wpdb->prefix . ‚bgc_consent‘;

// Stats
$total = (int) $wpdb->get_var(„SELECT COUNT(*) FROM $table“);

$days = [];
$counts = [];
for ($i = 6; $i >= 0; $i–) {
$d = date(‚Y-m-d‘, strtotime(„-$i days“));
$c = (int) $wpdb->get_var($wpdb->prepare(
„SELECT COUNT(*) FROM $table WHERE DATE(created_at) = %s“,
$d
));
$days[] = $d;
$counts[] = $c;
}

echo ‚

Gesamt: ‚ . $total . ‚

‚;
echo ‚‚;

// Chart.js aus CDN (nur im Dashboard-Widget)
?>


‚GET‘,
‚callback‘ => ‚bgc_rest_get_chart_data‘,
‚permission_callback‘ => function() {
return current_user_can(‚manage_options‘); // nur Admin
}
]);
});

function bgc_rest_get_chart_data(WP_REST_Request $request) {
global $wpdb;
$table = $wpdb->prefix . ‚bgc_consent‘;

// letzte 14 Tage
$days = [];
$counts = [];
for ($i = 13; $i >= 0; $i–) {
$d = date(‚Y-m-d‘, strtotime(„-$i days“));
$c = (int) $wpdb->get_var($wpdb->prepare(
„SELECT COUNT(*) FROM $table WHERE DATE(created_at) = %s“,
$d
));
$days[] = $d;
$counts[] = $c;
}

// Top-Länder
$countries_raw = $wpdb->get_results(„
SELECT country, COUNT(*) as c
FROM $table
GROUP BY country
ORDER BY c DESC
LIMIT 10
„, ARRAY_A);

$countries = [];
$country_counts = [];
foreach ($countries_raw as $row) {
$countries[] = $row[‚country‘];
$country_counts[] = (int) $row[‚c‘];
}

return [
‚days‘ => $days,
‚counts‘ => $counts,
‚countries‘ => $countries,
‚country_counts‘ => $country_counts,
];
}

‚default‘ => [
‚headline_de‘ => ‚Einwilligung & AGB‘,
‚headline_en‘ => ‚Consent & Terms‘,
‚headline_tr‘ => ‚Açık Rıza & Genel Şartlar‘,
‚primary_color‘ => ‚#b87333‘,
‚accent_color‘ => ‚#facc15‘,
‚bg_gradient‘ => ‚linear-gradient(135deg, #ffd700, #b87333, #c0c0c0)‘,
’notify_email‘ => get_option(‚admin_email‘),
‚webhook_url‘ => “,
‚webhook_export_url‘ => “,
‚retention_days‘ => 14,
]

$fields = [
‚headline_de‘ => ‚Überschrift (Deutsch)‘,
‚headline_en‘ => ‚Überschrift (Englisch)‘,
‚headline_tr‘ => ‚Überschrift (Türkisch)‘,
‚primary_color‘ => ‚Primärfarbe (z.B. #b87333)‘,
‚accent_color‘ => ‚Akzentfarbe/Gold (z.B. #facc15)‘,
‚bg_gradient‘ => ‚Hintergrund-Gradient (CSS)‘,
’notify_email‘ => ‚E-Mail für Benachrichtigungen‘,
‚webhook_url‘ => ‚Webhook-URL (Einzel-Einwilligungen)‘,
‚webhook_export_url‘ => ‚Webhook-URL (tägliche Exporte)‘,
‚retention_days‘ => ‚Export-Aufbewahrung (Tage)‘,
];

public function sanitize_options($input) {
$out = [];
$out[‚headline_de‘] = sanitize_text_field($input[‚headline_de‘] ?? “);
$out[‚headline_en‘] = sanitize_text_field($input[‚headline_en‘] ?? “);
$out[‚headline_tr‘] = sanitize_text_field($input[‚headline_tr‘] ?? “);
$out[‚primary_color‘] = sanitize_hex_color($input[‚primary_color‘] ?? ‚#b87333‘);
$out[‚accent_color‘] = sanitize_hex_color($input[‚accent_color‘] ?? ‚#facc15‘);
$out[‚bg_gradient‘] = wp_kses_post($input[‚bg_gradient‘] ?? ‚linear-gradient(135deg, #ffd700, #b87333, #c0c0c0)‘);
$out[’notify_email‘] = sanitize_email($input[’notify_email‘] ?? get_option(‚admin_email‘));
$out[‚webhook_url‘] = esc_url_raw($input[‚webhook_url‘] ?? “);
$out[‚webhook_export_url‘] = esc_url_raw($input[‚webhook_export_url‘] ?? “);
$out[‚retention_days‘] = max(1, (int)($input[‚retention_days‘] ?? 14));
return $out;
}

$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$retention_days = isset($options[‚retention_days‘]) ? (int)$options[‚retention_days‘] : 14;
$retention_days = max(1, $retention_days);

foreach (glob($dir . „*.zip“) as $file) {
if (filemtime($file) < strtotime("-{$retention_days} days")) { unlink($file); } } /* ADMIN-SEITE: LIVE MONITOR */ add_action('admin_menu', function() { add_submenu_page( 'bgc-consent-export', 'BlockGoldCoin Live Monitor', 'Live Monitor', 'manage_options', 'bgc-consent-live-monitor', 'bgc_render_live_monitor_page' ); }); function bgc_render_live_monitor_page() { ?>

BlockGoldCoin – Live Monitor

Realtime-Übersicht der Einwilligungen (letzte 14 Tage & Top-Länder).

Einwilligungen – letzte 14 Tage

Einwilligungen pro Land

Daten werden automatisch aktualisiert.



‚GET‘,
‚callback‘ => ‚bgc_rest_get_public_stats‘,
‚permission_callback‘ => ‚__return_true‘, // öffentlich
]);
});

function bgc_rest_get_public_stats(WP_REST_Request $request) {
global $wpdb;
$table = $wpdb->prefix . ‚bgc_consent‘;

$total = (int) $wpdb->get_var(„SELECT COUNT(*) FROM $table“);
$today = (int) $wpdb->get_var($wpdb->prepare(
„SELECT COUNT(*) FROM $table WHERE DATE(created_at) = %s“,
current_time(‚Y-m-d‘)
));
$last7 = (int) $wpdb->get_var($wpdb->prepare(
„SELECT COUNT(*) FROM $table WHERE created_at >= %s“,
date(‚Y-m-d 00:00:00‘, strtotime(‚-7 days‘))
));

// Tage (letzte 14) ohne PII
$days = [];
$counts = [];
for ($i = 13; $i >= 0; $i–) {
$d = date(‚Y-m-d‘, strtotime(„-$i days“));
$c = (int) $wpdb->get_var($wpdb->prepare(
„SELECT COUNT(*) FROM $table WHERE DATE(created_at) = %s“,
$d
));
$days[] = $d;
$counts[] = $c;
}

// Top-Länder (aggregiert)
$countries_raw = $wpdb->get_results(„
SELECT country, COUNT(*) as c
FROM $table
GROUP BY country
ORDER BY c DESC
LIMIT 10
„, ARRAY_A);

$countries = [];
$country_counts = [];
foreach ($countries_raw as $row) {
$countries[] = $row[‚country‘];
$country_counts[] = (int) $row[‚c‘];
}

return [
‚total‘ => $total,
‚today‘ => $today,
‚last7‘ => $last7,
‚days‘ => $days,
‚counts‘ => $counts,
‚countries‘ => $countries,
‚country_counts‘ => $country_counts,
‚generated_at‘ => current_time(‚mysql‘),
];
}

‚default‘ => [
// …
‚api_jwt_secret‘ => “,
]

$out[‚api_jwt_secret‘] = sanitize_text_field($input[‚api_jwt_secret‘] ?? “);

‚api_jwt_secret‘ => ‚API JWT Secret (für Partner-Tokens)‘,

function bgc_base64url_encode($data) {
return rtrim(strtr(base64_encode($data), ‚+/‘, ‚-_‘), ‚=‘);
}
function bgc_base64url_decode($data) {
return base64_decode(strtr($data, ‚-_‘, ‚+/‘));
}

function bgc_jwt_encode(array $payload) {
$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$secret = $options[‚api_jwt_secret‘] ?? “;
if (!$secret) return null;

$header = [‚alg‘ => ‚HS256‘, ‚typ‘ => ‚JWT‘];
$h64 = bgc_base64url_encode(json_encode($header));
$p64 = bgc_base64url_encode(json_encode($payload));
$sig = hash_hmac(’sha256′, $h64 . ‚.‘ . $p64, $secret, true);
$s64 = bgc_base64url_encode($sig);

return $h64 . ‚.‘ . $p64 . ‚.‘ . $s64;
}

function bgc_jwt_decode($token) {
$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$secret = $options[‚api_jwt_secret‘] ?? “;
if (!$secret) return null;

$parts = explode(‚.‘, $token);
if (count($parts) !== 3) return null;

list($h64, $p64, $s64) = $parts;
$sig_check = bgc_base64url_encode(hash_hmac(’sha256′, $h64 . ‚.‘ . $p64, $secret, true));

if (!hash_equals($sig_check, $s64)) return null;

$payload = json_decode(bgc_base64url_decode($p64), true);
if (!is_array($payload)) return null;

// exp prüfen (optional)
if (isset($payload[‚exp‘]) && time() > (int)$payload[‚exp‘]) {
return null;
}

return $payload;
}

add_action(‚rest_api_init‘, function() {
register_rest_route(‚blockgoldcoin/v1‘, ‚/partner-stats‘, [
‚methods‘ => ‚GET‘,
‚callback‘ => ‚bgc_rest_partner_stats‘,
‚permission_callback‘ => ‚__return_true‘, // Auth in Callback
]);
});

function bgc_rest_partner_stats(WP_REST_Request $request) {
$auth = $request->get_header(‚authorization‘);
if (!$auth || stripos($auth, ‚bearer ‚) !== 0) {
return new WP_REST_Response([‚error‘ => ‚missing_token‘], 401);
}

$token = trim(substr($auth, 7));
$payload = bgc_jwt_decode($token);
if (!$payload || empty($payload[‚partner_id‘])) {
return new WP_REST_Response([‚error‘ => ‚invalid_token‘], 403);
}

// Ab hier: partner_id verfügbar, aber wir liefern nur aggregierte Daten
return bgc_rest_get_public_stats($request);
}

$token = bgc_jwt_encode([
‚partner_id‘ => ‚your-partner‘,
‚exp‘ => time() + 3600, // 1 Stunde
]);

function bgc_export_audit_report_pdf() {
global $wpdb;
$table = $wpdb->prefix . ‚bgc_consent‘;

require_once plugin_dir_path(__FILE__) . ‚tcpdf/tcpdf.php‘;

$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$primary = $options[‚primary_color‘] ?? ‚#b87333‘;
$accent = $options[‚accent_color‘] ?? ‚#facc15‘;

// Stats
$total = (int) $wpdb->get_var(„SELECT COUNT(*) FROM $table“);
$today = (int) $wpdb->get_var($wpdb->prepare(
„SELECT COUNT(*) FROM $table WHERE DATE(created_at) = %s“,
current_time(‚Y-m-d‘)
));
$last7 = (int) $wpdb->get_var($wpdb->prepare(
„SELECT COUNT(*) FROM $table WHERE created_at >= %s“,
date(‚Y-m-d 00:00:00‘, strtotime(‚-7 days‘))
));

$countries_raw = $wpdb->get_results(„
SELECT country, COUNT(*) as c
FROM $table
GROUP BY country
ORDER BY c DESC
LIMIT 10
„, ARRAY_A);

// Exporte lesen
$upload_dir = wp_upload_dir();
$dir = trailingslashit($upload_dir[‚basedir‘]) . ‚blockgoldcoin_daily/‘;
$files = file_exists($dir) ? glob($dir . ‚blockgoldcoin_export_*.zip‘) : [];
rsort($files);
$files = array_slice($files, 0, 20);

$pdf = new TCPDF(‚P‘, ‚mm‘, ‚A4‘, true, ‚UTF-8‘, false);
$pdf->SetCreator(‚BlockGoldCoin‘);
$pdf->SetAuthor(‚BlockGoldCoin‘);
$pdf->SetTitle(‚BlockGoldCoin Audit Report‘);
$pdf->SetMargins(10, 20, 10);
$pdf->AddPage();

// Logo + Titel
$logo_svg = ‚ ‚;
$pdf->ImageSVG(‚@‘ . $logo_svg, 10, 10, 20, 20);

$pdf->SetFont(‚helvetica‘, ‚B‘, 18);
$pdf->Cell(0, 10, ‚BlockGoldCoin – Audit Report‘, 0, 1, ‚C‘);
$pdf->SetFont(‚helvetica‘, “, 10);
$pdf->Ln(2);
$pdf->Cell(0, 6, ‚Generiert: ‚ . current_time(‚mysql‘), 0, 1, ‚R‘);

// Section: Übersicht
$pdf->Ln(4);
$pdf->SetFont(‚helvetica‘, ‚B‘, 12);
$pdf->SetTextColor(0,0,0);
$pdf->Cell(0, 8, ‚1. Übersicht‘, 0, 1);

$pdf->SetFont(‚helvetica‘, “, 10);
$pdf->writeHTML(‚

  • Gesamtanzahl Einwilligungen: ‚ . $total . ‚
  • Heute: ‚ . $today . ‚
  • Letzte 7 Tage: ‚ . $last7 . ‚

‚, true, false, false, false, “);

// Section: Top-Länder
$pdf->Ln(2);
$pdf->SetFont(‚helvetica‘, ‚B‘, 12);
$pdf->Cell(0, 8, ‚2. Einwilligungen nach Ländern (Top 10)‘, 0, 1);

$pdf->SetFont(‚helvetica‘, “, 10);
$tbl_c = ‚

‚;
foreach ($countries_raw as $row) {
$tbl_c .= ‚

‚;
}
$tbl_c .= ‚

Land Anzahl
‚ . esc_html($row[‚country‘]) . ‚ ‚ . (int)$row[‚c‘] . ‚

‚;
$pdf->writeHTML($tbl_c, true, false, false, false, “);

// Section: Exporte
$pdf->AddPage();
$pdf->SetFont(‚helvetica‘, ‚B‘, 12);
$pdf->Cell(0, 8, ‚3. Exporte (ZIP-Bundles)‘, 0, 1);

if (!$files) {
$pdf->SetFont(‚helvetica‘, “, 10);
$pdf->Cell(0, 6, ‚Keine Export-Dateien gefunden.‘, 0, 1);
} else {
$pdf->SetFont(‚helvetica‘, “, 10);
$tbl_e = ‚

‚;
foreach ($files as $file) {
$basename = basename($file);
$date = date(‚Y-m-d H:i‘, filemtime($file));
$size_mb = number_format(filesize($file) / 1024 / 1024, 2);
$tbl_e .= ‚

‚;
}
$tbl_e .= ‚

Datei Datum Größe (MB)
‚ . $basename . ‚ ‚ . $date . ‚ ‚ . $size_mb . ‚

‚;
$pdf->writeHTML($tbl_e, true, false, false, false, “);
}

// Ausgabe
$pdf->Output(‚blockgoldcoin_audit_report.pdf‘, ‚D‘);
exit;
}

BlockGoldCoin – Partner Dashboard

Aggregierte Einwilligungs-Statistiken (readonly).

Einwilligungen (letzte 14 Tage)

Einwilligungen nach Ländern



‚partner-xyz‘,
‚exp‘ => time() + 86400, // 24h gültig
]);

public function on_activate() {
global $wpdb;

$charset = $wpdb->get_charset_collate();

// Token-Tabelle
$table_tokens = $wpdb->prefix . ‚bgc_tokens‘;
$sql1 = „CREATE TABLE IF NOT EXISTS $table_tokens (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
partner_name VARCHAR(255) NOT NULL,
token VARCHAR(255) NOT NULL,
expires_at DATETIME NOT NULL,
active TINYINT(1) NOT NULL DEFAULT 1,
created_at DATETIME NOT NULL,
PRIMARY KEY (id)
) $charset;“;

// Log-Tabelle
$table_logs = $wpdb->prefix . ‚bgc_token_logs‘;
$sql2 = „CREATE TABLE IF NOT EXISTS $table_logs (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
token_id BIGINT UNSIGNED NOT NULL,
endpoint VARCHAR(255) NOT NULL,
ip VARCHAR(64) NOT NULL,
created_at DATETIME NOT NULL,
PRIMARY KEY (id)
) $charset;“;

require_once ABSPATH . ‚wp-admin/includes/upgrade.php‘;
dbDelta($sql1);
dbDelta($sql2);
}

add_action(‚admin_menu‘, function() {
add_submenu_page(
‚bgc-consent-export‘,
‚Token Manager‘,
‚Token Manager‘,
‚manage_options‘,
‚bgc-token-manager‘,
‚bgc_render_token_manager‘
);
});

function bgc_create_token($partner_name, $days_valid = 30) {
global $wpdb;
$table = $wpdb->prefix . ‚bgc_tokens‘;

$token_raw = wp_generate_password(32, false, false);
$expires = date(‚Y-m-d H:i:s‘, strtotime(„+$days_valid days“));

$wpdb->insert($table, [
‚partner_name‘ => $partner_name,
‚token‘ => $token_raw,
‚expires_at‘ => $expires,
‚active‘ => 1,
‚created_at‘ => current_time(‚mysql‘),
]);

return $token_raw;
}

function bgc_render_token_manager() {
global $wpdb;
$table = $wpdb->prefix . ‚bgc_tokens‘;

// Token erzeugen
if (isset($_POST[‚bgc_new_token‘])) {
$partner = sanitize_text_field($_POST[‚partner_name‘]);
$days = (int)$_POST[‚valid_days‘];
$token = bgc_create_token($partner, $days);

echo ‚

Neues Token erzeugt: ‚ . esc_html($token) . ‚

‚;
}

// Token sperren/aktivieren
if (isset($_GET[‚toggle‘])) {
$id = (int)$_GET[‚toggle‘];
$wpdb->query(„UPDATE $table SET active = 1 – active WHERE id = $id“);
}

// Token löschen
if (isset($_GET[‚delete‘])) {
$id = (int)$_GET[‚delete‘];
$wpdb->delete($table, [‚id‘ => $id]);
}

$tokens = $wpdb->get_results(„SELECT * FROM $table ORDER BY created_at DESC“);

?>

BlockGoldCoin – Token Manager

Neues Token erzeugen




Bestehende Tokens


ID Partner Token Ablaufdatum Status Aktionen
id; ?> partner_name); ?> token); ?> expires_at); ?> active ? ‚Aktiv‘ : ‚Gesperrt‘; ?> id; ?>“ class=“button button-danger“
onclick=“return confirm(‚Token wirklich löschen?‘);“>
Löschen

prefix . ‚bgc_tokens‘;

$row = $wpdb->get_row($wpdb->prepare(
„SELECT * FROM $table WHERE token = %s LIMIT 1“,
$token_raw
));

if (!$row) return false;
if (!$row->active) return false;
if (time() > strtotime($row->expires_at)) return false;

return $row; // enthält partner_name, id, expires_at
}

$auth = $request->get_header(‚authorization‘);
if (!$auth || stripos($auth, ‚bearer ‚) !== 0) {
return new WP_REST_Response([‚error‘ => ‚missing_token‘], 401);
}

$token_raw = trim(substr($auth, 7));
$token = bgc_auth_partner_token($token_raw);

if (!$token) {
return new WP_REST_Response([‚error‘ => ‚invalid_or_expired_token‘], 403);
}

function bgc_log_partner_access($token_id, $endpoint) {
global $wpdb;
$table = $wpdb->prefix . ‚bgc_token_logs‘;

$wpdb->insert($table, [
‚token_id‘ => $token_id,
‚endpoint‘ => $endpoint,
‚ip‘ => $_SERVER[‚REMOTE_ADDR‘] ?? ‚unknown‘,
‚created_at‘ => current_time(‚mysql‘),
]);
}

bgc_log_partner_access($token->id, ‚partner-stats‘);

add_action(‚admin_menu‘, function() {
add_submenu_page(
‚bgc-consent-export‘,
‚Partner Logs‘,
‚Partner Logs‘,
‚manage_options‘,
‚bgc-partner-logs‘,
‚bgc_render_partner_logs‘
);
});

function bgc_render_partner_logs() {
global $wpdb;
$table_logs = $wpdb->prefix . ‚bgc_token_logs‘;
$table_tokens = $wpdb->prefix . ‚bgc_tokens‘;

$logs = $wpdb->get_results(„
SELECT l.*, t.partner_name
FROM $table_logs l
LEFT JOIN $table_tokens t ON t.id = l.token_id
ORDER BY l.created_at DESC
LIMIT 200
„);

?>

BlockGoldCoin – Partner Logs


Zeit Partner Endpoint IP
created_at); ?> partner_name); ?> endpoint); ?> ip); ?>

get_charset_collate();

// Einwilligungen
$table = $wpdb->prefix . self::TABLE_CONSENT;
$sql = „CREATE TABLE IF NOT EXISTS $table (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
created_at datetime NOT NULL,
phone varchar(64) DEFAULT “ NOT NULL,
email varchar(255) DEFAULT “ NOT NULL,
address text,
zip varchar(32) DEFAULT “ NOT NULL,
city varchar(128) DEFAULT “ NOT NULL,
country varchar(128) DEFAULT “ NOT NULL,
PRIMARY KEY (id)
) $charset;“;
require_once ABSPATH . ‚wp-admin/includes/upgrade.php‘;
dbDelta($sql);

// Tokens
$table_tokens = $wpdb->prefix . self::TABLE_TOKENS;
$sql1 = „CREATE TABLE IF NOT EXISTS $table_tokens (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
partner_name VARCHAR(255) NOT NULL,
token VARCHAR(255) NOT NULL,
expires_at DATETIME NOT NULL,
active TINYINT(1) NOT NULL DEFAULT 1,
created_at DATETIME NOT NULL,
PRIMARY KEY (id)
) $charset;“;
dbDelta($sql1);

// Logs
$table_logs = $wpdb->prefix . self::TABLE_LOGS;
$sql2 = „CREATE TABLE IF NOT EXISTS $table_logs (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
token_id BIGINT UNSIGNED NOT NULL,
endpoint VARCHAR(255) NOT NULL,
ip VARCHAR(64) NOT NULL,
created_at DATETIME NOT NULL,
PRIMARY KEY (id)
) $charset;“;
dbDelta($sql2);

if (!wp_next_scheduled(‚bgc_daily_export_event‘)) {
wp_schedule_event(time(), ‚daily‘, ‚bgc_daily_export_event‘);
}
}

public function on_deactivate() {
wp_clear_scheduled_hook(‚bgc_daily_export_event‘);
}

/* —————- ADMIN-EINSTELLUNGEN —————- */

public function add_settings_page() {
add_options_page(
‚BlockGoldCoin Consent‘,
‚BlockGoldCoin Consent‘,
‚manage_options‘,
‚bgc-consent-settings‘,
[$this, ‚render_settings_page‘]
);
}

public function register_settings() {
register_setting(self::OPTION_GROUP, self::OPTION_NAME, [
‚type‘ => ‚array‘,
’sanitize_callback‘ => [$this, ’sanitize_options‘],
‚default‘ => [
‚headline_de‘ => ‚Einwilligung & AGB‘,
‚headline_en‘ => ‚Consent & Terms‘,
‚headline_tr‘ => ‚Açık Rıza & Genel Şartlar‘,
‚primary_color‘ => ‚#b87333‘,
‚accent_color‘ => ‚#facc15‘,
‚bg_gradient‘ => ‚linear-gradient(135deg, #ffd700, #b87333, #c0c0c0)‘,
’notify_email‘ => get_option(‚admin_email‘),
‚webhook_url‘ => “,
‚webhook_export_url‘ => “,
‚retention_days‘ => 14,
‚api_jwt_secret‘ => “,
‚download_secret‘ => “,
‚download_ttl_min‘ => 60,
]
]);

add_settings_section(
‚bgc_consent_main‘,
‚BlockGoldCoin Consent Einstellungen‘,
‚__return_false‘,
‚bgc-consent-settings‘
);

$fields = [
‚headline_de‘ => ‚Überschrift (Deutsch)‘,
‚headline_en‘ => ‚Überschrift (Englisch)‘,
‚headline_tr‘ => ‚Überschrift (Türkisch)‘,
‚primary_color‘ => ‚Primärfarbe (z.B. #b87333)‘,
‚accent_color‘ => ‚Akzentfarbe/Gold (z.B. #facc15)‘,
‚bg_gradient‘ => ‚Hintergrund-Gradient (CSS)‘,
’notify_email‘ => ‚E-Mail für Benachrichtigungen‘,
‚webhook_url‘ => ‚Webhook-URL (Einzel-Einwilligungen)‘,
‚webhook_export_url‘ => ‚Webhook-URL (tägliche Exporte)‘,
‚retention_days‘ => ‚Export-Aufbewahrung (Tage)‘,
‚api_jwt_secret‘ => ‚API JWT Secret (optional)‘,
‚download_secret‘ => ‚Download-Secret (für signierte Links)‘,
‚download_ttl_min‘ => ‚Download-Link-Gültigkeit (Minuten)‘,
];

foreach ($fields as $key => $label) {
add_settings_field(
$key,
$label,
[$this, ‚render_settings_field‘],
‚bgc-consent-settings‘,
‚bgc_consent_main‘,
[‚key‘ => $key]
);
}
}

public function sanitize_options($input) {
$out = [];
$out[‚headline_de‘] = sanitize_text_field($input[‚headline_de‘] ?? “);
$out[‚headline_en‘] = sanitize_text_field($input[‚headline_en‘] ?? “);
$out[‚headline_tr‘] = sanitize_text_field($input[‚headline_tr‘] ?? “);
$out[‚primary_color‘] = sanitize_hex_color($input[‚primary_color‘] ?? ‚#b87333‘);
$out[‚accent_color‘] = sanitize_hex_color($input[‚accent_color‘] ?? ‚#facc15‘);
$out[‚bg_gradient‘] = wp_kses_post($input[‚bg_gradient‘] ?? ‚linear-gradient(135deg, #ffd700, #b87333, #c0c0c0)‘);
$out[’notify_email‘] = sanitize_email($input[’notify_email‘] ?? get_option(‚admin_email‘));
$out[‚webhook_url‘] = esc_url_raw($input[‚webhook_url‘] ?? “);
$out[‚webhook_export_url‘] = esc_url_raw($input[‚webhook_export_url‘] ?? “);
$out[‚retention_days‘] = max(1, (int)($input[‚retention_days‘] ?? 14));
$out[‚api_jwt_secret‘] = sanitize_text_field($input[‚api_jwt_secret‘] ?? “);
$out[‚download_secret‘] = sanitize_text_field($input[‚download_secret‘] ?? “);
$out[‚download_ttl_min‘] = max(5, (int)($input[‚download_ttl_min‘] ?? 60));
return $out;
}

public function render_settings_field($args) {
$key = $args[‚key‘];
$options = get_option(self::OPTION_NAME);
$value = esc_attr($options[$key] ?? “);
echo ‚‚;
}

public function render_settings_page() {
?>

BlockGoldCoin Consent


prefix . self::TABLE_CONSENT;

$wpdb->insert($table, [
‚created_at‘ => current_time(‚mysql‘),
‚phone‘ => $phone,
‚email‘ => $email,
‚address‘ => $address,
‚zip‘ => $zip,
‚city‘ => $city,
‚country‘ => $country,
]);

$options = get_option(self::OPTION_NAME);
$notify_email = $options[’notify_email‘] ?? get_option(‚admin_email‘);

$subject = ‚Neue BlockGoldCoin Einwilligung‘;
$message = „Neue Einwilligung:\n\n“.
„Telefon: $phone\n“.
„E-Mail: $email\n“.
„Adresse: $address\n“.
„PLZ: $zip\n“.
„Stadt: $city\n“.
„Land: $country\n“.
„Zeit: „.current_time(‚mysql‘).“\n“;

wp_mail($notify_email, $subject, $message);

// Webhook für Einzel-Einwilligung
if (!empty($options[‚webhook_url‘])) {
wp_remote_post($options[‚webhook_url‘], [
‚timeout‘ => 5,
‚headers‘ => [‚Content-Type‘ => ‚application/json; charset=utf-8‘],
‚body‘ => wp_json_encode([
‚phone‘ => $phone,
‚email‘ => $email,
‚zip‘ => $zip,
‚city‘ => $city,
‚country‘ => $country,
‚created‘ => current_time(‚mysql‘),
]),
]);
}

wp_safe_redirect(add_query_arg(‚bgc_consent‘, ‚ok‘, wp_get_referer() ?: home_url()));
exit;
}

/* —————- SHORTCODE + BLOCK —————- */

public function shortcode($atts = []) {
$options = get_option(self::OPTION_NAME);
$bg = $options[‚bg_gradient‘] ?? ‚linear-gradient(135deg, #ffd700, #b87333, #c0c0c0)‘;
$primary = $options[‚primary_color‘] ?? ‚#b87333‘;
$accent = $options[‚accent_color‘] ?? ‚#facc15‘;

$lang = isset($_GET[‚lang‘]) ? sanitize_text_field($_GET[‚lang‘]) : ‚de‘;

$headline = $options[‚headline_de‘] ?? ‚Einwilligung & AGB‘;
if ($lang === ‚en‘) $headline = $options[‚headline_en‘] ?? ‚Consent & Terms‘;
if ($lang === ‚tr‘) $headline = $options[‚headline_tr‘] ?? ‚Açık Rıza & Genel Şartlar‘;

ob_start();
?>











2,
‚render_callback‘ => [$this, ’shortcode‘],
‚attributes‘ => [],
‚editor_script‘ => ‚bgc-consent-block-editor‘,
]);

add_action(‚enqueue_block_editor_assets‘, function() {
$handle = ‚bgc-consent-block-editor‘;
wp_register_script($handle, “, [], false, true);
wp_enqueue_script($handle);
$inline = „wp.blocks.registerBlockType(‚blockgoldcoin/consent‘,{
title: ‚BlockGoldCoin Consent‘,
icon: ’shield‘,
category: ‚widgets‘,
edit: function(){ return wp.element.createElement(‚p‘,{},’BlockGoldCoin Consent Formular (im Frontend sichtbar).‘); },
save: function(){ return null; }
});“;
wp_add_inline_script($handle, $inline);
});
}
}

new BlockGoldCoin_Consent();

/* ==========================================================
* AB HIER: EXPORT-ADMIN, PDF/XLSX/ZIP, CRON, REST, TOKEN, LOGS
* ========================================================== */

/* ———- HILFSFUNKTIONEN ———- */

function bgc_get_download_secret() {
$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$secret = $options[‚download_secret‘] ?? “;
if (!$secret) {
$secret = wp_generate_password(32, true, true);
$options[‚download_secret‘] = $secret;
update_option(BlockGoldCoin_Consent::OPTION_NAME, $options);
}
return $secret;
}

function bgc_generate_signed_download_link($relative_file_path) {
$upload_dir = wp_upload_dir();
$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$ttl_min = isset($options[‚download_ttl_min‘]) ? (int)$options[‚download_ttl_min‘] : 60;
$ttl_min = max(5, $ttl_min);

$exp = time() + ($ttl_min * 60);
$file = $relative_file_path;

$secret = bgc_get_download_secret();
$data = $file . ‚|‘ . $exp;
$sig = hash_hmac(’sha256′, $data, $secret);

$url = add_query_arg([
‚bgc_download‘ => 1,
‚file‘ => rawurlencode($file),
‚exp‘ => $exp,
’sig‘ => $sig,
], home_url(‚/‘));

return $url;
}

/* ———- DOWNLOAD-PROXY ———- */

add_action(‚init‘, function() {
if (!isset($_GET[‚bgc_download‘])) return;

$file = isset($_GET[‚file‘]) ? rawurldecode($_GET[‚file‘]) : “;
$exp = isset($_GET[‚exp‘]) ? (int)$_GET[‚exp‘] : 0;
$sig = isset($_GET[’sig‘]) ? sanitize_text_field($_GET[’sig‘]) : “;

if (!$file || !$exp || !$sig) {
status_header(400);
exit(‚Invalid parameters.‘);
}
if (time() > $exp) {
status_header(403);
exit(‚Link expired.‘);
}

$secret = bgc_get_download_secret();
$data = $file . ‚|‘ . $exp;
$sig_check = hash_hmac(’sha256′, $data, $secret);

if (!hash_equals($sig_check, $sig)) {
status_header(403);
exit(‚Invalid signature.‘);
}

$upload_dir = wp_upload_dir();
$full_path = trailingslashit($upload_dir[‚basedir‘]) . ltrim($file, ‚/‘);
if (!file_exists($full_path)) {
status_header(404);
exit(‚File not found.‘);
}

$filename = basename($full_path);
header(‚Content-Type: application/zip‘);
header(‚Content-Disposition: attachment; filename=“‚.$filename.'“‚);
header(‚Content-Length: ‚ . filesize($full_path));
readfile($full_path);
exit;
});

/* ———- ADMIN: EINWILLIGUNGEN-EXPORT-SEITE (Liste + Filter + Export) ———- */

add_action(‚admin_menu‘, function() {
add_menu_page(
‚BlockGoldCoin Einwilligungen‘,
‚Einwilligungen‘,
‚manage_options‘,
‚bgc-consent-export‘,
‚bgc_render_export_page‘,
‚dashicons-database-export‘,
26
);
});

function bgc_render_export_page() {
global $wpdb;
$table = $wpdb->prefix . BlockGoldCoin_Consent::TABLE_CONSENT;

if (isset($_GET[‚export‘])) {
$type = sanitize_text_field($_GET[‚export‘]);
if ($type === ‚csv‘) { bgc_export_csv(); }
if ($type === ‚pdf‘) { bgc_export_pdf(); }
if ($type === ‚xlsx‘) { bgc_export_xlsx(); }
if ($type === ‚zip‘) { bgc_export_zip(); }
if ($type === ‚audit‘) { bgc_export_audit_report_pdf(); }
exit;
}

$where = ‚WHERE 1=1‘;
$params = [];

$date_from = isset($_GET[‚date_from‘]) ? sanitize_text_field($_GET[‚date_from‘]) : “;
$date_to = isset($_GET[‚date_to‘]) ? sanitize_text_field($_GET[‚date_to‘]) : “;
$country = isset($_GET[‚country‘]) ? sanitize_text_field($_GET[‚country‘]) : “;
$city = isset($_GET[‚city‘]) ? sanitize_text_field($_GET[‚city‘]) : “;
$zip = isset($_GET[‚zip‘]) ? sanitize_text_field($_GET[‚zip‘]) : “;
$search = isset($_GET[’s‘]) ? sanitize_text_field($_GET[’s‘]) : “;

if ($date_from) {
$where .= ‚ AND created_at >= %s‘;
$params[] = $date_from . ‚ 00:00:00‘;
}
if ($date_to) {
$where .= ‚ AND created_at <= %s'; $params[] = $date_to . ' 23:59:59'; } if ($country) { $where .= ' AND country LIKE %s'; $params[] = '%'.$wpdb->esc_like($country).’%‘;
}
if ($city) {
$where .= ‚ AND city LIKE %s‘;
$params[] = ‚%‘.$wpdb->esc_like($city).’%‘;
}
if ($zip) {
$where .= ‚ AND zip LIKE %s‘;
$params[] = ‚%‘.$wpdb->esc_like($zip).’%‘;
}
if ($search) {
$where .= “ AND (email LIKE %s OR phone LIKE %s OR address LIKE %s)“;
$like = ‚%‘.$wpdb->esc_like($search).’%‘;
$params[] = $like;
$params[] = $like;
$params[] = $like;
}

$per_page = 20;
$paged = isset($_GET[‚paged‘]) ? max(1, (int)$_GET[‚paged‘]) : 1;
$offset = ($paged – 1) * $per_page;

$sql_count = „SELECT COUNT(*) FROM $table $where“;
$total = $params ? $wpdb->get_var($wpdb->prepare($sql_count, $params)) : $wpdb->get_var($sql_count);
$pages = max(1, ceil($total / $per_page));

$sql_rows = „SELECT * FROM $table $where ORDER BY created_at DESC LIMIT %d OFFSET %d“;
$params_rows = $params;
$params_rows[] = $per_page;
$params_rows[] = $offset;
$rows = $wpdb->get_results($wpdb->prepare($sql_rows, $params_rows));

$base_url = remove_query_arg([‚paged‘,’export‘]);
?>

BlockGoldCoin – Einwilligungen


Filtern
“ class=“button button-primary“ style=“margin-right:5px;“>CSV exportieren
“ class=“button“>Excel exportieren
“ class=“button“>Audit Report PDF

Gesamt: Einträge


ID Datum Telefon E-Mail Adresse PLZ Stadt Land
id); ?> created_at); ?> phone); ?> email); ?> address); ?> zip); ?> city); ?> country); ?>
Keine Einträge gefunden.

1): ?>


‚;
$pdf->ImageSVG(‚@‘ . $logo_svg, 10, 10, 20, 20);

$pdf->SetFont(‚helvetica‘, ‚B‘, 18);
$pdf->Cell(0, 10, ‚BlockGoldCoin – Einwilligungen‘, 0, 1, ‚C‘);

$pdf->SetFont(‚helvetica‘, “, 10);
$tbl = ‚

‚;
foreach ($rows as $r) {
$tbl .= ‚

‚;
}
$tbl .= ‚

ID Datum E-Mail Telefon Stadt Land
‚.$r[‚id‘].‘ ‚.$r[‚created_at‘].‘ ‚.$r[‚email‘].‘ ‚.$r[‚phone‘].‘ ‚.$r[‚city‘].‘ ‚.$r[‚country‘].‘

‚;
$pdf->writeHTML($tbl, true, false, false, false, “);
$pdf->Output(‚blockgoldcoin_einwilligungen.pdf‘, ‚D‘);
exit;
}

function bgc_export_xlsx() {
global $wpdb;
$table = $wpdb->prefix . BlockGoldCoin_Consent::TABLE_CONSENT;

require_once plugin_dir_path(__FILE__) . ‚vendor/autoload.php‘;

$rows = $wpdb->get_results(„SELECT * FROM $table ORDER BY created_at DESC“, ARRAY_A);
$country_stats = $wpdb->get_results(„SELECT country, COUNT(*) as c FROM $table GROUP BY country ORDER BY c DESC“, ARRAY_A);

$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$primary = $options[‚primary_color‘] ?? ‚#b87333‘;

$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$ws = $spreadsheet->getActiveSheet();
$ws->setTitle(„Einwilligungen“);

$headers = [‚ID‘,’Datum‘,’E-Mail‘,’Telefon‘,’Adresse‘,’PLZ‘,’Stadt‘,’Land‘];
$col = ‚A‘;
foreach ($headers as $h) {
$ws->setCellValue($col.’1′, $h);
$ws->getStyle($col.’1′)->applyFromArray([
‚font‘ => [‚bold‘ => true, ‚color‘ => [‚rgb‘ => ‚FFFFFF‘]],
‚fill‘ => [‚fillType‘ => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, ’startColor‘ => [‚rgb‘ => str_replace(‚#‘,“,$primary)]],
‚borders‘ => [‚bottom‘ => [‚borderStyle‘ => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUM]],
]);
$col++;
}

$rowIndex = 2;
foreach ($rows as $r) {
$ws->setCellValue(„A$rowIndex“, $r[‚id‘]);
$ws->setCellValue(„B$rowIndex“, $r[‚created_at‘]);
$ws->setCellValue(„C$rowIndex“, $r[‚email‘]);
$ws->setCellValue(„D$rowIndex“, $r[‚phone‘]);
$ws->setCellValue(„E$rowIndex“, $r[‚address‘]);
$ws->setCellValue(„F$rowIndex“, $r[‚zip‘]);
$ws->setCellValue(„G$rowIndex“, $r[‚city‘]);
$ws->setCellValue(„H$rowIndex“, $r[‚country‘]);
$rowIndex++;
}

$ws->setAutoFilter(„A1:H1“);
foreach (range(‚A‘,’H‘) as $c) {
$ws->getColumnDimension($c)->setAutoSize(true);
}

$chartSheet = $spreadsheet->createSheet();
$chartSheet->setTitle(‚Länder-Stats‘);
$chartSheet->setCellValue(‚A1‘, ‚Land‘);
$chartSheet->setCellValue(‚B1‘, ‚Anzahl‘);
$r = 2;
foreach ($country_stats as $cs) {
$chartSheet->setCellValue(„A$r“, $cs[‚country‘]);
$chartSheet->setCellValue(„B$r“, (int)$cs[‚c‘]);
$r++;
}

$dataSeriesLabels = [
new \PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues(‚String‘, ‚Länder-Stats!$B$1‘, null, 1),
];
$xAxisTickValues = [
new \PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues(‚String‘, ‚Länder-Stats!$A$2:$A$‘.($r-1), null, $r-2),
];
$dataSeriesValues = [
new \PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues(‚Number‘, ‚Länder-Stats!$B$2:$B$‘.($r-1), null, $r-2),
];

$series = new \PhpOffice\PhpSpreadsheet\Chart\DataSeries(
\PhpOffice\PhpSpreadsheet\Chart\DataSeries::TYPE_PIECHART,
null,
range(0, count($dataSeriesValues)-1),
$dataSeriesLabels,
$xAxisTickValues,
$dataSeriesValues
);
$plotArea = new \PhpOffice\PhpSpreadsheet\Chart\PlotArea(null, [$series]);
$legend = new \PhpOffice\PhpSpreadsheet\Chart\Legend(\PhpOffice\PhpSpreadsheet\Chart\Legend::POSITION_RIGHT, null, false);
$title = new \PhpOffice\PhpSpreadsheet\Chart\Title(‚Einwilligungen pro Land‘);

$chart = new \PhpOffice\PhpSpreadsheet\Chart\Chart(
‚country_chart‘,
$title,
$legend,
$plotArea
);
$chart->setTopLeftPosition(‚D2‘);
$chart->setBottomRightPosition(‚L20‘);
$chartSheet->addChart($chart);

header(‚Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet‘);
header(‚Content-Disposition: attachment; filename=“blockgoldcoin_einwilligungen.xlsx“‚);

$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
$writer->setIncludeCharts(true);
$writer->save(‚php://output‘);
exit;
}

/* ———- Generische Dateierzeuger für ZIP & Cron ———- */

function bgc_generate_csv_file($path) {
global $wpdb;
$table = $wpdb->prefix . BlockGoldCoin_Consent::TABLE_CONSENT;
$rows = $wpdb->get_results(„SELECT * FROM $table ORDER BY created_at DESC“, ARRAY_A);

$f = fopen($path, ‚w‘);
fputcsv($f, [‚ID‘,’Datum‘,’Telefon‘,’E-Mail‘,’Adresse‘,’PLZ‘,’Stadt‘,’Land‘]);
foreach ($rows as $row) {
fputcsv($f, [
$row[‚id‘],
$row[‚created_at‘],
$row[‚phone‘],
$row[‚email‘],
$row[‚address‘],
$row[‚zip‘],
$row[‚city‘],
$row[‚country‘],
]);
}
fclose($f);
}

function bgc_generate_pdf_file($path) {
global $wpdb;
$table = $wpdb->prefix . BlockGoldCoin_Consent::TABLE_CONSENT;
require_once plugin_dir_path(__FILE__) . ‚tcpdf/tcpdf.php‘;

$rows = $wpdb->get_results(„SELECT * FROM $table ORDER BY created_at DESC“, ARRAY_A);
$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$primary = $options[‚primary_color‘] ?? ‚#b87333‘;
$accent = $options[‚accent_color‘] ?? ‚#facc15‘;

$pdf = new TCPDF(‚P‘, ‚mm‘, ‚A4‘, true, ‚UTF-8‘, false);
$pdf->SetCreator(‚BlockGoldCoin‘);
$pdf->SetAuthor(‚BlockGoldCoin‘);
$pdf->SetTitle(‚BlockGoldCoin Einwilligungen‘);
$pdf->SetMargins(10, 20, 10);
$pdf->AddPage();

$pdf->SetAlpha(0.06);
$pdf->SetFont(‚helvetica‘, ‚B‘, 60);
$pdf->SetTextColor(0, 0, 0);
$pdf->StartTransform();
$pdf->Rotate(45, $pdf->GetPageWidth()/2, $pdf->GetPageHeight()/2);
$pdf->Text(20, $pdf->GetPageHeight()/2, ‚BlockGoldCoin‘);
$pdf->StopTransform();
$pdf->SetAlpha(1);

$logo_svg = ‚ ‚;
$pdf->ImageSVG(‚@‘ . $logo_svg, 10, 10, 20, 20);

$pdf->SetFont(‚helvetica‘, ‚B‘, 18);
$pdf->Cell(0, 10, ‚BlockGoldCoin – Einwilligungen‘, 0, 1, ‚C‘);

$pdf->SetFont(‚helvetica‘, “, 10);
$tbl = ‚

‚;
foreach ($rows as $r) {
$tbl .= ‚

‚;
}
$tbl .= ‚

ID Datum E-Mail Telefon Stadt Land
‚.$r[‚id‘].‘ ‚.$r[‚created_at‘].‘ ‚.$r[‚email‘].‘ ‚.$r[‚phone‘].‘ ‚.$r[‚city‘].‘ ‚.$r[‚country‘].‘

‚;
$pdf->writeHTML($tbl, true, false, false, false, “);
$pdf->Output($path, ‚F‘);
}

function bgc_generate_xlsx_file($path) {
global $wpdb;
$table = $wpdb->prefix . BlockGoldCoin_Consent::TABLE_CONSENT;

require_once plugin_dir_path(__FILE__) . ‚vendor/autoload.php‘;

$rows = $wpdb->get_results(„SELECT * FROM $table ORDER BY created_at DESC“, ARRAY_A);
$country_stats = $wpdb->get_results(„SELECT country, COUNT(*) as c FROM $table GROUP BY country ORDER BY c DESC“, ARRAY_A);

$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$primary = $options[‚primary_color‘] ?? ‚#b87333‘;

$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
$ws = $spreadsheet->getActiveSheet();
$ws->setTitle(„Einwilligungen“);

$headers = [‚ID‘,’Datum‘,’E-Mail‘,’Telefon‘,’Adresse‘,’PLZ‘,’Stadt‘,’Land‘];
$col = ‚A‘;
foreach ($headers as $h) {
$ws->setCellValue($col.’1′, $h);
$ws->getStyle($col.’1′)->applyFromArray([
‚font‘ => [‚bold‘ => true, ‚color‘ => [‚rgb‘ => ‚FFFFFF‘]],
‚fill‘ => [‚fillType‘ => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, ’startColor‘ => [‚rgb‘ => str_replace(‚#‘,“,$primary)]],
‚borders‘ => [‚bottom‘ => [‚borderStyle‘ => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_MEDIUM]],
]);
$col++;
}

$rowIndex = 2;
foreach ($rows as $r) {
$ws->setCellValue(„A$rowIndex“, $r[‚id‘]);
$ws->setCellValue(„B$rowIndex“, $r[‚created_at‘]);
$ws->setCellValue(„C$rowIndex“, $r[‚email‘]);
$ws->setCellValue(„D$rowIndex“, $r[‚phone‘]);
$ws->setCellValue(„E$rowIndex“, $r[‚address‘]);
$ws->setCellValue(„F$rowIndex“, $r[‚zip‘]);
$ws->setCellValue(„G$rowIndex“, $r[‚city‘]);
$ws->setCellValue(„H$rowIndex“, $r[‚country‘]);
$rowIndex++;
}

$ws->setAutoFilter(„A1:H1“);
foreach (range(‚A‘,’H‘) as $c) {
$ws->getColumnDimension($c)->setAutoSize(true);
}

$chartSheet = $spreadsheet->createSheet();
$chartSheet->setTitle(‚Länder-Stats‘);
$chartSheet->setCellValue(‚A1‘, ‚Land‘);
$chartSheet->setCellValue(‚B1‘, ‚Anzahl‘);
$r = 2;
foreach ($country_stats as $cs) {
$chartSheet->setCellValue(„A$r“, $cs[‚country‘]);
$chartSheet->setCellValue(„B$r“, (int)$cs[‚c‘]);
$r++;
}

$dataSeriesLabels = [
new \PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues(‚String‘, ‚Länder-Stats!$B$1‘, null, 1),
];
$xAxisTickValues = [
new \PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues(‚String‘, ‚Länder-Stats!$A$2:$A$‘.($r-1), null, $r-2),
];
$dataSeriesValues = [
new \PhpOffice\PhpSpreadsheet\Chart\DataSeriesValues(‚Number‘, ‚Länder-Stats!$B$2:$B$‘.($r-1), null, $r-2),
];

$series = new \PhpOffice\PhpSpreadsheet\Chart\DataSeries(
\PhpOffice\PhpSpreadsheet\Chart\DataSeries::TYPE_PIECHART,
null,
range(0, count($dataSeriesValues)-1),
$dataSeriesLabels,
$xAxisTickValues,
$dataSeriesValues
);
$plotArea = new \PhpOffice\PhpSpreadsheet\Chart\PlotArea(null, [$series]);
$legend = new \PhpOffice\PhpSpreadsheet\Chart\Legend(\PhpOffice\PhpSpreadsheet\Chart\Legend::POSITION_RIGHT, null, false);
$title = new \PhpOffice\PhpSpreadsheet\Chart\Title(‚Einwilligungen pro Land‘);

$chart = new \PhpOffice\PhpSpreadsheet\Chart\Chart(
‚country_chart‘,
$title,
$legend,
$plotArea
);
$chart->setTopLeftPosition(‚D2‘);
$chart->setBottomRightPosition(‚L20‘);
$chartSheet->addChart($chart);

$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
$writer->setIncludeCharts(true);
$writer->save($path);
}

function bgc_export_zip() {
if (!class_exists(‚ZipArchive‘)) {
wp_die(‚ZipArchive nicht verfügbar.‘);
}

$upload_dir = wp_upload_dir();
$tmp_dir = trailingslashit($upload_dir[‚basedir‘]) . ‚blockgoldcoin_export/‘;
if (!file_exists($tmp_dir)) {
wp_mkdir_p($tmp_dir);
}

$csv_path = $tmp_dir . ‚einwilligungen.csv‘;
$pdf_path = $tmp_dir . ‚einwilligungen.pdf‘;
$xlsx_path = $tmp_dir . ‚einwilligungen.xlsx‘;
$zip_path = $tmp_dir . ‚blockgoldcoin_export_bundle.zip‘;

bgc_generate_csv_file($csv_path);
bgc_generate_pdf_file($pdf_path);
bgc_generate_xlsx_file($xlsx_path);

$zip = new ZipArchive();
if ($zip->open($zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
$zip->addFile($csv_path, ‚einwilligungen.csv‘);
$zip->addFile($pdf_path, ‚einwilligungen.pdf‘);
$zip->addFile($xlsx_path, ‚einwilligungen.xlsx‘);
$zip->close();
} else {
wp_die(‚Konnte ZIP nicht erstellen.‘);
}

header(‚Content-Type: application/zip‘);
header(‚Content-Disposition: attachment; filename=“blockgoldcoin_export_bundle.zip“‚);
header(‚Content-Length: ‚ . filesize($zip_path));
readfile($zip_path);
exit;
}

/* ———- AUDIT REPORT PDF ———- */

function bgc_export_audit_report_pdf() {
global $wpdb;
$table = $wpdb->prefix . BlockGoldCoin_Consent::TABLE_CONSENT;

require_once plugin_dir_path(__FILE__) . ‚tcpdf/tcpdf.php‘;

$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$primary = $options[‚primary_color‘] ?? ‚#b87333‘;
$accent = $options[‚accent_color‘] ?? ‚#facc15‘;

$total = (int) $wpdb->get_var(„SELECT COUNT(*) FROM $table“);
$today = (int) $wpdb->get_var($wpdb->prepare(
„SELECT COUNT(*) FROM $table WHERE DATE(created_at) = %s“,
current_time(‚Y-m-d‘)
));
$last7 = (int) $wpdb->get_var($wpdb->prepare(
„SELECT COUNT(*) FROM $table WHERE created_at >= %s“,
date(‚Y-m-d 00:00:00‘, strtotime(‚-7 days‘))
));
$countries_raw = $wpdb->get_results(„
SELECT country, COUNT(*) as c
FROM $table
GROUP BY country
ORDER BY c DESC
LIMIT 10
„, ARRAY_A);

$upload_dir = wp_upload_dir();
$dir = trailingslashit($upload_dir[‚basedir‘]) . ‚blockgoldcoin_daily/‘;
$files = file_exists($dir) ? glob($dir . ‚blockgoldcoin_export_*.zip‘) : [];
rsort($files);
$files = array_slice($files, 0, 20);

$pdf = new TCPDF(‚P‘, ‚mm‘, ‚A4‘, true, ‚UTF-8‘, false);
$pdf->SetCreator(‚BlockGoldCoin‘);
$pdf->SetAuthor(‚BlockGoldCoin‘);
$pdf->SetTitle(‚BlockGoldCoin Audit Report‘);
$pdf->SetMargins(10, 20, 10);
$pdf->AddPage();

$logo_svg = ‚ ‚;
$pdf->ImageSVG(‚@‘ . $logo_svg, 10, 10, 20, 20);
$pdf->SetFont(‚helvetica‘, ‚B‘, 18);
$pdf->Cell(0, 10, ‚BlockGoldCoin – Audit Report‘, 0, 1, ‚C‘);
$pdf->SetFont(‚helvetica‘, “, 10);
$pdf->Cell(0, 6, ‚Generiert: ‚ . current_time(‚mysql‘), 0, 1, ‚R‘);

$pdf->Ln(4);
$pdf->SetFont(‚helvetica‘, ‚B‘, 12);
$pdf->Cell(0, 8, ‚1. Übersicht‘, 0, 1);
$pdf->SetFont(‚helvetica‘, “, 10);
$pdf->writeHTML(‚

  • Gesamtanzahl Einwilligungen: ‚.$total.‘
  • Heute: ‚.$today.‘
  • Letzte 7 Tage: ‚.$last7.‘

‚, true, false, false, false, “);

$pdf->Ln(2);
$pdf->SetFont(‚helvetica‘, ‚B‘, 12);
$pdf->Cell(0, 8, ‚2. Einwilligungen nach Ländern (Top 10)‘, 0, 1);
$pdf->SetFont(‚helvetica‘, “, 10);
$tbl_c = ‚

‚;
foreach ($countries_raw as $row) {
$tbl_c .= ‚

‚;
}
$tbl_c .= ‚

Land Anzahl
‚.esc_html($row[‚country‘]).‘ ‚.(int)$row[‚c‘].‘

‚;
$pdf->writeHTML($tbl_c, true, false, false, false, “);

$pdf->AddPage();
$pdf->SetFont(‚helvetica‘, ‚B‘, 12);
$pdf->Cell(0, 8, ‚3. Exporte (ZIP-Bundles)‘, 0, 1);

if (!$files) {
$pdf->SetFont(‚helvetica‘, “, 10);
$pdf->Cell(0, 6, ‚Keine Export-Dateien gefunden.‘, 0, 1);
} else {
$pdf->SetFont(‚helvetica‘, “, 10);
$tbl_e = ‚

‚;
foreach ($files as $file) {
$basename = basename($file);
$date = date(‚Y-m-d H:i‘, filemtime($file));
$size_mb = number_format(filesize($file) / 1024 / 1024, 2);
$tbl_e .= ‚

‚;
}
$tbl_e .= ‚

Datei Datum Größe (MB)
‚.$basename.‘ ‚.$date.‘ ‚.$size_mb.‘

‚;
$pdf->writeHTML($tbl_e, true, false, false, false, “);
}

$pdf->Output(‚blockgoldcoin_audit_report.pdf‘, ‚D‘);
exit;
}

/* ———- TÄGLICHER CRON-EXPORT ———- */

function bgc_run_daily_export() {
$upload_dir = wp_upload_dir();
$dir = trailingslashit($upload_dir[‚basedir‘]) . ‚blockgoldcoin_daily/‘;
$url = trailingslashit($upload_dir[‚baseurl‘]) . ‚blockgoldcoin_daily/‘;

if (!file_exists($dir)) {
wp_mkdir_p($dir);
}

$date = date(‚Y-m-d‘);
$csv_path = $dir . „einwilligungen_$date.csv“;
$pdf_path = $dir . „einwilligungen_$date.pdf“;
$xlsx_path = $dir . „einwilligungen_$date.xlsx“;
$zip_path = $dir . „blockgoldcoin_export_$date.zip“;

bgc_generate_csv_file($csv_path);
bgc_generate_pdf_file($pdf_path);
bgc_generate_xlsx_file($xlsx_path);

$zip = new ZipArchive();
if ($zip->open($zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
$zip->addFile($csv_path, „einwilligungen_$date.csv“);
$zip->addFile($pdf_path, „einwilligungen_$date.pdf“);
$zip->addFile($xlsx_path, „einwilligungen_$date.xlsx“);
$zip->close();
}

$options = get_option(BlockGoldCoin_Consent::OPTION_NAME);
$notify_email = $options[’notify_email‘] ?? get_option(‚admin_email‘);
$relative_file_path = ‚blockgoldcoin_daily/blockgoldcoin_export_‘ . $date . ‚.zip‘;
$download_link = bgc_generate_signed_download_link($relative_file_path);

$msg = „Der tägliche BlockGoldCoin Export wurde erstellt.\n\nDownload (signierter Link):\n$download_link\n\nZeit: $date“;
wp_mail($notify_email, ‚BlockGoldCoin – Täglicher Export‘, $msg);

if (!empty($options[‚webhook_export_url‘])) {
wp_remote_post($options[‚webhook_export_url‘], [
‚timeout‘ => 8,
‚headers‘ => [‚Content-Type‘ => ‚application/json; charset=utf-8‘],
‚body‘ => wp_json_encode([
‚type‘ => ‚daily_export‘,
‚date‘ => $date,
‚zip_url‘ => $download_link,
]),
]);
}

$retention_days = isset($options[‚retention_days‘]) ? (int)$options[‚retention_days‘] : 14;
$retention_days = max(1, $retention_days);

foreach (glob($dir . „*.zip“) as $file) {
if (filemtime($file) < strtotime("-{$retention_days} days")) { unlink($file); } } } /* ---------- ADMIN-SEITE: EXPORT-LISTE ---------- */ add_action('admin_menu', function() { add_submenu_page( 'bgc-consent-export', 'BlockGoldCoin Exporte', 'Exporte', 'manage_options', 'bgc-consent-exports', 'bgc_render_exports_page' ); }); function bgc_render_exports_page() { $upload_dir = wp_upload_dir(); $dir = trailingslashit($upload_dir['basedir']) . 'blockgoldcoin_daily/'; $url = trailingslashit($upload_dir['baseurl']) . 'blockgoldcoin_daily/'; echo '

BlockGoldCoin – Exporte

‚;

if (!file_exists($dir)) {
echo ‚

Noch keine Exporte vorhanden.

‚;
return;
}

$files = glob($dir . ‚blockgoldcoin_export_*.zip‘);
rsort($files);

if (!$files) {
echo ‚

Noch keine Export-Dateien vorhanden.

‚;
return;
}

echo ‚

‚;

foreach ($files as $file) {
$basename = basename($file);
$date = date(‚Y-m-d H:i‘, filemtime($file));
$size = filesize($file);
$size_mb = number_format($size / 1024 / 1024, 2) . ‚ MB‘;
$relative = ‚blockgoldcoin_daily/‘.$basename;
$link = bgc_generate_signed_download_link($relative);

echo ‚

‚;
}

echo ‚

Datei Datum Größe Download
‚.esc_html($basename).‘ ‚.esc_html($date).‘ ‚.esc_html($size_mb).‘ Download

‚;
}

/* ———- REST-API: PUBLIC STATS + CHART DATA + PARTNER STATS ———- */

add_action(‚rest_api_init‘, function() {
register_rest_route(‚blockgoldcoin/v1‘, ‚/public-stats‘, [
‚methods‘ => ‚GET‘,
‚callback‘ => ‚bgc_rest_get_public_stats‘,
‚permission_callback‘ => ‚__return_true‘,
]);

register_rest_route(‚blockgoldcoin/v1‘, ‚/chart-data‘, [
‚methods‘ => ‚GET‘,
‚callback‘ => ‚bgc_rest_get_chart_data‘,
‚permission_callback‘ => function() {
return current_user_can(‚manage_options‘);
}
]);

register_rest_route(‚blockgoldcoin/v1‘, ‚/partner-stats‘, [
‚methods‘ => ‚GET‘,
‚callback‘ => ‚bgc_rest_partner_stats‘,
‚permission_callback‘ => ‚__return_true‘,
]);

register_rest_route(‚blockgoldcoin/v1‘, ‚/exports‘, [
‚methods‘ => ‚GET‘,
‚callback‘ => ‚bgc_rest_get_exports‘,
‚permission_callback‘ => function() {
return current_user_can(‚manage_options‘);
}
]);
});

function bgc_rest_get_public_stats(WP_REST_Request $request) {
global $wpdb;
$table = $wpdb->prefix . BlockGoldCoin_Consent::TABLE_CONSENT;

$total = (int) $wpdb->get_var(„SELECT COUNT(*) FROM $table“);
$today = (int) $wpdb->get_var($wpdb->prepare(
„SELECT COUNT(*) FROM $table WHERE DATE(created_at) = %s“,
current_time(‚Y-m-d‘)
));
$last7 = (int) $wpdb->get_var($wpdb->prepare(
„SELECT COUNT(*) FROM $table WHERE created_at >= %s“,
date(‚Y-m-d 00:00:00‘, strtotime(‚-7 days‘))
));

$days = [];
$counts = [];
for ($i = 13; $i >= 0; $i–) {
$d = date(‚Y-m-d‘, strtotime(„-$i days“));
$c = (int)$wpdb->get_var($wpdb->prepare(
„SELECT COUNT(*) FROM $table WHERE DATE(created_at) = %s“,
$d
));
$days[] = $d;
$counts[] = $c;
}

$countries_raw = $wpdb->get_results(„
SELECT country, COUNT(*) as c
FROM $table
GROUP BY country
ORDER BY c DESC
LIMIT 10
„, ARRAY_A);

$countries = [];
$country_counts = [];
foreach ($countries_raw as $row) {
$countries[] = $row[‚country‘];
$country_counts[] = (int)$row[‚c‘];
}

return [
‚total‘ => $total,
‚today‘ => $today,
‚last7‘ => $last7,
‚days‘ => $days,
‚counts‘ => $counts,
‚countries‘ => $countries,
‚country_counts‘ => $country_counts,
‚generated_at‘ => current_time(‚mysql‘),
];
}

function bgc_rest_get_chart_data(WP_REST_Request $request) {
return bgc_rest_get_public_stats($request);
}

function bgc_rest_get_exports(WP_REST_Request $request) {
$upload_dir = wp_upload_dir();
$dir = trailingslashit($upload_dir[‚basedir‘]) . ‚blockgoldcoin_daily/‘;
$url = trailingslashit($upload_dir[‚baseurl‘]) . ‚blockgoldcoin_daily/‘;

if (!file_exists($dir)) return [];

$files = glob($dir . ‚blockgoldcoin_export_*.zip‘);
rsort($files);
$data = [];
foreach ($files as $file) {
$basename = basename($file);
$data[] = [
‚file‘ => $basename,
‚date‘ => date(‚Y-m-d H:i:s‘, filemtime($file)),
’size‘ => filesize($file),
’size_mb‘ => (float) number_format(filesize($file) / 1024 / 1024, 2),
‚url‘ => bgc_generate_signed_download_link(‚blockgoldcoin_daily/‘.$basename),
];
}
return $data;
}

/* ———- TOKEN & LOGGING ———- */

function bgc_create_token($partner_name, $days_valid = 30) {
global $wpdb;
$table = $wpdb->prefix . BlockGoldCoin_Consent::TABLE_TOKENS;

$token_raw = wp_generate_password(32, false, false);
$expires = date(‚Y-m-d H:i:s‘, strtotime(„+$days_valid days“));

$wpdb->insert($table, [
‚partner_name‘ => $partner_name,
‚token‘ => $token_raw,
‚expires_at‘ => $expires,
‚active‘ => 1,
‚created_at‘ => current_time(‚mysql‘),
]);

return $token_raw;
}

function bgc_auth_partner_token($token_raw) {
global $wpdb;
$table = $wpdb->prefix . BlockGoldCoin_Consent::TABLE_TOKENS;

$row = $wpdb->get_row($wpdb->prepare(
„SELECT * FROM $table WHERE token = %s LIMIT 1“,
$token_raw
));

if (!$row) return false;
if (!$row->active) return false;
if (time() > strtotime($row->expires_at)) return false;

return $row;
}

function bgc_log_partner_access($token_id, $endpoint) {
global $wpdb;
$table = $wpdb->prefix . BlockGoldCoin_Consent::TABLE_LOGS;

$wpdb->insert($table, [
‚token_id‘ => $token_id,
‚endpoint‘ => $endpoint,
‚ip‘ => $_SERVER[‚REMOTE_ADDR‘] ?? ‚unknown‘,
‚created_at‘ => current_time(‚mysql‘),
]);
}

/* ———- PARTNER STATS (TOKEN-AUTH) ———- */

function bgc_rest_partner_stats(WP_REST_Request $request) {
$auth = $request->get_header(‚authorization‘);
if (!$auth || stripos($auth, ‚bearer ‚) !== 0) {
return new WP_REST_Response([‚error‘ => ‚missing_token‘], 401);
}

$token_raw = trim(substr($auth, 7));
$token = bgc_auth_partner_token($token_raw);
if (!$token) {
return new WP_REST_Response([‚error‘ => ‚invalid_or_expired_token‘], 403);
}

bgc_log_partner_access($token->id, ‚partner-stats‘);
return bgc_rest_get_public_stats($request);
}

/* ———- ADMIN: TOKEN MANAGER & PARTNER LOGS ———- */

add_action(‚admin_menu‘, function() {
add_submenu_page(
‚bgc-consent-export‘,
‚Token Manager‘,
‚Token Manager‘,
‚manage_options‘,
‚bgc-token-manager‘,
‚bgc_render_token_manager‘
);
add_submenu_page(
‚bgc-consent-export‘,
‚Partner Logs‘,
‚Partner Logs‘,
‚manage_options‘,
‚bgc-partner-logs‘,
‚bgc_render_partner_logs‘
);
add_submenu_page(
‚bgc-consent-export‘,
‚BlockGoldCoin Live Monitor‘,
‚Live Monitor‘,
‚manage_options‘,
‚bgc-consent-live-monitor‘,
‚bgc_render_live_monitor_page‘
);
});

function bgc_render_token_manager() {
global $wpdb;
$table = $wpdb->prefix . BlockGoldCoin_Consent::TABLE_TOKENS;

if (isset($_POST[‚bgc_new_token‘])) {
$partner = sanitize_text_field($_POST[‚partner_name‘]);
$days = (int)$_POST[‚valid_days‘];
$token = bgc_create_token($partner, $days);
echo ‚

Neues Token erzeugt: ‚ . esc_html($token) . ‚

‚;
}

if (isset($_GET[‚toggle‘])) {
$id = (int)$_GET[‚toggle‘];
$wpdb->query(„UPDATE $table SET active = 1 – active WHERE id = $id“);
}

if (isset($_GET[‚delete‘])) {
$id = (int)$_GET[‚delete‘];
$wpdb->delete($table, [‚id‘ => $id]);
}

$tokens = $wpdb->get_results(„SELECT * FROM $table ORDER BY created_at DESC“);
?>

BlockGoldCoin – Token Manager

Neues Token erzeugen




Bestehende Tokens


ID Partner Token Ablaufdatum Status Aktionen
id; ?> partner_name); ?> token); ?> expires_at); ?> active ? ‚Aktiv‘ : ‚Gesperrt‘; ?> id; ?>“ class=“button button-danger“
onclick=“return confirm(‚Token wirklich löschen?‘);“>
Löschen

prefix . BlockGoldCoin_Consent::TABLE_LOGS;
$table_tokens = $wpdb->prefix . BlockGoldCoin_Consent::TABLE_TOKENS;

$logs = $wpdb->get_results(„
SELECT l.*, t.partner_name
FROM $table_logs l
LEFT JOIN $table_tokens t ON t.id = l.token_id
ORDER BY l.created_at DESC
LIMIT 200
„);
?>

BlockGoldCoin – Partner Logs


Zeit Partner Endpoint IP
created_at); ?> partner_name); ?> endpoint); ?> ip); ?>

BlockGoldCoin – Live Monitor

Realtime-Übersicht der Einwilligungen (letzte 14 Tage & Top-Länder).

Einwilligungen – letzte 14 Tage

Einwilligungen pro Land

Daten werden automatisch aktualisiert.



prefix . BlockGoldCoin_Consent::TABLE_CONSENT;

$total = (int) $wpdb->get_var(„SELECT COUNT(*) FROM $table“);

$days = [];
$counts = [];
for ($i = 6; $i >= 0; $i–) {
$d = date(‚Y-m-d‘, strtotime(„-$i days“));
$c = (int)$wpdb->get_var($wpdb->prepare(
„SELECT COUNT(*) FROM $table WHERE DATE(created_at) = %s“,
$d
));
$days[] = $d;
$counts[] = $c;
}

echo ‚

Gesamt: ‚.$total.‘

‚;
echo ‚‚;
?>


“,
], $atts, ‚blockgoldcoin_partner_dashboard‘);

if (empty($atts[‚token‘])) {
return ‚

Token fehlt.

‚;
}

ob_start();
?>

BlockGoldCoin – Partner Dashboard

Aggregierte Einwilligungs-Statistiken (readonly).

Einwilligungen (letzte 14 Tage)

Einwilligungen nach Ländern



<div class="bgc-box">
  <h3>BlockGoldCoin – Sicherheit & Governance</h3>
  <p>
    Dieses Modul steht für Transparenz, Schutz und die stabile Governance-Struktur
    des BlockGoldCoin-Ökosystems.
  </p>
  <img 
    src="http://blockgoldcoin.com/wp-content/uploads/2025/02/BGC-Finanzschutz-Governance-transparent-e1766687863588.png"
    alt="BlockGoldCoin Finanzschutz- und Governance-Symbol"
    width="180"
  />
</div>
<section class="bgc-template-part">
  <div class="container">
    <h2>BlockGoldCoin – Modulbereich</h2>
    <p>
      Dieser Template‑Teil kann für wiederkehrende Inhalte wie Banner, Hinweise,
      Module oder Informationsboxen verwendet werden.
    </p>

    <div class="bgc-box">
      <img 
        src="http://blockgoldcoin.com/wp-content/uploads/2025/02/BGC-Finanzschutz-Governance-transparent-e1766687863588.png"
        alt="BlockGoldCoin Finanzschutz- und Governance-Symbol"
        width="140"
      />
      <p>
        Finanzschutz & Governance – zentrales Element des BlockGoldCoin‑Ökosystems.
      </p>
    </div>
  </div>
</section>
Zelle 1
Zelle 2
Zelle 3
Zelle 4
Sample Page
Dies ist eine Beispielseite innerhalb der BlockGoldCoin‑Website. Sie dient als Vorlage für neue Inhalte, Module oder Layout‑Tests.
BlockGoldCoin Modul
Hier kannst du Text, Bilder, Tabellen oder weitere Elemente einfügen, um die Seite nach deinen Anforderungen aufzubauen.
Geschichten aus dem BlockGoldCoin‑Ökosystem · entwickelt für SAFEARTH und die Finanzzukunft.Sample Page
Dies ist die zweite Beispielseite deiner BlockGoldCoin‑Website. Hier kannst du neue Inhalte, Module oder Layout‑Tests einfügen. BlockGoldCoin Bereich
Dieser Abschnitt kann für Informationen, Bilder oder Tabellen genutzt werden.

BlockGoldCoin (BGC)

Weiterlesen: Beitrag 2068 ohne Titel