403Webshell
Server IP : 202.61.199.114  /  Your IP : 216.73.217.139
Web Server : nginx/1.22.1
System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64
User : web20 ( 1018)
PHP Version : 8.4.23
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /var/www/seaside.pacim.de/web/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/seaside.pacim.de/web//zufriedenheit-api.php
<?php
/**
 * zufriedenheit-api.php – Admin-Auswertung der Kundenzufriedenheits-Umfrage (pacim_survey).
 * Nur Admins (is_admin).
 *
 *  action=list      GET  [rating=all|pos|neg, q, limit, offset]
 *                        -> { ok, surveys:[...], total, stats:{...} }
 *  action=get       GET  id                 -> { ok, survey:{... + booking/customer} }  (markiert gelesen)
 *  action=delete    POST id                 -> { ok }
 *  action=bookings  GET  q                   -> { ok, bookings:[{...,link,hasSurvey}] }  (Link erzeugen)
 */
require_once( __DIR__ . '/includes/config.inc.php' );
require_once( __DIR__ . '/includes/survey.php' );
@ini_set( 'display_errors', '0' );
error_reporting( 0 );
ob_start();

function sv_json( $a ) { while ( ob_get_level() > 0 ) ob_end_clean(); header( 'Content-Type: application/json; charset=utf-8' ); echo json_encode( $a ); exit(); }
function sv_fail( $m ) { sv_json( array( 'ok' => false, 'error' => $m ) ); }

if ( ! function_exists( 'is_admin' ) || ! is_admin() ) { http_response_code( 403 ); sv_fail( 'forbidden' ); }

$action = isset( $_GET['action'] ) ? $_GET['action'] : ( isset( $_POST['action'] ) ? $_POST['action'] : '' );
$db     = new MysqliDb( MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB );
$db->rawQuery( "SET NAMES utf8mb4" );
pacim_survey_ensure( $db );
pacim_survey_aspects_ensure( $db );

$ASPECTS = pacim_survey_aspects( $db );

