‚;
$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 = ‚
ID
Datum
E-Mail
Telefon
Stadt
Land
‚;
foreach ($rows as $r) {
$tbl .= ‚
‚ . $r[‚id‘] . ‚
‚ . $r[‚created_at‘] . ‚
‚ . $r[‚email‘] . ‚
‚ . $r[‚phone‘] . ‚
‚ . $r[‚city‘] . ‚
‚ . $r[‚country‘] . ‚
‚;
}
$tbl .= ‚
‚;
$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 = ‚
ID
Datum
E-Mail
Telefon
Stadt
Land
‚;
foreach ($rows as $r) {
$tbl .= ‚
‚.$r[‚id‘].‘
‚.$r[‚created_at‘].‘
‚.$r[‚email‘].‘
‚.$r[‚phone‘].‘
‚.$r[‚city‘].‘
‚.$r[‚country‘].‘
‚;
}
$tbl .= ‚
‚;
$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 ‚
Datei
Datum
Größe
Download
‚;
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 ‚
‚ . esc_html($basename) . ‚
‚ . esc_html($date) . ‚
‚ . esc_html($size_mb) . ‚
Download
‚;
}
echo ‚
‚;
}
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
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 = ‚
Land
Anzahl
‚;
foreach ($countries_raw as $row) {
$tbl_c .= ‚
‚ . esc_html($row[‚country‘]) . ‚
‚ . (int)$row[‚c‘] . ‚
‚;
}
$tbl_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 = ‚
Datei
Datum
Größe (MB)
‚;
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 .= ‚
‚ . $basename . ‚
‚ . $date . ‚
‚ . $size_mb . ‚
‚;
}
$tbl_e .= ‚
‚;
$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
require_once ABSPATH . ‚wp-admin/includes/upgrade.php‘;
dbDelta($sql1);
dbDelta($sql2);
}
$tokens = $wpdb->get_results(„SELECT * FROM $table ORDER BY created_at DESC“);
prefix . ‚bgc_tokens‘;
prefix . self::TABLE_CONSENT;
wp_safe_redirect(add_query_arg(‚bgc_consent‘, ‚ok‘, wp_get_referer() ?: home_url()));
exit;
}
$lang = isset($_GET[‚lang‘]) ? sanitize_text_field($_GET[‚lang‘]) : ‚de‘;