/* --------------------------------------------------------------- LISTE + STATISTIK */
if ( $action === 'list' ) {
    $scope  = (string) ( $_GET['scope'] ?? 'all' );
    if ( ! in_array( $scope, array( 'all', 'customer', 'general' ), true ) ) $scope = 'all';
    $rating = (string) ( $_GET['rating'] ?? 'all' );
    $q      = trim( (string) ( $_GET['q'] ?? '' ) );
    $limit  = min( 200, max( 1, (int) ( $_GET['limit'] ?? 100 ) ) );
    $offset = max( 0, (int) ( $_GET['offset'] ?? 0 ) );

    pacim_survey_general_ensure( $db );
    $wantCust = ( $scope !== 'general' );
    $wantGen  = ( $scope !== 'customer' );
    $parkLbl  = array( 'halle' => 'Halle', 'aussen' => 'Außen' );

    // ---- Kundenbezogen: Rohkomponenten (über ALLE) + gefilterte Tabellenzeilen ----
    $custRaw = null; $custRows = array(); $custTot = 0;
    if ( $wantCust ) {
        $st = $db->rawQueryOne(
            "SELECT COUNT(*) n, SUM(survey_overall) ovs, SUM(survey_overall>0) ovc,
                    SUM(survey_recommend=1) ry, SUM(survey_recommend IS NOT NULL) rt,
                    SUM(survey_overall=1) d1, SUM(survey_overall=2) d2, SUM(survey_overall=3) d3,
                    SUM(survey_overall=4) d4, SUM(survey_overall=5) d5, SUM(survey_seen=0) unseen,
                    SUM(survey_a_booking) sb, SUM(survey_a_booking>0) cb,
                    SUM(survey_a_parking) sp, SUM(survey_a_parking>0) cp,
                    SUM(survey_a_service) ss, SUM(survey_a_service>0) cs,
                    SUM(survey_a_staff)   sf, SUM(survey_a_staff>0)   cf,
                    SUM(survey_a_price)   sr, SUM(survey_a_price>0)   cr
               FROM pacim_survey" );
        $asp_sum = array(); $asp_cnt = array();
        $bm = array( 'booking' => array( 'sb', 'cb' ), 'parking' => array( 'sp', 'cp' ), 'service' => array( 'ss', 'cs' ), 'staff' => array( 'sf', 'cf' ), 'price' => array( 'sr', 'cr' ) );
        foreach ( $bm as $k => $m ) { $asp_sum[ $k ] = (float) ( $st[ $m[0] ] ?? 0 ); $asp_cnt[ $k ] = (int) ( $st[ $m[1] ] ?? 0 ); }
        foreach ( (array) $db->rawQuery( "SELECT ans_key, SUM(ans_rating) s, SUM(ans_rating>0) c FROM pacim_survey_answers GROUP BY ans_key" ) as $rr ) {
            $asp_sum[ $rr['ans_key'] ] = ( $asp_sum[ $rr['ans_key'] ] ?? 0 ) + (float) $rr['s'];
            $asp_cnt[ $rr['ans_key'] ] = ( $asp_cnt[ $rr['ans_key'] ] ?? 0 ) + (int) $rr['c'];
        }
        $custRaw = array(
            'n' => (int) $st['n'], 'ovs' => (float) $st['ovs'], 'ovc' => (int) $st['ovc'],
            'ry' => (int) $st['ry'], 'rt' => (int) $st['rt'], 'unseen' => (int) $st['unseen'],
            'dist' => array( 1 => (int) $st['d1'], 2 => (int) $st['d2'], 3 => (int) $st['d3'], 4 => (int) $st['d4'], 5 => (int) $st['d5'] ),
            'asp_sum' => $asp_sum, 'asp_cnt' => $asp_cnt,
        );

        $where = array(); $params = array();
        if ( $rating === 'pos' ) { $where[] = 's.survey_overall >= 4'; }
        elseif ( $rating === 'neg' ) { $where[] = 's.survey_overall <= 2'; }
        if ( $q !== '' ) {
            $like = '%' . $q . '%';
            $where[] = '( b.booking_no LIKE ? OR c.customer_name LIKE ? OR CONCAT_WS(" ",c.customer_firstname,c.customer_lastname) LIKE ? OR b.booking_event LIKE ? OR s.survey_comment LIKE ? )';
            array_push( $params, $like, $like, $like, $like, $like );
        }
        $wsql = $where ? ( 'WHERE ' . implode( ' AND ', $where ) ) : '';
        $rows = (array) $db->rawQuery(
            "SELECT s.survey_id, s.survey_booking, s.survey_overall, s.survey_recommend, s.survey_comment,
                    s.survey_seen, s.survey_created, s.survey_updated,
                    b.booking_no, b.booking_event, b.booking_begin, b.booking_end,
                    c.customer_firstname, c.customer_lastname, c.customer_name
               FROM pacim_survey s
          LEFT JOIN pacim_booking  b ON b.booking_id  = s.survey_booking
          LEFT JOIN pacim_customer c ON c.customer_id = s.survey_customer
               $wsql
           ORDER BY COALESCE(s.survey_updated, s.survey_created) DESC
              LIMIT $limit OFFSET $offset", $params );
        foreach ( $rows as $r ) { $r['_type'] = 'customer'; $r['_ts'] = $r['survey_updated'] ?: $r['survey_created']; $custRows[] = $r; }
        $ct = $db->rawQueryOne( "SELECT COUNT(*) n FROM pacim_survey s LEFT JOIN pacim_booking b ON b.booking_id=s.survey_booking LEFT JOIN pacim_customer c ON c.customer_id=s.survey_customer $wsql", $params );
        $custTot = (int) ( $ct['n'] ?? 0 );
    }

    // ---- Terminbezogen: Rohkomponenten (über ALLE) + gefilterte Tabellenzeilen ----
    $genRaw = null; $genRows = array(); $genTot = 0;
    if ( $wantGen ) {
        $gst = $db->rawQueryOne(
            "SELECT COUNT(*) n, SUM(sg_overall) ovs, SUM(sg_overall>0) ovc,
                    SUM(sg_recommend=1) ry, SUM(sg_recommend IS NOT NULL) rt,
                    SUM(sg_overall=1) d1, SUM(sg_overall=2) d2, SUM(sg_overall=3) d3,
                    SUM(sg_overall=4) d4, SUM(sg_overall=5) d5
               FROM pacim_survey_general" );
        $gsum = array(); $gcnt = array();
        foreach ( (array) $db->rawQuery( "SELECT sg_aspects FROM pacim_survey_general" ) as $ar ) {
            $j = json_decode( (string) $ar['sg_aspects'], true );
            if ( is_array( $j ) ) foreach ( $j as $k => $v ) { $v = (int) $v; if ( $v >= 1 && $v <= 5 ) { $gsum[ $k ] = ( $gsum[ $k ] ?? 0 ) + $v; $gcnt[ $k ] = ( $gcnt[ $k ] ?? 0 ) + 1; } }
        }
        $genRaw = array(
            'n' => (int) $gst['n'], 'ovs' => (float) $gst['ovs'], 'ovc' => (int) $gst['ovc'],
            'ry' => (int) $gst['ry'], 'rt' => (int) $gst['rt'], 'unseen' => 0,
            'dist' => array( 1 => (int) $gst['d1'], 2 => (int) $gst['d2'], 3 => (int) $gst['d3'], 4 => (int) $gst['d4'], 5 => (int) $gst['d5'] ),
            'asp_sum' => $gsum, 'asp_cnt' => $gcnt,
        );

        $gwhere = array(); $gparams = array();
        if ( $rating === 'pos' ) { $gwhere[] = 'sg_overall >= 4'; }
        elseif ( $rating === 'neg' ) { $gwhere[] = 'sg_overall <= 2'; }
        if ( $q !== '' ) { $like = '%' . $q . '%'; $gwhere[] = '( sg_ship LIKE ? OR sg_comment LIKE ? )'; array_push( $gparams, $like, $like ); }
        $gwsql = $gwhere ? ( 'WHERE ' . implode( ' AND ', $gwhere ) ) : '';
        $grows = (array) $db->rawQuery(
            "SELECT sg_id, sg_session, sg_ship, sg_park, sg_overall, sg_recommend, sg_aspects, sg_comment, sg_created
               FROM pacim_survey_general $gwsql ORDER BY sg_created DESC LIMIT $limit OFFSET $offset", $gparams );
        foreach ( $grows as $r ) {
            $genRows[] = array(
                '_type' => 'general', '_ts' => $r['sg_created'],
                'sg_id' => (int) $r['sg_id'], 'session_short' => substr( (string) $r['sg_session'], 0, 8 ),
                'ship' => (string) $r['sg_ship'], 'park' => $parkLbl[ $r['sg_park'] ] ?? (string) $r['sg_park'],
                'overall' => $r['sg_overall'] !== null ? (int) $r['sg_overall'] : null,
                'recommend' => $r['sg_recommend'] !== null ? (int) $r['sg_recommend'] : null,
                'aspects' => json_decode( (string) $r['sg_aspects'], true ) ?: array(),
                'comment' => (string) $r['sg_comment'], 'created' => $r['sg_created'],
            );
        }
        $gt = $db->rawQueryOne( "SELECT COUNT(*) n FROM pacim_survey_general $gwsql", $gparams );
        $genTot = (int) ( $gt['n'] ?? 0 );
    }

    // ---- Rohkomponenten je Scope zusammenführen -> Ø-Statistik ----
    $agg = array( 'n' => 0, 'ovs' => 0, 'ovc' => 0, 'ry' => 0, 'rt' => 0, 'unseen' => 0, 'dist' => array( 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0 ), 'asp_sum' => array(), 'asp_cnt' => array() );
    foreach ( array( $custRaw, $genRaw ) as $p ) {
        if ( ! $p ) continue;
        $agg['n'] += $p['n']; $agg['ovs'] += $p['ovs']; $agg['ovc'] += $p['ovc'];
        $agg['ry'] += $p['ry']; $agg['rt'] += $p['rt']; $agg['unseen'] += $p['unseen'];
        foreach ( array( 1, 2, 3, 4, 5 ) as $d ) { $agg['dist'][ $d ] += $p['dist'][ $d ]; }
        foreach ( $p['asp_sum'] as $k => $v ) { $agg['asp_sum'][ $k ] = ( $agg['asp_sum'][ $k ] ?? 0 ) + $v; }
        foreach ( $p['asp_cnt'] as $k => $v ) { $agg['asp_cnt'][ $k ] = ( $agg['asp_cnt'][ $k ] ?? 0 ) + $v; }
    }
    $aspAvg = array();
    foreach ( array_keys( $ASPECTS ) as $k ) { $aspAvg[ $k ] = ! empty( $agg['asp_cnt'][ $k ] ) ? round( $agg['asp_sum'][ $k ] / $agg['asp_cnt'][ $k ], 2 ) : 0; }

    // ---- Tabellenzeilen je Scope (bei „Alle" mischen + nach Datum sortieren) ----
    if ( $scope === 'customer' )      { $tableRows = $custRows; $total = $custTot; }
    elseif ( $scope === 'general' )   { $tableRows = $genRows;  $total = $genTot; }
    else {
        $tableRows = array_merge( $custRows, $genRows );
        usort( $tableRows, function ( $a, $b ) { return strcmp( (string) $b['_ts'], (string) $a['_ts'] ); } );
        if ( count( $tableRows ) > $limit ) $tableRows = array_slice( $tableRows, 0, $limit );
        $total = $custTot + $genTot;
    }

    sv_json( array(
        'ok'      => true,
        'scope'   => $scope,
        'surveys' => $tableRows,
        'total'   => $total,
        'aspects' => $ASPECTS,
        'stats'   => array(
            'count'   => $agg['n'],
            'unseen'  => $agg['unseen'],
            'overall' => $agg['ovc'] ? round( $agg['ovs'] / $agg['ovc'], 2 ) : 0,
            'aspects' => $aspAvg,
            'rec_yes' => $agg['ry'],
            'rec_tot' => $agg['rt'],
            'dist'    => $agg['dist'],
        ),
    ) );
}

/* --------------------------------------------------------------- EINZELNE BEWERTUNG */
if ( $action === 'get' ) {
    $id = (int) ( $_GET['id'] ?? 0 );
    $r = $db->rawQueryOne(
        "SELECT s.*, b.booking_no, b.booking_event, b.booking_begin, b.booking_end, b.booking_invoice,
                c.customer_firstname, c.customer_lastname, c.customer_name, c.customer_email
           FROM pacim_survey s
      LEFT JOIN pacim_booking  b ON b.booking_id  = s.survey_booking
      LEFT JOIN pacim_customer c ON c.customer_id = s.survey_customer
          WHERE s.survey_id = ?", array( $id ) );
    if ( ! $r ) sv_fail( 'not_found' );
    if ( (int) $r['survey_seen'] === 0 ) { $db->where( 'survey_id', $id ); $db->update( 'pacim_survey', array( 'survey_seen' => 1 ) ); $r['survey_seen'] = 1; }
    $r['aspects'] = $ASPECTS;
    // Custom-Bereich-Bewertungen unter survey_a_<key> spiegeln, damit das Frontend sie einheitlich liest.
    foreach ( (array) $db->rawQuery( "SELECT ans_key, ans_rating FROM pacim_survey_answers WHERE ans_survey = ?", array( $id ) ) as $a ) {
        $r[ 'survey_a_' . $a['ans_key'] ] = $a['ans_rating'];
    }
    sv_json( array( 'ok' => true, 'survey' => $r ) );
}

/* --------------------------------------------------------------- LÖSCHEN */
if ( $action === 'delete' ) {
    $id = (int) ( $_POST['id'] ?? 0 );
    if ( $id <= 0 ) sv_fail( 'bad_id' );
    $db->where( 'survey_id', $id );
    $db->delete( 'pacim_survey' );
    $db->rawQuery( "DELETE FROM pacim_survey_answers WHERE ans_survey = ?", array( $id ) );
    sv_json( array( 'ok' => true ) );
}

/* --------------------------------------------------------------- EINSTELLUNGEN: BEWERTUNGSBEREICHE */
if ( $action === 'aspects' ) {
    sv_json( array( 'ok' => true, 'aspects' => array_values( pacim_survey_aspects_all( $db ) ) ) );
}

if ( $action === 'aspect_add' ) {
    $label = mb_substr( trim( (string) ( $_POST['label'] ?? '' ) ), 0, 191 );
    if ( $label === '' ) sv_fail( 'label' );
    pacim_survey_aspects_ensure( $db );
    // Eindeutigen Key (Slug) erzeugen – keine Kollision mit eingebauten/vorhandenen Keys.
    $base = trim( preg_replace( '/[^a-z0-9]+/', '_', strtolower( $label ) ), '_' );
    if ( $base === '' ) $base = 'bereich';
    $base = substr( $base, 0, 30 );
    $key = $base; $n = 1;
    while ( pacim_survey_aspect_is_builtin( $key ) || $db->rawQueryOne( "SELECT aspect_id FROM pacim_survey_aspects WHERE aspect_key = ?", array( $key ) ) ) {
        $key = substr( $base, 0, 28 ) . '_' . ( ++$n );
    }
    $mx = $db->rawQueryOne( "SELECT COALESCE(MAX(aspect_sort),0) AS mx FROM pacim_survey_aspects" );
    $id = $db->insert( 'pacim_survey_aspects', array(
        'aspect_key' => $key, 'aspect_label' => $label, 'aspect_sort' => (int) ( $mx['mx'] ?? 0 ) + 10,
        'aspect_active' => 1, 'aspect_builtin' => 0, 'aspect_created' => date( 'Y-m-d H:i:s' ),
    ) );
    sv_json( array( 'ok' => (bool) $id, 'id' => (int) $id, 'key' => $key ) );
}

if ( $action === 'aspect_update' ) {
    $id = (int) ( $_POST['id'] ?? 0 );
    if ( $id <= 0 ) sv_fail( 'bad_id' );
    if ( ! $db->rawQueryOne( "SELECT aspect_id FROM pacim_survey_aspects WHERE aspect_id = ?", array( $id ) ) ) sv_fail( 'not_found' );
    $upd = array();
    if ( isset( $_POST['label'] ) ) { $lab = trim( (string) $_POST['label'] ); if ( $lab === '' ) sv_fail( 'label' ); $upd['aspect_label'] = mb_substr( $lab, 0, 191 ); }
    if ( isset( $_POST['active'] ) ) $upd['aspect_active'] = ( (int) $_POST['active'] ? 1 : 0 );
    if ( $upd ) { $db->where( 'aspect_id', $id ); $db->update( 'pacim_survey_aspects', $upd ); }
    sv_json( array( 'ok' => true ) );
}

if ( $action === 'aspect_delete' ) {
    $id = (int) ( $_POST['id'] ?? 0 );
    if ( $id <= 0 ) sv_fail( 'bad_id' );
    $row = $db->rawQueryOne( "SELECT aspect_key, aspect_builtin FROM pacim_survey_aspects WHERE aspect_id = ?", array( $id ) );
    if ( ! $row ) sv_fail( 'not_found' );
    if ( (int) $row['aspect_builtin'] === 1 ) sv_fail( 'builtin' ); // eingebaute Bereiche nur deaktivierbar, nicht löschbar
    $db->where( 'aspect_id', $id ); $db->delete( 'pacim_survey_aspects' );
    $db->rawQuery( "DELETE FROM pacim_survey_answers WHERE ans_key = ?", array( $row['aspect_key'] ) );
    sv_json( array( 'ok' => true ) );
}

if ( $action === 'aspects_reorder' ) {
    $ids = $_POST['order'] ?? '';
    if ( is_string( $ids ) ) $ids = json_decode( $ids, true );
    if ( ! is_array( $ids ) ) sv_fail( 'order' );
    $sort = 0;
    foreach ( $ids as $aid ) { $sort += 10; $db->where( 'aspect_id', (int) $aid ); $db->update( 'pacim_survey_aspects', array( 'aspect_sort' => $sort ) ); }
    sv_json( array( 'ok' => true ) );
}

/* --------------------------------------------------------------- BUCHUNGEN SUCHEN (Link erzeugen) */
if ( $action === 'bookings' ) {
    $q = trim( (string) ( $_GET['q'] ?? '' ) );
    if ( mb_strlen( $q ) < 2 ) sv_json( array( 'ok' => true, 'bookings' => array() ) );
    $like = '%' . $q . '%';
    $rows = (array) $db->rawQuery(
        "SELECT b.booking_id, b.booking_no, b.booking_event, b.booking_begin, b.booking_end,
                c.customer_firstname, c.customer_lastname, c.customer_name,
                i.invoice_no, license_plate(b.booking_serial) AS plate,
                (SELECT sv.survey_id FROM pacim_survey sv WHERE sv.survey_booking = b.booking_id) AS survey_id
           FROM pacim_booking b
      LEFT JOIN pacim_customer c ON c.customer_id = b.booking_customer
      LEFT JOIN pacim_invoice  i ON i.invoice_id  = b.booking_invoice
          WHERE b.booking_no LIKE ? OR i.invoice_no LIKE ? OR c.customer_name LIKE ?
                OR CONCAT_WS(' ', c.customer_firstname, c.customer_lastname) LIKE ?
                OR license_plate(b.booking_serial) LIKE ?
       ORDER BY b.booking_id DESC LIMIT 25",
        array( $like, $like, $like, $like, $like ) );

    $out = array();
    foreach ( $rows as $r ) {
        $out[] = array(
            'booking_id' => (int) $r['booking_id'],
            'booking_no' => (string) $r['booking_no'],
            'invoice_no' => (string) $r['invoice_no'],
            'ship'       => (string) $r['booking_event'],
            'plate'      => (string) $r['plate'],
            'name'       => trim( (string) $r['customer_firstname'] . ' ' . (string) $r['customer_lastname'] ) ?: (string) $r['customer_name'],
            'begin'      => (string) $r['booking_begin'],
            'end'        => (string) $r['booking_end'],
            'hasSurvey'  => ! empty( $r['survey_id'] ),
            'link'       => pacim_survey_link( (int) $r['booking_id'] ),
        );
    }
    sv_json( array( 'ok' => true, 'bookings' => $out ) );
}

/* --------------------------------------------------------------- ANALYSE-TAB (Filter-Optionen) */
if ( $action === 'analyse_meta' ) {
    require_once( __DIR__ . '/includes/survey-analyse.php' );
    sv_json( array( 'ok' => true, 'meta' => pacim_sa_meta( $db ) ) );
}

/* --------------------------------------------------------------- ANALYSE-TAB (PDF-Bericht) */
if ( $action === 'analyse_pdf' ) {
    require_once( __DIR__ . '/includes/survey-analyse.php' );
    $raw = file_get_contents( 'php://input' ); $in = json_decode( $raw, true ); if ( ! is_array( $in ) ) $in = array();
    $f = ( isset( $in['filters'] ) && is_array( $in['filters'] ) ) ? $in['filters'] : array();
    $images = ( isset( $in['images'] ) && is_array( $in['images'] ) ) ? $in['images'] : array();
    $ftext = isset( $in['filters_text'] ) ? (string) $in['filters_text'] : '';
    $bytes = pacim_survey_analyse_pdf( $db, $f, $images, $ftext );
    while ( ob_get_level() > 0 ) ob_end_clean();
    header( 'Content-Type: application/pdf' );
    header( 'Content-Disposition: attachment; filename="kundenzufriedenheit-analyse.pdf"' );
    header( 'Content-Length: ' . strlen( $bytes ) );
    header( 'Cache-Control: no-store' );
    echo $bytes; exit();
}

/* --------------------------------------------------------------- ANALYSE-TAB (alle Widget-Daten) */
if ( $action === 'analyse' ) {
    require_once( __DIR__ . '/includes/survey-analyse.php' );
    $keys = array( 'from','to','ship','trip','product','area','stars','recommend','land','bundesland','ci_from','ci_to','months','duration' );
    $f = array(); foreach ( $keys as $k ) if ( isset( $_GET[ $k ] ) ) $f[ $k ] = (string) $_GET[ $k ];

    // Optionaler 5-Minuten-Cache über pacim_dash_cache (dc_key ≤ 40 Zeichen).
    $ck = 'svan:' . md5( json_encode( $f ) );
    $cached = $db->rawQueryOne( "SELECT dc_data, dc_updated FROM pacim_dash_cache WHERE dc_key = ? AND dc_updated >= (NOW() - INTERVAL 5 MINUTE)", array( $ck ) );
    if ( $cached && ! empty( $cached['dc_data'] ) ) {
        $data = json_decode( $cached['dc_data'], true );
        if ( is_array( $data ) ) sv_json( array( 'ok' => true, 'cached' => true, 'data' => $data ) );
    }
    $data = pacim_survey_analyse( $db, $f );
    // Cache schreiben (ohne Abhängigkeit von einem Unique-Key: alten Eintrag ersetzen).
    $db->rawQuery( "DELETE FROM pacim_dash_cache WHERE dc_key = ?", array( $ck ) );
    $db->rawQuery( "INSERT INTO pacim_dash_cache (dc_key, dc_date, dc_data, dc_updated) VALUES (?, CURDATE(), ?, NOW())", array( $ck, json_encode( $data ) ) );
    sv_json( array( 'ok' => true, 'cached' => false, 'data' => $data ) );
}

/* --------------------------------------------------------------- ALLGEMEINER LINK + QR */
if ( $action === 'general_link' ) {
    $link = pacim_survey_general_link();
    $png  = pacim_survey_qr( $link, 'png', 8 );
    $svg  = pacim_survey_qr( $link, 'svg' );
    sv_json( array(
        'ok'     => true,
        'link'   => $link,
        'qr_png' => 'data:image/png;base64,' . base64_encode( (string) $png ),
        'qr_svg' => (string) $svg,
    ) );
}

/* --------------------------------------------------------------- ALLGEMEINE BEWERTUNGEN (nach Session) */
if ( $action === 'general_list' ) {
    pacim_survey_general_ensure( $db );
    $rows = (array) $db->rawQuery(
        "SELECT sg_id, sg_session, sg_ship, sg_park, sg_overall, sg_recommend, sg_aspects, sg_comment, sg_created
           FROM pacim_survey_general ORDER BY sg_created DESC LIMIT 1000" );
    $parkLbl = array( 'halle' => 'Halle', 'aussen' => 'Außen' );
    $sessions = array();
    foreach ( $rows as $r ) {
        $sid = (string) $r['sg_session'];
        if ( ! isset( $sessions[ $sid ] ) ) {
            $sessions[ $sid ] = array( 'session' => $sid, 'short' => substr( $sid, 0, 8 ), 'count' => 0, 'osum' => 0, 'on' => 0, 'last' => $r['sg_created'], 'items' => array() );
        }
        $sessions[ $sid ]['count']++;
        if ( $r['sg_overall'] !== null ) { $sessions[ $sid ]['osum'] += (int) $r['sg_overall']; $sessions[ $sid ]['on']++; }
        if ( $r['sg_created'] > $sessions[ $sid ]['last'] ) $sessions[ $sid ]['last'] = $r['sg_created'];
        $sessions[ $sid ]['items'][] = array(
            'id'        => (int) $r['sg_id'],
            'ship'      => (string) $r['sg_ship'],
            'park'      => $parkLbl[ $r['sg_park'] ] ?? (string) $r['sg_park'],
            'overall'   => $r['sg_overall'] !== null ? (int) $r['sg_overall'] : null,
            'recommend' => $r['sg_recommend'] !== null ? (int) $r['sg_recommend'] : null,
            'aspects'   => json_decode( (string) $r['sg_aspects'], true ) ?: array(),
            'comment'   => (string) $r['sg_comment'],
            'created'   => $r['sg_created'],
        );
    }
    $out = array();
    foreach ( $sessions as $s ) { $s['avg'] = $s['on'] ? round( $s['osum'] / $s['on'], 2 ) : null; unset( $s['osum'], $s['on'] ); $out[] = $s; }
    sv_json( array( 'ok' => true, 'aspects' => $ASPECTS, 'sessions' => $out, 'total' => count( $rows ) ) );
}

if ( $action === 'general_delete' ) {
    $id = (int) ( $_POST['id'] ?? 0 );
    if ( $id <= 0 ) sv_fail( 'bad_id' );
    $db->where( 'sg_id', $id );
    $db->delete( 'pacim_survey_general' );
    sv_json( array( 'ok' => true ) );
}

/* --------------------------------------------------------------- QR-CODE (hochauflösend) */
if ( $action === 'general_qr' ) {
    $px  = (int) ( $_GET['px'] ?? 4000 );
    $png = pacim_survey_qr_png_hires( pacim_survey_general_link(), $px );
    while ( ob_get_level() > 0 ) ob_end_clean();
    if ( $png === null ) { http_response_code( 500 ); header( 'Content-Type: text/plain; charset=utf-8' ); echo 'QR-Erzeugung fehlgeschlagen.'; exit(); }
    header( 'Content-Type: image/png' );
    header( 'Content-Disposition: attachment; filename="qr-bewertungslink-' . max( 100, min( 8000, $px ) ) . 'px.png"' );
    header( 'Content-Length: ' . strlen( $png ) );
    header( 'Cache-Control: no-store, no-cache, must-revalidate' );
    echo $png;
    exit();
}

sv_fail( 'unknown_action' );

Youez - 2016 - github.com/yon3zu
LinuXploit